Skip to content

Commit eb95c49

Browse files
committed
feat(draw): Implemented pinning to the top of the taskbar
1 parent e6b9d49 commit eb95c49

File tree

5 files changed

+63
-0
lines changed

5 files changed

+63
-0
lines changed

include/window/window_desktop_integration.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,16 @@ void SetWindowTopmost(HWND hwnd, BOOL topmost);
3434
*/
3535
void ReattachToDesktop(HWND hwnd);
3636

37+
/**
38+
* @brief Enforce topmost when window overlaps taskbar
39+
* @param hwnd Window handle
40+
* @return TRUE if window overlaps taskbar area, FALSE otherwise
41+
*
42+
* @details If window is in topmost mode and overlaps with taskbar area,
43+
* re-apply topmost to ensure visibility. Called periodically by main timer.
44+
* Uses standard SetWindowPos API - safe and game-compatible.
45+
*/
46+
BOOL EnforceTopmostOverTaskbar(HWND hwnd);
47+
3748
#endif /* WINDOW_DESKTOP_INTEGRATION_H */
3849

resource/resource.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#define TIMER_ID_VOLUME_PREVIEW 1007 /**< Volume preview auto-stop timer (3s limit) */
5555
#define TIMER_ID_EDIT_MODE_REFRESH 2001 /**< Edit mode refresh timer */
5656
#define TIMER_ID_RENDER_ANIMATION 2002 /**< Dedicated animation render timer (30-60 FPS) */
57+
#define TIMER_ID_TOPMOST_ENFORCE 2003 /**< Fast topmost enforcement when near taskbar (50ms) */
5758
#define TRAY_TIP_TIMER_ID 42421 /**< Tray tooltip update timer */
5859

5960
/** @brief Timer interval constants */

src/timer/timer_events.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "tray/tray_animation_core.h"
2222
#include "utils/string_convert.h"
2323
#include "log.h"
24+
#include "window/window_desktop_integration.h"
2425

2526
/* Pomodoro and timer constants:
2627
* - 1500s = 25 min (standard Pomodoro work duration)
@@ -45,6 +46,7 @@ static int pomodoro_initial_loop_count = 0;
4546
static DWORD last_timer_tick = 0;
4647
static int ms_accumulator = 0;
4748
static BOOL tail_fast_mode_active = FALSE;
49+
static BOOL topmost_fast_mode_active = FALSE;
4850

4951
static inline void ForceWindowRedraw(HWND hwnd) {
5052
InvalidateRect(hwnd, NULL, TRUE);
@@ -477,6 +479,19 @@ static void HandleCountdownCompletion(HWND hwnd) {
477479
}
478480

479481
static BOOL HandleMainTimer(HWND hwnd) {
482+
/* Manage fast topmost enforcement based on taskbar overlap */
483+
BOOL overlapsTaskbar = EnforceTopmostOverTaskbar(hwnd);
484+
485+
if (overlapsTaskbar && !topmost_fast_mode_active) {
486+
/* Window entered taskbar area - start fast timer (50ms) */
487+
SetTimer(hwnd, TIMER_ID_TOPMOST_ENFORCE, 50, NULL);
488+
topmost_fast_mode_active = TRUE;
489+
} else if (!overlapsTaskbar && topmost_fast_mode_active) {
490+
/* Window left taskbar area - stop fast timer */
491+
KillTimer(hwnd, TIMER_ID_TOPMOST_ENFORCE);
492+
topmost_fast_mode_active = FALSE;
493+
}
494+
480495
if (CLOCK_SHOW_CURRENT_TIME) {
481496
extern int last_displayed_second;
482497
last_displayed_second = -1;
@@ -599,6 +614,11 @@ BOOL HandleTimerEvent(HWND hwnd, WPARAM wp) {
599614
InvalidateRect(hwnd, NULL, TRUE);
600615
return TRUE;
601616

617+
case TIMER_ID_TOPMOST_ENFORCE:
618+
/* Fast topmost enforcement when overlapping taskbar (50ms) */
619+
EnforceTopmostOverTaskbar(hwnd);
620+
return TRUE;
621+
602622
default:
603623
return FALSE;
604624
}

src/window/window_desktop_integration.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,33 @@ void ReattachToDesktop(HWND hwnd) {
127127
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
128128
}
129129

130+
BOOL EnforceTopmostOverTaskbar(HWND hwnd) {
131+
/* Only enforce if topmost mode is enabled */
132+
if (!CLOCK_WINDOW_TOPMOST) return FALSE;
133+
134+
/* Get our window position */
135+
RECT rcWindow;
136+
if (!GetWindowRect(hwnd, &rcWindow)) return FALSE;
137+
138+
/* Get taskbar position */
139+
HWND hTaskbar = FindWindowW(L"Shell_TrayWnd", NULL);
140+
if (!hTaskbar) return FALSE;
141+
142+
RECT rcTaskbar;
143+
if (!GetWindowRect(hTaskbar, &rcTaskbar)) return FALSE;
144+
145+
/* Check if our window overlaps with taskbar area */
146+
BOOL overlaps = !(rcWindow.right < rcTaskbar.left ||
147+
rcWindow.left > rcTaskbar.right ||
148+
rcWindow.bottom < rcTaskbar.top ||
149+
rcWindow.top > rcTaskbar.bottom);
150+
151+
if (overlaps) {
152+
/* Re-apply topmost to ensure we stay above taskbar */
153+
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
154+
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
155+
}
156+
157+
return overlaps;
158+
}
159+

src/window_procedure/window_events.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ void HandleWindowDestroy(HWND hwnd) {
100100
CleanupUpdateThread();
101101

102102
KillTimer(hwnd, TIMER_ID_MAIN);
103+
KillTimer(hwnd, TIMER_ID_TOPMOST_ENFORCE);
103104
extern UINT GetClickThroughTimerId(void);
104105
KillTimer(hwnd, GetClickThroughTimerId());
105106
LOG_INFO("Timers stopped");

0 commit comments

Comments
 (0)