Mercurial > libanimone
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 |
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 |