https://git.reactos.org/?p=reactos.git;a=commitdiff;h=dd34ad7037edbc90117dbf24dcdca6135ac9c1b6
commit dd34ad7037edbc90117dbf24dcdca6135ac9c1b6 Author: Whindmar Saksit <whinds...@proton.me> AuthorDate: Sat Feb 8 16:22:20 2025 +0100 Commit: GitHub <nore...@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