Skip to content

Commit

Permalink
(NT-77) Improve focus window implementation on Windows to deal with f… (
Browse files Browse the repository at this point in the history
#178)

* (NT-77) Improve focus window implementation on Windows to deal with focus stealing countermeasures on Windows

* (NT-77) Adjust focus test
  • Loading branch information
s1hofmann authored Mar 18, 2024
1 parent d376d4f commit 19b4665
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 18 deletions.
42 changes: 24 additions & 18 deletions src/win32/window_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ std::vector<WindowHandle> getWindows() {
}

WindowHandle getActiveWindow() {
HWND foregroundWindow = GetForegroundWindow();
auto foregroundWindow = GetForegroundWindow();
if (IsWindow(foregroundWindow)) {
return reinterpret_cast<WindowHandle>(foregroundWindow);
}
return -1;
}

MMRect getWindowRect(const WindowHandle windowHandle) {
HWND hWnd = reinterpret_cast<HWND>(windowHandle);
auto hWnd = reinterpret_cast<HWND>(windowHandle);
RECT windowRect;
if (IsWindow(hWnd) && GetWindowRect(hWnd, &windowRect)) {
return MMRectMake(windowRect.left, windowRect.top, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);
Expand All @@ -39,65 +39,71 @@ MMRect getWindowRect(const WindowHandle windowHandle) {
}

std::string getWindowTitle(const WindowHandle windowHandle) {
HWND hWnd = reinterpret_cast<HWND>(windowHandle);
auto hWnd = reinterpret_cast<HWND>(windowHandle);
if (IsWindow(hWnd)) {
auto BUFFER_SIZE = GetWindowTextLength(hWnd) + 1;
if (BUFFER_SIZE) {
LPSTR windowTitle = new CHAR[BUFFER_SIZE];
auto windowTitle = new CHAR[BUFFER_SIZE];
if (GetWindowText(hWnd, windowTitle, BUFFER_SIZE)) {
return std::string(windowTitle);
return {windowTitle};
}
}
}
return "";
}

bool focusWindow(const WindowHandle windowHandle) {
HWND hWnd = reinterpret_cast<HWND>(windowHandle);
auto hWnd = reinterpret_cast<HWND>(windowHandle);
if (IsWindow(hWnd)) {
// Restore the window if it's minimized
if (IsIconic(hWnd)) {
ShowWindow(hWnd, SW_RESTORE);
}


auto processId = GetCurrentProcessId();
// const auto allowSetForeground = AllowSetForegroundWindow(ASFW_ANY);
const auto allowSetForeground = AllowSetForegroundWindow(processId);
const auto setTopLevel = BringWindowToTop(hWnd);
const auto setForeground = SetForegroundWindow(hWnd);

// Try to set the window to the foreground
return SetForegroundWindow(hWnd);
return allowSetForeground && setTopLevel && setForeground;
}
return false;
}

bool resizeWindow(const WindowHandle windowHandle, const MMSize newSize) {
HWND hWnd = reinterpret_cast<HWND>(windowHandle);
auto hWnd = reinterpret_cast<HWND>(windowHandle);
if (IsWindow(hWnd)) {
//size
auto width = newSize.width;
auto height = newSize.height;
const auto width = newSize.width;
const auto height = newSize.height;

RECT currentPosition;
GetWindowRect(reinterpret_cast<HWND>(windowHandle), &currentPosition);

//origin
auto x = currentPosition.left;
auto y = currentPosition.top;
const auto x = currentPosition.left;
const auto y = currentPosition.top;

return MoveWindow(hWnd, x, y, width, height, TRUE);
}
return false;
}

bool moveWindow(const WindowHandle windowHandle, const MMPoint newOrigin) {
HWND hWnd = reinterpret_cast<HWND>(windowHandle);
auto hWnd = reinterpret_cast<HWND>(windowHandle);
if (IsWindow(hWnd)) {
// origin
auto x = newOrigin.x;
auto y = newOrigin.y;
const auto x = newOrigin.x;
const auto y = newOrigin.y;

RECT currentPosition;
GetWindowRect(reinterpret_cast<HWND>(windowHandle), &currentPosition);

// size
auto width = currentPosition.right - currentPosition.left;
auto height = currentPosition.bottom - currentPosition.top;
const auto width = currentPosition.right - currentPosition.left;
const auto height = currentPosition.bottom - currentPosition.top;

return MoveWindow(hWnd, x, y, width, height, TRUE);
}
Expand Down
8 changes: 8 additions & 0 deletions test/window-integration-tests/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,18 @@ describe("focusWindow", () => {
// WHEN
const secondApp = await electron.launch({args: ['second.js']});
const secondPage = await secondApp.firstWindow({timeout: APP_TIMEOUT});
const handle = await secondApp.browserWindow(secondPage);
await secondPage.waitForLoadState("domcontentloaded");
await handle.evaluate((win) => {
win.minimize();
win.restore();
win.focus();
});

const result = libnut.focusWindow(openWindowHandle);

// THEN
await sleep(1500);
const activeWindowHandle = libnut.getActiveWindow();
const activeWindowName = libnut.getWindowTitle(activeWindowHandle);
expect(activeWindowName).toBe(TITLE);
Expand Down

0 comments on commit 19b4665

Please sign in to comment.