annotate src/win/win32.cc @ 21:973734ebd2be

dep/animone: REFACTOR ALL THE THINGS 1: animone now has its own syntax divergent from anisthesia, making different platforms actually have their own sections 2: process names in animone are now called `comm' (this will probably break things). this is what its called in bsd/linux so I'm just going to use it everywhere 3: the X11 code now checks for the existence of a UTF-8 window title and passes it if available 4: ANYTHING THATS NOT LINUX IS 100% UNTESTED AND CAN AND WILL BREAK! I still actually need to test the bsd code. to be honest I'm probably going to move all of the bsds into separate files because they're all essentially different operating systems at this point
author Paper <paper@paper.us.eu.org>
date Wed, 19 Jun 2024 12:51:15 -0400
parents 27b988a1048c
children 60ded877339b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
14
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
1 /*
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
2 * win/win32.cc: support for Windows
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
3 *
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
4 * Surprisingly, this is the one time where Microsoft actually
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
5 * does it fairly OK. Everything has a pretty simple API, despite
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
6 * the stupid wide string stuff.
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
7 */
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
8 #include "animone/win/win32.h"
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
9 #include "animone.h"
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
10 #include "animone/util/win32.h"
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
11 #include "animone/win.h"
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
12 #include "animone/fd.h"
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
13
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
14 #include <set>
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
15 #include <string>
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
16
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
17 #include <windows.h>
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
18
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
19 namespace animone::internal::win32 {
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
20
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
21 static std::wstring GetWindowClassName(HWND hwnd) {
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
22 static constexpr int kMaxSize = 256;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
23
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
24 std::wstring buffer(kMaxSize, L'\0');
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
25 const auto size = ::GetClassNameW(hwnd, &buffer.front(), buffer.length());
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
26 buffer.resize(size);
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
27 return buffer;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
28 }
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
29
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
30 static std::wstring GetWindowText(HWND hwnd) {
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
31 const auto estimated_size = ::GetWindowTextLengthW(hwnd);
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
32 std::wstring buffer(estimated_size + 1, L'\0');
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
33
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
34 const auto size = ::GetWindowTextW(hwnd, &buffer.front(), buffer.length());
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
35 /* GetWindowTextLength docs:
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
36 * "Under certain conditions, the GetWindowTextLength function may return a value
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
37 * that is larger than the actual length of the text." */
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
38 buffer.resize(size);
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
39 return buffer;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
40 }
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
41
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
42 static DWORD GetWindowProcessId(HWND hwnd) {
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
43 DWORD process_id = 0;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
44 ::GetWindowThreadProcessId(hwnd, &process_id);
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
45 return process_id;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
46 }
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
47
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
48 ////////////////////////////////////////////////////////////////////////////////
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
49
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
50 static bool VerifyWindowStyle(HWND hwnd) {
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
51 const auto window_style = ::GetWindowLong(hwnd, GWL_STYLE);
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
52 const auto window_ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
53
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
54 auto has_style = [&window_style](DWORD style) { return (window_style & style) != 0; };
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
55 auto has_ex_style = [&window_ex_style](DWORD ex_style) { return (window_ex_style & ex_style) != 0; };
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
56
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
57 // Toolbars, tooltips and similar topmost windows
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
58 if (has_style(WS_POPUP) && has_ex_style(WS_EX_TOOLWINDOW))
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
59 return false;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
60 if (has_ex_style(WS_EX_TOPMOST) && has_ex_style(WS_EX_TOOLWINDOW))
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
61 return false;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
62
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
63 return true;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
64 }
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
65
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
66 static bool VerifyClassName(const std::wstring& name) {
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
67 static const std::set<std::wstring> invalid_names = {
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
68 // System classes
21
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
69 "#32770", // Dialog box
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
70 "CabinetWClass", // Windows Explorer
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
71 "ComboLBox",
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
72 "DDEMLEvent",
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
73 "DDEMLMom",
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
74 "DirectUIHWND",
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
75 "GDI+ Hook Window Class",
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
76 "IME",
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
77 "Internet Explorer_Hidden",
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
78 "MSCTFIME UI",
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
79 "tooltips_class32",
14
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
80 };
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
81
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
82 return !name.empty() && !invalid_names.count(name);
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
83 }
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
84
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
85 ////////////////////////////////////////////////////////////////////////////////
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
86
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
87 static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM param) {
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
88 if (!::IsWindowVisible(hwnd))
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
89 return TRUE;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
90
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
91 if (!VerifyWindowStyle(hwnd))
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
92 return TRUE;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
93
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
94 Window window;
21
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
95 window.platform = WindowPlatform::Win32;
14
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
96 window.id = static_cast<unsigned int>(reinterpret_cast<ULONG_PTR>(hwnd));
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
97 window.text = ToUtf8String(GetWindowText(hwnd));
21
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
98 window.class_name = ToUtf8String(GetWindowClassName(hwnd));
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
99 if (!VerifyClassName(window.class_name))
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
100 return TRUE;
14
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
101
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
102 Process process;
21
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
103 process.platform = ExecutablePlatform::Win32;
14
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
104 process.pid = GetWindowProcessId(hwnd);
21
973734ebd2be dep/animone: REFACTOR ALL THE THINGS
Paper <paper@paper.us.eu.org>
parents: 14
diff changeset
105 GetProcessName(process.pid, process.comm);
14
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
106
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
107 auto& window_proc = *reinterpret_cast<window_proc_t*>(param);
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
108 if (!window_proc(process, window))
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
109 return FALSE;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
110
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
111 return TRUE;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
112 }
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
113
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
114 bool EnumerateWindows(window_proc_t window_proc) {
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
115 if (!window_proc)
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
116 return false;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
117
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
118 const auto param = reinterpret_cast<LPARAM>(&window_proc);
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
119
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
120 // Note that EnumWindows enumerates only top-level windows of desktop apps
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
121 // (as opposed to UWP apps) on Windows 8 and above.
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
122 return ::EnumWindows(EnumWindowsProc, param) != FALSE;
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
123 }
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
124
27b988a1048c *: convert all files CRLF -> LF
Paper <paper@paper.us.eu.org>
parents: 3
diff changeset
125 } // namespace animone::internal::win32