@@ -32,7 +32,6 @@ namespace SwayNotificationCenter.Widgets {
3232 private HashTable<string, unowned NotificationGroup > noti_groups_name =
3333 new HashTable<string, unowned NotificationGroup > (str_hash, str_equal);
3434
35- private int list_position = 0 ;
3635 private bool list_reverse = false ;
3736
3837 // Default config values
@@ -132,8 +131,15 @@ namespace SwayNotificationCenter.Widgets {
132131 expanded_group = null ;
133132 }
134133
134+ // Make sure to change focus to the sibling. Otherwise,
135+ // the ListBox focuses the first notification.
136+ if (list_reverse) {
137+ navigate_up (group, true );
138+ } else {
139+ navigate_down (group, true );
140+ }
135141 list_box_controller. remove (group);
136- navigate_list ( -- list_position);
142+
137143 // Switches the stack page depending on the amount of notifications
138144 if (list_box_controller. length < 1 ) {
139145 stack. set_visible_child_name (STACK_PLACEHOLDER_PAGE );
@@ -202,18 +208,9 @@ namespace SwayNotificationCenter.Widgets {
202208 noti_groups_name. set (param. name_id, group);
203209 }
204210
205- // Set the new list position when the group receives keyboard focus
206- Gtk . EventControllerFocus focus_controller = new Gtk .EventControllerFocus ();
207- group. add_controller (focus_controller);
208- focus_controller. enter. connect (() = > {
209- int i = list_box_controller. get_children (). index (group);
210- if (list_position != int . MAX && list_position != i) {
211- list_position = i;
212- }
213- });
214-
215211 // Switches the stack page depending on the amount of notifications
216212 stack. set_visible_child_name (STACK_NOTIFICATIONS_PAGE );
213+
217214 list_box_controller. append (group);
218215 }
219216
@@ -237,9 +234,8 @@ namespace SwayNotificationCenter.Widgets {
237234 stderr. printf (e. message + " \n " );
238235 }
239236
240- // Keep focus on currently focused notification
241- list_box. grab_focus ();
242- navigate_list (++ list_position);
237+ // Focus the incoming notification
238+ group. grab_focus ();
243239 }
244240
245241 public void set_list_is_reversed (bool reversed) {
@@ -253,6 +249,9 @@ namespace SwayNotificationCenter.Widgets {
253249
254250 public bool key_press_event_cb (uint keyval, uint keycode, Gdk . ModifierType state) {
255251 var children = list_box_controller. get_children ();
252+ if (! (list_box. get_focus_child () is NotificationGroup )) {
253+ focus_first_notification ();
254+ }
256255 var group = (NotificationGroup ) list_box. get_focus_child ();
257256 switch (Gdk . keyval_name (keyval)) {
258257 case " Return" :
@@ -267,32 +266,14 @@ namespace SwayNotificationCenter.Widgets {
267266 break ;
268267 case " Delete" :
269268 case " BackSpace" :
270- if (group != null ) {
271- int len = (int ) children. length ();
272- if (len == 0 ) break ;
273- // Add a delta so that we select the next notification
274- // due to it not being gone from the list yet due to
275- // the fade transition
276- int delta = 2 ;
277- if (list_reverse) {
278- if (children. first (). data != group) {
279- delta = 0 ;
280- }
281- list_position-- ;
282- } else {
283- if (list_position > 0 ) list_position-- ;
284- if (children. last (). data == group) {
285- delta = 0 ;
286- }
287- }
269+ if (group != null && ! children. is_empty ()) {
288270 var noti = group. get_latest_notification ();
289271 if (group. only_single_notification () && noti != null ) {
290272 close_notification (noti. param. applied_id, true );
291273 break ;
292274 }
293275 group. close_all_notifications ();
294- navigate_list (list_position + delta);
295- return true ;
276+ break ;
296277 }
297278 break ;
298279 case " C" :
@@ -306,19 +287,16 @@ namespace SwayNotificationCenter.Widgets {
306287 }
307288 break ;
308289 case " Down" :
309- if (list_position + 1 < children. length ()) {
310- ++ list_position;
311- }
290+ navigate_down (group);
312291 break ;
313292 case " Up" :
314- if (list_position > 0 ) -- list_position ;
293+ navigate_up (group) ;
315294 break ;
316295 case " Home" :
317- list_position = 0 ;
296+ navigate_to_first_notification () ;
318297 break ;
319298 case " End" :
320- list_position = ((int ) children. length ()) - 1 ;
321- if (list_position == uint . MAX ) list_position = 0 ;
299+ navigate_to_last_notification ();
322300 break ;
323301 default:
324302 // Pressing 1-9 to activate a notification action
@@ -333,7 +311,6 @@ namespace SwayNotificationCenter.Widgets {
333311 }
334312 break ;
335313 }
336- navigate_list (list_position);
337314 // Override the builtin list navigation
338315 return true ;
339316 }
@@ -391,29 +368,80 @@ namespace SwayNotificationCenter.Widgets {
391368 }
392369
393370 private void navigate_list (int i) {
371+ if (list_box_controller. length == 0 ) {
372+ return ;
373+ }
374+
394375 unowned Gtk . ListBoxRow ? widget = list_box. get_row_at_index (i);
395376 if (widget == null ) {
396377 // Try getting the last widget
397378 if (list_reverse) {
398379 widget = list_box. get_row_at_index (0 );
399380 } else {
400- int len = (( int ) list_box_controller. length) - 1 ;
381+ int len = list_box_controller. length - 1 ;
401382 widget = list_box. get_row_at_index (len);
402383 }
403384 }
404385 if (widget != null ) {
405386 widget. grab_focus ();
406- list_box. set_focus_child (widget);
387+ } else {
388+ list_box. grab_focus ();
389+ }
390+ }
391+
392+ private void navigate_up (NotificationGroup ? focused_group,
393+ bool fallback_other_dir = false ) {
394+ if (list_box_controller. length == 1 ) {
395+ focus_first_notification ();
396+ return ;
397+ }
398+ if (! (focused_group is NotificationGroup ) || list_box_controller. length == 0 ) {
399+ return ;
400+ }
401+ if (list_box. get_first_child () == focused_group) {
402+ if (fallback_other_dir) {
403+ navigate_down (focused_group, false );
404+ }
405+ return ;
406+ }
407+
408+ focused_group. move_focus (Gtk . DirectionType . TAB_BACKWARD );
409+ }
410+
411+ private void navigate_down (NotificationGroup ? focused_group,
412+ bool fallback_other_dir = false ) {
413+ if (list_box_controller. length == 1 ) {
414+ focus_first_notification ();
415+ return ;
416+ }
417+ if (! (focused_group is NotificationGroup ) || list_box_controller. length == 0 ) {
418+ return ;
419+ }
420+ if (list_box. get_last_child () == focused_group) {
421+ if (fallback_other_dir) {
422+ navigate_up (focused_group, false );
423+ }
424+ return ;
407425 }
426+
427+ focused_group. move_focus (Gtk . DirectionType . TAB_FORWARD );
428+ }
429+
430+ private void navigate_to_first_notification () {
431+ int i = (list_reverse ? list_box_controller. length - 1 : 0 )
432+ .clamp (0 , list_box_controller. length);
433+ navigate_list (i);
434+ }
435+
436+ private void navigate_to_last_notification () {
437+ int i = (list_reverse ? 0 : list_box_controller. length - 1 )
438+ .clamp (0 , list_box_controller. length);
439+ navigate_list (i);
408440 }
409441
410442 private void focus_first_notification () {
411- // Focus the first notification
412- list_position = (list_reverse ? (((int ) list_box_controller. length) - 1 ) : 0 )
413- .clamp (0 , (int ) list_box_controller. length);
443+ navigate_to_first_notification ();
414444
415- list_box. grab_focus ();
416- navigate_list (list_position);
417445 foreach (unowned Gtk . Widget w in list_box_controller. get_children ()) {
418446 var group = (NotificationGroup ) w;
419447 if (group != null ) group. update ();
0 commit comments