Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows 10: Window is not put to front on focus() #2867

Closed
bpasero opened this issue Sep 22, 2015 · 72 comments
Closed

Windows 10: Window is not put to front on focus() #2867

bpasero opened this issue Sep 22, 2015 · 72 comments

Comments

@bpasero
Copy link
Contributor

bpasero commented Sep 22, 2015

I am hitting an issue where a window (in Windows 10) is not being put to the front when I call focus() on it. The same code brings the window to the front on Windows 8 and below, so something must have changed in Windows 10 with regards to window management.

What I see happening is that the task bar is flashing in orange, so there is some indication. Just the window does not get focussed properly.

@OlsonDev
Copy link

I find it interesting you've had this working at all in the past. I've always found it to be relatively inconsistent due to ForegroundFlashCount and ForegroundLockTimeout; see http://www.thewindowsclub.com/disable-flashing-taskbar-buttons-windows if you're unfamiliar.

@zcbenz
Copy link
Member

zcbenz commented Sep 23, 2015

Under the hood focus() just called SetForegroundWindow API, from the description it only brings window to foreground if the calling process is a foreground process.

From #1954 it seems that Windows 10 starts to treat the renderer process of Chromium as foreground process, and thus the browser process becomes a background process, resulting in SetForegroundWindow not working.

I can probably fix this by calling AllowSetForegroundWindow in the renderer process to allow browser process to set foreground window, but I need to install Windows 10 first.

P.S. @bpasero Is it possible for you to reach the Windows team to verify my assumption? I know Microsoft is HUGE and it is hard to find the right team, but it can help understand the mysterious behaviors.

@bpasero
Copy link
Contributor Author

bpasero commented Sep 23, 2015

@zcbenz I will try to find a contact, meanwhile if you have a change in mind, I can build electron on my windows 10 to verify the fix. Is it possible that this also causes the issue that I cannot set user tasks anymore to the task bar menu of the window?

@anaisbetts
Copy link
Contributor

@bpasero Start at the win32prg alias and go from there

@bpasero
Copy link
Contributor Author

bpasero commented Sep 23, 2015

@paulcbetts ???

@anaisbetts
Copy link
Contributor

@bpasero Open up Outlook and look in the GAL for it :)

@bpasero
Copy link
Contributor Author

bpasero commented Sep 23, 2015

@paulcbetts ah you are talking about an email alias, I was searching electron source code for "win32prg" to fix this myself ;). Yeah I might have some people to ask, might not get back to me until Redmond wakes up though.

@anaisbetts
Copy link
Contributor

Fixing this Properly actually might be not particularly trivial if you have to do it The Hard Way. Basically:

  1. Every time a renderer process gets focus (either pragmatically, or via normal means), it needs to signal the browser process with its window ID.
  2. When someone calls focus, they signal the browser to ask, "Can you tell whoever currently has focus to AllowSetForegroundWindow me?"
  3. Browser has to IPC that renderer, who calls AllowSetForegroundWindow and responds back
  4. Once that completes, the Browser process has to then signal the focus caller and say "Yep you can SetForegroundWindow now"

