From 4e8d9d65e92d9e806f89753f2da026630028b5f8 Mon Sep 17 00:00:00 2001 From: wwxiaoqi Date: Fri, 18 Aug 2023 18:47:06 +0800 Subject: [PATCH] feat: fork implement window pinning. Title: implement window pinning Links: henkman#21 ```Describe-Text this is useful when you're running a multi-monitor setup and want some windows to persist on all desktops (such as having a performance monitor on your 2nd monitor) the hotkey for pinning is CTRL + SHIFT + ALT + P I opted for a small fixed size array to save memory since you're not gonna pin many windows anyway it's kind of a big patch (40+ lines) so I understand if you don't want to merge it to keep the lines of code count low tecnically using 0 as the empty hwnd value is wrong, but it's highly unlikely that a window that isn't a system window is gonna have HWND = 0, so it should be fine and it saves having to initialize the array to INVALID_WINDOW_HANDLE in virgo_init ``` --- README.md | 1 + virgo.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/README.md b/README.md index 4cdb01f..6d2147b 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Hotkeys: CTRL + 1..4 -> moves active window to desktop 1..4 ALT + CTRL + SHIFT + Q -> exits the program ALT + CTRL + SHIFT + S -> starts/stops handling of other hotkeys + ALT + CTRL + SHIFT + T -> pin active window (makes it always visible) the nerds can build it with diff --git a/virgo.c b/virgo.c index 2359d80..371aed3 100644 --- a/virgo.c +++ b/virgo.c @@ -19,6 +19,7 @@ #endif #define NUM_DESKTOPS 4 +#define NUM_PINNED 8 typedef struct { HWND *windows; @@ -39,6 +40,7 @@ typedef struct { unsigned handle_hotkeys; Windows desktops[NUM_DESKTOPS]; Trayicon trayicon; + HWND pinned[NUM_PINNED]; } Virgo; static void *stb__sbgrowf(void *arr, unsigned increment, unsigned itemsize) @@ -182,6 +184,38 @@ static void register_hotkey(unsigned id, unsigned mod, unsigned vk) } } +static unsigned virgo_is_pinned(Virgo *v, HWND hwnd) { + unsigned i; + for (i = 0; i < NUM_PINNED; ++i) { + if (v->pinned[i] == hwnd) { + return 1; + } + } + return 0; +} + +static void virgo_toggle_pin(Virgo *v, HWND hwnd) { + unsigned i; + unsigned empty = NUM_PINNED; + for (i = 0; i < NUM_PINNED; ++i) { + if (v->pinned[i] == hwnd) { + v->pinned[i] = 0; + windows_add(&v->desktops[v->current], hwnd); + return; + } + if (!v->pinned[i]) { + empty = i; + } + } + if (empty == NUM_PINNED) { + MessageBox(NULL, "reached pinned windows limit", "error", + MB_ICONEXCLAMATION); + return; + } + v->pinned[empty] = hwnd; + windows_del(&v->desktops[v->current], hwnd); +} + static BOOL enum_func(HWND hwnd, LPARAM lParam) { unsigned i, e; @@ -199,6 +233,9 @@ static BOOL enum_func(HWND hwnd, LPARAM lParam) } } } + if (virgo_is_pinned(v, hwnd)) { + return 1; + } windows_add(&(v->desktops[v->current]), hwnd); return 1; } @@ -217,6 +254,12 @@ static void virgo_update(Virgo *v) } } } + for (i = 0; i < NUM_PINNED; i++) { + hwnd = v->pinned[i]; + if (!GetWindowThreadProcessId(hwnd, NULL)) { + v->pinned[i] = 0; + } + } desk = &v->desktops[v->current]; for (i = 0; i < desk->count; i++) { hwnd = desk->windows[i]; @@ -256,6 +299,8 @@ static void virgo_init(Virgo *v) 'Q'); register_hotkey(i * 2 + 1, MOD_ALT | MOD_CONTROL | MOD_SHIFT | MOD_NOREPEAT, 'S'); + register_hotkey(i * 2 + 2, MOD_ALT | MOD_CONTROL | MOD_SHIFT | MOD_NOREPEAT, + 'T'); trayicon_init(&v->trayicon); } @@ -277,6 +322,9 @@ static void virgo_move_to_desk(Virgo *v, unsigned desk) } virgo_update(v); hwnd = GetForegroundWindow(); + if (virgo_is_pinned(v, hwnd)) { + return; + } if (!hwnd || !is_valid_window(hwnd)) { return; } @@ -312,6 +360,8 @@ void __main(void) } if (msg.wParam == NUM_DESKTOPS * 2 + 1) { virgo_toggle_hotkeys(&v); + } else if (msg.wParam == NUM_DESKTOPS * 2 + 2) { + virgo_toggle_pin(&v, GetForegroundWindow()); } else if (msg.wParam % 2 == 0) { virgo_go_to_desk(&v, msg.wParam / 2); } else {