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 () public static Gdk.Pixbuf? get_close_button_pixbuf ()
{ {
if (close_pixbuf == null) { 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 { 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) { } catch (Error e) {
warning (e.message); warning (e.message);
return null; return null;
@ -315,7 +320,12 @@ namespace Gala
// we'll just make this red so there's at least something as an // we'll just make this red so there's at least something as an
// indicator that loading failed. Should never happen and this // indicator that loading failed. Should never happen and this
// works as good as some weird fallback-image-failed-to-load pixbuf // 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 }; texture.background_color = { 255, 0, 0, 255 };
} }
@ -330,8 +340,13 @@ namespace Gala
public static Gdk.Pixbuf? get_resize_button_pixbuf () public static Gdk.Pixbuf? get_resize_button_pixbuf ()
{ {
if (resize_pixbuf == null) { 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 { 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) { } catch (Error e) {
warning (e.message); warning (e.message);
return null; return null;
@ -363,7 +378,12 @@ namespace Gala
// we'll just make this red so there's at least something as an // we'll just make this red so there's at least something as an
// indicator that loading failed. Should never happen and this // indicator that loading failed. Should never happen and this
// works as good as some weird fallback-image-failed-to-load pixbuf // 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 }; 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) 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) public override void draw_content (Cairo.Context cr)
@ -63,14 +63,17 @@ namespace Gala.Plugins.Notify
if (!has_progress) if (!has_progress)
return; return;
var x = MARGIN + PADDING + ICON_SIZE + SPACING; var scale = style_context.get_scale ();
var y = MARGIN + PADDING + (ICON_SIZE - PROGRESS_HEIGHT) / 2; var scaled_margin = MARGIN * scale;
var width = WIDTH - x - MARGIN; 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) if (!transitioning)
draw_progress_bar (cr, x, y, width, progress); draw_progress_bar (cr, x, y, width, progress);
else { 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 (); cr.clip ();
draw_progress_bar (cr, x, y + animation_slide_y_offset, width, old_progress); 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 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, 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.set_source_rgb (0.8, 0.8, 0.8);
cr.fill (); cr.fill ();
if (progress > 0) { if (progress > 0) {
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, x, y, fraction, 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.set_source_rgb (0.3, 0.3, 0.3);
cr.fill (); cr.fill ();
} }
@ -111,7 +116,8 @@ namespace Gala.Plugins.Notify
old_progress = this.progress; 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) { 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) 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; 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; min_height = nat_height = label_height;
} }
public override void allocate (ActorBox box, AllocationFlags flags) 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; 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, 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 (); var summary_alloc = ActorBox ();
summary_alloc.set_origin (label_x, label_y); summary_alloc.set_origin (label_x, label_y);
@ -119,7 +129,7 @@ namespace Gala.Plugins.Notify
summary_label.allocate (summary_alloc, flags); summary_label.allocate (summary_alloc, flags);
var body_alloc = ActorBox (); 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_alloc.set_size (label_width, body_height);
body_label.allocate (body_alloc, flags); 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, 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_x = margin + padding + height + spacing;
label_width = Notification.WIDTH - label_x - Notification.MARGIN - Notification.SPACING; label_width = Notification.WIDTH * scale - label_x - margin - spacing;
summary_label.get_preferred_height (label_width, null, out summary_height); summary_label.get_preferred_height (label_width, null, out summary_height);
body_label.get_preferred_height (label_width, null, out body_height); body_label.get_preferred_height (label_width, null, out body_height);
label_height = summary_height + LABEL_SPACING + body_height; label_height = summary_height + LABEL_SPACING * scale + body_height;
label_y = Notification.MARGIN + Notification.PADDING; label_y = margin + padding;
// center // center
if (label_height < height) { if (label_height < height) {
label_y += (height - (int) label_height) / 2; label_y += (height - (int) label_height) / 2;
@ -225,7 +238,7 @@ namespace Gala.Plugins.Notify
content_height = float.max (content_height, old_content_height); 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 (() => { get_transition ("switch").completed.connect (() => {
if (old_notification_content != null) if (old_notification_content != null)
@ -258,7 +271,10 @@ namespace Gala.Plugins.Notify
// assume a constant width // assume a constant width
notification_content.get_preferred_height (0, null, out content_height); 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) 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; float content_height;
notification_content.get_preferred_height (for_width, null, out 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 () public override void activate ()

View File

@ -53,7 +53,7 @@ namespace Gala.Plugins.Notify
Clutter.Actor close_button; Clutter.Actor close_button;
Gtk.StyleContext style_context; protected Gtk.StyleContext style_context { get; private set; }
uint remove_timeout = 0; uint remove_timeout = 0;
@ -88,8 +88,13 @@ namespace Gala.Plugins.Notify
construct 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 (); relevancy_time = new DateTime.now_local ().to_unix ();
width = WIDTH + MARGIN * 2; width = (WIDTH + MARGIN * 2) * scale;
reactive = true; reactive = true;
set_pivot_point (0.5f, 0.5f); 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_provider (default_css, Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK);
style_context.add_class ("gala-notification"); style_context.add_class ("gala-notification");
style_context.set_path (style_path); style_context.set_path (style_path);
style_context.set_scale (scale);
var label_style_path = style_path.copy (); var label_style_path = style_path.copy ();
label_style_path.iter_add_class (1, "gala-notification"); label_style_path.iter_add_class (1, "gala-notification");
@ -217,7 +223,7 @@ namespace Gala.Plugins.Notify
set_easing_mode (AnimationMode.EASE_IN_QUAD); set_easing_mode (AnimationMode.EASE_IN_QUAD);
opacity = 0; opacity = 0;
x = WIDTH + MARGIN * 2; x = (WIDTH + MARGIN * 2) * style_context.get_scale ();
being_destroyed = true; being_destroyed = true;
var transition = get_transition ("x"); var transition = get_transition ("x");
@ -306,19 +312,23 @@ namespace Gala.Plugins.Notify
{ {
var icon_alloc = ActorBox (); var icon_alloc = ActorBox ();
icon_alloc.set_origin (icon_only ? (WIDTH - ICON_SIZE) / 2 : MARGIN + PADDING, MARGIN + PADDING); var scale = style_context.get_scale ();
icon_alloc.set_size (ICON_SIZE, ICON_SIZE); 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); icon_container.allocate (icon_alloc, flags);
var close_alloc = ActorBox (); var close_alloc = ActorBox ();
close_alloc.set_origin (MARGIN + PADDING - close_button.width / 2, close_alloc.set_origin (scaled_margin_padding - close_button.width / 2,
MARGIN + PADDING - close_button.height / 2); scaled_margin_padding - close_button.height / 2);
close_alloc.set_size (close_button.width, close_button.height); close_alloc.set_size (close_button.width, close_button.height);
close_button.allocate (close_alloc, flags); close_button.allocate (close_alloc, flags);
float content_height; float content_height;
update_allocation (out content_height, flags); 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); 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) 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) protected void play_update_transition (float slide_height)
@ -344,9 +354,12 @@ namespace Gala.Plugins.Notify
animation_slide_height = slide_height; 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 (); old_texture = new Clutter.Texture ();
icon_container.add_child (old_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) { if (icon != null) {
try { try {
@ -382,10 +395,11 @@ namespace Gala.Plugins.Notify
{ {
var canvas = (Canvas) content; var canvas = (Canvas) content;
var x = MARGIN; var scale = style_context.get_scale ();
var y = MARGIN; var x = MARGIN * scale;
var width = canvas.width - MARGIN * 2; var y = MARGIN * scale;
var height = canvas.height - MARGIN * 2; var width = canvas.width - MARGIN * 2 * scale;
var height = canvas.height - MARGIN * 2 * scale;
cr.set_operator (Cairo.Operator.CLEAR); cr.set_operator (Cairo.Operator.CLEAR);
cr.paint (); cr.paint ();
cr.set_operator (Cairo.Operator.OVER); cr.set_operator (Cairo.Operator.OVER);

View File

@ -38,20 +38,30 @@ namespace Gala.Plugins.Notify
construct 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; clip_to_allocation = true;
} }
public void show_notification (Notification notification) public void show_notification (Notification notification)
{ {
animations_changed (true); 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 // raise ourselves when we got something to show
get_parent ().set_child_above_sibling (this, null); get_parent ().set_child_above_sibling (this, null);
// we have a shoot-over on the start of the close animation, which gets clipped // 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 // 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 (() => { notification.notify["being-destroyed"].connect (() => {
animations_changed (true); animations_changed (true);
@ -67,16 +77,21 @@ namespace Gala.Plugins.Notify
}); });
float height; float height;
notification.get_preferred_height (Notification.WIDTH, out height, null); notification.get_preferred_height (Notification.WIDTH * scale, out height, null);
update_positions (height); update_positions (height);
notification.y = TOP_OFFSET; notification.y = TOP_OFFSET * scale;
insert_child_at_index (notification, 0); insert_child_at_index (notification, 0);
} }
void update_positions (float add_y = 0.0f) 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 i = get_n_children ();
var delay_step = i > 0 ? 150 / i : 0; var delay_step = i > 0 ? 150 / i : 0;
foreach (var child in get_children ()) { foreach (var child in get_children ()) {

View File

@ -338,8 +338,13 @@ namespace Gala.Plugins.Notify
Gdk.Pixbuf? pixbuf = null; Gdk.Pixbuf? pixbuf = null;
Variant? variant = null; Variant? variant = null;
var size = Notification.ICON_SIZE; #if HAS_MUTTER326
var mask_offset = 4; 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 mask_size_offset = mask_offset * 2;
var has_mask = false; var has_mask = false;
@ -365,7 +370,7 @@ namespace Gala.Plugins.Notify
var file_path = File.new_for_commandline_arg (image_path).get_path (); 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); pixbuf = new Gdk.Pixbuf.from_file_at_scale (file_path, size, size, true);
} else { } 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); } } catch (Error e) { warning (e.message); }
@ -373,7 +378,7 @@ namespace Gala.Plugins.Notify
try { try {
var themed = new ThemedIcon.with_default_fallbacks (app_icon); 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) { if (info != null) {
pixbuf = info.load_symbolic (get_icon_fg_color ()); pixbuf = info.load_symbolic (get_icon_fg_color ());
@ -389,7 +394,7 @@ namespace Gala.Plugins.Notify
try { try {
var themed = new ThemedIcon (app_name.down ()); 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) { if (info != null) {
pixbuf = info.load_symbolic (get_icon_fg_color ()); pixbuf = info.load_symbolic (get_icon_fg_color ());
@ -399,19 +404,18 @@ namespace Gala.Plugins.Notify
} catch (Error e) { } catch (Error e) {
try { 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); } } catch (Error e) { warning (e.message); }
} }
} else if (has_mask) { } else if (has_mask) {
var mask_size = Notification.ICON_SIZE;
var offset_x = mask_offset; 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 surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, mask_size, mask_size);
var cr = new Cairo.Context (surface); var cr = new Cairo.Context (surface);
Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, offset_x, offset_y, size, size, mask_offset);
offset_x, offset_y, size, size, 4);
cr.clip (); cr.clip ();
Gdk.cairo_set_source_pixbuf (cr, pixbuf, offset_x, offset_y); Gdk.cairo_set_source_pixbuf (cr, pixbuf, offset_x, offset_y);