However, Windows probably has some heuristics around this and there might be a way less involved way to do it (do all processes in a Job share SetForegroundWindow'ability? Maybe!) This is where win32prg comes in, because the people on that list probably built some of this stuff.

@antoinepairet
Copy link
Contributor

@zcbenz if I understand your previous comment correctly, I should be able to bring a window to the foreground only if the call is made a foreground process. Therefore I understand that to have it working:

  • Win 10: the call needs to be made from the renderer process
  • Win 7, Win 8: the call needs to be made from the main process

As far I am concerned (see #3124), the call is made from the renderer process. If my assumptions are correct, I should get this working using windows 10. I will try it and report the result here.

Looking forward to have the feedback from the Windows team :-).
Thanks to everyone involved!

@bpasero
Copy link
Contributor Author

bpasero commented Oct 19, 2015

@antoinepairet is it really possible to make the call from the renderer? My understanding is that the call is just getting proxied, but still executed on the main side.

@antoinepairet
Copy link
Contributor

@bpasero I do not know the internal details of electron. Here is what I do: In the renderer process, I am loading a DLL using node-ffi. Still within the renderer process, I call a function of that DLL which in the end calls ShowWindow.

FYI, NW.js also seem to struggle with similar issues: nwjs/nw.js#3387

@bpasero
Copy link
Contributor Author

bpasero commented Oct 19, 2015

Ah ok that might work, I thought you would go through the official Electron API to focus a window.

@antoinepairet
Copy link
Contributor

We found a bug in our code. Shame on me. :-s.
To recap: from the renderer process, we successfully call showWindow through a DLL through ffi. It works on Win7 and Win8. Not tested under Win10.
Sorry for the confusion.
regards

@bpasero
Copy link
Contributor Author

bpasero commented Oct 28, 2015

@antoinepairet is your node-ffi code somewhere on GitHub? Just curious...

@antoinepairet
Copy link
Contributor

@bpasero Sorry for the late response. It's closed source but if you are interested, we can setup a Skype call or Google Hangout for a quick demo and have a look at the code :-). I am on CEST.

@jorangreef
Copy link

I ran into this today. It's a huge blocker for using BrowserWindow on Windows 10, since if you ever hide a BrowserWindow there is no way to give focus back to it.

@zcbenz have you tried calling AllowSetForegroundWindow in the renderer just to see if it works?

@bpasero have you made any progress within Microsoft?

Would be great to have this fixed.

@bpasero
Copy link
Contributor Author

bpasero commented Nov 4, 2015

After reading #1954 (comment) I have setup the latest Windows insider build and I cannot reproduce the issue anymore. It seems to me that Windows 10 v10565 now behaves again like Windows 8 in terms of Windows and SetForegroundWindow. To verify this assumption I have send a mail on win32prg.

@bpasero
Copy link
Contributor Author

bpasero commented Nov 5, 2015

Ok more insights: There is in fact no difference between the stable Win 10 and the insiders release. However there is a difference with how window.focus() works depending on wether the window is minimized or not. I was likely testing it with a minimized window in the one build and non-minimized in the other.

If I call window.minimize() right before window.focus(), I can get the window to the foreground no matter what on Windows 10.

@jorangreef
Copy link

Thanks @bpasero

@bpasero
Copy link
Contributor Author

bpasero commented Nov 6, 2015

@zcbenz would it actually be possible to call SetForegroundWindow from the renderer process without going through the main process? win32prg agrees that the workaround in #2867 (comment) is ugly and if you can call SetAllowForegroundWindow from the renderer you might as well just call SetForegroundWindow directly.

@zcbenz
Copy link
Member

zcbenz commented Nov 6, 2015

@bpasero We can probably pass the window handle to renderer process and call SetForegroundWindow there whenever BrowserWindow.focus is called.

@bpasero
Copy link
Contributor Author

bpasero commented Nov 6, 2015

@zcbenz I can look into that and verify the solution if you could send me pointers how to wire that up.

@zcbenz
Copy link
Member

zcbenz commented Nov 6, 2015

@bpasero You can references how WebContents::ExecuteJavaScript or WebContents::EnableDeviceEmulation is implemented to have an idea of how to send the handle to renderer process, it can be put under NativeWindowViews::Focus.

@bpasero
Copy link
Contributor Author

bpasero commented Nov 9, 2015

@zcbenz any clue if/how it is possible to get a hold of the renderer window's HWND from the renderer side?

@zcbenz
Copy link
Member

zcbenz commented Nov 9, 2015

@bpasero You can send a synchronous message to the main process to get it, an example is the SendSync API.

@jwheare
Copy link
Contributor

jwheare commented May 17, 2019

It doesn't fix it. My workaround is to have an event triggered in the webapp on notification click and then use this monstrosity to trigger a focus in the electron side:

https://github.com/irccloud/irccloud-desktop/blob/694923a20efd42bcc09943c8167c8fcffb3f0a01/app/render/notification.js#L4-L9

@codebytere codebytere self-assigned this May 17, 2019
@nehbit
Copy link

nehbit commented Aug 6, 2019

Another vote for this. We're facing this issue as well with our Electron app.

@NathanHawks
Copy link

NathanHawks commented Jan 3, 2020

Contrary to a report earlier in this thread, the issue does exist on Windows 8.1.

@elliottzheng
Copy link

elliottzheng commented Jun 20, 2020

Thanks to @robinwassen, https://www.npmjs.com/package/@adeperio/forcefocus this works for me with electron 8 and node 12.

@ericblade
Copy link

ericblade commented Oct 21, 2020

... for what it's worth, it should probably be in the documentation that BrowserWindow.show() is effectively non-functional for single window applications when running in Windows. BrowserWindow.show() will bring a window to the front only if it shares (X,Y) screenspace with another window from the same application that already has foreground

@rmuchall
Copy link

rmuchall commented Feb 8, 2021

This should probably be re-opened as there are definitely issues surrounding focus under Windows.
The comment below solved the problem for me without requiring any third party dependencies:
#9291 (comment)

EDIT: Here is the version I use

showWindow(): void {
        this.mainWindow?.setAlwaysOnTop(true);
        if (this.isMaximized) {
            this.mainWindow?.maximize();
        } else {
            this.mainWindow?.showInactive();
        }

        this.mainWindow?.setAlwaysOnTop(false);
        this.mainWindow?.focus();
        app.focus({
            steal: true
        });
    }

@pushkin-
Copy link

pushkin- commented Feb 8, 2021

@bpasero You say above:

If I call window.minimize() right before window.focus(), I can get the window to the foreground no matter what on Windows 10.

And later:

We are not using that hack anymore, it never really worked and can cause some serious issues with OS windows manager

This trick seems to work for me. What issues were you running into that made you stop using it?

@ericblade
Copy link

ericblade commented Feb 8, 2021

@rmuchall 's version seems to work pretty well in Windows at least, better than any other method i've found so far, however, the keyboard focus is not being forced into the window. That might actually be preferable for my application, but it's directly in contradiction of what the code seems to indicate it should do :-)

... though, after using it for a while, there is an odd flicker of the window occasionally that i can't yet explain

... scratch that, it doesn't work 100% reliably when other windows are in front of it, still only works 100% when another window from the same app is already in the fore.

@ericblade
Copy link

@bpasero You say above:

If I call window.minimize() right before window.focus(), I can get the window to the foreground no matter what on Windows 10.

And later:

We are not using that hack anymore, it never really worked and can cause some serious issues with OS windows manager

This trick seems to work for me. What issues were you running into that made you stop using it?

I can say for sure that messing with the minimized state definitely does weird things with the state of windows that are positioned using Aero-Snap in Windows.

@rmuchall
Copy link

rmuchall commented Feb 8, 2021

... though, after using it for a while, there is an odd flicker of the window occasionally that i can't yet explain

... scratch that, it doesn't work 100% reliably when other windows are in front of it, still only works 100% when another window from the same app is already in the fore.

Hi @ericblade ,
Weird, I'm not seeing the issues you describe above. My app uses a single BrowserWindow. I'm not sure if that would make any difference. I'll try putting together a minimal repository. Are you seeing those issues in Windows 10?

@ericblade
Copy link

@rmuchall yeah, i can pretty consistently defeat it coming foreground if I have Visual Studio Code or Vivaldi maximized. It does work better/more consistently than most of the other solutions that don't involve native plugins, though. The flashing seems to be some other window in the application coming forward briefly before the correct one does. It may have to do with that my application has many windows... which is part of why i want to bring forward specific ones..

i'm presently using a native node module called 'forcefocus', but it has pretty awful drawbacks, too.. namely it screws up keyboard input.

@rmuchall
Copy link

rmuchall commented Feb 8, 2021

@ericblade
Thanks for the info! :)
I've created a minimal repository. If possible, please could you check if it has the same issues that you listed above?
https://github.com/rmuchall/electron-focus

