Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IconGroup: Support floating scale factors #1628

Merged
merged 2 commits into from
Apr 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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