Created attachment 465504 [details] Screenshot showing Epiphany (Webkit-based) and Firefox on Ubuntu with high contrast setting enabled - note the difference in which prefers-contrast value evaluates to true # Steps to reproduce the problem: 1. In Linux's settings, enable high contrast (in my case, in Ubuntu, this is under Settings > Accessibility > Seeing > High Contrast) 2. Open https://codepen.io/patrickhlauke/full/NWyajBN which tests the various user preference media features of MQ Level 5 (tested using Epiphany) 3. Check the reported "prefers-contrast" values # Problem Description: The expectation is that once High Contrast is enabled, the "prefers-contrast: more" media feature should evaluate to true. Instead, that currently evaluates to false and "prefers-contrast: no-preference" evaluates to true. I.e. Epiphany is not picking up on the OS-level preference. Note that this works as expected in Firefox/Linux (but fails the same way in Chrome/Linux - see https://bugs.chromium.org/p/chromium/issues/detail?id=1425734) Tested in Epiphany 42.4 (the latest available from the Ubuntu software manager) Relates to support for https://www.w3.org/TR/mediaqueries-5/#mf-user-preferences
Copied over from https://gitlab.gnome.org/GNOME/epiphany/-/issues/2001#note_1701623
High contrast is a bit hard atm... Using GSettings alone won't work in Flatpak. Libadwaita has a fairly complicated logic to fetch it atm, I'm afraid WebKit may need to copy that... Otherwise - when using libadwaita it can hook into it directly - it's not impossible, and everything you need here is accessible via properties so it can be done without a hard dependency. And honestly - when not using libadwaita you can just check gtk-theme-name instead.
(In reply to Alexander Mikhaylenko from comment #2) > Libadwaita has a fairly complicated logic to fetch it atm, I'm afraid WebKit > may need to copy that... Why aren't these settings exposed via settings portal? I think we should just look at the gsetting (carefully, to ensure we don't crash if not installed) and if it's not propagated by the portal then too bad. Desktop-wide settings that applications would be expected to read should be readable. There's also a reduced motion accessibility setting that we should propagate as well (InternalSettings.h). (The other accessibility settings there don't have equivalents in GNOME.)
It is exposed by the settings portal. How would it work in other apps otherwise? ;) That's what libadwaita uses. Poratl + gsettings + deriving from gtk-theme-name on GdkDisplay + separate codepaths for macOS and Windows. But that's a lot of pretty fragile logic, do you really want to have it all in WebKit?
Oh, forgot about those parts. There is also an env variable to override it on startup that Builder uses for its run -> accessibility -> high contrast toggle, and there's a toggle in inspector.
I did some initial work on this in https://github.com/WebKit/WebKit/pull/13558 It doesn't cover all situations and it is only for GTK3 but I think it is still valuable for some users. I looked into using libadwaita to determine high-contrast on GTK4 but the complicated part is WebKit proxies over all GtkSettings to the WebProcess, but this isn't a GtkSetting, so we'd have to proxy it another way. Otherwise just dynamically loading libadwaita wasn't too much effort and should work fine.
Loading libadwaita only makes sense if the UI process is actually using libadwaita, though. How do you check whether you're in high contrast mode with libadwaita?
(In reply to Michael Catanzaro from comment #7) > Loading libadwaita only makes sense if the UI process is actually using > libadwaita, though. Yes. I was using `adw_is_initialized()` to conditionally check if we should respect libadwaita. > How do you check whether you're in high contrast mode with libadwaita? AdwStyleManager:high-contrast
(In reply to Patrick Griffis from comment #8) > Yes. I was using `adw_is_initialized()` to conditionally check if we should > respect libadwaita. Bah, I guess that is indeed a good reason to dlopen libadwaita, if you want to be able to do this check without having WebKit actually depend on libadwaita. > > How do you check whether you're in high contrast mode with libadwaita? > > AdwStyleManager:high-contrast Hm, I know we are WebKitGTK and not WebKitAdwaita, but maybe it would be easiest to just link to libadwaita after all. Dunno. Well, if using dlopen is not too hard, I suppose that's fine.
(In reply to Michael Catanzaro from comment #9) > (In reply to Patrick Griffis from comment #8) > > Yes. I was using `adw_is_initialized()` to conditionally check if we should > > respect libadwaita. > > Bah, I guess that is indeed a good reason to dlopen libadwaita, if you want > to be able to do this check without having WebKit actually depend on > libadwaita. > > > > How do you check whether you're in high contrast mode with libadwaita? > > > > AdwStyleManager:high-contrast > > Hm, I know we are WebKitGTK and not WebKitAdwaita, but maybe it would be > easiest to just link to libadwaita after all. Dunno. Well, if using dlopen > is not too hard, I suppose that's fine. Why not using the settings portal directly? We only need to watch the property “high-contrast” of the “org.gnome.desktop.a11y.interface”, and fallback to disabled if the interface is not available. I would rather not link libadwaita at all, and avoid dlopening it as well if possible. Alternatively, if we want to try libadwaita first, and fallback to the portal, we can: typedef struct _AdwStyleManager AdwStyleManager; void* handle = dlopen(NULL, RTLD_NOW); gboolean (*adwaitaIsInitialized)(void) = dlsym(handle, "adw_is_initialized"); AdwStyleManager (*adwaitaGetDefaultStyleManager)(void) = dlsym(handle, "adw_style_manager_get_default"); if (adwaitaIsInitialized && adwaitaGetDefaultStyleManager && adwaitaIsInitialized()) { // Proceed as before, but now we reach this code only iff the application // had already loaded libadwaita, without needing to load it ourselves. AdwStyleManager* styleManager = adwGetDefaultStyleManager(); g_signal_connect(styleManager, "notify::high-contrast", G_CALLBACK(...), ...); } else { // Assume high-contrast always off, or directly use DBus. }
(In reply to Adrian Perez from comment #10) > Why not using the settings portal directly? We only need to watch the > property “high-contrast” of the “org.gnome.desktop.a11y.interface”, and > fallback to disabled if the interface is not available. Any of these approaches are fine. We just have to proxy it similar to GtkSettingsManagerProxy.
FWIW portal is an implementation detail, libadwaita does not guarantee that HC will be read from there at all. In fact, there are quite a few situations where it's not, like there is an environment variable to override it, there's a toggle in inspector that overrides it and so on. One thing you can do without having to load libadwaita is: when AdwApplication is used, you can get the application, access the style-manager property, access the high-contrast property. That can be done in runtime, without linking or dlopening anything. That won't work if adw_init() was used without AdwApplication though, but that's not recommended to begin with.
(In reply to Alice Mikhaylenko from comment #12) > One thing you can do without having to load libadwaita is: when > AdwApplication is used, you can get the application, access the > style-manager property, access the high-contrast property. That can be done > in runtime, without linking or dlopening anything. Oh wow, so this works because it's GObjects all the way down? That's actually a really cool idea. We'd have to make sure the property actually exists before trying to get it using g_object_get(), to avoid criticals if the property doesn't exist, but I think that can be done by using G_OBJECT_GET_CLASS() then g_object_class_find_property().
Yup. An upside of GObject properties existing entirely in runtime. But yeah, there's still the case where you're not using AdwApplication. :(