@ciriousjoker
Copy link

From a user's perspective, this is terrible.
If an Electron window tries to get focus and doesn't get it due to this issue, Windows tries to make the taskbar flash.
However, if I understood it correctly, this bug causes the renderer process to get focus which isn't possible, resulting in nothing flashing.
However, the taskbar still won't close (I have it set to auto-hide).
I then have to cycle through all Electron windows (Spotify, Discord etc.) until I found the window that tried to grab focus...

Please consider fixing this issue if the behavior is caused by this issue.

@ericblade
Copy link

ericblade commented Jul 23, 2021

@ciriousjoker that doesn't sound related

unfortunately, the TLDR on this thread is -- there's not really anything to fix. Windows (the product)' window management features don't explicitly allow this to occur, and pretty much every way around it is garbage, so the best thing to do if you need to foreground windows explicitly, over the top of other applications, is to determine which workaround you can most live with the drawbacks of.

@liuyike98
Copy link

While we wait for a fix, sharing the code I used to work around the issue:

//This is how I show the window win.setAlwaysOnTop(true); win.show(); win.setAlwaysOnTop(false);

//But the window is not focused, even if I call win.focus(). The below did the trick app.focus();

Not the best solution, but at least solved my problem meanwhile...

that's so fanny, 2021 now, still has the problem, and your method still works

