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

WindowSwitcher: Don't use Gtk #1868

Merged
merged 8 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
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
2 changes: 2 additions & 0 deletions lib/Drawing/Color.vala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ namespace Gala.Drawing {
* A class containing an RGBA color and methods for more powerful color manipulation.
*/
public class Color : GLib.Object, SettingsSerializable {
public const Gdk.RGBA LIGHT_BACKGROUND = { (250f / 255f), (250f / 255f), (250f / 255f), 1};
public const Gdk.RGBA DARK_BACKGROUND = { (51 / 255f), (51 / 255f), (51 / 255f), 1};
public const Gdk.RGBA TOOLTIP_BACKGROUND = { 0, 0, 0, 1};
public const Gdk.RGBA TOOLTIP_TEXT_COLOR = { 1, 1, 1, 1};

Expand Down
200 changes: 84 additions & 116 deletions src/Widgets/WindowSwitcher/WindowSwitcher.vala
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ public class Gala.WindowSwitcher : CanvasActor {
private Granite.Settings granite_settings;
private Clutter.Actor container;
private Clutter.Text caption;

private Gtk.WidgetPath widget_path;
private Gtk.StyleContext style_context;
private unowned Gtk.CssProvider? dark_style_provider = null;
private ShadowEffect shadow_effect;

private WindowSwitcherIcon? _current_icon = null;
private WindowSwitcherIcon? current_icon {
Expand Down Expand Up @@ -64,114 +61,112 @@ public class Gala.WindowSwitcher : CanvasActor {
unowned var gtk_settings = Gtk.Settings.get_default ();
granite_settings = Granite.Settings.get_default ();

unowned var display = wm.get_display ();
scaling_factor = display.get_monitor_scale (display.get_current_monitor ());
container = new Clutter.Actor () {
reactive = true,
layout_manager = new Clutter.FlowLayout (Clutter.FlowOrientation.HORIZONTAL)
};

opacity = 0;
caption = new Clutter.Text () {
font_name = CAPTION_FONT_NAME,
ellipsize = END,
line_alignment = CENTER
};
caption.set_pivot_point (0.5f, 0.5f);
leolost2605 marked this conversation as resolved.
Show resolved Hide resolved

// Carry out the initial draw
create_components ();
add_child (container);
add_child (caption);
opacity = 0;
layout_manager = new Clutter.BoxLayout () {
orientation = VERTICAL
};

var effect = new ShadowEffect (40) {
shadow_effect = new ShadowEffect (40) {
shadow_opacity = 200,
css_class = "window-switcher",
scale_factor = scaling_factor
css_class = "window-switcher"
};
add_effect (effect);
add_effect (shadow_effect);

scale ();

container.button_release_event.connect (container_mouse_release);

// Redraw the components if the colour scheme changes.
granite_settings.notify["prefers-color-scheme"].connect (() => {
content.invalidate ();
create_components ();
});
granite_settings.notify["prefers-color-scheme"].connect (content.invalidate);

gtk_settings.notify["gtk-theme-name"].connect (() => {
content.invalidate ();
create_components ();
});
gtk_settings.notify["gtk-theme-name"].connect (content.invalidate);

unowned var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager ();
monitor_manager.monitors_changed.connect (() => {
var cur_scale = display.get_monitor_scale (display.get_current_monitor ());
if (cur_scale != scaling_factor) {
scaling_factor = cur_scale;
effect.scale_factor = scaling_factor;
create_components ();
}
});
monitor_manager.monitors_changed.connect (scale);
}

protected override void draw (Cairo.Context ctx, int width, int height) {
if (style_context == null) { // gtk is not initialized yet
create_gtk_objects ();
}
private void scale () {
scaling_factor = wm.get_display ().get_monitor_scale (wm.get_display ().get_current_monitor ());

ctx.save ();
ctx.set_operator (Cairo.Operator.CLEAR);
ctx.paint ();
ctx.clip ();
ctx.reset_clip ();
shadow_effect.scale_factor = scaling_factor;

if (granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK) {
unowned var gtksettings = Gtk.Settings.get_default ();
dark_style_provider = Gtk.CssProvider.get_named (gtksettings.gtk_theme_name, "dark");
style_context.add_provider (dark_style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
} else if (dark_style_provider != null) {
style_context.remove_provider (dark_style_provider);
dark_style_provider = null;
}
var margin = InternalUtils.scale_to_int (WRAPPER_PADDING, scaling_factor);

ctx.set_operator (Cairo.Operator.OVER);
style_context.render_background (ctx, 0, 0, width, height);
style_context.render_frame (ctx, 0, 0, width, height);
ctx.restore ();
container.margin_left = margin;
container.margin_right = margin;
container.margin_bottom = margin;
container.margin_top = margin;

caption.margin_left = margin;
caption.margin_right = margin;
caption.margin_bottom = margin;
}

private void create_components () {
// We've already been constructed once, start again
if (container != null) {
destroy_all_children ();
}
protected override void get_preferred_width (float for_height, out float min_width, out float natural_width) {
min_width = 0;

var margin = InternalUtils.scale_to_int (WRAPPER_PADDING, scaling_factor);
var layout = new Clutter.FlowLayout (Clutter.FlowOrientation.HORIZONTAL);
container = new Clutter.Actor () {
reactive = true,
layout_manager = layout,
margin_left = margin,
margin_top = margin,
margin_right = margin,
margin_bottom = margin
};
float preferred_nat_width;
base.get_preferred_width (for_height, null, out preferred_nat_width);

container.button_release_event.connect (container_mouse_release);
unowned var display = wm.get_display ();
var monitor = display.get_current_monitor ();
var geom = display.get_monitor_geometry (monitor);

float container_nat_width;
container.get_preferred_size (null, null, out container_nat_width, null);

var max_width = float.min (
geom.width - InternalUtils.scale_to_int (MIN_OFFSET, scaling_factor) * 2, //Don't overflow the monitor
container_nat_width //Ellipsize the label if it's longer than the icons
);

natural_width = float.min (max_width, preferred_nat_width);
}

protected override void draw (Cairo.Context ctx, int width, int height) {
var caption_color = "#2e2e31";

if (granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK) {
caption_color = "#fafafa";
}

caption = new Clutter.Text.full (CAPTION_FONT_NAME, "", Clutter.Color.from_string (caption_color));
caption.set_pivot_point (0.5f, 0.5f);
caption.set_ellipsize (Pango.EllipsizeMode.END);
caption.set_line_alignment (Pango.Alignment.CENTER);
caption.color = Clutter.Color.from_string (caption_color);

add_child (container);
add_child (caption);
}
ctx.save ();
ctx.set_operator (Cairo.Operator.CLEAR);
ctx.paint ();
ctx.clip ();
ctx.reset_clip ();

var background_color = Drawing.Color.LIGHT_BACKGROUND;
if (granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK) {
background_color = Drawing.Color.DARK_BACKGROUND;
}

private void create_gtk_objects () {
widget_path = new Gtk.WidgetPath ();
widget_path.append_type (typeof (Gtk.Window));
widget_path.iter_set_object_name (-1, "window");

style_context = new Gtk.StyleContext ();
style_context.set_scale ((int)Math.round (scaling_factor));
style_context.set_path (widget_path);
style_context.add_class ("background");
style_context.add_class ("csd");
style_context.add_class ("unified");
ctx.set_operator (Cairo.Operator.SOURCE);
ctx.set_source_rgba (
background_color.red,
background_color.green,
background_color.blue,
background_color.alpha
);
Drawing.Utilities.cairo_rounded_rectangle (ctx, 0, 0, width, height, InternalUtils.scale_to_int (6, scaling_factor));
ctx.fill ();
ctx.restore ();
}

[CCode (instance_pos = -1)]
Expand Down Expand Up @@ -272,8 +267,7 @@ public class Gala.WindowSwitcher : CanvasActor {
current_icon = null;
}

container.width = -1;
container.destroy_all_children ();
container.remove_all_children ();

foreach (unowned var window in windows) {
var icon = new WindowSwitcherIcon (window, ICON_SIZE, scaling_factor);
Expand All @@ -299,8 +293,7 @@ public class Gala.WindowSwitcher : CanvasActor {
return false;
}

container.width = -1;
container.destroy_all_children ();
container.remove_all_children ();

unowned var window_tracker = ((WindowManagerGala) wm).window_tracker;
var app = window_tracker.get_app_for_window (current_window);
Expand Down Expand Up @@ -340,37 +333,19 @@ public class Gala.WindowSwitcher : CanvasActor {
return;
}

opacity = 0;
float width, height;
get_preferred_size (null, null, out width, out height);

unowned var display = wm.get_display ();
var monitor = display.get_current_monitor ();
var geom = display.get_monitor_geometry (monitor);

float container_width;
container.get_preferred_width (
InternalUtils.scale_to_int (ICON_SIZE, scaling_factor) + container.margin_left + container.margin_right,
null,
out container_width
);
if (container_width + InternalUtils.scale_to_int (MIN_OFFSET, scaling_factor) * 2 > geom.width) {
container.width = geom.width - InternalUtils.scale_to_int (MIN_OFFSET, scaling_factor) * 2;
}

float nat_width, nat_height;
container.get_preferred_size (null, null, out nat_width, out nat_height);

var switcher_height = (int) (nat_height + caption.height / 2 - container.margin_bottom + WRAPPER_PADDING * 3 * scaling_factor);
set_size ((int) nat_width, switcher_height);
content.invalidate ();

// container width might have changed, so we must update caption width too
update_caption_text ();

set_position (
(int) (geom.x + (geom.width - width) / 2),
(int) (geom.y + (geom.height - height) / 2)
);

opacity = 0;
toggle_display (true);
}

Expand Down Expand Up @@ -469,13 +444,6 @@ public class Gala.WindowSwitcher : CanvasActor {
var current_window = current_icon != null ? current_icon.window : null;
var current_caption = current_window != null ? current_window.title : "n/a";
caption.set_text (current_caption);

// Make caption smaller than the wrapper, so it doesn't overflow.
caption.width = width - WRAPPER_PADDING * 2 * scaling_factor;
caption.set_position (
InternalUtils.scale_to_int (WRAPPER_PADDING, scaling_factor),
(int) (height - caption.height / 2 - InternalUtils.scale_to_int (WRAPPER_PADDING, scaling_factor) * 2)
);
}

public override void key_focus_out () {
Expand Down