Bug 540357 - [10.14] Make SWT adapt to switching to dark mode (and back)
Summary: [10.14] Make SWT adapt to switching to dark mode (and back)
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 4.9   Edit
Hardware: Macintosh Mac OS X
: P3 normal with 4 votes (vote)
Target Milestone: 4.12 M3   Edit
Assignee: Lakshmi P Shanmugam CLA
QA Contact:
URL:
Whiteboard:
Keywords: plan
Depends on:
Blocks: 541801
  Show dependency tree
 
Reported: 2018-10-22 04:37 EDT by Ingo Mohr CLA
Modified: 2020-12-07 13:30 EST (History)
14 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ingo Mohr CLA 2018-10-22 04:37:40 EDT
Current Situation
=================
SWT initially aimed to have the OS create and draw the widgets, so that SWT applications - other than Swing applications - have a native look and feel.

In Mac OS Mojave you can switch between light mode and dark mode in real time which also switches all running rich client applications (that support this) in real time.

On SWT windows, switching to dark mode, however, has no effect - even if I turned off CSS theming (in Eclipse).

Request
=======
Please add support for switching from light to dark mode and back on Mac OS Mojave so that the running SWT windows switch, as well.
In Mojave's dark mode, the SWT windows should adopt the dark mode colors from the OS - if theming support is turned off for SWT.
Comment 1 Till Brychcy CLA 2018-10-24 03:01:00 EDT
Just summarizing some discussion at EclipseCon Europe:

- As we won't link on 10.14 for now, this means setting 
<key>NSRequiresAquaSystemAppearance</key><false/>
in the Info.plist, see https://developer.apple.com/documentation/appkit/nsappearancecustomization/choosing_a_specific_appearance_for_your_app

- To active this setting in a nested eclipse, the CFProcessPath environment variable has to be set in the launch configuration so it points to a folder which contains a Info.plist with this setting (i.e. /path/to/Eclipse.app/Contents). I haven't found documentation for this, but Apple has opensourced the relevent code, see https://opensource.apple.com/source/CF/CF-476.15/CFPlatform.c

- When I do that, the application crashes when run with Java 9 or later in Contol.internal_new_GC
java.lang.NullPointerException
	at org.eclipse.swt.widgets.Control.internal_new_GC(Control.java:2180)
	at org.eclipse.swt.graphics.GC.<init>(GC.java:177)
	at org.eclipse.swt.graphics.GC.<init>(GC.java:138)
	at org.eclipse.swt.custom.CLabel.getTotalSize(CLabel.java:274)
[...]

- At EclipseCon I could not reproduce the crash in a nested eclipse. I now found out that this was because I was running with jdk1.8.0_162, so the difference is probably because of some api linkage check - it was linked with the 10.8 sdk:
otool -l /Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home/bin/java | fgrep -A4 LC_VERSION_MIN_MACOSX
      cmd LC_VERSION_MIN_MACOSX
  cmdsize 16
  version 10.7
      sdk 10.8

But for  java 9 it is the 10.9 sdk:
otool -l /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home/bin/java | fgrep -A3 LC_VERSION_MIN_MACOSX
      cmd LC_VERSION_MIN_MACOSX
  cmdsize 16
  version 10.7
      sdk 10.9

