[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
This commit is contained in:
Whindmar Saksit 2025-02-08 16:22:20 +01:00 committed by GitHub
parent 2d1144a5cd
commit dd34ad7037
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 131 additions and 17 deletions

View file

@ -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)

View file

@ -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;

View file

@ -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