Преглед изворни кода

added the following methods:
* set_minimized(bool)
* bool is_minimized()
* set_maximized(bool)
* bool is_maximized()

hurikhan пре 10 година
родитељ
комит
716971655e

+ 21 - 1
core/bind/core_bind.cpp

@@ -228,6 +228,22 @@ void _OS::set_resizable(bool 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) {
@@ -698,7 +714,11 @@ void _OS::_bind_methods() {
 	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("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);

+ 8 - 4
core/bind/core_bind.h

@@ -118,10 +118,14 @@ public:
 	virtual void set_window_position(const Point2& p_position);
 	virtual Size2 get_window_size() const;
 	virtual void set_window_size(const Size2& p_size);
-	void set_fullscreen(bool p_enabled);
-	bool is_fullscreen() const;
-	void set_resizable(bool p_enabled);
-	bool is_resizable() const;
+	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);

+ 4 - 0
core/os/os.h

@@ -164,6 +164,10 @@ public:
 	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);

+ 26 - 7
demos/misc/window_management/control.gd

@@ -13,17 +13,25 @@ func _fixed_process(delta):
 	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_Info").set_text( str("Screens:\n", OS.get_screen_count(),"\n\nCurrent:\n", OS.get_screen() ) )
+	get_node("Label_Screen_Count").set_text( str("Screens:\n", OS.get_screen_count() ) )
+	
+	get_node("Label_Screen_Current").set_text( str("Current:\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()))
+	get_node("Label_Screen0_Position").set_text(str("Screen0 Position:\n",OS.get_screen_position() ) )
 	
 	
 	if(OS.get_screen_count() > 1):
@@ -50,8 +58,9 @@ func _fixed_process(delta):
 		OS.set_fullscreen(false)
 		
 	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)
 
@@ -79,9 +88,6 @@ func _on_Button_Screen1_pressed():
 	OS.set_screen(1)
 
 
-
-
-
 func _on_Button_FixedSize_pressed():
 	if(OS.is_resizable()):
 		OS.set_resizable(false)
@@ -89,3 +95,16 @@ func _on_Button_FixedSize_pressed():
 		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)

BIN
demos/misc/window_management/window_management.scn


+ 131 - 6
platform/x11/os_x11.cpp

@@ -37,7 +37,16 @@
 
 #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"
 
@@ -214,6 +223,8 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
 
 		XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureNotifyMask, &xev);
 #else
+		minimized = false;
+		minimized = false;
 		window_data.position.x = 0;
 		window_data.position.y = 0;
 		window_data.size.width = 800;
@@ -549,7 +560,7 @@ void OS_X11::set_wm_border(bool p_enabled) {
 }
 
 void OS_X11::set_wm_fullscreen(bool p_enabled) {
-	// code for netwm-compliants
+	// 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);
@@ -559,7 +570,7 @@ void OS_X11::set_wm_fullscreen(bool p_enabled) {
 	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[0] = p_enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
 	xev.xclient.data.l[1] = wm_fullscreen;
 	xev.xclient.data.l[2] = 0;
 
@@ -567,6 +578,7 @@ void OS_X11::set_wm_fullscreen(bool p_enabled) {
 }
 
 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;
@@ -611,6 +623,7 @@ void OS_X11::set_screen(int p_screen) {
 }
 
 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);
@@ -625,6 +638,7 @@ Point2 OS_X11::get_screen_position(int p_screen) const {
 }
 
 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);
@@ -651,14 +665,14 @@ void OS_X11::set_window_position(const Point2& p_position) {
 	if( current_videomode.fullscreen )
 		return;
 
-	// _NET_FRAME_EXTENTS
+	// 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;
-	//long *extends;
 	int result;
 
 	result = XGetWindowProperty(
@@ -759,7 +773,6 @@ void OS_X11::set_resizable(bool p_enabled) {
 			xsh->max_width = xwa.width;
 			xsh->min_height = xwa.height;
 			xsh->max_height = xwa.height;
-			printf("%d %d\n", xwa.width, xwa.height);
 		}
 		XSetWMNormalHints(x11_display, x11_window, xsh);
 		XFree(xsh);
@@ -770,6 +783,119 @@ void OS_X11::set_resizable(bool 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, 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] == 3L ) 
+			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, 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;
+		}
+	}
+
+	return false;
+}
 #endif
 
 InputModifierState OS_X11::get_key_modifier_state(unsigned int p_x11_state) {
@@ -1719,4 +1845,3 @@ OS_X11::OS_X11() {
 	xim_style=0L;
 	mouse_mode=MOUSE_MODE_VISIBLE;
 };
-

+ 4 - 0
platform/x11/os_x11.h

@@ -241,6 +241,10 @@ public:
 	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();