44 */
55
66public class Dock.Launcher : BaseItem {
7+ private class PopoverTooltip : Gtk .Popover {
8+ class construct {
9+ set_css_name ("tooltip ");
10+ }
11+ }
12+
713 private const int DND_TIMEOUT = 1000 ;
814
915 private static Settings ? notify_settings;
@@ -30,7 +36,9 @@ public class Dock.Launcher : BaseItem {
3036 private Gtk . Revealer badge_revealer;
3137 private Adw . TimedAnimation bounce_up;
3238 private Adw . TimedAnimation bounce_down;
33- private Gtk . PopoverMenu popover;
39+ private Adw . TimedAnimation shake;
40+ private Gtk . PopoverMenu popover_menu;
41+ private Gtk . Popover popover_tooltip;
3442
3543 private Gtk . Image ? second_running_indicator;
3644 private bool multiple_windows_open {
@@ -63,11 +71,32 @@ public class Dock.Launcher : BaseItem {
6371 }
6472
6573 construct {
66- popover = new Gtk .PopoverMenu .from_model (app. menu_model) {
74+ popover_menu = new Gtk .PopoverMenu .from_model (app. menu_model) {
6775 autohide = true ,
6876 position = TOP
6977 };
70- popover. set_parent (this );
78+ popover_menu. set_parent (this );
79+
80+ var name_label = new Gtk .Label (app. app_info. get_display_name ());
81+ popover_tooltip = new PopoverTooltip () {
82+ position = TOP ,
83+ child = name_label,
84+ autohide = false ,
85+ can_focus = false ,
86+ can_target = false ,
87+ focusable = false ,
88+ has_arrow = false
89+ };
90+ popover_tooltip. set_parent (this );
91+
92+ var motion_controller = new Gtk .EventControllerMotion ();
93+ motion_controller. enter. connect (() = > {
94+ if (! popover_menu. visible) {
95+ popover_tooltip. popup ();
96+ }
97+ });
98+ motion_controller. leave. connect (popover_tooltip. popdown);
99+ add_controller (motion_controller);
71100
72101 image = new Gtk .Image ();
73102
@@ -99,8 +128,6 @@ public class Dock.Launcher : BaseItem {
99128 overlay. add_overlay (badge_revealer);
100129 overlay. add_overlay (progress_revealer);
101130
102- tooltip_text = app. app_info. get_display_name ();
103-
104131 insert_action_group (ACTION_GROUP_PREFIX , app. action_group);
105132
106133 // We have to destroy the progressbar when it is not needed otherwise it will
@@ -150,11 +177,33 @@ public class Dock.Launcher : BaseItem {
150177 };
151178 bounce_up. done. connect (bounce_down. play);
152179
180+ shake = new Adw .TimedAnimation (
181+ this ,
182+ 0 ,
183+ 0 ,
184+ 70 ,
185+ new Adw .CallbackAnimationTarget ((val) = > {
186+ var height = overlay. get_height ();
187+ var width = overlay. get_width ();
188+
189+ overlay. allocate (
190+ width, height, - 1 ,
191+ new Gsk .Transform (). translate (Graphene . Point () { x = (int ) val })
192+ );
193+ })
194+ ) {
195+ easing = EASE_OUT_CIRC ,
196+ reverse = true
197+ };
198+
153199 gesture_click. button = 0 ;
154200 gesture_click. released. connect (on_click_released);
155201
156202 var long_press = new Gtk .GestureLongPress ();
157- long_press. pressed. connect (popover. popup);
203+ long_press. pressed. connect (() = > {
204+ popover_menu. popup ();
205+ popover_tooltip. popdown ();
206+ });
158207 add_controller (long_press);
159208
160209 var scroll_controller = new Gtk .EventControllerScroll (VERTICAL );
@@ -200,8 +249,10 @@ public class Dock.Launcher : BaseItem {
200249 }
201250
202251 ~Launcher () {
203- popover. unparent ();
204- popover. dispose ();
252+ popover_menu. unparent ();
253+ popover_menu. dispose ();
254+ popover_tooltip. unparent ();
255+ popover_tooltip. dispose ();
205256 }
206257
207258 /**
@@ -211,6 +262,7 @@ public class Dock.Launcher : BaseItem {
211262 base . cleanup ();
212263 bounce_down = null ;
213264 bounce_up = null ;
265+ shake = null ;
214266 current_count_binding. unbind ();
215267 remove_dnd_cycle ();
216268 }
@@ -228,11 +280,13 @@ public class Dock.Launcher : BaseItem {
228280 if (app. launch_new_instance (context)) {
229281 animate_launch ();
230282 } else {
283+ animate_shake ();
231284 event_display. beep ();
232285 }
233286 break ;
234287 case Gdk . BUTTON_SECONDARY:
235- popover. popup ();
288+ popover_menu. popup ();
289+ popover_tooltip. popdown ();
236290 break ;
237291 }
238292 }
@@ -248,6 +302,28 @@ public class Dock.Launcher : BaseItem {
248302 bounce_up. play ();
249303 }
250304
305+ private void animate_shake () {
306+ if (shake. state == PLAYING ) {
307+ return ;
308+ }
309+
310+ shake. value_to = - 0.1 * overlay. get_width ();
311+ shake. play ();
312+
313+ int repeat_count = 0 ;
314+ ulong iterate = 0 ;
315+ iterate = shake. done. connect (() = > {
316+ if (repeat_count == 4 ) {
317+ disconnect (iterate);
318+ return ;
319+ }
320+
321+ shake. value_to * = - 1 ;
322+ shake. play ();
323+ repeat_count++ ;
324+ });
325+ }
326+
251327 protected override bool drag_cancelled (Gdk .Drag drag , Gdk .DragCancelReason reason ) {
252328 if (app. pinned && reason == NO_TARGET ) {
253329 var popover = new PoofPopover ();
@@ -288,6 +364,12 @@ public class Dock.Launcher : BaseItem {
288364 }
289365
290366 private void queue_dnd_cycle () {
367+ // This fixes an X11 bug where the cycling through all open windows of the app
368+ // is triggered while rearranging the app icons in the dock via drag and drop.
369+ if (moving) {
370+ return ;
371+ }
372+
291373 queue_dnd_cycle_id = Timeout . add (DND_TIMEOUT , () = > {
292374 app. next_window. begin (false );
293375 return Source . CONTINUE ;
0 commit comments