From 9117a5bf0fac83a716305f3715e36a8dd64f5517 Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Fri, 2 Mar 2018 14:01:29 +0100 Subject: hw/nxagent/Screen.c: Cover Xinerama bounding box corner cases. If the agent window is moved around on screen, it can happen that it is moved into an invisible area of the real Xserver, we calls this "beyond the bounding box". . If the agent window is partially beyond the bounding box, we don't want Xinerama to re-adjust the RandR parameters inside the agent. Near the bounding box, the session shall stay intact. . This means, desktop env wise, the desktop session control elements can be moved (with the agent window) into the invisible areas of the real Xserver and moved out again without RandR events arriving inside the agent session. Fixes ArcticaProject/nx-libs#662. --- nx-X11/programs/Xserver/hw/nxagent/Screen.c | 97 ++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 16 deletions(-) (limited to 'nx-X11') diff --git a/nx-X11/programs/Xserver/hw/nxagent/Screen.c b/nx-X11/programs/Xserver/hw/nxagent/Screen.c index 628bf990a..cc44c1b7a 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Screen.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Screen.c @@ -3642,6 +3642,11 @@ Bool intersect(int ax1, int ay1, unsigned int aw, unsigned int ah, /* check if there's any intersection at all */ if (ax2 < bx1 || bx2 < ax1 || ay2 < by1 || by2 < ay1) { + + #ifdef DEBUG + fprintf(stderr, "intersect: the given rectangles do not intersect at all\n"); + #endif + return FALSE; } @@ -3657,12 +3662,22 @@ Bool intersect(int ax1, int ay1, unsigned int aw, unsigned int ah, /* check if the resulting rectangle is feasible */ if (iw <= 0 || ih <= 0) { + + #ifdef DEBUG + fprintf(stderr, "intersect: intersection rectangle not feasible\n"); + #endif + return FALSE; } *x = ix; *y = iy; *w = iw; *h = ih; + + #ifdef DEBUG + fprintf(stderr, "intersect: intersection is: ([%d],[%d]) [ %d x %d ]\n", *x, *y, *w, *h); + #endif + return TRUE; } @@ -3674,24 +3689,73 @@ Bool intersect_bb(int ax1, int ay1, unsigned int aw, unsigned int ah, int bbx1, int bby1, int bbx2, int bby2, int *x, int *y, unsigned int *w, unsigned int *h) { + + #ifdef DEBUG + fprintf(stderr, "intersect_bb: session window: ([%d],[%d]) [ %d x %d ]\n", ax1, ay1, aw, ah); + fprintf(stderr, "intersect_bb: crtc: ([%d],[%d]) [ %d x %d ]\n", bx1, by1, bw, bh); + fprintf(stderr, "intersect_bb: bounding box: ([%d],[%d]) [ %d x %d ]\n", bbx1, bby1, bbx2-bbx1, bby2-bby1); + #endif + Bool result = intersect(ax1, ay1, aw, ah, bx1, by1, bw, bh, x, y, w, h); + if (result == TRUE) { - /* check if outside of bounding box */ - if (ax1 < bbx1 || ax1 + aw > bbx2) { + + /* + * ###### The X-Coordinate ###### + */ + + /* check if outside-left of bounding box */ + if (bx1 == bbx1 && ax1 < bbx1) { + + *w += bbx1 - ax1; + *x = 0; + + #ifdef DEBUG + fprintf(stderr, "intersect_bb: session box is outside-left of the bounding box - width gets adapted to [%d]\n", *w); + #endif + + + } + + /* check if outside-right of bounding box */ + if (bx1 + bw == bbx2 && ax1 + aw > bbx2) { + + *w += ax1 + aw - bbx2; + #ifdef DEBUG - fprintf(stderr, "intersect: box has parts outside bounding box - width stays unchanged [%d]\n", aw); + fprintf(stderr, "intersect_bb: session box is outside-right of the bounding box - width gets adapted to [%d]\n", *w); #endif - *w = aw; + } - if (ay1 < bby1 || ay1 + ah > bby2) { + /* + * ###### The Y-Coordinate ###### + */ + + /* check if outside-above of bounding box */ + if (by1 == bby1 && ay1 < bby1) { + + *h += bby1 - ay1; + *y = 0; + #ifdef DEBUG - fprintf(stderr, "intersect: box has parts outside bounding box - height stays unchanged [%d]\n", ah); + fprintf(stderr, "intersect_bb: session box is outside-above of the bounding box - height gets adapted to [%d]\n", *h); #endif - *h = ah; + } - } + /* check if outside-below of bounding box */ + if (by1 + bh == bby2 && ay1 + ah > bby2) { + + *h += ay1 + ah - bby2; + + #ifdef DEBUG + fprintf(stderr, "intersect_bb: session box is outside-below of the bounding box - height gets adapted to [%d]\n", *h); + #endif + + } + + } return result; } #endif @@ -4057,8 +4121,10 @@ int nxagentAdjustRandRXinerama(ScreenPtr pScreen) for (i = 0; i < pScrPriv->numOutputs; i++) { Bool disable_output = FALSE; RRModePtr mymode, prevmode; - int new_x, new_y; - unsigned int new_w, new_h; + int new_x = 0; + int new_y = 0; + unsigned int new_w = 0; + unsigned int new_h = 0; /* if ((nxagentOption(X) < bbx1 || (nxagentOption(X) + width >= bbx2 )) { @@ -4186,15 +4252,14 @@ int nxagentAdjustRandRXinerama(ScreenPtr pScreen) fprintf(stderr, "nxagentAdjustRandRXinerama: setting mode [%s] ([%p]) refcnt [%d] for output %d [%s]\n", mymode->name, (void *) mymode, mymode->refcnt, i, pScrPriv->outputs[i]->name); #endif RROutputSetModes(pScrPriv->outputs[i], &mymode, 1, 0); - - #ifdef DEBUG - fprintf(stderr, "nxagentAdjustRandRXinerama: setting mode [%s] ([%p]) refcnt [%d] for crtc %d\n", mymode->name, (void *) mymode, mymode->refcnt, i); - #endif - RRCrtcSet(pScrPriv->crtcs[i], mymode, new_x, new_y, RR_Rotate_0, 1, &(pScrPriv->outputs[i])); - } } /* if disable_output */ + #ifdef DEBUG + fprintf(stderr, "nxagentAdjustRandRXinerama: setting mode [%s] ([%p]) refcnt [%d] for crtc %d\n", mymode->name, (void *) mymode, mymode->refcnt, i); + #endif + RRCrtcSet(pScrPriv->crtcs[i], mymode, new_x, new_y, RR_Rotate_0, 1, &(pScrPriv->outputs[i])); + /* throw away the mode if otherwise unused. We do not need it anymore. We call FreeResource() to ensure the system will not try to free it again on shutdown */ -- cgit v1.2.3