Implement LockWindowUpdate, disabled for now
Mike Hearn
mike at navi.cx
Mon Apr 19 14:18:52 CDT 2004
A user requested the latest version of this patch in #winehq, so here it is.
Mike Hearn <mike at navi.cx>
Implement LockWindowUpdate using a new server request.
It's disabled with an #if 0 as the lack of inter-process invalidation
would break certain programs. It works fine for programs like Half-Life
though, as they only lock their own windows.
Generated from:
* mike at navi.cx--2004/wine--mainline--0.9--patch-4
--- orig/dlls/x11drv/winpos.c
+++ mod/dlls/x11drv/winpos.c
@@ -425,13 +425,23 @@
WND *win = WIN_GetPtr( hwnd );
HWND top = 0;
X11DRV_WND_DATA *data = win->pDriverData;
+ BOOL visible, locked;
struct x11drv_escape_set_drawable escape;
- BOOL visible;
escape.mode = IncludeInferiors;
/* don't clip siblings if using parent clip region */
if (flags & DCX_PARENTCLIP) flags &= ~DCX_CLIPSIBLINGS;
+ /* check if window or a parent is locked, in which case we suppress the visible region */
+ locked = FALSE;
+ SERVER_START_REQ( check_window_lock )
+ {
+ req->handle = hwnd;
+ if (!wine_server_call( req )) locked = reply->suppress;
+ }
+ SERVER_END_REQ;
+ if (locked) TRACE("window %p is locked, suppressing visible region\n", hwnd);
+
/* find the top parent in the hierarchy that isn't clipping siblings */
visible = (win->dwStyle & WS_VISIBLE) != 0;
@@ -510,7 +520,7 @@
/* need to recompute the visible region */
HRGN visRgn;
- if (visible)
+ if (visible && !locked)
{
visRgn = get_visible_region( win, top, flags, escape.mode );
--- orig/server/protocol.def
+++ mod/server/protocol.def
@@ -1896,6 +1896,20 @@
int incr; /* increment (can be negative) */
@END
+/* Set the currently locked window */
+ at REQ(set_window_lock)
+ user_handle_t handle; /* handle to the window or 0 to clear */
+ at REPLY
+ user_handle_t old_handle; /* if there was already a lock in effect, this is the handle of that window otherwise it's 0 */
+ at END
+
+/* Check the window and its parents to determine if painting should be suppressed */
+ at REQ(check_window_lock)
+ user_handle_t handle; /* handle to the window */
+ at REPLY
+ int suppress; /* 1 = window or parent is locked so suppress, 0 = don't suppress */
+ at END
+
/* Get the coordinates offset between two windows */
@REQ(get_windows_offset)
--- orig/server/window.c
+++ mod/server/window.c
@@ -795,6 +795,34 @@
}
}
+static struct window *locked_window = NULL;
+
+/* sets the paint locked window */
+DECL_HANDLER(set_window_lock)
+{
+ reply->old_handle = locked_window;
+
+ if (req->handle)
+ locked_window = get_window( req->handle );
+ else
+ locked_window = NULL;
+
+ return;
+}
+
+/* check the window and its parents to see if any of them are locked */
+DECL_HANDLER(check_window_lock)
+{
+ struct window *win = get_window( req->handle );
+ if (!win) return;
+
+ reply->suppress = 1;
+ if (win == locked_window) return;
+ while ((win = win->parent)) if (win == locked_window) return; /* check parents */
+
+ reply->suppress = 0;
+ return;
+}
/* get the coordinates offset between two windows */
DECL_HANDLER(get_windows_offset)
--- orig/windows/dce.c
+++ mod/windows/dce.c
@@ -41,6 +41,7 @@
#include "wownt32.h"
#include "wine/winbase16.h"
#include "wine/winuser16.h"
+#include "wine/server.h"
WINE_DEFAULT_DEBUG_CHANNEL(dc);
@@ -667,40 +668,41 @@
/***********************************************************************
* LockWindowUpdate (USER32.@)
+ *
+ * Locking a window makes BeginPaint, GetDC and GetDCEX for that
+ * window or any of its child windows return a DC with an empty
+ * visible region, ie that clips all drawing. It can be used to
+ * temporarily suspend drawing to a window.
+ *
+ * Only one window in the system can be locked at once.
+ *
+ * Calling with a NULL hwnd releases the lock. When locked GetDCEx can
+ * be used to get a DC you can draw onto for that window (to draw
+ * overlays, for instance).
+ *
*/
BOOL WINAPI LockWindowUpdate( HWND hwnd )
{
- static HWND lockedWnd;
-
- /* This function is fully implemented by the following patch:
- *
- * http://www.winehq.org/hypermail/wine-patches/2004/01/0142.html
- *
- * but in order to work properly, it needs the ability to invalidate
- * DCEs in other processes when the lock window is changed, which
- * isn't possible yet.
- * -mike
- */
-
- FIXME("(%p), partial stub!\n",hwnd);
-
- USER_Lock();
- if (lockedWnd)
- {
- if (!hwnd)
- {
- /* Unlock lockedWnd */
- /* FIXME: Do something */
- }
- else
- {
- /* Attempted to lock a second window */
- /* Return FALSE and do nothing */
- USER_Unlock();
- return FALSE;
- }
+ FIXME("stub: blocked on interprocess invalidation\n");
+#if 0
+ if (hwnd) TRACE("locking %p\n", hwnd);
+
+ SERVER_START_REQ( set_window_lock )
+ {
+ req->handle = hwnd;
+ if (!wine_server_call_err( req )) {
+ if (reply->old_handle) {
+ TRACE("unlocked window %p\n", reply->old_handle);
+
+ /* Windows tracks the area drawn to while locked (the accumulated region) and then invalides it on unlock.
+ * For simplicities sake we just invalidate the whole thing. FIXME: Does Windows set bErase below to TRUE or FALSE?
+ */
+ InvalidateRgn( reply->old_handle, NULL, FALSE );
+ }
+ return TRUE;
+ }
}
- lockedWnd = hwnd;
- USER_Unlock();
- return TRUE;
+ SERVER_END_REQ;
+#endif
+ return FALSE;
}
More information about the wine-patches
mailing list