|
2 | 2 | #include <memory> |
3 | 3 | #include <optional> |
4 | 4 | #include <vector> |
| 5 | +#include <iostream> |
5 | 6 | #include "../../foundation/id_allocator.h" |
6 | 7 | #include "../../image.h" |
7 | 8 | #include "../../menu.h" |
@@ -85,6 +86,71 @@ std::pair<UINT, UINT> ConvertAccelerator( |
85 | 86 | return std::make_pair(key, modifiers); |
86 | 87 | } |
87 | 88 |
|
| 89 | +// Helper function to get the main window for the current thread |
| 90 | +HWND GetMainWindowForCurrentThread() { |
| 91 | + static HWND main_window = nullptr; |
| 92 | + |
| 93 | + // First try to get the foreground window |
| 94 | + HWND hwnd = nullptr; |
| 95 | + |
| 96 | + |
| 97 | + // Use EnumWindows to find the main window |
| 98 | + struct EnumData { |
| 99 | + HWND main_window; |
| 100 | + DWORD current_thread_id; |
| 101 | + }; |
| 102 | + |
| 103 | + EnumData data = {nullptr, GetCurrentThreadId()}; |
| 104 | + |
| 105 | + EnumWindows( |
| 106 | + [](HWND hwnd, LPARAM lParam) -> BOOL { |
| 107 | + EnumData* data = reinterpret_cast<EnumData*>(lParam); |
| 108 | + |
| 109 | + // Check if window belongs to current thread |
| 110 | + DWORD window_thread_id = GetWindowThreadProcessId(hwnd, nullptr); |
| 111 | + if (window_thread_id != data->current_thread_id) { |
| 112 | + return TRUE; // Continue enumeration |
| 113 | + } |
| 114 | + |
| 115 | + // Check if window is visible and not a tool window |
| 116 | + if (!IsWindowVisible(hwnd)) { |
| 117 | + return TRUE; // Continue enumeration |
| 118 | + } |
| 119 | + |
| 120 | + // Skip tool windows |
| 121 | + if (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) { |
| 122 | + return TRUE; // Continue enumeration |
| 123 | + } |
| 124 | + |
| 125 | + // Skip message-only windows |
| 126 | + if (hwnd == HWND_MESSAGE) { |
| 127 | + return TRUE; // Continue enumeration |
| 128 | + } |
| 129 | + |
| 130 | + // Check if it's a main window (has a title bar, not a child window) |
| 131 | + if (GetParent(hwnd) != nullptr) { |
| 132 | + return TRUE; // Continue enumeration |
| 133 | + } |
| 134 | + |
| 135 | + // Found a candidate main window |
| 136 | + data->main_window = hwnd; |
| 137 | + return FALSE; // Stop enumeration |
| 138 | + }, |
| 139 | + reinterpret_cast<LPARAM>(&data)); |
| 140 | + |
| 141 | + if (data.main_window) { |
| 142 | + return data.main_window; |
| 143 | + } |
| 144 | + |
| 145 | + // Fallback: try to find any top-level window |
| 146 | + hwnd = FindWindow(nullptr, nullptr); |
| 147 | + if (hwnd && IsWindow(hwnd)) { |
| 148 | + return hwnd; |
| 149 | + } |
| 150 | + |
| 151 | + return nullptr; |
| 152 | +} |
| 153 | + |
88 | 154 | } // namespace nativeapi |
89 | 155 |
|
90 | 156 | namespace nativeapi { |
@@ -485,17 +551,8 @@ bool Menu::Open(double x, double y) { |
485 | 551 | pimpl_->visible_ = true; |
486 | 552 |
|
487 | 553 | POINT pt = {static_cast<int>(x), static_cast<int>(y)}; |
488 | | - // Try to get the foreground window first |
489 | | - HWND hwnd = GetForegroundWindow(); |
490 | | - if (!hwnd) { |
491 | | - hwnd = GetActiveWindow(); |
492 | | - return hwnd; |
493 | | - } |
494 | | - |
495 | | - // If still no window, try to find any top-level window |
496 | | - if (!hwnd) { |
497 | | - hwnd = FindWindow(nullptr, nullptr); |
498 | | - } |
| 554 | + // Use the helper function to get the main window for current thread |
| 555 | + HWND hwnd = GetMainWindowForCurrentThread(); |
499 | 556 |
|
500 | 557 | // Show the context menu |
501 | 558 | TrackPopupMenu(pimpl_->hmenu_, TPM_BOTTOMALIGN | TPM_LEFTALIGN, pt.x, pt.y, 0, |
|
0 commit comments