Fullscreening patch

Mike Hearn mike at navi.cx
Fri Jul 9 08:15:52 CDT 2004


Hi Alexandre,

Yes, it's that time again. Can you take another look at this patch?
Getting it in is the first step towards fixing a bunch of "i typed but it
appeared on the console instead of the game!" bugs (as well as improving a
bunch of apps like IE, TightVNC etc).

thanks -mike

Index: dlls/x11drv/window.c
===================================================================
RCS file: /cvstrees/crossover/office/wine/dlls/x11drv/window.c,v
retrieving revision 1.49.2.1.2.2
diff -u -w -B -r1.49.2.1.2.2 window.c
--- dlls/x11drv/window.c        28 Apr 2004 00:08:44 -0000      1.49.2.1.2.2
+++ dlls/x11drv/window.c        12 May 2004 13:57:38 -0000
@@ -78,6 +78,7 @@
     "_MOTIF_WM_HINTS",
     "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
     "_NET_WM_STATE",
+    "_NET_WM_STATE_FULLSCREEN",
     "_NET_WM_STATE_MAXIMIZED_VERT",
     "_NET_WM_STATE_MAXIMIZED_HORZ",
     "_NET_WM_STATE_SKIP_TASKBAR",
@@ -133,6 +134,7 @@
 inline static BOOL is_window_managed( WND *win )
 {
     if (!managed_mode) return FALSE;
+
     /* tray window is always managed */
     if (win->dwExStyle & WS_EX_TRAYWINDOW) return TRUE;
     /* tool windows *are* managed if we have mwm hints */
@@ -156,6 +158,8 @@
     if (win->dwExStyle & WS_EX_TOOLWINDOW) return FALSE;
     /* windows with thick frame are managed */
     if (win->dwStyle & WS_THICKFRAME) return TRUE;
+    /* windows with a system menu are managed */
+    if (win->dwStyle & WS_SYSMENU) return TRUE;
  
     /*
      * CODEWEAVERS HACK
@@ -189,13 +193,7 @@
  
     /* application windows are managed */
     if (win->dwExStyle & WS_EX_APPWINDOW) return TRUE;
-    /* full-screen popup windows are managed */
-    if ((win->dwStyle & WS_POPUP) &&
-        (win->rectWindow.right-win->rectWindow.left) == screen_width &&
-        (win->rectWindow.bottom-win->rectWindow.top) == screen_height)
-    {
-        return TRUE;
-    }
+
     /* default: not managed */
     return FALSE;
 }
@@ -435,7 +432,10 @@
         size_hints->y = data->whole_rect.top;
         size_hints->flags = PWinGravity | PPosition;
  
