diff options
Diffstat (limited to 'platform/linuxbsd')
| -rw-r--r-- | platform/linuxbsd/display_server_x11.cpp | 129 | ||||
| -rw-r--r-- | platform/linuxbsd/display_server_x11.h | 8 | ||||
| -rw-r--r-- | platform/linuxbsd/gl_manager_x11.cpp | 44 | ||||
| -rw-r--r-- | platform/linuxbsd/os_linuxbsd.cpp | 8 | 
4 files changed, 135 insertions, 54 deletions
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index c4f7a3a646..c3b44f348c 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -33,6 +33,7 @@  #ifdef X11_ENABLED  #include "core/config/project_settings.h" +#include "core/math/math_funcs.h"  #include "core/string/print_string.h"  #include "core/string/ustring.h"  #include "detect_prime_x11.h" @@ -64,7 +65,6 @@  // 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 <dlfcn.h>  #include <fcntl.h> @@ -324,20 +324,21 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) {  	if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {  		//flush pending motion events  		_flush_mouse_motion(); -		WindowData &main_window = windows[MAIN_WINDOW_ID]; +		WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; +		WindowData &window = windows[window_id];  		if (XGrabPointer( -					x11_display, main_window.x11_window, True, +					x11_display, window.x11_window, True,  					ButtonPressMask | ButtonReleaseMask | PointerMotionMask, -					GrabModeAsync, GrabModeAsync, windows[MAIN_WINDOW_ID].x11_window, None, CurrentTime) != GrabSuccess) { +					GrabModeAsync, GrabModeAsync, window.x11_window, None, CurrentTime) != GrabSuccess) {  			ERR_PRINT("NO GRAB");  		}  		if (mouse_mode == MOUSE_MODE_CAPTURED) { -			center.x = main_window.size.width / 2; -			center.y = main_window.size.height / 2; +			center.x = window.size.width / 2; +			center.y = window.size.height / 2; -			XWarpPointer(x11_display, None, main_window.x11_window, +			XWarpPointer(x11_display, None, window.x11_window,  					0, 0, 0, 0, (int)center.x, (int)center.y);  			Input::get_singleton()->set_mouse_position(center); @@ -359,27 +360,13 @@ void DisplayServerX11::mouse_warp_to_position(const Point2i &p_to) {  	if (mouse_mode == MOUSE_MODE_CAPTURED) {  		last_mouse_pos = p_to;  	} else { -		XWarpPointer(x11_display, None, windows[MAIN_WINDOW_ID].x11_window, +		WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; +		XWarpPointer(x11_display, None, windows[window_id].x11_window,  				0, 0, 0, 0, (int)p_to.x, (int)p_to.y);  	}  }  Point2i DisplayServerX11::mouse_get_position() const { -	int root_x, root_y; -	int win_x, win_y; -	unsigned int mask_return; -	Window window_returned; - -	Bool result = XQueryPointer(x11_display, RootWindow(x11_display, DefaultScreen(x11_display)), &window_returned, -			&window_returned, &root_x, &root_y, &win_x, &win_y, -			&mask_return); -	if (result == True) { -		return Point2i(root_x, root_y); -	} -	return Point2i(); -} - -Point2i DisplayServerX11::mouse_get_absolute_position() const {  	int number_of_screens = XScreenCount(x11_display);  	for (int i = 0; i < number_of_screens; i++) {  		Window root, child; @@ -1068,6 +1055,67 @@ int DisplayServerX11::screen_get_dpi(int p_screen) const {  	return 96;  } +float DisplayServerX11::screen_get_refresh_rate(int p_screen) const { +	_THREAD_SAFE_METHOD_ + +	if (p_screen == SCREEN_OF_MAIN_WINDOW) { +		p_screen = window_get_current_screen(); +	} + +	//invalid screen? +	ERR_FAIL_INDEX_V(p_screen, get_screen_count(), SCREEN_REFRESH_RATE_FALLBACK); + +	//Use xrandr to get screen refresh rate. +	if (xrandr_ext_ok) { +		XRRScreenResources *screen_info = XRRGetScreenResources(x11_display, windows[MAIN_WINDOW_ID].x11_window); +		if (screen_info) { +			RRMode current_mode = 0; +			xrr_monitor_info *monitors = nullptr; + +			if (xrr_get_monitors) { +				int count = 0; +				monitors = xrr_get_monitors(x11_display, windows[MAIN_WINDOW_ID].x11_window, true, &count); +				ERR_FAIL_INDEX_V(p_screen, count, SCREEN_REFRESH_RATE_FALLBACK); +			} else { +				ERR_PRINT("An error occured while trying to get the screen refresh rate."); +				return SCREEN_REFRESH_RATE_FALLBACK; +			} + +			bool found_active_mode = false; +			for (int crtc = 0; crtc < screen_info->ncrtc; crtc++) { // Loop through outputs to find which one is currently outputting. +				XRRCrtcInfo *monitor_info = XRRGetCrtcInfo(x11_display, screen_info, screen_info->crtcs[crtc]); +				if (monitor_info->x != monitors[p_screen].x || monitor_info->y != monitors[p_screen].y) { // If X and Y aren't the same as the monitor we're looking for, this isn't the right monitor. Continue. +					continue; +				} + +				if (monitor_info->mode != None) { +					current_mode = monitor_info->mode; +					found_active_mode = true; +					break; +				} +			} + +			if (found_active_mode) { +				for (int mode = 0; mode < screen_info->nmode; mode++) { +					XRRModeInfo m_info = screen_info->modes[mode]; +					if (m_info.id == current_mode) { +						// Snap to nearest 0.01 to stay consistent with other platforms. +						return Math::snapped((float)m_info.dotClock / ((float)m_info.hTotal * (float)m_info.vTotal), 0.01); +					} +				} +			} + +			ERR_PRINT("An error occured while trying to get the screen refresh rate."); // We should have returned the refresh rate by now. An error must have occured. +			return SCREEN_REFRESH_RATE_FALLBACK; +		} else { +			ERR_PRINT("An error occured while trying to get the screen refresh rate."); +			return SCREEN_REFRESH_RATE_FALLBACK; +		} +	} +	ERR_PRINT("An error occured while trying to get the screen refresh rate."); +	return SCREEN_REFRESH_RATE_FALLBACK; +} +  bool DisplayServerX11::screen_is_touchscreen(int p_screen) const {  	_THREAD_SAFE_METHOD_ @@ -1170,6 +1218,24 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) {  	windows.erase(p_id);  } +int64_t DisplayServerX11::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { +	ERR_FAIL_COND_V(!windows.has(p_window), 0); +	switch (p_handle_type) { +		case DISPLAY_HANDLE: { +			return (int64_t)x11_display; +		} +		case WINDOW_HANDLE: { +			return (int64_t)windows[p_window].x11_window; +		} +		case WINDOW_VIEW: { +			return 0; // Not supported. +		} +		default: { +			return 0; +		} +	} +} +  void DisplayServerX11::window_attach_instance_id(ObjectID p_instance, WindowID p_window) {  	ERR_FAIL_COND(!windows.has(p_window));  	WindowData &wd = windows[p_window]; @@ -1330,8 +1396,9 @@ int DisplayServerX11::window_get_current_screen(WindowID p_window) const {  void DisplayServerX11::gl_window_make_current(DisplayServer::WindowID p_window_id) {  #if defined(GLES3_ENABLED) -	if (gl_manager) +	if (gl_manager) {  		gl_manager->window_make_current(p_window_id); +	}  #endif  } @@ -1820,6 +1887,7 @@ void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {  			XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);  		} break; +		case WINDOW_MODE_EXCLUSIVE_FULLSCREEN:  		case WINDOW_MODE_FULLSCREEN: {  			//Remove full-screen  			wd.fullscreen = false; @@ -1872,6 +1940,7 @@ void DisplayServerX11::window_set_mode(WindowMode p_mode, WindowID p_window) {  			XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);  		} break; +		case WINDOW_MODE_EXCLUSIVE_FULLSCREEN:  		case WINDOW_MODE_FULLSCREEN: {  			wd.last_position_before_fs = wd.position; @@ -2412,7 +2481,7 @@ Key DisplayServerX11::keyboard_get_keycode_from_physical(Key p_keycode) const {  	Key keycode_no_mod = p_keycode & KeyModifierMask::CODE_MASK;  	unsigned int xkeycode = KeyMappingX11::get_xlibcode(keycode_no_mod);  	KeySym xkeysym = XkbKeycodeToKeysym(x11_display, xkeycode, 0, 0); -	if (xkeysym >= 'a' && xkeysym <= 'z') { +	if (is_ascii_lower_case(xkeysym)) {  		xkeysym -= ('a' - 'A');  	} @@ -3350,7 +3419,7 @@ void DisplayServerX11::process_events() {  				DEBUG_LOG_X11("[%u] FocusIn window=%lu (%u), mode='%u' \n", frame, event.xfocus.window, window_id, event.xfocus.mode);  				WindowData &wd = windows[window_id]; - +				last_focused_window = window_id;  				wd.focused = true;  				if (wd.xic) { @@ -3550,9 +3619,9 @@ void DisplayServerX11::process_events() {  				// The X11 API requires filtering one-by-one through the motion  				// notify events, in order to figure out which event is the one  				// generated by warping the mouse pointer. - +				WindowID focused_window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID;  				while (true) { -					if (mouse_mode == MOUSE_MODE_CAPTURED && event.xmotion.x == windows[MAIN_WINDOW_ID].size.width / 2 && event.xmotion.y == windows[MAIN_WINDOW_ID].size.height / 2) { +					if (mouse_mode == MOUSE_MODE_CAPTURED && event.xmotion.x == windows[focused_window_id].size.width / 2 && event.xmotion.y == windows[focused_window_id].size.height / 2) {  						//this is likely the warp event since it was warped here  						center = Vector2(event.xmotion.x, event.xmotion.y);  						break; @@ -3627,9 +3696,8 @@ void DisplayServerX11::process_events() {  				// Reset to prevent lingering motion  				xi.relative_motion.x = 0;  				xi.relative_motion.y = 0; -  				if (mouse_mode == MOUSE_MODE_CAPTURED) { -					pos = Point2i(windows[MAIN_WINDOW_ID].size.width / 2, windows[MAIN_WINDOW_ID].size.height / 2); +					pos = Point2i(windows[focused_window_id].size.width / 2, windows[focused_window_id].size.height / 2);  				}  				Ref<InputEventMouseMotion> mm; @@ -3647,7 +3715,6 @@ void DisplayServerX11::process_events() {  				mm->set_button_mask((MouseButton)mouse_get_button_state());  				mm->set_position(pos);  				mm->set_global_position(pos); -				Input::get_singleton()->set_mouse_position(pos);  				mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity());  				mm->set_relative(rel); diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index 1dcedabb1a..2d07361deb 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -143,7 +143,7 @@ class DisplayServerX11 : public DisplayServer {  		bool borderless = false;  		bool resize_disabled = false;  		Vector2i last_position_before_fs; -		bool focused = false; +		bool focused = true;  		bool minimized = false;  		unsigned int focus_order = 0; @@ -151,6 +151,8 @@ class DisplayServerX11 : public DisplayServer {  	Map<WindowID, WindowData> windows; +	WindowID last_focused_window = INVALID_WINDOW_ID; +  	WindowID window_id_counter = MAIN_WINDOW_ID;  	WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect); @@ -289,7 +291,6 @@ public:  	virtual void mouse_warp_to_position(const Point2i &p_to) override;  	virtual Point2i mouse_get_position() const override; -	virtual Point2i mouse_get_absolute_position() const override;  	virtual MouseButton mouse_get_button_state() const override;  	virtual void clipboard_set(const String &p_text) override; @@ -302,6 +303,7 @@ public:  	virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;  	virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;  	virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; +	virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;  	virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;  #if defined(DBUS_ENABLED) @@ -317,6 +319,8 @@ public:  	virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override; +	virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; +  	virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;  	virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override; diff --git a/platform/linuxbsd/gl_manager_x11.cpp b/platform/linuxbsd/gl_manager_x11.cpp index 1721d0e0b3..d3fb1d6705 100644 --- a/platform/linuxbsd/gl_manager_x11.cpp +++ b/platform/linuxbsd/gl_manager_x11.cpp @@ -68,8 +68,9 @@ static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) {  int GLManager_X11::_find_or_create_display(Display *p_x11_display) {  	for (unsigned int n = 0; n < _displays.size(); n++) {  		const GLDisplay &d = _displays[n]; -		if (d.x11_display == p_x11_display) +		if (d.x11_display == p_x11_display) {  			return n; +		}  	}  	// create @@ -82,8 +83,7 @@ int GLManager_X11::_find_or_create_display(Display *p_x11_display) {  	GLDisplay &d = _displays[new_display_id];  	d.context = memnew(GLManager_X11_Private); -	; -	d.context->glx_context = 0; +	d.context->glx_context = nullptr;  	//Error err = _create_context(d);  	_create_context(d); @@ -124,7 +124,7 @@ Error GLManager_X11::_create_context(GLDisplay &gl_display) {  	};  	int fbcount; -	GLXFBConfig fbconfig = 0; +	GLXFBConfig fbconfig = nullptr;  	XVisualInfo *vi = nullptr;  	gl_display.x_swa.event_mask = StructureNotifyMask; @@ -137,8 +137,9 @@ Error GLManager_X11::_create_context(GLDisplay &gl_display) {  		for (int i = 0; i < fbcount; i++) {  			vi = (XVisualInfo *)glXGetVisualFromFBConfig(x11_display, fbc[i]); -			if (!vi) +			if (!vi) {  				continue; +			}  			XRenderPictFormat *pict_format = XRenderFindVisualFormat(x11_display, vi->visual);  			if (!pict_format) { @@ -262,22 +263,26 @@ void GLManager_X11::window_destroy(DisplayServer::WindowID p_window_id) {  }  void GLManager_X11::release_current() { -	if (!_current_window) +	if (!_current_window) {  		return; +	}  	glXMakeCurrent(_x_windisp.x11_display, None, nullptr);  }  void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) { -	if (p_window_id == -1) +	if (p_window_id == -1) {  		return; +	}  	GLWindow &win = _windows[p_window_id]; -	if (!win.in_use) +	if (!win.in_use) {  		return; +	}  	// noop -	if (&win == _current_window) +	if (&win == _current_window) {  		return; +	}  	const GLDisplay &disp = get_display(win.gldisplay_id); @@ -287,8 +292,9 @@ void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) {  }  void GLManager_X11::make_current() { -	if (!_current_window) +	if (!_current_window) {  		return; +	}  	if (!_current_window->in_use) {  		WARN_PRINT("current window not in use!");  		return; @@ -301,8 +307,9 @@ void GLManager_X11::swap_buffers() {  	// NO NEED TO CALL SWAP BUFFERS for each window...  	// see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXSwapBuffers.xml -	if (!_current_window) +	if (!_current_window) {  		return; +	}  	if (!_current_window->in_use) {  		WARN_PRINT("current window not in use!");  		return; @@ -335,19 +342,23 @@ void GLManager_X11::set_use_vsync(bool p_use) {  	}  	// we need an active window to get a display to set the vsync -	if (!_current_window) +	if (!_current_window) {  		return; +	}  	const GLDisplay &disp = get_current_display();  	if (!setup) {  		setup = true;  		String extensions = glXQueryExtensionsString(disp.x11_display, DefaultScreen(disp.x11_display)); -		if (extensions.find("GLX_EXT_swap_control") != -1) +		if (extensions.find("GLX_EXT_swap_control") != -1) {  			glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalEXT"); -		if (extensions.find("GLX_MESA_swap_control") != -1) +		} +		if (extensions.find("GLX_MESA_swap_control") != -1) {  			glXSwapIntervalMESA = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalMESA"); -		if (extensions.find("GLX_SGI_swap_control") != -1) +		} +		if (extensions.find("GLX_SGI_swap_control") != -1) {  			glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalSGI"); +		}  	}  	int val = p_use ? 1 : 0;  	if (glXSwapIntervalMESA) { @@ -357,8 +368,9 @@ void GLManager_X11::set_use_vsync(bool p_use) {  	} else if (glXSwapIntervalEXT) {  		GLXDrawable drawable = glXGetCurrentDrawable();  		glXSwapIntervalEXT(disp.x11_display, drawable, val); -	} else +	} else {  		return; +	}  	use_vsync = p_use;  } diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index b5f127bb16..e95a865636 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -448,7 +448,7 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {  	// Create needed directories for decided trash can location.  	{ -		DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); +		DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);  		Error err = dir_access->make_dir_recursive(trash_path);  		// Issue an error if trash can is not created properly. @@ -457,7 +457,6 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {  		ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/files");  		err = dir_access->make_dir_recursive(trash_path + "/info");  		ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/info"); -		memdelete(dir_access);  	}  	// The trash can is successfully created, now we check that we don't exceed our file name length limit. @@ -497,16 +496,15 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {  	String trash_info = "[Trash Info]\nPath=" + p_path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";  	{  		Error err; -		FileAccess *file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err); +		FileAccessRef file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);  		ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file:" + trash_path + "/info/" + file_name + ".trashinfo");  		file->store_string(trash_info);  		file->close();  		// Rename our resource before moving it to the trash can. -		DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); +		DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);  		err = dir_access->rename(p_path, p_path.get_base_dir() + "/" + file_name);  		ERR_FAIL_COND_V_MSG(err != OK, err, "Can't rename file \"" + p_path + "\""); -		memdelete(dir_access);  	}  	// Move the given resource to the trash can.  |