summaryrefslogtreecommitdiff
path: root/platform/x11/os_x11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/x11/os_x11.cpp')
-rw-r--r--platform/x11/os_x11.cpp678
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;
-
-
};