diff --git a/ddterm/app/application.js b/ddterm/app/application.js index 0c9fbd2d2..9f6c33a06 100644 --- a/ddterm/app/application.js +++ b/ddterm/app/application.js @@ -347,6 +347,17 @@ export class Application extends Gtk.Application { if (!this.#settings.get_boolean('window-maximize')) this.#adjust_double_setting('window-size', SIZE_STEP); }, + 'window-size-secondary-dec': () => { + if (this.#settings.get_boolean('window-maximize')) + this.#settings.set_double('window-size-secondary', 1.0 - SIZE_STEP); + else + this.#adjust_double_setting('window-size-secondary', -SIZE_STEP); + }, + + 'window-size-secondary-inc': () => { + if (!this.#settings.get_boolean('window-maximize')) + this.#adjust_double_setting('window-size-secondary', SIZE_STEP); + }, 'background-opacity-dec': () => { this.#adjust_double_setting('background-opacity', -OPACITY_STEP); }, @@ -416,6 +427,8 @@ export class Application extends Gtk.Application { 'shortcut-window-hide': 'win.hide', 'shortcut-window-size-inc': 'app.window-size-inc', 'shortcut-window-size-dec': 'app.window-size-dec', + 'shortcut-window-size-secondary-inc': 'app.window-size-secondary-inc', + 'shortcut-window-size-secondary-dec': 'app.window-size-secondary-dec', 'shortcut-background-opacity-inc': 'app.background-opacity-inc', 'shortcut-background-opacity-dec': 'app.background-opacity-dec', 'shortcut-toggle-maximize': 'app.window-maximize', diff --git a/ddterm/pref/positionsize.js b/ddterm/pref/positionsize.js index 5446ce548..efd4ea279 100644 --- a/ddterm/pref/positionsize.js +++ b/ddterm/pref/positionsize.js @@ -7,7 +7,7 @@ import GObject from 'gi://GObject'; import Gio from 'gi://Gio'; import Gtk from 'gi://Gtk'; -import { PreferencesGroup, ComboRow, ScaleRow } from './util.js'; +import { PreferencesGroup, ComboRow } from './util.js'; import { Monitor } from '../util/displayconfig.js'; class SpecialMonitor extends Monitor { @@ -280,38 +280,24 @@ export class PositionSizeGroup extends PreferencesGroup { }, }); - const window_size_adjustment = new Gtk.Adjustment({ - upper: 1, - step_increment: 0.01, - page_increment: 0.10, - }); - - this.settings.bind( - 'window-size', - window_size_adjustment, - 'value', - Gio.SettingsBindFlags.DEFAULT - ); - - const window_size_row = new ScaleRow({ - adjustment: window_size_adjustment, - digits: 2, - round_digits: 2, - visible: true, - use_underline: true, + this.add_scale_row({ + key: 'window-size', + adjustment: new Gtk.Adjustment({ + upper: 1, + step_increment: 0.01, + page_increment: 0.10, + }), title: this.gettext('Window _Size'), }); - const percent_format = new Intl.NumberFormat(undefined, { style: 'percent' }); - window_size_row.set_format_value_func((_, v) => percent_format.format(v)); - - this.settings.bind_writable( - 'window-size', - window_size_row, - 'sensitive', - false - ); - - this.add(window_size_row); + this.add_scale_row({ + key: 'window-size-secondary', + adjustment: new Gtk.Adjustment({ + upper: 1, + step_increment: 0.01, + page_increment: 0.10, + }), + title: this.gettext('Window Size Secondary'), + }); } } diff --git a/ddterm/pref/shortcuts.js b/ddterm/pref/shortcuts.js index 47831d5f1..38ed8e867 100644 --- a/ddterm/pref/shortcuts.js +++ b/ddterm/pref/shortcuts.js @@ -533,6 +533,16 @@ export class ApplicationShortcutGroup extends ShortcutGroup { title: this.gettext('Decrease Window Size'), }); + this.add_shortcut_row({ + key: 'shortcut-window-size-secondary-inc', + title: this.gettext('Increase Secondary Window Size'), + }); + + this.add_shortcut_row({ + key: 'shortcut-window-size-secondary-dec', + title: this.gettext('Decrease Secondary Window Size'), + }); + this.add_shortcut_row({ key: 'shortcut-background-opacity-inc', title: this.gettext('Increase Background Opacity'), diff --git a/ddterm/pref/util.js b/ddterm/pref/util.js index 81c816a15..c8c4a0479 100644 --- a/ddterm/pref/util.js +++ b/ddterm/pref/util.js @@ -558,6 +558,38 @@ export class ScaleRow extends ActionRow { } } +function create_scale_row({ + settings, + key, + adjustment, + flags = Gio.SettingsBindFlags.DEFAULT, + percent = true, + ...params +}) { + const row = new ScaleRow({ + visible: true, + use_underline: true, + adjustment, + ...params, + }); + + settings.bind(key, adjustment, 'value', flags); + + settings.bind_writable( + key, + row, + 'sensitive', + false + ); + + if (percent) { + const percent_format = new Intl.NumberFormat(undefined, { style: 'percent' }); + row.set_format_value_func((_, v) => percent_format.format(v)); + } + + return row; +} + export class ExpanderRow extends AdwOrHdy.ExpanderRow { static [GObject.GTypeName] = 'DDTermExpanderRow'; @@ -676,6 +708,14 @@ export class PreferencesGroup extends AdwOrHdy.PreferencesGroup { return row; } + + add_scale_row(params) { + const row = create_scale_row({ settings: this.settings, ...params }); + + this.add(row); + + return row; + } } export class PreferencesPage extends AdwOrHdy.PreferencesPage { diff --git a/ddterm/shell/geometry.js b/ddterm/shell/geometry.js index a81bd9531..d3d679d9e 100644 --- a/ddterm/shell/geometry.js +++ b/ddterm/shell/geometry.js @@ -78,6 +78,15 @@ export const WindowGeometry = GObject.registerClass({ 1, 0.6 ), + 'window-size-secondary': GObject.ParamSpec.double( + 'window-size-secondary', + null, + null, + GObject.ParamFlags.READWRITE | GObject.ParamFlags.EXPLICIT_NOTIFY, + 0, + 1, + 1 + ), 'window-position': GObject.ParamSpec.enum( 'window-position', null, @@ -124,6 +133,7 @@ export const WindowGeometry = GObject.registerClass({ ); this.connect('notify::window-size', this.#update_target_rect.bind(this)); + this.connect('notify::window-size-secondary', this.#update_target_rect.bind(this)); this.connect('notify::window-position', this.#update_window_position.bind(this)); this.connect('notify::window-monitor', this.update_monitor.bind(this)); this.connect('notify::window-monitor-connector', this.update_monitor.bind(this)); @@ -139,24 +149,35 @@ export const WindowGeometry = GObject.registerClass({ } } - static get_target_rect(workarea, monitor_scale, size, window_pos) { + static get_target_rect(workarea, monitor_scale, size, size_secondary, window_pos) { const target_rect = workarea.copy(); - if (size === 1) - return target_rect; - if (window_pos === Meta.Side.LEFT || window_pos === Meta.Side.RIGHT) { - target_rect.width *= size; - target_rect.width -= target_rect.width % monitor_scale; + if (size !== 1) { + target_rect.width *= size; + target_rect.width -= target_rect.width % monitor_scale; - if (window_pos === Meta.Side.RIGHT) - target_rect.x += workarea.width - target_rect.width; - } else { - target_rect.height *= size; + if (window_pos === Meta.Side.RIGHT) + target_rect.x += workarea.width - target_rect.width; + } + target_rect.height *= size_secondary; target_rect.height -= target_rect.height % monitor_scale; + target_rect.height = Math.floor(target_rect.height); + + target_rect.y += Math.floor((workarea.height - target_rect.height) / 2); + } else { + if (size !== 1) { + target_rect.height *= size; + target_rect.height -= target_rect.height % monitor_scale; + + if (window_pos === Meta.Side.BOTTOM) + target_rect.y += workarea.height - target_rect.height; + } + target_rect.width *= size_secondary; + target_rect.width -= target_rect.width % monitor_scale; + target_rect.width = Math.floor(target_rect.width); - if (window_pos === Meta.Side.BOTTOM) - target_rect.y += workarea.height - target_rect.height; + target_rect.x += Math.floor((workarea.width - target_rect.width) / 2); } return target_rect; @@ -165,6 +186,7 @@ export const WindowGeometry = GObject.registerClass({ bind_settings(settings) { [ 'window-size', + 'window-size-secondary', 'window-position', 'window-monitor', 'window-monitor-connector', @@ -356,6 +378,7 @@ export const WindowGeometry = GObject.registerClass({ this.#workarea, Math.floor(this.#monitor_scale), this.window_size, + this.window_size_secondary, this.window_position ); diff --git a/ddterm/shell/wm.js b/ddterm/shell/wm.js index e1859118e..c8a2f24e6 100644 --- a/ddterm/shell/wm.js +++ b/ddterm/shell/wm.js @@ -115,6 +115,7 @@ export const WindowManager = GObject.registerClass({ 'changed::window-above': this.#set_window_above.bind(this), 'changed::window-stick': this.#set_window_stick.bind(this), 'changed::window-size': this.#disable_window_maximize_setting.bind(this), + 'changed::window-size-secondary': this.#disable_window_maximize_setting.bind(this), 'changed::window-maximize': this.#set_window_maximized.bind(this), 'changed::hide-when-focus-lost': this.#setup_hide_when_focus_lost.bind(this), }).map( @@ -578,11 +579,17 @@ export const WindowManager = GObject.registerClass({ this.logger?.log('Updating size setting on grab end'); const frame_rect = win.get_frame_rect(); - const size = this.geometry.orientation === Clutter.Orientation.HORIZONTAL + + const primary = this.geometry.orientation === Clutter.Orientation.HORIZONTAL ? frame_rect.width / this.geometry.workarea.width : frame_rect.height / this.geometry.workarea.height; - this.settings.set_double('window-size', Math.min(1.0, size)); + const secondary = this.geometry.orientation === Clutter.Orientation.HORIZONTAL + ? frame_rect.height / this.geometry.workarea.height + : frame_rect.width / this.geometry.workarea.width; + + this.settings.set_double('window-size', Math.min(1.0, primary)); + this.settings.set_double('window-size-secondary', Math.min(1.0, secondary)); } #unmaximize_for_resize(flags) { @@ -596,6 +603,7 @@ export const WindowManager = GObject.registerClass({ // There is a _update_window_geometry() call after successful unmaximize. // It must set window size to 100%. this.settings.set_double('window-size', 1.0); + this.settings.set_double('window-size-secondary', 1.0); Main.wm.skipNextEffect(this.#actor); this.#set_unmaximize_flags(flags); diff --git a/schemas/com.github.amezin.ddterm.gschema.xml b/schemas/com.github.amezin.ddterm.gschema.xml index 5e8f01149..e47b01099 100644 --- a/schemas/com.github.amezin.ddterm.gschema.xml +++ b/schemas/com.github.amezin.ddterm.gschema.xml @@ -138,6 +138,10 @@ SPDX-License-Identifier: GPL-3.0-or-later 0.6 + + 1.0 + + false @@ -385,6 +389,13 @@ SPDX-License-Identifier: GPL-3.0-or-later Up']]]> + + Down']]]> + + + + Up']]]> +