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;