summaryrefslogtreecommitdiff
path: root/platform/linuxbsd
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r--platform/linuxbsd/display_server_x11.cpp112
-rw-r--r--platform/linuxbsd/display_server_x11.h7
-rw-r--r--platform/linuxbsd/gl_manager_x11.cpp44
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp8
4 files changed, 133 insertions, 38 deletions
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 318d014ee5..844b5616c4 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -64,7 +64,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 +323,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,7 +359,8 @@ 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);
}
}
@@ -1053,6 +1054,66 @@ 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) {
+ return (float)m_info.dotClock / ((float)m_info.hTotal * (float)m_info.vTotal);
+ }
+ }
+ }
+
+ 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_
@@ -1155,6 +1216,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];
@@ -1315,8 +1394,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
}
@@ -1805,6 +1885,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;
@@ -1857,6 +1938,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;
@@ -2397,7 +2479,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');
}
@@ -3335,7 +3417,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) {
@@ -3535,9 +3617,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;
@@ -3612,9 +3694,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;
@@ -3632,7 +3713,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 8929f528d6..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);
@@ -301,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)
@@ -316,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.