Status: | Work in progress | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~gala-dev/gala/hidpi | ||||
Merge into: | lp:gala | ||||
Diff against target: |
678 lines (+203/-69) 9 files modified
lib/Utils.vala (+8/-6) lib/WindowManager.vala (+5/-0) plugins/notify/ConfirmationNotification.vala (+17/-8) plugins/notify/Main.vala (+3/-3) plugins/notify/NormalNotification.vala (+33/-14) plugins/notify/Notification.vala (+52/-25) plugins/notify/NotificationStack.vala (+8/-7) plugins/notify/NotifyServer.vala (+8/-6) src/WindowManager.vala (+69/-0) |
||||
To merge this branch: | bzr merge lp:~gala-dev/gala/hidpi | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gala developers | Pending | ||
Review via email: mp+317723@code.launchpad.net |
Commit message
Description of the change
Enable HiDPI on the notifications
To post a comment you must log in.
Unmerged revisions
- 564. By Corentin Noël
-
[HiDPI] Notifications are now working
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/Utils.vala' |
2 | --- lib/Utils.vala 2016-12-31 08:08:58 +0000 |
3 | +++ lib/Utils.vala 2017-02-19 16:15:16 +0000 |
4 | @@ -25,6 +25,7 @@ |
5 | static uint cache_clear_timeout = 0; |
6 | |
7 | static Gdk.Pixbuf? close_pixbuf = null; |
8 | + static int close_pixbuf_scale = 0; |
9 | |
10 | static construct |
11 | { |
12 | @@ -290,11 +291,12 @@ |
13 | * |
14 | * @return the close button pixbuf or null if it failed to load |
15 | */ |
16 | - public static Gdk.Pixbuf? get_close_button_pixbuf () |
17 | + public static Gdk.Pixbuf? get_close_button_pixbuf (int scale_factor) |
18 | { |
19 | - if (close_pixbuf == null) { |
20 | + if (close_pixbuf == null || close_pixbuf_scale != scale_factor) { |
21 | try { |
22 | - close_pixbuf = new Gdk.Pixbuf.from_file_at_scale (Config.PKGDATADIR + "/close.svg", -1, 36, true); |
23 | + close_pixbuf = new Gdk.Pixbuf.from_file_at_scale (Config.PKGDATADIR + "/close.svg", -1, 36 * scale_factor, true); |
24 | + close_pixbuf_scale = scale_factor; |
25 | } catch (Error e) { |
26 | warning (e.message); |
27 | return null; |
28 | @@ -309,10 +311,10 @@ |
29 | * |
30 | * @return The close button actor |
31 | */ |
32 | - public static Clutter.Actor create_close_button () |
33 | + public static Clutter.Actor create_close_button (int scale_factor = 1) |
34 | { |
35 | var texture = new Clutter.Texture (); |
36 | - var pixbuf = get_close_button_pixbuf (); |
37 | + var pixbuf = get_close_button_pixbuf (scale_factor); |
38 | |
39 | texture.reactive = true; |
40 | |
41 | @@ -326,7 +328,7 @@ |
42 | // we'll just make this red so there's at least something as an |
43 | // indicator that loading failed. Should never happen and this |
44 | // works as good as some weird fallback-image-failed-to-load pixbuf |
45 | - texture.set_size (36, 36); |
46 | + texture.set_size (36 * scale_factor, 36 * scale_factor); |
47 | texture.background_color = { 255, 0, 0, 255 }; |
48 | } |
49 | |
50 | |
51 | === modified file 'lib/WindowManager.vala' |
52 | --- lib/WindowManager.vala 2015-03-04 11:07:30 +0000 |
53 | +++ lib/WindowManager.vala 2017-02-19 16:15:16 +0000 |
54 | @@ -92,6 +92,11 @@ |
55 | public abstract Meta.BackgroundGroup background_group { get; protected set; } |
56 | |
57 | /** |
58 | + * The scale factor is the scale used by all user-facing elements |
59 | + */ |
60 | + public abstract int scale_factor { get; protected set; } |
61 | + |
62 | + /** |
63 | * Enters the modal mode, which means that all events are directed to the stage instead |
64 | * of the windows. This is the only way to receive keyboard events besides shortcut listeners. |
65 | * |
66 | |
67 | === modified file 'plugins/notify/ConfirmationNotification.vala' |
68 | --- plugins/notify/ConfirmationNotification.vala 2014-07-21 01:21:19 +0000 |
69 | +++ plugins/notify/ConfirmationNotification.vala 2017-02-19 16:15:16 +0000 |
70 | @@ -55,7 +55,7 @@ |
71 | |
72 | public override void update_allocation (out float content_height, AllocationFlags flags) |
73 | { |
74 | - content_height = ICON_SIZE; |
75 | + content_height = ICON_SIZE * style_context.get_scale (); |
76 | } |
77 | |
78 | public override void draw_content (Cairo.Context cr) |
79 | @@ -63,14 +63,21 @@ |
80 | if (!has_progress) |
81 | return; |
82 | |
83 | - var x = MARGIN + PADDING + ICON_SIZE + SPACING; |
84 | - var y = MARGIN + PADDING + (ICON_SIZE - PROGRESS_HEIGHT) / 2; |
85 | - var width = WIDTH - x - MARGIN; |
86 | + var scale = style_context.get_scale (); |
87 | + var scaled_width = WIDTH * scale; |
88 | + var scaled_margin = MARGIN * scale; |
89 | + var scaled_padding = PADDING * scale; |
90 | + var scaled_icon_size = ICON_SIZE * scale; |
91 | + var scaled_spacing = SPACING * scale; |
92 | + var scaled_progress_height = PROGRESS_HEIGHT * scale; |
93 | + var x = scaled_margin + scaled_padding + scaled_icon_size + scaled_spacing; |
94 | + var y = scaled_margin + scaled_padding + (scaled_icon_size - scaled_progress_height) / 2; |
95 | + var width = scaled_width - x - scaled_margin; |
96 | |
97 | if (!transitioning) |
98 | draw_progress_bar (cr, x, y, width, progress); |
99 | else { |
100 | - Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, MARGIN, MARGIN, WIDTH - MARGIN * 2, ICON_SIZE + PADDING * 2, 4); |
101 | + Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, scaled_margin, scaled_margin, scaled_width - scaled_margin * 2, scaled_icon_size + scaled_padding * 2, 4); |
102 | cr.clip (); |
103 | |
104 | draw_progress_bar (cr, x, y + animation_slide_y_offset, width, old_progress); |
105 | @@ -82,16 +89,18 @@ |
106 | |
107 | void draw_progress_bar (Cairo.Context cr, int x, float y, int width, int progress) |
108 | { |
109 | + var scale = style_context.get_scale (); |
110 | var fraction = (int) Math.floor (progress.clamp (0, 100) / 100.0 * width); |
111 | |
112 | + var scaled_height = PROGRESS_HEIGHT * scale; |
113 | Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, x, y, width, |
114 | - PROGRESS_HEIGHT, PROGRESS_HEIGHT / 2); |
115 | + scaled_height, scaled_height / 2); |
116 | cr.set_source_rgb (0.8, 0.8, 0.8); |
117 | cr.fill (); |
118 | |
119 | if (progress > 0) { |
120 | Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, x, y, fraction, |
121 | - PROGRESS_HEIGHT, PROGRESS_HEIGHT / 2); |
122 | + scaled_height, scaled_height / 2); |
123 | cr.set_source_rgb (0.3, 0.3, 0.3); |
124 | cr.fill (); |
125 | } |
126 | @@ -111,7 +120,7 @@ |
127 | |
128 | old_progress = this.progress; |
129 | |
130 | - play_update_transition (ICON_SIZE + PADDING * 2); |
131 | + play_update_transition ((ICON_SIZE + PADDING * 2) * style_context.get_scale ()); |
132 | } |
133 | |
134 | if (this.icon_only != icon_only) { |
135 | |
136 | === modified file 'plugins/notify/Main.vala' |
137 | --- plugins/notify/Main.vala 2014-07-18 11:12:31 +0000 |
138 | +++ plugins/notify/Main.vala 2017-02-19 16:15:16 +0000 |
139 | @@ -30,9 +30,8 @@ |
140 | public override void initialize (Gala.WindowManager wm) |
141 | { |
142 | this.wm = wm; |
143 | - var screen = wm.get_screen (); |
144 | |
145 | - stack = new NotificationStack (wm.get_screen ()); |
146 | + stack = new NotificationStack (wm); |
147 | wm.ui_group.add_child (stack); |
148 | track_actor (stack); |
149 | |
150 | @@ -43,6 +42,7 @@ |
151 | server = new NotifyServer (stack); |
152 | |
153 | update_position (); |
154 | + unowned Meta.Screen screen = wm.get_screen (); |
155 | screen.monitors_changed.connect (update_position); |
156 | screen.workareas_changed.connect (update_position); |
157 | |
158 | @@ -64,7 +64,7 @@ |
159 | |
160 | void update_position () |
161 | { |
162 | - var screen = wm.get_screen (); |
163 | + unowned Meta.Screen screen = wm.get_screen (); |
164 | var primary = screen.get_primary_monitor (); |
165 | var area = screen.get_active_workspace ().get_work_area_for_monitor (primary); |
166 | |
167 | |
168 | === modified file 'plugins/notify/NormalNotification.vala' |
169 | --- plugins/notify/NormalNotification.vala 2016-08-04 07:37:29 +0000 |
170 | +++ plugins/notify/NormalNotification.vala 2017-02-19 16:15:16 +0000 |
171 | @@ -38,6 +38,8 @@ |
172 | } catch (Error e) {} |
173 | } |
174 | |
175 | + public unowned Gtk.StyleContext parent_style_context { get; construct; } |
176 | + |
177 | const int LABEL_SPACING = 2; |
178 | |
179 | Text summary_label; |
180 | @@ -64,6 +66,7 @@ |
181 | var label_style_context = new Gtk.StyleContext (); |
182 | label_style_context.add_provider (Notification.default_css, Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK); |
183 | label_style_context.set_path (style_path); |
184 | + label_style_context.set_parent (parent_style_context); |
185 | |
186 | Gdk.RGBA color; |
187 | |
188 | @@ -93,6 +96,11 @@ |
189 | add_child (body_label); |
190 | } |
191 | |
192 | + public NormalNotificationContent (Gtk.StyleContext parent_style_context) |
193 | + { |
194 | + Object (parent_style_context: parent_style_context); |
195 | + } |
196 | + |
197 | public void set_values (string summary, string body) |
198 | { |
199 | summary_label.set_markup ("<b>%s</b>".printf (fix_markup (summary))); |
200 | @@ -119,7 +127,7 @@ |
201 | summary_label.allocate (summary_alloc, flags); |
202 | |
203 | var body_alloc = ActorBox (); |
204 | - body_alloc.set_origin (label_x, label_y + summary_height + LABEL_SPACING); |
205 | + body_alloc.set_origin (label_x, label_y + summary_height + LABEL_SPACING * parent_style_context.get_scale ()); |
206 | body_alloc.set_size (label_width, body_height); |
207 | body_label.allocate (body_alloc, flags); |
208 | |
209 | @@ -129,16 +137,22 @@ |
210 | void get_allocation_values (out float label_x, out float label_width, out float summary_height, |
211 | out float body_height, out float label_height, out float label_y) |
212 | { |
213 | - var height = Notification.ICON_SIZE; |
214 | + var scale = parent_style_context.get_scale (); |
215 | + var height = Notification.ICON_SIZE * scale; |
216 | + var width = scale * Notification.WIDTH; |
217 | + var margin = scale * Notification.MARGIN; |
218 | + var padding = scale * Notification.PADDING; |
219 | + var spacing = scale * Notification.SPACING; |
220 | + var label_spacing = scale * LABEL_SPACING; |
221 | |
222 | - label_x = Notification.MARGIN + Notification.PADDING + height + Notification.SPACING; |
223 | - label_width = Notification.WIDTH - label_x - Notification.MARGIN - Notification.SPACING; |
224 | + label_x = margin + padding + height + spacing; |
225 | + label_width = width - label_x - margin - spacing; |
226 | |
227 | summary_label.get_preferred_height (label_width, null, out summary_height); |
228 | body_label.get_preferred_height (label_width, null, out body_height); |
229 | |
230 | - label_height = summary_height + LABEL_SPACING + body_height; |
231 | - label_y = Notification.MARGIN + Notification.PADDING; |
232 | + label_height = summary_height + label_spacing + body_height; |
233 | + label_y = margin + padding; |
234 | // center |
235 | if (label_height < height) { |
236 | label_y += (height - (int) label_height) / 2; |
237 | @@ -168,13 +182,13 @@ |
238 | public string body { get; construct set; } |
239 | public uint32 sender_pid { get; construct; } |
240 | public string[] notification_actions { get; construct set; } |
241 | - public Screen screen { get; construct; } |
242 | + public unowned Gala.WindowManager wm { get; construct; } |
243 | |
244 | Actor content_container; |
245 | NormalNotificationContent notification_content; |
246 | NormalNotificationContent? old_notification_content = null; |
247 | |
248 | - public NormalNotification (Screen screen, uint32 id, string summary, string body, Gdk.Pixbuf? icon, |
249 | + public NormalNotification (Gala.WindowManager wm, uint32 id, string summary, string body, Gdk.Pixbuf? icon, |
250 | NotificationUrgency urgency, int32 expire_timeout, uint32 pid, string[] actions) |
251 | { |
252 | Object ( |
253 | @@ -182,7 +196,7 @@ |
254 | icon: icon, |
255 | urgency: urgency, |
256 | expire_timeout: expire_timeout, |
257 | - screen: screen, |
258 | + wm: wm, |
259 | summary: summary, |
260 | body: body, |
261 | sender_pid: pid, |
262 | @@ -192,9 +206,10 @@ |
263 | |
264 | construct |
265 | { |
266 | + set_scale_factor (wm.scale_factor); |
267 | content_container = new Actor (); |
268 | |
269 | - notification_content = new NormalNotificationContent (); |
270 | + notification_content = new NormalNotificationContent (style_context); |
271 | notification_content.set_values (summary, body); |
272 | |
273 | content_container.add_child (notification_content); |
274 | @@ -210,7 +225,7 @@ |
275 | if (old_notification_content != null) |
276 | old_notification_content.destroy (); |
277 | |
278 | - old_notification_content = new NormalNotificationContent (); |
279 | + old_notification_content = new NormalNotificationContent (style_context); |
280 | old_notification_content.set_values (this.summary, this.body); |
281 | |
282 | content_container.add_child (old_notification_content); |
283 | @@ -225,7 +240,7 @@ |
284 | |
285 | content_height = float.max (content_height, old_content_height); |
286 | |
287 | - play_update_transition (content_height + PADDING * 2); |
288 | + play_update_transition (content_height + PADDING * 2 * style_context.get_scale ()); |
289 | |
290 | get_transition ("switch").completed.connect (() => { |
291 | if (old_notification_content != null) |
292 | @@ -257,8 +272,10 @@ |
293 | // the for_width is not needed in our implementation of get_preferred_height as we |
294 | // assume a constant width |
295 | notification_content.get_preferred_height (0, null, out content_height); |
296 | + var scale = style_context.get_scale (); |
297 | + var scaled_margin = MARGIN * scale; |
298 | |
299 | - content_container.set_clip (MARGIN, MARGIN, MARGIN * 2 + WIDTH, content_height + PADDING * 2); |
300 | + content_container.set_clip (scaled_margin, scaled_margin, scaled_margin * 2 + WIDTH * scale, content_height + PADDING * 2 * scale); |
301 | } |
302 | |
303 | public override void get_preferred_height (float for_width, out float min_height, out float nat_height) |
304 | @@ -266,7 +283,7 @@ |
305 | float content_height; |
306 | notification_content.get_preferred_height (for_width, null, out content_height); |
307 | |
308 | - min_height = nat_height = content_height + (MARGIN + PADDING) * 2; |
309 | + min_height = nat_height = content_height + ((MARGIN + PADDING) * 2) * style_context.get_scale (); |
310 | } |
311 | |
312 | public override void activate () |
313 | @@ -287,6 +304,7 @@ |
314 | unowned Meta.Window? window = get_window (); |
315 | if (window != null) { |
316 | unowned Meta.Workspace workspace = window.get_workspace (); |
317 | + unowned Meta.Screen screen = wm.get_screen (); |
318 | var time = screen.get_display ().get_current_time (); |
319 | |
320 | if (workspace != screen.get_active_workspace ()) |
321 | @@ -303,6 +321,7 @@ |
322 | if (sender_pid == 0) |
323 | return null; |
324 | |
325 | + unowned Meta.Screen screen = wm.get_screen (); |
326 | foreach (unowned Meta.WindowActor actor in Meta.Compositor.get_window_actors (screen)) { |
327 | if (actor.is_destroyed ()) |
328 | continue; |
329 | |
330 | === modified file 'plugins/notify/Notification.vala' |
331 | --- plugins/notify/Notification.vala 2016-11-15 16:13:39 +0000 |
332 | +++ plugins/notify/Notification.vala 2017-02-19 16:15:16 +0000 |
333 | @@ -53,7 +53,7 @@ |
334 | |
335 | Clutter.Actor close_button; |
336 | |
337 | - Gtk.StyleContext style_context; |
338 | + protected Gtk.StyleContext style_context { get; private set; } |
339 | |
340 | uint remove_timeout = 0; |
341 | |
342 | @@ -99,20 +99,7 @@ |
343 | icon_container = new Actor (); |
344 | icon_container.add_child (icon_texture); |
345 | |
346 | - close_button = Utils.create_close_button (); |
347 | - close_button.opacity = 0; |
348 | - close_button.reactive = true; |
349 | - close_button.set_easing_duration (300); |
350 | - |
351 | - var close_click = new ClickAction (); |
352 | - close_click.clicked.connect (() => { |
353 | - closed (id, NotificationClosedReason.DISMISSED); |
354 | - close (); |
355 | - }); |
356 | - close_button.add_action (close_click); |
357 | - |
358 | add_child (icon_container); |
359 | - add_child (close_button); |
360 | |
361 | if (default_css == null) { |
362 | default_css = new Gtk.CssProvider (); |
363 | @@ -132,6 +119,8 @@ |
364 | style_context.add_class ("gala-notification"); |
365 | style_context.set_path (style_path); |
366 | |
367 | + create_close_button (); |
368 | + |
369 | var label_style_path = style_path.copy (); |
370 | label_style_path.iter_add_class (1, "gala-notification"); |
371 | label_style_path.append_type (typeof (Gtk.Label)); |
372 | @@ -227,6 +216,26 @@ |
373 | destroy (); |
374 | } |
375 | |
376 | + void create_close_button () { |
377 | + if (close_button != null) |
378 | + { |
379 | + close_button.destroy (); |
380 | + } |
381 | + |
382 | + close_button = Utils.create_close_button (style_context.get_scale ()); |
383 | + close_button.opacity = 0; |
384 | + close_button.reactive = true; |
385 | + close_button.set_easing_duration (300); |
386 | + |
387 | + var close_click = new ClickAction (); |
388 | + close_click.clicked.connect (() => { |
389 | + closed (id, NotificationClosedReason.DISMISSED); |
390 | + close (); |
391 | + }); |
392 | + close_button.add_action (close_click); |
393 | + add_child (close_button); |
394 | + } |
395 | + |
396 | protected void update_base (Gdk.Pixbuf? icon, int32 expire_timeout) |
397 | { |
398 | this.icon = icon; |
399 | @@ -273,6 +282,16 @@ |
400 | } |
401 | } |
402 | |
403 | + public void set_scale_factor (int scale_factor) |
404 | + { |
405 | + style_context.set_scale (scale_factor); |
406 | + width = (WIDTH + MARGIN * 2) * scale_factor; |
407 | + create_close_button (); |
408 | + if (content is Canvas) { |
409 | + ((Canvas) content).set_scale_factor (scale_factor); |
410 | + } |
411 | + } |
412 | + |
413 | public override bool enter_event (CrossingEvent event) |
414 | { |
415 | close_button.opacity = 255; |
416 | @@ -304,21 +323,26 @@ |
417 | |
418 | public override void allocate (ActorBox box, AllocationFlags flags) |
419 | { |
420 | + var scale = style_context.get_scale (); |
421 | + var scaled_width = WIDTH * scale; |
422 | + var scaled_icon_size = ICON_SIZE * scale; |
423 | + var scaled_margin = MARGIN * scale; |
424 | + var scaled_padding = PADDING * scale; |
425 | + var margin_padding = scaled_margin + scaled_padding; |
426 | var icon_alloc = ActorBox (); |
427 | |
428 | - icon_alloc.set_origin (icon_only ? (WIDTH - ICON_SIZE) / 2 : MARGIN + PADDING, MARGIN + PADDING); |
429 | - icon_alloc.set_size (ICON_SIZE, ICON_SIZE); |
430 | + icon_alloc.set_origin (icon_only ? (scaled_width - scaled_icon_size) / 2 : margin_padding, margin_padding); |
431 | + icon_alloc.set_size (scaled_icon_size, scaled_icon_size); |
432 | icon_container.allocate (icon_alloc, flags); |
433 | |
434 | var close_alloc = ActorBox (); |
435 | - close_alloc.set_origin (MARGIN + PADDING - close_button.width / 2, |
436 | - MARGIN + PADDING - close_button.height / 2); |
437 | + close_alloc.set_origin (margin_padding - close_button.width / 2, margin_padding - close_button.height / 2); |
438 | close_alloc.set_size (close_button.width, close_button.height); |
439 | close_button.allocate (close_alloc, flags); |
440 | |
441 | float content_height; |
442 | update_allocation (out content_height, flags); |
443 | - box.set_size (MARGIN * 2 + WIDTH, (MARGIN + PADDING) * 2 + content_height); |
444 | + box.set_size (scaled_margin * 2 + scaled_width, margin_padding * 2 + content_height); |
445 | |
446 | base.allocate (box, flags); |
447 | |
448 | @@ -331,7 +355,7 @@ |
449 | |
450 | public override void get_preferred_height (float for_width, out float min_height, out float nat_height) |
451 | { |
452 | - min_height = nat_height = ICON_SIZE + (MARGIN + PADDING) * 2; |
453 | + min_height = nat_height = (ICON_SIZE + (MARGIN + PADDING) * 2) * style_context.get_scale (); |
454 | } |
455 | |
456 | protected void play_update_transition (float slide_height) |
457 | @@ -346,7 +370,8 @@ |
458 | |
459 | old_texture = new Clutter.Texture (); |
460 | icon_container.add_child (old_texture); |
461 | - icon_container.set_clip (0, -PADDING, ICON_SIZE, ICON_SIZE + PADDING * 2); |
462 | + var scale = style_context.get_scale (); |
463 | + icon_container.set_clip (0, -PADDING * scale, ICON_SIZE * scale, (ICON_SIZE + PADDING * 2) * scale); |
464 | |
465 | if (icon != null) { |
466 | try { |
467 | @@ -382,10 +407,12 @@ |
468 | { |
469 | var canvas = (Canvas) content; |
470 | |
471 | - var x = MARGIN; |
472 | - var y = MARGIN; |
473 | - var width = canvas.width - MARGIN * 2; |
474 | - var height = canvas.height - MARGIN * 2; |
475 | + var scale = style_context.get_scale (); |
476 | + var margin_scaled = MARGIN * scale; |
477 | + var x = margin_scaled; |
478 | + var y = margin_scaled; |
479 | + var width = canvas.width - margin_scaled * 2; |
480 | + var height = canvas.height - margin_scaled * 2; |
481 | cr.set_operator (Cairo.Operator.CLEAR); |
482 | cr.paint (); |
483 | cr.set_operator (Cairo.Operator.OVER); |
484 | |
485 | === modified file 'plugins/notify/NotificationStack.vala' |
486 | --- plugins/notify/NotificationStack.vala 2016-07-28 22:19:16 +0000 |
487 | +++ plugins/notify/NotificationStack.vala 2017-02-19 16:15:16 +0000 |
488 | @@ -29,16 +29,16 @@ |
489 | |
490 | public signal void animations_changed (bool running); |
491 | |
492 | - public Screen screen { get; construct; } |
493 | + public unowned Gala.WindowManager wm { get; construct; } |
494 | |
495 | - public NotificationStack (Screen screen) |
496 | + public NotificationStack (Gala.WindowManager wm) |
497 | { |
498 | - Object (screen: screen); |
499 | + Object (wm: wm); |
500 | } |
501 | |
502 | construct |
503 | { |
504 | - width = Notification.WIDTH + 2 * Notification.MARGIN + ADDITIONAL_MARGIN; |
505 | + width = (Notification.WIDTH + 2 * Notification.MARGIN + ADDITIONAL_MARGIN) * wm.scale_factor; |
506 | clip_to_allocation = true; |
507 | } |
508 | |
509 | @@ -67,16 +67,17 @@ |
510 | }); |
511 | |
512 | float height; |
513 | - notification.get_preferred_height (Notification.WIDTH, out height, null); |
514 | + int scale_factor = wm.scale_factor; |
515 | + notification.get_preferred_height (Notification.WIDTH * scale_factor, out height, null); |
516 | update_positions (height); |
517 | |
518 | - notification.y = TOP_OFFSET; |
519 | + notification.y = TOP_OFFSET * scale_factor; |
520 | insert_child_at_index (notification, 0); |
521 | } |
522 | |
523 | void update_positions (float add_y = 0.0f) |
524 | { |
525 | - var y = add_y + TOP_OFFSET; |
526 | + var y = add_y + TOP_OFFSET * wm.scale_factor; |
527 | var i = get_n_children (); |
528 | var delay_step = i > 0 ? 150 / i : 0; |
529 | foreach (var child in get_children ()) { |
530 | |
531 | === modified file 'plugins/notify/NotifyServer.vala' |
532 | --- plugins/notify/NotifyServer.vala 2016-12-31 08:08:58 +0000 |
533 | +++ plugins/notify/NotifyServer.vala 2017-02-19 16:15:16 +0000 |
534 | @@ -170,7 +170,8 @@ |
535 | icon = app_info.get_icon ().to_string (); |
536 | |
537 | var id = (replaces_id != 0 ? replaces_id : ++id_counter); |
538 | - var pixbuf = get_pixbuf (app_name, icon, hints); |
539 | + unowned Gala.WindowManager wm = stack.wm; |
540 | + var pixbuf = get_pixbuf (app_name, icon, hints, wm.scale_factor); |
541 | var timeout = (expire_timeout == uint32.MAX ? DEFAULT_TMEOUT : expire_timeout); |
542 | |
543 | var urgency = NotificationUrgency.NORMAL; |
544 | @@ -285,9 +286,10 @@ |
545 | progress ? hints.@get ("value").get_int32 () : -1, |
546 | hints.@get (X_CANONICAL_PRIVATE_SYNCHRONOUS).get_string ()); |
547 | else |
548 | - notification = new NormalNotification (stack.screen, id, summary, body, pixbuf, |
549 | + notification = new NormalNotification (wm, id, summary, body, pixbuf, |
550 | urgency, timeout, pid, actions); |
551 | |
552 | + notification.set_scale_factor (wm.scale_factor); |
553 | notification.action_invoked.connect (notification_action_invoked_callback); |
554 | notification.closed.connect (notification_closed_callback); |
555 | stack.show_notification (notification); |
556 | @@ -326,7 +328,7 @@ |
557 | return icon_fg_color; |
558 | } |
559 | |
560 | - static Gdk.Pixbuf? get_pixbuf (string app_name, string app_icon, HashTable<string, Variant> hints) |
561 | + static Gdk.Pixbuf? get_pixbuf (string app_name, string app_icon, HashTable<string, Variant> hints, int scale_factor) |
562 | { |
563 | // decide on the icon, order: |
564 | // - image-data |
565 | @@ -338,8 +340,8 @@ |
566 | |
567 | Gdk.Pixbuf? pixbuf = null; |
568 | Variant? variant = null; |
569 | - var size = Notification.ICON_SIZE; |
570 | - var mask_offset = 4; |
571 | + var size = Notification.ICON_SIZE * scale_factor; |
572 | + var mask_offset = 4 * scale_factor; |
573 | var mask_size_offset = mask_offset * 2; |
574 | var has_mask = false; |
575 | |
576 | @@ -403,7 +405,7 @@ |
577 | } catch (Error e) { warning (e.message); } |
578 | } |
579 | } else if (has_mask) { |
580 | - var mask_size = Notification.ICON_SIZE; |
581 | + var mask_size = Notification.ICON_SIZE * scale_factor; |
582 | var offset_x = mask_offset; |
583 | var offset_y = mask_offset + 1; |
584 | |
585 | |
586 | === modified file 'src/WindowManager.vala' |
587 | --- src/WindowManager.vala 2016-11-18 16:57:03 +0000 |
588 | +++ src/WindowManager.vala 2017-02-19 16:15:16 +0000 |
589 | @@ -68,6 +68,11 @@ |
590 | */ |
591 | public Meta.BackgroundGroup background_group { get; protected set; } |
592 | |
593 | + /** |
594 | + * {@inheritDoc} |
595 | + */ |
596 | + public int scale_factor { get; protected set; } |
597 | + |
598 | Meta.PluginInfo info; |
599 | |
600 | WindowSwitcher? winswitcher = null; |
601 | @@ -144,6 +149,8 @@ |
602 | WindowListener.init (screen); |
603 | KeyboardManager.init (display); |
604 | |
605 | + compute_scale_factor (); |
606 | + |
607 | // Due to a bug which enables access to the stage when using multiple monitors |
608 | // in the screensaver, we have to listen for changes and make sure the input area |
609 | // is set to NONE when we are in locked mode |
610 | @@ -314,6 +321,68 @@ |
611 | return false; |
612 | } |
613 | |
614 | + /* DPI constants taken from gnome-settings-daemon/plugins/xsettings/gsd-xsettings-manager.c */ |
615 | + private const int DPI_FALLBACK = 96; |
616 | + /* The minimum resolution at which we turn on a window-scale of 2 */ |
617 | + private const int HIDPI_LIMIT = (DPI_FALLBACK * 2); |
618 | + /* The minimum screen height at which we turn on a window-scale of 2; |
619 | + * below this there just isn't enough vertical real estate for GNOME |
620 | + * apps to work, and it's better to just be tiny */ |
621 | + private const int HIDPI_MIN_HEIGHT = 1200; |
622 | + private const int SMALLEST_4K_WIDTH = 3656; |
623 | + |
624 | + void compute_scale_factor () |
625 | + { |
626 | + var desktop_settings = new GLib.Settings ("org.gnome.desktop.interface"); |
627 | + var desktop_scale = desktop_settings.get_int ("scaling-factor"); |
628 | + if (desktop_scale > 0) { |
629 | + scale_factor = desktop_scale; |
630 | + } else { |
631 | + weak Gdk.Display? display = Gdk.Display.get_default (); |
632 | + weak Gdk.Screen screen = display.get_default_screen (); |
633 | + var primary = screen.get_primary_monitor (); |
634 | + var rect = Gdk.Rectangle (); |
635 | + screen.get_monitor_geometry (primary, out rect); |
636 | + var monitor_scale = screen.get_monitor_scale_factor (primary); |
637 | + |
638 | + int width = rect.width * monitor_scale; |
639 | + int height = rect.height * monitor_scale; |
640 | + int width_mm = screen.get_monitor_width_mm (primary); |
641 | + int height_mm = screen.get_monitor_height_mm (primary); |
642 | + |
643 | + if (height < HIDPI_MIN_HEIGHT) |
644 | + { |
645 | + scale_factor = 1; |
646 | + return; |
647 | + } |
648 | + |
649 | + /* Somebody encoded the aspect ratio (16/9 or 16/10) |
650 | + * instead of the physical size */ |
651 | + if ((width_mm == 160 && height_mm == 90) || |
652 | + (width_mm == 160 && height_mm == 100) || |
653 | + (width_mm == 16 && height_mm == 9) || |
654 | + (width_mm == 16 && height_mm == 10)) |
655 | + { |
656 | + scale_factor = 1; |
657 | + return; |
658 | + } |
659 | + |
660 | + if (width_mm > 0 && height_mm > 0) { |
661 | + var dpi_x = (double)width / (width_mm / 25.4); |
662 | + var dpi_y = (double)height / (height_mm / 25.4); |
663 | + /* We don't completely trust these values so both |
664 | + must be high, and never pick higher ratio than |
665 | + 2 automatically */ |
666 | + if (dpi_x > HIDPI_LIMIT && dpi_y > HIDPI_LIMIT) { |
667 | + scale_factor = 2; |
668 | + return; |
669 | + } |
670 | + } |
671 | + |
672 | + scale_factor = 1; |
673 | + } |
674 | + } |
675 | + |
676 | void configure_hotcorners () |
677 | { |
678 | var geometry = get_screen ().get_monitor_geometry (get_screen ().get_primary_monitor ()); |