[metacity/main: 5/8] tooltip: request client side decorations




commit 36d60b1ae51e6c82fb7a46f195007275fd47d6df
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Sat Sep 4 14:41:56 2021 +0300

    tooltip: request client side decorations
    
    https://gitlab.gnome.org/GNOME/metacity/-/issues/25

 configure.ac              |   6 +-
 src/Makefile.am           |   2 +
 src/ui/meta-request-csd.c | 294 ++++++++++++++++++++++++++++++++++++++++++++++
 src/ui/meta-request-csd.h |  29 +++++
 src/ui/meta-tooltip.c     |   5 +-
 5 files changed, 334 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 04aafb94..6dba484d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -90,7 +90,7 @@ dnl Check for required packages
 dnl **************************************************************************
 
 GLIB_REQUIRED_VERSION=2.67.3
-GTK_REQUIRED_VERSION=3.22.0
+GTK_REQUIRED_VERSION=3.24.6
 PANGO_REQUIRED_VERSION=1.2.0
 XCOMPOSITE_REQUIRED_VERSION=0.3
 
@@ -342,6 +342,10 @@ if test x"$ZENITY" = xno; then
   AC_MSG_ERROR([zenity not found in your path - needed for dialogs])
 fi
 
+AC_SEARCH_LIBS([dlsym], [dl], [], [
+  AC_MSG_ERROR([unable to find the dlsym() function])
+])
+
 dnl **************************************************************************
 dnl Check for Vulkan support
 dnl **************************************************************************
diff --git a/src/Makefile.am b/src/Makefile.am
index 4aa3fdae..37da0f52 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -121,6 +121,8 @@ metacity_SOURCES = \
        ui/menu.h \
        ui/metaaccellabel.c \
        ui/metaaccellabel.h \
+       ui/meta-request-csd.c \
+       ui/meta-request-csd.h \
        ui/meta-tooltip.c \
        ui/meta-tooltip.h \
        ui/resizepopup.c \
