diff options
Diffstat (limited to 'platform')
-rw-r--r-- | platform/x11/detect.py | 10 | ||||
-rw-r--r-- | platform/x11/os_x11.cpp | 228 | ||||
-rw-r--r-- | platform/x11/os_x11.h | 26 |
3 files changed, 258 insertions, 6 deletions
diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 8264196a41..773928c72d 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -38,6 +38,11 @@ def can_build(): if (x11_error): print("xcursor not found.. x11 disabled.") return False + + x11_error=os.system("pkg-config xinerama --modversion > /dev/null ") + if (x11_error): + print("xinerama not found.. x11 disabled.") + return False return True # X11 enabled @@ -48,6 +53,7 @@ def get_opts(): ('use_llvm','Use llvm compiler','no'), ('use_sanitizer','Use llvm compiler sanitize address','no'), ('pulseaudio','Detect & Use pulseaudio','yes'), + ('experimental_wm_api', 'Use experimental window management API','no'), ] def get_flags(): @@ -150,3 +156,7 @@ def configure(env): env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) #env.Append( BUILDERS = { 'HLSL9' : env.Builder(action = methods.build_hlsl_dx9_headers, suffix = 'hlsl.h',src_suffix = '.hlsl') } ) + if(env["experimental_wm_api"]=="yes"): + env.Append(CPPFLAGS=['-DEXPERIMENTAL_WM_API']) + env.ParseConfig('pkg-config xinerama --cflags --libs') + diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index a40af8d2a9..d395e99210 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -36,6 +36,9 @@ #include "servers/physics/physics_server_sw.h" #include "X11/Xutil.h" +#ifdef EXPERIMENTAL_WM_API +#include "X11/extensions/Xinerama.h" +#endif #include "main/main.h" @@ -162,6 +165,7 @@ 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(); @@ -181,7 +185,8 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi // borderless fullscreen window mode if (current_videomode.fullscreen) { - // needed for lxde/openbox, possibly others +#ifndef EXPERIMENTAL_WM_API + // needed for lxde/openbox, possibly others Hints hints; Atom property; hints.flags = 2; @@ -208,6 +213,14 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi xev.xclient.data.l[2] = 0; XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureNotifyMask, &xev); +#else + window_data.position.x = 0; + window_data.position.y = 0; + window_data.size.width = 800; + window_data.size.height = 600; + set_wm_border(false); + set_wm_fullscreen(true); +#endif } // disable resizeable window @@ -520,6 +533,213 @@ void OS_X11::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) cons } +#ifdef EXPERIMENTAL_WM_API +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); +} + +void OS_X11::set_wm_fullscreen(bool p_enabled) { + // code for netwm-compliants + 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 ? 1L : 0L; + xev.xclient.data.l[1] = wm_fullscreen; + xev.xclient.data.l[2] = 0; + + XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureNotifyMask, &xev); +} + +int OS_X11::get_screen_count() const { + 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_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_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_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 { + 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 { + 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); + return Point2i(x,y); +} + +void OS_X11::set_window_position(const Point2& p_position) { + + if( current_videomode.fullscreen ) + return; + + // _NET_FRAME_EXTENTS + Atom property = XInternAtom(x11_display,"_NET_FRAME_EXTENTS", True); + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + //long *extends; + 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); + data = NULL; + } + + XMoveWindow(x11_display,x11_window,p_position.x - left,p_position.y - top); +} + +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) { + if( current_videomode.fullscreen ) + return; + + XResizeWindow(x11_display, x11_window, p_size.x, p_size.y); +} + +void OS_X11::set_fullscreen(bool p_enabled) { + + if(p_enabled && current_videomode.fullscreen) + return; + + if(p_enabled) { + window_data.size = get_window_size(); + window_data.position = get_window_position(); + + int screen = get_screen(); + Size2i size = get_screen_size(screen); + Point2i position = get_screen_position(screen); + + set_wm_border(false); + set_wm_fullscreen(true); + XMoveResizeWindow(x11_display, x11_window, position.x, position.y, size.x, size.y); + + current_videomode.fullscreen = True; + } else { + set_wm_fullscreen(false); + set_wm_border(true); + XMoveResizeWindow(x11_display, x11_window, + window_data.position.x, + window_data.position.y, + window_data.size.width, + window_data.size.height); + + current_videomode.fullscreen = False; + } + + visual_server->init(); +} + +bool OS_X11::is_fullscreen() const { + return current_videomode.fullscreen; +} +#endif InputModifierState OS_X11::get_key_modifier_state(unsigned int p_x11_state) { @@ -856,7 +1076,7 @@ void OS_X11::process_xevents() { 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. @@ -865,9 +1085,9 @@ void OS_X11::process_xevents() { break; } - Point2i ncenter = pos; + Point2i new_center = pos; pos = last_mouse_pos + ( pos-center ); - center=ncenter; + center=new_center; do_mouse_warp=true; #else //Dear X11, thanks for making my life miserable diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index dd2476ec1b..72d212c131 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -159,6 +159,14 @@ class OS_X11 : public OS_Unix { int joystick_count; Joystick joysticks[JOYSTICKS_MAX]; +#ifdef EXPERIMENTAL_WM_API + struct { + Point2i position; + Size2i size; + } window_data; + void set_wm_border(bool p_enabled); + void set_wm_fullscreen(bool p_enabled); +#endif protected: @@ -166,8 +174,8 @@ protected: virtual const char * get_video_driver_name(int p_driver) const; virtual VideoMode get_default_video_mode() const; - virtual int get_audio_driver_count() const; - virtual const char * get_audio_driver_name(int p_driver) const; + virtual int get_audio_driver_count() const; + virtual const char * get_audio_driver_name(int p_driver) const; virtual void initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver); virtual void finalize(); @@ -178,6 +186,7 @@ protected: void process_joysticks(); void close_joystick(int p_id = -1); + public: virtual String get_name(); @@ -213,6 +222,19 @@ public: virtual VideoMode get_video_mode(int p_screen=0) const; virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const; +#ifdef EXPERIMENTAL_WM_API + virtual int get_screen_count() const; + virtual int get_screen() const; + virtual void set_screen(int p_screen); + virtual Point2 get_screen_position(int p_screen=0) const; + virtual Size2 get_screen_size(int p_screen=0) const; + virtual Point2 get_window_position() const; + virtual void set_window_position(const Point2& p_position); + virtual Size2 get_window_size() const; + virtual void set_window_size(const Size2 p_size); + virtual void set_fullscreen(bool p_enabled); + virtual bool is_fullscreen() const; +#endif virtual void move_window_to_foreground(); void run(); |