Fix for bug 640 - moving thin frames leaves mess

Pavel Roskin proski at gnu.org
Thu Sep 25 02:01:56 CDT 2003


Hello!

I've made a patch for http://bugs.winehq.org/show_bug.cgi?id=640

I'm sending it here because I don't 100% sure it's ready for wine-patches.
But the patch fixes an important problem and I don't want it to be
unnoticed.

On certain versions of XFree86 (4.2.1 + Raveon 7000/VE), focus rectangles
are painted in white.  Also, windows with thin frames (including all popup
windows) create mess when dragged, except in when managed mode.

It appears that GXxor value used in graphics/x11drv/graphics.c is
misinterpreted - instead of xoring the background with the pen color, the
pen color is painted as is.  Another xoring doesn't hide the rectangle,
thus creating mess of white dotted rectangles.

The radical fix would be to avoid GXxor completely, but I'm leaving it to
gurus and I'm not sure if it's needed.  Fortunately, there is a correct
and justifiable fix on the higher level.

The focus rectangle (e.g. the rectangle around active buttons) should be
painted using the system text color.  Xoring this color with background is
wrong.  Even on systems where it works, it changes the color from black to
dark gray (light gray xor white), although not too much to notice it.
DrawFocusRect() has been changed to use R2_COPYPEN mode.

On the other hand, draw_moving_frame() should use xor, so using
DrawFocusRect() is wrong there, once the later is fixed.  PatBlt() with
PATINVERT works just fine with buggy XFree86 and it's already used for
thick frames.  The patch uses a checkered brush to imitate the dotted
line.

The result is very close to what I see on Windows 2000 - dotted line of
one pixel wide using inverted color.  In fact, the frame seems to be
redrawn faster and smoother than without the patch on the system without
the bug.

-- 
Regards,
Pavel Roskin
-------------- next part --------------
--- dlls/x11drv/winpos.c
+++ dlls/x11drv/winpos.c
@@ -1737,23 +1737,40 @@ int X11DRV_SetWindowRgn( HWND hwnd, HRGN
  */
 static void draw_moving_frame( HDC hdc, RECT *rect, BOOL thickframe )
 {
+    int width, height;
+    HBRUSH hOldBrush, hNewBrush;
+    HBITMAP hbm;
+    const WORD wPattern_AA55[8] = { 0xaaaa, 0x5555, 0xaaaa, 0x5555,
+                                    0xaaaa, 0x5555, 0xaaaa, 0x5555 };
+
     if (thickframe)
     {
-        const int width = GetSystemMetrics(SM_CXFRAME);
-        const int height = GetSystemMetrics(SM_CYFRAME);
-
-        HBRUSH hbrush = SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
-        PatBlt( hdc, rect->left, rect->top,
-                rect->right - rect->left - width, height, PATINVERT );
-        PatBlt( hdc, rect->left, rect->top + height, width,
-                rect->bottom - rect->top - height, PATINVERT );
-        PatBlt( hdc, rect->left + width, rect->bottom - 1,
-                rect->right - rect->left - width, -height, PATINVERT );
-        PatBlt( hdc, rect->right - 1, rect->top, -width,
-                rect->bottom - rect->top - height, PATINVERT );
-        SelectObject( hdc, hbrush );
+        width = GetSystemMetrics(SM_CXFRAME);
+        height = GetSystemMetrics(SM_CYFRAME);
+        hNewBrush = GetStockObject(GRAY_BRUSH);
     }
-    else DrawFocusRect( hdc, rect );
+    else
+    {
+        width = 1;
+        height = 1;
+        hNewBrush = GetStockObject(DKGRAY_BRUSH);
+        hbm = CreateBitmap(8, 8, 1, 1, wPattern_AA55);
+        hNewBrush = CreatePatternBrush(hbm);
+        DeleteObject(hbm);
+    }
+
+    hOldBrush = SelectObject( hdc, hNewBrush );
+    PatBlt( hdc, rect->left, rect->top,
+            rect->right - rect->left - width, height, PATINVERT );
+    PatBlt( hdc, rect->left, rect->top + height, width,
+            rect->bottom - rect->top - height, PATINVERT );
+    PatBlt( hdc, rect->left + width, rect->bottom - 1,
+            rect->right - rect->left - width, -height, PATINVERT );
+    PatBlt( hdc, rect->right - 1, rect->top, -width,
+            rect->bottom - rect->top - height, PATINVERT );
+    SelectObject( hdc, hOldBrush );
+
+    if (!thickframe) DeleteObject( hNewBrush );
 }
 
 
--- windows/painting.c
+++ windows/painting.c
@@ -1160,7 +1160,7 @@ BOOL WINAPI DrawFocusRect( HDC hdc, cons
     hOldBrush = SelectObject(hdc, GetStockObject(NULL_BRUSH));
     hNewPen = CreatePen(PS_ALTERNATE, 1, GetSysColor(COLOR_WINDOWTEXT));
     hOldPen = SelectObject(hdc, hNewPen);
-    oldDrawMode = SetROP2(hdc, R2_XORPEN);
+    oldDrawMode = SetROP2(hdc, R2_COPYPEN);
     oldBkMode = SetBkMode(hdc, TRANSPARENT);
 
     Rectangle(hdc, rc->left, rc->top, rc->right, rc->bottom);


More information about the wine-devel mailing list