Rework internals of ShellAppMonitor to use Metacity library

The code here is significantly cleaner if we use the data Metacity
already has cached and validated, rather than talking to X directly.

Also some preparatory work for extending the monitor API by
clarifying the name of the (current) main entry point.
This commit is contained in:
Colin Walters 2009-05-26 17:22:51 -04:00
parent 0ea01b31af
commit 278a44caf1
4 changed files with 30 additions and 153 deletions

View File

@ -395,7 +395,7 @@ AppDisplay.prototype = {
_setDefaultList : function() { _setDefaultList : function() {
// Ask or more app than we need, since the list of recently used apps // Ask or more app than we need, since the list of recently used apps
// might contain an app we don't have a desktop file for // might contain an app we don't have a desktop file for
var apps = this._appMonitor.get_apps (0, Math.round(MAX_ITEMS * 1.5)); var apps = this._appMonitor.get_most_used_apps (0, Math.round(MAX_ITEMS * 1.5));
this._matchedItems = []; this._matchedItems = [];
for (let i = 0; i < apps.length; i++) { for (let i = 0; i < apps.length; i++) {
if (this._matchedItems.length > MAX_ITEMS) if (this._matchedItems.length > MAX_ITEMS)

View File

@ -15,6 +15,7 @@
#include "shell-app-monitor.h" #include "shell-app-monitor.h"
#include "shell-global.h" #include "shell-global.h"
#include "display.h"
/* This file includes modified code from /* This file includes modified code from
* desktop-data-engine/engine-dbus/hippo-application-monitor.c * desktop-data-engine/engine-dbus/hippo-application-monitor.c
@ -260,32 +261,32 @@ shell_app_monitor_finalize (GObject *object)
} }
/** /**
* shell_app_monitor_get_apps: * shell_app_monitor_get_most_used_apps:
* *
* Get a list of desktop identifiers representing the most popular applications * Get a list of desktop identifiers representing the most popular applications
* for a given activity. * for a given activity.
* *
* @monitor: the app monitor instance to request * @monitor: the app monitor instance to request
* @activity: the activity for which stats are considered * @activity: the activity for which stats are considered
* @max_count: how many applications are requested. Note that the actual * @max_count: how many applications are requested. Note that the actual
* list size may be less, or NULL if not enough applications are registered. * list size may be less, or NULL if not enough applications are registered.
* *
* Returns: (element-type utf8) (transfer full): List of application desktop * Returns: (element-type utf8) (transfer full): List of application desktop
* identifiers, in low case * identifiers, in low case
*/ */
GSList * GSList *
shell_app_monitor_get_apps (ShellAppMonitor *monitor, shell_app_monitor_get_most_used_apps (ShellAppMonitor *monitor,
gint activity, gint activity,
gint max_count) gint max_count)
{ {
GSList *list = NULL; GSList *list = NULL;
GSList *popularity; GSList *popularity;
AppPopularity *app_popularity; AppPopularity *app_popularity;
int i; int i;
popularity = g_hash_table_lookup (monitor->popularities, popularity = g_hash_table_lookup (monitor->popularities,
GINT_TO_POINTER (activity)); GINT_TO_POINTER (activity));
for (i = 0; i < max_count; i++) for (i = 0; i < max_count; i++)
{ {
if (!popularity) if (!popularity)
@ -304,154 +305,28 @@ get_active_app_properties (ShellAppMonitor *monitor,
char **wm_class, char **wm_class,
char **title) char **title)
{ {
Display *xdisplay = GDK_DISPLAY_XDISPLAY (monitor->display); ShellGlobal *global;
int n_screens = gdk_display_get_n_screens (monitor->display); MetaScreen *screen;
Atom net_active_window_x = MetaDisplay *display;
gdk_x11_get_xatom_by_name_for_display (monitor->display, MetaWindow *active;
"_NET_ACTIVE_WINDOW");
GdkAtom net_active_window_gdk =
gdk_atom_intern ("_NET_ACTIVE_WINDOW", FALSE);
Window active_window = None;
int i;
Atom type; global = shell_global_get ();
int format; g_object_get (global, "screen", &screen, NULL);
unsigned long n_items; display = meta_screen_get_display (screen);
unsigned long bytes_after; g_object_unref (screen);
guchar *data;
gboolean is_desktop = FALSE; active = meta_display_get_focus_window (display);
if (wm_class) if (wm_class)
*wm_class = NULL; *wm_class = NULL;
if (title) if (title)
*title = NULL; *title = NULL;
/* Find the currently focused window by looking at the _NET_ACTIVE_WINDOW property if (active == NULL)
* on all the screens of the display. return;
*/
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)) *wm_class = g_strdup (meta_window_get_wm_class (active));
continue; *title = g_strdup (meta_window_get_description (active));
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 app 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 app
* usage because it frequently can be a false-positive on 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 ();
} }
void void

View File

@ -36,9 +36,13 @@ GType shell_app_monitor_get_type (void) G_GNUC_CONST;
ShellAppMonitor* shell_app_monitor_new(void); ShellAppMonitor* shell_app_monitor_new(void);
/* Get the most popular applications for a given activity */ /* Get the most popular applications for a given activity */
GSList *shell_app_monitor_get_apps (ShellAppMonitor *monitor, GSList *shell_app_monitor_get_most_used_apps (ShellAppMonitor *monitor,
int activity, int activity,
gint number); gint number);
/* Get whatever's running right now */
GSList *shell_app_monitor_get_running_apps (ShellAppMonitor *monitor,
int activity);
G_END_DECLS G_END_DECLS

View File

@ -68,8 +68,6 @@ GList *shell_global_get_windows (ShellGlobal *global);
void _shell_global_set_plugin (ShellGlobal *global, void _shell_global_set_plugin (ShellGlobal *global,
MutterPlugin *plugin); MutterPlugin *plugin);
MetaScreen * shell_global_get_screen (ShellGlobal *global);
gboolean shell_global_grab_keyboard (ShellGlobal *global); gboolean shell_global_grab_keyboard (ShellGlobal *global);
void shell_global_ungrab_keyboard (ShellGlobal *global); void shell_global_ungrab_keyboard (ShellGlobal *global);