From 784f33fe0cfec3fc708e54fb4d5c29a4816d27c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Thu, 29 Feb 2024 10:39:34 -0800 Subject: [PATCH] Port to GTK4 (#369) * Update deps * remove DisplayWindow * Filters view stuff * NightLightView * DisplayPlug * DisplaysView * DisplayWidget: more fixes * rotate labels with css * I hate all of this * Don't subclass overlay * Fix radio issues * Use secondary text in filters view * Maybe fix overlay * Use drag gesture * slightly simplify * one less commented code * Update DisplaysView.vala * Update DisplaysView.vala * Update DisplaysView.vala * Update DisplaysView.vala * Fix weird layout thing * Fix warnings * uncomment code * lint * Css stuff * Finish namespace stuff * Update README.md * Update README.md * Fix review comments * Has frame property * Fix disabled style --------- Co-authored-by: Jeremy Wootten --- .github/workflows/gettext.yml | 2 +- .github/workflows/main.yml | 2 +- .github/workflows/release.yml | 2 +- README.md | 13 +- data/Display.css | 58 ++++---- ...ay.gresource.xml => display.gresource.xml} | 2 +- data/display.metainfo.xml.in | 6 +- data/meson.build | 7 +- meson.build | 10 +- ...pot => io.elementary.settings.display.pot} | 0 src/DisplayPlug.vala | 15 ++- src/Views/DisplaysView.vala | 31 ++--- src/Views/FiltersView.vala | 124 ++++++++---------- src/Views/NightLightView.vala | 58 ++++---- src/Widgets/DisplayWidget.vala | 96 +++++++------- src/Widgets/DisplaysOverlay.vala | 42 +++--- src/meson.build | 10 +- 17 files changed, 235 insertions(+), 243 deletions(-) rename data/{io.elementary.switchboard.display.gresource.xml => display.gresource.xml} (75%) rename po/{display-plug.pot => io.elementary.settings.display.pot} (100%) diff --git a/.github/workflows/gettext.yml b/.github/workflows/gettext.yml index 3f5087d5..839f84b2 100644 --- a/.github/workflows/gettext.yml +++ b/.github/workflows/gettext.yml @@ -2,7 +2,7 @@ name: Gettext Updates on: push: - branches: [master] + branches: [main] jobs: build: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index eb6c0426..4cd237d6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,7 +23,7 @@ jobs: - name: Install Dependencies run: | apt update - apt install -y meson libgranite-dev libswitchboard-2.0-dev valac + apt install -y meson libadwaita-1-dev libgranite-7-dev libswitchboard-3-dev valac - name: Build env: DESTDIR: out diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6d9a340a..e2418cdd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,7 +2,7 @@ name: Release on: pull_request: - branches: [master] + branches: [main] types: [closed] jobs: release: diff --git a/README.md b/README.md index eda3adba..4a7deae8 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# Switchboard Display Plug +# Display Settings [![Packaging status](https://repology.org/badge/tiny-repos/switchboard-plug-display.svg)](https://repology.org/metapackage/switchboard-plug-display) [![Translation status](https://l10n.elementary.io/widgets/switchboard/-/switchboard-plug-display/svg-badge.svg)](https://l10n.elementary.io/engage/switchboard/?utm_source=widget) -Extension for [Switchboard](https://github.com/elementary/switchboard) to manage multiple monitor setups. +Extension for [System Settings](https://github.com/elementary/switchboard) to manage multiple monitor setups. ![screenshot](data/screenshot.png?raw=true) @@ -10,9 +10,10 @@ Extension for [Switchboard](https://github.com/elementary/switchboard) to manage You'll need the following dependencies: -* libgranite-dev -* libgtk-3-dev -* libswitchboard-2.0-dev +* libadwaita-1-dev +* libgranite-7-dev +* libgtk-4-dev +* libswitchboard-3-dev * meson * valac @@ -24,4 +25,4 @@ Run `meson` to configure the build environment and then `ninja` to build To install, use `ninja install` - sudo ninja install + ninja install diff --git a/data/Display.css b/data/Display.css index 12f0d72d..2f0b057f 100644 --- a/data/Display.css +++ b/data/Display.css @@ -1,5 +1,6 @@ display-widget { border-radius: 3px; + padding: 6px; text-shadow: 0 1px 1px alpha(white, 0.1); -gtk-icon-shadow: 0 1px 1px alpha(white, 0.1); } @@ -8,7 +9,7 @@ display-widget > grid > label { font-weight: 600; } -display-widget button { +display-widget button.flat.image-button { border-radius: 50%; color: inherit; padding: 6px; @@ -19,17 +20,16 @@ display-widget image { -gtk-icon-palette: success @text_color; } -display-widget.disabled { - background-color: @SLATE_100; - color: @SLATE_700; +display-widget label.rotate-90 { + transform: rotate(90deg); } -display-widget.disabled button:focus { - background: alpha(@SLATE_700, 0.25); +display-widget label.rotate-180 { + transform: rotate(180deg); } -display-widget.disabled button:checked { - background: alpha(@SLATE_700, 0.5); +display-widget label.rotate-270 { + transform: rotate(270deg); } display-widget.color-0 { @@ -38,11 +38,11 @@ display-widget.color-0 { color: @BLUEBERRY_900; } -display-widget.color-0 button:focus { +display-widget.color-0 button.flat.image-button:focus { background: @BLUEBERRY_300; } -display-widget.color-0 button:checked { +display-widget.color-0 button.flat.image-button:checked { background: alpha(@BLUEBERRY_500, 0.75); } @@ -52,11 +52,11 @@ display-widget.color-1 { color: @STRAWBERRY_900; } -display-widget.color-1 button:focus { +display-widget.color-1 button.flat.image-button:focus { background: @STRAWBERRY_300; } -display-widget.color-1 button:checked { +display-widget.color-1 button.flat.image-button:checked { background: alpha(@STRAWBERRY_500, 0.75); } @@ -66,11 +66,11 @@ display-widget.color-2 { color: @ORANGE_900; } -display-widget.color-2 button:focus { +display-widget.color-2 button.flat.image-button:focus { background: @ORANGE_300; } -display-widget.color-2 button:checked { +display-widget.color-2 button.flat.image-button:checked { background: alpha(@ORANGE_500, 0.75); } @@ -80,11 +80,11 @@ display-widget.color-3 { color: @BANANA_900; } -display-widget.color-3 button:focus { +display-widget.color-3 button.flat.image-button:focus { background: @BANANA_300; } -display-widget.color-3 button:checked { +display-widget.color-3 button.flat.image-button:checked { background: alpha(@BANANA_500, 0.75); } @@ -94,11 +94,11 @@ display-widget.color-4 { color: @LIME_900; } -display-widget.color-4 button:focus { +display-widget.color-4 button.flat.image-button:focus { background: @LIME_300; } -display-widget.color-4 button:checked { +display-widget.color-4 button.flat.image-button:checked { background: alpha(@LIME_500, 0.75); } @@ -108,11 +108,11 @@ display-widget.color-5 { color: @GRAPE_900; } -display-widget.color-5 button:focus { +display-widget.color-5 button.flat.image-button:focus { background: @GRAPE_300; } -display-widget.color-5 button:checked { +display-widget.color-5 button.flat.image-button:checked { background: alpha(@GRAPE_500, 0.75); } @@ -122,10 +122,24 @@ display-widget.color-6 { color: @COCOA_900; } -display-widget.color-6 button:focus { +display-widget.color-6 button.flat.image-button:focus { background: @COCOA_300; } -display-widget.color-6 button:checked { +display-widget.color-6 button.flat.image-button:checked { background: alpha(@COCOA_500, 0.75); } + +display-widget.disabled { + background-color: alpha(@SLATE_100, 0.75); + border: 1px solid alpha(@SLATE_500, 0.75); + color: @SLATE_700; +} + +display-widget.disabled button.flat.image-button:focus { + background: alpha(@SLATE_700, 0.25); +} + +display-widget.disabled button.flat.image-button:checked { + background: alpha(@SLATE_700, 0.5); +} diff --git a/data/io.elementary.switchboard.display.gresource.xml b/data/display.gresource.xml similarity index 75% rename from data/io.elementary.switchboard.display.gresource.xml rename to data/display.gresource.xml index 64f749db..4ec22cef 100644 --- a/data/io.elementary.switchboard.display.gresource.xml +++ b/data/display.gresource.xml @@ -1,6 +1,6 @@ - + Display.css Filters.css diff --git a/data/display.metainfo.xml.in b/data/display.metainfo.xml.in index 8101fcb8..4e513932 100644 --- a/data/display.metainfo.xml.in +++ b/data/display.metainfo.xml.in @@ -1,8 +1,8 @@ - io.elementary.switchboard.display - io.elementary.switchboard - display-plug + io.elementary.settings.display + io.elementary.settings + io.elementary.settings.display CC0-1.0 GPL-3.0+ diff --git a/data/meson.build b/data/meson.build index 9e22b7fa..bb32ce31 100644 --- a/data/meson.build +++ b/data/meson.build @@ -1,8 +1,13 @@ i18n.merge_file( input: 'display.metainfo.xml.in', - output: 'io.elementary.switchboard.display.metainfo.xml', + output: gettext_name + '.metainfo.xml', po_dir: meson.project_source_root() / 'po' / 'extra', type: 'xml', install: true, install_dir: get_option('datadir') / 'metainfo', ) + +gresource = gnome.compile_resources( + 'gresource', + 'display.gresource.xml' +) diff --git a/meson.build b/meson.build index 20410e4f..ced548fa 100644 --- a/meson.build +++ b/meson.build @@ -4,7 +4,7 @@ project( version: '7.0.0' ) -gettext_name = meson.project_name() + '-plug' +gettext_name = 'io.elementary.settings.' + meson.project_name() gnome = import('gnome') i18n = import('i18n') @@ -17,15 +17,9 @@ add_project_arguments( language:'c' ) -asresources = gnome.compile_resources( - 'as-resources', 'data/' + 'io.elementary.switchboard.display.gresource.xml', - source_dir: 'data', - c_name: 'as' -) - config_data = configuration_data() config_data.set_quoted('LOCALEDIR', join_paths(get_option('prefix'), get_option('localedir'))) -config_data.set_quoted('GETTEXT_PACKAGE', meson.project_name() + '-plug') +config_data.set_quoted('GETTEXT_PACKAGE', gettext_name) config_file = configure_file( input: 'src/Config.vala.in', output: '@BASENAME@', diff --git a/po/display-plug.pot b/po/io.elementary.settings.display.pot similarity index 100% rename from po/display-plug.pot rename to po/io.elementary.settings.display.pot diff --git a/src/DisplayPlug.vala b/src/DisplayPlug.vala index fde2eb9b..08392aaa 100644 --- a/src/DisplayPlug.vala +++ b/src/DisplayPlug.vala @@ -35,7 +35,7 @@ public class Display.Plug : Switchboard.Plug { settings.set ("display/night-light", "night-light"); settings.set ("display/filters", "filters"); Object (category: Category.HARDWARE, - code_name: "io.elementary.switchboard.display", + code_name: "io.elementary.settings.display", display_name: _("Displays"), description: _("Configure resolution and position of monitors and projectors"), icon: "preferences-desktop-display", @@ -64,7 +64,6 @@ public class Display.Plug : Switchboard.Plug { var stack_switcher = new Gtk.StackSwitcher () { halign = Gtk.Align.CENTER, - homogeneous = true, margin_top = 12, margin_end = 12, margin_bottom = 12, @@ -72,10 +71,16 @@ public class Display.Plug : Switchboard.Plug { stack = stack }; + var switcher_sizegroup = new Gtk.SizeGroup (HORIZONTAL); + unowned var switcher_child =stack_switcher.get_first_child (); + while (switcher_child != null) { + switcher_sizegroup.add_widget (switcher_child); + switcher_child = switcher_child.get_next_sibling (); + } + box = new Gtk.Box (VERTICAL, 0); - box.add (stack_switcher); - box.add (stack); - box.show_all (); + box.append (stack_switcher); + box.append (stack); stack.notify["visible-child"].connect (() => { if (stack.visible_child == displays_view) { diff --git a/src/Views/DisplaysView.vala b/src/Views/DisplaysView.vala index 0ac72168..d9fa8997 100644 --- a/src/Views/DisplaysView.vala +++ b/src/Views/DisplaysView.vala @@ -15,7 +15,9 @@ public class Display.DisplaysView : Gtk.Box { private const string TOUCHSCREEN_SETTINGS_PATH = "org.gnome.settings-daemon.peripherals.touchscreen"; construct { - displays_overlay = new DisplaysOverlay (); + displays_overlay = new DisplaysOverlay () { + vexpand = true + }; var mirror_label = new Gtk.Label (_("Mirror Display:")); var mirror_switch = new Gtk.Switch (); @@ -27,8 +29,8 @@ public class Display.DisplaysView : Gtk.Box { margin_start = 6, valign = CENTER }; - mirror_box.add (mirror_label); - mirror_box.add (mirror_switch); + mirror_box.append (mirror_label); + mirror_box.append (mirror_switch); var dpi_label = new Gtk.Label (_("Scaling factor:")); @@ -43,13 +45,13 @@ public class Display.DisplaysView : Gtk.Box { margin_bottom = 6, margin_start = 6 }; - dpi_box.add (dpi_label); - dpi_box.add (dpi_combo); + dpi_box.append (dpi_label); + dpi_box.append (dpi_combo); var detect_button = new Gtk.Button.with_label (_("Detect Displays")); var apply_button = new Gtk.Button.with_label (_("Apply")); - apply_button.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); + apply_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); apply_button.sensitive = false; var button_box = new Gtk.Box (HORIZONTAL, 6) { @@ -60,11 +62,11 @@ public class Display.DisplaysView : Gtk.Box { margin_start = 6, valign = CENTER }; - button_box.add (detect_button); - button_box.add (apply_button); + button_box.append (detect_button); + button_box.append (apply_button); var action_bar = new Gtk.ActionBar (); - action_bar.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); + action_bar.add_css_class (Granite.STYLE_CLASS_FLAT); action_bar.pack_start (dpi_box); action_bar.pack_start (mirror_box); @@ -89,9 +91,9 @@ public class Display.DisplaysView : Gtk.Box { action_bar.pack_end (button_box); orientation = VERTICAL; - add (new Gtk.Separator (HORIZONTAL)); - add (displays_overlay); - add (action_bar); + append (new Gtk.Separator (HORIZONTAL)); + append (displays_overlay); + append (action_bar); displays_overlay.configuration_changed.connect ((changed) => { apply_button.sensitive = changed; @@ -143,9 +145,8 @@ public class Display.DisplaysView : Gtk.Box { var rotation_lock_label = new Gtk.Label (_("Rotation Lock:")); var rotation_lock_switch = new Gtk.Switch (); - rotation_lock_box.add (rotation_lock_label); - rotation_lock_box.add (rotation_lock_switch); - rotation_lock_box.show_all (); + rotation_lock_box.append (rotation_lock_label); + rotation_lock_box.append (rotation_lock_switch); touchscreen_settings.bind ("orientation-lock", rotation_lock_switch, "state", DEFAULT); } diff --git a/src/Views/FiltersView.vala b/src/Views/FiltersView.vala index 93949040..d264d2ff 100644 --- a/src/Views/FiltersView.vala +++ b/src/Views/FiltersView.vala @@ -7,24 +7,11 @@ public class Display.FiltersView : Gtk.Box { private const string TEXT_MARKUP = "%s\n%s"; construct { - var colorblindness_header = new Granite.HeaderLabel (_("Color Deficiency Assistance")); - - var colorblindness_subtitle = new Gtk.Label ( - _("Each of the circles below should appear as a different color. A filter can be applied to the entire display to help differentiate between colors.") - ) { - wrap = true, - xalign = 0 + var colorblindness_header = new Granite.HeaderLabel (_("Color Deficiency Assistance")) { + secondary_text = _("Each of the circles below should appear as a different color. A filter can be applied to the entire display to help differentiate between colors.") }; - colorblindness_subtitle.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); - // FIXME: Replace with Granite.HeaderLabel secondary_text in Gtk4 - var colorblindness_headerbox = new Gtk.Box (VERTICAL, 0) { - margin_bottom = 3 - }; - colorblindness_headerbox.add (colorblindness_header); - colorblindness_headerbox.add (colorblindness_subtitle); - - var none_radio = new Gtk.RadioButton.with_label (null, _("None")); + var none_radio = new Gtk.CheckButton.with_label (_("None")); var protanopia_label = new Gtk.Label ( TEXT_MARKUP.printf (_("Red/Green"), _("Protanopia")) @@ -36,14 +23,15 @@ public class Display.FiltersView : Gtk.Box { }; var protanopia_box = new Gtk.Box (HORIZONTAL, 0); - protanopia_box.add (protanopia_label); - protanopia_box.add (new ColorSwatch ("green")); - protanopia_box.add (new ColorSwatch ("orange")); - protanopia_box.add (new ColorSwatch ("red")); + protanopia_box.append (protanopia_label); + protanopia_box.append (new ColorSwatch ("green")); + protanopia_box.append (new ColorSwatch ("orange")); + protanopia_box.append (new ColorSwatch ("red")); - var protanopia_radio = new Gtk.RadioButton.from_widget (none_radio) { - child = protanopia_box + var protanopia_radio = new Gtk.CheckButton () { + group = none_radio }; + protanopia_box.set_parent (protanopia_radio); var protanopia_hc_label = new Gtk.Label ( TEXT_MARKUP.printf (_("Red/Green — High Contrast"), _("Protanopia")) @@ -55,11 +43,12 @@ public class Display.FiltersView : Gtk.Box { }; var protanopia_hc_box = new Gtk.Box (HORIZONTAL, 0); - protanopia_hc_box.add (protanopia_hc_label); + protanopia_hc_box.append (protanopia_hc_label); - var protanopia_hc_radio = new Gtk.RadioButton.from_widget (none_radio) { - child = protanopia_hc_box + var protanopia_hc_radio = new Gtk.CheckButton () { + group = none_radio }; + protanopia_hc_box.set_parent (protanopia_hc_radio); var deuteranopia_label = new Gtk.Label ( TEXT_MARKUP.printf (_("Green/Red"), _("Deuteranopia")) @@ -71,14 +60,15 @@ public class Display.FiltersView : Gtk.Box { }; var deuteranopia_box = new Gtk.Box (HORIZONTAL, 0); - deuteranopia_box.add (deuteranopia_label); - deuteranopia_box.add (new ColorSwatch ("teal")); - deuteranopia_box.add (new ColorSwatch ("purple")); - deuteranopia_box.add (new ColorSwatch ("pink")); + deuteranopia_box.append (deuteranopia_label); + deuteranopia_box.append (new ColorSwatch ("teal")); + deuteranopia_box.append (new ColorSwatch ("purple")); + deuteranopia_box.append (new ColorSwatch ("pink")); - var deuteranopia_radio = new Gtk.RadioButton.from_widget (none_radio) { - child = deuteranopia_box + var deuteranopia_radio = new Gtk.CheckButton () { + group = none_radio }; + deuteranopia_box.set_parent (deuteranopia_radio); var deuteranopia_hc_label = new Gtk.Label ( TEXT_MARKUP.printf (_("Green/Red — High Contrast"), _("Deuteranopia")) @@ -90,11 +80,12 @@ public class Display.FiltersView : Gtk.Box { }; var deuteranopia_hc_box = new Gtk.Box (HORIZONTAL, 0); - deuteranopia_hc_box.add (deuteranopia_hc_label); + deuteranopia_hc_box.append (deuteranopia_hc_label); - var deuteranopia_hc_radio = new Gtk.RadioButton.from_widget (none_radio) { - child = deuteranopia_hc_box + var deuteranopia_hc_radio = new Gtk.CheckButton () { + group = none_radio }; + deuteranopia_hc_box.set_parent (deuteranopia_hc_radio); var tritanopia_label = new Gtk.Label ( TEXT_MARKUP.printf (_("Blue/Yellow"), _("Tritanopia")) @@ -106,13 +97,14 @@ public class Display.FiltersView : Gtk.Box { }; var tritanopia_box = new Gtk.Box (HORIZONTAL, 0); - tritanopia_box.add (tritanopia_label); - tritanopia_box.add (new ColorSwatch ("yellow")); - tritanopia_box.add (new ColorSwatch ("blue")); + tritanopia_box.append (tritanopia_label); + tritanopia_box.append (new ColorSwatch ("yellow")); + tritanopia_box.append (new ColorSwatch ("blue")); - var tritanopia_radio = new Gtk.RadioButton.from_widget (none_radio) { - child = tritanopia_box + var tritanopia_radio = new Gtk.CheckButton () { + group = none_radio }; + tritanopia_box.set_parent (tritanopia_radio); var colorblindness_adjustment = new Gtk.Adjustment (0, 0.15, 1, 0.01, 0, 0); @@ -125,31 +117,24 @@ public class Display.FiltersView : Gtk.Box { colorblindness_scale.add_mark (1, BOTTOM, _("More Assistance")); var colorblindness_box = new Gtk.Box (VERTICAL, 6); - colorblindness_box.add (colorblindness_headerbox); - colorblindness_box.add (none_radio); - colorblindness_box.add (protanopia_radio); - colorblindness_box.add (protanopia_hc_radio); - colorblindness_box.add (deuteranopia_radio); - colorblindness_box.add (deuteranopia_hc_radio); - colorblindness_box.add (tritanopia_radio); - colorblindness_box.add (colorblindness_scale); - - var grayscale_header = new Granite.HeaderLabel (_("Grayscale")); + colorblindness_box.append (colorblindness_header); + colorblindness_box.append (none_radio); + colorblindness_box.append (protanopia_radio); + colorblindness_box.append (protanopia_hc_radio); + colorblindness_box.append (deuteranopia_radio); + colorblindness_box.append (deuteranopia_hc_radio); + colorblindness_box.append (tritanopia_radio); + colorblindness_box.append (colorblindness_scale); + + var grayscale_header = new Granite.HeaderLabel (_("Grayscale")) { + secondary_text = _("Reducing color can help avoid distractions and alleviate screen addiction") + }; var grayscale_switch = new Gtk.Switch () { halign = END, valign = CENTER }; - // FIXME: Replace with Granite.HeaderLabel secondary_text in Gtk4 - var grayscale_subtitle = new Gtk.Label ( - _("Reducing color can help avoid distractions and alleviate screen addiction") - ) { - wrap = true, - xalign = 0 - }; - grayscale_subtitle.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); - var grayscale_adjustment = new Gtk.Adjustment (0, 0.15, 1, 0.01, 0, 0); var grayscale_scale = new Gtk.Scale (HORIZONTAL, grayscale_adjustment) { @@ -164,18 +149,18 @@ public class Display.FiltersView : Gtk.Box { column_spacing = 12 }; grayscale_grid.attach (grayscale_header, 0, 0); - grayscale_grid.attach (grayscale_subtitle, 0, 1); - grayscale_grid.attach (grayscale_switch, 1, 0, 1, 2); - grayscale_grid.attach (grayscale_scale, 0, 2, 2); + grayscale_grid.attach (grayscale_switch, 1, 0); + grayscale_grid.attach (grayscale_scale, 0, 1, 2); var box = new Gtk.Box (VERTICAL, 24); - box.add (colorblindness_box); - box.add (grayscale_grid); + box.append (colorblindness_box); + box.append (grayscale_grid); - var clamp = new Hdy.Clamp (); - clamp.add (box); + var clamp = new Adw.Clamp () { + child = box + }; - add (clamp); + append (clamp); margin_start = 12; margin_end = 12; margin_bottom = 12; @@ -313,13 +298,12 @@ public class Display.FiltersView : Gtk.Box { static construct { provider = new Gtk.CssProvider (); - provider.load_from_resource ("io/elementary/switchboard/display/Filters.css"); + provider.load_from_resource ("io/elementary/settings/display/Filters.css"); } construct { - var context = get_style_context (); - context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - context.add_class (color); + get_style_context ().add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + add_css_class (color); valign = CENTER; } diff --git a/src/Views/NightLightView.vala b/src/Views/NightLightView.vala index a13f9ef6..3a445878 100644 --- a/src/Views/NightLightView.vala +++ b/src/Views/NightLightView.vala @@ -5,7 +5,9 @@ public class Display.NightLightView : Gtk.Box { construct { - var nightlight_header = new Granite.HeaderLabel (_("Night Light")); + var nightlight_header = new Granite.HeaderLabel (_("Night Light")) { + secondary_text = _("Making the colors of your display warmer may help prevent eye strain and sleeplessness") + }; var nightlight_switch = new Gtk.Switch () { halign = END, @@ -13,15 +15,6 @@ public class Display.NightLightView : Gtk.Box { valign = CENTER }; - // FIXME: Replace with Granite.HeaderLabel secondary_text in Gtk4 - var nightlight_subtitle = new Gtk.Label ( - _("Making the colors of your display warmer may help prevent eye strain and sleeplessness") - ) { - wrap = true, - xalign = 0 - }; - nightlight_subtitle.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); - var temp_adjustment = new Gtk.Adjustment (0, 1500, 6000, 10, 0, 0); var temp_scale = new Gtk.Scale (HORIZONTAL, temp_adjustment) { @@ -33,66 +26,63 @@ public class Display.NightLightView : Gtk.Box { temp_scale.add_mark (1500, Gtk.PositionType.BOTTOM, _("More Warm")); temp_scale.add_mark (4500, Gtk.PositionType.BOTTOM, null); temp_scale.add_mark (6000, Gtk.PositionType.BOTTOM, _("Less Warm")); - temp_scale.get_style_context ().add_class ("warmth"); + temp_scale.add_css_class ("warmth"); var nightlight_grid = new Gtk.Grid () { column_spacing = 12 }; nightlight_grid.attach (nightlight_header, 0, 0); - nightlight_grid.attach (nightlight_subtitle, 0, 1); - nightlight_grid.attach (nightlight_switch, 1, 0, 1, 2); - nightlight_grid.attach (temp_scale, 0, 2, 2); + nightlight_grid.attach (nightlight_switch, 1, 0); + nightlight_grid.attach (temp_scale, 0, 1, 2); var schedule_header = new Granite.HeaderLabel (_("Schedule")); - var schedule_sunset_radio = new Gtk.RadioButton.with_label_from_widget ( - null, - _("Sunset to Sunrise") - ); + var schedule_sunset_radio = new Gtk.CheckButton.with_label (_("Sunset to Sunrise")); var from_label = new Gtk.Label (_("From:")); - var from_time = new Granite.Widgets.TimePicker () { + var from_time = new Granite.TimePicker () { hexpand = true, margin_end = 6 }; var to_label = new Gtk.Label (_("To:")); - var to_time = new Granite.Widgets.TimePicker () { + var to_time = new Granite.TimePicker () { hexpand = true }; var schedule_manual_box = new Gtk.Box (HORIZONTAL, 6); - schedule_manual_box.add (from_label); - schedule_manual_box.add (from_time); - schedule_manual_box.add (to_label); - schedule_manual_box.add (to_time); + schedule_manual_box.append (from_label); + schedule_manual_box.append (from_time); + schedule_manual_box.append (to_label); + schedule_manual_box.append (to_time); - var schedule_manual_radio = new Gtk.RadioButton.from_widget (schedule_sunset_radio); + var schedule_manual_radio = new Gtk.CheckButton () { + group = schedule_sunset_radio + }; + schedule_manual_box.set_parent (schedule_manual_radio); var schedule_grid = new Gtk.Grid () { - column_spacing = 7, // Off by one with Gtk.RadioButton + column_spacing = 6, row_spacing = 6 }; - schedule_grid.attach (schedule_header, 0, 3, 2); - schedule_grid.attach (schedule_sunset_radio, 0, 5, 2); + schedule_grid.attach (schedule_header, 0, 3); + schedule_grid.attach (schedule_sunset_radio, 0, 5); schedule_grid.attach (schedule_manual_radio, 0, 6); - schedule_grid.attach (schedule_manual_box, 1, 6); var box = new Gtk.Box (VERTICAL, 24); - box.add (nightlight_grid); - box.add (schedule_grid); + box.append (nightlight_grid); + box.append (schedule_grid); - var clamp = new Hdy.Clamp () { + var clamp = new Adw.Clamp () { child = box }; - add (clamp); + append (clamp); margin_start = 12; margin_end = 12; margin_bottom = 12; - show_all (); var settings = new Settings ("org.gnome.settings-daemon.plugins.color"); settings.bind ("night-light-enabled", nightlight_switch, "active", DEFAULT); diff --git a/src/Widgets/DisplayWidget.vala b/src/Widgets/DisplayWidget.vala index d643ad94..eb8537e7 100644 --- a/src/Widgets/DisplayWidget.vala +++ b/src/Widgets/DisplayWidget.vala @@ -26,7 +26,7 @@ public struct Display.Resolution { bool is_current; } -public class Display.DisplayWidget : Gtk.EventBox { +public class Display.DisplayWidget : Gtk.Box { public signal void set_as_primary (); public signal void check_position (); public signal void configuration_changed (); @@ -90,14 +90,10 @@ public class Display.DisplayWidget : Gtk.EventBox { virtual_monitor.get_current_mode_size (out real_width, out real_height); primary_image = new Gtk.Button.from_icon_name ("non-starred-symbolic") { + has_frame = false, halign = START, - valign = START, - margin_top = 6, - margin_end = 6, - margin_bottom = 6, - margin_start = 6 + valign = START }; - primary_image.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); primary_image.clicked.connect (() => set_as_primary ()); var virtual_monitor_name = virtual_monitor.get_display_name (); @@ -245,40 +241,36 @@ public class Display.DisplayWidget : Gtk.EventBox { margin_top = 6, margin_bottom = 12 }; - popover_box.add (use_switch); - popover_box.add (resolution_label); - popover_box.add (resolution_combobox); - popover_box.add (rotation_label); - popover_box.add (rotation_combobox); - popover_box.add (refresh_label); - popover_box.add (refresh_combobox); - popover_box.show_all (); - - var popover = new Gtk.Popover (null) { + popover_box.append (use_switch); + popover_box.append (resolution_label); + popover_box.append (resolution_combobox); + popover_box.append (rotation_label); + popover_box.append (rotation_combobox); + popover_box.append (refresh_label); + popover_box.append (refresh_combobox); + + var popover = new Gtk.Popover () { child = popover_box, position = BOTTOM }; var toggle_settings = new Gtk.MenuButton () { + has_frame = false, halign = END, valign = START, - image = new Gtk.Image.from_icon_name ("open-menu-symbolic", Gtk.IconSize.MENU), - margin_top = 6, - margin_end = 6, - margin_bottom = 6, - margin_start = 6, + icon_name = "open-menu-symbolic", popover = popover, tooltip_text = _("Configure display") }; - toggle_settings.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); var grid = new Gtk.Grid (); grid.attach (primary_image, 0, 0); grid.attach (toggle_settings, 2, 0); grid.attach (label, 0, 0, 3, 2); + append (grid); + set_primary (virtual_monitor.primary); - add (grid); use_switch.bind_property ("active", resolution_combobox, "sensitive"); use_switch.bind_property ("active", rotation_combobox, "sensitive"); @@ -290,9 +282,9 @@ public class Display.DisplayWidget : Gtk.EventBox { if (refresh_combobox.active == -1) refresh_combobox.set_active (0); if (use_switch.active) { - get_style_context ().remove_class ("disabled"); + remove_css_class ("disabled"); } else { - get_style_context ().add_class ("disabled"); + add_css_class ("disabled"); } configuration_changed (); @@ -300,10 +292,13 @@ public class Display.DisplayWidget : Gtk.EventBox { }); if (!virtual_monitor.is_active) { - get_style_context ().add_class ("disabled"); + add_css_class ("disabled"); } resolution_combobox.changed.connect (() => { + // Prevent breaking autohide by closing popover + popover.popdown (); + int active_width, active_height; Gtk.TreeIter iter; if (resolution_combobox.get_active_iter (out iter)) { @@ -329,6 +324,9 @@ public class Display.DisplayWidget : Gtk.EventBox { }); rotation_combobox.changed.connect (() => { + // Prevent breaking autohide by closing popover + popover.popdown (); + Value val; Gtk.TreeIter iter; rotation_combobox.get_active_iter (out iter); @@ -337,45 +335,45 @@ public class Display.DisplayWidget : Gtk.EventBox { var transform = (DisplayTransform)((int)val); virtual_monitor.transform = transform; + label.css_classes = {""}; + switch (transform) { case DisplayTransform.NORMAL: virtual_monitor.get_current_mode_size (out real_width, out real_height); - label.angle = 0; label.label = virtual_monitor_name; break; case DisplayTransform.ROTATION_90: virtual_monitor.get_current_mode_size (out real_height, out real_width); - label.angle = 270; + label.add_css_class ("rotate-270"); label.label = virtual_monitor_name; break; case DisplayTransform.ROTATION_180: virtual_monitor.get_current_mode_size (out real_width, out real_height); - label.angle = 180; + label.add_css_class ("rotate-180"); label.label = virtual_monitor_name; break; case DisplayTransform.ROTATION_270: virtual_monitor.get_current_mode_size (out real_height, out real_width); - label.angle = 90; + label.add_css_class ("rotate-90"); label.label = virtual_monitor_name; break; case DisplayTransform.FLIPPED: virtual_monitor.get_current_mode_size (out real_width, out real_height); - label.angle = 0; label.label = virtual_monitor_name.reverse (); //mirroring simulation, because we can't really mirror the text break; case DisplayTransform.FLIPPED_ROTATION_90: virtual_monitor.get_current_mode_size (out real_height, out real_width); - label.angle = 270; + label.add_css_class ("rotate-270"); label.label = virtual_monitor_name.reverse (); break; case DisplayTransform.FLIPPED_ROTATION_180: virtual_monitor.get_current_mode_size (out real_width, out real_height); - label.angle = 180; + label.add_css_class ("rotate-180"); label.label = virtual_monitor_name.reverse (); break; case DisplayTransform.FLIPPED_ROTATION_270: virtual_monitor.get_current_mode_size (out real_height, out real_width); - label.angle = 90; + label.add_css_class ("rotate-90"); label.label = virtual_monitor_name.reverse (); break; } @@ -385,6 +383,9 @@ public class Display.DisplayWidget : Gtk.EventBox { }); refresh_combobox.changed.connect (() => { + // Prevent breaking autohide by closing popover + popover.popdown (); + Value val; Gtk.TreeIter iter; if (refresh_combobox.get_active_iter (out iter)) { @@ -405,7 +406,6 @@ public class Display.DisplayWidget : Gtk.EventBox { configuration_changed (); check_position (); - } private void populate_refresh_rates () { @@ -513,27 +513,25 @@ public class Display.DisplayWidget : Gtk.EventBox { }); } - public void set_primary (bool is_primary) { if (is_primary) { - ((Gtk.Image) primary_image.image).icon_name = "starred-symbolic"; + primary_image.icon_name = "starred-symbolic"; primary_image.tooltip_text = _("Is the primary display"); } else { - ((Gtk.Image) primary_image.image).icon_name = "non-starred-symbolic"; + primary_image.icon_name = "non-starred-symbolic"; primary_image.tooltip_text = _("Set as primary display"); } use_switch.sensitive = !is_primary; } - public override void get_preferred_width (out int minimum_width, out int natural_width) { - minimum_width = (int)(real_width * window_ratio); - natural_width = minimum_width; - } + public new void get_preferred_size (out Gtk.Requisition minimum_size, out Gtk.Requisition natural_size) { + minimum_size = Gtk.Requisition () { + height = (int)(real_height * window_ratio), + width = (int)(real_width * window_ratio) + }; - public override void get_preferred_height (out int minimum_height, out int natural_height) { - minimum_height = (int)(real_height * window_ratio); - natural_height = minimum_height; + natural_size = minimum_size; } public void get_virtual_monitor_geometry (out int x, out int y, out int width, out int height) { @@ -549,17 +547,17 @@ public class Display.DisplayWidget : Gtk.EventBox { real_width = width; real_height = height; - queue_resize_no_redraw (); + queue_resize (); } public void move_x (int dx) { virtual_monitor.x += dx; - queue_resize_no_redraw (); + queue_resize (); } public void move_y (int dy) { virtual_monitor.y += dy; - queue_resize_no_redraw (); + queue_resize (); } public bool equals (DisplayWidget sibling) { diff --git a/src/Widgets/DisplaysOverlay.vala b/src/Widgets/DisplaysOverlay.vala index 2146cdfb..8441fb11 100644 --- a/src/Widgets/DisplaysOverlay.vala +++ b/src/Widgets/DisplaysOverlay.vala @@ -33,9 +33,8 @@ public class Display.DisplaysOverlay : Gtk.Box { // display widgets to changes in real monitor position and ensuring display widgets // fit inside overlay after dragging. private double current_ratio = 1.0f; - - private int current_allocated_width = 0; - private int current_allocated_height = 0; + private int current_width = 0; + private int current_height = 0; private int default_x_margin = 0; private int default_y_margin = 0; @@ -73,18 +72,20 @@ public class Display.DisplaysOverlay : Gtk.Box { private Gtk.GestureDrag drag_gesture; construct { - get_style_context ().add_class (Gtk.STYLE_CLASS_VIEW); + add_css_class (Granite.STYLE_CLASS_VIEW); overlay = new Gtk.Overlay (); - add (overlay); + append (overlay); display_widgets = new List (); - drag_gesture = new Gtk.GestureDrag (this); + drag_gesture = new Gtk.GestureDrag (); drag_gesture.drag_begin.connect (on_drag_begin); drag_gesture.drag_update.connect (on_drag_update); drag_gesture.drag_end.connect (on_drag_end); + add_controller (drag_gesture); + monitor_manager = Display.MonitorManager.get_default (); monitor_manager.notify["virtual-monitor-number"].connect (() => rescan_displays ()); rescan_displays (); @@ -94,10 +95,10 @@ public class Display.DisplaysOverlay : Gtk.Box { static construct { var display_provider = new Gtk.CssProvider (); - display_provider.load_from_resource ("io/elementary/switchboard/display/Display.css"); + display_provider.load_from_resource ("io/elementary/settings/display/Display.css"); - Gtk.StyleContext.add_provider_for_screen ( - Gdk.Screen.get_default (), + Gtk.StyleContext.add_provider_for_display ( + Gdk.Display.get_default (), display_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ); @@ -158,8 +159,8 @@ public class Display.DisplaysOverlay : Gtk.Box { // virtual monitor geometry and any offsets when dragging. private bool get_child_position (Gtk.Widget widget, out Gdk.Rectangle allocation) { allocation = Gdk.Rectangle (); - if (current_allocated_width != get_allocated_width () || - current_allocated_height != get_allocated_height ()) { + if (current_width != get_width () || + current_height != get_height ()) { calculate_ratio (); } @@ -304,28 +305,27 @@ public class Display.DisplaysOverlay : Gtk.Box { max_height = int.max (max_height, y + height); } - current_allocated_width = get_allocated_width (); - current_allocated_height = get_allocated_height (); + current_width = get_width (); + current_height = get_height (); current_ratio = double.min ( - (double) (get_allocated_width () - 24) / (double) added_width, - (double) (get_allocated_height () - 24) / (double) added_height + (double) (get_width () - 24) / (double) added_width, + (double) (get_height () - 24) / (double) added_height ); - default_x_margin = (int) ((get_allocated_width () - max_width * current_ratio) / 2); - default_y_margin = (int) ((get_allocated_height () - max_height * current_ratio) / 2); + default_x_margin = (int) ((get_width () - max_width * current_ratio) / 2); + default_y_margin = (int) ((get_height () - max_height * current_ratio) / 2); } private void add_output (Display.VirtualMonitor virtual_monitor) { - current_allocated_width = 0; - current_allocated_height = 0; + current_width = 0; + current_height = 0; var color_number = (display_widgets.length () - 1) % 7; var display_widget = new DisplayWidget (virtual_monitor, colors[color_number], text_colors[color_number]); - display_widget.get_style_context ().add_class ("color-%u".printf (color_number)); + display_widget.add_css_class ("color-%u".printf (color_number)); overlay.add_overlay (display_widget); display_widgets.append (display_widget); - display_widget.show_all (); display_widget.set_as_primary.connect (() => set_as_primary (display_widget.virtual_monitor)); display_widget.check_position.connect (() => { diff --git a/src/meson.build b/src/meson.build index 14fafff8..60897e1a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -16,21 +16,21 @@ plug_files = files( 'Widgets/DisplaysOverlay.vala', ) -switchboard_dep = dependency('switchboard-2.0') +switchboard_dep = dependency('switchboard-3') switchboard_plugsdir = switchboard_dep.get_pkgconfig_variable('plugsdir', define_variable: ['libdir', libdir]) shared_module( meson.project_name(), plug_files, config_file, - asresources, + gresource, dependencies: [ dependency('glib-2.0'), dependency('gio-2.0'), dependency('gobject-2.0'), - dependency('granite'), - dependency('gtk+-3.0'), - dependency('libhandy-1', version: '>=0.83.0'), + dependency('granite-7'), + dependency('gtk4'), + dependency('libadwaita-1'), meson.get_compiler('vala').find_library('posix'), switchboard_dep ],