[Gtk-sharp-list] Modified Gdk.Global glue bindings to expose some EWMH

Boyd Timothy boyd@timothy.ws
Thu, 15 Apr 2004 14:48:58 -0600


--=-k8ZT5AWsYQtcNZ52Qb33
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Concerns about X11 cross-platform independence came up.  It appears that
the gdk_property_get () function is available in Win32.  I don't have a
windows machine setup with Mono at the moment.  Anyone who could try
this patch out and make sure that gtk-sharp can still compile it would
be great!

For now, I've modified makefile.win32 to include the new windowmanager.o
library so that Global.custom will compile correctly.

In any case, I've implemented a couple other features of the window
manager hints and have attached my latest code (diff'd against CVS just
a few minutes ago).

-Boyd

On Fri, 2004-04-09 at 14:30, Boyd Timothy wrote:
> I've added _NET_ACTIVE_WINDOW now as well.  It was suggested that we
> will have to make a #define in the glue code so we could provide the
> functionality of these methods on other operating systems (like win32).
> 
> Does anyone else have any thoughts/concerns?
> 
> -Boyd
> On Thu, 2004-04-08 at 16:54, Boyd Timothy wrote:
> > Following Mike's recommendation to move the methods to properties, here
> > is an updated patch to gdk/Global.custom
> > 
> > On Wed, 2004-04-07 at 23:45, Boyd Timothy wrote:
> > > Attached is the patch to current CVS and a new windowmanager.c which
> > > goes in the gtk-sharp/gdk/glue/ directory.
> > > 
> > > The new static properties/methods I added are:
> > > 
> > > Gdk.Global.ListSupportedWindowManagerHints () : Gdk.Atom []
> > > Gdk.Global.NumberOfDesktops : int
> > > Gdk.Global.CurrentDesktop: int
> > > Gdk.Global.ListDesktopWorkareas () : Gdk.Rectangle []
> > > 
> > > These make it easy from C# to get these values without having to mess
> > > with the crazy format of Gdk.Property.Get () or using gdk_property_get
> > > () directly with P/Invoke from C#.
> > > 
> > > Anyhow, since I've never really posted any patches, I'm not sure what
> > > the process is from here.  Mike, I assume you'll take it from here?
> > > 
> > > Thanks,
> > > 
> > > Boyd

--=-k8ZT5AWsYQtcNZ52Qb33
Content-Disposition: attachment; filename=gtk-sharp-windowmanager.patch
Content-Type: text/plain; name=gtk-sharp-windowmanager.patch; charset=UTF-8
Content-Transfer-Encoding: 7bit

? gtk-sharp/gdk/glue/windowmanager.c
Index: gtk-sharp/gdk/Global.custom
===================================================================
RCS file: /mono/gtk-sharp/gdk/Global.custom,v
retrieving revision 1.1
diff -u -p -r1.1 Global.custom
--- gtk-sharp/gdk/Global.custom	12 Feb 2004 18:45:19 -0000	1.1
+++ gtk-sharp/gdk/Global.custom	15 Apr 2004 20:33:01 -0000
@@ -1,6 +1,7 @@
 // Global.custom - customizations to Gdk.Global
 //
 // Authors: Mike Kestner  <mkestner@ximian.com>
+//          Boyd Timothy  <btimothy@novell.com>
 //
 // Copyright (c) 2004 Novell, Inc.
 
@@ -34,3 +35,89 @@
 			return result;
 		}
 
