diff options
| -rw-r--r-- | core/bind/core_bind.cpp | 91 | ||||
| -rw-r--r-- | core/bind/core_bind.h | 20 | ||||
| -rw-r--r-- | core/os/os.h | 24 | ||||
| -rw-r--r-- | demos/misc/window_management/control.gd | 177 | ||||
| -rw-r--r-- | demos/misc/window_management/engine.cfg | 19 | ||||
| -rw-r--r-- | demos/misc/window_management/icon.png | bin | 0 -> 3639 bytes | |||
| -rw-r--r-- | demos/misc/window_management/icon.png.flags | 1 | ||||
| -rw-r--r-- | demos/misc/window_management/observer/observer.gd | 79 | ||||
| -rw-r--r-- | demos/misc/window_management/observer/observer.scn | bin | 0 -> 1786 bytes | |||
| -rw-r--r-- | demos/misc/window_management/window_management.scn | bin | 0 -> 5087 bytes | |||
| -rw-r--r-- | platform/x11/detect.py | 10 | ||||
| -rw-r--r-- | platform/x11/os_x11.cpp | 485 | ||||
| -rw-r--r-- | platform/x11/os_x11.h | 30 | 
13 files changed, 884 insertions, 52 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 8d18acdc23..858f5cec27 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 NEW_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 { @@ -637,6 +706,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 NEW_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 057ad90fe9..1a80e35221 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 NEW_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..6301bd495f 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 NEW_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..bca13c5a0c --- /dev/null +++ b/demos/misc/window_management/control.gd @@ -0,0 +1,177 @@ + +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" +	 +	if(Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED): +		modetext += "MouseGrab\n" +		get_node("Label_MouseGrab_KeyInfo").show() +	else: +		get_node("Label_MouseGrab_KeyInfo").hide() +	 +	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_MousePosition").set_text(str("Mouse Position:\n", Input.get_mouse_pos() ) ) +	 +	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() +		 +	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() ) +	get_node("Button_Mouse_Grab").set_pressed( Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED ) + + +func check_wm_api(): +	var s = "" +	if( !OS.has_method("get_screen_count") ): +		s += " - get_screen_count()\n" +	 +	if( !OS.has_method("get_screen") ): +		s += " - get_screen()\n" +	 +	if( !OS.has_method("set_screen") ): +		s += " - set_screen()\n" +	 +	if( !OS.has_method("get_screen_position") ): +		s += " - get_screen_position()\n" +	 +	if( !OS.has_method("get_screen_size") ): +		s += " - get_screen_size()\n" +	 +	if( !OS.has_method("get_window_position") ): +		s += " - get_window_position()\n" +	 +	if( !OS.has_method("set_window_position") ): +		s += " - set_window_position()\n" +	 +	if( !OS.has_method("get_window_size") ): +		s += " - get_window_size()\n" +	 +	if( !OS.has_method("set_window_size") ): +		s += " - set_window_size()\n" +	 +	if( !OS.has_method("set_fullscreen") ): +		s += " - set_fullscreen()\n" +	 +	if( !OS.has_method("is_fullscreen") ): +		s += " - is_fullscreen()\n" +	 +	if( !OS.has_method("set_resizable") ): +		s += " - set_resizable()\n" +	 +	if( !OS.has_method("is_resizable") ): +		s += " - is_resizable()\n" +	 +	if( !OS.has_method("set_minimized") ): +		s += " - set_minimized()\n" +	 +	if( !OS.has_method("is_minimized") ): +		s += " - is_minimized()\n" +	 +	if( !OS.has_method("set_maximized") ): +		s += " - set_maximized()\n" +	 +	if( !OS.has_method("is_maximized") ): +		s += " - is_maximized()\n" +	 +	if( s.length() == 0 ): +		return true +	else: +		var text = get_node("ImplementationDialog/Text").get_text() +		get_node("ImplementationDialog/Text").set_text( text + s ) +		get_node("ImplementationDialog").show() +		return false + + +func _ready(): +	if( check_wm_api() ): +		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) + + +func _on_Button_Mouse_Grab_pressed(): +	var observer = get_node("../Observer") +	observer.state = observer.STATE_GRAB diff --git a/demos/misc/window_management/engine.cfg b/demos/misc/window_management/engine.cfg new file mode 100644 index 0000000000..c53bd45fb7 --- /dev/null +++ b/demos/misc/window_management/engine.cfg @@ -0,0 +1,19 @@ +[application] + +name="window_management" +main_scene="res://window_management.scn" +icon="icon.png" + +[display] + +fullscreen=false +resizable=true +width=800 +height=600 + +[input] + +move_forward=[key(W)] +move_backwards=[key(S)] +move_left=[key(A)] +move_right=[key(D)] diff --git a/demos/misc/window_management/icon.png b/demos/misc/window_management/icon.png Binary files differnew file mode 100644 index 0000000000..0c422e37b0 --- /dev/null +++ b/demos/misc/window_management/icon.png 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/observer/observer.gd b/demos/misc/window_management/observer/observer.gd new file mode 100644 index 0000000000..d27912a670 --- /dev/null +++ b/demos/misc/window_management/observer/observer.gd @@ -0,0 +1,79 @@ + +extends Spatial + +var r_pos = Vector2() +var state + +const STATE_MENU=0 +const STATE_GRAB=1 + +func direction(vector): +	var v = get_node("Camera").get_global_transform().basis * vector +	v = v.normalized() +	 +	return v + + +func impulse(event, action): +	if(event.is_action(action) && event.is_pressed() && !event.is_echo()): +		return true +	else: +		return false + + +func _fixed_process(delta): +	 +	if(state != STATE_GRAB): +		return +	 +	if(Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED): +		Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) +	 +	var dir = Vector3()  +	var cam = get_global_transform() +	var org = get_translation() +	 +	if (Input.is_action_pressed("move_forward")): +		dir += direction(Vector3(0,0,-1)) +	if (Input.is_action_pressed("move_backwards")): +		dir += direction(Vector3(0,0,1)) +	if (Input.is_action_pressed("move_left")): +		dir += direction(Vector3(-1,0,0)) +	if (Input.is_action_pressed("move_right")): +		dir += direction(Vector3(1,0,0)) +	 +	dir = dir.normalized() +	 +	move(dir * 10 * delta) +	var d = delta * 0.1 +	 +	var yaw = get_transform().rotated(Vector3(0,1,0), d * r_pos.x) +	set_transform(yaw) +	 +	var cam = get_node("Camera") +	var pitch = cam.get_transform().rotated(Vector3(1,0,0), d * r_pos.y) +	cam.set_transform(pitch) +	 +	r_pos.x = 0.0 +	r_pos.y = 0.0 + + +func _input( event ): +	if(event.type == InputEvent.MOUSE_MOTION): +		r_pos = event.relative_pos +	 +	if(impulse(event, "ui_cancel")): +		if(state == STATE_GRAB): +			Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) +			state = STATE_MENU +		else: +			Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) +			state = STATE_GRAB + + +func _ready(): +	set_fixed_process(true) +	set_process_input(true) +	 +	state = STATE_MENU + diff --git a/demos/misc/window_management/observer/observer.scn b/demos/misc/window_management/observer/observer.scn Binary files differnew file mode 100644 index 0000000000..da29ad62b8 --- /dev/null +++ b/demos/misc/window_management/observer/observer.scn diff --git a/demos/misc/window_management/window_management.scn b/demos/misc/window_management/window_management.scn Binary files differnew file mode 100644 index 0000000000..b8b0ee210b --- /dev/null +++ b/demos/misc/window_management/window_management.scn diff --git a/platform/x11/detect.py b/platform/x11/detect.py index fb5cdb5089..2519dd6fdf 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'), +	('new_wm_api', 'Use experimental window management API','no'),  	]  def get_flags(): @@ -147,3 +153,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["new_wm_api"]=="yes"): +		env.Append(CPPFLAGS=['-DNEW_WM_API']) +		env.ParseConfig('pkg-config xinerama --cflags --libs') + diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index ac1818d200..8196281732 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 NEW_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,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 (true) { -		rasterizer = memnew( RasterizerGLES2 ); -	} else { -		//rasterizer = memnew( RasterizerGLES1 ); -	}; +	rasterizer = memnew( RasterizerGLES2 );  #endif  	visual_server = memnew( VisualServerRaster(rasterizer) ); @@ -179,9 +187,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 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; @@ -210,7 +219,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 +235,25 @@ 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_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 +291,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); @@ -468,8 +496,9 @@ 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); +	}  }  void OS_X11::warp_mouse_pos(const Point2& p_to) { @@ -497,7 +526,6 @@ OS::MouseMode OS_X11::get_mouse_mode() const {  int OS_X11::get_mouse_button_state() const { -  	return last_button_state;  } @@ -524,6 +552,344 @@ void OS_X11::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) cons  } +#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_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) { +	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) { @@ -598,11 +964,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. @@ -699,7 +1063,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 @@ -763,13 +1127,18 @@ void OS_X11::process_xevents() {  			break;  		case VisibilityNotify: { -  			XVisibilityEvent * visibility = (XVisibilityEvent *)&event;  			minimized = (visibility->state == VisibilityFullyObscured); -  		} break; -		case FocusIn: +		case FocusIn:  +			minimized = false; +#ifdef NEW_WM_API +			if(current_videomode.fullscreen) { +				set_wm_fullscreen(true); +				visual_server->init(); +			} +#endif  			main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);  			if (mouse_mode==MOUSE_MODE_CAPTURED) {  				XGrabPointer(x11_display, x11_window, True, @@ -780,6 +1149,13 @@ void OS_X11::process_xevents() {  			break;  		case FocusOut: +#ifdef NEW_WM_API +			if(current_videomode.fullscreen) { +				set_wm_fullscreen(false); +				set_minimized(true); +				visual_server->init(); +			} +#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. @@ -806,7 +1182,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; @@ -841,7 +1217,7 @@ 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); @@ -851,16 +1227,15 @@ void OS_X11::process_xevents() {  			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. @@ -869,9 +1244,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 @@ -884,9 +1259,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) { @@ -895,7 +1268,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; @@ -915,6 +1295,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); @@ -989,8 +1371,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); +		*/  	}  } @@ -1358,6 +1750,7 @@ void OS_X11::process_joysticks() {  	#endif  }; +  void OS_X11::set_cursor_shape(CursorShape p_shape) {  	ERR_FAIL_INDEX(p_shape,CURSOR_MAX); @@ -1470,8 +1863,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..ffa1ce00b3 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -159,6 +159,12 @@ class OS_X11 : public OS_Unix {  	int joystick_count;  	Joystick joysticks[JOYSTICKS_MAX]; +#ifdef NEW_WM_API +	unsigned int capture_idle; +	bool maximized; +	//void set_wm_border(bool p_enabled); +	void set_wm_fullscreen(bool p_enabled); +#endif  protected: @@ -166,8 +172,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 +184,7 @@ protected:  	void process_joysticks();  	void close_joystick(int p_id = -1); +  public:  	virtual String get_name(); @@ -213,6 +220,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 NEW_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();  |