Module: wine Branch: master Commit: 6efd198c521f341e3807c5620f5d3f30088e7386 URL: http://source.winehq.org/git/wine.git/?a=commit;h=6efd198c521f341e3807c5620f...
Author: Ken Thomases ken@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