From 73b45e71c7e870dddc6955797b989ac965b6ced4 Mon Sep 17 00:00:00 2001 From: Deve Date: Wed, 30 Jul 2014 21:12:12 +0200 Subject: [PATCH 1/2] xrandr: fixed issue with fullscreen window which was placed in wrong screen in some window managers. In some cases main screen may have other position than (0, 0) - fixed it. --- .../source/Irrlicht/CIrrDeviceLinux.cpp | 48 +++++++++++++++---- .../source/Irrlicht/CIrrDeviceLinux.h | 2 + 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp index 44c1bb895..16275eb6f 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.cpp @@ -826,6 +826,17 @@ bool CIrrDeviceLinux::createWindow() { if (netWM) { + // Some window managers don't respect values from XCreateWindow and + // place window in random position. This may cause that fullscreen + // window is showed in wrong screen. It doesn't matter for vidmode + // which displays cloned image in all devices. + #ifdef _IRR_LINUX_X11_RANDR_ + XResizeWindow(display, window, Width, Height); + XMoveWindow(display, window, crtc_x, crtc_y); + XRaiseWindow(display, window); + XFlush(display); + #endif + // Workaround for Gnome which sometimes creates window smaller than display XSizeHints *hints = XAllocSizeHints(); hints->flags=PMinSize; @@ -839,7 +850,8 @@ bool CIrrDeviceLinux::createWindow() Atom WMStateAtom = XInternAtom(display, "_NET_WM_STATE", true); Atom WMFullscreenAtom = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", true); // Set the fullscreen property - XChangeProperty(display, window, WMStateAtom, XA_ATOM, 32, PropModeReplace, reinterpret_cast(& WMFullscreenAtom), 1); + XChangeProperty(display, window, WMStateAtom, XA_ATOM, 32, PropModeReplace, + reinterpret_cast(&WMFullscreenAtom), 1); // Notify the root window XEvent xev = {0}; // The event should be filled with zeros before setting its attributes @@ -850,7 +862,10 @@ bool CIrrDeviceLinux::createWindow() xev.xclient.format = 32; xev.xclient.data.l[0] = 1; xev.xclient.data.l[1] = WMFullscreenAtom; - XSendEvent(display, DefaultRootWindow(display), false, SubstructureRedirectMask | SubstructureNotifyMask, &xev); + XSendEvent(display, RootWindow(display, visual->screen), false, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); + + XFlush(display); } else { @@ -1557,10 +1572,11 @@ video::IVideoModeList* CIrrDeviceLinux::getVideoModeList() XRRScreenResources* res = XRRGetScreenResources(display, DefaultRootWindow(display)); if (!res) - return NULL; + return &VideoModeList; XRROutputInfo *output = NULL; XRRCrtcInfo* crtc = NULL; + crtc_x = crtc_y = -1; for (int i = 0; i < res->noutput; i++) { @@ -1574,23 +1590,39 @@ video::IVideoModeList* CIrrDeviceLinux::getVideoModeList() crtc = XRRGetCrtcInfo(display, res, output->crtc); - if (!crtc || crtc->x != 0 || crtc->y != 0) + if (!crtc) { XRRFreeCrtcInfo(crtc); XRRFreeOutputInfo(output); continue; } - - output_id = res->outputs[i]; - break; + + if (crtc_x == -1 || crtc->x < crtc_x) + { + crtc_x = crtc->x; + crtc_y = crtc->y; + output_id = res->outputs[i]; + } + else if (crtc_x == crtc->x && crtc->y < crtc_y) + { + crtc_x = crtc->x; + crtc_y = crtc->y; + output_id = res->outputs[i]; + } + + XRRFreeCrtcInfo(crtc); + XRRFreeOutputInfo(output); } + + output = XRRGetOutputInfo(display, res, output_id); + crtc = XRRGetCrtcInfo(display, res, output->crtc); if (crtc == NULL) { XRRFreeCrtcInfo(crtc); XRRFreeOutputInfo(output); XRRFreeScreenResources(res); - return NULL; + return &VideoModeList; } for (int i = 0; i < res->nmode; i++) diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.h b/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.h index 1ed59e72e..e071724de 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.h +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceLinux.h @@ -396,6 +396,8 @@ namespace irr #ifdef _IRR_LINUX_X11_RANDR_ RROutput output_id; RRMode old_mode; + int crtc_x; + int crtc_y; #endif #ifdef _IRR_COMPILE_WITH_OPENGL_ GLXWindow glxWin; From b11fd2aaf69867734268ed1ebbc58625baea00f1 Mon Sep 17 00:00:00 2001 From: Deve Date: Wed, 30 Jul 2014 21:29:15 +0200 Subject: [PATCH 2/2] xrandr: now it seems to work fine. I enable it for testing. This should be useful for people which have two or more display devices. It changes resolution only on main screen and leaves other screens untouched. Currently I use screen which is the most on left (or on top). Ideally we should be able to choose in settings which screen we want to use. But support it on all platforms is rather too much of work. We could also detect from which screen STK was executed. This can be done differently on different window managers, but nothing impossible. Maybe in future. Perhaps we should add fallback using old xrandr method. BTW. in some specific cases it works better than SDL2 ;-) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 23d20b86a..82ea054d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ else() endif() if(UNIX AND NOT APPLE) - option(USE_XRANDR "Use xrandr instead of vidmode" OFF) + option(USE_XRANDR "Use xrandr instead of vidmode" ON) endif() set(STK_SOURCE_DIR "src")