Author: dquintana Date: Sun Dec 13 00:34:18 2015 New Revision: 70335
URL: http://svn.reactos.org/svn/reactos?rev=70335&view=rev Log: [MAGNIFY] Some improvements to the drawing code: * Draw as soon as the mouse/caret/focus changes, or after 100ms if nothing changed. * Copy only the needed area of the screen into the internal buffer. * Blank out the area of the buffer where the client region of the magnifier overlaps, to avoid re-zooming the pixels. * Keep the source region contained within the closest monitor, instead of only the primary one. * Invert colors when copying from the screen, instead of when stretching, since there's less pixels to draw.
First step toward the improvements described in CORE-10691
Modified: trunk/reactos/base/applications/magnify/magnifier.c
Modified: trunk/reactos/base/applications/magnify/magnifier.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/magnify/m... ============================================================================== --- trunk/reactos/base/applications/magnify/magnifier.c [iso-8859-1] (original) +++ trunk/reactos/base/applications/magnify/magnifier.c [iso-8859-1] Sun Dec 13 00:34:18 2015 @@ -27,7 +27,10 @@
TCHAR szTitle[MAX_LOADSTRING];
+#define TIMER_SPEED 1 #define REPAINT_SPEED 100 + +DWORD lastTicks = 0;
HWND hDesktopWindow = NULL;
@@ -148,26 +151,62 @@ } }
+void GetBestOverlapWithMonitors(LPRECT rect) +{ + int rcLeft, rcTop; + int rcWidth, rcHeight; + RECT rcMon; + HMONITOR hMon = MonitorFromRect(rect, MONITOR_DEFAULTTONEAREST); + MONITORINFO info; + info.cbSize = sizeof(info); + + GetMonitorInfo(hMon, &info); + + rcMon = info.rcMonitor; + + rcLeft = rect->left; + rcTop = rect->top; + rcWidth = (rect->right - rect->left); + rcHeight = (rect->bottom - rect->top); + + if (rcLeft < rcMon.left) + rcLeft = rcMon.left; + + if (rcTop < rcMon.top) + rcTop = rcMon.top; + + if (rcLeft > (rcMon.right - rcWidth)) + rcLeft = (rcMon.right - rcWidth); + + if (rcTop > (rcMon.bottom - rcHeight)) + rcTop = (rcMon.bottom - rcHeight); + + OffsetRect(rect, (rcLeft-rect->left), (rcTop-rect->top)); +} + void Draw(HDC aDc) { HDC desktopHdc = NULL; - HDC HdcStrech; + HDC HdcStretch; HANDLE hOld; HBITMAP HbmpStrech; - - RECT R; - RECT appRect; + + RECT sourceRect, intersectedRect; + RECT targetRect, appRect; DWORD rop = SRCCOPY; CURSORINFO cinfo; ICONINFO iinfo;
- int Width, Height, AppWidth, AppHeight; - LONG blitAreaWidth, blitAreaHeight, blitAreaX, blitAreaY; - - desktopHdc = GetWindowDC(hDesktopWindow); + int AppWidth, AppHeight; + LONG blitAreaWidth, blitAreaHeight; + + if (bInvertColors) + rop = NOTSRCCOPY; + + desktopHdc = GetDC(0);
GetClientRect(hMainWnd, &appRect); - GetWindowRect(hDesktopWindow, &R); + GetWindowRect(hDesktopWindow, &sourceRect);
ZeroMemory(&cinfo, sizeof(cinfo)); ZeroMemory(&iinfo, sizeof(iinfo)); @@ -175,63 +214,59 @@ GetCursorInfo(&cinfo); GetIconInfo(cinfo.hCursor, &iinfo);
+ targetRect = appRect; + ClientToScreen(hMainWnd, (POINT*)&targetRect.left); + ClientToScreen(hMainWnd, (POINT*)&targetRect.right); + + AppWidth = (appRect.right - appRect.left); + AppHeight = (appRect.bottom - appRect.top); + + blitAreaWidth = AppWidth / iZoom; + blitAreaHeight = AppHeight / iZoom; + + sourceRect.left = (cp.x) - (blitAreaWidth /2); + sourceRect.top = (cp.y) - (blitAreaHeight /2); + sourceRect.right = sourceRect.left + blitAreaWidth; + sourceRect.bottom = sourceRect.top + blitAreaHeight; + + GetBestOverlapWithMonitors(&sourceRect); + /* Create a memory DC compatible with client area DC */ - HdcStrech = CreateCompatibleDC(desktopHdc); + HdcStretch = CreateCompatibleDC(desktopHdc);
/* Create a bitmap compatible with the client area DC */ HbmpStrech = CreateCompatibleBitmap( desktopHdc, - R.right, - R.bottom); + blitAreaWidth, + blitAreaHeight);
/* Select our bitmap in memory DC and save the old one */ - hOld = SelectObject(HdcStrech , HbmpStrech); - + hOld = SelectObject(HdcStretch , HbmpStrech); + /* Paint the screen bitmap to our in memory DC */ BitBlt( - HdcStrech, + HdcStretch, 0, 0, - R.right, - R.bottom, + blitAreaWidth, + blitAreaHeight, desktopHdc, - 0, - 0, - SRCCOPY); - + sourceRect.left, + sourceRect.top, + rop); + + if (IntersectRect(&intersectedRect, &sourceRect, &targetRect)) + { + OffsetRect(&intersectedRect, -sourceRect.left, -sourceRect.top); + FillRect(HdcStretch, &intersectedRect, GetStockObject(DC_BRUSH)); + } + /* Draw the mouse pointer in the right position */ DrawIcon( - HdcStrech , - pMouse.x - iinfo.xHotspot, // - 10, - pMouse.y - iinfo.yHotspot, // - 10, + HdcStretch , + pMouse.x - iinfo.xHotspot - sourceRect.left, // - 10, + pMouse.y - iinfo.yHotspot - sourceRect.top, // - 10, cinfo.hCursor); - - Width = (R.right - R.left); - Height = (R.bottom - R.top); - - AppWidth = (appRect.right - appRect.left); - AppHeight = (appRect.bottom - appRect.top); - - blitAreaWidth = AppWidth / iZoom; - blitAreaHeight = AppHeight / iZoom; - - blitAreaX = (cp.x) - (blitAreaWidth /2); - blitAreaY = (cp.y) - (blitAreaHeight /2); - - if (blitAreaX < 0) - blitAreaX = 0; - - if (blitAreaY < 0) - blitAreaY = 0; - - if (blitAreaX > (Width - blitAreaWidth)) - blitAreaX = (Width - blitAreaWidth); - - if (blitAreaY > (Height - blitAreaHeight)) - blitAreaY = (Height - blitAreaHeight); - - if (bInvertColors) - rop = NOTSRCCOPY;
/* Blast the stretched image from memory DC to window DC */ StretchBlt( @@ -240,22 +275,21 @@ 0, AppWidth, AppHeight, - HdcStrech, - blitAreaX, - blitAreaY, + HdcStretch, + 0, + 0, blitAreaWidth, blitAreaHeight, - rop | NOMIRRORBITMAP); - - + SRCCOPY | NOMIRRORBITMAP); + /* Cleanup */ if (iinfo.hbmMask) DeleteObject(iinfo.hbmMask); if (iinfo.hbmColor) DeleteObject(iinfo.hbmColor); - SelectObject(HdcStrech, hOld); + SelectObject(HdcStretch, hOld); DeleteObject (HbmpStrech); - DeleteDC(HdcStrech); + DeleteDC(HdcStretch); ReleaseDC(hDesktopWindow, desktopHdc); }
@@ -267,53 +301,85 @@ { case WM_TIMER: { - POINT pNewMouse; - POINT pNewCaret; - POINT pNewFocus; - HWND hwnd1, hwnd2, hwnd3; - DWORD a, b; - RECT controlRect; - - //Get current mouse position - GetCursorPos (&pNewMouse); - - //Get caret position - hwnd1 = GetForegroundWindow (); - a = GetWindowThreadProcessId(hwnd1, NULL); - b = GetCurrentThreadId(); - AttachThreadInput (a, b, TRUE); - hwnd2 = GetFocus(); - - GetCaretPos( &pNewCaret); - ClientToScreen (hwnd2, (LPPOINT) &pNewCaret); - AttachThreadInput (a, b, FALSE); - - //Get current control focus - hwnd3 = GetFocus (); - GetWindowRect (hwnd3 , &controlRect); - pNewFocus.x = controlRect.left; - pNewFocus.y = controlRect.top; - - //If mouse has moved .... - if (((pMouse.x != pNewMouse.x) || (pMouse.y != pNewMouse.y)) && bFollowMouse) - { - //Update to new position - pMouse = pNewMouse; - cp = pNewMouse; - } - else if (((pCaret.x != pNewCaret.x) || (pCaret.y != pNewCaret.y)) && bFollowCaret) - { - //Update to new position - pCaret = pNewCaret; - cp = pNewCaret; - } - else if (((pFocus.x != pNewFocus.x) || (pFocus.y != pNewFocus.y)) && bFollowFocus) - { - //Update to new position - pFocus = pNewFocus; - cp = pNewFocus; - } - Refresh(); + BOOL hasMoved = FALSE; + + if (bFollowMouse) + { + POINT pNewMouse; + + //Get current mouse position + GetCursorPos (&pNewMouse); + + //If mouse has moved ... + if (((pMouse.x != pNewMouse.x) || (pMouse.y != pNewMouse.y))) + { + //Update to new position + pMouse = pNewMouse; + cp = pNewMouse; + hasMoved = TRUE; + } + } + + if (bFollowCaret && !hasMoved) + { + POINT pNewCaret; + HWND hwnd2; + + //Get caret position + HWND hwnd1 = GetForegroundWindow (); + DWORD a = GetWindowThreadProcessId(hwnd1, NULL); + DWORD b = GetCurrentThreadId(); + AttachThreadInput (a, b, TRUE); + hwnd2 = GetFocus(); + + GetCaretPos( &pNewCaret); + ClientToScreen (hwnd2, (LPPOINT) &pNewCaret); + AttachThreadInput (a, b, FALSE); + + if (((pCaret.x != pNewCaret.x) || (pCaret.y != pNewCaret.y))) + { + //Update to new position + pCaret = pNewCaret; + cp = pNewCaret; + hasMoved = TRUE; + } + } + + if (bFollowFocus && !hasMoved) + { + POINT pNewFocus; + RECT controlRect; + + //Get current control focus + HWND hwnd3 = GetFocus (); + GetWindowRect (hwnd3 , &controlRect); + pNewFocus.x = controlRect.left; + pNewFocus.y = controlRect.top; + + if(((pFocus.x != pNewFocus.x) || (pFocus.y != pNewFocus.y))) + { + //Update to new position + pFocus = pNewFocus; + cp = pNewFocus; + hasMoved = TRUE; + } + } + + if(!hasMoved) + { + DWORD newTicks = GetTickCount(); + DWORD elapsed = (newTicks - lastTicks); + if(elapsed > REPAINT_SPEED) + { + hasMoved = TRUE; + } + } + + if(hasMoved) + { + lastTicks = GetTickCount(); + Refresh(); + } } break;
@@ -367,7 +433,7 @@ hDesktopWindow = GetDesktopWindow();
/* Set the timer */ - SetTimer (hWnd , 1, REPAINT_SPEED , NULL); + SetTimer (hWnd , 1, TIMER_SPEED , NULL); break;
default: