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

WIP, ENH: Automatic theme switching on macOS #10655

Closed
wants to merge 7 commits into from

Conversation

GuillaumeFavelier
Copy link
Contributor

This PR comes from #10565 (comment) and adds support for automatic theme switching on macOS. It is a draft until it has been tested on macOS.

How to test?

On a macOS machine, plot any 3d figure (alignment, stc, coreg, ...etc) then switch the system theme.

Expected result

The window, the widgets and the icons should follow the new theme.


Closes #9182

@GuillaumeFavelier GuillaumeFavelier self-assigned this May 20, 2022
@hoechenberger
Copy link
Member

Related:
Yesterday's release of darkdetect allows automatic theme switching detection on Windows and Linux:

https://github.com/albertosottile/darkdetect/releases/tag/v0.6.0

@cbrnr
Copy link
Contributor

cbrnr commented May 23, 2022

Yesterday's release of darkdetect allows automatic theme switching detection on Windows and Linux:

👀 – this is great! But Qt application still don't change to dark (native look) on Windows and Linux unless stylesheets are used, right?

@hoechenberger
Copy link
Member

But Qt application still don't change to dark (native look) on Windows and Linux unless stylesheets are used, right?

I'm afraid so

@GuillaumeFavelier GuillaumeFavelier marked this pull request as ready for review May 24, 2022 09:18
@GuillaumeFavelier
Copy link
Contributor Author

automatic theme switching detection on Windows and Linux:

Too bad it's only for Windows and Linux, it would be nice to use the same approach for all systems if possible.
I looked at the code for the linux part, is it only for Gnome desktop? Anyway, I'll give it a try locally, thanks for the heads-up 👍

@cbrnr
Copy link
Contributor

cbrnr commented May 24, 2022

Detection/switching on macOS has worked for a long time I thought? And yes, it seems to be GNOME-specific.

@hoechenberger
Copy link
Member

Detection/switching on macOS has worked for a long time I thought? And yes, it seems to be GNOME-specific.

I suppose this PR is about switching without restarting the app.

@cbrnr
Copy link
Contributor

cbrnr commented May 24, 2022

This has worked on macOS for years.

@hoechenberger
Copy link
Member

This has worked on macOS for years.

But not with Qt out of the box…

@hoechenberger
Copy link
Member

This has worked on macOS for years.

But not with Qt out of the box…

MWE:

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
import sys

class PushButton(QWidget):
    def __init__(self):
        super(PushButton,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("PushButton")
        self.setGeometry(400,400,300,260)
        self.closeButton = QPushButton(self)
        self.closeButton.setText("Close")
        self.closeButton.clicked.connect(self.close)
        self.closeButton.move(100,100)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = PushButton()
    ex.show()
    sys.exit(app.exec_())

Switching between light and dark only affects the title bar:

Screen.Recording.2022-05-24.at.11.47.11.mov

@cbrnr
Copy link
Contributor

cbrnr commented May 24, 2022

Works for me. I've used this for years with MNELAB. macOS is the only platform where this works, Windows and Linux require a workaround (e.g. with a listener thread constantly polling for the theme).

mwe.mov

@hoechenberger
Copy link
Member

Son of a gun, you're right – seems the only reason it didn't work for me here is because I used an x86 Python install on my M1 Mac. With a native arm64 build, it works as in your video.

@GuillaumeFavelier
Copy link
Contributor Author

GuillaumeFavelier commented May 24, 2022

Well in your case, you use the default 'dark style' macOS palette but this PR is about applying the one from qdarkstyle :)

@GuillaumeFavelier
Copy link
Contributor Author

GuillaumeFavelier commented May 24, 2022

darkdetect offers to detect theme change on Windows and Linux with their new listener but this PR relies on Qt PaletteChange event for that on macOS. That's why I say:

it would be nice to use the same approach for all systems if possible.

@GuillaumeFavelier
Copy link
Contributor Author

There is also the option to use the darkdetect+qdarkstyle combination only on Windows and Linux (the operating systems that do not change the Qt palette automatically) and just update the icon theme when necessary for macOS, similarly to mnelab.

@cbrnr
Copy link
Contributor

cbrnr commented May 24, 2022

To me, it works as it should only on macOS. It would be great if Qt added support for theme changes on Windows and Linux via the PaletteChange event as well. I prefer native look and feel over styled widgets.

@GuillaumeFavelier
Copy link
Contributor Author

It would be great if Qt added support for theme changes on Windows and Linux via the PaletteChange event as well.

I agree, anything consistent across the main OSes/desktops would be great. But it seems that darkdetect tries to fill the gap 👍

@cbrnr
Copy link
Contributor

cbrnr commented May 24, 2022

I agree, anything consistent across the main OSes/desktops would be great. But it seems that darkdetect tries to fill the gap 👍

Yep! Not only something consistent, but Qt should support native light/dark modes on Windows and Linux too. On Windows and Linux the app needs to use stylesheets, which doesn't look like native apps.

@hoechenberger
Copy link
Member

hoechenberger commented May 24, 2022

There is also the option to use the darkdetect+qdarkstyle combination only on Windows and Linux (the operating systems that do not change the Qt palette automatically) and just update the icon theme when necessary for macOS, similarly to mnelab.

Yes I would love that, but @larsoner was opposed. I don't think our custom dark theme looks native on macOS. It feels a little strange.

