diff --git a/config.h.meson.in b/config.h.meson.in index 8b49bbd10..910413897 100644 --- a/config.h.meson.in +++ b/config.h.meson.in @@ -19,6 +19,8 @@ #mesondefine HAVE_SELINUX // Define to enable pango-1.44 fixes #mesondefine HAVE_PANGO_144 +// Define to use gtk-layer-shell +#mesondefine HAVE_GTK_LAYER_SHELL diff --git a/debian/control b/debian/control index b250e40d1..2003578b9 100644 --- a/debian/control +++ b/debian/control @@ -21,12 +21,14 @@ Build-Depends: libgsf-1-dev, libgtk-3-dev (>= 3.10), libgtk-3-doc, + libgtk-layer-shell-dev, libjson-glib-dev (>= 1.6), libpango1.0-dev, libx11-dev, libxapp-dev (>= 2.0.0), libxext-dev, libxrender-dev, + libwayland-dev, meson, python3, python3-gi, diff --git a/debian/rules b/debian/rules index 6c68fb92b..3a73818b4 100755 --- a/debian/rules +++ b/debian/rules @@ -8,6 +8,7 @@ CONFIGURE_EXTRA_FLAGS = \ --buildtype=debugoptimized \ -D deprecated_warnings=false \ -D gtk_doc=true \ + -D gtk_layer_shell=true \ -D selinux=false export DEB_LDFLAGS_MAINT_APPEND = -Wl,-z,defs -Wl,-O1 -Wl,--as-needed diff --git a/meson.build b/meson.build index 53ad80c0c..bfeedbcca 100644 --- a/meson.build +++ b/meson.build @@ -133,6 +133,13 @@ if libselinux_enabled endif conf.set('HAVE_SELINUX', libselinux_enabled) +gtk_layer_shell_enabled = get_option('gtk_layer_shell') +if gtk_layer_shell_enabled + gtk_layer_shell = dependency('gtk-layer-shell-0', version: '>=0.8', required: true) + wayland_client = dependency('wayland-client', required: true) + conf.set('HAVE_GTK_LAYER_SHELL', gtk_layer_shell.found()) +endif + # make sure pango development files are installed pango = dependency('pango', version: '>=1.40.0') # check for newer pango for necessary workarounds @@ -201,6 +208,7 @@ message('\n'.join(['', ' exempi support: @0@'.format(exempi_enabled), ' Tracker support: @0@'.format(tracker_enabled), ' Wayland support: @0@'.format(cc.has_header('gdk/gdkwayland.h', dependencies: gtk)), +' gtk-layer-shell: @0@'.format(gtk_layer_shell_enabled), '', ' nemo-extension documentation: @0@'.format(gtkdoc_enabled), ' nemo-extension introspection: @0@'.format(true), diff --git a/meson_options.txt b/meson_options.txt index 68814d64d..c3122fc2a 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -12,3 +12,5 @@ option('empty_view', type : 'boolean', value : false, description: 'Enable empty view') option('tracker',type : 'combo', choices : ['true', 'false', 'auto'], value : 'false', description: 'Tracker support') +option('gtk_layer_shell', type : 'boolean', value : false, + description: 'Use gtk-layer-shell to draw desktop on wayland') diff --git a/src/meson.build b/src/meson.build index 07a56957d..da1b52b9e 100644 --- a/src/meson.build +++ b/src/meson.build @@ -113,6 +113,11 @@ if libexif_enabled nemo_deps += libexif endif +if gtk_layer_shell_enabled + nemo_deps += gtk_layer_shell + nemo_deps += wayland_client +endif + nemo = executable('nemo', nemoCommon_sources + nemoWindow_sources, include_directories: [ rootInclude ], diff --git a/src/nemo-blank-desktop-window.c b/src/nemo-blank-desktop-window.c index f6d6e545d..2d9aaf869 100644 --- a/src/nemo-blank-desktop-window.c +++ b/src/nemo-blank-desktop-window.c @@ -30,6 +30,10 @@ #include #include +#ifdef HAVE_GTK_LAYER_SHELL +#include +#endif + #include #include #include @@ -402,7 +406,15 @@ nemo_blank_desktop_window_init (NemoBlankDesktopWindow *window) window->details->popup_menu = NULL; window->details->actions_changed_id = 0; - gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DESKTOP); + +#ifdef HAVE_GTK_LAYER_SHELL + if (gtk_layer_is_supported ()) { + gtk_layer_init_for_window (GTK_WINDOW (window)); + } else +#endif + { + gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DESKTOP); + } /* Make it easier for themes authors to style the desktop window separately */ gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (window)), "nemo-desktop-window"); @@ -436,7 +448,13 @@ map (GtkWidget *widget) { /* Chain up to realize our children */ GTK_WIDGET_CLASS (nemo_blank_desktop_window_parent_class)->map (widget); - gdk_window_lower (gtk_widget_get_window (widget)); + +#ifdef HAVE_GTK_LAYER_SHELL + if (!gtk_layer_is_layer_window (GTK_WINDOW (widget))) +#endif + { + gdk_window_lower (gtk_widget_get_window (widget)); + } GdkWindow *window; GdkRGBA transparent = { 0, 0, 0, 0 }; @@ -499,6 +517,31 @@ nemo_blank_desktop_window_update_geometry (NemoBlankDesktopWindow *window) { GdkRectangle rect; +#ifdef HAVE_GTK_LAYER_SHELL + if (gtk_layer_is_layer_window (GTK_WINDOW (window))) { + GdkDisplay *display = gdk_display_get_default (); + GdkMonitor *monitor = gdk_display_get_monitor (display, window->details->monitor); + + DEBUG ("NemoBlankDesktopWindow: using layer-shell for monitor %d", + window->details->monitor); + + gtk_layer_set_layer (GTK_WINDOW (window), GTK_LAYER_SHELL_LAYER_BOTTOM); + gtk_layer_set_namespace (GTK_WINDOW (window), "nemo-desktop"); + gtk_layer_set_keyboard_mode (GTK_WINDOW (window), GTK_LAYER_SHELL_KEYBOARD_MODE_NONE); + gtk_layer_set_exclusive_zone (GTK_WINDOW (window), 0); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_TOP, TRUE); + 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_RIGHT, TRUE); + + if (monitor) { + gtk_layer_set_monitor (GTK_WINDOW (window), monitor); + } + + return; + } +#endif + nemo_desktop_manager_get_window_rect_for_monitor (nemo_desktop_manager_get (), window->details->monitor, &rect); diff --git a/src/nemo-desktop-main.c b/src/nemo-desktop-main.c index 5bbcad36a..c957f57f5 100644 --- a/src/nemo-desktop-main.c +++ b/src/nemo-desktop-main.c @@ -55,6 +55,47 @@ #ifdef HAVE_GTK_LAYER_SHELL #include +#include + +static gboolean layer_shell_available = FALSE; + +static void +registry_handle_global (void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + if (g_strcmp0 (interface, "zwlr_layer_shell_v1") == 0) + layer_shell_available = TRUE; +} + +static void +registry_handle_global_remove (void *data, struct wl_registry *registry, uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove, +}; + +static gboolean +check_layer_shell_support (void) +{ + struct wl_display *display; + struct wl_registry *registry; + + display = wl_display_connect (NULL); + if (!display) + return FALSE; + + registry = wl_display_get_registry (display); + wl_registry_add_listener (registry, ®istry_listener, NULL); + wl_display_roundtrip (display); + + wl_registry_destroy (registry); + wl_display_disconnect (display); + + return layer_shell_available; +} #endif int @@ -91,7 +132,20 @@ main (int argc, char *argv[]) g_set_prgname ("nemo-desktop"); +#ifdef HAVE_GTK_LAYER_SHELL + if (check_layer_shell_support ()) + { + g_message ("nemo-desktop: using Wayland backend, gtk-layer-shell supported"); + } + else + { + g_message ("nemo-desktop: Not a Wayland session, or wlr-layer-shell protocol not supported, using X11 backend"); + gdk_set_allowed_backends ("x11"); + } +#else + g_message ("nemo-desktop: using X11"); gdk_set_allowed_backends ("x11"); +#endif #ifdef HAVE_EXEMPI xmp_init(); diff --git a/src/nemo-desktop-manager.c b/src/nemo-desktop-manager.c index 86928e5b9..b0389cdc5 100644 --- a/src/nemo-desktop-manager.c +++ b/src/nemo-desktop-manager.c @@ -15,6 +15,10 @@ #include #include +#ifdef HAVE_GTK_LAYER_SHELL +#include +#endif + #include "libnemo-private/nemo-action-manager.h" #include #include @@ -629,12 +633,16 @@ fallback_startup_idle_cb (NemoDesktopManager *manager) static gboolean is_cinnamon_desktop (void) { + const gchar *session_desktop = g_getenv ("XDG_SESSION_DESKTOP"); + const gchar *desktop_session = g_getenv ("DESKTOP_SESSION"); - if (g_strcmp0 (g_getenv ("XDG_SESSION_DESKTOP"), "cinnamon") == 0) { + if (session_desktop != NULL && + g_strstr_len (session_desktop, -1, "cinnamon") != NULL) { return TRUE; } - if (g_strstr_len (g_getenv ("DESKTOP_SESSION"), -1, "cinnamon") != NULL) { + if (desktop_session != NULL && + g_strstr_len (desktop_session, -1, "cinnamon") != NULL) { return TRUE; } @@ -882,13 +890,24 @@ nemo_desktop_manager_get_margins (NemoDesktopManager *manager, { FETCH_PRIV (manager); GdkRectangle work_rect, geometry; + gboolean use_layer_shell = FALSE; + +#ifdef HAVE_GTK_LAYER_SHELL + use_layer_shell = gtk_layer_is_supported (); +#endif - /* We don't use margins if we have reliable work area - * info (e.g. having an active Cinnamon session) */ + DEBUG ("NemoDesktopManager get_margins: monitor=%d proxy_owned=%d other_desktop=%d use_layer_shell=%d", + monitor, priv->proxy_owned, priv->other_desktop, use_layer_shell); + + /* When Cinnamon is running, we don't use margins because the window is + * sized to the work area (X11 mode) or the compositor sizes it to the + * workarea (layer-shell mode with exclusive_zone=0). */ if (priv->proxy_owned && !priv->other_desktop) { *left = *right = *top = *bottom = 0; + DEBUG ("NemoDesktopManager get_margins: returning 0 margins (Cinnamon running)"); + return; } diff --git a/src/nemo-desktop-window.c b/src/nemo-desktop-window.c index 22f5040a3..3fa13f882 100644 --- a/src/nemo-desktop-window.c +++ b/src/nemo-desktop-window.c @@ -36,6 +36,10 @@ #include #include +#ifdef HAVE_GTK_LAYER_SHELL +#include +#endif + #include #include #include @@ -177,12 +181,20 @@ nemo_desktop_window_init (NemoDesktopWindow *window) window->details = G_TYPE_INSTANCE_GET_PRIVATE (window, NEMO_TYPE_DESKTOP_WINDOW, NemoDesktopWindowDetails); - g_object_set_data (G_OBJECT (window), "is_desktop_window", + g_object_set_data (G_OBJECT (window), "is_desktop_window", GINT_TO_POINTER (1)); /* Make it easier for themes authors to style the desktop window separately */ gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (window)), "nemo-desktop-window"); - gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DESKTOP); + +#ifdef HAVE_GTK_LAYER_SHELL + if (gtk_layer_is_supported ()) { + gtk_layer_init_for_window (GTK_WINDOW (window)); + } else +#endif + { + gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DESKTOP); + } } NemoDesktopWindow * @@ -230,7 +242,13 @@ map (GtkWidget *widget) { /* Chain up to realize our children */ GTK_WIDGET_CLASS (nemo_desktop_window_parent_class)->map (widget); - gdk_window_lower (gtk_widget_get_window (widget)); + +#ifdef HAVE_GTK_LAYER_SHELL + if (!gtk_layer_is_layer_window (GTK_WINDOW (widget))) +#endif + { + gdk_window_lower (gtk_widget_get_window (widget)); + } GdkWindow *window; GdkRGBA transparent = { 0, 0, 0, 0 }; @@ -335,6 +353,31 @@ nemo_desktop_window_update_geometry (NemoDesktopWindow *window) { GdkRectangle rect; +#ifdef HAVE_GTK_LAYER_SHELL + if (gtk_layer_is_layer_window (GTK_WINDOW (window))) { + GdkDisplay *display = gdk_display_get_default (); + GdkMonitor *monitor = gdk_display_get_monitor (display, window->details->monitor); + + DEBUG ("NemoDesktopWindow: using layer-shell for monitor %d", + window->details->monitor); + + gtk_layer_set_layer (GTK_WINDOW (window), GTK_LAYER_SHELL_LAYER_BOTTOM); + gtk_layer_set_namespace (GTK_WINDOW (window), "nemo-desktop"); + gtk_layer_set_keyboard_mode (GTK_WINDOW (window), GTK_LAYER_SHELL_KEYBOARD_MODE_ON_DEMAND); + gtk_layer_set_exclusive_zone (GTK_WINDOW (window), 0); + gtk_layer_set_anchor (GTK_WINDOW (window), GTK_LAYER_SHELL_EDGE_TOP, TRUE); + 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_RIGHT, TRUE); + + if (monitor) { + gtk_layer_set_monitor (GTK_WINDOW (window), monitor); + } + + return; + } +#endif + nemo_desktop_manager_get_window_rect_for_monitor (nemo_desktop_manager_get (), window->details->monitor, &rect);