Skip to content

Commit d6c3ef3

Browse files
committed
Merge pull request #5277 from FernetMenta/X11
X11: fix window placement on multi-monitor setups
2 parents b07a633 + 4671c65 commit d6c3ef3

File tree

3 files changed

+53
-26
lines changed

3 files changed

+53
-26
lines changed

xbmc/windowing/X11/WinSystemX11.cpp

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@ bool CWinSystemX11::DestroyWindow()
151151
CWinEventsX11Imp::Quit();
152152

153153
XUnmapWindow(m_dpy, m_mainWindow);
154-
XSync(m_dpy,TRUE);
155154
XDestroyWindow(m_dpy, m_glWindow);
156155
XDestroyWindow(m_dpy, m_mainWindow);
157156
m_glWindow = 0;
@@ -208,7 +207,6 @@ bool CWinSystemX11::ResizeWindow(int newWidth, int newHeight, int newLeft, int n
208207

209208
bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays)
210209
{
211-
212210
#if defined(HAS_XRANDR)
213211
XOutput out;
214212
XMode mode;
@@ -248,6 +246,28 @@ bool CWinSystemX11::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool bl
248246
currmode.hz != mode.hz || currmode.id != mode.id)
249247
{
250248
CLog::Log(LOGNOTICE, "CWinSystemX11::SetFullScreen - calling xrandr");
249+
250+
// remember last position of mouse
251+
Window root_return, child_return;
252+
int root_x_return, root_y_return;
253+
int win_x_return, win_y_return;
254+
unsigned int mask_return;
255+
bool isInWin = XQueryPointer(m_dpy, m_mainWindow, &root_return, &child_return,
256+
&root_x_return, &root_y_return,
257+
&win_x_return, &win_y_return,
258+
&mask_return);
259+
260+
if (isInWin)
261+
{
262+
m_MouseX = win_x_return;
263+
m_MouseY = win_y_return;
264+
}
265+
else
266+
{
267+
m_MouseX = -1;
268+
m_MouseY = -1;
269+
}
270+
251271
OnLostDevice();
252272
m_bIsInternalXrr = true;
253273
g_xrandr.SetMode(out, mode);
@@ -659,13 +679,13 @@ bool CWinSystemX11::Restore()
659679
bool CWinSystemX11::Hide()
660680
{
661681
XUnmapWindow(m_dpy, m_mainWindow);
662-
XSync(m_dpy, False);
682+
XFlush(m_dpy);
663683
return true;
664684
}
665685
bool CWinSystemX11::Show(bool raise)
666686
{
667687
XMapWindow(m_dpy, m_mainWindow);
668-
XSync(m_dpy, False);
688+
XFlush(m_dpy);
669689
m_minimized = false;
670690
return true;
671691
}
@@ -688,7 +708,6 @@ void CWinSystemX11::NotifyXRREvent()
688708
{
689709
UpdateResolutions();
690710
}
691-
m_bIsInternalXrr = false;
692711

693712
XOutput *out = g_xrandr.GetOutput(m_userOutput);
694713
XMode mode = g_xrandr.GetCurrentMode(m_userOutput);
@@ -773,16 +792,24 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std:
773792
{
774793
bool changeWindow = false;
775794
bool changeSize = false;
776-
bool mouseActive = false;
777-
float mouseX = 0;
778-
float mouseY = 0;
779-
int x0 = 0;
780-
int y0 = 0;
795+
float mouseX = 0.5;
796+
float mouseY = 0.5;
797+
798+
if (!m_mainWindow)
799+
{
800+
g_Mouse.SetActive(false);
801+
}
781802

782803
if (m_mainWindow && ((m_bFullScreen != fullscreen) || m_currentOutput.compare(output) != 0 || m_windowDirty))
783804
{
784-
mouseActive = g_Mouse.IsActive();
785-
if (mouseActive)
805+
// set mouse to last known position
806+
// we can't trust values after an xrr event
807+
if (m_bIsInternalXrr && m_MouseX >= 0 && m_MouseY >= 0)
808+
{
809+
mouseX = (float)m_MouseX/m_nWidth;
810+
mouseY = (float)m_MouseY/m_nHeight;
811+
}
812+
else if (!m_windowDirty)
786813
{
787814
Window root_return, child_return;
788815
int root_x_return, root_y_return;
@@ -792,15 +819,15 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std:
792819
&root_x_return, &root_y_return,
793820
&win_x_return, &win_y_return,
794821
&mask_return);
822+
795823
if (isInWin)
796824
{
797825
mouseX = (float)win_x_return/m_nWidth;
798826
mouseY = (float)win_y_return/m_nHeight;
799-
g_Mouse.SetActive(false);
800827
}
801-
else
802-
mouseActive = false;
803828
}
829+
830+
g_Mouse.SetActive(false);
804831
OnLostDevice();
805832
DestroyWindow();
806833
m_windowDirty = true;
@@ -825,6 +852,8 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std:
825852
Colormap cmap;
826853
XSetWindowAttributes swa;
827854
XVisualInfo *vi;
855+
int x0 = 0;
856+
int y0 = 0;
828857

829858
XOutput *out = g_xrandr.GetOutput(output);
830859
if (!out)
@@ -931,7 +960,6 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std:
931960
class_hints->res_class = (char*)classString.c_str();
932961
class_hints->res_name = (char*)classString.c_str();
933962

934-
XSync(m_dpy,False);
935963
XSetWMProperties(m_dpy, m_mainWindow, &windowName, &iconName,
936964
NULL, 0, NULL, wm_hints,
937965
class_hints);
@@ -942,18 +970,15 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std:
942970
Atom wmDeleteMessage = XInternAtom(m_dpy, "WM_DELETE_WINDOW", False);
943971
XSetWMProtocols(m_dpy, m_mainWindow, &wmDeleteMessage, 1);
944972
}
945-
XMapRaised(m_dpy, m_glWindow);
946-
XMapRaised(m_dpy, m_mainWindow);
947973

948-
if (fullscreen)
949-
XMoveWindow(m_dpy, m_mainWindow, x0, y0);
974+
// placement of window may follow mouse
975+
XWarpPointer(m_dpy, None, m_mainWindow, 0, 0, 0, 0, mouseX*width, mouseY*height);
950976

951-
XSync(m_dpy,TRUE);
977+
XMapRaised(m_dpy, m_glWindow);
978+
XMapRaised(m_dpy, m_mainWindow);
952979

953-
if (changeWindow && mouseActive)
954-
{
955-
XWarpPointer(m_dpy, None, m_mainWindow, 0, 0, 0, 0, mouseX*width, mouseY*height);
956-
}
980+
// discard events generated by creating the window, i.e. xrr events
981+
XSync(m_dpy, TRUE);
957982

958983
CDirtyRegionList dr;
959984
RefreshGlxContext(m_currentOutput.compare(output) != 0);
@@ -962,6 +987,7 @@ bool CWinSystemX11::SetWindow(int width, int height, bool fullscreen, const std:
962987
g_graphicsContext.Flip(dr);
963988
g_Windowing.ResetVSync();
964989
m_windowDirty = false;
990+
m_bIsInternalXrr = false;
965991

966992
CSingleLock lock(m_resourceSection);
967993
// tell any shared resources

xbmc/windowing/X11/WinSystemX11.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class CWinSystemX11 : public CWinSystemBase, public ISettingCallback
9494
bool m_windowDirty;
9595
bool m_bIsInternalXrr;
9696
bool m_newGlContext;
97+
int m_MouseX, m_MouseY;
9798

9899
private:
99100
bool IsSuitableVisual(XVisualInfo *vInfo);

xbmc/windowing/X11/XRandR.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ bool CXRandR::Query(bool force, int screennum, bool ignoreoff)
7474
CStdString cmd;
7575
cmd = getenv("XBMC_BIN_HOME");
7676
cmd += "/xbmc-xrandr";
77-
cmd = StringUtils::Format("%s -q --screen %d", cmd.c_str(), screennum);
77+
cmd = StringUtils::Format("%s -q --screen %d --current", cmd.c_str(), screennum);
7878

7979
FILE* file = popen(cmd.c_str(),"r");
8080
if (!file)

0 commit comments

Comments
 (0)