annotate dep/animone/src/win/win32.cc @ 327:b5d6c27c308f

anime: refactor Anime::SeriesSeason to Season class ToLocalString has also been altered to take in both season and year because lots of locales actually treat formatting seasons differently! most notably is Russian which adds a suffix at the end to notate seasons(??)
author Paper <paper@paper.us.eu.org>
date Thu, 13 Jun 2024 01:49:18 -0400
parents b1f625b0227c
children a7d4e5107531
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
301
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
1 /*
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
2 * win/win32.cc: support for Windows
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
3 *
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
4 * Surprisingly, this is the one time where Microsoft actually
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
5 * does it fairly OK. Everything has a pretty simple API, despite
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
6 * the stupid wide string stuff.
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
7 */
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
8 #include "animone/win/win32.h"
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
9 #include "animone.h"
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
10 #include "animone/util/win32.h"
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
11 #include "animone/win.h"
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
12 #include "animone/fd.h"
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
13
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
14 #include <set>
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
15 #include <string>
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
16
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
17 #include <windows.h>
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
18
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
19 namespace animone::internal::win32 {
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
20
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
21 static std::wstring GetWindowClassName(HWND hwnd) {
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
22 static constexpr int kMaxSize = 256;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
23
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
24 std::wstring buffer(kMaxSize, L'\0');
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
25 const auto size = ::GetClassNameW(hwnd, &buffer.front(), buffer.length());
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
26 buffer.resize(size);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
27 return buffer;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
28 }
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
29
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
30 static std::wstring GetWindowText(HWND hwnd) {
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
31 const auto estimated_size = ::GetWindowTextLengthW(hwnd);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
32 std::wstring buffer(estimated_size + 1, L'\0');
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
33
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
34 const auto size = ::GetWindowTextW(hwnd, &buffer.front(), buffer.length());
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
35 /* GetWindowTextLength docs:
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
36 * "Under certain conditions, the GetWindowTextLength function may return a value
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
37 * that is larger than the actual length of the text." */
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
38 buffer.resize(size);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
39 return buffer;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
40 }
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
41
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
42 static DWORD GetWindowProcessId(HWND hwnd) {
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
43 DWORD process_id = 0;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
44 ::GetWindowThreadProcessId(hwnd, &process_id);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
45 return process_id;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
46 }
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
47
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
48 ////////////////////////////////////////////////////////////////////////////////
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
49
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
50 static bool VerifyWindowStyle(HWND hwnd) {
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
51 const auto window_style = ::GetWindowLong(hwnd, GWL_STYLE);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
52 const auto window_ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
53
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
54 auto has_style = [&window_style](DWORD style) { return (window_style & style) != 0; };
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
55 auto has_ex_style = [&window_ex_style](DWORD ex_style) { return (window_ex_style & ex_style) != 0; };
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
56
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
57 // Toolbars, tooltips and similar topmost windows
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
58 if (has_style(WS_POPUP) && has_ex_style(WS_EX_TOOLWINDOW))
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
59 return false;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
60 if (has_ex_style(WS_EX_TOPMOST) && has_ex_style(WS_EX_TOOLWINDOW))
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
61 return false;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
62
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
63 return true;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
64 }
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
65
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
66 static bool VerifyClassName(const std::wstring& name) {
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
67 static const std::set<std::wstring> invalid_names = {
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
68 // System classes
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
69 L"#32770", // Dialog box
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
70 L"CabinetWClass", // Windows Explorer
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
71 L"ComboLBox",
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
72 L"DDEMLEvent",
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
73 L"DDEMLMom",
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
74 L"DirectUIHWND",
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
75 L"GDI+ Hook Window Class",
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
76 L"IME",
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
77 L"Internet Explorer_Hidden",
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
78 L"MSCTFIME UI",
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
79 L"tooltips_class32",
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
80 };
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
81
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
82 return !name.empty() && !invalid_names.count(name);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
83 }
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
84
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
85 static bool VerifyProcessPath(const std::wstring& path) {
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
86 return !path.empty() && !IsSystemDirectory(path);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
87 }
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
88
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
89 static bool VerifyProcessFileName(const std::wstring& name) {
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
90 static const std::set<std::wstring> invalid_names = {
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
91 // System files
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
92 L"explorer", // Windows Explorer
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
93 L"taskeng", // Task Scheduler Engine
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
94 L"taskhost", // Host Process for Windows Tasks
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
95 L"taskhostex", // Host Process for Windows Tasks
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
96 L"Taskmgr", // Task Manager
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
97 };
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
98
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
99 return !name.empty() && !invalid_names.count(name);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
100 }
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
101
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
102 ////////////////////////////////////////////////////////////////////////////////
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
103
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
104 static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM param) {
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
105 if (!::IsWindowVisible(hwnd))
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
106 return TRUE;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
107
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
108 if (!VerifyWindowStyle(hwnd))
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
109 return TRUE;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
110
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
111 Window window;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
112 window.id = static_cast<unsigned int>(reinterpret_cast<ULONG_PTR>(hwnd));
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
113 window.text = ToUtf8String(GetWindowText(hwnd));
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
114
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
115 {
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
116 std::wstring class_name = GetWindowClassName(hwnd);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
117 window.class_name = ToUtf8String(class_name);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
118 if (!VerifyClassName(class_name))
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
119 return TRUE;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
120 }
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
121
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
122 Process process;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
123 process.pid = GetWindowProcessId(hwnd);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
124 GetProcessName(process.pid, process.name);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
125
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
126 auto& window_proc = *reinterpret_cast<window_proc_t*>(param);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
127 if (!window_proc(process, window))
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
128 return FALSE;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
129
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
130 return TRUE;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
131 }
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
132
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
133 bool EnumerateWindows(window_proc_t window_proc) {
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
134 if (!window_proc)
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
135 return false;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
136
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
137 const auto param = reinterpret_cast<LPARAM>(&window_proc);
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
138
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
139 // Note that EnumWindows enumerates only top-level windows of desktop apps
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
140 // (as opposed to UWP apps) on Windows 8 and above.
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
141 return ::EnumWindows(EnumWindowsProc, param) != FALSE;
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
142 }
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
143
b1f625b0227c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 267
diff changeset
144 } // namespace animone::internal::win32