But let's address this in a different issue or PR

@GuillaumeFavelier
Copy link
Contributor Author

GuillaumeFavelier commented May 24, 2022

Okay, I did not remember all the details of the discussion back then.

Does the PR work in its current state by the way, anybody tried?

@larsoner
Copy link
Member

Yes I would love that, but @larsoner was opposed. I don't think our custom dark theme looks native on macOS. It feels a little strange.

I don't remember why I was opposed -- but in any case, currently qdarkstyle isn't really used on macOS for dark stylesheets when in dark mode, at least on PyQt6 where dark theming is correct. And I think for PyQt5 it overrides as little as possible already. So in any case, +1 for using native light/dark styling where they actually work from me.

There are cases where I think we can't get around using qdarkstyle, though, like when you ask for dark theme but your system is currently in light mode. Maybe this is what you're thinking of experiencing @hoechenberger ?

As an aside, I looked for quite some time to see if there is a way to tell Qt "even though my system is in light mode, use the native dark mode Qt styling" but I couldn't find a way to do it. They don't just apply an internal stylesheet to do it, it's coded in a class somehow somewhere IIRC using private attributes/methods so I didn't see a way we could use them.

def event(self, ev):
"""Catch system events."""
if ev.type() == QEvent.PaletteChange: # detect theme switches
theme = get_config('MNE_3D_OPTION_THEME', 'auto')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this won't quite do what I'd expect -- if I pass theme='light' when instantiating a brain, I would expect it not to change to dark when the system switches. So the user-selected option (light, dark, auto) needs to be stored on instantiation, and switching done only when it's auto.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah good idea!

@GuillaumeFavelier GuillaumeFavelier changed the title ENH: Automatic theme switching on macOS WIP, ENH: Automatic theme switching on macOS May 24, 2022
@GuillaumeFavelier GuillaumeFavelier marked this pull request as draft May 24, 2022 15:14
@GuillaumeFavelier
Copy link
Contributor Author

As an aside, I looked for quite some time to see if there is a way to tell Qt "even though my system is in light mode, use the native dark mode Qt styling" but I couldn't find a way to do it. They don't just apply an internal stylesheet to do it, it's coded in a class somehow somewhere IIRC using private attributes/methods so I didn't see a way we could use them.

Could it be the macOS system itself that changes the Qt palette somehow? It would explain why we need to filter PaletteChange event on macOS to update the icons. In this scenario, it's even possible that the stylesheet is stored on the macOS side. I am just guessing here of course, I did not investigate.

@larsoner
Copy link
Member

Could it be the macOS system itself that changes the Qt palette somehow?

Could be, with stuff like:

https://github.com/qt/qtbase/blob/067b53864112c084587fa9a507eb4bde3d50a6e1/src/widgets/widgets/qtoolbar.cpp#L28-L30
https://github.com/qt/qtbase/tree/067b53864112c084587fa9a507eb4bde3d50a6e1/src/plugins/platforms/cocoa

etc. So maybe there is some way for us to dig into the cocoa platform plugin and say, in the case that a user is in light mode but requests dark mode, "cocoa, restyle this as dark mode" after a light-mode window is been created (or tell it to use dark mode before it creates a light mode one, but this seems harder). But we're getting pretty deep in the internals of Qt here...

What might be a low effort possible solution would be to post a question like this to the Qt forums somewhere, and hope someone knows how to do it. If the solution is easy, we implement it; if nobody responds, if someone is bored they can look into the Qt internals to figure out if there's a way to tell Cocoa to restyle (in the same way that the user changing their OS mode changes things); and until then we just use qdarkstyle and live with the blue.

@cbrnr
Copy link
Contributor

cbrnr commented May 24, 2022

@larsoner if you post a question in the forum please add a link to the thread here. I'm very interested to see if this is possible. Ideally, this should be added to Qt directly instead of rolling our own workaround/fix. And not just the macOS dark app in system light mode, but also support for native light/dark mode on Windows and Linux.

@larsoner
Copy link
Member

I'll let someone else post when they're motivated :)

@cbrnr
Copy link
Contributor

cbrnr commented May 24, 2022

I'm motivated but I need to find the time to do it... Let's see. I could imagine that there are tons of threads about light/dark mode switching on Windows/Linux already, but I haven't even searched the forum properly.

@hoechenberger
Copy link
Member

hoechenberger commented May 24, 2022

My 2 cts:

I don't see any reason to support selecting a different theme than what is currently set system-wide, as long as we allow automated switching upon system-wide theme change. It's so trivially easy to change the theme on macOS – for me, it means right-clicking on an icon in the menu bar. I'm not against having this functionality, but if it causes pain and more complicated code (does it? I'm not sure?), I'd say, just don't support it and tell users about that neat tool that I'm using, NightOwl 🦉

It even allows you to always start certain apps in light or dark mode, independent from the global system setting.

@cbrnr
Copy link
Contributor

cbrnr commented May 24, 2022

I agree with @hoechenberger. The priority should be to support automatic switching on all three OSs, preferably using a native styling (as opposed to stylesheets).

@larsoner
Copy link
Member

It sounds like we might just wait on this one (?) and even if we don't, will try to avoid having qdarkstyle set the stylesheet where possible. So I'll close for now!

@larsoner larsoner closed this Aug 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Automatic light/dark mode switching of open STC plot windows
4 participants