Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/Views/Wallpaper.vala
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,9 @@ public class PantheonShell.Wallpaper : Switchboard.SettingsPage {
return;
}

var wallpaper = new WallpaperContainer (uri);
var wallpaper = new WallpaperContainer () {
uri = uri
};
wallpaper_model.insert_sorted (wallpaper, wallpapers_sort_function);

wallpaper.trash.connect (() => {
Expand Down
175 changes: 129 additions & 46 deletions src/Widgets/WallpaperContainer.vala
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,24 @@
public class PantheonShell.WallpaperContainer : Granite.Bin {
public signal void trash ();

// https://www.w3.org/WAI/WCAG21/Understanding/target-size.html
private const int TOUCH_TARGET_WIDTH = 44;

protected const int THUMB_WIDTH = 256;
protected const int THUMB_HEIGHT = 144;
protected Gtk.Picture image;

private GLib.Menu menu_model;
private GLib.SimpleAction remove_wallpaper_action;
private Gtk.Revealer check_revealer;

private Gtk.EventControllerKey menu_key_controller;
private Gtk.GestureClick? click_controller;
private Gtk.GestureLongPress? long_press_controller;
private Gtk.PopoverMenu? context_menu;
private string? thumb_path = null;

public string? uri { get; construct; default = null; }
public string? uri { get; set; default = null; }
public uint64 creation_date = 0;

public bool checked {
Expand All @@ -48,10 +57,6 @@ public class PantheonShell.WallpaperContainer : Granite.Bin {
}
}

public WallpaperContainer (string uri) {
Object (uri: uri);
}

construct {
image = new Gtk.Picture () {
content_fit = COVER,
Expand Down Expand Up @@ -80,58 +85,136 @@ public class PantheonShell.WallpaperContainer : Granite.Bin {
halign = CENTER;
valign = CENTER;

// So we can receive key events
focusable = true;
child = overlay;

if (uri != null) {
var remove_wallpaper_action = new SimpleAction ("trash", null);
remove_wallpaper_action.activate.connect (() => trash ());
remove_wallpaper_action = new SimpleAction ("trash", null);
remove_wallpaper_action.activate.connect (() => trash ());

var action_group = new SimpleActionGroup ();
action_group.add_action (remove_wallpaper_action);
var action_group = new SimpleActionGroup ();
action_group.add_action (remove_wallpaper_action);

insert_action_group ("wallpaper", action_group);
insert_action_group ("wallpaper", action_group);

var file = File.new_for_uri (uri);
try {
var info = file.query_info ("*", FileQueryInfoFlags.NONE);
menu_model = new Menu ();
menu_model.append (_("Remove"), "wallpaper.trash");

thumb_path = info.get_attribute_as_string (FileAttribute.THUMBNAIL_PATH);
notify["uri"].connect (construct_from_uri);
}

if (thumb_path != null && info.get_attribute_boolean (FileAttribute.THUMBNAIL_IS_VALID)) {
update_thumb.begin ();
} else {
generate_and_load_thumb ();
}
private void construct_from_uri () {
if (uri == null) {
remove_controller (click_controller);
remove_controller (long_press_controller);
remove_controller (menu_key_controller);

creation_date = info.get_attribute_uint64 (GLib.FileAttribute.TIME_CREATED);
remove_wallpaper_action.set_enabled (info.get_attribute_boolean (GLib.FileAttribute.ACCESS_CAN_DELETE));
} catch (Error e) {
critical (e.message);
click_controller = null;
long_press_controller = null;
menu_key_controller = null;

context_menu.unparent ();
context_menu = null;

return;
}

var file = File.new_for_uri (uri);
try {
var info = file.query_info ("*", FileQueryInfoFlags.NONE);

thumb_path = info.get_attribute_as_string (FileAttribute.THUMBNAIL_PATH);

if (thumb_path != null && info.get_attribute_boolean (FileAttribute.THUMBNAIL_IS_VALID)) {
update_thumb.begin ();
} else {
generate_and_load_thumb ();
}

var menu_model = new Menu ();
menu_model.append (_("Remove"), "wallpaper.trash");

var context_menu = new Gtk.PopoverMenu.from_model (menu_model) {
halign = START,
has_arrow = false
};
context_menu.set_parent (this);

var secondary_click_gesture = new Gtk.GestureClick () {
button = Gdk.BUTTON_SECONDARY
};
secondary_click_gesture.released.connect ((n_press, x, y) => {
secondary_click_gesture.set_state (CLAIMED);
context_menu.pointing_to = Gdk.Rectangle () {
x = (int) x,
y = (int) y
};
context_menu.popup ();
});

add_controller (secondary_click_gesture);
creation_date = info.get_attribute_uint64 (GLib.FileAttribute.TIME_CREATED);
remove_wallpaper_action.set_enabled (info.get_attribute_boolean (GLib.FileAttribute.ACCESS_CAN_DELETE));
} catch (Error e) {
critical (e.message);
}

context_menu = new Gtk.PopoverMenu.from_model (menu_model) {
halign = START,
has_arrow = false
};
context_menu.set_parent (this);

click_controller = new Gtk.GestureClick () {
button = 0,
exclusive = true
};
click_controller.pressed.connect ((n_press, x, y) => {
var sequence = click_controller.get_current_sequence ();
var event = click_controller.get_last_event (sequence);

if (event.triggers_context_menu ()) {
context_menu.halign = START;
menu_popup_at_pointer (context_menu, x, y);

click_controller.set_state (CLAIMED);
click_controller.reset ();
}
});

long_press_controller = new Gtk.GestureLongPress () {
touch_only = true
};
long_press_controller.pressed.connect ((x, y) => {
// Try to keep menu from under your hand
if (x > get_root ().get_width () / 2) {
context_menu.halign = END;
x -= TOUCH_TARGET_WIDTH;
} else {
context_menu.halign = START;
x += TOUCH_TARGET_WIDTH;
}

menu_popup_at_pointer (context_menu, x, y - (TOUCH_TARGET_WIDTH * 0.75));
});

menu_key_controller = new Gtk.EventControllerKey ();
menu_key_controller.key_released.connect ((keyval, keycode, state) => {
var mods = state & Gtk.accelerator_get_default_mod_mask ();
switch (keyval) {
case Gdk.Key.F10:
if (mods == Gdk.ModifierType.SHIFT_MASK) {
menu_popup_on_keypress (context_menu);
}
break;
case Gdk.Key.Menu:
case Gdk.Key.MenuKB:
menu_popup_on_keypress (context_menu);
break;
default:
return;
}
});

add_controller (click_controller);
add_controller (long_press_controller);
add_controller (menu_key_controller);
}

private void menu_popup_on_keypress (Gtk.PopoverMenu popover) {
popover.halign = END;
popover.set_pointing_to (Gdk.Rectangle () {
x = (int) get_width (),
y = (int) get_height () / 2
});
popover.popup ();
}

private void menu_popup_at_pointer (Gtk.PopoverMenu popover, double x, double y) {
var rect = Gdk.Rectangle () {
x = (int) x,
y = (int) y
};
popover.pointing_to = rect;
popover.popup ();
}

private void generate_and_load_thumb () {
Expand Down