@gkourpa
Copy link

gkourpa commented Jan 12, 2022

I discovered that if you first minimize and then restore the win object, you can successfully bring it to the foreground, above all the other windows. The following did the work for me on Windows 10.

if (!win.isFocused()) {
  win.minimize();
  win.restore();
  win.focus();
}

@kreativhut
Copy link

kreativhut commented Feb 16, 2022

Take a look into BrowserWindow.moveTop(). Brings the window above all the other windows. Did the work for me.

@darklightblue
Copy link

2022, minimize then focus no longer works (at least for me). What liuyike98 suggested however still works:

  ipcMain.on('foreground', () => {
    mainWindow?.setAlwaysOnTop(true);
    mainWindow?.show();
    mainWindow?.setAlwaysOnTop(false);
  });

For some reason the app.focus(); doesnt't work for me tho, but I guess this is better than having your app behind the browser/other apps.

@skident
Copy link

skident commented Jun 7, 2023

@darklightblue, your example of setAlwaysOnTop(true/false) has a bad side-effect on Windows 11. Once, you close the app window, OS will bring to front one or two non-related windows (for instance, you had opened a notepad, a browser and other applications, so then one of those windows will be pushed to foreground).

@sinamotamedi
Copy link

The workaround of calling window.minimize() first works for Windows but on Mac it makes the app launch minimized to the dock.

window.minimize();
window.show();

Instead, using window.setAlwaysOnTop() seems to work for both platforms.

window.show();
window.setAlwaysOnTop(true);
window.setAlwaysOnTop(false);

It's worth noting that we observed this issue only happens when we construct the BrowserWindow object with show: false. If we do new BrowserWindow({ show: true }) then the app launches in the foreground. It's only when we do new BrowserWindow({ show: false }) and later call window.show() that we encounter this problem. We do the latter so we can wait for the page to be loaded before displaying the app to the user.

Not sure why this issue is unresolved after 8 years and this thread is closed. At a minimum, the Electron docs should be updated.

@TreeOfAlpha
Copy link

TreeOfAlpha commented Aug 21, 2023

After having to fight with this issue for most of the day yesterday none of the solutions here were acceptable.
The closest one was @robinwassen's "forcefocus", but it messes with keyboard input and that is a dealbreaker for my use case.

I ended up adopting a very hacky but functional workaround.
Bottom line is: Windows only cares that the user is actually doing something at the time of showing the window, so the easiest and most stable fix is to emulate keyboard/mouse input at the time.

I used RobotJS and tried several keyboard/mouse input combinations including "alt" and "shift", but the most stable, smooth and least harmful for the user ended up being a simple mouse click release.

const robot = require('robotjs');

robot.mouseToggle("up");
win.show();
win.focus();

Combined with electron-rebuild, this offered a smooth alternative to Windows' stubbornness and I hope this can help someone out.

undergroundwires added a commit to undergroundwires/privacy.sexy that referenced this issue May 3, 2024
This commit updates the application startup behavior to prevent showing
a blank window until it's fully loaded on all platforms. This enhancement
improves the user experience by ensuring the UI only becomes visible
when it is ready to interact with.

This fix contributes to a smoother user experience by aligning the
window display timing with content readiness, thus avoiding the brief
display of an empty screen.

Changes:

- Set window to initially hide until fully loaded using the
  `ready-to-show` event.
- Show the window, focus on it and bring it front once it is loaded.
  Windows requires additional logic to put Window to front, see
  electron/electron#2867.
- Parametrize the behavior of opening developer tools for easier
  configuration during testing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests