diff --git a/gnome/src/extension.js b/gnome/src/extension.js index b993221..4710881 100644 --- a/gnome/src/extension.js +++ b/gnome/src/extension.js @@ -292,7 +292,8 @@ export default class BreezyDesktopExtension extends Extension { 'display-size', 'framerate-cap', 'look-ahead-override', - 'disable-anti-aliasing' + 'disable-anti-aliasing', + 'display-dimming' ] this._effect_settings_bindings.forEach(settings_key => this.settings.bind(settings_key, this._virtual_displays_actor, settings_key, Gio.SettingsBindFlags.DEFAULT) diff --git a/gnome/src/virtualdisplayeffect.js b/gnome/src/virtualdisplayeffect.js index f4b29f5..43b6f1d 100644 --- a/gnome/src/virtualdisplayeffect.js +++ b/gnome/src/virtualdisplayeffect.js @@ -242,6 +242,15 @@ export const VirtualDisplayEffect = GObject.registerClass({ 45, -1 ), + 'display-dimming': GObject.ParamSpec.double( + 'display-dimming', + 'Display dimming', + 'Dim the display brightness (0.0 to 1.0)', + GObject.ParamFlags.READWRITE, + 0.0, + 1.0, + 1.0 + ), } }, class VirtualDisplayEffect extends Shell.GLSLEffect { constructor(params = {}) { @@ -257,6 +266,7 @@ export const VirtualDisplayEffect = GObject.registerClass({ this.connect('notify::monitor-placements', this._update_display_position.bind(this)); this.connect('notify::show-banner', this._handle_banner_update.bind(this)); this.connect('notify::smooth-follow-enabled', this._handle_smooth_follow_enabled_update.bind(this)); + this.connect('notify::display-dimming', this._handle_dimming_update.bind(this)); this._update_display_position(); } @@ -402,6 +412,12 @@ export const VirtualDisplayEffect = GObject.registerClass({ this.set_uniform_float(this.get_uniform_location("u_show_banner"), 1, [this.show_banner ? 1.0 : 0.0]); } + _handle_dimming_update() { + if (this._initialized) { + this.set_uniform_float(this.get_uniform_location("u_display_dimming"), 1, [this.display_dimming]); + } + } + perspective(fovHorizontalRadians, aspect, near, far) { const f = 1.0 / Math.tan(fovHorizontalRadians / 2.0); const range = far - near; @@ -538,6 +554,15 @@ export const VirtualDisplayEffect = GObject.registerClass({ ` this.add_glsl_snippet(Cogl.SnippetHook?.VERTEX ?? Shell.SnippetHook.VERTEX, declarations, main, false); + + // Fragment shader for dimming + const fragmentDeclarations = ` + uniform float u_display_dimming; + `; + const fragmentMain = ` + cogl_color_out.rgb *= u_display_dimming; + `; + this.add_glsl_snippet(Cogl.SnippetHook?.FRAGMENT ?? Shell.SnippetHook.FRAGMENT, fragmentDeclarations, fragmentMain, false); } vfunc_paint_target(node, paintContext) { @@ -561,6 +586,7 @@ export const VirtualDisplayEffect = GObject.registerClass({ this.set_uniform_float(this.get_uniform_location("u_lens_vector"), 3, this.lens_vector); this._update_display_position(); this._handle_banner_update(); + this._handle_dimming_update(); } if (this.imu_snapshots && !this.show_banner) { diff --git a/gnome/src/virtualdisplaysactor.js b/gnome/src/virtualdisplaysactor.js index 4f7d7db..f7534e6 100644 --- a/gnome/src/virtualdisplaysactor.js +++ b/gnome/src/virtualdisplaysactor.js @@ -572,6 +572,15 @@ export const VirtualDisplaysActor = GObject.registerClass({ 'Disable anti-aliasing for the effect', GObject.ParamFlags.READWRITE, false + ), + 'display-dimming': GObject.ParamSpec.double( + 'display-dimming', + 'Display dimming', + 'Dim the display brightness (0.0 to 1.0)', + GObject.ParamFlags.READWRITE, + 0.0, + 1.0, + 1.0 ) } }, class VirtualDisplaysActor extends Clutter.Actor { @@ -743,7 +752,8 @@ export const VirtualDisplaysActor = GObject.registerClass({ 'lens-vector', 'look-ahead-override', 'disable-anti-aliasing', - 'show-banner' + 'show-banner', + 'display-dimming' ].forEach((property => { this._property_bindings.push(this.bind_property(property, effect, property, GObject.BindingFlags.DEFAULT)); })); diff --git a/kwin/src/breezydesktopconfig.kcfg b/kwin/src/breezydesktopconfig.kcfg index 99cfec4..5501b86 100644 --- a/kwin/src/breezydesktopconfig.kcfg +++ b/kwin/src/breezydesktopconfig.kcfg @@ -91,5 +91,12 @@ Curve the displays around you + + 100 + 0 + 100 + + Dim the display brightness (0-100%) + diff --git a/kwin/src/breezydesktopeffect.cpp b/kwin/src/breezydesktopeffect.cpp index d0f3a64..eeb4f9d 100644 --- a/kwin/src/breezydesktopeffect.cpp +++ b/kwin/src/breezydesktopeffect.cpp @@ -265,6 +265,9 @@ void BreezyDesktopEffect::reconfigure(ReconfigureFlags) bool curved = BreezyDesktopConfig::curvedDisplay() && m_curvedDisplaySupported; if (m_curvedDisplay != curved) { m_curvedDisplay = curved; Q_EMIT curvedDisplayChanged(); } + qreal dimming = BreezyDesktopConfig::displayDimming() / 100.0; + if (!qFuzzyCompare(m_displayDimming, dimming)) { m_displayDimming = dimming; Q_EMIT displayDimmingChanged(); } + // this one doesn't have a signal, just always assign it m_allDisplaysFollowMode = BreezyDesktopConfig::allDisplaysFollowMode(); } @@ -563,6 +566,10 @@ bool BreezyDesktopEffect::curvedDisplaySupported() const { return m_curvedDisplaySupported; } +qreal BreezyDesktopEffect::displayDimming() const { + return m_displayDimming; +} + void BreezyDesktopEffect::setCurvedDisplaySupported(bool supported) { if (m_curvedDisplaySupported != supported) { m_curvedDisplaySupported = supported; diff --git a/kwin/src/breezydesktopeffect.h b/kwin/src/breezydesktopeffect.h index 328a67d..56a987e 100644 --- a/kwin/src/breezydesktopeffect.h +++ b/kwin/src/breezydesktopeffect.h @@ -52,6 +52,7 @@ namespace KWin Q_PROPERTY(bool mirrorPhysicalDisplays READ mirrorPhysicalDisplays NOTIFY mirrorPhysicalDisplaysChanged) Q_PROPERTY(bool curvedDisplay READ curvedDisplay NOTIFY curvedDisplayChanged) Q_PROPERTY(bool curvedDisplaySupported READ curvedDisplaySupported WRITE setCurvedDisplaySupported NOTIFY curvedDisplaySupportedChanged) + Q_PROPERTY(qreal displayDimming READ displayDimming NOTIFY displayDimmingChanged) public: @@ -103,6 +104,7 @@ namespace KWin bool mirrorPhysicalDisplays() const; bool curvedDisplay() const; void setCurvedDisplaySupported(bool supported); + qreal displayDimming() const; void showCursor(); void hideCursor(); @@ -142,6 +144,7 @@ namespace KWin void curvedDisplaySupportedChanged(); void cursorImageSourceChanged(); void cursorPosChanged(); + void displayDimmingChanged(); protected: QVariantMap initialProperties(Output *screen) override; @@ -199,6 +202,7 @@ namespace KWin bool m_mirrorPhysicalDisplays = false; bool m_curvedDisplay = false; bool m_curvedDisplaySupported = false; + qreal m_displayDimming = 1.0; float m_smoothFollowThreshold = 1.0f; bool m_allDisplaysFollowMode = false; bool m_focusedSmoothFollowEnabled = false; diff --git a/kwin/src/kcm/breezydesktopeffectkcm.ui b/kwin/src/kcm/breezydesktopeffectkcm.ui index 372b818..6b4d183 100644 --- a/kwin/src/kcm/breezydesktopeffectkcm.ui +++ b/kwin/src/kcm/breezydesktopeffectkcm.ui @@ -196,7 +196,36 @@ - + + + + Display brightness: + + + + + + + Qt::Horizontal + + + true + + + QSlider::NoTicks + + + 0 + + + 25 + + + % + + + + Add Virtual Display: @@ -209,7 +238,7 @@ - + false @@ -272,7 +301,7 @@ - + false false @@ -285,7 +314,7 @@ - + diff --git a/kwin/src/qml/BreezyDesktopDisplay.qml b/kwin/src/qml/BreezyDesktopDisplay.qml index e4ce5d7..0c9d321 100644 --- a/kwin/src/qml/BreezyDesktopDisplay.qml +++ b/kwin/src/qml/BreezyDesktopDisplay.qml @@ -57,6 +57,7 @@ Model { property real cursorW: display.cursorImageSize.width property real cursorH: display.cursorImageSize.height property bool showCursor: cursorX >= 0 && cursorX < screenWidth && cursorY >= 0 && cursorY < screenHeight + property real displayDimming: effect.displayDimming property TextureInput desktopTex: TextureInput { texture: Texture { diff --git a/kwin/src/qml/cursorOverlay.frag b/kwin/src/qml/cursorOverlay.frag index 4660e60..0a17b97 100644 --- a/kwin/src/qml/cursorOverlay.frag +++ b/kwin/src/qml/cursorOverlay.frag @@ -14,5 +14,7 @@ void MAIN() { color = mix(color, cursorCol, cursorCol.a); } } + // Apply dimming by scaling RGB towards black while preserving alpha + color.rgb *= displayDimming; FRAGCOLOR = color; } \ No newline at end of file diff --git a/ui/data/com.xronlinux.BreezyDesktop.gschema.xml b/ui/data/com.xronlinux.BreezyDesktop.gschema.xml index 6704f6e..32214fb 100644 --- a/ui/data/com.xronlinux.BreezyDesktop.gschema.xml +++ b/ui/data/com.xronlinux.BreezyDesktop.gschema.xml @@ -279,6 +279,15 @@ Framerate cap + + + + 1.0 + + Display dimming + + Dim the display brightness (0.0 to 1.0) + diff --git a/ui/src/connecteddevice.py b/ui/src/connecteddevice.py index ee1442c..6090711 100644 --- a/ui/src/connecteddevice.py +++ b/ui/src/connecteddevice.py @@ -35,6 +35,8 @@ class ConnectedDevice(Gtk.Box): display_zoom_on_focus_switch = Gtk.Template.Child() follow_threshold_scale = Gtk.Template.Child() follow_threshold_adjustment = Gtk.Template.Child() + display_dimming_scale = Gtk.Template.Child() + display_dimming_adjustment = Gtk.Template.Child() follow_mode_switch = Gtk.Template.Child() curved_display_switch = Gtk.Template.Child() top_features_group = Gtk.Template.Child() @@ -130,6 +132,10 @@ class ConnectedDevice(Gtk.Box): self.settings.bind('monitor-spacing', self.monitor_spacing_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT) self.settings.bind('viewport-offset-x', self.viewport_offset_x_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT) self.settings.bind('viewport-offset-y', self.viewport_offset_y_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT) + + # Display dimming uses 0-100 in UI but 0.0-1.0 in settings + self.display_dimming_adjustment.set_value(self.settings.get_double('display-dimming') * 100) + self.display_dimming_adjustment.connect('value-changed', self._on_display_dimming_changed) self.settings.connect('changed::monitor-wrapping-scheme', self._handle_monitor_wrapping_scheme_setting_changed) self.desktop_settings.bind('text-scaling-factor', self.text_scaling_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT) self.display_zoom_on_focus_switch.connect('notify::active', self._handle_zoom_on_focus_switch_changed) @@ -244,6 +250,9 @@ class ConnectedDevice(Gtk.Box): def _handle_monitor_wrapping_scheme_menu_changed(self, widget): self.settings.set_string('monitor-wrapping-scheme', widget.get_active_id()) + def _on_display_dimming_changed(self, adjustment): + self.settings.set_double('display-dimming', adjustment.get_value() / 100.0) + def _handle_enabled_features(self, state_manager, val): enabled_breezy_features = [feature for feature in state_manager.get_property('enabled-features-list') if feature in BREEZY_GNOME_FEATURES] breezy_features_granted = len(enabled_breezy_features) > 0 diff --git a/ui/src/gtk/connected-device.ui b/ui/src/gtk/connected-device.ui index daec778..0169306 100644 --- a/ui/src/gtk/connected-device.ui +++ b/ui/src/gtk/connected-device.ui @@ -253,6 +253,37 @@ + + + Display brightness + Dim the display to reduce eye strain or match ambient lighting. + + + 3 + true + 0 + 0 + 350 + false + + + 0 + 100 + 1 + 100 + + + + 0% + + 50% + + 100% + + + + + Display angling