notify: Make notifications to be HiDPI compatible

This commit is contained in:
Corentin Noël 2017-09-26 00:59:55 +02:00 committed by Rico Tzschichholz
parent 0b8fa51cab
commit 9b68c4b664
6 changed files with 128 additions and 53 deletions

View File

@ -282,8 +282,13 @@ namespace Gala
public static Gdk.Pixbuf? get_close_button_pixbuf ()
{
if (close_pixbuf == null) {
#if HAS_MUTTER326
var scale = Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
#else
var scale = 1;
#endif
try {
close_pixbuf = new Gdk.Pixbuf.from_resource_at_scale (Config.RESOURCEPATH + "/buttons/close.svg", -1, 36, true);
close_pixbuf = new Gdk.Pixbuf.from_resource_at_scale (Config.RESOURCEPATH + "/buttons/close.svg", -1, 36 * scale, true);
} catch (Error e) {
warning (e.message);
return null;
@ -315,7 +320,12 @@ 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
texture.set_size (36, 36);
#if HAS_MUTTER326
var scale = Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
#else
var scale = 1;
#endif
texture.set_size (36 * scale, 36 * scale);
texture.background_color = { 255, 0, 0, 255 };
}
@ -330,8 +340,13 @@ namespace Gala
public static Gdk.Pixbuf? get_resize_button_pixbuf ()
{
if (resize_pixbuf == null) {
#if HAS_MUTTER326
var scale = Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
#else
var scale = 1;
#endif
try {
resize_pixbuf = new Gdk.Pixbuf.from_resource_at_scale (Config.RESOURCEPATH + "/buttons/resize.svg", -1, 36, true);
resize_pixbuf = new Gdk.Pixbuf.from_resource_at_scale (Config.RESOURCEPATH + "/buttons/resize.svg", -1, 36 * scale, true);
} catch (Error e) {
warning (e.message);
return null;
@ -363,7 +378,12 @@ 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
texture.set_size (36, 36);
#if HAS_MUTTER326
var scale = Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
#else
var scale = 1;
#endif
texture.set_size (36 * scale, 36 * scale);
texture.background_color = { 255, 0, 0, 255 };
}

View File

@ -55,7 +55,7 @@ namespace Gala.Plugins.Notify
public override void update_allocation (out float content_height, AllocationFlags flags)
{
content_height = ICON_SIZE;
content_height = ICON_SIZE * style_context.get_scale ();
}
public override void draw_content (Cairo.Context cr)
@ -63,14 +63,17 @@ namespace Gala.Plugins.Notify
if (!has_progress)
return;
var x = MARGIN + PADDING + ICON_SIZE + SPACING;
var y = MARGIN + PADDING + (ICON_SIZE - PROGRESS_HEIGHT) / 2;
var width = WIDTH - x - MARGIN;
var scale = style_context.get_scale ();
var scaled_margin = MARGIN * scale;
var scaled_width = WIDTH * scale;
var x = (MARGIN + PADDING + ICON_SIZE + SPACING) * scale;
var y = (MARGIN + PADDING + (ICON_SIZE - PROGRESS_HEIGHT) / 2) * scale;
var width = scaled_width - x - scaled_margin;
if (!transitioning)
draw_progress_bar (cr, x, y, width, progress);
else {
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, MARGIN, MARGIN, WIDTH - MARGIN * 2, ICON_SIZE + PADDING * 2, 4);
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, scaled_margin, scaled_margin, scaled_width - scaled_margin * 2, ICON_SIZE * scale + PADDING * 2 * scale, 4 * scale);
cr.clip ();
draw_progress_bar (cr, x, y + animation_slide_y_offset, width, old_progress);
@ -84,14 +87,16 @@ namespace Gala.Plugins.Notify
{
var fraction = (int) Math.floor (progress.clamp (0, 100) / 100.0 * width);
var scale = style_context.get_scale ();
var scaled_progress_height = PROGRESS_HEIGHT * scale;
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, x, y, width,
PROGRESS_HEIGHT, PROGRESS_HEIGHT / 2);
scaled_progress_height, scaled_progress_height / 2);
cr.set_source_rgb (0.8, 0.8, 0.8);
cr.fill ();
if (progress > 0) {
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, x, y, fraction,
PROGRESS_HEIGHT, PROGRESS_HEIGHT / 2);
scaled_progress_height, scaled_progress_height / 2);
cr.set_source_rgb (0.3, 0.3, 0.3);
cr.fill ();
}
@ -111,7 +116,8 @@ namespace Gala.Plugins.Notify
old_progress = this.progress;
play_update_transition (ICON_SIZE + PADDING * 2);
var scale = style_context.get_scale ();
play_update_transition ((ICON_SIZE + PADDING * 2) * scale);
}
if (this.icon_only != icon_only) {

View File

@ -101,17 +101,27 @@ namespace Gala.Plugins.Notify
public override void get_preferred_height (float for_width, out float min_height, out float nat_height)
{
#if HAS_MUTTER326
var scale = Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
#else
var scale = 1;
#endif
float label_height;
get_allocation_values (null, null, null, null, out label_height, null);
get_allocation_values (null, null, null, null, out label_height, null, scale);
min_height = nat_height = label_height;
}
public override void allocate (ActorBox box, AllocationFlags flags)
{
#if HAS_MUTTER326
var scale = Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
#else
var scale = 1;
#endif
float label_x, label_width, summary_height, body_height, label_height, label_y;
get_allocation_values (out label_x, out label_width, out summary_height,
out body_height, out label_height, out label_y);
out body_height, out label_height, out label_y, scale);
var summary_alloc = ActorBox ();
summary_alloc.set_origin (label_x, label_y);
@ -119,7 +129,7 @@ namespace Gala.Plugins.Notify
summary_label.allocate (summary_alloc, flags);
var body_alloc = ActorBox ();
body_alloc.set_origin (label_x, label_y + summary_height + LABEL_SPACING);
body_alloc.set_origin (label_x, label_y + summary_height + LABEL_SPACING * scale);
body_alloc.set_size (label_width, body_height);
body_label.allocate (body_alloc, flags);
@ -127,18 +137,21 @@ namespace Gala.Plugins.Notify
}
void get_allocation_values (out float label_x, out float label_width, out float summary_height,
out float body_height, out float label_height, out float label_y)
out float body_height, out float label_height, out float label_y, int scale)
{
var height = Notification.ICON_SIZE;
var height = Notification.ICON_SIZE * scale;
var margin = Notification.MARGIN * scale;
var padding = Notification.PADDING * scale;
var spacing = Notification.SPACING * scale;
label_x = Notification.MARGIN + Notification.PADDING + height + Notification.SPACING;
label_width = Notification.WIDTH - label_x - Notification.MARGIN - Notification.SPACING;
label_x = margin + padding + height + spacing;
label_width = Notification.WIDTH * scale - label_x - margin - spacing;
summary_label.get_preferred_height (label_width, null, out summary_height);
body_label.get_preferred_height (label_width, null, out body_height);
label_height = summary_height + LABEL_SPACING + body_height;
label_y = Notification.MARGIN + Notification.PADDING;
label_height = summary_height + LABEL_SPACING * scale + body_height;
label_y = margin + padding;
// center
if (label_height < height) {
label_y += (height - (int) label_height) / 2;
@ -225,7 +238,7 @@ namespace Gala.Plugins.Notify
content_height = float.max (content_height, old_content_height);
play_update_transition (content_height + PADDING * 2);
play_update_transition (content_height + PADDING * 2 * style_context.get_scale ());
get_transition ("switch").completed.connect (() => {
if (old_notification_content != null)
@ -258,7 +271,10 @@ namespace Gala.Plugins.Notify
// assume a constant width
notification_content.get_preferred_height (0, null, out content_height);
content_container.set_clip (MARGIN, MARGIN, MARGIN * 2 + WIDTH, content_height + PADDING * 2);
var scale = style_context.get_scale ();
var scaled_margin = MARGIN * scale;
content_container.set_clip (scaled_margin, scaled_margin, scaled_margin * 2 + WIDTH * scale, content_height + PADDING * 2 * scale);
}
public override void get_preferred_height (float for_width, out float min_height, out float nat_height)
@ -266,7 +282,7 @@ namespace Gala.Plugins.Notify
float content_height;
notification_content.get_preferred_height (for_width, null, out content_height);
min_height = nat_height = content_height + (MARGIN + PADDING) * 2;
min_height = nat_height = content_height + (MARGIN + PADDING) * 2 * style_context.get_scale ();
}
public override void activate ()

View File

@ -53,7 +53,7 @@ namespace Gala.Plugins.Notify
Clutter.Actor close_button;
Gtk.StyleContext style_context;
protected Gtk.StyleContext style_context { get; private set; }
uint remove_timeout = 0;
@ -88,8 +88,13 @@ namespace Gala.Plugins.Notify
construct
{
#if HAS_MUTTER326
var scale = Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
#else
var scale = 1;
#endif
relevancy_time = new DateTime.now_local ().to_unix ();
width = WIDTH + MARGIN * 2;
width = (WIDTH + MARGIN * 2) * scale;
reactive = true;
set_pivot_point (0.5f, 0.5f);
@ -131,6 +136,7 @@ namespace Gala.Plugins.Notify
style_context.add_provider (default_css, Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK);
style_context.add_class ("gala-notification");
style_context.set_path (style_path);
style_context.set_scale (scale);
var label_style_path = style_path.copy ();
label_style_path.iter_add_class (1, "gala-notification");
@ -217,7 +223,7 @@ namespace Gala.Plugins.Notify
set_easing_mode (AnimationMode.EASE_IN_QUAD);
opacity = 0;
x = WIDTH + MARGIN * 2;
x = (WIDTH + MARGIN * 2) * style_context.get_scale ();
being_destroyed = true;
var transition = get_transition ("x");
@ -306,19 +312,23 @@ namespace Gala.Plugins.Notify
{
var icon_alloc = ActorBox ();
icon_alloc.set_origin (icon_only ? (WIDTH - ICON_SIZE) / 2 : MARGIN + PADDING, MARGIN + PADDING);
icon_alloc.set_size (ICON_SIZE, ICON_SIZE);
var scale = style_context.get_scale ();
var scaled_width = WIDTH * scale;
var scaled_icon_size = ICON_SIZE * scale;
var scaled_margin_padding = (MARGIN + PADDING) * scale;
icon_alloc.set_origin (icon_only ? (scaled_width - scaled_icon_size) / 2 : scaled_margin_padding, scaled_margin_padding);
icon_alloc.set_size (scaled_icon_size, scaled_icon_size);
icon_container.allocate (icon_alloc, flags);
var close_alloc = ActorBox ();
close_alloc.set_origin (MARGIN + PADDING - close_button.width / 2,
MARGIN + PADDING - close_button.height / 2);
close_alloc.set_origin (scaled_margin_padding - close_button.width / 2,
scaled_margin_padding - close_button.height / 2);
close_alloc.set_size (close_button.width, close_button.height);
close_button.allocate (close_alloc, flags);
float content_height;
update_allocation (out content_height, flags);
box.set_size (MARGIN * 2 + WIDTH, (MARGIN + PADDING) * 2 + content_height);
box.set_size (MARGIN * 2 * scale + scaled_width, scaled_margin_padding * 2 + content_height);
base.allocate (box, flags);
@ -331,7 +341,7 @@ namespace Gala.Plugins.Notify
public override void get_preferred_height (float for_width, out float min_height, out float nat_height)
{
min_height = nat_height = ICON_SIZE + (MARGIN + PADDING) * 2;
min_height = nat_height = (ICON_SIZE + (MARGIN + PADDING) * 2) * style_context.get_scale ();
}
protected void play_update_transition (float slide_height)
@ -344,9 +354,12 @@ namespace Gala.Plugins.Notify
animation_slide_height = slide_height;
var scale = style_context.get_scale ();
var scaled_padding = PADDING * scale;
var scaled_icon_size = ICON_SIZE * scale;
old_texture = new Clutter.Texture ();
icon_container.add_child (old_texture);
icon_container.set_clip (0, -PADDING, ICON_SIZE, ICON_SIZE + PADDING * 2);
icon_container.set_clip (0, -scaled_padding, scaled_icon_size, scaled_icon_size + scaled_padding * 2);
if (icon != null) {
try {
@ -382,10 +395,11 @@ namespace Gala.Plugins.Notify
{
var canvas = (Canvas) content;
var x = MARGIN;
var y = MARGIN;
var width = canvas.width - MARGIN * 2;
var height = canvas.height - MARGIN * 2;
var scale = style_context.get_scale ();
var x = MARGIN * scale;
var y = MARGIN * scale;
var width = canvas.width - MARGIN * 2 * scale;
var height = canvas.height - MARGIN * 2 * scale;
cr.set_operator (Cairo.Operator.CLEAR);
cr.paint ();
cr.set_operator (Cairo.Operator.OVER);

View File

@ -38,20 +38,30 @@ namespace Gala.Plugins.Notify
construct
{
width = Notification.WIDTH + 2 * Notification.MARGIN + ADDITIONAL_MARGIN;
#if HAS_MUTTER326
var scale = Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
#else
var scale = 1;
#endif
width = (Notification.WIDTH + 2 * Notification.MARGIN + ADDITIONAL_MARGIN) * scale;
clip_to_allocation = true;
}
public void show_notification (Notification notification)
{
animations_changed (true);
#if HAS_MUTTER326
var scale = Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
#else
var scale = 1;
#endif
// raise ourselves when we got something to show
get_parent ().set_child_above_sibling (this, null);
// we have a shoot-over on the start of the close animation, which gets clipped
// unless we make our container a bit wider and move the notifications over
notification.margin_left = ADDITIONAL_MARGIN;
notification.margin_left = ADDITIONAL_MARGIN * scale;
notification.notify["being-destroyed"].connect (() => {
animations_changed (true);
@ -67,16 +77,21 @@ namespace Gala.Plugins.Notify
});
float height;
notification.get_preferred_height (Notification.WIDTH, out height, null);
notification.get_preferred_height (Notification.WIDTH * scale, out height, null);
update_positions (height);
notification.y = TOP_OFFSET;
notification.y = TOP_OFFSET * scale;
insert_child_at_index (notification, 0);
}
void update_positions (float add_y = 0.0f)
{
var y = add_y + TOP_OFFSET;
#if HAS_MUTTER326
var scale = Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
#else
var scale = 1;
#endif
var y = add_y + TOP_OFFSET * scale;
var i = get_n_children ();
var delay_step = i > 0 ? 150 / i : 0;
foreach (var child in get_children ()) {

View File

@ -338,8 +338,13 @@ namespace Gala.Plugins.Notify
Gdk.Pixbuf? pixbuf = null;
Variant? variant = null;
var size = Notification.ICON_SIZE;
var mask_offset = 4;
#if HAS_MUTTER326
var scale = Meta.Backend.get_backend ().get_settings ().get_ui_scaling_factor ();
#else
var scale = 1;
#endif
var size = Notification.ICON_SIZE * scale;
var mask_offset = 4 * scale;
var mask_size_offset = mask_offset * 2;
var has_mask = false;
@ -365,7 +370,7 @@ namespace Gala.Plugins.Notify
var file_path = File.new_for_commandline_arg (image_path).get_path ();
pixbuf = new Gdk.Pixbuf.from_file_at_scale (file_path, size, size, true);
} else {
pixbuf = Gtk.IconTheme.get_default ().load_icon (image_path, size, 0);
pixbuf = Gtk.IconTheme.get_default ().load_icon_for_scale (image_path, Notification.ICON_SIZE, scale, 0);
}
} catch (Error e) { warning (e.message); }
@ -373,7 +378,7 @@ namespace Gala.Plugins.Notify
try {
var themed = new ThemedIcon.with_default_fallbacks (app_icon);
var info = Gtk.IconTheme.get_default ().lookup_by_gicon (themed, size, 0);
var info = Gtk.IconTheme.get_default ().lookup_by_gicon_for_scale (themed, Notification.ICON_SIZE, scale, 0);
if (info != null) {
pixbuf = info.load_symbolic (get_icon_fg_color ());
@ -389,7 +394,7 @@ namespace Gala.Plugins.Notify
try {
var themed = new ThemedIcon (app_name.down ());
var info = Gtk.IconTheme.get_default ().lookup_by_gicon (themed, size, 0);
var info = Gtk.IconTheme.get_default ().lookup_by_gicon_for_scale (themed, Notification.ICON_SIZE, scale, 0);
if (info != null) {
pixbuf = info.load_symbolic (get_icon_fg_color ());
@ -399,19 +404,18 @@ namespace Gala.Plugins.Notify
} catch (Error e) {
try {
pixbuf = Gtk.IconTheme.get_default ().load_icon (FALLBACK_ICON, size, 0);
pixbuf = Gtk.IconTheme.get_default ().load_icon_for_scale (FALLBACK_ICON, Notification.ICON_SIZE, scale, 0);
} catch (Error e) { warning (e.message); }
}
} else if (has_mask) {
var mask_size = Notification.ICON_SIZE;
var offset_x = mask_offset;
var offset_y = mask_offset + 1;
var offset_y = mask_offset + scale;
var mask_size = Notification.ICON_SIZE * scale;
var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, mask_size, mask_size);
var cr = new Cairo.Context (surface);
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr,
offset_x, offset_y, size, size, 4);
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, offset_x, offset_y, size, size, mask_offset);
cr.clip ();
Gdk.cairo_set_source_pixbuf (cr, pixbuf, offset_x, offset_y);