Skip to content

Commit

Permalink
IconGroup: Support floating scale factors (#1628)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmhewitt committed Apr 7, 2023
1 parent ca807c6 commit e5ef835
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 61 deletions.
24 changes: 14 additions & 10 deletions lib/Utils.vala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace Gala {
}

private static Gdk.Pixbuf? resize_pixbuf = null;
private static Gdk.Pixbuf? close_pixbuf = null;
private static Gee.HashMap<int, Gdk.Pixbuf?>? close_pixbufs = null;

private static Gee.HashMultiMap<DesktopAppInfo, CachedIcon?> icon_cache;
private static Gee.HashMap<Meta.Window, DesktopAppInfo> window_to_desktop_cache;
Expand Down Expand Up @@ -320,11 +320,16 @@ namespace Gala {
*
* @return the close button pixbuf or null if it failed to load
*/
public static Gdk.Pixbuf? get_close_button_pixbuf () {
var height = 36 * Utils.get_ui_scaling_factor ();
if (close_pixbuf == null || close_pixbuf.height != height) {
public static Gdk.Pixbuf? get_close_button_pixbuf (float scale) {
var height = scale_to_int (36, scale);

if (close_pixbufs == null) {
close_pixbufs = new Gee.HashMap<int, Gdk.Pixbuf?> ();
}

if (close_pixbufs[height] == null) {
try {
close_pixbuf = new Gdk.Pixbuf.from_resource_at_scale (
close_pixbufs[height] = new Gdk.Pixbuf.from_resource_at_scale (
Config.RESOURCEPATH + "/buttons/close.svg",
-1,
height,
Expand All @@ -336,17 +341,17 @@ namespace Gala {
}
}

return close_pixbuf;
return close_pixbufs[height];
}

/**
* Creates a new reactive ClutterActor at 36px with the close pixbuf
*
* @return The close button actor
*/
public static Clutter.Actor create_close_button () {
public static Clutter.Actor create_close_button (float scale) {
var texture = new Clutter.Actor ();
var pixbuf = get_close_button_pixbuf ();
var pixbuf = get_close_button_pixbuf (scale);

texture.reactive = true;

Expand All @@ -362,8 +367,7 @@ namespace Gala {
// we'll just make this red so there's at least something as an
// indicator that loading failed. Should never happen and this
// works as good as some weird fallback-image-failed-to-load pixbuf
var scale = Utils.get_ui_scaling_factor ();
texture.set_size (36 * scale, 36 * scale);
texture.set_size (scale_to_int (36, scale), scale_to_int (36, scale));
texture.background_color = { 255, 0, 0, 255 };
}

Expand Down
2 changes: 1 addition & 1 deletion plugins/pip/PopupWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public class Gala.Plugins.PIP.PopupWindow : Clutter.Actor {
close_action = new Clutter.ClickAction ();
close_action.clicked.connect (on_close_click_clicked);

close_button = Gala.Utils.create_close_button ();
close_button = Gala.Utils.create_close_button (scale);
close_button.opacity = 0;
close_button.reactive = true;
// TODO: Check if close button should be on the right
Expand Down
106 changes: 61 additions & 45 deletions src/Widgets/IconGroup.vala
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,24 @@ namespace Gala {

public WindowManager wm { get; construct; }
public Meta.Workspace workspace { get; construct; }
private float _scale_factor = 1.0f;
public float scale_factor {
get { return _scale_factor; }
set {
if (value != _scale_factor) {
_scale_factor = value;
resize_canvas ();
create_close_button ();
}
}
}

private Clutter.Actor? prev_parent = null;
private Clutter.Actor close_button;
private Clutter.Actor icon_container;

public IconGroup (WindowManager wm, Meta.Workspace workspace) {
Object (wm: wm, workspace: workspace);
public IconGroup (WindowManager wm, Meta.Workspace workspace, float scale) {
Object (wm: wm, workspace: workspace, scale_factor: scale);
}

construct {
Expand All @@ -103,7 +114,13 @@ namespace Gala {

resize_canvas ();

close_button = Utils.create_close_button ();
create_close_button ();

icon_container.actor_removed.connect_after (redraw);
}

private void create_close_button () {
close_button = Utils.create_close_button (scale_factor);
place_close_button ();
close_button.opacity = 0;
close_button.reactive = true;
Expand All @@ -118,8 +135,6 @@ namespace Gala {
var close_click = new Clutter.ClickAction ();
close_click.clicked.connect (close);
close_button.add_action (close_click);

icon_container.actor_removed.connect_after (redraw);
}

~IconGroup () {
Expand Down Expand Up @@ -184,8 +199,7 @@ namespace Gala {
}

private bool resize_canvas () {
var scale = InternalUtils.get_ui_scaling_factor ();
var size = SIZE * scale;
var size = InternalUtils.scale_to_int (SIZE, scale_factor);

width = size;
height = size;
Expand All @@ -194,7 +208,7 @@ namespace Gala {
}

private void place_close_button () {
var size = CLOSE_BUTTON_SIZE * InternalUtils.get_ui_scaling_factor ();
var size = InternalUtils.scale_to_int (CLOSE_BUTTON_SIZE, scale_factor);
close_button.set_size (size, size);

close_button.x = -Math.floorf (close_button.width * 0.4f);
Expand All @@ -210,11 +224,10 @@ namespace Gala {
return;
}

var scale = InternalUtils.get_ui_scaling_factor ();
var width = 100 * scale;
var x = ((SIZE * scale) - width) / 2;
var width = InternalUtils.scale_to_int (100, scale_factor);
var x = (InternalUtils.scale_to_int (SIZE, scale_factor) - width) / 2;
var y = -10;
var height = WorkspaceClone.BOTTOM_OFFSET * scale;
var height = InternalUtils.scale_to_int (WorkspaceClone.BOTTOM_OFFSET, scale_factor);

Cogl.VertexP2T2C4 vertices[4];
vertices[0] = { x, y + height, 0, 1, backdrop_opacity, backdrop_opacity, backdrop_opacity, backdrop_opacity };
Expand Down Expand Up @@ -327,8 +340,6 @@ namespace Gala {
* by relayouting in the same function, as it's only ever called when we invalidate it.
*/
private bool draw (Cairo.Context cr) {
var scale = InternalUtils.get_ui_scaling_factor ();

cr.set_operator (Cairo.Operator.CLEAR);
cr.paint ();
cr.set_operator (Cairo.Operator.OVER);
Expand All @@ -346,11 +357,11 @@ namespace Gala {
// more than one => we need a folder
Drawing.Utilities.cairo_rounded_rectangle (
cr,
0.5 * scale,
0.5 * scale,
(int) width - (1 * scale),
(int) height - (1 * scale),
5 * scale
0.5 * scale_factor,
0.5 * scale_factor,
(int) width - InternalUtils.scale_to_int (1, scale_factor),
(int) height - InternalUtils.scale_to_int (1, scale_factor),
InternalUtils.scale_to_int (5, scale_factor)
);

if (drag_action.dragging) {
Expand All @@ -362,7 +373,7 @@ namespace Gala {

cr.fill_preserve ();

cr.set_line_width (1 * scale);
cr.set_line_width (InternalUtils.scale_to_int (1, scale_factor));

var grad = new Cairo.Pattern.linear (0, 0, 0, height);
grad.add_color_stop_rgba (0.8, 0, 0, 0, 0);
Expand All @@ -373,11 +384,11 @@ namespace Gala {

Drawing.Utilities.cairo_rounded_rectangle (
cr,
1.5 * scale,
1.5 * scale,
(int) width - (3 * scale),
(int) height - (3 * scale),
5 * scale
1.5 * scale_factor,
1.5 * scale_factor,
(int) width - InternalUtils.scale_to_int (3, scale_factor),
(int) height - InternalUtils.scale_to_int (3, scale_factor),
InternalUtils.scale_to_int (5, scale_factor)
);

cr.set_source_rgba (0, 0, 0, 0.3);
Expand All @@ -394,23 +405,28 @@ namespace Gala {
}
}

var scaled_size = InternalUtils.scale_to_int (SIZE, scale_factor);

if (n_windows < 1) {
if (!Meta.Prefs.get_dynamic_workspaces ()
|| workspace_index != manager.get_n_workspaces () - 1)
return false;

var buffer = new Drawing.BufferSurface (SIZE * scale, SIZE * scale);
var offset = (SIZE * scale) / 2 - (PLUS_WIDTH * scale) / 2;
var buffer = new Drawing.BufferSurface (scaled_size, scaled_size);
var offset = scaled_size / 2 - InternalUtils.scale_to_int (PLUS_WIDTH, scale_factor) / 2;

buffer.context.rectangle (PLUS_WIDTH / 2 * scale - PLUS_SIZE / 2 * scale + 0.5 + offset,
buffer.context.rectangle (
InternalUtils.scale_to_int (PLUS_WIDTH / 2, scale_factor) - InternalUtils.scale_to_int (PLUS_SIZE / 2, scale_factor) + 0.5 + offset,
0.5 + offset,
PLUS_SIZE * scale - 1,
PLUS_WIDTH * scale - 1);
InternalUtils.scale_to_int (PLUS_SIZE, scale_factor) - 1,
InternalUtils.scale_to_int (PLUS_WIDTH, scale_factor) - 1
);

buffer.context.rectangle (0.5 + offset,
PLUS_WIDTH / 2 * scale - PLUS_SIZE / 2 * scale + 0.5 + offset,
PLUS_WIDTH * scale - 1,
PLUS_SIZE * scale - 1);
InternalUtils.scale_to_int (PLUS_WIDTH / 2, scale_factor) - InternalUtils.scale_to_int (PLUS_SIZE / 2, scale_factor) + 0.5 + offset,
InternalUtils.scale_to_int (PLUS_WIDTH, scale_factor) - 1,
InternalUtils.scale_to_int (PLUS_SIZE, scale_factor) - 1
);

buffer.context.set_source_rgb (0, 0, 0);
buffer.context.fill_preserve ();
Expand Down Expand Up @@ -439,12 +455,12 @@ namespace Gala {
var columns = (int) Math.ceil (Math.sqrt (n_tiled_windows));
var rows = (int) Math.ceil (n_tiled_windows / (double) columns);

int spacing = 6 * scale;
int spacing = InternalUtils.scale_to_int (6, scale_factor);

var width = columns * (size * scale) + (columns - 1) * spacing;
var height = rows * (size * scale) + (rows - 1) * spacing;
var x_offset = SIZE * scale / 2 - width / 2;
var y_offset = SIZE * scale / 2 - height / 2;
var width = columns * InternalUtils.scale_to_int (size, scale_factor) + (columns - 1) * spacing;
var height = rows * InternalUtils.scale_to_int (size, scale_factor) + (rows - 1) * spacing;
var x_offset = scaled_size / 2 - width / 2;
var y_offset = scaled_size / 2 - height / 2;

var show_ellipsis = false;
var n_shown_windows = n_windows;
Expand All @@ -461,10 +477,10 @@ namespace Gala {

// draw an ellipsis at the 9th position if we need one
if (show_ellipsis && i == 8) {
int top_offset = 10 * scale;
int left_offset = 2 * scale;
int radius = 2 * scale;
int dot_spacing = 3 * scale;
int top_offset = InternalUtils.scale_to_int (10, scale_factor);
int left_offset = InternalUtils.scale_to_int (2, scale_factor);
int radius = InternalUtils.scale_to_int (2, scale_factor);
int dot_spacing = InternalUtils.scale_to_int (3, scale_factor);
cr.arc (left_offset + x, y + top_offset, radius, 0, 2 * Math.PI);
cr.arc (left_offset + x + radius + dot_spacing, y + top_offset, radius, 0, 2 * Math.PI);
cr.arc (left_offset + x + radius * 2 + dot_spacing * 2, y + top_offset, radius, 0, 2 * Math.PI);
Expand All @@ -480,10 +496,10 @@ namespace Gala {

window.place (x, y, size);

x += (size * scale) + spacing;
if (x + (size * scale) >= SIZE * scale) {
x += InternalUtils.scale_to_int (size, scale_factor) + spacing;
if (x + InternalUtils.scale_to_int (size, scale_factor) >= scaled_size) {
x = x_offset;
y += (size * scale) + spacing;
y += InternalUtils.scale_to_int (size, scale_factor) + spacing;
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/Widgets/WindowClone.vala
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,18 @@ public class Gala.WindowClone : Clutter.Actor {
add_action (drag_action);
}

var scale_factor = InternalUtils.get_ui_scaling_factor ();

var close_button_action = new Clutter.ClickAction ();
close_button_action.clicked.connect (() => {
close_window ();
});
close_button = Utils.create_close_button ();
close_button = Utils.create_close_button (scale_factor);
close_button.opacity = 0;
// block propagation of button release event to window clone
close_button.button_release_event.connect (() => { return Gdk.EVENT_STOP; });
close_button.add_action (close_button_action);

var scale_factor = InternalUtils.get_ui_scaling_factor ();

var window_frame_rect = window.get_frame_rect ();
window_icon = new WindowIcon (window, WINDOW_ICON_SIZE, scale_factor);
window_icon.opacity = 0;
Expand Down
7 changes: 5 additions & 2 deletions src/Widgets/WorkspaceClone.vala
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ namespace Gala {
opened = false;

unowned Meta.Display display = workspace.get_display ();
var monitor_geometry = display.get_monitor_geometry (display.get_primary_monitor ());
var primary_monitor = display.get_primary_monitor ();
var monitor_geometry = display.get_monitor_geometry (primary_monitor);
var monitor_scale = display.get_monitor_scale (primary_monitor);

var background_click_action = new Clutter.ClickAction ();
background_click_action.clicked.connect (() => {
Expand All @@ -183,7 +185,7 @@ namespace Gala {
window_container.window_selected.connect ((w) => { window_selected (w); });
window_container.set_size (monitor_geometry.width, monitor_geometry.height);

icon_group = new IconGroup (wm, workspace);
icon_group = new IconGroup (wm, workspace, monitor_scale);
icon_group.selected.connect (() => selected (true));

var icons_drop_action = new DragDropAction (DragDropActionType.DESTINATION, "multitaskingview-window");
Expand Down Expand Up @@ -340,6 +342,7 @@ namespace Gala {
window_container.restack_windows ();

var scale_factor = InternalUtils.get_ui_scaling_factor ();
icon_group.scale_factor = scale_factor;
var display = workspace.get_display ();

var monitor = display.get_monitor_geometry (display.get_primary_monitor ());
Expand Down

0 comments on commit e5ef835

Please sign in to comment.