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

Mac: "Launching" app when it's already open doesn't put it in foreground #2616

Closed
mherrmann opened this Issue May 19, 2017 · 7 comments

Comments

Projects
None yet
2 participants
@mherrmann
Contributor

mherrmann commented May 19, 2017

On macOS, launching applications when they are already open puts them in the foreground. For instance:

open -a TextEdit
# TextEdit opened. Leave it open. Switch back to the terminal and type again:
open -a TextEdit
# TextEdit is again in the foreground, Terminal in the background.

This also works with apps built with py2app:

git clone https://github.com/adamw523/simple_pyobjc_cocoa_xib
cd simple_pyobjc_cocoa_xib
virtualenv --system-site-packages venv
source venv/bin/activate
python setup.py py2app -A
ln -s "`pwd`/dist/SimpleXibDemo.app" /Applications/SimpleXibDemo.app

open -a SimpleXibDemo
open -a SimpleXibDemo

But it doesn't work with apps built with PyInstaller. Proceeding from the above command line:

# Preserve the .nib file compiled by py2app:
cp dist/SimpleXibDemo.app/Contents/Resources/SimpleXibDemo.nib .

rm -rf build/ dist/

# Build with PyInstaller
pip install https://github.com/pyinstaller/pyinstaller/archive/develop.zip
pyinstaller --name SimpleXibDemo --windowed SimpleXibDemo.py
cp SimpleXibDemo.nib dist/SimpleXibDemo.app/Contents/Resources/

# Run:
open -a SimpleXibDemo
# SimpleXibDemo is in the foreground. Go back to terminal and type:
open -a SimpleXibDemo
# SimpleXibDemo should be in foreground but isn't.

I am encountering exactly the same problem with a PyQt5 app I'm working on. So the problem is not specific to PyObjC.

@mherrmann

This comment has been minimized.

Contributor

mherrmann commented May 19, 2017

Without knowing PyInstaller well enough, I suspect it is because of the way it launches. When starting an app built with PyInstaller, it spawns a new process:

image

I am guessing the parent process (19285) sets up the environment, and the child process does the actual GUI display. I suspect that macOS only "sees" the parent process, thinks it doesn't have a GUI and is thus unable to "switch to it".

Or, it could be caused by the parent process "Not Responding" in the screenshot.

@ghost

This comment has been minimized.

ghost commented May 19, 2017

PyInstaller already uses a single process for windows. I'm not sure what py2app does, but if you're familiar with C, then you could look at changing this for mac. This additional complexity comes from --onefile, but it shouldn't affect --onedir.

@tallforasmurf

This comment has been minimized.

Contributor

tallforasmurf commented May 19, 2017

Possibly relevant: pyi_parent_to_background called by bootloader in the child process.

@mherrmann

This comment has been minimized.

Contributor

mherrmann commented May 20, 2017

So @xoviat do you think the problem could be solved by simply moving the #ifdef _WIN32 you linked to 7 lines down?

@ghost

This comment has been minimized.

ghost commented May 20, 2017

You could try changing it to #ifdef _WIN32 || __APPLE__, but I strongly suspect that's not the only change required. This really needs to be changed, but I think that as soon as you change that, some other problems will appear, which will need to be fixed as well. If you're familiar with C and osx, then it might take a few hours to fix these problems, but if you're not, then it could take significantly longer. I cannot do anything more on this problem than make some recommendations because I don't have access to osx, which means that it's not going to be possible for me to resolve these issues.

@mherrmann

This comment has been minimized.

Contributor

mherrmann commented May 21, 2017

Amazing. That works!

#if defined(_WIN32) || defined(__APPLE__)

My app runs perfectly fine with this change - and the "not coming to foreground" issue is fixed. I'll create a PR to get this merged (or at least reviewed) by PyInstaller. Thanks @xoviat!

@ghost

This comment has been minimized.

ghost commented May 21, 2017

Wow! I did not expect it to be that easy!

htgoebel added a commit that referenced this issue Jul 25, 2017

Bootloader: Use single process on Mac for --onedir mode.
On Mac, launching an application that's already open puts it in the
foreground. This didn't work for apps built with PyInstaller because
of the parent -> subprocess structure at runtime. The present commit
fixes the problem for --onedir mode by using a single process.

Closes #2616.

cowo78 pushed a commit to cowo78/pyinstaller that referenced this issue Dec 7, 2018

Bootloader: Use single process on Mac for --onedir mode.
On Mac, launching an application that's already open puts it in the
foreground. This didn't work for apps built with PyInstaller because
of the parent -> subprocess structure at runtime. The present commit
fixes the problem for --onedir mode by using a single process.

Closes pyinstaller#2616.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment