https://git.reactos.org/?p=reactos.git;a=commitdiff;h=dd34ad7037edbc90117db…
commit dd34ad7037edbc90117dbf24dcdca6135ac9c1b6
Author: Whindmar Saksit <whindsaks(a)proton.me>
AuthorDate: Sat Feb 8 16:22:20 2025 +0100
Commit: GitHub <noreply(a)github.com>
CommitDate: Sat Feb 8 16:22:20 2025 +0100
[SHIMGVW] Fixes and enhancements (#7705)
Fixes:
- Reduce flicker when resizing main window
- Fixed slideshow starting with 1x1 pixel image zoom
- Don't reset zoom levels > 100% when resizing main window
- Always retain an active window on toggle slideshow (show/hide actions order)
- Enable/disable real-size button as required
- Correctly handle accelerators in main window after slideshow has been closed
- Use same zoom shortcuts as NT6
New features (unique to ROS):
- Fullscreen mode (slideshow mode but without timer)
- Alt+Enter or double-click to toggle fullscreen mode
- Shift +/- to change fullscreen slideshow next picture timer
CORE-19358
---
dll/win32/shimgvw/resource.h | 5 ++
dll/win32/shimgvw/shimgvw.c | 132 +++++++++++++++++++++++++++++++++++++------
dll/win32/shimgvw/shimgvw.rc | 11 +++-
3 files changed, 131 insertions(+), 17 deletions(-)
diff --git a/dll/win32/shimgvw/resource.h b/dll/win32/shimgvw/resource.h
index ec2fbf116bd..17fce85b7fc 100644
--- a/dll/win32/shimgvw/resource.h
+++ b/dll/win32/shimgvw/resource.h
@@ -30,6 +30,11 @@
/* ToolBar buttons */
#define IDC_TOOL_BASE 500
+#define IDC_ACCEL_BASE (IDC_TOOL_BASE + 100) /* Accelerator commands not on the toolbar
*/
+
+#define IDC_TOGGLEFULLSCREEN (IDC_ACCEL_BASE + 0)
+#define IDC_INCTIMER (IDC_ACCEL_BASE + 1)
+#define IDC_DECTIMER (IDC_ACCEL_BASE + 2)
#define IDC_PREV_PIC (IDC_TOOL_BASE + 0)
#define IDC_NEXT_PIC (IDC_TOOL_BASE + 1)
diff --git a/dll/win32/shimgvw/shimgvw.c b/dll/win32/shimgvw/shimgvw.c
index 693b499761f..c0ce4de2d39 100644
--- a/dll/win32/shimgvw/shimgvw.c
+++ b/dll/win32/shimgvw/shimgvw.c
@@ -20,6 +20,8 @@
/* Slide show timer */
#define SLIDESHOW_TIMER_ID 0xFACE
#define SLIDESHOW_TIMER_INTERVAL 5000 /* 5 seconds */
+#define HIDECURSOR_TIMER_ID 0xBABE
+#define HIDECURSOR_TIMER_TIMEOUT 3000
HINSTANCE g_hInstance = NULL;
HWND g_hMainWnd = NULL;
@@ -109,11 +111,15 @@ typedef struct tagPREVIEW_DATA
INT m_xScrollOffset;
INT m_yScrollOffset;
UINT m_nMouseDownMsg;
+ UINT m_nTimerInterval;
+ BOOL m_bHideCursor;
POINT m_ptOrigin;
IStream *m_pMemStream;
WCHAR m_szFile[MAX_PATH];
} PREVIEW_DATA, *PPREVIEW_DATA;
+static VOID Preview_ToggleSlideShowEx(PPREVIEW_DATA pData, BOOL StartTimer);
+
static inline PPREVIEW_DATA
Preview_GetData(HWND hwnd)
{
@@ -131,14 +137,34 @@ Preview_RestartTimer(HWND hwnd)
{
if (!Preview_IsMainWnd(hwnd))
{
+ PPREVIEW_DATA pData = Preview_GetData(hwnd);
KillTimer(hwnd, SLIDESHOW_TIMER_ID);
- SetTimer(hwnd, SLIDESHOW_TIMER_ID, SLIDESHOW_TIMER_INTERVAL, NULL);
+ if (pData->m_nTimerInterval)
+ SetTimer(hwnd, SLIDESHOW_TIMER_ID, pData->m_nTimerInterval, NULL);
}
}
static VOID
-ZoomWnd_UpdateScroll(PPREVIEW_DATA pData, HWND hwnd, BOOL bResetPos)
+Preview_ChangeSlideShowTimer(PPREVIEW_DATA pData, BOOL bSlower)
{
+ BOOL IsFullscreen = !Preview_IsMainWnd(pData->m_hwnd);
+ enum { mintime = 1000, maxtime = SLIDESHOW_TIMER_INTERVAL * 3, step = 1000 };
+ UINT interval = pData->m_nTimerInterval ? pData->m_nTimerInterval :
SLIDESHOW_TIMER_INTERVAL;
+ if (IsFullscreen)
+ {
+ interval = bSlower ? min(interval + step, maxtime) : max(interval - step,
mintime);
+ if (pData->m_nTimerInterval != interval)
+ {
+ pData->m_nTimerInterval = interval;
+ Preview_RestartTimer(pData->m_hwnd);
+ }
+ }
+}
+
+static VOID
+ZoomWnd_UpdateScroll(PPREVIEW_DATA pData, BOOL bResetPos)
+{
+ HWND hwnd = pData->m_hwndZoom;
RECT rcClient;
UINT ImageWidth, ImageHeight, ZoomedWidth, ZoomedHeight;
SCROLLINFO si;
@@ -221,10 +247,10 @@ Preview_UpdateZoom(PPREVIEW_DATA pData, UINT NewZoom, BOOL
bEnableBestFit, BOOL
bEnableZoomOut = (NewZoom > MIN_ZOOM);
/* Update toolbar buttons */
- PostMessageW(hToolBar, TB_ENABLEBUTTON, IDC_ZOOM_OUT, bEnableZoomOut);
- PostMessageW(hToolBar, TB_ENABLEBUTTON, IDC_ZOOM_IN, bEnableZoomIn);
- PostMessageW(hToolBar, TB_ENABLEBUTTON, IDC_BEST_FIT, bEnableBestFit);
- PostMessageW(hToolBar, TB_ENABLEBUTTON, IDC_REAL_SIZE, bEnableRealSize);
+ SendMessageW(hToolBar, TB_ENABLEBUTTON, IDC_BEST_FIT, bEnableBestFit);
+ SendMessageW(hToolBar, TB_ENABLEBUTTON, IDC_REAL_SIZE, NewZoom != 100);
+ SendMessageW(hToolBar, TB_ENABLEBUTTON, IDC_ZOOM_IN, bEnableZoomIn);
+ SendMessageW(hToolBar, TB_ENABLEBUTTON, IDC_ZOOM_OUT, bEnableZoomOut);
/* Redraw the display window */
InvalidateRect(pData->m_hwndZoom, NULL, TRUE);
@@ -233,7 +259,7 @@ Preview_UpdateZoom(PPREVIEW_DATA pData, UINT NewZoom, BOOL
bEnableBestFit, BOOL
Preview_RestartTimer(pData->m_hwnd);
/* Update scroll info */
- ZoomWnd_UpdateScroll(pData, pData->m_hwndZoom, FALSE);
+ ZoomWnd_UpdateScroll(pData, FALSE);
}
static VOID
@@ -592,7 +618,7 @@ Preview_UpdateImage(PPREVIEW_DATA pData)
if (!Preview_IsMainWnd(pData->m_hwnd))
Preview_ResetZoom(pData);
- ZoomWnd_UpdateScroll(pData, pData->m_hwndZoom, TRUE);
+ ZoomWnd_UpdateScroll(pData, TRUE);
}
static SHIMGVW_FILENODE*
@@ -985,11 +1011,24 @@ Preview_EndSlideShow(HWND hwnd)
return;
KillTimer(hwnd, SLIDESHOW_TIMER_ID);
+ ShowWindow(g_hMainWnd, SW_SHOW);
ShowWindow(hwnd, SW_HIDE);
- ShowWindow(g_hMainWnd, SW_SHOWNORMAL);
Preview_ResetZoom(Preview_GetData(g_hMainWnd));
}
+static VOID
+GenerateSetCursor(HWND hwnd, UINT uMsg)
+{
+ SendMessage(hwnd, WM_SETCURSOR, (WPARAM)hwnd, MAKELONG(HTCLIENT, uMsg));
+}
+
+static VOID
+ZoomWnd_StopHideCursor(PPREVIEW_DATA pData)
+{
+ pData->m_bHideCursor = FALSE;
+ KillTimer(pData->m_hwndZoom, HIDECURSOR_TIMER_ID);
+}
+
static VOID
ZoomWnd_OnButtonDown(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
@@ -1002,6 +1041,7 @@ ZoomWnd_OnButtonDown(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
lParam)
return;
}
+ ZoomWnd_StopHideCursor(pData);
pData->m_nMouseDownMsg = uMsg;
pData->m_ptOrigin.x = GET_X_LPARAM(lParam);
pData->m_ptOrigin.y = GET_Y_LPARAM(lParam);
@@ -1015,6 +1055,13 @@ ZoomWnd_OnMouseMove(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
lParam)
PPREVIEW_DATA pData = Preview_GetData(hwnd);
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+ if (!Preview_IsMainWnd(pData->m_hwnd))
+ {
+ ZoomWnd_StopHideCursor(pData);
+ if (!pData->m_nMouseDownMsg)
+ SetTimer(hwnd, HIDECURSOR_TIMER_ID, HIDECURSOR_TIMER_TIMEOUT, NULL);
+ }
+
if (pData->m_nMouseDownMsg == WM_MBUTTONDOWN)
{
INT x = GetScrollPos(hwnd, SB_HORZ) - (pt.x - pData->m_ptOrigin.x);
@@ -1034,6 +1081,12 @@ ZoomWnd_OnSetCursor(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
lParam)
SetCursor(LoadCursorW(g_hInstance, MAKEINTRESOURCEW(IDC_HANDDRAG)));
return TRUE;
}
+
+ if (pData->m_bHideCursor)
+ {
+ SetCursor(NULL); /* Hide cursor in fullscreen */
+ return TRUE;
+ }
return FALSE;
}
@@ -1041,8 +1094,15 @@ static VOID
ZoomWnd_OnButtonUp(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PPREVIEW_DATA pData = Preview_GetData(hwnd);
+ BOOL wasdrag = pData->m_nMouseDownMsg == WM_MBUTTONDOWN;
+
pData->m_nMouseDownMsg = 0;
+ if (wasdrag)
+ GenerateSetCursor(hwnd, uMsg); /* Reset to default cursor */
ReleaseCapture();
+
+ if (!Preview_IsMainWnd(pData->m_hwnd))
+ SetTimer(hwnd, HIDECURSOR_TIMER_ID, HIDECURSOR_TIMER_TIMEOUT, NULL);
}
static VOID
@@ -1167,6 +1227,12 @@ ZoomWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
ZoomWnd_OnButtonUp(hwnd, uMsg, wParam, lParam);
break;
}
+ case WM_LBUTTONDBLCLK:
+ {
+ if (Preview_IsMainWnd(pData->m_hwnd))
+ Preview_ToggleSlideShowEx(pData, FALSE);
+ break;
+ }
case WM_PAINT:
{
ZoomWnd_OnPaint(pData, hwnd);
@@ -1184,8 +1250,19 @@ ZoomWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
break;
case WM_TIMER:
{
+ if (wParam == HIDECURSOR_TIMER_ID)
+ {
+ ZoomWnd_StopHideCursor(pData);
+ if (IsWindowVisible(hwnd))
+ {
+ pData->m_bHideCursor = TRUE;
+ GenerateSetCursor(hwnd, uMsg);
+ }
+ }
if (Anime_OnTimer(&pData->m_Anime, wParam))
+ {
InvalidateRect(hwnd, NULL, FALSE);
+ }
break;
}
default:
@@ -1298,7 +1375,9 @@ Preview_OnSize(HWND hwnd)
MoveWindow(pData->m_hwndZoom, 0, 0, cx, cy - (rc.bottom - rc.top), TRUE);
- if (!IsIconic(hwnd)) /* Is it not minimized? */
+ if (pData->m_nZoomPercents > 100)
+ ZoomWnd_UpdateScroll(pData, FALSE);
+ else if (!IsIconic(hwnd)) /* Is it not minimized? */
Preview_ResetZoom(pData);
Preview_OnMoveSize(hwnd);
@@ -1372,7 +1451,7 @@ Preview_Edit(HWND hwnd)
}
static VOID
-Preview_ToggleSlideShow(PPREVIEW_DATA pData)
+Preview_ToggleSlideShowEx(PPREVIEW_DATA pData, BOOL StartTimer)
{
if (!IsWindow(g_hwndFullscreen))
{
@@ -1385,18 +1464,28 @@ Preview_ToggleSlideShow(PPREVIEW_DATA pData)
if (IsWindowVisible(g_hwndFullscreen))
{
- ShowWindow(g_hwndFullscreen, SW_HIDE);
- ShowWindow(g_hMainWnd, SW_SHOWNORMAL);
KillTimer(g_hwndFullscreen, SLIDESHOW_TIMER_ID);
+ ShowWindow(g_hMainWnd, SW_SHOW);
+ ShowWindow(g_hwndFullscreen, SW_HIDE);
}
else
{
- ShowWindow(g_hMainWnd, SW_HIDE);
+ PPREVIEW_DATA pSlideData = Preview_GetData(g_hwndFullscreen);
+ pSlideData->m_nTimerInterval = StartTimer ? SLIDESHOW_TIMER_INTERVAL : 0;
ShowWindow(g_hwndFullscreen, SW_SHOWMAXIMIZED);
+ ShowWindow(g_hMainWnd, SW_HIDE);
+ Preview_ResetZoom(pSlideData);
Preview_RestartTimer(g_hwndFullscreen);
+ PostMessage(pSlideData->m_hwndZoom, WM_MOUSEMOVE, 0, 0); /* Start hide cursor
*/
}
}
+static inline VOID
+Preview_ToggleSlideShow(PPREVIEW_DATA pData)
+{
+ Preview_ToggleSlideShowEx(pData, TRUE);
+}
+
static VOID
Preview_GoNextPic(PPREVIEW_DATA pData, BOOL bNext)
{
@@ -1452,6 +1541,15 @@ Preview_OnCommand(HWND hwnd, UINT nCommandID)
Preview_EndSlideShow(hwnd);
break;
+ case IDC_TOGGLEFULLSCREEN:
+ Preview_ToggleSlideShowEx(pData, FALSE);
+ break;
+
+ case IDC_INCTIMER:
+ case IDC_DECTIMER:
+ Preview_ChangeSlideShowTimer(pData, nCommandID == IDC_INCTIMER);
+ break;
+
default:
break;
}
@@ -1541,6 +1639,7 @@ Preview_OnDestroy(HWND hwnd)
PPREVIEW_DATA pData = Preview_GetData(hwnd);
KillTimer(hwnd, SLIDESHOW_TIMER_ID);
+ KillTimer(hwnd, HIDECURSOR_TIMER_ID);
pFreeFileList(g_pCurrentFile);
g_pCurrentFile = NULL;
@@ -1683,7 +1782,7 @@ ImageView_Main(HWND hwnd, LPCWSTR szFileName)
WndClass.style = CS_HREDRAW | CS_VREDRAW;
WndClass.hIcon = LoadIconW(g_hInstance, MAKEINTRESOURCEW(IDI_APP_ICON));
WndClass.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
- WndClass.hbrBackground = (HBRUSH)UlongToHandle(COLOR_3DFACE + 1);
+ WndClass.hbrBackground = GetStockBrush(NULL_BRUSH); /* less flicker */
if (!RegisterClassW(&WndClass))
return -1;
WndClass.lpszClassName = WC_ZOOM;
@@ -1714,7 +1813,8 @@ ImageView_Main(HWND hwnd, LPCWSTR szFileName)
/* Message Loop */
while (GetMessageW(&msg, NULL, 0, 0) > 0)
{
- if (g_hwndFullscreen && TranslateAcceleratorW(g_hwndFullscreen, hAccel,
&msg))
+ const HWND hwndFull = g_hwndFullscreen;
+ if (IsWindowVisible(hwndFull) && TranslateAcceleratorW(hwndFull, hAccel,
&msg))
continue;
if (TranslateAcceleratorW(hMainWnd, hAccel, &msg))
continue;
diff --git a/dll/win32/shimgvw/shimgvw.rc b/dll/win32/shimgvw/shimgvw.rc
index bb46198ded1..bec550cb4c3 100644
--- a/dll/win32/shimgvw/shimgvw.rc
+++ b/dll/win32/shimgvw/shimgvw.rc
@@ -43,10 +43,19 @@ BEGIN
"B", IDC_BEST_FIT, VIRTKEY, CONTROL
"A", IDC_REAL_SIZE, VIRTKEY, CONTROL
VK_F11, IDC_SLIDE_SHOW, VIRTKEY
+ VK_RETURN, IDC_TOGGLEFULLSCREEN, VIRTKEY, ALT
+ VK_ADD, IDC_INCTIMER, VIRTKEY, SHIFT
+ VK_OEM_PLUS, IDC_INCTIMER, VIRTKEY, SHIFT
+ VK_OEM_MINUS,IDC_DECTIMER, VIRTKEY, SHIFT
+ VK_SUBTRACT, IDC_DECTIMER, VIRTKEY, SHIFT
VK_ADD, IDC_ZOOM_IN, VIRTKEY
+ VK_ADD, IDC_ZOOM_IN, VIRTKEY, CONTROL
+ VK_OEM_PLUS, IDC_ZOOM_IN, VIRTKEY
+ VK_OEM_PLUS, IDC_ZOOM_IN, VIRTKEY, CONTROL
VK_SUBTRACT, IDC_ZOOM_OUT, VIRTKEY
- VK_OEM_PLUS, IDC_ZOOM_IN, VIRTKEY, SHIFT
+ VK_SUBTRACT, IDC_ZOOM_OUT, VIRTKEY, CONTROL
VK_OEM_MINUS,IDC_ZOOM_OUT, VIRTKEY
+ VK_OEM_MINUS,IDC_ZOOM_OUT, VIRTKEY, CONTROL
"K", IDC_ROT_CLOCKW, VIRTKEY, CONTROL
"L", IDC_ROT_COUNCW, VIRTKEY, CONTROL
VK_DELETE, IDC_DELETE, VIRTKEY