summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberts Muktupāvels <alberts.muktupavels@gmail.com>2021-09-04 14:41:56 +0300
committerAlberts Muktupāvels <alberts.muktupavels@gmail.com>2021-10-22 20:04:16 +0300
commit36d60b1ae51e6c82fb7a46f195007275fd47d6df (patch)
treead9cc10495786fb4aea2f21185810517e6828cfc
parentf2e22abc678be6dc8c7a5739976ace0775eed499 (diff)
downloadmetacity-36d60b1ae51e6c82fb7a46f195007275fd47d6df.tar.gz
tooltip: request client side decorations
https://gitlab.gnome.org/GNOME/metacity/-/issues/25
-rw-r--r--configure.ac6
-rw-r--r--src/Makefile.am2
-rw-r--r--src/ui/meta-request-csd.c294
-rw-r--r--src/ui/meta-request-csd.h29
-rw-r--r--src/ui/meta-tooltip.c5
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 *