+		[DllImport ("gdksharpglue")]
+		static extern IntPtr gtksharp_get_gdk_net_supported ();
+
+		public static Gdk.Atom[] SupportedWindowManagerHints {
+			get {
+				IntPtr raw_ret = gtksharp_get_gdk_net_supported ();
+				if (raw_ret == IntPtr.Zero)
+					return new Gdk.Atom [0];
+				GLib.List list = new GLib.List (raw_ret, typeof (Gdk.Atom));
+				Gdk.Atom[] atoms = new Gdk.Atom [list.Count];
+				for (int i = 0; i < list.Count; i++)
+					atoms [i] = list [i] as Gdk.Atom;
+
+				return atoms;
+			}
+		}
+
+		[DllImport ("gdksharpglue")]
+		static extern IntPtr gtksharp_get_gdk_net_client_list (out int count);
+
+		public static Gdk.Window[] WindowManagerClientWindows {
+			get {
+				int count;
+				IntPtr raw_ret = gtksharp_get_gdk_net_client_list (out count);
+				if (raw_ret == IntPtr.Zero)
+					return new Gdk.Window [0];
+				Gdk.Window [] windows = new Gdk.Window [count];
+				int offset = 0;
+				for (int i = 0; i < count; i++) {
+					int windowID = Marshal.ReadInt32 (raw_ret, offset);
+					Console.WriteLine ("WinID: {0}", windowID);
+					offset += IntPtr.Size;
+					windows [i] = Gdk.Window.ForeignNew ((uint) windowID);
+				}
+				return windows;
+			}
+		}
+
+		[DllImport ("gdksharpglue")]
+		static extern int gtksharp_get_gdk_net_number_of_desktops ();
+
+		public static int NumberOfDesktops {
+			get {
+				return gtksharp_get_gdk_net_number_of_desktops ();
+			}
+		}
+
+		[DllImport ("gdksharpglue")]
+		static extern int gtksharp_get_gdk_net_current_desktop ();
+
+		public static int CurrentDesktop {
+			get {
+				return gtksharp_get_gdk_net_current_desktop ();
+			}
+		}
+
+		[DllImport ("gdksharpglue")]
+		static extern uint gtksharp_get_gdk_net_active_window ();
+
+		public static Gdk.Window ActiveWindow {
+			get {
+				uint windowID = gtksharp_get_gdk_net_active_window ();
+				if (windowID == 0)
+					return Gdk.Global.DefaultRootWindow;
+				Console.WriteLine ("Active Window ID: {0}", windowID);
+				Gdk.Window window = Gdk.Window.ForeignNew (windowID);
+				return window;
+			}
+		}
+
+		[DllImport ("gdksharpglue")]
+		static extern IntPtr gtksharp_get_gdk_net_workarea ();
+
+		public static Gdk.Rectangle[] DesktopWorkareas {
+			get {
+				IntPtr raw_ret = gtksharp_get_gdk_net_workarea ();
+				if (raw_ret == IntPtr.Zero)
+					return new Gdk.Rectangle [0];
+				GLib.List list = new GLib.List (raw_ret, typeof (Gdk.Rectangle));
+				Gdk.Rectangle[] workareas = new Gdk.Rectangle [list.Count];
+				for (int i = 0; i < list.Count; i++)
+					workareas [i] = (Gdk.Rectangle) list [i];
+
+				return workareas;
+			}
+		}
Index: gtk-sharp/gdk/glue/Makefile.am
===================================================================
RCS file: /mono/gtk-sharp/gdk/glue/Makefile.am,v
retrieving revision 1.3
diff -u -p -r1.3 Makefile.am
--- gtk-sharp/gdk/glue/Makefile.am	31 Mar 2004 16:34:08 -0000	1.3
+++ gtk-sharp/gdk/glue/Makefile.am	15 Apr 2004 20:33:01 -0000
@@ -4,7 +4,8 @@ libgdksharpglue_la_SOURCES =	\
 	dragcontext.c		\
 	event.c			\
 	selection.c		\
-	vmglueheaders.h
+	vmglueheaders.h		\
+	windowmanager.c
 
 # Adding a new glue file?
 # Please remember to update makefile.win32
Index: gtk-sharp/gdk/glue/makefile.win32
===================================================================
RCS file: /mono/gtk-sharp/gdk/glue/makefile.win32,v
retrieving revision 1.3
diff -u -p -r1.3 makefile.win32
--- gtk-sharp/gdk/glue/makefile.win32	31 Mar 2004 16:34:08 -0000	1.3
+++ gtk-sharp/gdk/glue/makefile.win32	15 Apr 2004 20:33:01 -0000
@@ -7,7 +7,8 @@ GLUE_OBJS = \
 	dragcontext.o		\
         event.o                 \
         selection.o             \
-	win32dll.o
+	win32dll.o		\
+	windowmanager.o
 
 all: gdksharpglue.dll
 

--=-k8ZT5AWsYQtcNZ52Qb33
Content-Disposition: attachment; filename=windowmanager.c
Content-Type: text/x-c; name=windowmanager.c; charset=UTF-8
Content-Transfer-Encoding: 7bit

