Skip to content

Commit 7e97727

Browse files
authored
ShellClients: Better separation of concern (#2575)
1 parent fa49edf commit 7e97727

File tree

6 files changed

+122
-171
lines changed

6 files changed

+122
-171
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2025 elementary, Inc. (https://elementary.io)
3+
* SPDX-License-Identifier: GPL-3.0-or-later
4+
*
5+
* Authored by: Leonhard Kargl <[email protected]>
6+
*/
7+
8+
public class Gala.ExtendedBehaviorWindow : ShellWindow {
9+
public ExtendedBehaviorWindow (Meta.Window window) {
10+
var target = new PropertyTarget (CUSTOM, window.get_compositor_private (), "opacity", typeof (uint), 255u, 0u);
11+
Object (window: window, hide_target: target);
12+
}
13+
14+
protected override void get_window_position (Mtk.Rectangle window_rect, out int x, out int y) {
15+
var monitor_rect = window.display.get_monitor_geometry (window.get_monitor ());
16+
17+
x = monitor_rect.x + (monitor_rect.width - window_rect.width) / 2;
18+
y = monitor_rect.y + (monitor_rect.height - window_rect.height) / 2;
19+
}
20+
}

src/ShellClients/PanelWindow.vala

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@ public class Gala.PanelWindow : ShellWindow, RootTarget {
3535
private GestureController workspace_gesture_controller;
3636
private WorkspaceHideTracker workspace_hide_tracker;
3737

38+
private int width = -1;
39+
private int height = -1;
40+
3841
public PanelWindow (WindowManager wm, Meta.Window window, Pantheon.Desktop.Anchor anchor) {
39-
Object (wm: wm, anchor: anchor, window: window, position: Position.from_anchor (anchor));
42+
Object (wm: wm, window: window, anchor: anchor);
4043
}
4144

4245
construct {
@@ -46,7 +49,7 @@ public class Gala.PanelWindow : ShellWindow, RootTarget {
4649
}
4750
});
4851

49-
notify["anchor"].connect (() => position = Position.from_anchor (anchor));
52+
notify["anchor"].connect (position_window);
5053

5154
unowned var workspace_manager = window.display.get_workspace_manager ();
5255
workspace_manager.workspace_added.connect (update_strut);
@@ -71,20 +74,50 @@ public class Gala.PanelWindow : ShellWindow, RootTarget {
7174
workspace_hide_tracker.switching_workspace_progress_updated.connect ((value) => workspace_gesture_controller.progress = value);
7275
workspace_hide_tracker.window_state_changed_progress_updated.connect (workspace_gesture_controller.goto);
7376

77+
window.size_changed.connect (update_target);
78+
notify["anchor"].connect (update_target);
79+
update_target ();
80+
7481
add_gesture_controller (user_gesture_controller);
7582
add_gesture_controller (workspace_gesture_controller);
83+
84+
var window_actor = (Meta.WindowActor) window.get_compositor_private ();
85+
86+
window_actor.notify["width"].connect (update_clip);
87+
window_actor.notify["height"].connect (update_clip);
88+
window_actor.notify["translation-y"].connect (update_clip);
89+
notify["anchor"].connect (update_clip);
90+
}
91+
92+
public Mtk.Rectangle get_custom_window_rect () {
93+
var window_rect = window.get_frame_rect ();
94+
95+
if (width > 0) {
96+
window_rect.width = width;
97+
}
98+
99+
if (height > 0) {
100+
window_rect.height = height;
101+
102+
if (anchor == BOTTOM) {
103+
var geom = window.display.get_monitor_geometry (window.get_monitor ());
104+
window_rect.y = geom.y + geom.height - height;
105+
}
106+
}
107+
108+
return window_rect;
109+
}
110+
111+
public void set_size (int width, int height) {
112+
this.width = width;
113+
this.height = height;
76114
}
77115

78116
public void request_visible_in_multitasking_view () {
79117
visible_in_multitasking_view = true;
80118
actor.add_action (new DragDropAction (DESTINATION, "multitaskingview-window"));
81119
}
82120

83-
protected override void update_target () {
84-
base.update_target ();
85-
workspace_hide_tracker.recalculate_all_workspaces ();
86-
}
87-
88121
protected override double get_hidden_progress () {
89122
var user_workspace_hidden_progress = double.min (
90123
user_gesture_controller.progress,
@@ -214,4 +247,47 @@ public class Gala.PanelWindow : ShellWindow, RootTarget {
214247
return TOP;
215248
}
216249
}
250+
251+
protected override void get_window_position (Mtk.Rectangle window_rect, out int x, out int y) {
252+
var monitor_rect = window.display.get_monitor_geometry (window.display.get_primary_monitor ());
253+
switch (anchor) {
254+
case TOP:
255+
x = monitor_rect.x + (monitor_rect.width - window_rect.width) / 2;
256+
y = monitor_rect.y;
257+
break;
258+
259+
case BOTTOM:
260+
x = monitor_rect.x + (monitor_rect.width - window_rect.width) / 2;
261+
y = monitor_rect.y + monitor_rect.height - window_rect.height;
262+
break;
263+
264+
default:
265+
warning ("Unsupported anchor %s for PanelWindow", anchor.to_string ());
266+
x = 0;
267+
y = 0;
268+
break;
269+
}
270+
}
271+
272+
private void update_target () {
273+
var to_value = anchor == TOP ? -get_custom_window_rect ().height : get_custom_window_rect ().height;
274+
hide_target = new PropertyTarget (CUSTOM, actor, "translation-y", typeof (float), 0f, (float) to_value);
275+
276+
workspace_hide_tracker.recalculate_all_workspaces ();
277+
}
278+
279+
private void update_clip () {
280+
var monitor_geom = window.display.get_monitor_geometry (window.get_monitor ());
281+
var window_actor = (Meta.WindowActor) window.get_compositor_private ();
282+
283+
var y = window_actor.y + window_actor.translation_y;
284+
285+
if (y + window_actor.height > monitor_geom.y + monitor_geom.height) {
286+
window_actor.set_clip (0, 0, window_actor.width, monitor_geom.y + monitor_geom.height - y);
287+
} else if (y < monitor_geom.y) {
288+
window_actor.set_clip (0, monitor_geom.y - y, window_actor.width, window_actor.height);
289+
} else {
290+
window_actor.remove_clip ();
291+
}
292+
}
217293
}

src/ShellClients/PositionedWindow.vala

Lines changed: 5 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,11 @@
55
* Authored by: Leonhard Kargl <[email protected]>
66
*/
77

8-
public class Gala.PositionedWindow : Object {
9-
public enum Position {
10-
TOP,
11-
BOTTOM,
12-
CENTER;
13-
14-
public static Position from_anchor (Pantheon.Desktop.Anchor anchor) {
15-
if (anchor > 1) {
16-
warning ("Position %s not supported yet", anchor.to_string ());
17-
return CENTER;
18-
}
19-
20-
return (Position) anchor;
21-
}
22-
}
23-
8+
public abstract class Gala.PositionedWindow : Object {
249
public Meta.Window window { get; construct; }
25-
/**
26-
* This may only be set after the window was shown.
27-
* The initial position should only be given in the constructor.
28-
*/
29-
public Position position { get; construct set; }
30-
public Variant? position_data { get; construct set; }
31-
32-
private int width = -1;
33-
private int height = -1;
3410

3511
private ulong position_changed_id;
3612

37-
public PositionedWindow (Meta.Window window, Position position, Variant? position_data = null) {
38-
Object (window: window, position: position, position_data: position_data);
39-
}
40-
4113
construct {
4214
window.stick ();
4315

@@ -48,62 +20,18 @@ public class Gala.PositionedWindow : Object {
4820
unowned var monitor_manager = window.display.get_context ().get_backend ().get_monitor_manager ();
4921
monitor_manager.monitors_changed.connect (position_window);
5022
monitor_manager.monitors_changed_internal.connect (position_window);
51-
52-
notify["position"].connect (position_window);
53-
notify["position-data"].connect (position_window);
5423
}
5524

56-
public Mtk.Rectangle get_custom_window_rect () {
25+
protected void position_window () {
5726
var window_rect = window.get_frame_rect ();
5827

59-
if (width > 0) {
60-
window_rect.width = width;
61-
}
62-
63-
if (height > 0) {
64-
window_rect.height = height;
65-
66-
if (position == BOTTOM) {
67-
var geom = window.display.get_monitor_geometry (window.get_monitor ());
68-
window_rect.y = geom.y + geom.height - height;
69-
}
70-
}
71-
72-
return window_rect;
73-
}
74-
75-
public void set_size (int width, int height) {
76-
this.width = width;
77-
this.height = height;
78-
}
79-
80-
private void position_window () {
8128
int x = 0, y = 0;
82-
var window_rect = window.get_frame_rect ();
83-
unowned var display = window.display;
84-
85-
switch (position) {
86-
case CENTER:
87-
var monitor_geom = display.get_monitor_geometry (display.get_primary_monitor ());
88-
x = monitor_geom.x + (monitor_geom.width - window_rect.width) / 2;
89-
y = monitor_geom.y + (monitor_geom.height - window_rect.height) / 2;
90-
break;
91-
92-
case TOP:
93-
var monitor_geom = display.get_monitor_geometry (display.get_primary_monitor ());
94-
x = monitor_geom.x + (monitor_geom.width - window_rect.width) / 2;
95-
y = monitor_geom.y;
96-
break;
97-
98-
case BOTTOM:
99-
var monitor_geom = display.get_monitor_geometry (display.get_primary_monitor ());
100-
x = monitor_geom.x + (monitor_geom.width - window_rect.width) / 2;
101-
y = monitor_geom.y + monitor_geom.height - window_rect.height;
102-
break;
103-
}
29+
get_window_position (window_rect, out x, out y);
10430

10531
SignalHandler.block (window, position_changed_id);
10632
window.move_frame (false, x, y);
10733
SignalHandler.unblock (window, position_changed_id);
10834
}
35+
36+
protected abstract void get_window_position (Mtk.Rectangle window_rect, out int x, out int y);
10937
}

src/ShellClients/ShellClientsManager.vala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ public class Gala.ShellClientsManager : Object, GestureTarget {
199199
}
200200

201201
public void make_centered (Meta.Window window) requires (!is_itself_positioned (window)) {
202-
positioned_windows[window] = new ShellWindow (window, CENTER);
202+
positioned_windows[window] = new ExtendedBehaviorWindow (window);
203203

204204
// connect_after so we make sure that any queued move is unqueued
205205
window.unmanaging.connect_after ((_window) => positioned_windows.remove (_window));

src/ShellClients/ShellWindow.vala

Lines changed: 12 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,18 @@
55
* Authored by: Leonhard Kargl <[email protected]>
66
*/
77

8-
public class Gala.ShellWindow : PositionedWindow, GestureTarget {
8+
public abstract class Gala.ShellWindow : PositionedWindow, GestureTarget {
99
public bool restore_previous_x11_region { private get; set; default = false; }
1010

11-
private Meta.WindowActor window_actor;
11+
/**
12+
* A gesture target that will receive a CUSTOM update every time a gesture
13+
* is propagated, with the progress gotten via {@link get_hidden_progress()}
14+
*/
15+
public GestureTarget hide_target { get; construct set; }
16+
1217
private double multitasking_view_progress = 0;
1318
private int animations_ongoing = 0;
1419

15-
private PropertyTarget property_target;
16-
17-
public ShellWindow (Meta.Window window, Position position, Variant? position_data = null) {
18-
base (window, position, position_data);
19-
}
20-
21-
construct {
22-
window_actor = (Meta.WindowActor) window.get_compositor_private ();
23-
24-
window_actor.notify["width"].connect (update_clip);
25-
window_actor.notify["height"].connect (update_clip);
26-
window_actor.notify["translation-y"].connect (update_clip);
27-
notify["position"].connect (update_clip);
28-
29-
window.size_changed.connect (update_target);
30-
notify["position"].connect (update_target);
31-
update_target ();
32-
}
33-
34-
protected virtual void update_target () {
35-
property_target = new PropertyTarget (
36-
CUSTOM, window_actor,
37-
get_animation_property (),
38-
get_property_type (),
39-
calculate_value (false),
40-
calculate_value (true)
41-
);
42-
}
43-
4420
public virtual void propagate (UpdateType update_type, GestureAction action, double progress) {
4521
switch (update_type) {
4622
case START:
@@ -53,7 +29,7 @@ public class Gala.ShellWindow : PositionedWindow, GestureTarget {
5329
multitasking_view_progress = progress;
5430
}
5531

56-
property_target.propagate (UPDATE, CUSTOM, get_hidden_progress ());
32+
hide_target.propagate (UPDATE, CUSTOM, get_hidden_progress ());
5733
break;
5834

5935
case END:
@@ -71,6 +47,8 @@ public class Gala.ShellWindow : PositionedWindow, GestureTarget {
7147
}
7248

7349
private void update_visibility () {
50+
unowned var window_actor = (Meta.WindowActor) window.get_compositor_private ();
51+
7452
var visible = get_hidden_progress () < 0.1;
7553
var animating = animations_ongoing > 0;
7654

@@ -104,63 +82,11 @@ public class Gala.ShellWindow : PositionedWindow, GestureTarget {
10482
return true;
10583
}
10684

107-
unowned var window_actor = (Meta.WindowActor) transient.get_compositor_private ();
85+
unowned var transient_window_actor = (Meta.WindowActor) transient.get_compositor_private ();
10886

109-
window_actor.visible = visible && !animating;
87+
transient_window_actor.visible = visible && !animating;
11088

11189
return true;
11290
});
11391
}
114-
115-
private string get_animation_property () {
116-
switch (position) {
117-
case TOP:
118-
case BOTTOM:
119-
return "translation-y";
120-
default:
121-
return "opacity";
122-
}
123-
}
124-
125-
private Type get_property_type () {
126-
switch (position) {
127-
case TOP:
128-
case BOTTOM:
129-
return typeof (float);
130-
default:
131-
return typeof (uint);
132-
}
133-
}
134-
135-
private Value calculate_value (bool hidden) {
136-
var custom_rect = get_custom_window_rect ();
137-
138-
switch (position) {
139-
case TOP:
140-
return hidden ? -custom_rect.height : 0f;
141-
case BOTTOM:
142-
return hidden ? custom_rect.height : 0f;
143-
default:
144-
return hidden ? 0u : 255u;
145-
}
146-
}
147-
148-
private void update_clip () {
149-
if (position != TOP && position != BOTTOM) {
150-
window_actor.remove_clip ();
151-
return;
152-
}
153-
154-
var monitor_geom = window.display.get_monitor_geometry (window.get_monitor ());
155-
156-
var y = window_actor.y + window_actor.translation_y;
157-
158-
if (y + window_actor.height > monitor_geom.y + monitor_geom.height) {
159-
window_actor.set_clip (0, 0, window_actor.width, monitor_geom.y + monitor_geom.height - y);
160-
} else if (y < monitor_geom.y) {
161-
window_actor.set_clip (0, monitor_geom.y - y, window_actor.width, window_actor.height);
162-
} else {
163-
window_actor.remove_clip ();
164-
}
165-
}
16692
}

0 commit comments

Comments
 (0)