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