/* windowmanager.c : Glue to access the extended window 
 * manager hints via the root window properties using
 * gdk_property_get ()
 *
 * This work is based on the specification found here:
 *	http://www.freedesktop.org/standards/wm-spec/
 *
 * Author: Boyd Timothy <btimothy@novell.com>
 *
 * Copyright (c) 2004 Novell, Inc.
 */

#include <gdk/gdkscreen.h>
#include <gdk/gdkwindow.h>
#include <gdk/gdkproperty.h>

GList * gtksharp_get_gdk_net_supported (void);
guint * gtksharp_get_gdk_net_client_list (int *count);
gint gtksharp_get_gdk_net_number_of_desktops (void);
gint gtksharp_get_gdk_net_current_desktop (void);
guint gtksharp_get_gdk_net_active_window (void);
GList * gtksharp_get_gdk_net_workarea (void);

GList * gtksharp_get_gdk_net_supported (void)
{
	GdkAtom actual_property_type;
	int actual_format;
	int actual_length;
	long *data = NULL;
	GList *list = NULL;
	int i;

	if (!gdk_property_get (
			gdk_screen_get_root_window (gdk_screen_get_default ()),
			gdk_atom_intern ("_NET_SUPPORTED", FALSE),
			gdk_atom_intern ("ATOM", FALSE),
			0,
			G_MAXLONG,
			FALSE,
			&actual_property_type,
			&actual_format,
			&actual_length,
			(guchar **) &data)) {
		g_critical ("Unable to get _NET_SUPPORTED");
		gchar *actual_property_type_name = gdk_atom_name (actual_property_type);
		if (actual_property_type_name) {
			g_message ("actual_property_type: %s", actual_property_type_name);
			g_free (actual_property_type_name);
		}
		return NULL;
	}

	// Put all of the GdkAtoms into a GList to return
	for (i = 0; i < actual_length / sizeof (long); i ++) {
		list = g_list_append (list, (GdkAtom) data [i]);
	}

	g_free (data);
	return list;
}

guint * gtksharp_get_gdk_net_client_list (int *count)
{
	GdkAtom actual_property_type;
	int actual_format;
	int actual_length;
	long *data = NULL;
	//GList *list = NULL;
	guint * list = NULL;
	int i;

	if (!gdk_property_get (
			gdk_screen_get_root_window (gdk_screen_get_default ()),
			gdk_atom_intern ("_NET_CLIENT_LIST", FALSE),
			gdk_atom_intern ("WINDOW", FALSE),
			0,
			G_MAXLONG,
			FALSE,
			&actual_property_type,
			&actual_format,
			&actual_length,
			(guchar **) &data)) {
		g_critical ("Unable to get _NET_CLIENT_LIST");
		gchar *actual_property_type_name = gdk_atom_name (actual_property_type);
		if (actual_property_type_name) {
			g_message ("actual_property_type: %s", actual_property_type_name);
			g_free (actual_property_type_name);
		}
		return NULL;
	}

	*count = actual_length / sizeof (long);
	list = g_malloc (*count * sizeof (guint));
	// Put all of the windows into a GList to return
	for (i = 0; i < *count; i ++) {
		//list = g_list_append (list, (gpointer) data [i]);
		list [i] = data [i];
		g_message ("WinID: %d", list [i]);
	}

	g_free (data);
	return list;
}

gint gtksharp_get_gdk_net_number_of_desktops (void)
{
	GdkAtom actual_property_type;
	int actual_format;
	int actual_length;
	long *data = NULL;
	gint num_of_desktops;

	if (!gdk_property_get (
			gdk_screen_get_root_window (gdk_screen_get_default ()),
			gdk_atom_intern ("_NET_NUMBER_OF_DESKTOPS", FALSE),
			gdk_atom_intern ("CARDINAL", FALSE),
			0,
			G_MAXLONG,
			FALSE,
			&actual_property_type,
			&actual_format,
			&actual_length,
			(guchar **) &data)) {
		g_critical ("Unable to get _NET_NUMBER_OF_DESKTOPS");
		gchar *actual_property_type_name = gdk_atom_name (actual_property_type);
		if (actual_property_type_name) {
			g_message ("actual_property_type: %s", actual_property_type_name);
			g_free (actual_property_type_name);
		}

		return -1;
	}

	num_of_desktops = (gint) data[0];
	g_free (data);

	return num_of_desktops;
}

gint gtksharp_get_gdk_net_current_desktop (void)
{
	GdkAtom actual_property_type;
	int actual_format;
	int actual_length;
	long *data = NULL;
	gint current_desktop;

	if (!gdk_property_get (
			gdk_screen_get_root_window (gdk_screen_get_default ()),
			gdk_atom_intern ("_NET_CURRENT_DESKTOP", FALSE),
			gdk_atom_intern ("CARDINAL", FALSE),
			0,
			G_MAXLONG,
			FALSE,
			&actual_property_type,
			&actual_format,
			&actual_length,
			(guchar **) &data)) {
		g_critical ("Unable to get _NET_CURRENT_DESKTOP");
		gchar *actual_property_type_name = gdk_atom_name (actual_property_type);
		if (actual_property_type_name) {
			g_message ("actual_property_type: %s", actual_property_type_name);
			g_free (actual_property_type_name);
		}
		return -1;
	}

	current_desktop = (gint) data[0];
	g_free (data);

	return current_desktop;
}

guint gtksharp_get_gdk_net_active_window (void)
{
	GdkAtom actual_property_type;
	int actual_format;
	int actual_length;
	long *data = NULL;
	guint windowID = 0;

	if (!gdk_property_get (
			gdk_screen_get_root_window (gdk_screen_get_default ()),	// GdkWindow * window,
			gdk_atom_intern ("_NET_ACTIVE_WINDOW", FALSE),		// GdkAtom property,
			gdk_atom_intern ("WINDOW", FALSE),			// GdkAtom type,
			0,							// gulong offset,
			G_MAXLONG,						// gulong length,
			FALSE,							// gint pdelete,
			&actual_property_type,					// GdkAtom * actual_property_type,
			&actual_format,						// gint * actual_format,
			&actual_length,						// gint * actual_length,
			(guchar **) &data)) {					// guchar ** data);
		g_critical ("Unable to get _NET_ACTIVE_WINDOW");
		gchar *actualPropertyTypeName = gdk_atom_name (actual_property_type);
		if (actualPropertyTypeName) {
			g_message ("actual_property_type: %s", actualPropertyTypeName);
			g_free(actualPropertyTypeName);
		}
			return -1;
	}

	windowID = (gint) data [0];
	g_free (data);

	return windowID;
}

GList * gtksharp_get_gdk_net_workarea (void)
{
	GdkAtom actual_property_type;
	int actual_format;
	int actual_length;
	long *data = NULL;	
	int i = 0;
	GList *list = NULL;

	if (!gdk_property_get (
			gdk_screen_get_root_window (gdk_screen_get_default ()),	// GdkWindow * window,
			gdk_atom_intern ("_NET_WORKAREA", FALSE),		// GdkAtom property,
			gdk_atom_intern ("CARDINAL", FALSE),			// GdkAtom type,
			0,							// gulong offset,
			G_MAXLONG,						// gulong length,
			FALSE,							// gint pdelete,
			&actual_property_type,					// GdkAtom * actual_property_type,
			&actual_format,						// gint * actual_format,
			&actual_length,						// gint * actual_length,
			(guchar **) &data)) {					// guchar ** data);
		g_critical ("Unable to get _NET_WORKAREA");
		gchar *actualPropertyTypeName = gdk_atom_name (actual_property_type);
		if (actualPropertyTypeName) {
			g_message ("actual_property_type: %s", actualPropertyTypeName);
			g_free(actualPropertyTypeName);
		}
			return FALSE;
	}

	for (i = 0; i < actual_length / sizeof (long); i += 4) {
		GdkRectangle *rectangle = g_malloc(sizeof (GdkRectangle));
		rectangle->x		= (int) data [i];
		rectangle->y		= (int) data [i + 1];
		rectangle->width	= (int) data [i + 2];
		rectangle->height	= (int) data [i + 3];
		list = g_list_append (list, rectangle);
	}


	if (data != NULL)
		g_free(data);

	return list;
}

--=-k8ZT5AWsYQtcNZ52Qb33--