Skip to content

Commit d7469b8

Browse files
committed
extension/dbus: expose target monitor scale in d-bus interface
1 parent 1f57424 commit d7469b8

File tree

5 files changed

+134
-27
lines changed

5 files changed

+134
-27
lines changed

ddterm/com.github.amezin.ddterm.Extension.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@
77
<method name="Activate"/>
88
<method name="Hide"/>
99
<method name="Service"/>
10+
1011
<method name="GetTargetRect">
1112
<arg type="i" name="x" direction="out"/>
1213
<arg type="i" name="y" direction="out"/>
1314
<arg type="i" name="width" direction="out"/>
1415
<arg type="i" name="height" direction="out"/>
1516
</method>
17+
<method name="GetTargetMonitorScale">
18+
<arg type="d" direction="out"/>
19+
</method>
1620

1721
<method name="MissingDependencies">
1822
<arg type="as" name="packages" direction="in"/>
@@ -25,6 +29,8 @@
2529
<method name="VersionMismatch"/>
2630

2731
<property type="(iiii)" name="TargetRect" access="read"/>
32+
<property type="d" name="TargetMonitorScale" access="read"/>
33+
2834
<property type="s" name="Version" access="read"/>
2935
<property type="s" name="Revision" access="read"/>
3036
</interface>