(For the eclipse launcher it is the 10.10 sdk - and configuring 1.8 as jvm in the eclipse.ini using -vm doesn't avoid the crash, so this must be the difference)
Comment 2 Till Brychcy CLA 2018-10-25 02:27:57 EDT
I think I found the reason for the NPEs caused by NSGraphicsContext.graphicsContextWithWindow returning null:

https://developer.apple.com/documentation/appkit/appkit_release_notes_for_macos_10_14?language=objc says
"Windows in apps linked against the macOS 10.14 SDK are displayed using Core Animation when the app is running in macOS 10.14"

and the WWDC presentation at https://developer.apple.com/videos/play/wwdc2018/209/ has 
on page 122 of the slide pdf:

Obsolete Patterns
-[NSView lockFocus] / -[NSView unlockFocus]
-[NSWindow graphicsContext] / +[NSGraphicsContext graphicsContextWithWindow:]

They say to just subclass NSView and implement draw(), but as I understand it, our code where the NPE happens now is outside of drawing calls (otherwise the if() that uses NSGraphicsContext.currentContext() would be entered)
Comment 3 Paul Gardner CLA 2018-11-06 08:32:58 EST
I am running into this same issue when attempting to run BiglyBT in 'dark mode' - there are a couple of places I am getting a stack trace:

  java.lang.NullPointerException
	at org.eclipse.swt.widgets.Control.internal_new_GC(Control.java:2180)
	at org.eclipse.swt.graphics.GC.<init>(GC.java:177)
	at org.eclipse.swt.graphics.GC.<init>(GC.java:138)
	at org.eclipse.swt.custom.CLabel.getTotalSize(CLabel.java:274)
	at org.eclipse.swt.custom.CLabel.computeSize(CLabel.java:148)
	at org.eclipse.swt.layout.GridData.computeSize(GridData.java:494)
	at org.eclipse.swt.layout.GridLayout.layout(GridLayout.java:224)
	at org.eclipse.swt.layout.GridLayout.computeSize(GridLayout.java:167)
	at org.eclipse.swt.widgets.Composite.computeSize(Composite.java:229)
	at org.eclipse.swt.layout.FormData.computeSize(FormData.java:131)
	at org.eclipse.swt.layout.FormLayout.layout(FormLayout.java:326)
	at org.eclipse.swt.layout.FormLayout.layout(FormLayout.java:292)
	at org.eclipse.swt.widgets.Composite.updateLayout(Composite.java:1267)
	at org.eclipse.swt.widgets.Composite.layout(Composite.java:742)



  java.lang.NullPointerException
	at org.eclipse.swt.widgets.Control.internal_new_GC(Control.java:2180)
	at org.eclipse.swt.graphics.GC.<init>(GC.java:177)
	at org.eclipse.swt.graphics.GC.<init>(GC.java:138)
	at org.eclipse.swt.widgets.Tree.setScrollWidth(Tree.java:3172)
	at org.eclipse.swt.widgets.Tree.sendMeasureItem(Tree.java:2746)
	at org.eclipse.swt.widgets.Tree.drawInteriorWithFrame_inView(Tree.java:1067)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:6405)
	at org.eclipse.swt.internal.cocoa.OS.objc_msgSendSuper(Native Method)
	at org.eclipse.swt.widgets.Widget.drawRect(Widget.java:769)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:5942)
	at org.eclipse.swt.internal.cocoa.OS.objc_msgSendSuper(Native Method)
	at org.eclipse.swt.widgets.Display.applicationNextEventMatchingMask(Display.java:5196)
	at org.eclipse.swt.widgets.Display.applicationProc(Display.java:5620)
	at org.eclipse.swt.internal.cocoa.OS.objc_msgSend(Native Method)
	at org.eclipse.swt.internal.cocoa.NSApplication.nextEventMatchingMask(NSApplication.java:97)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3732)
Comment 4 Serge Rider CLA 2018-11-13 17:35:37 EST
Exactly the same issue is in DBeaver (recently switched to E4.9 and now fails to start/work on some Mojave machines): https://github.com/dbeaver/dbeaver/issues/4539

Tons of NPEs at 
org.eclipse.swt.widgets.Control.internal_new_GC(Control.java:2180)
in very different controls.