-        if ( !(win->dwStyle & WS_THICKFRAME) )
+        /* we only want to be able to resize windows with WS_THICKFRAME.
+         * in addition, metacity refuses to fullscreen non-resizable windows
+         */
+        if ( !(win->dwStyle & WS_THICKFRAME) && !data->fullscreened)
         {
             size_hints->max_width = data->whole_rect.right - data->whole_rect.left;
             size_hints->max_height = data->whole_rect.bottom - data->whole_rect.top;
@@ -590,7 +590,7 @@
         if (win->dwStyle & WS_MINIMIZEBOX)   mwm_hints.functions |= MWM_FUNC_MINIMIZE;
         if (win->dwStyle & WS_MAXIMIZEBOX)   mwm_hints.functions |= MWM_FUNC_MAXIMIZE;
         if (win->dwStyle & WS_SYSMENU)    mwm_hints.functions |= MWM_FUNC_CLOSE;
-        if ((win->dwStyle & WS_CAPTION) == WS_CAPTION) mwm_hints.decorations |= MWM_DECOR_TITLE;
+        if (((win->dwStyle & WS_CAPTION) == WS_CAPTION) && (!data->fullscreened)) mwm_hints.decorations |= MWM_DECOR_TITLE;
         if (win->dwExStyle & WS_EX_DLGMODALFRAME) mwm_hints.decorations |= MWM_DECOR_BORDER;
         else if (win->dwStyle & WS_THICKFRAME) mwm_hints.decorations |= MWM_DECOR_BORDER | MWM_DECOR_RESIZEH;
         else if ((win->dwStyle & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME) mwm_hints.decorations |= MWM_DECOR_BORDER;
@@ -607,6 +607,15 @@
     XChangeProperty( display, data->whole_window, x11drv_atom(XdndAware),
                      XA_ATOM, 32, PropModeReplace, (unsigned char*)&dndVersion, 1 );
  
+    /* for windows that are already mapped, toggle_fullscreen sends a message to the WM */
+    if (data->fullscreened && !(win->dwStyle & WS_VISIBLE)) {
+        Atom newstate = x11drv_atom(_NET_WM_STATE_FULLSCREEN);
+
+        TRACE("setting state to _NET_WM_STATE_FULLSCREEN\n");
+        XChangeProperty( display, data->whole_window, x11drv_atom(_NET_WM_STATE),
+                         XA_ATOM, 32, PropModeReplace, (unsigned char*)&newstate, 1 );
+    }
+
     wm_hints = XAllocWMHints();
     wine_tsx11_unlock();
  
@@ -963,6 +972,8 @@
     RECT rect;
     BOOL is_top_level = is_window_top_level( win );
  
+    data->fullscreened = FALSE;
+
     rect = win->rectWindow;
     X11DRV_window_to_X_rect( win, &rect );
  
Index: dlls/x11drv/winpos.c
===================================================================
RCS file: /cvstrees/crossover/office/wine/dlls/x11drv/winpos.c,v
retrieving revision 1.44.2.3.2.1
diff -u -w -B -r1.44.2.3.2.1 winpos.c
--- dlls/x11drv/winpos.c        27 Apr 2004 22:38:15 -0000      1.44.2.3.2.1
+++ dlls/x11drv/winpos.c        12 May 2004 13:57:50 -0000
@@ -76,6 +76,45 @@
 extern XContext winContext;
  
 /***********************************************************************
+ *             toggle_fullscreen
+ *
+ * Use the NETWM fullscreening protocol to toggle fullscreened state. This only
+ * works for mapped windows.
+ */
+static void toggle_fullscreen( HWND hwnd )
+{
+    WND *win = WIN_GetPtr(hwnd);
+    struct x11drv_win_data *data = win->pDriverData;
+    XEvent xev;
+
+    TRACE("hwnd=%p, current=%s\n", hwnd, data->fullscreened ? "true" : "false");
+    data->fullscreened = !data->fullscreened;
+
+    wine_tsx11_lock();
+
+    X11DRV_set_wm_hints(thread_display(), win);
+    if (win->dwStyle & WS_VISIBLE) {
+        TRACE("toggling fullscreen state\n");
+        xev.xclient.type = ClientMessage;
+        xev.xclient.window = data->whole_window;
+        xev.xclient.message_type = x11drv_atom(_NET_WM_STATE);
+        xev.xclient.serial = 0;
+        xev.xclient.display = thread_display();
+        xev.xclient.send_event = True;
+        xev.xclient.format = 32;
+        /* using _NET_WM_STATE_TOGGLE here does not work correctly with some WMs */
+        xev.xclient.data.l[0] = (data->fullscreened ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE);
+        xev.xclient.data.l[1] = x11drv_atom(_NET_WM_STATE_FULLSCREEN);
+        xev.xclient.data.l[2] = 0;
+        XSendEvent(thread_display(), root_window, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+        TRACE("toggled\n");
+    }
+
+    wine_tsx11_unlock();
+    WIN_ReleasePtr(win);
+}
+
+/***********************************************************************
  *             clip_children
  *
  * Clip all children of a given window out of the visible region
@@ -936,25 +976,44 @@
     RECT newWindowRect, newClientRect;
     RECT oldWindowRect, oldClientRect;
     UINT wvrFlags = 0;
-    BOOL bChangePos;
+    BOOL bChangePos, fromXEvent;
+    struct x11drv_win_data *data;
  
-    TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
+    TRACE("hwnd %p, insert-after %p, swp %d,%d %dx%d\n",
            winpos->hwnd, winpos->hwndInsertAfter, winpos->x, winpos->y,
-           winpos->cx, winpos->cy, winpos->flags);
+           winpos->cx, winpos->cy);
  
+    fromXEvent = winpos->flags & SWP_WINE_NOHOSTMOVE;
     bChangePos = !(winpos->flags & SWP_WINE_NOHOSTMOVE);
     winpos->flags &= ~SWP_WINE_NOHOSTMOVE;
  
     /* Check window handle */
     if (winpos->hwnd == GetDesktopWindow()) return FALSE;
  
+    if (!(wndPtr = WIN_FindWndPtr( winpos->hwnd ))) return FALSE;
+    data = wndPtr->pDriverData;
+
     if (!SWP_DoWinPosChanging( winpos, &newWindowRect, &newClientRect )) return FALSE;
  
+    if (data->fullscreened) {
+
+        /* Windows has no concept of fullscreen, so to unfullscreen an app you just resize it or move it.
+         * Therefore we need to watch for this behaviour and release fullscreen mode so we can once again
+         * control our position.
+         */
+
+        if (!fromXEvent /* ignore spurious WM changes once we are fullscreened */
+            && !(winpos->flags & (SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE)) /* ignore SWP calls that aren't changing our geometry */
+            && !((newWindowRect.left < 0) && (newWindowRect.top < 0))) /* probably moving us beyond the screen boundaries to hide the borders, ignore */ {
+
+            TRACE("releasing fullscreen for %p\n", winpos->hwnd);
+            toggle_fullscreen( winpos->hwnd );
+        }
+    }
+
     /* Fix redundant flags */
     if (!fixup_flags( winpos )) return FALSE;
  
-    if (!(wndPtr = WIN_FindWndPtr( winpos->hwnd ))) return FALSE;
-
     TRACE("  current (%ld,%ld)-(%ld,%ld), client (%ld,%ld)-(%ld,%ld), style %08x\n",
           wndPtr->rectWindow.left, wndPtr->rectWindow.top,
           wndPtr->rectWindow.right, wndPtr->rectWindow.bottom,
@@ -973,8 +1032,9 @@
     }
  
     /* Common operations */
+    wvrFlags = SWP_DoNCCalcSize( winpos, &newWindowRect, &newClientRect ); /* FIXME: this should only be called if the size is actually being changed, unless SWP_FRAMECHANGED is set */
  
-    wvrFlags = SWP_DoNCCalcSize( winpos, &newWindowRect, &newClientRect );
+    TRACE("after NC_CALCSIZE (%ld,%ld,%ld,%ld)\n", newWindowRect.left, newWindowRect.top, newWindowRect.right, newWindowRect.bottom);
  
     if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
     {
@@ -1049,6 +1109,7 @@
             XClearArea( display, get_whole_window(wndPtr), 0, 0, 0, 0, True );
             winpos->flags |= SWP_FRAMECHANGED;
         }
+
         if (winpos->flags & SWP_SHOWWINDOW)
         {
             set_visible_style( winpos->hwnd, TRUE );
@@ -1124,6 +1185,7 @@
         SendMessageA( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)winpos );
         /* WM_WINDOWPOSCHANGED is send even if SWP_NOSENDCHANGING is set */
  
+    TRACE("done for %p\n", winpos->hwnd);
     return TRUE;
 }
  
@@ -1206,6 +1265,7 @@
     POINT size;
     LONG old_style;
     WINDOWPLACEMENT wpl;
+    struct x11drv_win_data* data;
  
     TRACE("%p %u\n", hwnd, cmd );
  
@@ -1224,9 +1284,12 @@
  
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
  
+    data = wndPtr->pDriverData;
+
     size.x = wndPtr->rectWindow.left;
     size.y = wndPtr->rectWindow.top;
  
+
     switch( cmd )
     {
     case SW_MINIMIZE:
@@ -1400,11 +1463,13 @@
 BOOL X11DRV_ShowWindow( HWND hwnd, INT cmd )
 {
     WND*       wndPtr = WIN_FindWndPtr( hwnd );
+    struct x11drv_win_data *data;
     BOOL       wasVisible, showFlag, wmMaximize, wmMinimize;
     RECT       newPos = {0, 0, 0, 0};
     UINT       swp = 0;
  
     if (!wndPtr) return FALSE;
+    data = wndPtr->pDriverData;
     hwnd = wndPtr->hwndSelf;  /* make it a full handle */
  
     TRACE("hwnd=%p, cmd=%d\n", hwnd, cmd);
@@ -1539,11 +1604,18 @@
                   MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
     }
  
+    if (!data->fullscreened && wmMaximize) {
+        /* we should fullscreen captionless windows on maximization (IE uses this) */
+        if ((wndPtr->dwStyle & WS_CAPTION) != WS_CAPTION) {
+            if ((wmMaximize && data->fullscreened) || (cmd == SW_RESTORE && !data->fullscreened)) {
+                TRACE("toggling fullscreen due to %s of captionless window %p\n", wmMaximize ? "maximization" : "restoration", hwnd);
+                toggle_fullscreen( hwnd );
+            }
+        } else
     /* ask the window manager to maximize this window for us */
-    if( wmMaximize )
         X11DRV_WMMaximizeWindow(wndPtr, TRUE);
-    else if ( wmMinimize )
-        X11DRV_WMMinimizeWindow(wndPtr);
+    } else if (wmMinimize) X11DRV_WMMinimizeWindow(wndPtr);
+
  
 END:
     WIN_ReleaseWndPtr(wndPtr);
@@ -2191,8 +2263,10 @@
     /* if nothing changed, don't do anything */
     if (winpos.flags == (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE)) return;
  
+    TRACE("syncing window pos enter\n");
     SetWindowPos( hwnd, winpos.hwndInsertAfter, winpos.x, winpos.y,
                   winpos.cx, winpos.cy, winpos.flags | SWP_WINE_NOHOSTMOVE );
+    TRACE("syncing window pos leave\n");
 }
  
  
Index: dlls/x11drv/x11drv.h
===================================================================
RCS file: /cvstrees/crossover/office/wine/dlls/x11drv/x11drv.h,v
retrieving revision 1.16.4.1
diff -u -w -B -r1.16.4.1 x11drv.h
--- dlls/x11drv/x11drv.h        27 Apr 2004 22:38:15 -0000      1.16.4.1
+++ dlls/x11drv/x11drv.h        12 May 2004 13:57:54 -0000
@@ -420,6 +420,7 @@
     XATOM__MOTIF_WM_HINTS,
     XATOM__KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR,
     XATOM__NET_WM_STATE,
+    XATOM__NET_WM_STATE_FULLSCREEN,
     XATOM__NET_WM_STATE_MAXIMIZED_VERT,
     XATOM__NET_WM_STATE_MAXIMIZED_HORZ,
     XATOM__NET_WM_STATE_SKIP_TASKBAR,
@@ -555,6 +556,7 @@
     XIC     xic;            /* X input context */
     HBITMAP hWMIconBitmap;
     HBITMAP hWMIconMask;
+    BOOL    fullscreened;   /* does the window have a NETWM fullscreening hint set? */
 };
  
 typedef struct x11drv_win_data X11DRV_WND_DATA;





More information about the wine-devel mailing list