From 786eab112c55907de593ba2593e2ce418fdd5173 Mon Sep 17 00:00:00 2001 From: wb9688 Date: Fri, 5 Feb 2021 19:16:02 +0100 Subject: [PATCH 1/4] Support Wayland in desktop manager --- configure.ac | 13 ++++ src/desktop.c | 179 ++++++++++++++++++++++++++++++++++---------------- src/pcmanfm.c | 3 +- 3 files changed, 137 insertions(+), 58 deletions(-) diff --git a/configure.ac b/configure.ac index 2ec70ed2..8afde669 100644 --- a/configure.ac +++ b/configure.ac @@ -80,6 +80,12 @@ AC_ARG_WITH(gtk, [ac_with_gtk="${withval}"], [ac_with_gtk=2]) +AC_ARG_ENABLE(wayland, + [AC_HELP_STRING([--enable-wayland], + [Enable Wayland support])], + [enable_wayland="${enableval}"], + [enable_wayland=no]) + # Checks for libraries. PKG_CHECK_MODULES(XLIB, "x11") @@ -95,9 +101,16 @@ fm_modules="$gio_modules glib-2.0 pango >= 1.20.0 libfm >= 1.0" case "$ac_with_gtk" in 3|3.*) fm_modules="$fm_modules gtk+-3.0 libfm-gtk3 >= 1.0.1" + if test "x$enable_wayland" = "xyes"; then + fm_modules="$fm_modules gtk-layer-shell-0 >= 0.5.2" + AC_DEFINE(HAVE_WAYLAND, 1, [Have Wayland support]) + fi ;; *) fm_modules="$fm_modules gtk+-2.0 libfm-gtk >= 1.0.1" + if test "x$enable_wayland" = "xyes"; then + AC_MSG_ERROR([Wayland only works with GTK3]) + fi ;; esac PKG_CHECK_MODULES(FM, [$fm_modules]) diff --git a/src/desktop.c b/src/desktop.c index 0686a595..06e106bd 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -33,6 +33,9 @@ #include #include #include +#ifdef HAVE_WAYLAND +#include +#endif #include #include @@ -55,6 +58,8 @@ /* the search dialog timeout (in ms) */ #define DESKTOP_SEARCH_DIALOG_TIMEOUT (5000) +#define IS_X11() (GDK_IS_X11_DISPLAY(gdk_display_get_default())) + struct _FmDesktopItem { FmFileInfo* fi; @@ -2086,8 +2091,9 @@ static void paint_rubber_banding_rect(FmDesktop* self, cairo_t* cr, GdkRectangle static void _free_cache_image(FmBackgroundCache *cache) { #if GTK_CHECK_VERSION(3, 0, 0) - XFreePixmap(cairo_xlib_surface_get_display(cache->bg), - cairo_xlib_surface_get_drawable(cache->bg)); + if(IS_X11()) + XFreePixmap(cairo_xlib_surface_get_display(cache->bg), + cairo_xlib_surface_get_drawable(cache->bg)); cairo_surface_destroy(cache->bg); #else g_object_unref(cache->bg); @@ -2298,13 +2304,18 @@ static void update_background(FmDesktop* desktop, int is_it) } } #if GTK_CHECK_VERSION(3, 0, 0) - xdisplay = GDK_WINDOW_XDISPLAY(root); - /* this code is taken from libgnome-desktop */ - xpixmap = XCreatePixmap(xdisplay, RootWindow(xdisplay, screen_num), - dest_w, dest_h, DefaultDepth(xdisplay, screen_num)); - cache->bg = cairo_xlib_surface_create(xdisplay, xpixmap, - GDK_VISUAL_XVISUAL(gdk_screen_get_system_visual(screen)), - dest_w, dest_h); + if(IS_X11()) + { + xdisplay = GDK_WINDOW_XDISPLAY(root); + /* this code is taken from libgnome-desktop */ + xpixmap = XCreatePixmap(xdisplay, RootWindow(xdisplay, screen_num), + dest_w, dest_h, DefaultDepth(xdisplay, screen_num)); + cache->bg = cairo_xlib_surface_create(xdisplay, xpixmap, + GDK_VISUAL_XVISUAL(gdk_screen_get_system_visual(screen)), + dest_w, dest_h); + } else { + cache->bg = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dest_w, dest_h); + } cr = cairo_create(cache->bg); #else cache->bg = gdk_pixmap_new(window, dest_w, dest_h, -1); @@ -2370,55 +2381,58 @@ static void update_background(FmDesktop* desktop, int is_it) gdk_window_set_back_pixmap(window, cache->bg, FALSE); #endif - /* set root map here */ - xdisplay = GDK_WINDOW_XDISPLAY(root); - xroot = RootWindow(xdisplay, screen_num); + if(IS_X11()) + { + /* set root map here */ + xdisplay = GDK_WINDOW_XDISPLAY(root); + xroot = RootWindow(xdisplay, screen_num); #if GTK_CHECK_VERSION(3, 0, 0) - xpixmap = cairo_xlib_surface_get_drawable(cache->bg); + xpixmap = cairo_xlib_surface_get_drawable(cache->bg); #else - xpixmap = GDK_WINDOW_XWINDOW(cache->bg); + xpixmap = GDK_WINDOW_XWINDOW(cache->bg); #endif - XChangeProperty(xdisplay, GDK_WINDOW_XID(root), - XA_XROOTMAP_ID, XA_PIXMAP, 32, PropModeReplace, (guchar*)&xpixmap, 1); + XChangeProperty(xdisplay, GDK_WINDOW_XID(root), + XA_XROOTMAP_ID, XA_PIXMAP, 32, PropModeReplace, (guchar*)&xpixmap, 1); - XGrabServer (xdisplay); + XGrabServer (xdisplay); #if 0 - result = XGetWindowProperty (display, - RootWindow (display, screen_num), - gdk_x11_get_xatom_by_name ("ESETROOT_PMAP_ID"), - 0L, 1L, False, XA_PIXMAP, - &type, &format, &nitems, - &bytes_after, - &data_esetroot); - - if (data_esetroot != NULL) { - if (result == Success && type == XA_PIXMAP && - format == 32 && - nitems == 1) { - gdk_error_trap_push (); - XKillClient (display, *(Pixmap *)data_esetroot); - gdk_error_trap_pop_ignored (); - } - XFree (data_esetroot); - } + result = XGetWindowProperty (display, + RootWindow (display, screen_num), + gdk_x11_get_xatom_by_name ("ESETROOT_PMAP_ID"), + 0L, 1L, False, XA_PIXMAP, + &type, &format, &nitems, + &bytes_after, + &data_esetroot); + + if (data_esetroot != NULL) { + if (result == Success && type == XA_PIXMAP && + format == 32 && + nitems == 1) { + gdk_error_trap_push (); + XKillClient (display, *(Pixmap *)data_esetroot); + gdk_error_trap_pop_ignored (); + } + XFree (data_esetroot); + } - XChangeProperty (display, RootWindow (display, screen_num), - gdk_x11_get_xatom_by_name ("ESETROOT_PMAP_ID"), - XA_PIXMAP, 32, PropModeReplace, - (guchar *) &xpixmap, 1); + XChangeProperty (display, RootWindow (display, screen_num), + gdk_x11_get_xatom_by_name ("ESETROOT_PMAP_ID"), + XA_PIXMAP, 32, PropModeReplace, + (guchar *) &xpixmap, 1); #endif - XChangeProperty(xdisplay, xroot, XA_XROOTPMAP_ID, XA_PIXMAP, 32, - PropModeReplace, (guchar*)&xpixmap, 1); + XChangeProperty(xdisplay, xroot, XA_XROOTPMAP_ID, XA_PIXMAP, 32, + PropModeReplace, (guchar*)&xpixmap, 1); - XSetWindowBackgroundPixmap(xdisplay, xroot, xpixmap); - XClearWindow(xdisplay, xroot); + XSetWindowBackgroundPixmap(xdisplay, xroot, xpixmap); + XClearWindow(xdisplay, xroot); - XFlush(xdisplay); - XUngrabServer(xdisplay); + XFlush(xdisplay); + XUngrabServer(xdisplay); + } if(pix) g_object_unref(pix); @@ -3469,7 +3483,8 @@ static gboolean on_button_press(GtkWidget* w, GdkEventButton* evt) else if(evt->button != 1 && evt->button == self->button_pressed) { self->forward_pending = TRUE; - forward_event_to_rootwin(gtk_widget_get_screen(w), (GdkEvent*)evt); + if(IS_X11()) + forward_event_to_rootwin(gtk_widget_get_screen(w), (GdkEvent*)evt); } if(! gtk_widget_has_focus(w)) @@ -3506,7 +3521,7 @@ static gboolean on_button_release(GtkWidget* w, GdkEventButton* evt) /* forward the event to root window */ if (self->button_pressed == evt->button) { - if (self->forward_pending) + if (self->forward_pending && IS_X11()) forward_event_to_rootwin(gtk_widget_get_screen(w), (GdkEvent*)evt); self->button_pressed = 0; self->forward_pending = FALSE; @@ -3922,10 +3937,18 @@ static void desktop_search_position(FmDesktop *desktop) #endif /* put it into right upper corner */ - gdk_screen_get_monitor_geometry(gtk_widget_get_screen((GtkWidget*)desktop), - desktop->monitor, &geom); - x = geom.x + desktop->working_area.x + desktop->working_area.width - requisition.width; - y = geom.y + desktop->working_area.y; + if(IS_X11()) + { + gdk_screen_get_monitor_geometry(gtk_widget_get_screen((GtkWidget*)desktop), + desktop->monitor, &geom); + x = geom.x + desktop->working_area.x + desktop->working_area.width - requisition.width; + y = geom.y + desktop->working_area.y; + } + else + { + x = desktop->working_area.x + desktop->working_area.width - requisition.width; + y = desktop->working_area.y; + } gtk_window_move(GTK_WINDOW(desktop->search_window), x, y); } @@ -3994,6 +4017,7 @@ static void desktop_search_ensure_window(FmDesktop *desktop) gtk_window_group_add_window(win_group, window); gtk_window_set_modal(window, TRUE); gtk_window_set_screen(window, gtk_widget_get_screen(GTK_WIDGET(desktop))); + gtk_window_set_transient_for(window, GTK_WINDOW(desktop)); /* connect signal handlers */ g_signal_connect(window, "delete-event", G_CALLBACK(desktop_search_delete_event), desktop); g_signal_connect(window, "scroll-event", G_CALLBACK(desktop_search_scroll_event), desktop); @@ -4044,6 +4068,11 @@ static gboolean desktop_search_start(FmDesktop *desktop, gboolean keybinding) /* display the search dialog */ gtk_widget_show(desktop->search_window); +#ifdef HAVE_WAYLAND + if(gtk_layer_is_layer_window(GTK_WINDOW(desktop))) + gtk_layer_set_keyboard_interactivity(GTK_WINDOW(desktop), TRUE); +#endif + /* connect "changed" signal for the entry */ if (G_UNLIKELY(desktop->search_entry_changed_id == 0)) desktop->search_entry_changed_id = g_signal_connect(G_OBJECT(desktop->search_entry), @@ -4831,7 +4860,8 @@ static void fm_desktop_destroy(GtkObject *object) if(self->icon_render) /* see bug #3533958 by korzhpavel@SF */ { screen = gtk_widget_get_screen((GtkWidget*)self); - gdk_window_remove_filter(gdk_screen_get_root_window(screen), on_root_event, self); + if(IS_X11()) + gdk_window_remove_filter(gdk_screen_get_root_window(screen), on_root_event, self); g_signal_handlers_disconnect_by_func(screen, on_screen_size_changed, self); #if FM_CHECK_VERSION(1, 2, 0) @@ -4918,6 +4948,20 @@ static void fm_desktop_init(FmDesktop *self) #endif } +#ifdef HAVE_WAYLAND +static gboolean on_enter(GtkWidget *widget, GdkEvent *event) +{ + gtk_layer_set_keyboard_interactivity(GTK_WINDOW(widget), TRUE); + return FALSE; +} + +static gboolean on_leave(GtkWidget *widget, GdkEvent *event) +{ + gtk_layer_set_keyboard_interactivity(GTK_WINDOW(widget), FALSE); + return FALSE; +} +#endif + /* we should have a constructor to handle parameters */ static GObject* fm_desktop_constructor(GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) @@ -4930,6 +4974,23 @@ static GObject* fm_desktop_constructor(GType type, guint n_construct_properties, gint n; GdkRectangle geom; +#ifdef HAVE_WAYLAND + if(gtk_layer_is_supported()) + { + gtk_widget_add_events(GTK_WIDGET(self), GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + g_signal_connect(GTK_WIDGET(self), "enter-notify-event", G_CALLBACK(on_enter), NULL); + g_signal_connect(GTK_WIDGET(self), "leave-notify-event", G_CALLBACK(on_leave), NULL); + + gtk_layer_init_for_window(GTK_WINDOW(self)); + gtk_layer_set_layer(GTK_WINDOW(self), GTK_LAYER_SHELL_LAYER_BOTTOM); + gtk_layer_set_monitor(GTK_WINDOW(self), gdk_display_get_monitor(gdk_screen_get_display(screen), self->monitor)); + gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_LEFT, TRUE); + gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_RIGHT, TRUE); + gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_TOP, TRUE); + gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_BOTTOM, TRUE); + } +#endif + for(i = 0; i < n_construct_properties; i++) if(!strcmp(construct_properties[i].pspec->name, "monitor") && G_VALUE_HOLDS_INT(construct_properties[i].value)) @@ -4971,12 +5032,15 @@ static GObject* fm_desktop_constructor(GType type, guint n_construct_properties, G_CALLBACK(on_show_full_names_changed), self); #endif - root = gdk_screen_get_root_window(screen); - gdk_window_set_events(root, gdk_window_get_events(root)|GDK_PROPERTY_CHANGE_MASK); - gdk_window_add_filter(root, on_root_event, self); + if(IS_X11()) + { + root = gdk_screen_get_root_window(screen); + gdk_window_set_events(root, gdk_window_get_events(root)|GDK_PROPERTY_CHANGE_MASK); + gdk_window_add_filter(root, on_root_event, self); + } g_signal_connect(screen, "monitors-changed", G_CALLBACK(on_screen_size_changed), self); - n = get_desktop_for_root_window(root); + n = IS_X11() ? get_desktop_for_root_window(root) : 0; if(n < 0) n = 0; self->cur_desktop = (guint)n; @@ -5076,7 +5140,8 @@ static void fm_desktop_class_init(FmDesktopClass *klass) #endif /* widget_class->drag_data_get = on_drag_data_get; */ - if(XInternAtoms(gdk_x11_get_default_xdisplay(), atom_names, + if(IS_X11() && + XInternAtoms(gdk_x11_get_default_xdisplay(), atom_names, G_N_ELEMENTS(atom_names), False, atoms)) { XA_NET_WORKAREA = atoms[0]; diff --git a/src/pcmanfm.c b/src/pcmanfm.c index 08a7fc30..4ae1a021 100644 --- a/src/pcmanfm.c +++ b/src/pcmanfm.c @@ -575,7 +575,8 @@ gboolean pcmanfm_open_folder(GAppLaunchContext* ctx, GList* folder_infos, gpoint FmFileInfo* fi = (FmFileInfo*)l->data; fm_main_win_open_in_last_active(fm_file_info_get_path(fi)); } - if(user_data && FM_IS_DESKTOP(user_data)) + if(user_data && FM_IS_DESKTOP(user_data) && + GDK_IS_X11_WINDOW(gtk_widget_get_window(GTK_WIDGET(user_data)))) move_window_to_desktop(fm_main_win_get_last_active(), user_data); return TRUE; } From 8d8ecb30f64f644ebe37bac827b018b51add12a2 Mon Sep 17 00:00:00 2001 From: wb9688 Date: Sat, 6 Feb 2021 16:43:07 +0100 Subject: [PATCH 2/4] Show error if unsupported display protocol is used --- src/pcmanfm.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/pcmanfm.c b/src/pcmanfm.c index 4ae1a021..7811f59b 100644 --- a/src/pcmanfm.c +++ b/src/pcmanfm.c @@ -37,6 +37,10 @@ #include #include /* for getcwd */ +#ifdef HAVE_WAYLAND +#include +#endif + #include #include "app-config.h" #include "main-win.h" @@ -349,6 +353,19 @@ gboolean pcmanfm_run(gint screen_num) { if(!desktop_running) { + GdkDisplay *default_display = gdk_display_get_default(); +#if HAVE_WAYLAND + if(!GDK_IS_X11_DISPLAY(default_display) && !gtk_layer_is_supported()) + { + fm_show_error(NULL, NULL, _("Only X11 and Wayland (with wlr-layer-shell) are supported")); +#else + if(!GDK_IS_X11_DISPLAY(default_display)) + { + fm_show_error(NULL, NULL, _("Only X11 is supported")); +#endif + reset_options(); + return FALSE; + } fm_desktop_manager_init(one_screen ? screen_num : -1); desktop_running = TRUE; } From ab74ac2ff9c34a8375aac67d3eaf7987c96af6bb Mon Sep 17 00:00:00 2001 From: wb9688 Date: Sun, 7 Feb 2021 14:45:51 +0100 Subject: [PATCH 3/4] Make X11 support optional --- configure.ac | 31 +++++++++++++++---------- src/Makefile.am | 2 -- src/desktop.c | 61 ++++++++++++++++++++++++++++++++++++++++++++----- src/pcmanfm.c | 23 +++++++++++++++---- 4 files changed, 93 insertions(+), 24 deletions(-) diff --git a/configure.ac b/configure.ac index 8afde669..1d1361cc 100644 --- a/configure.ac +++ b/configure.ac @@ -44,7 +44,7 @@ AC_ARG_ENABLE(debug, [enable_debug="${enableval}"], [enable_debug=no]) -if test "$enable_debug" = "yes"; then +if test x"$enable_debug" = "xyes"; then # turn on debug and disable optimization CPPFLAGS="$CPPFLAGS -DG_ENABLE_DEBUG -O0 -g" case "$CC" in @@ -86,33 +86,40 @@ AC_ARG_ENABLE(wayland, [enable_wayland="${enableval}"], [enable_wayland=no]) -# Checks for libraries. +AC_ARG_ENABLE(x11, + [AC_HELP_STRING([--enable-x11], + [Enable X11 support])], + [enable_x11="${enableval}"], + [enable_x11=yes]) -PKG_CHECK_MODULES(XLIB, "x11") -AC_SUBST(XLIB_CFLAGS) -AC_SUBST(XLIB_LIBS) +if test x"$enable_wayland" = "xno" -a x"&$enable_x11" = "xno"; then + AC_MSG_ERROR([At least one of X11 and Wayland needs to be enabled]) +fi -gio_modules="gthread-2.0 gio-unix-2.0 >= 2.18.0" -PKG_CHECK_MODULES(GIO, [$gio_modules]) -AC_SUBST(GIO_CFLAGS) -AC_SUBST(GIO_LIBS) +# Checks for libraries. +fm_modules="gthread-2.0 gio-unix-2.0 >= 2.18.0 glib-2.0 pango >= 1.20.0 libfm >= 1.0" -fm_modules="$gio_modules glib-2.0 pango >= 1.20.0 libfm >= 1.0" case "$ac_with_gtk" in 3|3.*) fm_modules="$fm_modules gtk+-3.0 libfm-gtk3 >= 1.0.1" - if test "x$enable_wayland" = "xyes"; then + if test x"$enable_wayland" = "xyes"; then fm_modules="$fm_modules gtk-layer-shell-0 >= 0.5.2" AC_DEFINE(HAVE_WAYLAND, 1, [Have Wayland support]) fi ;; *) fm_modules="$fm_modules gtk+-2.0 libfm-gtk >= 1.0.1" - if test "x$enable_wayland" = "xyes"; then + if test x"$enable_wayland" = "xyes"; then AC_MSG_ERROR([Wayland only works with GTK3]) fi ;; esac + +if test x"$enable_x11" = "xyes"; then + fm_modules="$fm_modules x11" + AC_DEFINE(HAVE_X11, 1, [Have X11 support]) +fi + PKG_CHECK_MODULES(FM, [$fm_modules]) AC_SUBST(FM_CFLAGS) AC_SUBST(FM_LIBS) diff --git a/src/Makefile.am b/src/Makefile.am index 68e2eb96..f5264b23 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -38,7 +38,6 @@ EXTRA_DIST= \ include_HEADERS = pcmanfm-modules.h pcmanfm_CFLAGS = \ - $(XLIB_CFLAGS) \ $(FM_CFLAGS) \ $(G_CAST_CHECKS) \ -Wall \ @@ -46,7 +45,6 @@ pcmanfm_CFLAGS = \ $(NULL) pcmanfm_LDADD = \ - $(XLIB_LIBS) \ $(FM_LIBS) \ $(NULL) diff --git a/src/desktop.c b/src/desktop.c index 06e106bd..6b4e9f6d 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -29,16 +29,26 @@ #include +#ifdef HAVE_X11 #include +#else +#include +#endif #include +#ifdef HAVE_X11 #include #include +#endif #ifdef HAVE_WAYLAND #include #endif #include +#ifdef HAVE_X11 #include +#else +#include +#endif #include "pref.h" #include "main-win.h" @@ -58,7 +68,15 @@ /* the search dialog timeout (in ms) */ #define DESKTOP_SEARCH_DIALOG_TIMEOUT (5000) +#ifdef HAVE_X11 +#ifdef HAVE_WAYLAND #define IS_X11() (GDK_IS_X11_DISPLAY(gdk_display_get_default())) +#else +#define IS_X11() (TRUE) +#endif +#else +#define IS_X11() (FALSE) +#endif struct _FmDesktopItem { @@ -108,11 +126,13 @@ static int n_screens = 0; static guint icon_theme_changed = 0; static GtkAccelGroup* acc_grp = NULL; +#ifdef HAVE_X11 static Atom XA_NET_WORKAREA = 0; static Atom XA_NET_NUMBER_OF_DESKTOPS = 0; static Atom XA_NET_CURRENT_DESKTOP = 0; static Atom XA_XROOTMAP_ID = 0; static Atom XA_XROOTPMAP_ID = 0; +#endif static GdkCursor* hand_cursor = NULL; @@ -371,6 +391,7 @@ static inline void reload_items(FmDesktop *desktop) load_items(desktop); } +#ifdef HAVE_X11 static gint get_desktop_for_root_window(GdkWindow *root) { gint desktop = -1; @@ -389,6 +410,7 @@ static gint get_desktop_for_root_window(GdkWindow *root) } return desktop; } +#endif /* save position of desktop icons */ static void save_item_pos(FmDesktop* desktop) @@ -2091,9 +2113,11 @@ static void paint_rubber_banding_rect(FmDesktop* self, cairo_t* cr, GdkRectangle static void _free_cache_image(FmBackgroundCache *cache) { #if GTK_CHECK_VERSION(3, 0, 0) +#ifdef HAVE_X11 if(IS_X11()) XFreePixmap(cairo_xlib_surface_get_display(cache->bg), cairo_xlib_surface_get_drawable(cache->bg)); +#endif cairo_surface_destroy(cache->bg); #else g_object_unref(cache->bg); @@ -2128,9 +2152,11 @@ static void update_background(FmDesktop* desktop, int is_it) cairo_pattern_t *pattern; #endif +#ifdef HAVE_X11 Display* xdisplay; Pixmap xpixmap; Window xroot; +#endif int screen_num = gdk_screen_get_number(screen); char *wallpaper; @@ -2306,6 +2332,7 @@ static void update_background(FmDesktop* desktop, int is_it) #if GTK_CHECK_VERSION(3, 0, 0) if(IS_X11()) { +#ifdef HAVE_X11 xdisplay = GDK_WINDOW_XDISPLAY(root); /* this code is taken from libgnome-desktop */ xpixmap = XCreatePixmap(xdisplay, RootWindow(xdisplay, screen_num), @@ -2313,9 +2340,10 @@ static void update_background(FmDesktop* desktop, int is_it) cache->bg = cairo_xlib_surface_create(xdisplay, xpixmap, GDK_VISUAL_XVISUAL(gdk_screen_get_system_visual(screen)), dest_w, dest_h); - } else { - cache->bg = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dest_w, dest_h); +#endif } + else + cache->bg = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dest_w, dest_h); cr = cairo_create(cache->bg); #else cache->bg = gdk_pixmap_new(window, dest_w, dest_h, -1); @@ -2381,6 +2409,7 @@ static void update_background(FmDesktop* desktop, int is_it) gdk_window_set_back_pixmap(window, cache->bg, FALSE); #endif +#ifdef HAVE_X11 if(IS_X11()) { /* set root map here */ @@ -2433,6 +2462,7 @@ static void update_background(FmDesktop* desktop, int is_it) XFlush(xdisplay); XUngrabServer(xdisplay); } +#endif if(pix) g_object_unref(pix); @@ -2610,6 +2640,7 @@ static void update_working_area(FmDesktop* desktop) return; } +#ifdef HAVE_X11 static GdkFilterReturn on_root_event(GdkXEvent *xevent, GdkEvent *event, gpointer data) { XPropertyEvent * evt = (XPropertyEvent*) xevent; @@ -2632,6 +2663,7 @@ static GdkFilterReturn on_root_event(GdkXEvent *xevent, GdkEvent *event, gpointe } return GDK_FILTER_CONTINUE; } +#endif static void on_screen_size_changed(GdkScreen* screen, FmDesktop* desktop) { @@ -3111,6 +3143,7 @@ static void _focus_and_select_focused_item(FmDesktop *desktop, FmDesktopItem *it set_focused_item(desktop, item); } +#ifdef HAVE_X11 /* This function is taken from xfdesktop */ static void forward_event_to_rootwin(GdkScreen *gscreen, GdkEvent *event) { @@ -3182,6 +3215,7 @@ static void forward_event_to_rootwin(GdkScreen *gscreen, GdkEvent *event) XSendEvent(dpy, xev2.window, False, ButtonPressMask | ButtonReleaseMask, (XEvent *) & xev2); } +#endif #if GTK_CHECK_VERSION(3, 0, 0) @@ -3483,8 +3517,10 @@ static gboolean on_button_press(GtkWidget* w, GdkEventButton* evt) else if(evt->button != 1 && evt->button == self->button_pressed) { self->forward_pending = TRUE; +#ifdef HAVE_X11 if(IS_X11()) forward_event_to_rootwin(gtk_widget_get_screen(w), (GdkEvent*)evt); +#endif } if(! gtk_widget_has_focus(w)) @@ -3521,8 +3557,10 @@ static gboolean on_button_release(GtkWidget* w, GdkEventButton* evt) /* forward the event to root window */ if (self->button_pressed == evt->button) { +#ifdef HAVE_X11 if (self->forward_pending && IS_X11()) forward_event_to_rootwin(gtk_widget_get_screen(w), (GdkEvent*)evt); +#endif self->button_pressed = 0; self->forward_pending = FALSE; } @@ -4860,8 +4898,10 @@ static void fm_desktop_destroy(GtkObject *object) if(self->icon_render) /* see bug #3533958 by korzhpavel@SF */ { screen = gtk_widget_get_screen((GtkWidget*)self); +#ifdef HAVE_X11 if(IS_X11()) gdk_window_remove_filter(gdk_screen_get_root_window(screen), on_root_event, self); +#endif g_signal_handlers_disconnect_by_func(screen, on_screen_size_changed, self); #if FM_CHECK_VERSION(1, 2, 0) @@ -5034,17 +5074,22 @@ static GObject* fm_desktop_constructor(GType type, guint n_construct_properties, if(IS_X11()) { +#ifdef HAVE_X11 root = gdk_screen_get_root_window(screen); gdk_window_set_events(root, gdk_window_get_events(root)|GDK_PROPERTY_CHANGE_MASK); gdk_window_add_filter(root, on_root_event, self); - } - g_signal_connect(screen, "monitors-changed", G_CALLBACK(on_screen_size_changed), self); - n = IS_X11() ? get_desktop_for_root_window(root) : 0; - if(n < 0) + n = get_desktop_for_root_window(root); + if(n < 0) + n = 0; +#endif + } + else n = 0; self->cur_desktop = (guint)n; + g_signal_connect(screen, "monitors-changed", G_CALLBACK(on_screen_size_changed), self); + /* init dnd support */ self->dnd_src = fm_dnd_src_new((GtkWidget*)self); #if !FM_CHECK_VERSION(1, 2, 1) @@ -5099,9 +5144,11 @@ static void fm_desktop_class_init(FmDesktopClass *klass) { GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass); typedef gboolean (*DeleteEvtHandler) (GtkWidget*, GdkEventAny*); +#ifdef HAVE_X11 char* atom_names[] = {"_NET_WORKAREA", "_NET_NUMBER_OF_DESKTOPS", "_NET_CURRENT_DESKTOP", "_XROOTMAP_ID", "_XROOTPMAP_ID"}; Atom atoms[G_N_ELEMENTS(atom_names)] = {0}; +#endif GObjectClass* object_class = G_OBJECT_CLASS(klass); #if GTK_CHECK_VERSION(3, 0, 0) @@ -5140,6 +5187,7 @@ static void fm_desktop_class_init(FmDesktopClass *klass) #endif /* widget_class->drag_data_get = on_drag_data_get; */ +#ifdef HAVE_X11 if(IS_X11() && XInternAtoms(gdk_x11_get_default_xdisplay(), atom_names, G_N_ELEMENTS(atom_names), False, atoms)) @@ -5150,6 +5198,7 @@ static void fm_desktop_class_init(FmDesktopClass *klass) XA_XROOTMAP_ID = atoms[3]; XA_XROOTPMAP_ID = atoms[4]; } +#endif object_class->constructor = fm_desktop_constructor; object_class->set_property = fm_desktop_set_property; diff --git a/src/pcmanfm.c b/src/pcmanfm.c index 7811f59b..4556f751 100644 --- a/src/pcmanfm.c +++ b/src/pcmanfm.c @@ -26,7 +26,11 @@ #endif #include +#ifdef HAVE_X11 #include +#else +#include +#endif #include #include @@ -227,7 +231,9 @@ int main(int argc, char** argv) inst.prog_name = "pcmanfm"; inst.cb = single_inst_cb; inst.opt_entries = opt_entries + 3; +#ifdef HAVE_X11 inst.screen_num = gdk_x11_get_default_screen(); +#endif switch(single_inst_init(&inst)) { case SINGLE_INST_CLIENT: /* we're not the first instance. */ @@ -353,13 +359,18 @@ gboolean pcmanfm_run(gint screen_num) { if(!desktop_running) { - GdkDisplay *default_display = gdk_display_get_default(); -#if HAVE_WAYLAND - if(!GDK_IS_X11_DISPLAY(default_display) && !gtk_layer_is_supported()) +#ifdef HAVE_WAYLAND +#ifdef HAVE_X11 + if(!GDK_IS_X11_DISPLAY(gdk_display_get_default()) && !gtk_layer_is_supported()) { fm_show_error(NULL, NULL, _("Only X11 and Wayland (with wlr-layer-shell) are supported")); #else - if(!GDK_IS_X11_DISPLAY(default_display)) + if(!gtk_layer_is_supported()) + { + fm_show_error(NULL, NULL, _("Only Wayland (with wlr-layer-shell) is supported")); +#endif +#else + if(!GDK_IS_X11_DISPLAY(gdk_display_get_default())) { fm_show_error(NULL, NULL, _("Only X11 is supported")); #endif @@ -542,6 +553,7 @@ void pcmanfm_unref() gtk_main_quit(); } +#ifdef HAVE_X11 static void move_window_to_desktop(FmMainWin* win, FmDesktop* desktop) { GdkScreen* screen = gtk_widget_get_screen(GTK_WIDGET(desktop)); @@ -569,6 +581,7 @@ static void move_window_to_desktop(FmMainWin* win, FmDesktop* desktop) (SubstructureNotifyMask | SubstructureRedirectMask), (XEvent *) &xev); } +#endif gboolean pcmanfm_open_folder(GAppLaunchContext* ctx, GList* folder_infos, gpointer user_data, GError** err) { @@ -592,9 +605,11 @@ gboolean pcmanfm_open_folder(GAppLaunchContext* ctx, GList* folder_infos, gpoint FmFileInfo* fi = (FmFileInfo*)l->data; fm_main_win_open_in_last_active(fm_file_info_get_path(fi)); } +#ifdef HAVE_X11 if(user_data && FM_IS_DESKTOP(user_data) && GDK_IS_X11_WINDOW(gtk_widget_get_window(GTK_WIDGET(user_data)))) move_window_to_desktop(fm_main_win_get_last_active(), user_data); +#endif return TRUE; } From f54ceb781e84913c2db2ac8a9bab1ab656a48cf6 Mon Sep 17 00:00:00 2001 From: wb9688 Date: Thu, 11 Feb 2021 20:29:45 +0100 Subject: [PATCH 4/4] Show wallpaper in a separate window on Wayland --- src/desktop.c | 65 ++++++++++++++++++++++++++++++++++++++++++--------- src/desktop.h | 3 +++ 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/desktop.c b/src/desktop.c index 6b4e9f6d..bc58ebd1 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -2141,7 +2141,13 @@ static void _clear_bg_cache(FmDesktop *self) static void update_background(FmDesktop* desktop, int is_it) { - GtkWidget* widget = (GtkWidget*)desktop; + GtkWidget* widget; + if(IS_X11()) + widget = (GtkWidget*)desktop; +#ifdef HAVE_WAYLAND + else + widget = (GtkWidget*)desktop->wallpaper_window; +#endif GdkPixbuf* pix, *scaled; cairo_t* cr; GdkScreen *screen = gtk_widget_get_screen(widget); @@ -2566,11 +2572,20 @@ static void update_working_area(FmDesktop* desktop) GdkScreen* screen = gtk_widget_get_screen((GtkWidget*)desktop); GdkRectangle geom; #if GTK_CHECK_VERSION(3, 4, 0) - gdk_screen_get_monitor_workarea(screen, desktop->monitor, &desktop->working_area); - /* we need working area coordinates within the monitor not the screen */ - gdk_screen_get_monitor_geometry(screen, desktop->monitor, &geom); - desktop->working_area.x -= geom.x; - desktop->working_area.y -= geom.y; + if(IS_X11()) + { + gdk_screen_get_monitor_workarea(screen, desktop->monitor, &desktop->working_area); + /* we need working area coordinates within the monitor not the screen */ + gdk_screen_get_monitor_geometry(screen, desktop->monitor, &geom); + desktop->working_area.x -= geom.x; + desktop->working_area.y -= geom.y; + } + else + { + desktop->working_area.x = 0; + desktop->working_area.y = 0; + gtk_window_get_size((GtkWindow*)desktop, &desktop->working_area.width, &desktop->working_area.height); + } #else GdkWindow* root = gdk_screen_get_root_window(screen); Atom ret_type; @@ -2677,11 +2692,16 @@ static void on_screen_size_changed(GdkScreen* screen, FmDesktop* desktop) break; if (i < n_screens) desktops[i] = fm_desktop_new(screen, desktop->monitor ? -2 : -1); +#ifdef HAVE_WAYLAND + if (!IS_X11()) + gtk_widget_destroy(GTK_WIDGET(desktop->wallpaper_window)); +#endif gtk_widget_destroy(GTK_WIDGET(desktop)); return; } gdk_screen_get_monitor_geometry(screen, desktop->monitor, &geom); - gtk_window_resize((GtkWindow*)desktop, geom.width, geom.height); + if(IS_X11()) + gtk_window_resize((GtkWindow*)desktop, geom.width, geom.height); /* bug #3614780: if monitor was moved desktop should be moved too */ gtk_window_move((GtkWindow*)desktop, geom.x, geom.y); /* FIXME: check if new monitor was added! */ @@ -4354,7 +4374,8 @@ static void on_realize(GtkWidget* w) GTK_WIDGET_CLASS(fm_desktop_parent_class)->realize(w); gtk_window_set_skip_pager_hint(GTK_WINDOW(w), TRUE); gtk_window_set_skip_taskbar_hint(GTK_WINDOW(w), TRUE); - gtk_window_set_resizable((GtkWindow*)w, FALSE); + if(IS_X11()) + gtk_window_set_resizable((GtkWindow*)w, FALSE); load_config(self); /* setup self->conf now if it wasn't loaded above */ @@ -5028,6 +5049,20 @@ static GObject* fm_desktop_constructor(GType type, guint n_construct_properties, gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_RIGHT, TRUE); gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_TOP, TRUE); gtk_layer_set_anchor(GTK_WINDOW(self), GTK_LAYER_SHELL_EDGE_BOTTOM, TRUE); + gtk_layer_set_exclusive_zone(GTK_WINDOW(self), 0); + + self->wallpaper_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_widget_set_app_paintable((GtkWidget*)self->wallpaper_window, TRUE); + gtk_layer_init_for_window(self->wallpaper_window); + gtk_layer_set_layer(self->wallpaper_window, GTK_LAYER_SHELL_LAYER_BACKGROUND); + gtk_layer_set_monitor(self->wallpaper_window, gdk_display_get_monitor(gdk_screen_get_display(screen), self->monitor)); + gtk_layer_set_anchor(self->wallpaper_window, GTK_LAYER_SHELL_EDGE_LEFT, TRUE); + gtk_layer_set_anchor(self->wallpaper_window, GTK_LAYER_SHELL_EDGE_RIGHT, TRUE); + gtk_layer_set_anchor(self->wallpaper_window, GTK_LAYER_SHELL_EDGE_TOP, TRUE); + gtk_layer_set_anchor(self->wallpaper_window, GTK_LAYER_SHELL_EDGE_BOTTOM, TRUE); + gtk_layer_set_exclusive_zone(self->wallpaper_window, -1); + gtk_widget_realize((GtkWidget*)self->wallpaper_window); + gtk_widget_show((GtkWidget*)self->wallpaper_window); } #endif @@ -5039,7 +5074,8 @@ static GObject* fm_desktop_constructor(GType type, guint n_construct_properties, return object; /* this monitor is disabled */ g_debug("fm_desktop_constructor for monitor %d", self->monitor); gdk_screen_get_monitor_geometry(screen, self->monitor, &geom); - gtk_window_set_default_size((GtkWindow*)self, geom.width, geom.height); + if(IS_X11()) + gtk_window_set_default_size((GtkWindow*)self, geom.width, geom.height); gtk_window_move(GTK_WINDOW(self), geom.x, geom.y); gtk_widget_set_app_paintable((GtkWidget*)self, TRUE); gtk_window_set_type_hint(GTK_WINDOW(self), GDK_WINDOW_TYPE_HINT_DESKTOP); @@ -5154,8 +5190,11 @@ static void fm_desktop_class_init(FmDesktopClass *klass) #if GTK_CHECK_VERSION(3, 0, 0) widget_class->destroy = fm_desktop_destroy; widget_class->draw = on_draw; - widget_class->get_preferred_width = on_get_preferred_width; - widget_class->get_preferred_height = on_get_preferred_height; + if(IS_X11()) + { + widget_class->get_preferred_width = on_get_preferred_width; + widget_class->get_preferred_height = on_get_preferred_height; + } #else GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS(klass); gtk_object_class->destroy = fm_desktop_destroy; @@ -6040,6 +6079,10 @@ void fm_desktop_manager_finalize() } for(i = 0; i < n_screens; i++) { +#ifdef HAVE_WAYLAND + if (!IS_X11()) + gtk_widget_destroy(GTK_WIDGET(desktops[i]->wallpaper_window)); +#endif gtk_widget_destroy(GTK_WIDGET(desktops[i])); } g_free(desktops); diff --git a/src/desktop.h b/src/desktop.h index 1205d11d..2dbaebf0 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -96,6 +96,9 @@ struct _FmDesktop guint search_timeout_id; /* desktop settings for this monitor */ FmDesktopConfig conf; +#ifdef HAVE_WAYLAND + GtkWindow *wallpaper_window; +#endif }; struct _FmDesktopClass