Are there any workarounds for that?
Comment 5 Serge Rider CLA 2018-11-14 01:09:05 EST
Here is a workaround: pressing Ctrl during program launch resolves the issue.
This sounds like a magic trick but it works. Some other users use this trick on Windows as well.
Umm.. Anybody?.. :)
Comment 6 Eclipse Genie CLA 2018-11-18 10:04:54 EST
New Gerrit change created: https://git.eclipse.org/r/132638
Comment 7 Till Brychcy CLA 2018-11-18 10:23:17 EST
(In reply to Eclipse Genie from comment #6)
> New Gerrit change created: https://git.eclipse.org/r/132638

Experimental patch for avoiding NPEs when running with <key>NSRequiresAquaSystemAppearance</key><false/>, because default and window NSGraphicsContext is then only available within drawRect invocations. 

Other invocations are usually need to compute the size of buttons etc. which depend on the font, so returning a NSBitmapImageRep based context seems to work. 

The other issue is that explicitly invoking view.displayIfNeeded() does not work because of this, but we already discussed in bug 526395 that doing synchronous paints is bad for performance and as cocoa invokes displayIfNeeded based on time in when nextEventMatchingMask is called, so not doing anything in Control.update(boolean) works  (at least for normal apps which invoke nextEventMatchingMask often enough)

Still this patch is no complete solution, as views are now layer based, which leads various drawing problems:
- when resizing the editors or views, editor or view contents are scaled rather than redrawn.
- redrawing problems in various situations (probably because cocoa doesn't redraw subviews with a layer just because the parent view is marked as dirty)
Comment 8 Eclipse Genie CLA 2019-01-22 06:43:14 EST
New Gerrit change created: https://git.eclipse.org/r/135546
Comment 9 Lakshmi P Shanmugam CLA 2019-01-22 06:48:07 EST
(In reply to Eclipse Genie from comment #8)
> New Gerrit change created: https://git.eclipse.org/r/135546

The patch is WIP.
It sets the NSAppearance to dark or light based on the system
setting. The patch reads the setting only at startup, changing the
system setting dynamically doesn't cause any change in SWT.

It works with SWT Control and Custom Control examples. Doesn't work as expected with eclipse yet.

Solution is based on https://developer.apple.com/documentation/appkit/nsappearancecustomization/choosing_a_specific_appearance_for_your_app?language=objc#2993819
Comment 10 Alexander Kurtakov CLA 2019-02-01 08:17:44 EST
Eric, we should make sure that on GTK dynamic swith of the theme is also handled properly.
Comment 11 Lakshmi P Shanmugam CLA 2019-02-13 01:41:37 EST
(In reply to Eclipse Genie from comment #8)
> New Gerrit change created: https://git.eclipse.org/r/135546

I've updated the patch. The SWT application will check for the System appearance at startup and set it's appearance to Light or Dark accordingly.
This will affect all SWT applications. I'm not sure if users expect this behaviour for all SWT apps or if we should provide a way to override this behaviour.

@Till, what do you think?
Comment 12 Till Brychcy CLA 2019-02-13 02:50:21 EST
(In reply to Lakshmi Shanmugam from comment #11)
> @Till, what do you think?

Very nice :-) It avoids that the window title is temporarily in the light design during startup and I hope the workspace chooser would also be dark during startup.

Some thoughts:

- With this Gerrit, it makes sense to run eclipse with theming disabled. I then noticed, that many colors are still for the light appearance.  When I launch with my experimental patch and <key>NSRequiresAquaSystemAppearance</key><false/> as written in comment 7 and theming disabled, the UI is consistently dark (just the default colors for syntax coloring are used).
Maybe the correct system colors for the dark design can be retrieved using NSAppearance.setCurrentAppearance in Display.initColors
 as described in: https://stackoverflow.com/a/52516863

- I agree It should be possible to disable this somehow, maybe simply by  a system property?

- Some other platforms have a native dark mode, too, so we could try to make to cross-platform api (as far as possible) with methods to:
   - query if the platform has native dark mode support at all
   - query what the current system setting is
   - set the requested app appearance.
  This would allow to implement a simplified Appearance Preference page is I wrote in Bug 544039 Comment 10
Comment 13 Thomas Singer CLA 2019-02-13 11:58:40 EST
Is it right, that native applications adapt to the new theme immediately if it changes and don't require a restart?
Comment 14 Ingo Mohr CLA 2019-02-13 12:57:34 EST
Yes, they do (adopt the new theme in real time w/o having to restart the application). On MacOS Mojave.

Would be (very) nice if SWT applications would integrate to that.
Comment 15 Lakshmi P Shanmugam CLA 2019-02-15 08:02:24 EST
Thanks for trying out the patch, Till!

(In reply to Till Brychcy from comment #12)
> (In reply to Lakshmi Shanmugam from comment #11)
> > @Till, what do you think?
> 
> Very nice :-) It avoids that the window title is temporarily in the light
> design during startup and I hope the workspace chooser would also be dark
> during startup.
> 
> Some thoughts:
> 
> - With this Gerrit, it makes sense to run eclipse with theming disabled. I
> then noticed, that many colors are still for the light appearance.  When I
> launch with my experimental patch and
> <key>NSRequiresAquaSystemAppearance</key><false/> as written in comment 7
> and theming disabled, the UI is consistently dark (just the default colors
> for syntax coloring are used).
I did some testing by running Eclipse with the patch and theming disabled. Many colors are for light appearance, but that seems like a refresh or redraw issue. When I force a refresh for example by enabling/disabling the fullscreen mode, the controls get the dark appearance. Some controls like CTabFolder, Table headers seem to have wrong colors even after refresh.

The workspace chooser dialog has a similar refresh problem, the title bar turns dark but the controls are not coloured correctly.
SWT applications like ControlExample and other snippets don't have this problem. So, the patch works for SWT applications but can't be used yet for Eclipse.

> Maybe the correct system colors for the dark design can be retrieved using
> NSAppearance.setCurrentAppearance in Display.initColors
>  as described in: https://stackoverflow.com/a/52516863
> 
I think the correct system colors for the theme are retrieved for the appearance but not set or drawn correctly. I'm not sure yet why this happens.

> - I agree It should be possible to disable this somehow, maybe simply by  a
> system property?
>
Yes, will add a system property to ignore the system theme.

> - Some other platforms have a native dark mode, too, so we could try to make
> to cross-platform api (as far as possible) with methods to:
>    - query if the platform has native dark mode support at all
>    - query what the current system setting is
>    - set the requested app appearance.
>   This would allow to implement a simplified Appearance Preference page is I
> wrote in Bug 544039 Comment 10
I agree. Mac and GTK have support for Dark theme, so we should create APIs that can be called from Platform UI. Will look into this for 4.12.
Comment 16 Lakshmi P Shanmugam CLA 2019-02-21 04:31:07 EST
The refresh issue after applying the appearance needs to be fixed.
Moving to 4.12.
Comment 17 Eclipse Genie CLA 2019-04-23 05:30:09 EDT
New Gerrit change created: https://git.eclipse.org/r/140967
Comment 18 Eclipse Genie CLA 2019-04-23 07:31:02 EDT
New Gerrit change created: https://git.eclipse.org/r/140976
Comment 21 Eclipse Genie CLA 2019-04-26 03:51:30 EDT
New Gerrit change created: https://git.eclipse.org/r/141199
Comment 22 Lakshmi P Shanmugam CLA 2019-04-26 04:13:27 EDT
(In reply to Eclipse Genie from comment #21)
> New Gerrit change created: https://git.eclipse.org/r/141199

This patch adds a new system property "org.eclipse.swt.display.useSystemTheme" which
should be set for SWT application to use the system's theme. For now, this is false by default.
Comment 25 Lakshmi P Shanmugam CLA 2019-04-26 04:57:05 EDT
(In reply to Eclipse Genie from comment #23)
> Gerrit change https://git.eclipse.org/r/135546 was merged to [master].
> Commit:
> http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/
> ?id=215b2e93a351272e93bda116b9240ee541b38b83

With this change, Control Example and other SWT snippets launch correctly in Dark or Light mode based on the System appearance.
System property org.eclipse.swt.display.useSystemTheme=true has to be set.

Eclipse still uses the theme set in the application.
Comment 26 Thomas Singer CLA 2019-04-29 09:57:05 EDT
Is it intended that if this property is not set, the composite's background color changed from light-gray to white now?
Comment 27 Lakshmi P Shanmugam CLA 2019-04-30 04:57:35 EDT
(In reply to Thomas Singer from comment #26)
> Is it intended that if this property is not set, the composite's background
> color changed from light-gray to white now?

This was not intended. I can see this with Shell, but not other Composites, I'll check.
Comment 28 Eclipse Genie CLA 2019-04-30 05:16:20 EDT
New Gerrit change created: https://git.eclipse.org/r/141383
Comment 30 Lakshmi P Shanmugam CLA 2019-04-30 08:03:23 EDT
(In reply to Lakshmi Shanmugam from comment #15)
> I agree. Mac and GTK have support for Dark theme, so we should create APIs
> that can be called from Platform UI. Will look into this for 4.12.
Opened Bug 546859 to track this.
Comment 31 Lakshmi P Shanmugam CLA 2019-04-30 08:04:57 EDT
(In reply to Eclipse Genie from comment #29)
> Gerrit change https://git.eclipse.org/r/141383 was merged to [master].
> Commit:
> http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/
> ?id=185875bb106fe3fe40c69c19fad03e22794580e3

(In reply to Thomas Singer from comment #26)
> Is it intended that if this property is not set, the composite's background
> color changed from light-gray to white now?

This commit should fix the white background problem in Shell.
Comment 32 Dinesh Vijay CLA 2019-05-06 02:33:28 EDT
Hi Lakshmi,

May I know that below gerrit changelist will be available in which swt stable version for Mac OS.

New Gerrit change created: https://git.eclipse.org/r/132638
Comment 33 Lakshmi P Shanmugam CLA 2019-05-06 08:08:10 EDT
(In reply to Dinesh  Vijay from comment #32)
> Hi Lakshmi,
> 
> May I know that below gerrit changelist will be available in which swt
> stable version for Mac OS.
> 
> New Gerrit change created: https://git.eclipse.org/r/132638
There is no plan yet to merge this patch as it's required after we make changes to Info.plist as described in comment#1. Any specific reason, you are looking for this patch to be merged?
Comment 34 Thomas Singer CLA 2019-05-07 03:29:30 EDT
Please see bug 547030.
Comment 35 Dinesh Vijay CLA 2019-05-08 07:34:44 EDT
Hi Lakshmi,

We have also created a bug as our application was not working on Mac Mojave 10.14 

Bug Link: https://bugs.eclipse.org/bugs/show_bug.cgi?id=540160

Because of same stack trace it was failing,which you guys have fixed in below gerrit commit.

Gerrit Commit: https://git.eclipse.org/r/132638

So just wanted to test above gerrit commit in our application. That is why I asked.

Thanks,
Dinesh Vijay
Comment 36 Lakshmi P Shanmugam CLA 2019-05-16 01:55:37 EDT
SWT application can now start with the System's theme when the system property org.eclipse.swt.display.useSystemTheme is set to true.
Closing this bug as fixed.

Opened bugs for related/remaining tasks.
Bug 547316 - Dynamically change SWT applications's theme based on System theme.
Bug 546859 - Provide APIs for dark theme support
Bug 547038 - Start eclipse in dark theme based on system theme
Comment 37 Till Brychcy CLA 2019-05-16 02:08:22 EDT
(In reply to Lakshmi Shanmugam from comment #33)
> (In reply to Dinesh  Vijay from comment #32)
> > Hi Lakshmi,
> > 
> > May I know that below gerrit changelist will be available in which swt
> > stable version for Mac OS.
> > 
> > New Gerrit change created: https://git.eclipse.org/r/132638
> There is no plan yet to merge this patch as it's required after we make
> changes to Info.plist as described in comment#1. Any specific reason, you
> are looking for this patch to be merged?

I think we should still merge this. It only changes behaviour where user would get an NPE now, so it can't break anything.

Sooner or later something like this will be needed anyway (probably when we link against macOS 10.14 API)

Or should we move it to a new bug like "Prepare for new MacOS API"?

WDYT?
Comment 38 Lakshmi P Shanmugam CLA 2019-05-16 04:17:08 EDT
(In reply to Till Brychcy from comment #37)
> (In reply to Lakshmi Shanmugam from comment #33)
> > (In reply to Dinesh  Vijay from comment #32)
> > > Hi Lakshmi,
> > > 
> > > May I know that below gerrit changelist will be available in which swt
> > > stable version for Mac OS.
> > > 
> > > New Gerrit change created: https://git.eclipse.org/r/132638
> > There is no plan yet to merge this patch as it's required after we make
> > changes to Info.plist as described in comment#1. Any specific reason, you
> > are looking for this patch to be merged?
> 
> I think we should still merge this. It only changes behaviour where user
> would get an NPE now, so it can't break anything.
> 
> Sooner or later something like this will be needed anyway (probably when we
> link against macOS 10.14 API)
> 
> Or should we move it to a new bug like "Prepare for new MacOS API"?
> 
> WDYT?

@Till,
From your comment#7, I thought this was an experimental patch and was required only when the Info.plist was changed. The comment also says that view.displayIfNeeded() doesn't work with this patch. Is it not the case? Please let me know if have I misunderstood something.
Comment 39 Till Brychcy CLA 2019-05-16 04:34:51 EDT
(In reply to Lakshmi Shanmugam from comment #38)
> @Till,
> From your comment#7, I thought this was an experimental patch and was
> required only when the Info.plist was changed. The comment also says that

Changing the Info.plist seems to trigger new macOS API behaviour for drawing even when linking against old API.

> view.displayIfNeeded() doesn't work with this patch. Is it not the case?
> Please let me know if have I misunderstood something.

I guess I meant org.eclipse.swt.widgets.Control.update(boolean) doesn't do anything (i.e. doesn't call view.displayIfNeeded() because that would causes NPEs because of missing graphicsContext)

Again, a change in behaviour would only happen, if currently an NPE happens anyway.
Comment 40 Lakshmi P Shanmugam CLA 2019-05-16 06:56:27 EDT
(In reply to Till Brychcy from comment #39)
> (In reply to Lakshmi Shanmugam from comment #38)
> > @Till,
> > From your comment#7, I thought this was an experimental patch and was
> > required only when the Info.plist was changed. The comment also says that
> 
> Changing the Info.plist seems to trigger new macOS API behaviour for drawing
> even when linking against old API.
> 
> > view.displayIfNeeded() doesn't work with this patch. Is it not the case?
> > Please let me know if have I misunderstood something.
> 
> I guess I meant org.eclipse.swt.widgets.Control.update(boolean) doesn't do
> anything (i.e. doesn't call view.displayIfNeeded() because that would causes
> NPEs because of missing graphicsContext)
> 
> Again, a change in behaviour would only happen, if currently an NPE happens
> anyway.

I haven't seen any of the reported NPEs, but it has been reported in https://bugs.eclipse.org/bugs/show_bug.cgi?id=540160#c12 and https://bugs.eclipse.org/bugs/show_bug.cgi?id=540081#c4. May be we can merge this change as part of Bug 540081?
Comment 41 Till Brychcy CLA 2019-05-16 07:39:32 EDT
(In reply to Lakshmi Shanmugam from comment #40)
> I haven't seen any of the reported NPEs, but it has been reported in
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=540160#c12 and
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=540081#c4. May be we can merge
> this change as part of Bug 540081?

OK.
Comment 42 Till Brychcy CLA 2019-05-16 13:03:21 EDT
(In reply to Till Brychcy from comment #41)
> (In reply to Lakshmi Shanmugam from comment #40)
> > I haven't seen any of the reported NPEs, but it has been reported in
> > https://bugs.eclipse.org/bugs/show_bug.cgi?id=540160#c12 and
> > https://bugs.eclipse.org/bugs/show_bug.cgi?id=540081#c4. May be we can merge
> > this change as part of Bug 540081?
> 
> OK.

Bug 540081 comment 0 is about a different issue, so I've created Bug 547399 for this.
Comment 43 Eclipse Genie CLA 2019-05-22 07:38:57 EDT
New Gerrit change created: https://git.eclipse.org/r/142579
Comment 45 Lakshmi P Shanmugam CLA 2019-05-22 08:06:42 EDT
Verified on I20190520-1805.