summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md21
-rw-r--r--core/bind/core_bind.cpp91
-rw-r--r--core/bind/core_bind.h20
-rw-r--r--core/os/os.h24
-rw-r--r--demos/misc/window_management/control.gd116
-rw-r--r--demos/misc/window_management/engine.cfg12
-rw-r--r--demos/misc/window_management/icon.pngbin0 -> 3639 bytes
-rw-r--r--demos/misc/window_management/icon.png.flags1
-rw-r--r--demos/misc/window_management/window_management.scnbin0 -> 4030 bytes
-rw-r--r--main/main.cpp1
-rw-r--r--platform/x11/detect.py10
-rw-r--r--platform/x11/os_x11.cpp468
-rw-r--r--platform/x11/os_x11.h29
13 files changed, 756 insertions, 37 deletions
diff --git a/README.md b/README.md
index 3456290f74..35841c8b29 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,24 @@
+### x11-window-management branch
+
+#### New GDScript Methods for the OS Class:
+* int OS.get_screen_count()
+* int OS.get_screen()
+* void OS.set_screen(int screen)
+* Vector2 OS.get_screen_position(int screen=0)
+* Vector2 OS.get_screen_size(int screen=0)
+* Vector2 OS.get_window_position()
+* void OS.set_window_position(Vector2 position)
+* Vector2 OS.get_window_size()
+* void OS.set_window_size(Vector2 size)
+* void OS.set_fullscreen(bool enabled)
+* bool OS.is_fullscreen()
+
+#### Demo
+A demo/test is available at "demos/misc/window-management"
+
+#### Scons Commandline
+'''scons p=x11 experimental_wm_api=yes'''
+
![GODOT](/logo.png)
### The Engine
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 0c5d21b4f6..6919c70a5f 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -176,6 +176,76 @@ bool _OS::is_video_mode_fullscreen(int p_screen) const {
}
+#ifdef EXPERIMENTAL_WM_API
+int _OS::get_screen_count() const {
+ return OS::get_singleton()->get_screen_count();
+}
+
+int _OS::get_screen() const {
+ return OS::get_singleton()->get_screen();
+}
+
+void _OS::set_screen(int p_screen) {
+ OS::get_singleton()->set_screen(p_screen);
+}
+
+Point2 _OS::get_screen_position(int p_screen) const {
+ return OS::get_singleton()->get_screen_position(p_screen);
+}
+
+Size2 _OS::get_screen_size(int p_screen) const {
+ return OS::get_singleton()->get_screen_size(p_screen);
+}
+
+Point2 _OS::get_window_position() const {
+ return OS::get_singleton()->get_window_position();
+}
+
+void _OS::set_window_position(const Point2& p_position) {
+ OS::get_singleton()->set_window_position(p_position);
+}
+
+Size2 _OS::get_window_size() const {
+ return OS::get_singleton()->get_window_size();
+}
+
+void _OS::set_window_size(const Size2& p_size) {
+ OS::get_singleton()->set_window_size(p_size);
+}
+
+void _OS::set_fullscreen(bool p_enabled) {
+ OS::get_singleton()->set_fullscreen(p_enabled);
+}
+
+bool _OS::is_fullscreen() const {
+ return OS::get_singleton()->is_fullscreen();
+}
+
+void _OS::set_resizable(bool p_enabled) {
+ OS::get_singleton()->set_resizable(p_enabled);
+}
+
+bool _OS::is_resizable() const {
+ return OS::get_singleton()->is_resizable();
+}
+
+void _OS::set_minimized(bool p_enabled) {
+ OS::get_singleton()->set_minimized(p_enabled);
+}
+
+bool _OS::is_minimized() const {
+ return OS::get_singleton()->is_minimized();
+}
+
+void _OS::set_maximized(bool p_enabled) {
+ OS::get_singleton()->set_maximized(p_enabled);
+}
+
+bool _OS::is_maximized() const {
+ return OS::get_singleton()->is_maximized();
+}
+#endif
+
void _OS::set_use_file_access_save_and_swap(bool p_enable) {
FileAccess::set_backup_save(p_enable);
@@ -186,7 +256,6 @@ bool _OS::is_video_mode_resizable(int p_screen) const {
OS::VideoMode vm;
vm = OS::get_singleton()->get_video_mode(p_screen);
return vm.resizable;
-
}
Array _OS::get_fullscreen_mode_list(int p_screen) const {
@@ -632,6 +701,26 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_video_mode_resizable","screen"),&_OS::is_video_mode_resizable,DEFVAL(0));
ObjectTypeDB::bind_method(_MD("get_fullscreen_mode_list","screen"),&_OS::get_fullscreen_mode_list,DEFVAL(0));
+#ifdef EXPERIMENTAL_WM_API
+ ObjectTypeDB::bind_method(_MD("get_screen_count"),&_OS::get_screen_count);
+ ObjectTypeDB::bind_method(_MD("get_screen"),&_OS::get_screen);
+ ObjectTypeDB::bind_method(_MD("set_screen"),&_OS::set_screen);
+ ObjectTypeDB::bind_method(_MD("get_screen_position"),&_OS::get_screen_position,DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("get_screen_size"),&_OS::get_screen_size,DEFVAL(0));
+ ObjectTypeDB::bind_method(_MD("get_window_position"),&_OS::get_window_position);
+ ObjectTypeDB::bind_method(_MD("set_window_position"),&_OS::set_window_position);
+ ObjectTypeDB::bind_method(_MD("get_window_size"),&_OS::get_window_size);
+ ObjectTypeDB::bind_method(_MD("set_window_size"),&_OS::set_window_size);
+ ObjectTypeDB::bind_method(_MD("set_fullscreen","enabled"),&_OS::set_fullscreen);
+ ObjectTypeDB::bind_method(_MD("is_fullscreen"),&_OS::is_fullscreen);
+ ObjectTypeDB::bind_method(_MD("set_resizable","enabled"),&_OS::set_resizable);
+ ObjectTypeDB::bind_method(_MD("is_resizable"),&_OS::is_resizable);
+ ObjectTypeDB::bind_method(_MD("set_minimized", "enabled"),&_OS::set_minimized);
+ ObjectTypeDB::bind_method(_MD("is_minimized"),&_OS::is_minimized);
+ ObjectTypeDB::bind_method(_MD("set_maximized", "enabled"),&_OS::set_maximized);
+ ObjectTypeDB::bind_method(_MD("is_maximized"),&_OS::is_maximized);
+#endif
+
ObjectTypeDB::bind_method(_MD("set_iterations_per_second","iterations_per_second"),&_OS::set_iterations_per_second);
ObjectTypeDB::bind_method(_MD("get_iterations_per_second"),&_OS::get_iterations_per_second);
ObjectTypeDB::bind_method(_MD("set_target_fps","target_fps"),&_OS::set_target_fps);
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 12a4ae86eb..b6f4f8eef4 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -108,6 +108,26 @@ public:
bool is_video_mode_resizable(int p_screen=0) const;
Array get_fullscreen_mode_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;
+ virtual void set_resizable(bool p_enabled);
+ virtual bool is_resizable() const;
+ virtual void set_minimized(bool p_enabled);
+ virtual bool is_minimized() const;
+ virtual void set_maximized(bool p_enabled);
+ virtual bool is_maximized() const;
+#endif
+
Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
bool native_video_is_playing();
void native_video_pause();
diff --git a/core/os/os.h b/core/os/os.h
index d4deff2f5e..c04a91e302 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -73,7 +73,7 @@ public:
bool fullscreen;
bool resizable;
float get_aspect() const { return (float)width/(float)height; }
- VideoMode(int p_width=640,int p_height=480,bool p_fullscreen=false, bool p_resizable = true) { width=p_width; height=p_height; fullscreen=p_fullscreen; resizable = p_resizable; }
+ VideoMode(int p_width=640,int p_height=480,bool p_fullscreen=false, bool p_resizable = true) {width=p_width; height=p_height; fullscreen=p_fullscreen; resizable = p_resizable; }
};
protected:
friend class Main;
@@ -149,7 +149,27 @@ public:
virtual void set_video_mode(const VideoMode& p_video_mode,int p_screen=0)=0;
virtual VideoMode get_video_mode(int p_screen=0) const=0;
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen=0) const=0;
-
+
+#ifdef EXPERIMENTAL_WM_API
+ virtual int get_screen_count() const=0;
+ virtual int get_screen() const=0;
+ virtual void set_screen(int p_screen)=0;
+ virtual Point2 get_screen_position(int p_screen=0) const=0;
+ virtual Size2 get_screen_size(int p_screen=0) const=0;
+ virtual Point2 get_window_position() const=0;
+ virtual void set_window_position(const Point2& p_position)=0;
+ virtual Size2 get_window_size() const=0;
+ virtual void set_window_size(const Size2 p_size)=0;
+ virtual void set_fullscreen(bool p_enabled)=0;
+ virtual bool is_fullscreen() const=0;
+ virtual void set_resizable(bool p_enabled)=0;
+ virtual bool is_resizable() const=0;
+ virtual void set_minimized(bool p_enabled)=0;
+ virtual bool is_minimized() const=0;
+ virtual void set_maximized(bool p_enabled)=0;
+ virtual bool is_maximized() const=0;
+#endif
+
virtual void set_iterations_per_second(int p_ips);
virtual int get_iterations_per_second() const;
diff --git a/demos/misc/window_management/control.gd b/demos/misc/window_management/control.gd
new file mode 100644
index 0000000000..4929b1376c
--- /dev/null
+++ b/demos/misc/window_management/control.gd
@@ -0,0 +1,116 @@
+
+extends Control
+
+func _fixed_process(delta):
+
+ var modetext = "Mode:\n"
+
+ if(OS.is_fullscreen()):
+ modetext += "Fullscreen\n"
+ else:
+ modetext += "Windowed\n"
+
+ if(!OS.is_resizable()):
+ modetext += "FixedSize\n"
+
+ if(OS.is_minimized()):
+ modetext += "Minimized\n"
+
+ if(OS.is_maximized()):
+ modetext += "Maximized\n"
+
+ get_node("Label_Mode").set_text(modetext)
+
+ get_node("Label_Position").set_text( str("Position:\n", OS.get_window_position() ) )
+
+ get_node("Label_Size").set_text(str("Size:\n", OS.get_window_size() ) )
+
+ get_node("Label_Screen_Count").set_text( str("Screen_Count:\n", OS.get_screen_count() ) )
+
+ get_node("Label_Screen_Current").set_text( str("Screen:\n", OS.get_screen() ) )
+
+ get_node("Label_Screen0_Resolution").set_text( str("Screen0 Resolution:\n", OS.get_screen_size() ) )
+
+ get_node("Label_Screen0_Position").set_text(str("Screen0 Position:\n",OS.get_screen_position() ) )
+
+
+ if(OS.get_screen_count() > 1):
+ get_node("Button_Screen0").show()
+ get_node("Button_Screen1").show()
+ get_node("Label_Screen1_Resolution").show()
+ get_node("Label_Screen1_Position").show()
+ get_node("Label_Screen1_Resolution").set_text( str("Screen1 Resolution:\n", OS.get_screen_size(1) ) )
+ get_node("Label_Screen1_Position").set_text( str("Screen1 Position:\n", OS.get_screen_position(1) ) )
+ else:
+ get_node("Button_Screen0").hide()
+ get_node("Button_Screen1").hide()
+ get_node("Label_Screen1_Resolution").hide()
+ get_node("Label_Screen1_Position").hide()
+
+ if( Input.is_action_pressed("ui_right")):
+ OS.set_screen(1)
+
+ if( Input.is_action_pressed("ui_left")):
+ OS.set_screen(0)
+
+ if( Input.is_action_pressed("ui_up")):
+ OS.set_fullscreen(true)
+
+ if( Input.is_action_pressed("ui_down")):
+ OS.set_fullscreen(false)
+
+ get_node("Button_Fullscreen").set_pressed( OS.is_fullscreen() )
+ get_node("Button_FixedSize").set_pressed( !OS.is_resizable() )
+ get_node("Button_Minimized").set_pressed( OS.is_minimized() )
+ get_node("Button_Maximized").set_pressed( OS.is_maximized() )
+
+
+func _ready():
+ set_fixed_process(true)
+
+
+func _on_Button_MoveTo_pressed():
+ OS.set_window_position( Vector2(100,100) )
+
+
+func _on_Button_Resize_pressed():
+ OS.set_window_size( Vector2(1024,768) )
+
+
+func _on_Button_Screen0_pressed():
+ OS.set_screen(0)
+
+
+func _on_Button_Screen1_pressed():
+ OS.set_screen(1)
+
+
+func _on_Button_Fullscreen_pressed():
+ if(OS.is_fullscreen()):
+ OS.set_fullscreen(false)
+ else:
+ OS.set_fullscreen(true)
+
+
+func _on_Button_FixedSize_pressed():
+ if(OS.is_resizable()):
+ OS.set_resizable(false)
+ else:
+ OS.set_resizable(true)
+
+
+func _on_Button_Minimized_pressed():
+ if(OS.is_minimized()):
+ OS.set_minimized(false)
+ else:
+ OS.set_minimized(true)
+
+
+func _on_Button_Maximized_pressed():
+ if(OS.is_maximized()):
+ OS.set_maximized(false)
+ else:
+ OS.set_maximized(true)
+
+
+
diff --git a/demos/misc/window_management/engine.cfg b/demos/misc/window_management/engine.cfg
new file mode 100644
index 0000000000..6ce3d51aee
--- /dev/null
+++ b/demos/misc/window_management/engine.cfg
@@ -0,0 +1,12 @@
+[application]
+
+name="window_management"
+main_scene="res://window_management.scn"
+icon="icon.png"
+
+[display]
+
+fullscreen=false
+resizable=true
+width=800
+height=600
diff --git a/demos/misc/window_management/icon.png b/demos/misc/window_management/icon.png
new file mode 100644
index 0000000000..0c422e37b0
--- /dev/null
+++ b/demos/misc/window_management/icon.png
Binary files differ
diff --git a/demos/misc/window_management/icon.png.flags b/demos/misc/window_management/icon.png.flags
new file mode 100644
index 0000000000..5130fd1aab
--- /dev/null
+++ b/demos/misc/window_management/icon.png.flags
@@ -0,0 +1 @@
+gen_mipmaps=false
diff --git a/demos/misc/window_management/window_management.scn b/demos/misc/window_management/window_management.scn
new file mode 100644
index 0000000000..baf03bdfd1
--- /dev/null
+++ b/demos/misc/window_management/window_management.scn
Binary files differ
diff --git a/main/main.cpp b/main/main.cpp
index f0e376a045..27d7d97e85 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -627,7 +627,6 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
}
}
-
GLOBAL_DEF("display/width",video_mode.width);
GLOBAL_DEF("display/height",video_mode.height);
GLOBAL_DEF("display/fullscreen",video_mode.fullscreen);
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index 5171bc972d..6adba510e1 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():
@@ -153,3 +159,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..d711cea42e 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -36,6 +36,17 @@
#include "servers/physics/physics_server_sw.h"
#include "X11/Xutil.h"
+#ifdef EXPERIMENTAL_WM_API
+#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
+#endif
#include "main/main.h"
@@ -56,7 +67,7 @@
#include <X11/Xatom.h>
-#include "os/pc_joystick_map.h"
+//#include "os/pc_joystick_map.h"
#undef CursorShape
@@ -117,10 +128,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) {
@@ -128,7 +139,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] ==
@@ -162,6 +173,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();
@@ -179,9 +191,10 @@ 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));
}
+#ifndef EXPERIMENTAL_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;
@@ -210,7 +223,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();
@@ -226,7 +239,23 @@ 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
+ if (current_videomode.fullscreen) {
+ minimized = false;
+ maximized = false;
+ //set_wm_border(false);
+ set_wm_fullscreen(true);
+ }
+ if (!current_videomode.resizable) {
+ int screen = get_screen();
+ Size2i screen_size = get_screen_size(screen);
+ set_window_size(screen_size);
+ set_resizable(false);
}
+#endif
+
AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
@@ -264,19 +293,20 @@ 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) {
+ char wmclass[] = "Godot";
+ classHint->res_name = wmclass;
+ classHint->res_class = wmclass;
+ }
+ 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);
@@ -493,7 +523,6 @@ OS::MouseMode OS_X11::get_mouse_mode() const {
int OS_X11::get_mouse_button_state() const {
-
return last_button_state;
}
@@ -520,6 +549,378 @@ void OS_X11::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) cons
}
+#ifdef EXPERIMENTAL_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_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 {
+ // 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_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
+ 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_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);
+}
+
+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_fullscreen(bool p_enabled) {
+
+#if 0
+ if(p_enabled && current_videomode.fullscreen)
+ return;
+
+ if(!current_videomode.resizable)
+ set_resizable(true);
+
+ 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;
+ }
+#endif
+ set_wm_fullscreen(p_enabled);
+ current_videomode.fullscreen = p_enabled;
+
+ visual_server->init();
+
+}
+
+bool OS_X11::is_fullscreen() const {
+ return current_videomode.fullscreen;
+}
+
+void OS_X11::set_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_resizable() const {
+ return current_videomode.resizable;
+}
+
+void OS_X11::set_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_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_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);
+
+ maximized = p_enabled;
+}
+
+bool OS_X11::is_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;
+}
+#endif
InputModifierState OS_X11::get_key_modifier_state(unsigned int p_x11_state) {
@@ -594,11 +995,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.
@@ -695,7 +1094,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
@@ -759,13 +1158,16 @@ void OS_X11::process_xevents() {
break;
case VisibilityNotify: {
-
XVisibilityEvent * visibility = (XVisibilityEvent *)&event;
minimized = (visibility->state == VisibilityFullyObscured);
-
} break;
- case FocusIn:
+ case FocusIn:
+ minimized = false;
+ if(current_videomode.fullscreen) {
+ set_wm_fullscreen(true);
+ visual_server->init();
+ }
main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
if (mouse_mode==MOUSE_MODE_CAPTURED) {
XGrabPointer(x11_display, x11_window, True,
@@ -776,6 +1178,11 @@ void OS_X11::process_xevents() {
break;
case FocusOut:
+ if(current_videomode.fullscreen) {
+ set_wm_fullscreen(false);
+ set_minimized(true);
+ visual_server->init();
+ }
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.
@@ -856,7 +1263,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 +1272,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
@@ -1354,6 +1761,7 @@ void OS_X11::process_joysticks() {
#endif
};
+
void OS_X11::set_cursor_shape(CursorShape p_shape) {
ERR_FAIL_INDEX(p_shape,CURSOR_MAX);
@@ -1466,8 +1874,6 @@ OS_X11::OS_X11() {
#endif
minimized = false;
- xim_style=NULL;
+ xim_style=0L;
mouse_mode=MOUSE_MODE_VISIBLE;
-
-
};
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index dd2476ec1b..b47c5db069 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -159,6 +159,11 @@ class OS_X11 : public OS_Unix {
int joystick_count;
Joystick joysticks[JOYSTICKS_MAX];
+#ifdef EXPERIMENTAL_WM_API
+ bool maximized;
+ //void set_wm_border(bool p_enabled);
+ void set_wm_fullscreen(bool p_enabled);
+#endif
protected:
@@ -166,8 +171,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 +183,7 @@ protected:
void process_joysticks();
void close_joystick(int p_id = -1);
+
public:
virtual String get_name();
@@ -213,6 +219,25 @@ 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;
+ virtual void set_resizable(bool p_enabled);
+ virtual bool is_resizable() const;
+ virtual void set_minimized(bool p_enabled);
+ virtual bool is_minimized() const;
+ virtual void set_maximized(bool p_enabled);
+ virtual bool is_maximized() const;
+#endif
virtual void move_window_to_foreground();
void run();