/** * gdk_x11_xatom_to_atom: * @xatom: an X atom for the default GDK display * * Convert from an X atom for the default display to the corresponding * #GdkAtom. * * Return value: the corresponding G#dkAtom. **/ GdkAtom gdk_x11_xatom_to_atom (Atom xatom) { return gdk_x11_xatom_to_atom_for_display (gdk_display_get_default (), xatom); }
gboolean gdk_property_get (GdkWindow *window, GdkAtom property, GdkAtom type, gulong offset, gulong length, gint pdelete, GdkAtom *actual_property_type, gint *actual_format_type, gint *actual_length, guchar **data) { GdkDisplay *display; Atom ret_prop_type; gint ret_format; gulong ret_nitems; gulong ret_bytes_after; gulong get_length; gulong ret_length; guchar *ret_data; Atom xproperty; Atom xtype; int res; g_return_val_if_fail (!window || GDK_IS_WINDOW (window), FALSE); if (!window) { GdkScreen *screen = gdk_screen_get_default (); window = gdk_screen_get_root_window (screen); GDK_NOTE (MULTIHEAD, g_message ("gdk_property_get(): window is NULL\n")); } if (GDK_WINDOW_DESTROYED (window)) return FALSE; display = gdk_drawable_get_display (window); xproperty = gdk_x11_atom_to_xatom_for_display (display, property); if (type == GDK_NONE) xtype = AnyPropertyType; else xtype = gdk_x11_atom_to_xatom_for_display (display, type); ret_data = NULL; /* * Round up length to next 4 byte value. Some code is in the (bad?) * habit of passing G_MAXLONG as the length argument, causing an * overflow to negative on the add. In this case, we clamp the * value to G_MAXLONG. */ get_length = length + 3; if (get_length > G_MAXLONG) get_length = G_MAXLONG; /* To fail, either the user passed 0 or G_MAXULONG */ get_length = get_length / 4; if (get_length == 0) { g_warning ("gdk_propery-get(): invalid length 0"); return FALSE; } res = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XWINDOW (window), xproperty, offset, get_length, pdelete, xtype, &ret_prop_type, &ret_format, &ret_nitems, &ret_bytes_after, &ret_data); if (res != Success || (ret_prop_type == None && ret_format == 0)) { return FALSE; } if (actual_property_type) *actual_property_type = gdk_x11_xatom_to_atom_for_display (display, ret_prop_type); if (actual_format_type) *actual_format_type = ret_format; if ((xtype != AnyPropertyType) && (ret_prop_type != xtype)) { XFree (ret_data); g_warning ("Couldn't match property type %s to %s\n", gdk_x11_get_xatom_name_for_display (display, ret_prop_type), gdk_x11_get_xatom_name_for_display (display, xtype)); return FALSE; } /* FIXME: ignoring bytes_after could have very bad effects */ if (data) { if (ret_prop_type == XA_ATOM || ret_prop_type == gdk_x11_get_xatom_by_name_for_display (display, "ATOM_PAIR")) { /* * data is an array of X atom, we need to convert it * to an array of GDK Atoms */ gint i; GdkAtom *ret_atoms = g_new (GdkAtom, ret_nitems); Atom *xatoms = (Atom *)ret_data; *data = (guchar *)ret_atoms; for (i = 0; i < ret_nitems; i++) ret_atoms[i] = gdk_x11_xatom_to_atom_for_display (display, xatoms[i]); if (actual_length) *actual_length = ret_nitems * sizeof (GdkAtom); } else { switch (ret_format) { case 8: ret_length = ret_nitems; break; case 16: ret_length = sizeof(short) * ret_nitems; break; case 32: ret_length = sizeof(long) * ret_nitems; break; default: g_warning ("unknown property return format: %d", ret_format); XFree (ret_data); return FALSE; } *data = g_new (guchar, ret_length); memcpy (*data, ret_data, ret_length); if (actual_length) *actual_length = ret_length; } } XFree (ret_data); return TRUE; }
/* Code to find the active window in order to collect stats for social * application browsing. */ static void get_active_application_properties(HippoIdleMonitor *monitor, char **wm_class, char **title) { Display *xdisplay = GDK_DISPLAY_XDISPLAY(monitor->display); int n_screens = gdk_display_get_n_screens(monitor->display); Atom net_active_window_x = gdk_x11_get_xatom_by_name_for_display(monitor->display, "_NET_ACTIVE_WINDOW"); GdkAtom net_active_window_gdk = gdk_atom_intern("_NET_ACTIVE_WINDOW", FALSE); Window active_window = None; int i; Atom type; int format; unsigned long n_items; unsigned long bytes_after; guchar *data; if (wm_class) *wm_class = NULL; if (title) *title = NULL; /* Find the currently focused window by looking at the _NET_ACTIVE_WINDOW property * on all the screens of the display. */ for (i = 0; i < n_screens; i++) { GdkScreen *screen = gdk_display_get_screen(monitor->display, i); GdkWindow *root = gdk_screen_get_root_window(screen); if (!gdk_x11_screen_supports_net_wm_hint (screen, net_active_window_gdk)) continue; XGetWindowProperty (xdisplay, GDK_DRAWABLE_XID(root), net_active_window_x, 0, 1, False, XA_WINDOW, &type, &format, &n_items, &bytes_after, &data); if (type == XA_WINDOW) { active_window = *(Window *)data; XFree(data); break; } } /* Now that we have the active window, figure out the application name and WM class */ gdk_error_trap_push(); if (active_window && wm_class) { if (XGetWindowProperty (xdisplay, active_window, XA_WM_CLASS, 0, G_MAXLONG, False, XA_STRING, &type, &format, &n_items, &bytes_after, &data) == Success && type == XA_STRING) { if (format == 8) { char **list; int count; count = gdk_text_property_to_utf8_list_for_display(monitor->display, GDK_TARGET_STRING, 8, data, n_items, &list); if (count > 1) *wm_class = g_strdup(list[1]); if (list) g_strfreev(list); } XFree(data); } } if (active_window && title) { Atom utf8_string = gdk_x11_get_xatom_by_name_for_display(monitor->display, "UTF8_STRING"); if (XGetWindowProperty (xdisplay, active_window, gdk_x11_get_xatom_by_name_for_display(monitor->display, "_NET_WM_NAME"), 0, G_MAXLONG, False, utf8_string, &type, &format, &n_items, &bytes_after, &data) == Success && type == utf8_string) { if (format == 8 && g_utf8_validate((char *)data, -1, NULL)) { *title = g_strdup((char *)data); } XFree(data); } } if (active_window && title && *title == NULL) { if (XGetWindowProperty (xdisplay, active_window, XA_WM_NAME, 0, G_MAXLONG, False, AnyPropertyType, &type, &format, &n_items, &bytes_after, &data) == Success && type != None) { if (format == 8) { char **list; int count; count = gdk_text_property_to_utf8_list_for_display(monitor->display, gdk_x11_xatom_to_atom_for_display(monitor->display, type), 8, data, n_items, &list); if (count > 0) *title = g_strdup(list[0]); if (list) g_strfreev(list); } XFree(data); } } gdk_error_trap_pop(); }
/* Code to find the active window in order to collect stats for social * application browsing. */ static void get_active_application_properties(HippoIdleMonitor *monitor, char **wm_class, char **title) { Display *xdisplay = GDK_DISPLAY_XDISPLAY(monitor->display); int n_screens = gdk_display_get_n_screens(monitor->display); Atom net_active_window_x = gdk_x11_get_xatom_by_name_for_display(monitor->display, "_NET_ACTIVE_WINDOW"); GdkAtom net_active_window_gdk = gdk_atom_intern("_NET_ACTIVE_WINDOW", FALSE); Window active_window = None; int i; Atom type; int format; unsigned long n_items; unsigned long bytes_after; guchar *data; gboolean is_desktop = FALSE; if (wm_class) *wm_class = NULL; if (title) *title = NULL; /* Find the currently focused window by looking at the _NET_ACTIVE_WINDOW property * on all the screens of the display. */ for (i = 0; i < n_screens; i++) { GdkScreen *screen = gdk_display_get_screen(monitor->display, i); GdkWindow *root = gdk_screen_get_root_window(screen); if (!gdk_x11_screen_supports_net_wm_hint (screen, net_active_window_gdk)) continue; XGetWindowProperty (xdisplay, GDK_DRAWABLE_XID(root), net_active_window_x, 0, 1, False, XA_WINDOW, &type, &format, &n_items, &bytes_after, &data); if (type == XA_WINDOW) { active_window = *(Window *)data; XFree(data); break; } } /* Now that we have the active window, figure out the application name and WM class */ gdk_error_trap_push(); if (active_window && wm_class) { if (XGetWindowProperty (xdisplay, active_window, XA_WM_CLASS, 0, G_MAXLONG, False, XA_STRING, &type, &format, &n_items, &bytes_after, &data) == Success && type == XA_STRING) { if (format == 8) { char **list; int count; count = gdk_text_property_to_utf8_list_for_display(monitor->display, GDK_TARGET_STRING, 8, data, n_items, &list); if (count > 1) { /* This is a check for Nautilus, which sets the instance to this * value for the desktop window; we do this rather than check for * the more general _NET_WM_WINDOW_TYPE_DESKTOP to avoid having * to do another XGetProperty on every iteration. We generally * don't want to count the desktop being focused as application * usage because it frequently can be a false-positive of an * empty workspace. */ if (strcmp(list[0], "desktop_window") == 0) is_desktop = TRUE; else *wm_class = g_strdup(list[1]); } if (list) g_strfreev(list); } XFree(data); } } if (is_desktop) active_window = None; if (active_window && title) { Atom utf8_string = gdk_x11_get_xatom_by_name_for_display(monitor->display, "UTF8_STRING"); if (XGetWindowProperty (xdisplay, active_window, gdk_x11_get_xatom_by_name_for_display(monitor->display, "_NET_WM_NAME"), 0, G_MAXLONG, False, utf8_string, &type, &format, &n_items, &bytes_after, &data) == Success && type == utf8_string) { if (format == 8 && g_utf8_validate((char *)data, -1, NULL)) { *title = g_strdup((char *)data); } XFree(data); } } if (active_window && title && *title == NULL) { if (XGetWindowProperty (xdisplay, active_window, XA_WM_NAME, 0, G_MAXLONG, False, AnyPropertyType, &type, &format, &n_items, &bytes_after, &data) == Success && type != None) { if (format == 8) { char **list; int count; count = gdk_text_property_to_utf8_list_for_display(monitor->display, gdk_x11_xatom_to_atom_for_display(monitor->display, type), 8, data, n_items, &list); if (count > 0) *title = g_strdup(list[0]); if (list) g_strfreev(list); } XFree(data); } } gdk_error_trap_pop(); }