diff --git a/nx-X11/programs/Xserver/hw/nxagent/Screen.c b/nx-X11/programs/Xserver/hw/nxagent/Screen.c index 6ec4b245fe..44c89e03f7 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Screen.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Screen.c @@ -297,6 +297,35 @@ void nxagentSetPixmapFormats(ScreenInfo *screenInfo) } } +/* check if possible_parent is parent of candidate */ +Bool nxagentIsParentOf(Display *d, XlibWindow possible_parent, XlibWindow candidate) +{ + XlibWindow parent, root, *children = NULL; + unsigned int num_children; + + if (XQueryTree(d, candidate, &root, &parent, &children, &num_children)) + { + if (children) + XFree((char *)children); + + #ifdef TEST + fprintf(stderr, "%s: parent of full screen window [%p] root [%p] possible_parent [%p] candidate [%p]\n", __func__, parent, root, possible_parent, candidate); + #endif + return (parent == possible_parent); + } + else + { + return False; + } +} + +/* + * Pressing the minimize keystroke while in fullscreen mode will call + * this function. It will unmap the fullscreen window and iconify the + * previously created icon window immediately. The window manager may + * decide how to show an iconified window. kwin e.g. shows it in the + * task bar. + */ void nxagentMinimizeFromFullScreen(ScreenPtr pScreen) { XUnmapWindow(nxagentDisplay, nxagentFullscreenWindow); @@ -304,16 +333,20 @@ void nxagentMinimizeFromFullScreen(ScreenPtr pScreen) if (nxagentIpaq) { XMapWindow(nxagentDisplay, nxagentIconWindow); - XIconifyWindow(nxagentDisplay, nxagentIconWindow, - DefaultScreen(nxagentDisplay)); } - else - { - XIconifyWindow(nxagentDisplay, nxagentIconWindow, + + XIconifyWindow(nxagentDisplay, nxagentIconWindow, DefaultScreen(nxagentDisplay)); - } } +/* + * This is the opposite function to nxagentMinimizeFromFullscreen. It + * will map the fullscreen window and unmap the icon window. It is + * only called if fullscreen mode was active when the minimize + * keystroke was pressed. + * Some window managers tend to do 'interesting' things with the + * icon window, which we try to counterfeit here. + */ void nxagentMaximizeToFullScreen(ScreenPtr pScreen) { if (nxagentIpaq) @@ -327,36 +360,51 @@ void nxagentMaximizeToFullScreen(ScreenPtr pScreen) /* XUnmapWindow(nxagentDisplay, nxagentIconWindow); */ + + Window root = RootWindow(nxagentDisplay, DefaultScreen(nxagentDisplay)); + /* -FIXME: We'll check for ReparentNotify and LeaveNotify events after XReparentWindow() - in order to avoid the session window is iconified. - We could avoid the session window is iconified when a LeaveNotify event is received, - so this check would be unnecessary. +FIXME: We'll check for ReparentNotify and LeaveNotify events after + XReparentWindow() in order to avoid the session window being + iconified. We could avoid the session window being iconified + when a LeaveNotify event is received, so this check would be + unnecessary. */ - struct timeval timeout; - int i; - XEvent e; - XReparentWindow(nxagentDisplay, nxagentFullscreenWindow, - RootWindow(nxagentDisplay, DefaultScreen(nxagentDisplay)), 0, 0); + /* only reparent if necessary. FIXME: also check if the desired coordinates match */ - for (i = 0; i < 100 && nxagentWMIsRunning; i++) + if (!nxagentIsParentOf(nxagentDisplay, root, nxagentFullscreenWindow)) { - #ifdef TEST - fprintf(stderr, "nxagentMaximizeToFullscreen: WARNING! Going to wait for the ReparentNotify event.\n"); - #endif + XReparentWindow(nxagentDisplay, nxagentFullscreenWindow, + root, 0, 0); - if (XCheckTypedWindowEvent(nxagentDisplay, nxagentFullscreenWindow, ReparentNotify, &e)) + for (int i = 0; i < 100 && nxagentWMIsRunning; i++) { - break; - } + struct timeval timeout; + XEvent e; - XSync(nxagentDisplay, 0); + #ifdef TEST + fprintf(stderr, "nxagentMaximizeToFullscreen: WARNING! Going to wait for the ReparentNotify event [%d].\n", i); + #endif - timeout.tv_sec = 0; - timeout.tv_usec = 50 * 1000; + if (XCheckTypedWindowEvent(nxagentDisplay, nxagentFullscreenWindow, ReparentNotify, &e)) + { + break; + } - nxagentWaitEvents(nxagentDisplay, &timeout); + XSync(nxagentDisplay, 0); + + timeout.tv_sec = 0; + timeout.tv_usec = 50 * 1000; + + nxagentWaitEvents(nxagentDisplay, &timeout); + } + } + else + { + #ifdef TEST + fprintf(stderr, "%s: FullscreenWindow already is child of root window - skipping reparenting,\n", __func__); + #endif } XMapRaised(nxagentDisplay, nxagentFullscreenWindow); @@ -364,7 +412,19 @@ FIXME: We'll check for ReparentNotify and LeaveNotify events after XReparentWind XIconifyWindow(nxagentDisplay, nxagentIconWindow, DefaultScreen(nxagentDisplay)); - while (XCheckTypedWindowEvent(nxagentDisplay, nxagentFullscreenWindow, LeaveNotify, &e)); + /* swallow all LeaveNotify events for the FullscreenWindow; + Normally this does not swallow anything these days, but when + using fvwm you see one of these events here. */ + while (1) + { + XEvent e; + if (!XCheckTypedWindowEvent(nxagentDisplay, nxagentFullscreenWindow, LeaveNotify, &e)) + break; + #ifdef TEST + fprintf(stderr, "%d: swallowing LeaveNotify event\m", __func__); + #endif + } + /* XMapWindow(nxagentDisplay, nxagentIconWindow); */ @@ -1982,7 +2042,7 @@ N/A } else { - nxagentIconWindow = 0; + nxagentIconWindow = None; } /* diff --git a/nx-X11/programs/Xserver/hw/nxagent/Window.c b/nx-X11/programs/Xserver/hw/nxagent/Window.c index 78a5081f02..0e5def294e 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/Window.c +++ b/nx-X11/programs/Xserver/hw/nxagent/Window.c @@ -831,6 +831,11 @@ void nxagentSwitchAllScreens(ScreenPtr pScreen, Bool switchOn) } w = nxagentDefaultWindows[pScreen -> myNum]; + + /* + * override_redirect makes the window manager ignore the window and + * not add decorations, see ICCCM) + */ attributes.override_redirect = switchOn; valuemask = CWOverrideRedirect; XUnmapWindow(nxagentDisplay, w); @@ -1003,14 +1008,28 @@ void nxagentSwitchAllScreens(ScreenPtr pScreen, Bool switchOn) } } - if (nxagentOption(WMBorderWidth) > 0 && nxagentOption(WMTitleHeight) > 0) + /* + * FIXME: These are 0 most of the time nowadays. The effect is, + * that the window is moving a bit to right/bottom every time + * fullscreen mode is left. To fix this query the frame extents + * from the window manager via _NET_REQUEST_FRAME_EXTENTS + */ + + if (nxagentOption(WMBorderWidth) > 0) { nxagentChangeOption(X, nxagentOption(SavedX) - nxagentOption(WMBorderWidth)); - nxagentChangeOption(Y, nxagentOption(SavedY) - nxagentOption(WMTitleHeight)); } else { nxagentChangeOption(X, nxagentOption(SavedX)); + } + + if (nxagentOption(WMTitleHeight) > 0) + { + nxagentChangeOption(Y, nxagentOption(SavedY) - nxagentOption(WMTitleHeight)); + } + else + { nxagentChangeOption(Y, nxagentOption(SavedY)); } @@ -2635,7 +2654,7 @@ void nxagentMapDefaultWindows(void) * Map the icon window. */ - if (nxagentIconWindow != 0) + if (nxagentIconWindow != None) { #ifdef TEST fprintf(stderr, "nxagentMapDefaultWindows: Mapping icon window id [%ld].\n",