[gnome-flashback] desktop-background: redo background window
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] desktop-background: redo background window
- Date: Fri, 18 Sep 2015 16:44:27 +0000 (UTC)
commit bd5283e37b66b7a44cd4e29224fbf125ee73ecbc
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Fri Sep 18 19:40:16 2015 +0300
desktop-background: redo background window
Now background should be always under desktop window. Tested with
metacity and compiz.
https://bugzilla.gnome.org/show_bug.cgi?id=754963
.../libdesktop-background/gf-background-window.c | 358 ++++++++++++++++++--
.../libdesktop-background/gf-desktop-background.c | 162 ---------
2 files changed, 325 insertions(+), 195 deletions(-)
---
diff --git a/gnome-flashback/libdesktop-background/gf-background-window.c
b/gnome-flashback/libdesktop-background/gf-background-window.c
index 4cab3e1..9ce8ee1 100644
--- a/gnome-flashback/libdesktop-background/gf-background-window.c
+++ b/gnome-flashback/libdesktop-background/gf-background-window.c
@@ -16,91 +16,383 @@
*/
#include "config.h"
+
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+
#include "gf-background-window.h"
struct _GfBackgroundWindow
{
- GtkWindow parent;
+ GtkWindow parent;
+
+ Atom desktop_manager_atom;
+ Atom client_list_atom;
+ Atom type_atom;
+ Atom type_desktop_atom;
+
+ Window xbackground;
+ GdkWindow *background;
+
+ Window xdesktop;
+ GdkWindow *desktop;
};
G_DEFINE_TYPE (GfBackgroundWindow, gf_background_window, GTK_TYPE_WINDOW)
+static GdkWindow *
+create_window_from_xwindow (Window xwindow)
+{
+ GdkDisplay *display;
+ GdkWindow *window;
+ GdkEventMask mask;
+
+ display = gdk_display_get_default ();
+
+ gdk_error_trap_push ();
+ window = gdk_x11_window_foreign_new_for_display (display, xwindow);
+
+ if (gdk_error_trap_pop () != 0)
+ return NULL;
+
+ mask = gdk_window_get_events (window);
+ gdk_window_set_events (window, mask | GDK_STRUCTURE_MASK);
+
+ return window;
+}
+
+static gboolean
+is_desktop_window (GfBackgroundWindow *window,
+ Display *display,
+ Window xwindow)
+{
+ Atom type;
+ Atom *atoms;
+ int result;
+ int format;
+ unsigned long items;
+ unsigned long left;
+
+ if (window->type_atom == None)
+ window->type_atom = XInternAtom (display, "_NET_WM_WINDOW_TYPE", False);
+
+ if (window->type_desktop_atom == None)
+ window->type_desktop_atom = XInternAtom (display,
+ "_NET_WM_WINDOW_TYPE_DESKTOP",
+ False);
+
+ gdk_error_trap_push ();
+ result = XGetWindowProperty (display, xwindow, window->type_atom,
+ 0L, 1L, False, XA_ATOM, &type, &format,
+ &items, &left, (unsigned char **) &atoms);
+
+ if (gdk_error_trap_pop () != 0 || result != Success)
+ return FALSE;
+
+ if (items && atoms[0] == window->type_desktop_atom)
+ {
+ XFree (atoms);
+ return TRUE;
+ }
+
+ XFree (atoms);
+ return FALSE;
+}
+
+static gboolean
+get_desktop (GfBackgroundWindow *window)
+{
+ GdkDisplay *display;
+ Display *xdisplay;
+ Window root;
+ Atom type;
+ int result;
+ int format;
+ unsigned long items;
+ unsigned long left;
+ unsigned long i;
+ Window *windows;
+ Window desktop;
+
+ display = gdk_display_get_default ();
+ xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+ if (window->client_list_atom == None)
+ window->client_list_atom = XInternAtom (xdisplay, "_NET_CLIENT_LIST",
+ False);
+
+ gdk_error_trap_push ();
+
+ root = XDefaultRootWindow (xdisplay);
+ result = XGetWindowProperty (xdisplay, root, window->client_list_atom,
+ 0L, 1024L, False, XA_WINDOW, &type, &format,
+ &items, &left, (unsigned char **) &windows);
+
+ if (gdk_error_trap_pop () != 0 || result != Success)
+ return FALSE;
+
+ desktop = None;
+ for (i = 0; i < items; i++)
+ {
+ if (windows[i] == window->xbackground)
+ continue;
+
+ if (is_desktop_window (window, xdisplay, windows[i]))
+ {
+ desktop = windows[i];
+ break;
+ }
+ }
+
+ XFree (windows);
+
+ if (desktop == None)
+ return FALSE;
+
+ window->xdesktop = desktop;
+ window->desktop = create_window_from_xwindow (desktop);
+
+ return TRUE;
+}
+
+static Window
+get_desktop_manager (GfBackgroundWindow *window)
+{
+ GdkDisplay *display;
+ Display *xdisplay;
+
+ display = gdk_display_get_default ();
+ xdisplay = gdk_x11_display_get_xdisplay (display);
+
+ if (window->desktop_manager_atom == None)
+ {
+ GdkScreen *screen;
+ gint screen_number;
+ gchar *name;
+
+ screen = gdk_display_get_default_screen (display);
+ screen_number = gdk_screen_get_number (screen);
+
+ name = g_strdup_printf ("_NET_DESKTOP_MANAGER_S%d", screen_number);
+ window->desktop_manager_atom = XInternAtom (xdisplay, name, False);
+ g_free (name);
+ }
+
+ return XGetSelectionOwner (xdisplay, window->desktop_manager_atom);
+}
+
+static void
+handle_xevent (GfBackgroundWindow *window,
+ XEvent *event)
+{
+ static gboolean is_desktop_above_background;
+
+ if (event->type == DestroyNotify && window->xdesktop != None)
+ {
+ if (window->xdesktop == event->xdestroywindow.window)
+ {
+ is_desktop_above_background = FALSE;
+
+ window->xdesktop = None;
+ g_clear_object (&window->desktop);
+
+ return;
+ }
+ }
+
+ if (get_desktop_manager (window) == None)
+ return;
+
+ if (window->xdesktop == None && get_desktop (window) == FALSE)
+ return;
+
+ if (event->type == ConfigureNotify)
+ {
+ if (event->xconfigure.window == window->xdesktop)
+ is_desktop_above_background = FALSE;
+ else if (event->xconfigure.window == window->xbackground)
+ is_desktop_above_background = FALSE;
+ }
+
+ if (is_desktop_above_background == FALSE)
+ {
+ if (window->desktop == NULL)
+ return;
+
+ gdk_window_restack (window->desktop, window->background, TRUE);
+ gdk_window_lower (window->background);
+
+ is_desktop_above_background = TRUE;
+ }
+}
+
+static GdkFilterReturn
+event_filter_func (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ GfBackgroundWindow *window;
+ XEvent *e;
+
+ window = GF_BACKGROUND_WINDOW (data);
+ e = (GdkXEvent *) xevent;
+
+ switch (e->type)
+ {
+ case CirculateNotify:
+ case ConfigureNotify:
+ case CreateNotify:
+ case DestroyNotify:
+ case GravityNotify:
+ case MapNotify:
+ case MappingNotify:
+ case ReparentNotify:
+ case UnmapNotify:
+ case VisibilityNotify:
+ handle_xevent (window, e);
+ break;
+
+ default:
+ break;
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
static void
-screen_changed (GdkScreen *screen,
- gpointer user_data)
+gf_background_window_screen_changed (GdkScreen *screen,
+ gpointer user_data)
{
GfBackgroundWindow *window;
+ GtkWidget *widget;
gint width;
gint height;
window = GF_BACKGROUND_WINDOW (user_data);
+ widget = GTK_WIDGET (window);
+
width = gdk_screen_get_width (screen);
height = gdk_screen_get_height (screen);
- g_object_set (window,
- "width-request", width,
- "height-request", height,
- NULL);
+ gtk_widget_set_size_request (widget, width, height);
+}
+
+static void
+gf_background_window_dispose (GObject *object)
+{
+ GfBackgroundWindow *window;
+
+ window = GF_BACKGROUND_WINDOW (object);
+
+ g_clear_object (&window->desktop);
+
+ G_OBJECT_CLASS (gf_background_window_parent_class)->dispose (object);
+}
+
+static void
+gf_background_window_finalize (GObject *object)
+{
+ GfBackgroundWindow *window;
+ GdkScreen *screen;
+ GdkWindow *root;
+
+ window = GF_BACKGROUND_WINDOW (object);
+
+ screen = gdk_screen_get_default ();
+ root = gdk_screen_get_root_window (screen);
+
+ gdk_window_remove_filter (root, event_filter_func, window);
+
+ G_OBJECT_CLASS (gf_background_window_parent_class)->finalize (object);
}
static void
gf_background_window_map (GtkWidget *widget)
{
- GdkWindow *window;
+ GfBackgroundWindow *window;
+
+ window = GF_BACKGROUND_WINDOW (widget);
GTK_WIDGET_CLASS (gf_background_window_parent_class)->map (widget);
- window = gtk_widget_get_window (widget);
+ gdk_window_lower (window->background);
+}
+
+static void
+gf_background_window_realize (GtkWidget *widget)
+{
+ GfBackgroundWindow *window;
+ GdkWindow *gdk_window;
+
+ window = GF_BACKGROUND_WINDOW (widget);
+
+ GTK_WIDGET_CLASS (gf_background_window_parent_class)->realize (widget);
+
+ gdk_window = gtk_widget_get_window (widget);
- gdk_window_lower (window);
+ window->xbackground = gdk_x11_window_get_xid (gdk_window);
+ window->background = gdk_window;
}
static void
gf_background_window_class_init (GfBackgroundWindowClass *window_class)
{
+ GObjectClass *object_class;
GtkWidgetClass *widget_class;
+ object_class= G_OBJECT_CLASS (window_class);
widget_class = GTK_WIDGET_CLASS (window_class);
+ object_class->dispose = gf_background_window_dispose;
+ object_class->finalize = gf_background_window_finalize;
+
widget_class->map = gf_background_window_map;
+ widget_class->realize = gf_background_window_realize;
}
static void
gf_background_window_init (GfBackgroundWindow *window)
{
GdkScreen *screen;
+ GtkWindow *gtk_window;
+ GtkWidget *gtk_widget;
+ GdkWindow *root;
+ GdkEventMask mask;
screen = gdk_screen_get_default ();
+ gtk_window = GTK_WINDOW (window);
+ gtk_widget = GTK_WIDGET (window);
g_signal_connect_object (screen, "monitors-changed",
- G_CALLBACK (screen_changed), window,
- G_CONNECT_AFTER);
-
+ G_CALLBACK (gf_background_window_screen_changed),
+ window, G_CONNECT_AFTER);
g_signal_connect_object (screen, "size-changed",
- G_CALLBACK (screen_changed), window,
- G_CONNECT_AFTER);
+ G_CALLBACK (gf_background_window_screen_changed),
+ window, G_CONNECT_AFTER);
+
+ gf_background_window_screen_changed (screen, window);
+ gtk_window_set_keep_below (gtk_window, TRUE);
+ gtk_widget_add_events (gtk_widget, GDK_STRUCTURE_MASK);
+ gtk_widget_realize (gtk_widget);
- screen_changed (screen, window);
+ root = gdk_screen_get_root_window (screen);
+ mask = gdk_window_get_events (root);
+
+ gdk_window_set_events (root, mask | GDK_SUBSTRUCTURE_MASK);
+ gdk_window_add_filter (root, event_filter_func, window);
}
GtkWidget *
gf_background_window_new (void)
{
- GtkWidget *window;
-
- window = g_object_new (GF_TYPE_BACKGROUND_WINDOW,
- "accept-focus", FALSE,
- "app-paintable", TRUE,
- "decorated", FALSE,
- "resizable", FALSE,
- "skip-pager-hint", TRUE,
- "skip-taskbar-hint", TRUE,
- "type", GTK_WINDOW_TOPLEVEL,
- "type-hint", GDK_WINDOW_TYPE_HINT_DESKTOP,
- NULL);
-
- gtk_window_set_keep_below (GTK_WINDOW (window), TRUE);
- gtk_widget_realize (window);
-
- return window;
+ return g_object_new (GF_TYPE_BACKGROUND_WINDOW,
+ "accept-focus", FALSE,
+ "app-paintable", TRUE,
+ "decorated", FALSE,
+ "resizable", FALSE,
+ "skip-pager-hint", TRUE,
+ "skip-taskbar-hint", TRUE,
+ "type", GTK_WINDOW_TOPLEVEL,
+ "type-hint", GDK_WINDOW_TYPE_HINT_DESKTOP,
+ NULL);
}
diff --git a/gnome-flashback/libdesktop-background/gf-desktop-background.c
b/gnome-flashback/libdesktop-background/gf-desktop-background.c
index 7a109f8..0ab5c19 100644
--- a/gnome-flashback/libdesktop-background/gf-desktop-background.c
+++ b/gnome-flashback/libdesktop-background/gf-desktop-background.c
@@ -17,10 +17,8 @@
#include "config.h"
-#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include <libgnome-desktop/gnome-bg.h>
-#include <X11/Xatom.h>
#include "gf-background-window.h"
#include "gf-desktop-background.h"
@@ -49,162 +47,6 @@ struct _GfDesktopBackground
G_DEFINE_TYPE (GfDesktopBackground, gf_desktop_background, G_TYPE_OBJECT)
-static gboolean
-is_nautilus_desktop_manager (void)
-{
- GdkDisplay *display;
- Display *xdisplay;
- GdkScreen *screen;
- gint screen_number;
- gchar *name;
- Atom atom;
- Window window;
-
- display = gdk_display_get_default ();
- xdisplay = GDK_DISPLAY_XDISPLAY (display);
- screen = gdk_display_get_default_screen (display);
- screen_number = gdk_screen_get_number (screen);
-
- name = g_strdup_printf ("_NET_DESKTOP_MANAGER_S%d", screen_number);
- atom = XInternAtom (xdisplay, name, False);
- g_free (name);
-
- window = XGetSelectionOwner (xdisplay, atom);
-
- if (window != None)
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-is_desktop_window (Display *display,
- Window window)
-{
- Atom window_type;
- Atom desktop;
- Atom type;
- Atom *atoms;
- int result;
- int format;
- unsigned long items;
- unsigned long left;
-
- window_type = XInternAtom (display, "_NET_WM_WINDOW_TYPE", False);
- desktop = XInternAtom (display, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
-
- result = XGetWindowProperty (display, window, window_type,
- 0L, 1L, False, XA_ATOM, &type, &format,
- &items, &left, (unsigned char **) &atoms);
-
- if (result != Success)
- return FALSE;
-
- if (items && atoms[0] == desktop)
- {
- XFree (atoms);
- return TRUE;
- }
-
- XFree (atoms);
- return FALSE;
-}
-
-static GdkWindow *
-get_nautilus_window (GfDesktopBackground *background)
-{
- GdkDisplay *display;
- GdkWindow *window;
- Display *xdisplay;
- Atom client_list;
- Window root;
- Atom type;
- int result;
- int format;
- unsigned long items;
- unsigned long left;
- unsigned long i;
- Window *windows;
- Window nautilus;
- GdkWindow *background_window;
- Window desktop;
-
- gdk_error_trap_push ();
-
- display = gdk_display_get_default ();
- xdisplay = GDK_DISPLAY_XDISPLAY (display);
- client_list = XInternAtom (xdisplay, "_NET_CLIENT_LIST", False);
- root = XDefaultRootWindow (xdisplay);
-
- result = XGetWindowProperty (xdisplay, root, client_list,
- 0L, 1024L, False, XA_WINDOW, &type, &format,
- &items, &left, (unsigned char **) &windows);
-
- if (result != Success)
- {
- gdk_error_trap_pop_ignored ();
- return NULL;
- }
-
- nautilus = None;
- background_window = gtk_widget_get_window (background->background);
- desktop = GDK_WINDOW_XID (background_window);
-
- for (i = 0; i < items; i++)
- {
- if (is_desktop_window (xdisplay, windows[i]) && windows[i] != desktop)
- {
- nautilus = windows[i];
- break;
- }
- }
-
- XFree (windows);
-
- window = NULL;
- if (nautilus != None)
- window = gdk_x11_window_foreign_new_for_display (display, nautilus);
-
- gdk_error_trap_pop_ignored ();
-
- return window;
-}
-
-static GdkFilterReturn
-event_filter_func (GdkXEvent *xevent,
- GdkEvent *event,
- gpointer data)
-{
- static gboolean nautilus_raised = FALSE;
- GfDesktopBackground *background;
-
- background = GF_DESKTOP_BACKGROUND (data);
-
- if (is_nautilus_desktop_manager ())
- {
- if (nautilus_raised == FALSE)
- {
- GdkWindow *nautilus;
-
- nautilus = get_nautilus_window (background);
-
- if (GDK_IS_WINDOW (nautilus))
- {
- gdk_window_hide (nautilus);
- gdk_window_show (nautilus);
-
- nautilus_raised = TRUE;
- }
- }
- }
- else
- {
- nautilus_raised = FALSE;
- }
-
- return GDK_FILTER_CONTINUE;
-}
-
static void
free_fade (GfDesktopBackground *background)
{
@@ -484,8 +326,6 @@ gf_desktop_background_finalize (GObject *object)
g_clear_object (&background->gnome_settings);
g_clear_object (&background->background_settings);
- gdk_window_remove_filter (NULL, event_filter_func, background);
-
G_OBJECT_CLASS (gf_desktop_background_parent_class)->finalize (object);
}
@@ -520,8 +360,6 @@ gf_desktop_background_init (GfDesktopBackground *background)
G_CALLBACK (size_allocate), background);
queue_background_change (background);
-
- gdk_window_add_filter (NULL, event_filter_func, background);
}
GfDesktopBackground *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]