Difference between revisions of "Color management Gtk4"

From Inkscape Wiki
Jump to navigation Jump to search
Line 65: Line 65:
** After EVERY event (mouse, scroll, etc.) event_after_cb is called.
** After EVERY event (mouse, scroll, etc.) event_after_cb is called.
*** If the event is a GDK_CONFIGURE event, there is a check to see if the gdk window is on a different monitor.
*** If the event is a GDK_CONFIGURE event, there is a check to see if the gdk window is on a different monitor.
*** If the monitor has changed, the tracker "changed" signal triggers a call to SPDesktopWidget::color_profile_event, this updates the canvas cms key (a checksum of profile buffer) corresponding to the new monitor.
*** If the monitor has changed, the tracker "changed" signal triggers a call to SPDesktopWidget::color_profile_event, this updates the canvas cms key (a checksum of profile buffer) corresponding to the new monitor. This event often is delayed some number of seconds.
* Drawing
* Drawing
** CanvasPrivate::commit_tiles takes the value of prefs.from_display:
** CanvasPrivate::commit_tiles takes the value of prefs.from_display:
*** True: calls cms_system->get_display_transform_monitor(q->_cms_key). This uses the display profile linked to a monitor.
*** True: calls cms_system->get_display_transform_monitor(q->_cms_key). This uses the display profile linked to a monitor.
*** False: calls cms_system->get_display_transform_system(). This uses the display profile set in the preferences dialog (same profile for all monitors).
*** False: calls cms_system->get_display_transform_system(). This uses the display profile set in the preferences dialog (same profile for all monitors).

Revision as of 20:03, 12 June 2023

Introduction

Inkscape has supported color management for some time using ICC color profiles. ICC color profiles are used three places in Inkscape:

  1. For specifying a particular color (see Fill and Stroke dialog). The profile and the color value are stored in the SVG file (see the SPObject based ColorProfile class).
  2. For color adjustment of monitor(s).
  3. For pre-flighting output.

The latter two uses are controlled by settings in the "Color management" subsection of the Input/Output section of the Preferences dialog.

The current code has some problems, particularly, the monitor adjustment code. These problems include

  • Only one profile can be specified even if there are multiple displays that need different corrections.
  • Retrieving a profile from a display doesn't appear to work.
  • The code for retrieving display profiles relies on X11 functionality that is missing under Wayland or other windowing systems.
  • The code was written for Gtk2 which defined a Gdk screen per monitor. In Gtk3, there is only one screen that can have multiple monitors. Gtk4 removes Gdk screen completely.
  • Only one color transform can be specified at a time due to the use of global variables.
  • The code is quite messy, based on GObject, and is poorly documented.
  • The drawing doesn't always update properly.

For per monitor color correction to work under X11, a ICC profile must be attached to each monitor, verify by:

  xprop -display :0.0 -len 14 -root _ICC_PROFILE

Spec: https://www.burtonini.com/computing/x-icc-profiles-spec-latest.html

Darktable has a color management test: darktable-cmstest

A redesigned system

Each canvas should have its own color transform. This color transform should be updated when:

  • The user changes a color transform related preference.
  • The canvas is moved to a different monitor (if Inkscape handles monitor color corrections, see below). In Gtk4 there is Gdk::Surface::signal_enter_monitor than can be used for this. In Gtk3, there was Gtk::Widget::signal_screen_changed but as of 3.20 there is only one screen. One could check which monitor the canvas is on each time there is a draw and if the monitor changes, recalculate the color transform.

There is the question of if Inkscape should even handle monitor color corrections. On most Linux (Gnome, KDE) systems, colord can be used to set a system wide color correction for each monitor (see, for example, the "Color" page for in Gnome's "Settings"). Windows and OSX have their own color corrections frameworks.

If Inkscape does handle per monitor color corrections, there are two methods for determining the color corrections:

  1. Allow the user to set the corrections. Currently (Inkscape 1.3), only one correction can be set which is used for all monitors.
  2. Automatically obtain the color corrections from the monitors themselves. On Linux, one can either use X11 functionality or colord (or use X11 via colord?):
    1. X11: X11 has an "Atom" for finding the color correction for each monitor. The primary monitor's atom is "_ICC_PROFILE", additional monitors have atoms of the form "_ICC_PROFILE_n" where n is the additional screen number (starting at 1). On, at least my system only the primary monitor's color profile atom is defined. This is Inkscape's current method.
    2. colord: One can use the colord library to find the color correction set for a particular monitor. As this would be by default the same as used by the system wide monitor correction, there is probably no added advantage in supporting this method.

The color transform is defined as a cmsHTRANSFORM (void *), this is a pointer to a data structure defined by lcms2. We need to track it, not only to avoid recreating it but also to delete it when replaced or no longer needed.

Test program

A test program for examining monitor information can be found at: https://gitlab.com/Tavmjong/gtk_sandbox/-/tree/master/gtk_monitor

Notes:

  • Output of Gdk::Display::get_name() is of the form "wayland-n" for Wayland and ":n" for X11, where n is a number.
  • Wayland has proper device model names, x11 has generic names (DP-1, DP-2).
  • Gtk4 with X11 lists all seat devices such as "Power Button", "Logitech M310/310t"; Gtk4 with Wayland lists a small set of devices including "Wayland Keyboard" and "Wayland Pointer".
  • Gtk3 has Gtk::Window::signal_screen_changed but Gtk has only one screen since 3.20 so it is useless to track moving a window between monitors. Gtk4 has Gtk::Surface::signal_enter_monitor(). This signal is not fired under X11. The Gtk4 function Gdk::Display::get_monitor_at_surface() does work on both X11 and Wayland.
  • The initial monitor is set wrong under Gtk3/Gtk4 x11/Wayland (as seen while constructing the Window, and in the signal handlers for realizing and mapping the window (it is always set to the second monitor). Under x11, the monitor is correct when using a button to trigger code to check the monitor. Under Wayland, the window has to be moved to a different monitor and back before the correct monitor is shown via the button. This is probably a Gtk bug.

Inkscape 1.3

This documents the ege-color-prof-tracker code as of 1.3.

  • On start-up:
    • ege-color_prof_tracker_new is called with no target widget (why?).
    • target_screen_change_cb
    • ege-color_prof_tracker_new is called with LayerSelector as target widget (why?).
    • target_screen_change_cb
  • On event handling:
    • After EVERY event (mouse, scroll, etc.) event_after_cb is called.
      • If the event is a GDK_CONFIGURE event, there is a check to see if the gdk window is on a different monitor.
      • If the monitor has changed, the tracker "changed" signal triggers a call to SPDesktopWidget::color_profile_event, this updates the canvas cms key (a checksum of profile buffer) corresponding to the new monitor. This event often is delayed some number of seconds.
  • Drawing
    • CanvasPrivate::commit_tiles takes the value of prefs.from_display:
      • True: calls cms_system->get_display_transform_monitor(q->_cms_key). This uses the display profile linked to a monitor.
      • False: calls cms_system->get_display_transform_system(). This uses the display profile set in the preferences dialog (same profile for all monitors).