Ken Thomases : winemac: Implement ScrollDC().
Alexandre Julliard
julliard at winehq.org
Tue Feb 5 13:25:25 CST 2013
Module: wine
Branch: master
Commit: 6efd198c521f341e3807c5620f5d3f30088e7386
URL: http://source.winehq.org/git/wine.git/?a=commit;h=6efd198c521f341e3807c5620f5d3f30088e7386
Author: Ken Thomases <ken at codeweavers.com>
Date: Sun Feb 3 17:20:03 2013 -0600
winemac: Implement ScrollDC().
---
dlls/winemac.drv/Makefile.in | 1 +
dlls/winemac.drv/scroll.c | 188 +++++++++++++++++++++++++++++++++++++
dlls/winemac.drv/winemac.drv.spec | 1 +
3 files changed, 190 insertions(+), 0 deletions(-)
diff --git a/dlls/winemac.drv/Makefile.in b/dlls/winemac.drv/Makefile.in
index 8484db8..c0bdbb7 100644
--- a/dlls/winemac.drv/Makefile.in
+++ b/dlls/winemac.drv/Makefile.in
@@ -8,6 +8,7 @@ C_SRCS = \
gdi.c \
macdrv_main.c \
mouse.c \
+ scroll.c \
surface.c \
window.c
diff --git a/dlls/winemac.drv/scroll.c b/dlls/winemac.drv/scroll.c
new file mode 100644
index 0000000..e8e7537
--- /dev/null
+++ b/dlls/winemac.drv/scroll.c
@@ -0,0 +1,188 @@
+/*
+ * MACDRV window/DC scrolling
+ *
+ * Copyright 1993 David W. Metcalfe
+ * Copyright 1995, 1996 Alex Korobka
+ * Copyright 2001 Alexandre Julliard
+ * Copyright 2011, 2013 Ken Thomases for CodeWeavers Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include "macdrv.h"
+#include "winuser.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(scroll);
+
+
+static void dump_region(const char *p, HRGN hrgn)
+{
+ DWORD i, size;
+ RGNDATA *data = NULL;
+ RECT *rect;
+
+ if (!hrgn)
+ {
+ TRACE("%s null region\n", p);
+ return;
+ }
+ if (!(size = GetRegionData(hrgn, 0, NULL)))
+ return;
+ if (!(data = HeapAlloc(GetProcessHeap(), 0, size))) return;
+ GetRegionData(hrgn, size, data);
+ TRACE("%s %d rects:", p, data->rdh.nCount);
+ for (i = 0, rect = (RECT *)data->Buffer; i<20 && i < data->rdh.nCount; i++, rect++)
+ TRACE(" %s", wine_dbgstr_rect(rect));
+ TRACE("\n");
+ HeapFree(GetProcessHeap(), 0, data);
+}
+
+
+/*************************************************************************
+ * ScrollDC (MACDRV.@)
+ */
+BOOL CDECL macdrv_ScrollDC(HDC hdc, INT dx, INT dy, const RECT *lprcScroll,
+ const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate)
+{
+ RECT rcSrc, rcClip, offset;
+ INT dxdev, dydev, res;
+ HRGN DstRgn, clipRgn, visrgn;
+
+ TRACE("dx,dy %d,%d rcScroll %s rcClip %s hrgnUpdate %p lprcUpdate %p\n",
+ dx, dy, wine_dbgstr_rect(lprcScroll), wine_dbgstr_rect(lprcClip),
+ hrgnUpdate, lprcUpdate);
+
+ /* get the visible region */
+ visrgn = CreateRectRgn(0, 0, 0, 0);
+ GetRandomRgn(hdc, visrgn, SYSRGN);
+ if (!(GetVersion() & 0x80000000))
+ {
+ /* Window NT/2k/XP */
+ POINT org;
+ GetDCOrgEx(hdc, &org);
+ OffsetRgn(visrgn, -org.x, -org.y);
+ }
+
+ /* intersect with the clipping Region if the DC has one */
+ clipRgn = CreateRectRgn(0, 0, 0, 0);
+ if (GetClipRgn(hdc, clipRgn) != 1)
+ {
+ DeleteObject(clipRgn);
+ clipRgn = NULL;
+ }
+ else
+ CombineRgn(visrgn, visrgn, clipRgn, RGN_AND);
+
+ /* only those pixels in the scroll rectangle that remain in the clipping
+ * rect are scrolled. */
+ if (lprcClip)
+ rcClip = *lprcClip;
+ else
+ GetClipBox(hdc, &rcClip);
+ rcSrc = rcClip;
+ OffsetRect(&rcClip, -dx, -dy);
+ IntersectRect(&rcSrc, &rcSrc, &rcClip);
+
+ /* if an scroll rectangle is specified, only the pixels within that
+ * rectangle are scrolled */
+ if (lprcScroll)
+ IntersectRect(&rcSrc, &rcSrc, lprcScroll);
+
+ /* now convert to device coordinates */
+ LPtoDP(hdc, (LPPOINT)&rcSrc, 2);
+ TRACE("source rect: %s\n", wine_dbgstr_rect(&rcSrc));
+
+ /* also dx and dy */
+ SetRect(&offset, 0, 0, dx, dy);
+ LPtoDP(hdc, (LPPOINT)&offset, 2);
+ dxdev = offset.right - offset.left;
+ dydev = offset.bottom - offset.top;
+
+ /* now intersect with the visible region to get the pixels that will
+ * actually scroll */
+ DstRgn = CreateRectRgnIndirect(&rcSrc);
+ res = CombineRgn(DstRgn, DstRgn, visrgn, RGN_AND);
+
+ /* and translate, giving the destination region */
+ OffsetRgn(DstRgn, dxdev, dydev);
+ if (TRACE_ON(scroll)) dump_region("Destination scroll region: ", DstRgn);
+
+ /* if there are any, do it */
+ if (res > NULLREGION)
+ {
+ RECT rect ;
+ /* clip to the destination region, so we can BitBlt with a simple
+ * bounding rectangle */
+ if (clipRgn)
+ ExtSelectClipRgn(hdc, DstRgn, RGN_AND);
+ else
+ SelectClipRgn(hdc, DstRgn);
+ GetRgnBox(DstRgn, &rect);
+ DPtoLP(hdc, (LPPOINT)&rect, 2);
+ TRACE("destination rect: %s\n", wine_dbgstr_rect(&rect));
+
+ BitBlt(hdc, rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top,
+ hdc, rect.left - dx, rect.top - dy, SRCCOPY);
+ }
+
+ /* compute the update areas. This is the combined clip rectangle
+ * minus the scrolled region, and intersected with the visible
+ * region. */
+ if (hrgnUpdate || lprcUpdate)
+ {
+ HRGN hrgn = hrgnUpdate;
+
+ /* Intersect clip and scroll rectangles, allowing NULL values */
+ if (lprcScroll)
+ if (lprcClip)
+ IntersectRect(&rcClip, lprcClip, lprcScroll);
+ else
+ rcClip = *lprcScroll;
+ else
+ if (lprcClip)
+ rcClip = *lprcClip;
+ else
+ GetClipBox(hdc, &rcClip);
+
+ /* Convert the combined clip rectangle to device coordinates */
+ LPtoDP(hdc, (LPPOINT)&rcClip, 2);
+ if (hrgn)
+ SetRectRgn(hrgn, rcClip.left, rcClip.top, rcClip.right, rcClip.bottom);
+ else
+ hrgn = CreateRectRgnIndirect(&rcClip);
+ CombineRgn(hrgn, hrgn, visrgn, RGN_AND);
+ CombineRgn(hrgn, hrgn, DstRgn, RGN_DIFF);
+ if (TRACE_ON(scroll)) dump_region("Update region: ", hrgn);
+ if (lprcUpdate)
+ {
+ GetRgnBox(hrgn, lprcUpdate);
+ /* Put the lprcUpdate in logical coordinates */
+ DPtoLP(hdc, (LPPOINT)lprcUpdate, 2);
+ TRACE("returning lprcUpdate %s\n", wine_dbgstr_rect(lprcUpdate));
+ }
+ if (!hrgnUpdate)
+ DeleteObject(hrgn);
+ }
+
+ /* restore original clipping region */
+ SelectClipRgn(hdc, clipRgn);
+ DeleteObject(visrgn);
+ DeleteObject(DstRgn);
+ if (clipRgn) DeleteObject(clipRgn);
+ return TRUE;
+}
diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec
index a0e1ab8..6f780ed 100644
--- a/dlls/winemac.drv/winemac.drv.spec
+++ b/dlls/winemac.drv/winemac.drv.spec
@@ -10,6 +10,7 @@
@ cdecl EnumDisplayMonitors(long ptr ptr long) macdrv_EnumDisplayMonitors
@ cdecl GetMonitorInfo(long ptr) macdrv_GetMonitorInfo
@ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) macdrv_MsgWaitForMultipleObjectsEx
+@ cdecl ScrollDC(long long long ptr ptr long ptr) macdrv_ScrollDC
@ cdecl SetFocus(long) macdrv_SetFocus
@ cdecl SetLayeredWindowAttributes(long long long long) macdrv_SetLayeredWindowAttributes
@ cdecl SetParent(long long long) macdrv_SetParent
More information about the wine-cvs
mailing list