diff --git a/src/ui/meta-request-csd.c b/src/ui/meta-request-csd.c
new file mode 100644
index 00000000..3670397b
--- /dev/null
+++ b/src/ui/meta-request-csd.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2021 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define _GNU_SOURCE
+
+#include "config.h"
+#include "meta-request-csd.h"
+
+#include <dlfcn.h>
+
+typedef GType (* RegisterStaticSimple)   (GType              parent_type,
+                                          const gchar       *type_name,
+                                          guint              class_size,
+                                          GClassInitFunc     class_init,
+                                          guint              instance_size,
+                                          GInstanceInitFunc  instance_init,
+                                          GTypeFlags         flags);
+
+typedef gint  (* AddInstancePrivateFunc) (GType              class_type,
+                                          gsize              private_size);
+
+typedef struct _GtkMnemnonicHash GtkMnemonicHash;
+typedef struct _GtkCssNode GtkCssNode;
+
+struct _GtkWindowPrivate
+{
+  GtkMnemonicHash       *mnemonic_hash;
+
+  GtkWidget             *attach_widget;
+  GtkWidget             *default_widget;
+  GtkWidget             *initial_focus;
+  GtkWidget             *focus_widget;
+  GtkWindow             *transient_parent;
+  GtkWindowGeometryInfo *geometry_info;
+  GtkWindowGroup        *group;
+  GdkScreen             *screen;
+  GdkDisplay            *display;
+  GtkApplication        *application;
+
+  GList                 *popovers;
+
+  GdkModifierType        mnemonic_modifier;
+
+  gchar                 *startup_id;
+  gchar                 *title;
+  gchar                 *wmclass_class;
+  gchar                 *wmclass_name;
+  gchar                 *wm_role;
+
+  guint                  keys_changed_handler;
+  guint                  delete_event_handler;
+
+  guint32                initial_timestamp;
+
+  guint16                configure_request_count;
+
+  guint                  mnemonics_display_timeout_id;
+
+  gint                   scale;
+
+  gint                   title_height;
+  GtkWidget             *title_box;
+  GtkWidget             *titlebar;
+  GtkWidget             *popup_menu;
+
+  GdkWindow             *border_window[8];
+  gint                   initial_fullscreen_monitor;
+  guint                  edge_constraints;
+
+  guint                  need_default_position        : 1;
+  guint                  need_default_size            : 1;
+
+  guint                  above_initially              : 1;
+  guint                  accept_focus                 : 1;
+  guint                  below_initially              : 1;
+  guint                  builder_visible              : 1;
+  guint                  configure_notify_received    : 1;
+  guint                  decorated                    : 1;
+  guint                  deletable                    : 1;
+  guint                  destroy_with_parent          : 1;
+  guint                  focus_on_map                 : 1;
+  guint                  fullscreen_initially         : 1;
+  guint                  has_focus                    : 1;
+  guint                  has_user_ref_count           : 1;
+  guint                  has_toplevel_focus           : 1;
+  guint                  hide_titlebar_when_maximized : 1;
+  guint                  iconify_initially            : 1;
+  guint                  is_active                    : 1;
+  guint                  maximize_initially           : 1;
+  guint                  mnemonics_visible            : 1;
+  guint                  mnemonics_visible_set        : 1;
+  guint                  focus_visible                : 1;
+  guint                  modal                        : 1;
+  guint                  position                     : 3;
+  guint                  resizable                    : 1;
+  guint                  skips_pager                  : 1;
+  guint                  skips_taskbar                : 1;
+  guint                  stick_initially              : 1;
+  guint                  transient_parent_group       : 1;
+  guint                  type                         : 4;
+  guint                  urgent                       : 1;
+  guint                  gravity                      : 5;
+  guint                  csd_requested                : 1;
+  guint                  client_decorated             : 1;
+  guint                  use_client_shadow            : 1;
+  guint                  maximized                    : 1;
+  guint                  fullscreen                   : 1;
+  guint                  tiled                        : 1;
+  guint                  unlimited_guessed_size_x     : 1;
+  guint                  unlimited_guessed_size_y     : 1;
+  guint                  force_resize                 : 1;
+  guint                  fixate_size                  : 1;
+
+  guint                  use_subsurface               : 1;
+
+  GdkWindowTypeHint      type_hint;
+
+  GtkGesture            *multipress_gesture;
+  GtkGesture            *drag_gesture;
+
+  GdkWindow             *hardcoded_window;
+
+  GtkCssNode            *decoration_node;
+};
+
+static RegisterStaticSimple register_static_simple_orig_func = NULL;
+static RegisterStaticSimple register_static_simple_func = NULL;
+static GType gtk_window_type = 0;
+
+static AddInstancePrivateFunc add_instance_private_orig_func = NULL;
+static AddInstancePrivateFunc add_instance_private_func = NULL;
+static gsize gtk_window_private_size = 0;
+
+static GType
+find_gtk_window_type (GType              parent_type,
+                      const gchar       *type_name,
+                      guint              class_size,
+                      GClassInitFunc     class_init,
+                      guint              instance_size,
+                      GInstanceInitFunc  instance_init,
+                      GTypeFlags         flags)
+{
+  GType type_id;
+
+  type_id = register_static_simple_orig_func (parent_type,
+                                              type_name,
+                                              class_size,
+                                              class_init,
+                                              instance_size,
+                                              instance_init,
+                                              flags);
+
+  if (g_strcmp0 (type_name, "GtkWindow") == 0)
+    {
+      register_static_simple_func = register_static_simple_orig_func;
+      gtk_window_type = type_id;
+    }
+
+  return type_id;
+}
+
+static gint
+find_gtk_window_private_size (GType class_type,
+                              gsize private_size)
+{
+  if (class_type == gtk_window_type)
+    {
+      add_instance_private_func = add_instance_private_orig_func;
+      gtk_window_private_size = private_size;
+    }
+
+  return add_instance_private_orig_func (class_type, private_size);
+}
+
+__attribute__((constructor))
+static void
+add_instance_private_init (void)
+{
+  void *func;
+
+  func = dlsym (RTLD_NEXT, "g_type_register_static_simple");
+  register_static_simple_orig_func = func;
+  register_static_simple_func = find_gtk_window_type;
+
+  func = dlsym (RTLD_NEXT, "g_type_add_instance_private");
+  add_instance_private_orig_func = func;
+  add_instance_private_func = find_gtk_window_private_size;
+}
+
+GType
+g_type_register_static_simple (GType              parent_type,
+                               const gchar       *type_name,
+                               guint              class_size,
+                               GClassInitFunc     class_init,
+                               guint              instance_size,
+                               GInstanceInitFunc  instance_init,
+                               GTypeFlags         flags)
+{
+  return register_static_simple_func (parent_type,
+                                      type_name,
+                                      class_size,
+                                      class_init,
+                                      instance_size,
+                                      instance_init,
+                                      flags);
+}
+
+gint
+g_type_add_instance_private (GType class_type,
+                             gsize private_size)
+{
+  return add_instance_private_func (class_type, private_size);
+}
+
+static gboolean
+check_gtk_window_private (void)
+{
+  static gboolean ret = FALSE;
+  static gboolean checked = FALSE;
+
+  if (!checked)
+    {
+      GtkWindow *window;
+
+      if (gtk_window_private_size < sizeof (GtkWindowPrivate))
+        {
+          checked = TRUE;
+          return FALSE;
+        }
+
+      window = g_object_new (GTK_TYPE_WINDOW,
+                             "type", GTK_WINDOW_POPUP,
+                             "type-hint", GDK_WINDOW_TYPE_HINT_TOOLTIP,
+                             NULL);
+
+      while (TRUE)
+        {
+          GtkWindowPrivate *priv;
+          GtkWidget *titlebar;
+
+          priv = window->priv;
+
+          if (priv->type != GTK_WINDOW_POPUP ||
+              priv->type_hint != GDK_WINDOW_TYPE_HINT_TOOLTIP)
+            break;
+
+          gtk_window_set_gravity (window, GDK_GRAVITY_STATIC);
+
+          if (priv->gravity != GDK_GRAVITY_STATIC)
+            break;
+
+          titlebar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+          gtk_window_set_titlebar (window, titlebar);
+
+          if (priv->title_box != titlebar ||
+              !priv->client_decorated)
+            break;
+
+          if (priv->csd_requested)
+            break;
+
+          ret = TRUE;
+          break;
+        }
+
+      gtk_widget_destroy (GTK_WIDGET (window));
+      checked = TRUE;
+    }
+
+  return ret;
+}
+
+void
+meta_request_csd (GtkWindow *window)
+{
+  if (!check_gtk_window_private ())
+    return;
+
+  window->priv->csd_requested = TRUE;
+}
diff --git a/src/ui/meta-request-csd.h b/src/ui/meta-request-csd.h
new file mode 100644
index 00000000..11ecb082
--- /dev/null
+++ b/src/ui/meta-request-csd.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef META_REQUEST_CSD_H
+#define META_REQUEST_CSD_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+void meta_request_csd (GtkWindow *window);
+
+G_END_DECLS
+
+#endif
diff --git a/src/ui/meta-tooltip.c b/src/ui/meta-tooltip.c
index f338b8b0..270b1166 100644
--- a/src/ui/meta-tooltip.c
+++ b/src/ui/meta-tooltip.c
@@ -16,9 +16,10 @@
  */
 
 #include "config.h"
-
 #include "meta-tooltip.h"
 
+#include "meta-request-csd.h"
+
 struct _MetaTooltip
 {
   GtkWindow  parent;
@@ -85,6 +86,8 @@ meta_tooltip_init (MetaTooltip *tooltip)
 
   gtk_label_set_line_wrap (GTK_LABEL (tooltip->label), TRUE);
   gtk_label_set_max_width_chars (GTK_LABEL (tooltip->label), 70);
+
+  meta_request_csd (GTK_WINDOW (tooltip));
 }
 
 GtkWidget *


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