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/…
==============================================================================
--- 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: