gnome-control-center/capplets/common/wm-common.c
Jens Granseuer c1a2b46553 make sure we always return a copy of the window manager name, not a static
2007-05-23  Jens Granseuer  <jensgr@gmx.net>

	* wm-common.c: (wm_common_get_current_window_manager): make sure we
	always return a copy of the window manager name, not a static string
	(fixes bug #439244)

svn path=/trunk/; revision=7650
2007-05-23 17:30:07 +00:00

142 lines
3.2 KiB
C

#include <X11/Xatom.h>
#include <gdk/gdkx.h>
#include <gdk/gdk.h>
#include <string.h>
#include <glib.h>
#include <glib-object.h>
#include "wm-common.h"
typedef struct _WMCallbackData
{
GFunc func;
gpointer data;
} WMCallbackData;
/* Our WM Window */
static Window wm_window = None;
char*
wm_common_get_current_window_manager (void)
{
Atom utf8_string, atom, type;
int result;
char *retval;
int format;
gulong nitems;
gulong bytes_after;
guchar *val;
if (wm_window == None)
return g_strdup (WM_COMMON_UNKNOWN);
utf8_string = XInternAtom (GDK_DISPLAY (), "UTF8_STRING", False);
atom = XInternAtom (GDK_DISPLAY (), "_NET_WM_NAME", False);
gdk_error_trap_push ();
val = NULL;
result = XGetWindowProperty (GDK_DISPLAY (),
wm_window,
atom,
0, G_MAXLONG,
False, utf8_string,
&type, &format, &nitems,
&bytes_after, &val);
if (gdk_error_trap_pop () || result != Success ||
type != utf8_string || format != 8 || nitems == 0 ||
!g_utf8_validate (val, nitems, NULL))
{
retval = g_strdup (WM_COMMON_UNKNOWN);
}
else
{
retval = g_strndup (val, nitems);
}
if (val)
XFree (val);
return retval;
}
static void
update_wm_window (void)
{
Window *xwindow;
Atom type;
gint format;
gulong nitems;
gulong bytes_after;
XGetWindowProperty (GDK_DISPLAY (), GDK_ROOT_WINDOW (),
XInternAtom (GDK_DISPLAY (), "_NET_SUPPORTING_WM_CHECK", False),
0, G_MAXLONG, False, XA_WINDOW, &type, &format,
&nitems, &bytes_after, (guchar **) &xwindow);
if (type != XA_WINDOW)
{
wm_window = None;
return;
}
gdk_error_trap_push ();
XSelectInput (GDK_DISPLAY (), *xwindow, StructureNotifyMask | PropertyChangeMask);
XSync (GDK_DISPLAY (), False);
if (gdk_error_trap_pop ())
{
XFree (xwindow);
wm_window = None;
return;
}
wm_window = *xwindow;
XFree (xwindow);
}
static GdkFilterReturn
wm_window_event_filter (GdkXEvent *xev,
GdkEvent *event,
gpointer data)
{
WMCallbackData *ncb_data = (WMCallbackData*) data;
XEvent *xevent = (XEvent *)xev;
if ((xevent->type == DestroyNotify &&
wm_window != None && xevent->xany.window == wm_window) ||
(xevent->type == PropertyNotify &&
xevent->xany.window == GDK_ROOT_WINDOW () &&
xevent->xproperty.atom == (XInternAtom (GDK_DISPLAY (), "_NET_SUPPORTING_WM_CHECK", False))) ||
(xevent->type == PropertyNotify &&
wm_window != None && xevent->xany.window == wm_window &&
xevent->xproperty.atom == (XInternAtom (GDK_DISPLAY (), "_NET_WM_NAME", False))))
{
update_wm_window ();
(* ncb_data->func) ((gpointer)wm_common_get_current_window_manager(),
ncb_data->data);
}
return GDK_FILTER_CONTINUE;
}
void
wm_common_register_window_manager_change (GFunc func,
gpointer data)
{
WMCallbackData *ncb_data;
ncb_data = g_new0 (WMCallbackData, 1);
ncb_data->func = func;
ncb_data->data = data;
gdk_window_add_filter (NULL, wm_window_event_filter, ncb_data);
update_wm_window ();
XSelectInput (GDK_DISPLAY (), GDK_ROOT_WINDOW (), PropertyChangeMask);
XSync (GDK_DISPLAY (), False);
}