[gnome-desktop] Make the RR labels honor workarea so they don't appear over/under panels



commit 053a932b09487c4fa3e6331ef7fb65d24667263d
Author: William Jon McCann <jmccann redhat com>
Date:   Thu Oct 7 21:05:17 2010 -0400

    Make the RR labels honor workarea so they don't appear over/under panels

 libgnome-desktop/gnome-rr-labeler.c |  135 ++++++++++++++++++++++++++++++++++-
 1 files changed, 132 insertions(+), 3 deletions(-)
---
diff --git a/libgnome-desktop/gnome-rr-labeler.c b/libgnome-desktop/gnome-rr-labeler.c
index c38db37..276c1a6 100644
--- a/libgnome-desktop/gnome-rr-labeler.c
+++ b/libgnome-desktop/gnome-rr-labeler.c
@@ -1,4 +1,6 @@
-/* gnome-rr-labeler.c - Utility to label monitors to identify them
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * gnome-rr-labeler.c - Utility to label monitors to identify them
  * while they are being configured.
  *
  * Copyright 2008, Novell, Inc.
@@ -30,6 +32,12 @@
 #include "libgnomeui/gnome-rr-labeler.h"
 #include <gtk/gtk.h>
 
+#include <X11/Xproto.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <gdk/gdkx.h>
+
 struct _GnomeRRLabeler {
 	GObject parent;
 
@@ -39,6 +47,9 @@ struct _GnomeRRLabeler {
 
 	GdkColor *palette;
 	GtkWidget **windows;
+
+	GdkScreen  *screen;
+	Atom        workarea_atom;
 };
 
 struct _GnomeRRLabelerClass {
@@ -48,11 +59,105 @@ struct _GnomeRRLabelerClass {
 G_DEFINE_TYPE (GnomeRRLabeler, gnome_rr_labeler, G_TYPE_OBJECT);
 
 static void gnome_rr_labeler_finalize (GObject *object);
+static void create_label_windows (GnomeRRLabeler *labeler);
+
+static gboolean
+get_work_area (GnomeRRLabeler *labeler,
+	       GdkRectangle   *rect)
+{
+	Atom            workarea;
+	Atom            type;
+	Window          win;
+	int             format;
+	gulong          num;
+	gulong          leftovers;
+	gulong          max_len = 4 * 32;
+	guchar         *ret_workarea;
+	long           *workareas;
+	int             result;
+	int             disp_screen;
+	Display        *display;
+
+	display = GDK_DISPLAY_XDISPLAY (gdk_screen_get_display (labeler->screen));
+	workarea = XInternAtom (display, "_NET_WORKAREA", True);
+
+	disp_screen = GDK_SCREEN_XNUMBER (labeler->screen);
+
+	/* Defaults in case of error */
+	rect->x = 0;
+	rect->y = 0;
+	rect->width = gdk_screen_get_width (labeler->screen);
+	rect->height = gdk_screen_get_height (labeler->screen);
+
+	if (workarea == None)
+		return FALSE;
+
+	win = XRootWindow (display, disp_screen);
+	result = XGetWindowProperty (display,
+				     win,
+				     workarea,
+				     0,
+				     max_len,
+				     False,
+				     AnyPropertyType,
+				     &type,
+				     &format,
+				     &num,
+				     &leftovers,
+				     &ret_workarea);
+
+	if (result != Success
+	    || type == None
+	    || format == 0
+	    || leftovers
+	    || num % 4) {
+		return FALSE;
+	}
+
+	workareas = (long *) ret_workarea;
+	rect->x = workareas[disp_screen * 4];
+	rect->y = workareas[disp_screen * 4 + 1];
+	rect->width = workareas[disp_screen * 4 + 2];
+	rect->height = workareas[disp_screen * 4 + 3];
+
+	XFree (ret_workarea);
+
+	return TRUE;
+}
+
+static GdkFilterReturn
+screen_xevent_filter (GdkXEvent      *xevent,
+		      GdkEvent       *event,
+		      GnomeRRLabeler *labeler)
+{
+	XEvent *xev;
+
+	xev = (XEvent *) xevent;
+
+	if (xev->type == PropertyNotify &&
+	    xev->xproperty.atom == labeler->workarea_atom) {
+		/* update label positions */
+		gnome_rr_labeler_hide (labeler);
+		create_label_windows (labeler);
+	}
+
+	return GDK_FILTER_CONTINUE;
+}
 
 static void
 gnome_rr_labeler_init (GnomeRRLabeler *labeler)
 {
-	/* nothing */
+	GdkWindow *gdkwindow;
+
+	labeler->workarea_atom = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+					      "_NET_WORKAREA",
+					      True);
+
+	labeler->screen = gdk_screen_get_default ();
+	/* code is not really designed to handle multiple screens so *shrug* */
+	gdkwindow = gdk_screen_get_root_window (labeler->screen);
+	gdk_window_add_filter (gdkwindow, (GdkFilterFunc) screen_xevent_filter, labeler);
+	gdk_window_set_events (gdkwindow, gdk_window_get_events (gdkwindow) | GDK_PROPERTY_CHANGE_MASK);
 }
 
 static void
@@ -69,9 +174,13 @@ static void
 gnome_rr_labeler_finalize (GObject *object)
 {
 	GnomeRRLabeler *labeler;
+	GdkWindow      *gdkwindow;
 
 	labeler = GNOME_RR_LABELER (object);
 
+	gdkwindow = gdk_screen_get_root_window (labeler->screen);
+	gdk_window_remove_filter (gdkwindow, (GdkFilterFunc) screen_xevent_filter, labeler);
+
 	/* We don't destroy the labeler->config (a GnomeRRConfig*) here; let our
 	 * caller do that instead.
 	 */
@@ -173,6 +282,26 @@ label_window_draw_event_cb (GtkWidget *widget, cairo_t *cr, gpointer data)
 	return FALSE;
 }
 
+static void
+position_window (GnomeRRLabeler  *labeler,
+		 GtkWidget       *window,
+		 int              x,
+		 int              y)
+{
+	GdkRectangle    workarea;
+	GdkRectangle    monitor;
+	int             monitor_num;
+
+	get_work_area (labeler, &workarea);
+	monitor_num = gdk_screen_get_monitor_at_point (labeler->screen, x, y);
+	gdk_screen_get_monitor_geometry (labeler->screen,
+                                         monitor_num,
+                                         &monitor);
+	gdk_rectangle_intersect (&monitor, &workarea, &workarea);
+
+	gtk_window_move (GTK_WINDOW (window), workarea.x, workarea.y);
+}
+
 static GtkWidget *
 create_label_window (GnomeRRLabeler *labeler, GnomeOutputInfo *output, GdkColor *color)
 {
@@ -222,7 +351,7 @@ create_label_window (GnomeRRLabeler *labeler, GnomeOutputInfo *output, GdkColor
 	gtk_container_add (GTK_CONTAINER (window), widget);
 
 	/* Should we center this at the top edge of the monitor, instead of using the upper-left corner? */
-	gtk_window_move (GTK_WINDOW (window), output->x, output->y);
+	position_window (labeler, window, output->x, output->y);
 
 	gtk_widget_show_all (window);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]