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;