Skip to content

Commit 9bd15f2

Browse files
committed
Added feature to resize horizontally & apply XY position offset via preferences window sliders
1 parent 11812eb commit 9bd15f2

5 files changed

Lines changed: 141 additions & 41 deletions

File tree

ddterm/app/application.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,13 +339,13 @@ export class Application extends Gtk.Application {
339339
'hide': () => this.#window?.hide(),
340340
'window-size-dec': () => {
341341
if (this.#settings.get_boolean('window-maximize'))
342-
this.#settings.set_double('window-size', 1.0 - SIZE_STEP);
342+
this.#settings.set_double('window-size-y', 1.0 - SIZE_STEP);
343343
else
344-
this.#adjust_double_setting('window-size', -SIZE_STEP);
344+
this.#adjust_double_setting('window-size-y', -SIZE_STEP);
345345
},
346346
'window-size-inc': () => {
347347
if (!this.#settings.get_boolean('window-maximize'))
348-
this.#adjust_double_setting('window-size', SIZE_STEP);
348+
this.#adjust_double_setting('window-size-y', SIZE_STEP);
349349
},
350350
'background-opacity-dec': () => {
351351
this.#adjust_double_setting('background-opacity', -OPACITY_STEP);

ddterm/pref/positionsize.js

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -280,38 +280,68 @@ export class PositionSizeGroup extends PreferencesGroup {
280280
},
281281
});
282282

283-
const window_size_adjustment = new Gtk.Adjustment({
284-
upper: 1,
285-
step_increment: 0.01,
286-
page_increment: 0.10,
283+
this.add_slider({
284+
key: 'window-size-x',
285+
title: 'Window Width',
286+
percent: true,
287+
lower: 0,
288+
upper: 1
289+
});
290+
291+
this.add_slider({
292+
key: 'window-size-y',
293+
title: 'Window Height',
294+
percent: true,
295+
lower: 0,
296+
upper: 1
297+
});
298+
299+
this.add_slider({
300+
key: 'pos-x-offset',
301+
title: 'Horizontal Offset',
302+
});
303+
304+
this.add_slider({
305+
key: 'pos-y-offset',
306+
title: 'Vertical Offset',
307+
});
308+
}
309+
310+
add_slider({ key, title, lower = -0.5, upper = 0.5, step = 0.01, digits = 2, percent = true }) {
311+
const adjustment = new Gtk.Adjustment({
312+
lower,
313+
upper,
314+
step_increment: step,
315+
page_increment: step * 10,
287316
});
288317

289318
this.settings.bind(
290-
'window-size',
291-
window_size_adjustment,
319+
key,
320+
adjustment,
292321
'value',
293322
Gio.SettingsBindFlags.DEFAULT
294323
);
295324

296-
const window_size_row = new ScaleRow({
297-
adjustment: window_size_adjustment,
298-
digits: 2,
299-
round_digits: 2,
325+
const row = new ScaleRow({
326+
adjustment,
327+
digits,
328+
round_digits: digits,
300329
visible: true,
301-
use_underline: true,
302-
title: this.gettext('Window _Size'),
330+
title: this.gettext(title),
303331
});
304332

305-
const percent_format = new Intl.NumberFormat(undefined, { style: 'percent' });
306-
window_size_row.set_format_value_func((_, v) => percent_format.format(v));
333+
if (percent) {
334+
const percent_format = new Intl.NumberFormat(undefined, { style: 'percent' });
335+
row.set_format_value_func((_, v) => percent_format.format(v));
336+
}
307337

308338
this.settings.bind_writable(
309-
'window-size',
310-
window_size_row,
339+
key,
340+
row,
311341
'sensitive',
312342
false
313343
);
314344

315-
this.add(window_size_row);
345+
this.add(row);
316346
}
317347
}

ddterm/shell/geometry.js

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,18 @@ export const WindowGeometry = GObject.registerClass({
6969
Meta.MaximizeFlags,
7070
Meta.MaximizeFlags.VERTICAL
7171
),
72-
'window-size': GObject.ParamSpec.double(
73-
'window-size',
72+
'window-size-x': GObject.ParamSpec.double(
73+
'window-size-x',
74+
null,
75+
null,
76+
GObject.ParamFlags.READWRITE | GObject.ParamFlags.EXPLICIT_NOTIFY,
77+
0,
78+
1,
79+
1
80+
),
81+
82+
'window-size-y': GObject.ParamSpec.double(
83+
'window-size-y',
7484
null,
7585
null,
7686
GObject.ParamFlags.READWRITE | GObject.ParamFlags.EXPLICIT_NOTIFY,
@@ -86,6 +96,24 @@ export const WindowGeometry = GObject.registerClass({
8696
Meta.Side,
8797
Meta.Side.TOP
8898
),
99+
'pos-x-offset': GObject.ParamSpec.double(
100+
'pos-x-offset',
101+
null,
102+
null,
103+
GObject.ParamFlags.READWRITE | GObject.ParamFlags.EXPLICIT_NOTIFY,
104+
-10000,
105+
10000,
106+
0
107+
),
108+
'pos-y-offset': GObject.ParamSpec.double(
109+
'pos-y-offset',
110+
null,
111+
null,
112+
GObject.ParamFlags.READWRITE | GObject.ParamFlags.EXPLICIT_NOTIFY,
113+
-10000,
114+
10000,
115+
0
116+
),
89117
'window-monitor': GObject.ParamSpec.string(
90118
'window-monitor',
91119
null,
@@ -123,7 +151,10 @@ export const WindowGeometry = GObject.registerClass({
123151
this.#update_workarea.bind(this)
124152
);
125153

126-
this.connect('notify::window-size', this.#update_target_rect.bind(this));
154+
this.connect('notify::window-size-x', this.#update_target_rect.bind(this));
155+
this.connect('notify::window-size-y', this.#update_target_rect.bind(this));
156+
this.connect('notify::pos-x-offset', this.#update_target_rect.bind(this));
157+
this.connect('notify::pos-y-offset', this.#update_target_rect.bind(this));
127158
this.connect('notify::window-position', this.#update_window_position.bind(this));
128159
this.connect('notify::window-monitor', this.update_monitor.bind(this));
129160
this.connect('notify::window-monitor-connector', this.update_monitor.bind(this));
@@ -139,33 +170,54 @@ export const WindowGeometry = GObject.registerClass({
139170
}
140171
}
141172

142-
static get_target_rect(workarea, monitor_scale, size, window_pos) {
143-
const target_rect = workarea.copy();
173+
static get_target_rect(workarea, monitor_scale, size_x, size_y, window_pos, pos_x_offset, pos_y_offset) {
174+
if (size_x === 1 && size_y === 1 && pos_x_offset === 0 && pos_y_offset === 0)
175+
return workarea.copy();
144176

145-
if (size === 1)
146-
return target_rect;
177+
const target_rect = workarea.copy();
147178

148179
if (window_pos === Meta.Side.LEFT || window_pos === Meta.Side.RIGHT) {
149-
target_rect.width *= size;
150-
target_rect.width -= target_rect.width % monitor_scale;
180+
target_rect.height *= size_y;
181+
target_rect.height -= target_rect.height % monitor_scale;
151182

152183
if (window_pos === Meta.Side.RIGHT)
153184
target_rect.x += workarea.width - target_rect.width;
154185
} else {
155-
target_rect.height *= size;
186+
target_rect.height *= size_y;
156187
target_rect.height -= target_rect.height % monitor_scale;
157188

189+
target_rect.width *= size_x;
190+
target_rect.width -= target_rect.width % monitor_scale;
191+
192+
target_rect.x += Math.floor((workarea.width - target_rect.width) / 2);
193+
158194
if (window_pos === Meta.Side.BOTTOM)
159195
target_rect.y += workarea.height - target_rect.height;
160196
}
161197

198+
target_rect.x -= pos_x_offset * workarea.width;
199+
target_rect.y -= pos_y_offset * workarea.height;
200+
201+
target_rect.x = Math.min(
202+
Math.max(target_rect.x, workarea.x),
203+
workarea.x + workarea.width - target_rect.width
204+
);
205+
206+
target_rect.y = Math.min(
207+
Math.max(target_rect.y, workarea.y),
208+
workarea.y + workarea.height - target_rect.height
209+
);
210+
162211
return target_rect;
163212
}
164213

165214
bind_settings(settings) {
166215
[
167-
'window-size',
216+
'window-size-x',
217+
'window-size-y',
168218
'window-position',
219+
'pos-x-offset',
220+
'pos-y-offset',
169221
'window-monitor',
170222
'window-monitor-connector',
171223
].forEach(key => {
@@ -355,8 +407,11 @@ export const WindowGeometry = GObject.registerClass({
355407
const target_rect = WindowGeometry.get_target_rect(
356408
this.#workarea,
357409
Math.floor(this.#monitor_scale),
358-
this.window_size,
359-
this.window_position
410+
this.window_size_x,
411+
this.window_size_y,
412+
this.window_position,
413+
this.pos_x_offset,
414+
this.pos_y_offset,
360415
);
361416

362417
this.#set_target_rect(target_rect);

ddterm/shell/wm.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ export const WindowManager = GObject.registerClass({
114114
this.#settings_handlers = Object.entries({
115115
'changed::window-above': this.#set_window_above.bind(this),
116116
'changed::window-stick': this.#set_window_stick.bind(this),
117-
'changed::window-size': this.#disable_window_maximize_setting.bind(this),
117+
'changed::window-size-x': this.#disable_window_maximize_setting.bind(this),
118+
'changed::window-size-y': this.#disable_window_maximize_setting.bind(this),
118119
'changed::window-maximize': this.#set_window_maximized.bind(this),
119120
'changed::hide-when-focus-lost': this.#setup_hide_when_focus_lost.bind(this),
120121
}).map(
@@ -565,7 +566,7 @@ export const WindowManager = GObject.registerClass({
565566
return;
566567

567568
if (MOUSE_RESIZE_GRABS.includes(flags))
568-
this.#unmaximize_for_resize(this.geometry.maximize_flag);
569+
this.#unmaximize_for_resize(Meta.MaximizeFlags.BOTH);
569570
}
570571

571572
#update_size_setting_on_grab_end(display, win) {
@@ -578,11 +579,12 @@ export const WindowManager = GObject.registerClass({
578579
this.logger?.log('Updating size setting on grab end');
579580

580581
const frame_rect = win.get_frame_rect();
581-
const size = this.geometry.orientation === Clutter.Orientation.HORIZONTAL
582-
? frame_rect.width / this.geometry.workarea.width
583-
: frame_rect.height / this.geometry.workarea.height;
584582

585-
this.settings.set_double('window-size', Math.min(1.0, size));
583+
const size_x = Math.min(1.0, frame_rect.width / this.geometry.workarea.width);
584+
const size_y = Math.min(1.0, frame_rect.height / this.geometry.workarea.height);
585+
586+
this.settings.set_double('window-size-x', size_x);
587+
this.settings.set_double('window-size-y', size_y);
586588
}
587589

588590
#unmaximize_for_resize(flags) {
@@ -595,7 +597,8 @@ export const WindowManager = GObject.registerClass({
595597

596598
// There is a _update_window_geometry() call after successful unmaximize.
597599
// It must set window size to 100%.
598-
this.settings.set_double('window-size', 1.0);
600+
this.settings.set_double('window-size-x', 1.0);
601+
this.settings.set_double('window-size-y', 1.0);
599602

600603
Main.wm.skipNextEffect(this.#actor);
601604
this.#set_unmaximize_flags(flags);

schemas/com.github.amezin.ddterm.gschema.xml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,11 @@ SPDX-License-Identifier: GPL-3.0-or-later
134134
</enum>
135135

136136
<schema path="/com/github/amezin/ddterm/" id="com.github.amezin.ddterm">
137-
<key name="window-size" type="d">
137+
<key name="window-size-x" type="d">
138+
<default>1.0</default>
139+
<range min="0.0" max="1.0"/>
140+
</key>
141+
<key name="window-size-y" type="d">
138142
<default>0.6</default>
139143
<range min="0.0" max="1.0"/>
140144
</key>
@@ -144,6 +148,14 @@ SPDX-License-Identifier: GPL-3.0-or-later
144148
<key name="window-position" enum="com.github.amezin.ddterm.WindowPosition">
145149
<default>'top'</default>
146150
</key>
151+
<key name="pos-x-offset" type="d">
152+
<default>0.0</default>
153+
<range min="-10000.0" max="10000.0"/>
154+
</key>
155+
<key name="pos-y-offset" type="d">
156+
<default>0.0</default>
157+
<range min="-10000.0" max="10000.0"/>
158+
</key>
147159
<key name="window-monitor" enum="com.github.amezin.ddterm.WindowMonitor">
148160
<default>'current'</default>
149161
</key>

0 commit comments

Comments
 (0)