diff options
Diffstat (limited to 'platform/x11/os_x11.cpp')
| -rw-r--r-- | platform/x11/os_x11.cpp | 678 |
1 files changed, 593 insertions, 85 deletions
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 0466984359..74ebad748a 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,15 +28,26 @@ /*************************************************************************/ #include "servers/visual/visual_server_raster.h" #include "drivers/gles2/rasterizer_gles2.h" -#include "drivers/gles1/rasterizer_gles1.h" #include "os_x11.h" #include "key_mapping_x11.h" #include <stdio.h> #include <stdlib.h> #include "print_string.h" #include "servers/physics/physics_server_sw.h" +#include "errno.h" #include "X11/Xutil.h" + +#include "X11/Xatom.h" +#include "X11/extensions/Xinerama.h" +// ICCCM +#define WM_NormalState 1L // window normal state +#define WM_IconicState 3L // window minimized +// EWMH +#define _NET_WM_STATE_REMOVE 0L // remove/unset property +#define _NET_WM_STATE_ADD 1L // add/set property +#define _NET_WM_STATE_TOGGLE 2L // toggle property + #include "main/main.h" @@ -57,23 +68,33 @@ #include <X11/Xatom.h> -#include "os/pc_joystick_map.h" +//#include "os/pc_joystick_map.h" #undef CursorShape int OS_X11::get_video_driver_count() const { - - return 2; + return 1; } -const char * OS_X11::get_video_driver_name(int p_driver) const { - return p_driver==0?"GLES2":"GLES1"; +const char * OS_X11::get_video_driver_name(int p_driver) const { + return "GLES2"; } -OS::VideoMode OS_X11::get_default_video_mode() const { +OS::VideoMode OS_X11::get_default_video_mode() const { return OS::VideoMode(800,600,false); } +int OS_X11::get_audio_driver_count() const { + return AudioDriverManagerSW::get_driver_count(); +} + +const char *OS_X11::get_audio_driver_name(int p_driver) const { + + AudioDriverSW* driver = AudioDriverManagerSW::get_driver(p_driver); + ERR_FAIL_COND_V( !driver, "" ); + return AudioDriverManagerSW::get_driver(p_driver)->get_name(); +} + void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) { last_button_state=0; @@ -106,10 +127,10 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi if (xim == NULL) { WARN_PRINT("XOpenIM failed"); - xim_style=NULL; + xim_style=0L; } else { ::XIMStyles *xim_styles=NULL; - xim_style=0; + xim_style=0L; char *imvalret=NULL; imvalret = XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL); if (imvalret != NULL || xim_styles == NULL) { @@ -117,7 +138,7 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi } if (xim_styles) { - xim_style = 0; + xim_style = 0L; for (int i=0;i<xim_styles->count_styles;i++) { if (xim_styles->supported_styles[i] == @@ -130,6 +151,7 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi XFree (xim_styles); } + XFree( imvalret ); } /* @@ -151,14 +173,11 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi // maybe contextgl wants to be in charge of creating the window //print_line("def videomode "+itos(current_videomode.width)+","+itos(current_videomode.height)); #if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) + context_gl = memnew( ContextGL_X11( x11_display, x11_window,current_videomode, false ) ); context_gl->initialize(); - if (p_video_driver == 0) { - rasterizer = memnew( RasterizerGLES2 ); - } else { - rasterizer = memnew( RasterizerGLES1 ); - }; + rasterizer = memnew( RasterizerGLES2 ); #endif visual_server = memnew( VisualServerRaster(rasterizer) ); @@ -168,9 +187,11 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi visual_server =memnew(VisualServerWrapMT(visual_server,get_render_thread_mode()==RENDER_SEPARATE_THREAD)); } +#if 1 + // NEW_WM_API // borderless fullscreen window mode if (current_videomode.fullscreen) { - // needed for lxde/openbox, possibly others + // needed for lxde/openbox, possibly others Hints hints; Atom property; hints.flags = 2; @@ -199,7 +220,7 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureNotifyMask, &xev); } - // disable resizeable window + // disable resizable window if (!current_videomode.resizable) { XSizeHints *xsh; xsh = XAllocSizeHints(); @@ -215,13 +236,48 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi xsh->min_height = xwa.height; xsh->max_height = xwa.height; XSetWMNormalHints(x11_display, x11_window, xsh); + XFree(xsh); + } +#else + capture_idle = 0; + minimized = false; + maximized = false; + + if (current_videomode.fullscreen) { + //set_wm_border(false); + set_wm_fullscreen(true); + } + if (!current_videomode.resizable) { + int screen = get_current_screen(); + Size2i screen_size = get_screen_size(screen); + set_window_size(screen_size); + set_window_resizable(false); } +#endif AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton(); + audio_driver_index=p_audio_driver; if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) { - ERR_PRINT("Initializing audio failed."); + bool success=false; + audio_driver_index=-1; + for(int i=0;i<AudioDriverManagerSW::get_driver_count();i++) { + if (i==p_audio_driver) + continue; + AudioDriverManagerSW::get_driver(i)->set_singleton(); + if (AudioDriverManagerSW::get_driver(i)->init()==OK) { + success=true; + print_line("Audio Driver Failed: "+String(AudioDriverManagerSW::get_driver(p_audio_driver)->get_name())); + print_line("Using alternate audio driver: "+String(AudioDriverManagerSW::get_driver(i)->get_name())); + audio_driver_index=i; + break; + } + } + if (!success) { + ERR_PRINT("Initializing audio failed."); + } + } sample_manager = memnew( SampleManagerMallocSW ); @@ -253,19 +309,19 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi XChangeWindowAttributes(x11_display, x11_window,CWEventMask,&new_attr); - XClassHint* classHint; + XClassHint* classHint; - /* set the titlebar name */ - XStoreName(x11_display, x11_window, "Godot"); + /* set the titlebar name */ + XStoreName(x11_display, x11_window, "Godot"); - /* set the name and class hints for the window manager to use */ - classHint = XAllocClassHint(); - if (classHint) { - classHint->res_name = "Godot"; - classHint->res_class = "Godot"; - } - XSetClassHint(x11_display, x11_window, classHint); - XFree(classHint); + /* set the name and class hints for the window manager to use */ + classHint = XAllocClassHint(); + if (classHint) { + classHint->res_name = (char *)"Godot"; + classHint->res_class = (char *)"Godot"; + } + XSetClassHint(x11_display, x11_window, classHint); + XFree(classHint); wm_delete = XInternAtom(x11_display, "WM_DELETE_WINDOW", true); XSetWMProtocols(x11_display, x11_window, &wm_delete, 1); @@ -293,6 +349,7 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi for(int i=0;i<CURSOR_MAX;i++) { cursors[i]=None; + img[i]=NULL; } current_cursor=CURSOR_ARROW; @@ -321,16 +378,15 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi "question_arrow" }; - XcursorImage *img = XcursorLibraryLoadImage(cursor_file[i],cursor_theme,cursor_size); - if (img) { - cursors[i]=XcursorImageLoadCursor(x11_display,img); + img[i] = XcursorLibraryLoadImage(cursor_file[i],cursor_theme,cursor_size); + if (img[i]) { + cursors[i]=XcursorImageLoadCursor(x11_display,img[i]); //print_line("found cursor: "+String(cursor_file[i])+" id "+itos(cursors[i])); } else { if (OS::is_stdout_verbose()) print_line("failed cursor: "+String(cursor_file[i])); } } - } @@ -341,9 +397,9 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi XColor col; Cursor cursor; - cursormask = XCreatePixmap(x11_display, RootWindow(x11_display,DefaultScreen(x11_display)), 1, 1, 1); - xgc.function = GXclear; - gc = XCreateGC(x11_display, cursormask, GCFunction, &xgc); + cursormask = XCreatePixmap(x11_display, RootWindow(x11_display,DefaultScreen(x11_display)), 1, 1, 1); + xgc.function = GXclear; + gc = XCreateGC(x11_display, cursormask, GCFunction, &xgc); XFillRectangle(x11_display, cursormask, gc, 0, 0, 1, 1); col.pixel = 0; col.red = 0; @@ -370,7 +426,8 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi // physics_server = memnew( PhysicsServerSW ); physics_server->init(); - physics_2d_server = memnew( Physics2DServerSW ); + //physics_2d_server = memnew( Physics2DServerSW ); + physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>(); physics_2d_server->init(); input = memnew( InputDefault ); @@ -378,13 +435,8 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi probe_joystick(); _ensure_data_dir(); - - net_wm_icon = XInternAtom(x11_display, "_NET_WM_ICON", False); - - - //printf("got map notify\n"); - } + void OS_X11::finalize() { if(main_loop) @@ -400,9 +452,10 @@ void OS_X11::finalize() { // memdelete(debugger_connection_console); //} + memdelete(sample_manager); + audio_server->finish(); memdelete(audio_server); - memdelete(sample_manager); visual_server->finish(); memdelete(visual_server); @@ -416,14 +469,26 @@ void OS_X11::finalize() { memdelete(input); + XUnmapWindow( x11_display, x11_window ); + XDestroyWindow( x11_display, x11_window ); + #if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) memdelete(context_gl); #endif - + for(int i=0;i<CURSOR_MAX;i++) { + if( cursors[i] != None ) + XFreeCursor( x11_display, cursors[i] ); + if( img[i] != NULL ) + XcursorImageDestroy( img[i] ); + }; + + XDestroyIC( xic ); + XCloseIM( xim ); XCloseDisplay(x11_display); if (xmbstring) memfree(xmbstring); + args.clear(); } @@ -445,6 +510,23 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) { mouse_mode=p_mode; if (mouse_mode==MOUSE_MODE_CAPTURED) { + + while(true) { + //flush pending motion events + + if (XPending(x11_display) > 0) { + XEvent event; + XPeekEvent(x11_display, &event); + if (event.type==MotionNotify) { + XNextEvent(x11_display,&event); + } else { + break; + } + } else { + break; + } + } + if (XGrabPointer(x11_display, x11_window, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, @@ -457,8 +539,11 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) { center.y = current_videomode.height/2; XWarpPointer(x11_display, None, x11_window, 0,0,0,0, (int)center.x, (int)center.y); - } + input->set_mouse_pos(center); + } else { + do_mouse_warp=false; + } } void OS_X11::warp_mouse_pos(const Point2& p_to) { @@ -468,45 +553,390 @@ void OS_X11::warp_mouse_pos(const Point2& p_to) { last_mouse_pos=p_to; } else { + /*XWindowAttributes xwa; + XGetWindowAttributes(x11_display, x11_window, &xwa); + printf("%d %d\n", xwa.x, xwa.y); needed? */ + XWarpPointer(x11_display, None, x11_window, - 0,0,0,0, (int)p_to.x, (int)p_to.y); + 0,0,0,0, (int)p_to.x , (int)p_to.y); } } OS::MouseMode OS_X11::get_mouse_mode() const { - return mouse_mode; } - - int OS_X11::get_mouse_button_state() const { - return last_button_state; } Point2 OS_X11::get_mouse_pos() const { - return last_mouse_pos; } void OS_X11::set_window_title(const String& p_title) { - XStoreName(x11_display,x11_window,p_title.utf8().get_data()); } void OS_X11::set_video_mode(const VideoMode& p_video_mode,int p_screen) { - - } -OS::VideoMode OS_X11::get_video_mode(int p_screen) const { +OS::VideoMode OS_X11::get_video_mode(int p_screen) const { return current_videomode; } + void OS_X11::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) const { +} + +//#ifdef NEW_WM_API +#if 0 +// Just now not needed. Can be used for a possible OS.set_border(bool) method +void OS_X11::set_wm_border(bool p_enabled) { + // needed for lxde/openbox, possibly others + Hints hints; + Atom property; + hints.flags = 2; + hints.decorations = p_enabled ? 1L : 0L; + property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); + XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); + XMapRaised(x11_display, x11_window); + //XMoveResizeWindow(x11_display, x11_window, 0, 0, 800, 800); +} +#endif + +void OS_X11::set_wm_fullscreen(bool p_enabled) { + // Using EWMH -- Extened Window Manager Hints + XEvent xev; + Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); + Atom wm_fullscreen = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = x11_window; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; + xev.xclient.data.l[1] = wm_fullscreen; + xev.xclient.data.l[2] = 0; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); +} + +int OS_X11::get_screen_count() const { + // Using Xinerama Extension + int event_base, error_base; + const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); + if( !ext_okay ) return 0; + + int count; + XineramaScreenInfo* xsi = XineramaQueryScreens(x11_display, &count); + XFree(xsi); + return count; +} + +int OS_X11::get_current_screen() const { + int x,y; + Window child; + XTranslateCoordinates( x11_display, x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child); + + int count = get_screen_count(); + for(int i=0; i<count; i++) { + Point2i pos = get_screen_position(i); + Size2i size = get_screen_size(i); + if( (x >= pos.x && x <pos.x + size.width) && (y >= pos.y && y < pos.y + size.height) ) + return i; + } + return 0; +} + +void OS_X11::set_current_screen(int p_screen) { + int count = get_screen_count(); + if(p_screen >= count) return; + + if( current_videomode.fullscreen ) { + Point2i position = get_screen_position(p_screen); + Size2i size = get_screen_size(p_screen); + + XMoveResizeWindow(x11_display, x11_window, position.x, position.y, size.x, size.y); + } + else { + if( p_screen != get_current_screen() ) { + Point2i position = get_screen_position(p_screen); + XMoveWindow(x11_display, x11_window, position.x, position.y); + } + } +} + +Point2 OS_X11::get_screen_position(int p_screen) const { + // Using Xinerama Extension + int event_base, error_base; + const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); + if( !ext_okay ) { + return Point2i(0,0); + } + + int count; + XineramaScreenInfo* xsi = XineramaQueryScreens(x11_display, &count); + if( p_screen >= count ) { + return Point2i(0,0); + } + + Point2i position = Point2i(xsi[p_screen].x_org, xsi[p_screen].y_org); + + XFree(xsi); + + return position; +} + +Size2 OS_X11::get_screen_size(int p_screen) const { + // Using Xinerama Extension + int event_base, error_base; + const Bool ext_okay = XineramaQueryExtension(x11_display, &event_base, &error_base); + if( !ext_okay ) return Size2i(0,0); + + int count; + XineramaScreenInfo* xsi = XineramaQueryScreens(x11_display, &count); + if( p_screen >= count ) return Size2i(0,0); + + Size2i size = Point2i(xsi[p_screen].width, xsi[p_screen].height); + XFree(xsi); + return size; +} + +Point2 OS_X11::get_window_position() const { + int x,y; + Window child; + XTranslateCoordinates( x11_display, x11_window, DefaultRootWindow(x11_display), 0, 0, &x, &y, &child); + + int screen = get_current_screen(); + Point2i screen_position = get_screen_position(screen); + + return Point2i(x-screen_position.x, y-screen_position.y); +} + +void OS_X11::set_window_position(const Point2& p_position) { + // Using EWMH -- Extended Window Manager Hints + // to get the size of the decoration +#if 0 + Atom property = XInternAtom(x11_display,"_NET_FRAME_EXTENTS", True); + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + int result; + + result = XGetWindowProperty( + x11_display, + x11_window, + property, + 0, + 32, + False, + AnyPropertyType, + &type, + &format, + &len, + &remaining, + &data + ); + + long left = 0L; + long top = 0L; + + if( result == Success ) { + long *extends = (long *) data; + + left = extends[0]; + top = extends[2]; + + XFree(data); + } + + int screen = get_current_screen(); + Point2i screen_position = get_screen_position(screen); + + left -= screen_position.x; + top -= screen_position.y; + + XMoveWindow(x11_display,x11_window,p_position.x - left,p_position.y - top); +#else + XMoveWindow(x11_display,x11_window,p_position.x,p_position.y); +#endif +} + +Size2 OS_X11::get_window_size() const { + XWindowAttributes xwa; + XGetWindowAttributes(x11_display, x11_window, &xwa); + return Size2i(xwa.width, xwa.height); +} + +void OS_X11::set_window_size(const Size2 p_size) { + XResizeWindow(x11_display, x11_window, p_size.x, p_size.y); +} + +void OS_X11::set_window_fullscreen(bool p_enabled) { + set_wm_fullscreen(p_enabled); + current_videomode.fullscreen = p_enabled; +} + +bool OS_X11::is_window_fullscreen() const { + return current_videomode.fullscreen; +} +void OS_X11::set_window_resizable(bool p_enabled) { + XSizeHints *xsh; + xsh = XAllocSizeHints(); + xsh->flags = p_enabled ? 0L : PMinSize | PMaxSize; + if(!p_enabled) { + XWindowAttributes xwa; + XGetWindowAttributes(x11_display,x11_window,&xwa); + xsh->min_width = xwa.width; + xsh->max_width = xwa.width; + xsh->min_height = xwa.height; + xsh->max_height = xwa.height; + } + XSetWMNormalHints(x11_display, x11_window, xsh); + XFree(xsh); + current_videomode.resizable = p_enabled; +} +bool OS_X11::is_window_resizable() const { + return current_videomode.resizable; +} + +void OS_X11::set_window_minimized(bool p_enabled) { + // Using ICCCM -- Inter-Client Communication Conventions Manual + XEvent xev; + Atom wm_change = XInternAtom(x11_display, "WM_CHANGE_STATE", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = x11_window; + xev.xclient.message_type = wm_change; + xev.xclient.format = 32; + xev.xclient.data.l[0] = p_enabled ? WM_IconicState : WM_NormalState; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); + + //XEvent xev; + Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); + Atom wm_hidden = XInternAtom(x11_display, "_NET_WM_STATE_HIDDEN", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = x11_window; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = _NET_WM_STATE_ADD; + xev.xclient.data.l[1] = wm_hidden; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); +} + +bool OS_X11::is_window_minimized() const { + // Using ICCCM -- Inter-Client Communication Conventions Manual + Atom property = XInternAtom(x11_display,"WM_STATE", True); + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + + int result = XGetWindowProperty( + x11_display, + x11_window, + property, + 0, + 32, + False, + AnyPropertyType, + &type, + &format, + &len, + &remaining, + &data + ); + + if( result == Success ) { + long *state = (long *) data; + if( state[0] == WM_IconicState ) + return true; + } + return false; +} + +void OS_X11::set_window_maximized(bool p_enabled) { + // Using EWMH -- Extended Window Manager Hints + XEvent xev; + Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); + Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); + Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = x11_window; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; + xev.xclient.data.l[1] = wm_max_horz; + xev.xclient.data.l[2] = wm_max_vert; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); +/* sorry this does not fix it, fails on multi monitor + XWindowAttributes xwa; + XGetWindowAttributes(x11_display,DefaultRootWindow(x11_display),&xwa); + current_videomode.width = xwa.width; + current_videomode.height = xwa.height; +*/ + maximized = p_enabled; +} + +bool OS_X11::is_window_maximized() const { + // Using EWMH -- Extended Window Manager Hints + Atom property = XInternAtom(x11_display,"_NET_WM_STATE",False ); + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + + int result = XGetWindowProperty( + x11_display, + x11_window, + property, + 0, + 1024, + False, + XA_ATOM, + &type, + &format, + &len, + &remaining, + &data + ); + + if(result == Success) { + Atom *atoms = (Atom*) data; + Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); + Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); + bool found_wm_max_horz = false; + bool found_wm_max_vert = false; + + for( unsigned int i=0; i < len; i++ ) { + if( atoms[i] == wm_max_horz ) + found_wm_max_horz = true; + if( atoms[i] == wm_max_vert ) + found_wm_max_vert = true; + + if( found_wm_max_horz && found_wm_max_vert ) + return true; + } + XFree(atoms); + } + + return false; } @@ -556,7 +986,6 @@ unsigned int OS_X11::get_mouse_button_state(unsigned int p_x11_state) { } void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { - // X11 functions don't know what const is XKeyEvent *xkeyevent = p_event; @@ -583,11 +1012,9 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { KeySym keysym_keycode=0; // keysym used to find a keycode KeySym keysym_unicode=0; // keysym used to find unicode - int nbytes=0; // bytes the string takes - // XLookupString returns keysyms usable as nice scancodes/ char str[256+1]; - nbytes=XLookupString(xkeyevent, str, 256, &keysym_keycode, NULL); + XLookupString(xkeyevent, str, 256, &keysym_keycode, NULL); // Meanwhile, XLookupString returns keysyms useful for unicode. @@ -684,7 +1111,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { ::Time tresh=ABS(peek_event.xkey.time-xkeyevent->time); if (peek_event.type == KeyPress && tresh<5 ) { KeySym rk; - nbytes=XLookupString((XKeyEvent*)&peek_event, str, 256, &rk, NULL); + XLookupString((XKeyEvent*)&peek_event, str, 256, &rk, NULL); if (rk==keysym_keycode) { XEvent event; XNextEvent(x11_display, &event); //erase next event @@ -724,15 +1151,13 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { //printf("key: %x\n",event.key.scancode); input->parse_input_event( event); - - } void OS_X11::process_xevents() { //printf("checking events %i\n", XPending(x11_display)); - bool do_mouse_warp=false; + do_mouse_warp=false; while (XPending(x11_display) > 0) { XEvent event; @@ -748,13 +1173,31 @@ void OS_X11::process_xevents() { break; case VisibilityNotify: { - XVisibilityEvent * visibility = (XVisibilityEvent *)&event; minimized = (visibility->state == VisibilityFullyObscured); + } break; + case LeaveNotify: { + + if (main_loop && mouse_mode!=MOUSE_MODE_CAPTURED) + main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT); + if (input) + input->set_mouse_in_window(false); } break; + case EnterNotify: { + if (main_loop && mouse_mode!=MOUSE_MODE_CAPTURED) + main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER); + if (input) + input->set_mouse_in_window(true); + } break; case FocusIn: + minimized = false; +#ifdef NEW_WM_API + if(current_videomode.fullscreen) { + set_wm_fullscreen(true); + } +#endif main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); if (mouse_mode==MOUSE_MODE_CAPTURED) { XGrabPointer(x11_display, x11_window, True, @@ -765,6 +1208,12 @@ void OS_X11::process_xevents() { break; case FocusOut: +#ifdef NEW_WM_API + if(current_videomode.fullscreen) { + set_wm_fullscreen(false); + set_window_minimized(true); + } +#endif main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); if (mouse_mode==MOUSE_MODE_CAPTURED) { //dear X11, I try, I really try, but you never work, you do whathever you want. @@ -791,7 +1240,7 @@ void OS_X11::process_xevents() { event.xbutton.x=last_mouse_pos.x; event.xbutton.y=last_mouse_pos.y; } - + InputEvent mouse_event; mouse_event.ID=++event_id; mouse_event.type = InputEvent::MOUSE_BUTTON; @@ -826,26 +1275,55 @@ void OS_X11::process_xevents() { last_click_ms+=diff; last_click_pos = Point2(event.xbutton.x,event.xbutton.y); } - } + } input->parse_input_event( mouse_event); } break; case MotionNotify: { - + + // FUCK YOU X11 API YOU SERIOUSLY GROSS ME OUT + // YOU ARE AS GROSS AS LOOKING AT A PUTRID PILE + // OF POOP STICKING OUT OF A CLOGGED TOILET + // HOW THE FUCK I AM SUPPOSED TO KNOW WHICH ONE + // OF THE MOTION NOTIFY EVENTS IS THE ONE GENERATED + // BY WARPING THE MOUSE POINTER? + // YOU ARE FORCING ME TO FILTER ONE BY ONE TO FIND IT + // PLEASE DO ME A FAVOR AND DIE DROWNED IN A FECAL + // MOUNTAIN BECAUSE THAT'S WHERE YOU BELONG. + + while(true) { + if (mouse_mode==MOUSE_MODE_CAPTURED && event.xmotion.x==current_videomode.width/2 && event.xmotion.y==current_videomode.height/2) { + //this is likely the warp event since it was warped here + center=Vector2(event.xmotion.x,event.xmotion.y); + break; + } + + if (XPending(x11_display) > 0) { + XEvent tevent; + XPeekEvent(x11_display, &tevent); + if (tevent.type==MotionNotify) { + XNextEvent(x11_display,&event); + } else { + break; + } + } else { + break; + } + } + last_timestamp=event.xmotion.time; - + // Motion is also simple. // A little hack is in order // to be able to send relative motion events. - Point2i pos( event.xmotion.x, event.xmotion.y ); if (mouse_mode==MOUSE_MODE_CAPTURED) { #if 1 - Vector2 c = Point2i(current_videomode.width/2,current_videomode.height/2); + //Vector2 c = Point2i(current_videomode.width/2,current_videomode.height/2); if (pos==Point2i(current_videomode.width/2,current_videomode.height/2)) { //this sucks, it's a hack, etc and is a little inaccurate, etc. //but nothing I can do, X11 sucks. @@ -854,9 +1332,9 @@ void OS_X11::process_xevents() { break; } - Point2i ncenter = pos; - pos = last_mouse_pos + ( pos-center ); - center=ncenter; + Point2i new_center = pos; + pos = last_mouse_pos + ( pos - center ); + center=new_center; do_mouse_warp=true; #else //Dear X11, thanks for making my life miserable @@ -869,9 +1347,7 @@ void OS_X11::process_xevents() { XWarpPointer(x11_display, None, x11_window, 0,0,0,0, (int)center.x, (int)center.y); #endif - } - if (!last_mouse_pos_valid) { @@ -880,7 +1356,14 @@ void OS_X11::process_xevents() { } Point2i rel = pos - last_mouse_pos; - + +#ifdef NEW_WM_API + if (mouse_mode==MOUSE_MODE_CAPTURED) { + pos.x = current_videomode.width / 2; + pos.y = current_videomode.height / 2; + } +#endif + InputEvent motion_event; motion_event.ID=++event_id; motion_event.type=InputEvent::MOUSE_MOTION; @@ -900,6 +1383,8 @@ void OS_X11::process_xevents() { motion_event.mouse_motion.relative_y=rel.y; last_mouse_pos=pos; + + // printf("rel: %d,%d\n", rel.x, rel.y ); input->parse_input_event( motion_event); @@ -974,8 +1459,18 @@ void OS_X11::process_xevents() { if (do_mouse_warp) { XWarpPointer(x11_display, None, x11_window, - 0,0,0,0, (int)current_videomode.width/2, (int)current_videomode.height/2); - + 0,0,0,0, (int)current_videomode.width/2, (int)current_videomode.height/2); + + /* + Window root, child; + int root_x, root_y; + int win_x, win_y; + unsigned int mask; + XQueryPointer( x11_display, x11_window, &root, &child, &root_x, &root_y, &win_x, &win_y, &mask ); + + printf("Root: %d,%d\n", root_x, root_y); + printf("Win: %d,%d\n", win_x, win_y); + */ } } @@ -1343,6 +1838,7 @@ void OS_X11::process_joysticks() { #endif }; + void OS_X11::set_cursor_shape(CursorShape p_shape) { ERR_FAIL_INDEX(p_shape,CURSOR_MAX); @@ -1356,7 +1852,6 @@ void OS_X11::set_cursor_shape(CursorShape p_shape) { XDefineCursor(x11_display,x11_window,cursors[CURSOR_ARROW]); } - current_cursor=p_shape; } @@ -1377,8 +1872,20 @@ void OS_X11::swap_buffers() { context_gl->swap_buffers(); } +void OS_X11::alert(const String& p_alert,const String& p_title) { + + List<String> args; + args.push_back("-center"); + args.push_back("-title"); + args.push_back(p_title); + args.push_back(p_alert); + + execute("/usr/bin/xmessage",args,true); +} void OS_X11::set_icon(const Image& p_icon) { + Atom net_wm_icon = XInternAtom(x11_display, "_NET_WM_ICON", False); + if (!p_icon.empty()) { Image img=p_icon; img.convert(Image::FORMAT_RGBA); @@ -1411,7 +1918,6 @@ void OS_X11::set_icon(const Image& p_icon) { XDeleteProperty(x11_display, x11_window, net_wm_icon); } XFlush(x11_display); - } @@ -1446,13 +1952,15 @@ OS_X11::OS_X11() { AudioDriverManagerSW::add_driver(&driver_rtaudio); #endif +#ifdef PULSEAUDIO_ENABLED + AudioDriverManagerSW::add_driver(&driver_pulseaudio); +#endif + #ifdef ALSA_ENABLED AudioDriverManagerSW::add_driver(&driver_alsa); #endif minimized = false; - xim_style=NULL; + xim_style=0L; mouse_mode=MOUSE_MODE_VISIBLE; - - }; |