[USER] Fix ClipCursor.

Lionel Ulmer lionel.ulmer at free.fr
Fri Jan 30 12:03:52 CST 2004


As seen on Wine-devel, DungeonKeeper relies on the ClipCursor being updated
on resolution changes. At the same time, I checked what Windows does on
whacky rectangles :-)

     Lionel

Changelog:
 - initialize the cursor clip rectangle at USER loading
 - update it on resolution changes
 - do the same checks as real Windows do (tested on Win2K)
   
-- 
		 Lionel Ulmer - http://www.bbrox.org/
-------------- next part --------------
diff -ur ../wine_CVS/windows/cursoricon.c windows/cursoricon.c
--- ../wine_CVS/windows/cursoricon.c	2004-01-27 15:59:35.000000000 +0100
+++ windows/cursoricon.c	2004-01-30 17:07:50.000000000 +0100
@@ -1419,7 +1419,11 @@
 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
 {
     if (!rect) SetRectEmpty( &CURSOR_ClipRect );
-    else CONV_RECT16TO32( rect, &CURSOR_ClipRect );
+    else {
+	RECT rect_32;
+	CONV_RECT16TO32(rect, &rect_32);
+	return ClipCursor(&rect_32);
+    }
     return TRUE;
 }
 
@@ -1430,7 +1434,29 @@
 BOOL WINAPI ClipCursor( const RECT *rect )
 {
     if (!rect) SetRectEmpty( &CURSOR_ClipRect );
-    else CopyRect( &CURSOR_ClipRect, rect );
+    else {
+	/* Some sanity checks (verified on Win2K) */
+	RECT screen_rect;
+	
+	screen_rect.top = screen_rect.left = 0;
+	screen_rect.right = GetSystemMetrics(SM_CXSCREEN);
+	screen_rect.bottom = GetSystemMetrics(SM_CYSCREEN);
+
+	/* If the rectangle is bad or out of the screen rectangle, the clip cursor is set
+	 * to the whole screen.
+	 */
+	if ((rect->top > rect->bottom) || (rect->left > rect->right) ||
+	    (rect->top >= screen_rect.bottom) ||
+	    (rect->bottom < screen_rect.top) ||
+	    (rect->left >= screen_rect.right) ||
+	    (rect->right < screen_rect.left))
+	    rect = &screen_rect;
+	
+	/* If the rectangle is empty, keep the same rectangle */
+	if (IsRectEmpty(rect)) CopyRect(&CURSOR_ClipRect, rect);
+	/* Otherwise, it's the intersection of the given rectangle with the screen */
+	else IntersectRect(&CURSOR_ClipRect, rect, &screen_rect);
+    }
     return TRUE;
 }
 
diff -ur ../wine_CVS/dlls/x11drv/settings.c dlls/x11drv/settings.c
--- ../wine_CVS/dlls/x11drv/settings.c	2003-10-16 02:21:42.000000000 +0200
+++ dlls/x11drv/settings.c	2004-01-30 17:19:31.000000000 +0100
@@ -239,6 +239,7 @@
 {
     DWORD i;
     DEVMODEW dm;
+    int cur_mode;
 
     TRACE("(%s,%p,%p,0x%08lx,%p)\n",debugstr_w(devname),devmode,hwnd,flags,lpvoid);
     TRACE("flags=%s\n",_CDS_flags(flags));
@@ -260,6 +261,8 @@
         devmode = &dm;
     }
 
+    cur_mode = pGetCurrentMode();
+
     for (i = 0; i < dd_mode_count; i++)
     {
         if (devmode->dmFields & DM_BITSPERPEL)
@@ -285,6 +288,27 @@
         /* we have a valid mode */
         TRACE("Requested display settings match mode %ld (%s)\n", i, handler_name);
         pSetCurrentMode(i);
+
+	if (i != cur_mode) {
+	    /* This means that we choose another resolution .. Update the clip cursor accordingly.
+	     *
+	     * Note: at this point, as 'pSetCurrentMode' has been called, we suppose that the System
+	     *       metrics have been updated properly and that the sanity checks in ClipCursor
+	     *       won't give us any problems.
+	     */
+	    RECT rect;
+
+	    TRACE("New mode (%ld) different from current mode (%d) - updating clip cursor.\n", i, cur_mode);
+	    
+	    rect.top    = 0;
+	    rect.bottom = dd_modes[i].dwHeight;
+	    
+	    rect.left  = 0;
+	    rect.right = dd_modes[i].dwWidth;
+	
+	    ClipCursor(&rect);
+	}
+	
         return DISP_CHANGE_SUCCESSFUL;
     }
 
diff -ur ../wine_CVS/dlls/user/user_main.c dlls/user/user_main.c
--- ../wine_CVS/dlls/user/user_main.c	2004-01-27 15:59:23.000000000 +0100
+++ dlls/user/user_main.c	2004-01-29 19:43:01.000000000 +0100
@@ -186,6 +186,7 @@
 static BOOL process_attach( HINSTANCE inst )
 {
     HINSTANCE16 instance;
+    RECT rect;
 
     /* Create USER heap */
     if ((instance = LoadLibrary16( "USER.EXE" )) >= 32) USER_HeapSel = instance | 7;
@@ -203,6 +204,13 @@
     SYSMETRICS_Init();
     SYSCOLOR_Init();
 
+    /* Now that system metrics are set-up, we can initialize the clip rectangle */
+    rect.left   = 0;
+    rect.right  = GetSystemMetrics(SM_CXSCREEN);
+    rect.top    = 0;
+    rect.bottom = GetSystemMetrics(SM_CYSCREEN);
+    ClipCursor(&rect);
+
     /* Setup palette function pointers */
     palette_init();
 


More information about the wine-patches mailing list