ddterm/shell/dbusapi.js

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ export const DBusApi = GObject.registerClass({
104104
GObject.ParamFlags.READWRITE | GObject.ParamFlags.EXPLICIT_NOTIFY,
105105
Mtk.Rectangle
106106
),
107+
'target-monitor-scale': GObject.ParamSpec.double(
108+
'target-monitor-scale',
109+
'',
110+
'',
111+
GObject.ParamFlags.READWRITE | GObject.ParamFlags.EXPLICIT_NOTIFY,
112+
0,
113+
100,
114+
1
115+
),
107116
},
108117
Signals: {
109118
'missing-dependencies': {
@@ -113,13 +122,14 @@ export const DBusApi = GObject.registerClass({
113122
param_types: [String, String],
114123
},
115124
'version-mismatch': {},
116-
'refresh-target-rect': {},
125+
'update-target-monitor': {},
117126
},
118127
}, class DDTermDBusApi extends GObject.Object {
119128
_init(params) {
120129
super._init(params);
121130

122131
this._target_rect = new Mtk.Rectangle({ x: 0, y: 0, width: 0, height: 0 });
132+
this._target_monitor_scale = 1;
123133

124134
this.dbus = Gio.DBusExportedObject.wrapJSObject(
125135
Shell.get_file_contents_utf8_sync(this.xml_file_path),
@@ -156,14 +166,23 @@ export const DBusApi = GObject.registerClass({
156166
}
157167

158168
GetTargetRect() {
159-
this.emit('refresh-target-rect');
169+
this.emit('update-target-monitor');
160170
return meta_rect_to_list(this._target_rect);
161171
}
162172

173+
GetTargetMonitorScale() {
174+
this.emit('update-target-monitor');
175+
return this._target_monitor_scale;
176+
}
177+
163178
get TargetRect() {
164179
return this.GetTargetRect();
165180
}
166181

182+
get TargetMonitorScale() {
183+
return this.GetTargetMonitorScale();
184+
}
185+
167186
get Version() {
168187
return this.version;
169188
}
@@ -184,6 +203,19 @@ export const DBusApi = GObject.registerClass({
184203
this.notify('target-rect');
185204

186205
this.dbus.emit_property_changed('TargetRect', meta_rect_to_variant(value));
187-
this.dbus.flush();
206+
}
207+
208+
get target_monitor_scale() {
209+
return this._target_monitor_scale;
210+
}
211+
212+
set target_monitor_scale(value) {
213+
if (this._target_monitor_scale === value)
214+
return;
215+
216+
this._target_monitor_scale = value;
217+
this.notify('target-monitor-scale');
218+
219+
this.dbus.emit_property_changed('TargetMonitorScale', GLib.Variant.new_double(value));
188220
}
189221
});

ddterm/shell/extension.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ function create_dbus_interface(
9595
app_control,
9696
});
9797

98-
dbus_interface.connect('refresh-target-rect', () => {
98+
dbus_interface.connect('update-target-monitor', () => {
9999
/*
100100
* Don't want to track mouse pointer continuously, so try to update the
101101
* index manually in multiple places. Also, Meta.CursorTracker doesn't
@@ -114,13 +114,27 @@ function create_dbus_interface(
114114
notifications.show_version_mismatch();
115115
});
116116

117+
window_geometry.bind_property(
118+
'monitor-scale',
119+
dbus_interface,
120+
'target-monitor-scale',
121+
GObject.BindingFlags.SYNC_CREATE
122+
);
117123
window_geometry.bind_property(
118124
'target-rect',
119125
dbus_interface,
120126
'target-rect',
121127
GObject.BindingFlags.SYNC_CREATE
122128
);
123129

130+
const flush_handler = window_geometry.connect('updated', () => {
131+
dbus_interface.dbus.flush();
132+
});
133+
134+
rollback.push(() => {
135+
window_geometry.disconnect(flush_handler);
136+
});
137+
124138
dbus_interface.dbus.export(Gio.DBus.session, '/org/gnome/Shell/Extensions/ddterm');
125139

126140
rollback.push(() => {

ddterm/shell/geometry.js

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ export const WindowGeometry = GObject.registerClass({
5959
GLib.MAXINT32,
6060
0
6161
),
62+
'monitor-scale': GObject.ParamSpec.double(
63+
'monitor-scale',
64+
'',
65+
'',
66+
GObject.ParamFlags.READABLE,
67+
0,
68+
100,
69+
1
70+
),
6271
'pivot-point': GObject.ParamSpec.boxed(
6372
'pivot-point',
6473
'',
@@ -114,12 +123,17 @@ export const WindowGeometry = GObject.registerClass({
114123
''
115124
),
116125
},
126+
Signals: {
127+
'updated': {},
128+
},
117129
}, class DDTermWindowGeometry extends GObject.Object {
118130
_init(params) {
119131
super._init(params);
120132

121-
this._workareas_changed_handler =
122-
global.display.connect('workareas-changed', this._update_workarea.bind(this));
133+
this._workareas_changed_handler = global.display.connect(
134+
'workareas-changed',
135+
this._update_workarea.bind(this)
136+
);
123137

124138
this.connect('notify::window-size', this._update_target_rect.bind(this));
125139
this.connect('notify::window-position', this._update_window_position.bind(this));
@@ -180,6 +194,10 @@ export const WindowGeometry = GObject.registerClass({
180194
return this._monitor_index;
181195
}
182196

197+
get monitor_scale() {
198+
return this._monitor_scale;
199+
}
200+
183201
get pivot_point() {
184202
return this._pivot_point;
185203
}
@@ -216,6 +234,14 @@ export const WindowGeometry = GObject.registerClass({
216234
this.notify('monitor-index');
217235
}
218236

237+
_set_monitor_scale(new_monitor_scale) {
238+
if (this._monitor_scale === new_monitor_scale)
239+
return;
240+
241+
this._monitor_scale = new_monitor_scale;
242+
this.notify('monitor-scale');
243+
}
244+
219245
_set_pivot_point(x, y) {
220246
if (this._pivot_point?.x === x && this._pivot_point?.y === y)
221247
return;
@@ -254,10 +280,11 @@ export const WindowGeometry = GObject.registerClass({
254280
return;
255281
}
256282

283+
this._set_monitor_scale(global.display.get_monitor_scale(this._monitor_index));
257284
this._set_workarea(Main.layoutManager.getWorkAreaForMonitor(this._monitor_index));
258285
this._update_target_rect();
259286
} finally {
260-
this.thaw_notify();
287+
this._thaw_notify_emit_updated();
261288
}
262289
}
263290

@@ -295,7 +322,7 @@ export const WindowGeometry = GObject.registerClass({
295322
this._set_monitor_index(this._get_monitor_index());
296323
this._update_workarea();
297324
} finally {
298-
this.thaw_notify();
325+
this._thaw_notify_emit_updated();
299326
}
300327
}
301328

@@ -323,21 +350,42 @@ export const WindowGeometry = GObject.registerClass({
323350

324351
this._update_target_rect();
325352
} finally {
326-
this.thaw_notify();
353+
this._thaw_notify_emit_updated();
327354
}
328355
}
329356

330357
_update_target_rect() {
331-
if (!this._workarea)
332-
return;
358+
this.freeze_notify();
333359

334-
const target_rect = WindowGeometry.get_target_rect(
335-
this._workarea,
336-
Math.floor(global.display.get_monitor_scale(this._monitor_index)),
337-
this.window_size,
338-
this.window_position
339-
);
360+
try {
361+
if (!this._workarea)
362+
return;
363+
364+
const target_rect = WindowGeometry.get_target_rect(
365+
this._workarea,
366+
Math.floor(this._monitor_scale),
367+
this.window_size,
368+
this.window_position
369+
);
370+
371+
this._set_target_rect(target_rect);
372+
} finally {
373+
this._thaw_notify_emit_updated();
374+
}
375+
}
376+
377+
_thaw_notify_emit_updated() {
378+
// 'updated' should ideally be emitted by vfunc_dispatch_properties_changed()
379+
// But implementing dispatch_properties_changed() in GJS doesn't seem possible.
380+
381+
this._notify_emitted = false;
382+
this.thaw_notify();
383+
384+
if (this._notify_emitted)
385+
this.emit('updated');
386+
}
340387

341-
this._set_target_rect(target_rect);
388+
on_notify() {
389+
this._notify_emitted = true;
342390
}
343391
});

test/test_wm.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -353,20 +353,23 @@ def current_monitor(self, request, shell_test_hook, workareas):
353353
def workarea(self, workareas, window_monitor):
354354
return workareas[window_monitor]
355355

356+
@pytest.fixture
357+
def monitor_scale(self, monitor_config, window_monitor):
358+
return monitor_config[window_monitor].scale
359+
356360
@pytest.fixture
357361
def unmaximized_rect(
358362
self,
359363
workarea,
360364
window_size,
361365
window_position,
362-
window_monitor,
363-
monitor_config,
366+
monitor_scale,
364367
):
365368
return compute_target_rect(
366369
window_size=window_size,
367370
window_position=window_position,
368371
workarea=workarea,
369-
round_to=int(monitor_config[window_monitor].scale)
372+
round_to=int(monitor_scale)
370373
)
371374

372375
@pytest.fixture
@@ -405,6 +408,7 @@ def test_show(
405408
self,
406409
unmaximized_rect,
407410
expected_rect,
411+
monitor_scale,
408412
window_maximize,
409413
window_above,
410414
window_stick,
@@ -425,6 +429,7 @@ def test_show(
425429
assert extension_test_hook.HasWindow
426430
assert unmaximized_rect == extension_dbus_interface.TargetRect
427431
assert extension_test_hook.ClientType == gdk_backend
432+
assert monitor_scale == extension_dbus_interface.TargetMonitorScale
428433

429434
extension_test_hook.wait_property('RenderedFirstFrame', True)
430435
wait_idle()
@@ -496,6 +501,7 @@ def test_maximize_unmaximize(
496501
unmaximized_rect,
497502
expected_rect,
498503
workarea,
504+
monitor_scale,
499505
window_maximize,
500506
window_above,
501507
window_skip_taskbar,
@@ -513,6 +519,7 @@ def test_maximize_unmaximize(
513519
assert extension_test_hook.HasWindow
514520
assert unmaximized_rect == extension_dbus_interface.TargetRect
515521
assert extension_test_hook.ClientType == gdk_backend
522+
assert monitor_scale == extension_dbus_interface.TargetMonitorScale
516523

517524
extension_test_hook.wait_property('RenderedFirstFrame', True)
518525
wait_idle()
@@ -552,8 +559,7 @@ def test_mouse_resize(
552559
window_size,
553560
window_size2,
554561
window_position,
555-
window_monitor,
556-
monitor_config,
562+
monitor_scale,
557563
extension_dbus_interface,
558564
extension_test_hook,
559565
shell_test_hook,
@@ -566,6 +572,7 @@ def test_mouse_resize(
566572
assert extension_test_hook.HasWindow
567573
assert unmaximized_rect == extension_dbus_interface.TargetRect
568574
assert extension_test_hook.ClientType == gdk_backend
575+
assert monitor_scale == extension_dbus_interface.TargetMonitorScale
569576

570577
extension_test_hook.wait_property('RenderedFirstFrame', True)
571578
wait_idle()
@@ -580,7 +587,7 @@ def test_mouse_resize(
580587
window_size=window_size2,
581588
window_position=window_position,
582589
workarea=workarea,
583-
round_to=int(monitor_config[window_monitor].scale)
590+
round_to=int(monitor_scale)
584591
)
585592

586593
end = resize_point(expected_rect2, window_position)
@@ -611,8 +618,7 @@ def test_resize_maximize_unmaximize(
611618
window_size,
612619
window_size2,
613620
window_position,
614-
window_monitor,
615-
monitor_config,
621+
monitor_scale,
616622
extension_dbus_interface,
617623
extension_test_hook,
618624
settings_test_hook,
@@ -628,6 +634,7 @@ def test_resize_maximize_unmaximize(
628634
assert extension_test_hook.HasWindow
629635
assert unmaximized_rect == extension_dbus_interface.TargetRect
630636
assert extension_test_hook.ClientType == gdk_backend
637+
assert monitor_scale == extension_dbus_interface.TargetMonitorScale
631638

632639
wait_idle()
633640

@@ -639,7 +646,7 @@ def test_resize_maximize_unmaximize(
639646
window_size=window_size2,
640647
window_position=window_position,
641648
workarea=workarea,
642-
round_to=int(monitor_config[window_monitor].scale)
649+
round_to=int(monitor_scale)
643650
)
644651

645652
settings_test_hook.window_size = window_size2

0 commit comments

Comments
 (0)