Skip to content

Commit 7e9b398

Browse files
authored
WallpaperContainer: set uri, all the context menu controllers (#478)
1 parent fe337a5 commit 7e9b398

2 files changed

Lines changed: 132 additions & 47 deletions

File tree

src/Views/Wallpaper.vala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,9 @@ public class PantheonShell.Wallpaper : Switchboard.SettingsPage {
405405
}
406406
}
407407

408-
var wallpaper = new WallpaperContainer (uri);
408+
var wallpaper = new WallpaperContainer () {
409+
uri = uri
410+
};
409411

410412
wallpaper_model.insert_sorted (wallpaper, wallpapers_sort_function);
411413

src/Widgets/WallpaperContainer.vala

Lines changed: 129 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,24 @@
2121
public class PantheonShell.WallpaperContainer : Granite.Bin {
2222
public signal void trash ();
2323

24+
// https://www.w3.org/WAI/WCAG21/Understanding/target-size.html
25+
private const int TOUCH_TARGET_WIDTH = 44;
26+
2427
protected const int THUMB_WIDTH = 256;
2528
protected const int THUMB_HEIGHT = 144;
2629
protected Gtk.Picture image;
2730

31+
private GLib.Menu menu_model;
32+
private GLib.SimpleAction remove_wallpaper_action;
2833
private Gtk.Revealer check_revealer;
2934

35+
private Gtk.EventControllerKey menu_key_controller;
36+
private Gtk.GestureClick? click_controller;
37+
private Gtk.GestureLongPress? long_press_controller;
38+
private Gtk.PopoverMenu? context_menu;
3039
private string? thumb_path = null;
3140

32-
public string? uri { get; construct; default = null; }
41+
public string? uri { get; set; default = null; }
3342
public uint64 creation_date = 0;
3443

3544
public bool checked {
@@ -48,10 +57,6 @@ public class PantheonShell.WallpaperContainer : Granite.Bin {
4857
}
4958
}
5059

51-
public WallpaperContainer (string uri) {
52-
Object (uri: uri);
53-
}
54-
5560
construct {
5661
image = new Gtk.Picture () {
5762
content_fit = COVER,
@@ -80,58 +85,136 @@ public class PantheonShell.WallpaperContainer : Granite.Bin {
8085
halign = CENTER;
8186
valign = CENTER;
8287

88+
// So we can receive key events
89+
focusable = true;
8390
child = overlay;
8491

85-
if (uri != null) {
86-
var remove_wallpaper_action = new SimpleAction ("trash", null);
87-
remove_wallpaper_action.activate.connect (() => trash ());
92+
remove_wallpaper_action = new SimpleAction ("trash", null);
93+
remove_wallpaper_action.activate.connect (() => trash ());
8894

89-
var action_group = new SimpleActionGroup ();
90-
action_group.add_action (remove_wallpaper_action);
95+
var action_group = new SimpleActionGroup ();
96+
action_group.add_action (remove_wallpaper_action);
9197

92-
insert_action_group ("wallpaper", action_group);
98+
insert_action_group ("wallpaper", action_group);
9399

94-
var file = File.new_for_uri (uri);
95-
try {
96-
var info = file.query_info ("*", FileQueryInfoFlags.NONE);
100+
menu_model = new Menu ();
101+
menu_model.append (_("Remove"), "wallpaper.trash");
97102

98-
thumb_path = info.get_attribute_as_string (FileAttribute.THUMBNAIL_PATH);
103+
notify["uri"].connect (construct_from_uri);
104+
}
99105

100-
if (thumb_path != null && info.get_attribute_boolean (FileAttribute.THUMBNAIL_IS_VALID)) {
101-
update_thumb.begin ();
102-
} else {
103-
generate_and_load_thumb ();
104-
}
106+
private void construct_from_uri () {
107+
if (uri == null) {
108+
remove_controller (click_controller);
109+
remove_controller (long_press_controller);
110+
remove_controller (menu_key_controller);
105111

106-
creation_date = info.get_attribute_uint64 (GLib.FileAttribute.TIME_CREATED);
107-
remove_wallpaper_action.set_enabled (info.get_attribute_boolean (GLib.FileAttribute.ACCESS_CAN_DELETE));
108-
} catch (Error e) {
109-
critical (e.message);
112+
click_controller = null;
113+
long_press_controller = null;
114+
menu_key_controller = null;
115+
116+
context_menu.unparent ();
117+
context_menu = null;
118+
119+
return;
120+
}
121+
122+
var file = File.new_for_uri (uri);
123+
try {
124+
var info = file.query_info ("*", FileQueryInfoFlags.NONE);
125+
126+
thumb_path = info.get_attribute_as_string (FileAttribute.THUMBNAIL_PATH);
127+
128+
if (thumb_path != null && info.get_attribute_boolean (FileAttribute.THUMBNAIL_IS_VALID)) {
129+
update_thumb.begin ();
130+
} else {
131+
generate_and_load_thumb ();
110132
}
111133

112-
var menu_model = new Menu ();
113-
menu_model.append (_("Remove"), "wallpaper.trash");
114-
115-
var context_menu = new Gtk.PopoverMenu.from_model (menu_model) {
116-
halign = START,
117-
has_arrow = false
118-
};
119-
context_menu.set_parent (this);
120-
121-
var secondary_click_gesture = new Gtk.GestureClick () {
122-
button = Gdk.BUTTON_SECONDARY
123-
};
124-
secondary_click_gesture.released.connect ((n_press, x, y) => {
125-
secondary_click_gesture.set_state (CLAIMED);
126-
context_menu.pointing_to = Gdk.Rectangle () {
127-
x = (int) x,
128-
y = (int) y
129-
};
130-
context_menu.popup ();
131-
});
132-
133-
add_controller (secondary_click_gesture);
134+
creation_date = info.get_attribute_uint64 (GLib.FileAttribute.TIME_CREATED);
135+
remove_wallpaper_action.set_enabled (info.get_attribute_boolean (GLib.FileAttribute.ACCESS_CAN_DELETE));
136+
} catch (Error e) {
137+
critical (e.message);
134138
}
139+
140+
context_menu = new Gtk.PopoverMenu.from_model (menu_model) {
141+
halign = START,
142+
has_arrow = false
143+
};
144+
context_menu.set_parent (this);
145+
146+
click_controller = new Gtk.GestureClick () {
147+
button = 0,
148+
exclusive = true
149+
};
150+
click_controller.pressed.connect ((n_press, x, y) => {
151+
var sequence = click_controller.get_current_sequence ();
152+
var event = click_controller.get_last_event (sequence);
153+
154+
if (event.triggers_context_menu ()) {
155+
context_menu.halign = START;
156+
menu_popup_at_pointer (context_menu, x, y);
157+
158+
click_controller.set_state (CLAIMED);
159+
click_controller.reset ();
160+
}
161+
});
162+
163+
long_press_controller = new Gtk.GestureLongPress () {
164+
touch_only = true
165+
};
166+
long_press_controller.pressed.connect ((x, y) => {
167+
// Try to keep menu from under your hand
168+
if (x > get_root ().get_width () / 2) {
169+
context_menu.halign = END;
170+
x -= TOUCH_TARGET_WIDTH;
171+
} else {
172+
context_menu.halign = START;
173+
x += TOUCH_TARGET_WIDTH;
174+
}
175+
176+
menu_popup_at_pointer (context_menu, x, y - (TOUCH_TARGET_WIDTH * 0.75));
177+
});
178+
179+
menu_key_controller = new Gtk.EventControllerKey ();
180+
menu_key_controller.key_released.connect ((keyval, keycode, state) => {
181+
var mods = state & Gtk.accelerator_get_default_mod_mask ();
182+
switch (keyval) {
183+
case Gdk.Key.F10:
184+
if (mods == Gdk.ModifierType.SHIFT_MASK) {
185+
menu_popup_on_keypress (context_menu);
186+
}
187+
break;
188+
case Gdk.Key.Menu:
189+
case Gdk.Key.MenuKB:
190+
menu_popup_on_keypress (context_menu);
191+
break;
192+
default:
193+
return;
194+
}
195+
});
196+
197+
add_controller (click_controller);
198+
add_controller (long_press_controller);
199+
add_controller (menu_key_controller);
200+
}
201+
202+
private void menu_popup_on_keypress (Gtk.PopoverMenu popover) {
203+
popover.halign = END;
204+
popover.set_pointing_to (Gdk.Rectangle () {
205+
x = (int) get_width (),
206+
y = (int) get_height () / 2
207+
});
208+
popover.popup ();
209+
}
210+
211+
private void menu_popup_at_pointer (Gtk.PopoverMenu popover, double x, double y) {
212+
var rect = Gdk.Rectangle () {
213+
x = (int) x,
214+
y = (int) y
215+
};
216+
popover.pointing_to = rect;
217+
popover.popup ();
135218
}
136219

137220
private void generate_and_load_thumb () {

0 commit comments

Comments
 (0)