From 3b8ad0b9cd1addb41d938785faa3247b1cf4a9db Mon Sep 17 00:00:00 2001 From: lukefromdc Date: Sat, 12 Aug 2023 18:52:14 -0400 Subject: Wayland: Fix position and behavior of dictionary applet popup window *Use gtk layer shell to duplicate the x11 behavior of the dictionary applet's popup dialog window --- configure.ac | 43 +++++++++++++++++---- mate-dictionary/src/Makefile.am | 8 ++++ mate-dictionary/src/gdict-aligned-window.c | 60 ++++++++++++++++++++++++++++++ mate-dictionary/src/gdict-applet.c | 15 ++++++++ 4 files changed, 118 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index 2587115e..d3f65b23 100644 --- a/configure.ac +++ b/configure.ac @@ -206,20 +206,46 @@ AS_CASE([$enable_gdict_applet], AM_CONDITIONAL([BUILD_GDICT_APPLET], [test "x$enable_gdict_applet" = "xyes"]) +#============================================================================ +# Dictionary Applet in-process and Wayland support +#============================================================================ + +AC_ARG_ENABLE([wayland], + [AS_HELP_STRING([--enable-wayland], + [Explicitly enable or disable Wayland support + (default is to enable only if Wayland client development library is detected)])], + [enable_wayland=$enableval], + [enable_wayland=auto]) AC_ARG_ENABLE([in-process], [AS_HELP_STRING([--enable-in-process], - [Build dictionary applet in-process])], + [Enable in-process build of dictionary applet (default: no, required for wayland)])], [enable_in_process=$enableval], - [enable_in_process=no]) + [dnl the default follows whether Wayland is requested or not, + dnl as Wayland support requires it but we d rather not have it + dnl otherwise for the moment + enable_in_process=$enable_wayland]) + +dnl $enable_in_process is gonna be either: +dnl - "no" if explicitly disabled +dnl - "yes" if explicitly enabled or if Wayland is explicitly enabled +dnl - "auto" if nothing specific is requested, in which case, default back to "no" +AS_IF([test "x$enable_in_process" != xyes], [enable_in_process=no]) + +WAYLAND_DEPS="gtk-layer-shell-0 >= $GTK_LAYER_SHELL_REQUIRED_VERSION wayland-client gdk-wayland-3.0 >= $GDK_WAYLAND_REQUIRED_VERSION" +AS_CASE(["x$enable_wayland$enable_in_process"], + [xautoyes], [PKG_CHECK_MODULES([WAYLAND], [$WAYLAND_DEPS], + [enable_wayland=yes], [enable_wayland=no])], + [xyesyes], [PKG_CHECK_MODULES([WAYLAND], [$WAYLAND_DEPS])], + [xyes*], [AC_MSG_ERROR([--enable-wayland requires --enable-in-process])], + [enable_wayland=no]) -# Automake conditional on whether to build dictionary applet in-process AM_CONDITIONAL([ENABLE_IN_PROCESS], [test "x$enable_in_process" = "xyes"]) AS_IF([test "x$enable_in_process" = "xyes"], - [AC_SUBST([APPLET_IN_PROCESS], [true])], - [AC_SUBST([APPLET_IN_PROCESS], [false])]) -# C conditional on whether to build in-process -AS_IF([test "x$enable_in_process" = "xyes"], - [AC_DEFINE([ENABLE_IN_PROCESS], [1], [building in-process])]) + [AC_DEFINE([ENABLE_IN_PROCESS], [1], [Enable if you want to build the panel applet in-process])]) +AM_CONDITIONAL(ENABLE_WAYLAND, [test "x$enable_wayland" = "xyes"]) +AS_IF([test "x$enable_wayland" = "xyes"], + [AC_DEFINE([ENABLE_WAYLAND], [1], [Enable if you want to build the panel applet in-process])]) + # Convenience C define selecting the right applet factory AS_IF([test "x$enable_in_process" = "xyes"], [factory=MATE_PANEL_APPLET_IN_PROCESS_FACTORY], @@ -432,5 +458,6 @@ mate-utils $VERSION configuration summary: Logview built with ZLib support : $msg_zlib Dictionary mate-panel applet : $enable_gdict_applet Dictionary applet in-process : $enable_in_process +Dictionary applet wayland support : $enable_wayland Native Language support : ${USE_NLS} " diff --git a/mate-dictionary/src/Makefile.am b/mate-dictionary/src/Makefile.am index 915c9c0c..fb05c24e 100644 --- a/mate-dictionary/src/Makefile.am +++ b/mate-dictionary/src/Makefile.am @@ -111,6 +111,14 @@ libmate_dictionary_applet_la_LIBADD = \ $(GIO_LIBS) \ $(GTK_LIBS) \ $(NULL) + +if ENABLE_WAYLAND +libmate_dictionary_applet_la_LIBADD += \ + $(WAYLAND_LIBS) +libmate_dictionary_applet_la_CFLAGS += \ + $(WAYLAND_CFLAGS) +endif + else mate_dictionary_applet_SOURCES = \ gdict-about.c \ diff --git a/mate-dictionary/src/gdict-aligned-window.c b/mate-dictionary/src/gdict-aligned-window.c index 42a00cc9..8c38d0ae 100644 --- a/mate-dictionary/src/gdict-aligned-window.c +++ b/mate-dictionary/src/gdict-aligned-window.c @@ -33,6 +33,11 @@ #include "gdict-aligned-window.h" +#if defined (ENABLE_WAYLAND) && defined (GDK_WINDOWING_WAYLAND) +#include +#include +#endif + struct _GdictAlignedWindowPrivate { GtkWidget *align_widget; @@ -215,6 +220,61 @@ gdict_aligned_window_position (GdictAlignedWindow *window) gtk_window_set_gravity (GTK_WINDOW (window), gravity); gtk_window_move (GTK_WINDOW (window), x, y); + +#if defined (ENABLE_WAYLAND) && defined (GDK_WINDOWING_WAYLAND) + if (GDK_IS_WAYLAND_DISPLAY (display)) + { + gboolean top, bottom, left, right; + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET(priv->align_widget)); + + top = gtk_layer_get_anchor (GTK_WINDOW (toplevel), GTK_LAYER_SHELL_EDGE_TOP); + bottom = gtk_layer_get_anchor (GTK_WINDOW (toplevel), GTK_LAYER_SHELL_EDGE_BOTTOM); + left = gtk_layer_get_anchor (GTK_WINDOW (toplevel), GTK_LAYER_SHELL_EDGE_LEFT); + right = gtk_layer_get_anchor (GTK_WINDOW (toplevel), GTK_LAYER_SHELL_EDGE_RIGHT); + + /*Set anchors to the edges (will hold to panel edge) and position along the panel + *Unset margins and anchors from any other position so as to avoid rendering issues + *when orientation changes as when the panel is moved + */ + if (top && left && right) + { + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_TOP, TRUE); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_LEFT, TRUE); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_BOTTOM, FALSE); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_RIGHT, FALSE); + gtk_layer_set_margin (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_LEFT, entry_x); + gtk_layer_set_margin (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_TOP, 0); + } + + if (bottom && left && right) + { + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_BOTTOM, TRUE); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_LEFT, TRUE); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_TOP, FALSE); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_RIGHT, FALSE); + gtk_layer_set_margin (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_LEFT, entry_x); + gtk_layer_set_margin (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_TOP, 0); + } + if (left && bottom && top && !right) + { + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_LEFT, TRUE); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_TOP, TRUE); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_RIGHT, FALSE); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_BOTTOM, FALSE); + gtk_layer_set_margin (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_TOP, entry_y); + gtk_layer_set_margin (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_LEFT, 0); + } + if (right && bottom && top && !left) + { + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_RIGHT, TRUE); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_TOP, TRUE); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_LEFT, FALSE); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_BOTTOM, FALSE); + gtk_layer_set_margin (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_TOP, entry_y); + gtk_layer_set_margin (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_LEFT, 0); + } + } +#endif } static void diff --git a/mate-dictionary/src/gdict-applet.c b/mate-dictionary/src/gdict-applet.c index b8c1b4eb..bc4b7593 100644 --- a/mate-dictionary/src/gdict-applet.c +++ b/mate-dictionary/src/gdict-applet.c @@ -38,6 +38,11 @@ #include "gdict-common.h" #include "gdict-aligned-window.h" +#if defined (ENABLE_WAYLAND) && defined (GDK_WINDOWING_WAYLAND) +#include +#include +#endif + #define GDICT_APPLET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDICT_TYPE_APPLET, GdictAppletClass)) #define GDICT_APPLET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDICT_TYPE_APPLET, GdictAppletClass)) @@ -314,6 +319,16 @@ gdict_applet_build_window (GdictApplet *applet) G_CALLBACK (window_show_cb), applet); + GdkDisplay *display = gdk_screen_get_display (gdk_screen_get_default()); + +#if defined (ENABLE_WAYLAND) && defined (GDK_WINDOWING_WAYLAND) + if ((GDK_IS_WAYLAND_DISPLAY (display)) && (!gtk_layer_is_layer_window (GTK_WINDOW (window)))) + { + gtk_layer_init_for_window (GTK_WINDOW (window)); + gtk_layer_set_layer (GTK_WINDOW (window), GTK_LAYER_SHELL_LAYER_TOP); + gtk_layer_set_keyboard_mode (GTK_WINDOW (window), GTK_LAYER_SHELL_KEYBOARD_MODE_ON_DEMAND); + } +#endif frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); gtk_container_add (GTK_CONTAINER (window), frame); -- cgit v1.2.1