[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1101701: marco: lag of orca when using alt + tab when certain applications are launched



Package: marco
Version: 1.26.2-4.1
Severity: important
Tags: a11y patch upstream

Dear Maintainer,

with orca running, slowdowns have been observed when using the alt + tab
shortcut when QT applications are launched.

after investigation by orca (1), it has been shown that the bug originated from
marco. the attached patch corrects the problem.

(1): https://gitlab.gnome.org/GNOME/orca/-/issues/430

pr upstr    eam: https://github.com/mate-desktop/marco/pull/773

thanks !

-- System Information:
Debian Release: trixie/sid
APT prefers testing
APT policy: (500, 'testing'), (50, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 6.12.20-amd64 (SMP w/8 CPU threads; PREEMPT)
Kernel taint flags: TAINT_FORCED_RMMOD, TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages marco depends on:
ii libc6 2.41-6
ii libcairo2 1.18.4-1+b1
ii libgdk-pixbuf-2.0-0 2.42.12+dfsg-2
ii libglib2.0-0t64 [libglib2.0-0] 2.84.0-2
ii libgtk-3-0t64 [libgtk-3-0] 3.24.49-2
ii libmarco-private2 1.26.2-4.1
ii libpango-1.0-0 1.56.3-1
ii libx11-6 2:1.8.12-1
ii marco-common 1.26.2-4.1
ii mate-desktop-common 1.26.2-1.2
ii zenity 4.1.90-1

marco recommends no packages.

marco suggests no packages.

-- no debconf information
diff --git a/src/ui/tabpopup.c b/src/ui/tabpopup.c
index abd37b6d..892de65b 100644
--- a/src/ui/tabpopup.c
+++ b/src/ui/tabpopup.c
@@ -36,6 +36,7 @@
 #include "../core/frame-private.h"
 #include "draw-workspace.h"
 #include <gtk/gtk.h>
+#include <gtk/gtk-a11y.h>
 #include <gdk/gdkx.h>
 #include <math.h>
 
@@ -70,6 +71,14 @@ struct _MetaTabPopup
   gint border;
 };
 
+typedef GtkWindowAccessibleClass MetaTabPopupWindowAccessibleClass;
+typedef GtkWindowAccessible MetaTabPopupWindowAccessible;
+typedef GtkWindowClass MetaTabPopupWindowClass;
+typedef GtkWindow MetaTabPopupWindow;
+
+static GType      meta_tab_popup_window_get_type            (void);
+static GType      meta_tab_popup_window_accessible_get_type (void);
+
 static GtkWidget* selectable_image_new (GdkPixbuf *pixbuf, cairo_surface_t *win_surface);
 static void       select_image         (GtkWidget *widget);
 static void       unselect_image       (GtkWidget *widget);
@@ -79,6 +88,65 @@ static GtkWidget* selectable_workspace_new (MetaWorkspace *workspace,
 static void       select_workspace         (GtkWidget *widget);
 static void       unselect_workspace       (GtkWidget *widget);
 
+G_DEFINE_TYPE (MetaTabPopupWindowAccessible, meta_tab_popup_window_accessible, GTK_TYPE_WINDOW_ACCESSIBLE)
+G_DEFINE_TYPE (MetaTabPopupWindow, meta_tab_popup_window, GTK_TYPE_WINDOW)
+
+/*--- Accessible implementation for the popup window to report itself as active
+ *    when a switch is in progress.  We need special handling because the
+ *    actual interaction is done through key grabs, and thus GTK doesn't see
+ *    the switcher window as active, but that confuses some ATs that are
+ *    looking for the active window and find nothing. ---*/
+static AtkStateSet *
+meta_tab_popup_window_accessible_ref_state_set (AtkObject *accessible)
+{
+  AtkStateSet *state_set;
+  GtkWidget *widget;
+
+  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
+  if (widget == NULL)
+    return NULL;
+
+  state_set = ATK_OBJECT_CLASS (meta_tab_popup_window_accessible_parent_class)->ref_state_set (accessible);
+
+  if (gtk_widget_get_visible (widget))
+    atk_state_set_add_state (state_set, ATK_STATE_ACTIVE);
+
+  return state_set;
+}
+
+static void
+meta_tab_popup_window_accessible_class_init (MetaTabPopupWindowAccessibleClass *cls)
+{
+  AtkObjectClass *atk_cls = ATK_OBJECT_CLASS (cls);
+
+  atk_cls->ref_state_set = meta_tab_popup_window_accessible_ref_state_set;
+}
+
+static void
+meta_tab_popup_window_accessible_init (MetaTabPopupWindowAccessible *self)
+{
+}
+
+/*--- Custom GtkWindow subclass, mainly to be able to have our own accessible
+ *    implementation overrides ---*/
+static void
+meta_tab_popup_window_class_init (MetaTabPopupWindowClass *cls)
+{
+  gtk_widget_class_set_accessible_type (GTK_WIDGET_CLASS (cls), meta_tab_popup_window_accessible_get_type ());
+}
+
+static void
+meta_tab_popup_window_init (MetaTabPopupWindow *self)
+{
+}
+
+/* Creates a MetaTabPopupWindow instance with the required defaults */
+static GtkWidget *
+meta_tab_popup_window_new (void)
+{
+  return g_object_new (meta_tab_popup_window_get_type (), "type", GTK_WINDOW_POPUP, NULL);
+}
+
 static gboolean
 outline_window_draw (GtkWidget *widget,
                      cairo_t   *cr,
@@ -285,7 +353,7 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries,
   else
     popup->outline_window = NULL;
 
-  popup->window = gtk_window_new (GTK_WINDOW_POPUP);
+  popup->window = meta_tab_popup_window_new ();
 
   gtk_window_set_screen (GTK_WINDOW (popup->window), screen);
   gtk_window_set_position (GTK_WINDOW (popup->window), GTK_WIN_POS_CENTER_ALWAYS);
@@ -340,13 +408,6 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries,
 
   popup->label = gtk_label_new ("");
 
-  /* Set the accessible role of the label to a status bar so it
-   * will emit name changed events that can be used by screen
-   * readers.
-   */
-  obj = gtk_widget_get_accessible (popup->label);
-  atk_object_set_role (obj, ATK_ROLE_STATUSBAR);
-
   gtk_widget_set_margin_start (popup->label, 16);
   gtk_widget_set_margin_end (popup->label, 16);
   gtk_widget_set_margin_top (popup->label, 0);
@@ -421,6 +482,15 @@ meta_ui_tab_popup_new (const MetaTabEntry *entries,
   /* Make it so that we ellipsize if the text is too long */
   gtk_label_set_ellipsize (GTK_LABEL (popup->label), PANGO_ELLIPSIZE_END);
 
+  /* Set the accessible role of the label to a status bar so it
+   * will emit name changed events that can be used by screen
+   * readers.
+   * We do this *after* messing with the label content for computing the size
+   * not to send a change even for each entry at start.
+   */
+  obj = gtk_widget_get_accessible (popup->label);
+  atk_object_set_role (obj, ATK_ROLE_STATUSBAR);
+
   int default_window_width = 0; /* 0 == small as possible, truncate label */
 
   if (expand_for_titles && top <= 1 && left < width)

Reply to: