Mercurial > minori
view dep/animone/src/win/win32.cc @ 342:adb79bdde329
dep/animone: fix tons of issues
for example, the window ID stuff was just... completely wrong. since we're
supporting multiple different window systems, it *has* to be a union rather
than just a single integer type. HWND is also not a DWORD, it's a pointer(!),
so now it's stored as a std::uintptr_t.
(this probably breaks things)
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Thu, 20 Jun 2024 03:03:05 -0400 |
parents | a7d4e5107531 |
children |
line wrap: on
line source
/* * win/win32.cc: support for Windows * * Surprisingly, this is the one time where Microsoft actually * does it fairly OK. Everything has a pretty simple API, despite * the stupid wide string stuff. */ #include "animone/win/win32.h" #include "animone.h" #include "animone/util/win32.h" #include "animone/win.h" #include "animone/fd.h" #include <set> #include <string> #include <windows.h> namespace animone::internal::win32 { static std::wstring GetWindowClassName(HWND hwnd) { static constexpr int kMaxSize = 256; std::wstring buffer(kMaxSize, L'\0'); const auto size = ::GetClassNameW(hwnd, &buffer.front(), buffer.length()); buffer.resize(size); return buffer; } static std::wstring GetWindowText(HWND hwnd) { const auto estimated_size = ::GetWindowTextLengthW(hwnd); std::wstring buffer(estimated_size + 1, L'\0'); const auto size = ::GetWindowTextW(hwnd, &buffer.front(), buffer.length()); /* GetWindowTextLength docs: * "Under certain conditions, the GetWindowTextLength function may return a value * that is larger than the actual length of the text." */ buffer.resize(size); return buffer; } static DWORD GetWindowProcessId(HWND hwnd) { DWORD process_id = 0; ::GetWindowThreadProcessId(hwnd, &process_id); return process_id; } //////////////////////////////////////////////////////////////////////////////// static bool VerifyWindowStyle(HWND hwnd) { const auto window_style = ::GetWindowLong(hwnd, GWL_STYLE); const auto window_ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE); auto has_style = [&window_style](DWORD style) { return (window_style & style) != 0; }; auto has_ex_style = [&window_ex_style](DWORD ex_style) { return (window_ex_style & ex_style) != 0; }; // Toolbars, tooltips and similar topmost windows if (has_style(WS_POPUP) && has_ex_style(WS_EX_TOOLWINDOW)) return false; if (has_ex_style(WS_EX_TOPMOST) && has_ex_style(WS_EX_TOOLWINDOW)) return false; return true; } static bool VerifyClassName(const std::string& name) { static const std::set<std::string> invalid_names = { // System classes "#32770", // Dialog box "CabinetWClass", // Windows Explorer "ComboLBox", "DDEMLEvent", "DDEMLMom", "DirectUIHWND", "GDI+ Hook Window Class", "IME", "Internet Explorer_Hidden", "MSCTFIME UI", "tooltips_class32", }; return !name.empty() && !invalid_names.count(name); } //////////////////////////////////////////////////////////////////////////////// static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM param) { if (!::IsWindowVisible(hwnd)) return TRUE; if (!VerifyWindowStyle(hwnd)) return TRUE; Window window; window.platform = WindowPlatform::Win32; window.id.win32 = reinterpret_cast<std::uintptr_t>(hwnd); window.text = ToUtf8String(GetWindowText(hwnd)); window.class_name = ToUtf8String(GetWindowClassName(hwnd)); if (!VerifyClassName(window.class_name)) return TRUE; Process process; process.platform = ExecutablePlatform::Win32; process.pid = GetWindowProcessId(hwnd); GetProcessName(process.pid, process.comm); auto& window_proc = *reinterpret_cast<window_proc_t*>(param); if (!window_proc(process, window)) return FALSE; return TRUE; } bool EnumerateWindows(window_proc_t window_proc) { if (!window_proc) return false; const auto param = reinterpret_cast<LPARAM>(&window_proc); // Note that EnumWindows enumerates only top-level windows of desktop apps // (as opposed to UWP apps) on Windows 8 and above. return ::EnumWindows(EnumWindowsProc, param) != FALSE; } } // namespace animone::internal::win32