[libwnck/wip/muktupavels/wnck-handle: 6/10] screen: move screen handling to WnckHandle
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libwnck/wip/muktupavels/wnck-handle: 6/10] screen: move screen handling to WnckHandle
- Date: Thu, 16 Sep 2021 15:29:53 +0000 (UTC)
commit efbab521a4aa59e46484ff5aa7abb0143818aeaf
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Mon Aug 19 21:41:48 2019 +0300
screen: move screen handling to WnckHandle
Deprecate old functions and update libwnck to use new functions.
libwnck/pager.c | 26 +-
libwnck/pager.h | 3 +
libwnck/private.h | 10 +-
libwnck/screen.c | 112 +------
libwnck/screen.h | 5 +
libwnck/selector.c | 26 +-
libwnck/selector.h | 10 +-
libwnck/tasklist.c | 50 ++-
libwnck/tasklist.h | 3 +
libwnck/util.c | 548 +------------------------------
libwnck/util.h | 2 +
libwnck/window.c | 5 +-
libwnck/wnck-handle-private.h | 9 +-
libwnck/wnck-handle.c | 738 +++++++++++++++++++++++++++++++++++++++++-
libwnck/wnck-handle.h | 29 +-
15 files changed, 898 insertions(+), 678 deletions(-)
---
diff --git a/libwnck/pager.c b/libwnck/pager.c
index c769d62..dad5307 100644
--- a/libwnck/pager.c
+++ b/libwnck/pager.c
@@ -61,6 +61,8 @@
struct _WnckPagerPrivate
{
+ WnckHandle *handle;
+
WnckScreen *screen;
int n_rows; /* really columns for vertical orientation */
@@ -296,7 +298,8 @@ _wnck_pager_set_screen (WnckPager *pager)
return;
gdkscreen = gtk_widget_get_screen (GTK_WIDGET (pager));
- pager->priv->screen = wnck_screen_get (gdk_x11_screen_get_screen_number (gdkscreen));
+ pager->priv->screen = wnck_handle_get_screen (pager->priv->handle,
+ gdk_x11_screen_get_screen_number (gdkscreen));
if (!wnck_pager_set_layout_hint (pager))
{
@@ -2194,6 +2197,27 @@ wnck_pager_new (void)
WnckPager *pager;
pager = g_object_new (WNCK_TYPE_PAGER, NULL);
+ pager->priv->handle = _wnck_get_handle ();
+
+ return GTK_WIDGET (pager);
+}
+
+/**
+ * wnck_pager_new_with_handle:
+ * @handle: a #WnckHandle
+ *
+ * Creates a new #WnckPager. The #WnckPager will show the #WnckWorkspace of the
+ * #WnckScreen it is on.
+ *
+ * Returns: a newly created #WnckPager.
+ */
+GtkWidget *
+wnck_pager_new_with_handle (WnckHandle *handle)
+{
+ WnckPager *pager;
+
+ pager = g_object_new (WNCK_TYPE_PAGER, NULL);
+ pager->priv->handle = handle;
return GTK_WIDGET (pager);
}
diff --git a/libwnck/pager.h b/libwnck/pager.h
index c67f2fa..084aeb4 100644
--- a/libwnck/pager.h
+++ b/libwnck/pager.h
@@ -102,8 +102,11 @@ typedef enum {
GType wnck_pager_get_type (void) G_GNUC_CONST;
+G_DEPRECATED_FOR(wnck_pager_new_with_handle)
GtkWidget* wnck_pager_new (void);
+GtkWidget* wnck_pager_new_with_handle (WnckHandle *handle);
+
gboolean wnck_pager_set_orientation (WnckPager *pager,
GtkOrientation orientation);
gboolean wnck_pager_set_n_rows (WnckPager *pager,
diff --git a/libwnck/private.h b/libwnck/private.h
index 8404d8f..887455b 100644
--- a/libwnck/private.h
+++ b/libwnck/private.h
@@ -108,8 +108,6 @@ void _wnck_screen_change_workspace_name (WnckScreen *screen,
int number,
const char *name);
-void _wnck_screen_shutdown_all (void);
-
gboolean _wnck_workspace_set_geometry (WnckWorkspace *space, int w, int h);
gboolean _wnck_workspace_set_viewport (WnckWorkspace *space, int x, int y);
@@ -118,6 +116,12 @@ Display *_wnck_get_default_display (void);
#define WNCK_SCREEN_XSCREEN(screen) (_wnck_screen_get_xscreen (screen))
+void _wnck_screen_construct (WnckScreen *screen,
+ WnckHandle *handle,
+ Display *display,
+ int number);
+
+Window _wnck_screen_get_xroot (WnckScreen *screen);
Screen *_wnck_screen_get_xscreen (WnckScreen *screen);
GdkScreen *_wnck_screen_get_gdk_screen (WnckScreen *screen);
@@ -125,8 +129,6 @@ GdkScreen *_wnck_screen_get_gdk_screen (WnckScreen *screen);
SnDisplay* _wnck_screen_get_sn_display (WnckScreen *screen);
#endif
-WnckScreen* _wnck_screen_get_existing (int number);
-
void _wnck_pager_activate_workspace (WnckWorkspace *wspace,
guint32 timestamp);
int _wnck_pager_get_n_workspaces (WnckPager *pager);
diff --git a/libwnck/screen.c b/libwnck/screen.c
index e6364eb..f12e065 100644
--- a/libwnck/screen.c
+++ b/libwnck/screen.c
@@ -65,8 +65,6 @@
#define _NET_WM_BOTTOMRIGHT 2
#define _NET_WM_BOTTOMLEFT 3
-static WnckScreen** screens = NULL;
-
struct _WnckScreenPrivate
{
WnckHandle *handle;
@@ -500,8 +498,6 @@ wnck_screen_finalize (GObject *object)
g_free (screen->priv->wm_name);
screen->priv->wm_name = NULL;
- screens[screen->priv->number] = NULL;
-
#ifdef HAVE_STARTUP_NOTIFICATION
sn_display_unref (screen->priv->sn_display);
screen->priv->sn_display = NULL;
@@ -526,12 +522,13 @@ sn_error_trap_pop (SnDisplay *display,
}
#endif /* HAVE_STARTUP_NOTIFICATION */
-static void
-wnck_screen_construct (Display *display,
- WnckScreen *screen,
- int number)
+void
+_wnck_screen_construct (WnckScreen *screen,
+ WnckHandle *handle,
+ Display *display,
+ int number)
{
- screen->priv->handle = _wnck_get_handle ();
+ screen->priv->handle = handle;
/* Create the initial state of the screen. */
screen->priv->xroot = RootWindow (display, number);
@@ -578,44 +575,7 @@ wnck_screen_construct (Display *display,
WnckScreen*
wnck_screen_get (int index)
{
- Display *display;
-
- display = _wnck_get_default_display ();
-
- g_return_val_if_fail (display != NULL, NULL);
-
- if (index >= ScreenCount (display))
- return NULL;
-
- if (screens == NULL)
- {
- screens = g_new0 (WnckScreen*, ScreenCount (display));
- }
-
- if (screens[index] == NULL)
- {
- screens[index] = g_object_new (WNCK_TYPE_SCREEN, NULL);
-
- wnck_screen_construct (display, screens[index], index);
- }
-
- return screens[index];
-}
-
-WnckScreen*
-_wnck_screen_get_existing (int number)
-{
- Display *display;
-
- display = _wnck_get_default_display ();
-
- g_return_val_if_fail (display != NULL, NULL);
- g_return_val_if_fail (number < ScreenCount (display), NULL);
-
- if (screens != NULL)
- return screens[number];
- else
- return NULL;
+ return wnck_handle_get_screen (_wnck_get_handle (), index);
}
/**
@@ -630,15 +590,7 @@ _wnck_screen_get_existing (int number)
WnckScreen*
wnck_screen_get_default (void)
{
- int default_screen;
- Display *default_display = _wnck_get_default_display ();
-
- if (default_display == NULL)
- return NULL;
-
- default_screen = DefaultScreen (default_display);
-
- return wnck_screen_get (default_screen);
+ return wnck_handle_get_default_screen (_wnck_get_handle ());
}
/**
@@ -658,24 +610,7 @@ wnck_screen_get_default (void)
WnckScreen*
wnck_screen_get_for_root (gulong root_window_id)
{
- int i;
- Display *display;
-
- if (screens == NULL)
- return NULL;
-
- i = 0;
- display = _wnck_get_default_display ();
-
- while (i < ScreenCount (display))
- {
- if (screens[i] != NULL && screens[i]->priv->xroot == root_window_id)
- return screens[i];
-
- ++i;
- }
-
- return NULL;
+ return wnck_handle_get_screen_for_root (_wnck_get_handle (), root_window_id);
}
/**
@@ -2502,6 +2437,12 @@ wnck_screen_get_height (WnckScreen *screen)
return HeightOfScreen (screen->priv->xscreen);
}
+Window
+_wnck_screen_get_xroot (WnckScreen *screen)
+{
+ return screen->priv->xroot;
+}
+
Screen *
_wnck_screen_get_xscreen (WnckScreen *screen)
{
@@ -2732,26 +2673,3 @@ _wnck_screen_change_workspace_name (WnckScreen *screen,
g_free (names);
}
-
-void
-_wnck_screen_shutdown_all (void)
-{
- int i;
- Display *display;
-
- if (screens == NULL)
- return;
-
- display = _wnck_get_default_display ();
-
- for (i = 0; i < ScreenCount (display); ++i)
- {
- if (screens[i] != NULL) {
- g_object_unref (screens[i]);
- screens[i] = NULL;
- }
- }
-
- g_free (screens);
- screens = NULL;
-}
diff --git a/libwnck/screen.h b/libwnck/screen.h
index 153cf5f..9fca17b 100644
--- a/libwnck/screen.h
+++ b/libwnck/screen.h
@@ -194,8 +194,13 @@ typedef enum
GType wnck_screen_get_type (void) G_GNUC_CONST;
+G_DEPRECATED_FOR(wnck_handle_get_default_screen)
WnckScreen* wnck_screen_get_default (void);
+
+G_DEPRECATED_FOR(wnck_handle_get_screen)
WnckScreen* wnck_screen_get (int index);
+
+G_DEPRECATED_FOR(wnck_handle_get_screen_for_root)
WnckScreen* wnck_screen_get_for_root (gulong root_window_id);
WnckHandle* wnck_screen_get_handle (WnckScreen *screen);
diff --git a/libwnck/selector.c b/libwnck/selector.c
index b975b27..ea686d1 100644
--- a/libwnck/selector.c
+++ b/libwnck/selector.c
@@ -52,6 +52,8 @@
*/
struct _WnckSelectorPrivate {
+ WnckHandle *handle;
+
GtkWidget *image;
WnckWindow *icon_window;
@@ -118,7 +120,8 @@ wnck_selector_get_screen (WnckSelector *selector)
screen = gtk_widget_get_screen (GTK_WIDGET (selector));
- return wnck_screen_get (gdk_x11_screen_get_screen_number (screen));
+ return wnck_handle_get_screen (selector->priv->handle,
+ gdk_x11_screen_get_screen_number (screen));
}
static GdkPixbuf *
@@ -1273,6 +1276,27 @@ wnck_selector_new (void)
WnckSelector *selector;
selector = g_object_new (WNCK_TYPE_SELECTOR, NULL);
+ selector->priv->handle = _wnck_get_handle ();
+
+ return GTK_WIDGET (selector);
+}
+
+/**
+ * wnck_selector_new_with_handle:
+ * @handle: a #WnckHandle
+ *
+ * Creates a new #WnckSelector. The #WnckSelector will list #WnckWindow of the
+ * #WnckScreen it is on.
+ *
+ * Returns: a newly created #WnckSelector.
+ */
+GtkWidget *
+wnck_selector_new_with_handle (WnckHandle *handle)
+{
+ WnckSelector *selector;
+
+ selector = g_object_new (WNCK_TYPE_SELECTOR, NULL);
+ selector->priv->handle = handle;
return GTK_WIDGET (selector);
}
diff --git a/libwnck/selector.h b/libwnck/selector.h
index 4783162..c793f42 100644
--- a/libwnck/selector.h
+++ b/libwnck/selector.h
@@ -27,6 +27,7 @@
#define WNCK_SELECTOR_H
#include <gtk/gtk.h>
+#include <libwnck/wnck-handle.h>
G_BEGIN_DECLS
#define WNCK_TYPE_SELECTOR (wnck_selector_get_type ())
@@ -62,8 +63,13 @@ struct _WnckSelectorClass
void (* pad4) (void);
};
-GtkWidget *wnck_selector_new (void);
-GType wnck_selector_get_type (void) G_GNUC_CONST;
+
+G_DEPRECATED_FOR(wnck_selector_new_with_handle)
+GtkWidget *wnck_selector_new (void);
+
+GtkWidget *wnck_selector_new_with_handle (WnckHandle *handle);
+
+GType wnck_selector_get_type (void) G_GNUC_CONST;
G_END_DECLS
diff --git a/libwnck/tasklist.c b/libwnck/tasklist.c
index 4166d76..d298597 100644
--- a/libwnck/tasklist.c
+++ b/libwnck/tasklist.c
@@ -189,6 +189,8 @@ typedef struct _skipped_window
struct _WnckTasklistPrivate
{
+ WnckHandle *handle;
+
WnckScreen *screen;
WnckTask *active_task; /* NULL if active window not in tasklist */
@@ -1816,12 +1818,9 @@ get_preferred_size (WnckTasklist *self,
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
- WnckHandle *handle;
int min_button_width;
- handle = wnck_screen_get_handle (self->priv->screen);
-
- get_minimum_button_size (handle, &min_button_width, NULL);
+ get_minimum_button_size (self->priv->handle, &min_button_width, NULL);
if (self->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
@@ -2160,7 +2159,8 @@ wnck_tasklist_realize (GtkWidget *widget)
tasklist = WNCK_TASKLIST (widget);
gdkscreen = gtk_widget_get_screen (widget);
- tasklist->priv->screen = wnck_screen_get (gdk_x11_screen_get_screen_number (gdkscreen));
+ tasklist->priv->screen = wnck_handle_get_screen (tasklist->priv->handle,
+ gdk_x11_screen_get_screen_number (gdkscreen));
g_assert (tasklist->priv->screen != NULL);
#ifdef HAVE_STARTUP_NOTIFICATION
@@ -2555,10 +2555,31 @@ wnck_tasklist_new (void)
WnckTasklist *tasklist;
tasklist = g_object_new (WNCK_TYPE_TASKLIST, NULL);
+ tasklist->priv->handle = _wnck_get_handle ();
return GTK_WIDGET (tasklist);
}
+/**
+ * wnck_tasklist_new_with_handle:
+ * @handle: a #WnckHandle
+ *
+ * Creates a new #WnckTasklist. The #WnckTasklist will list #WnckWindow of the
+ * #WnckScreen it is on.
+ *
+ * Returns: a newly created #WnckTasklist.
+ */
+GtkWidget *
+wnck_tasklist_new_with_handle (WnckHandle *handle)
+{
+ WnckTasklist *self;
+
+ self = g_object_new (WNCK_TYPE_TASKLIST, NULL);
+ self->priv->handle = handle;
+
+ return GTK_WIDGET (self);
+}
+
static void
wnck_tasklist_free_tasks (WnckTasklist *tasklist)
{
@@ -3683,17 +3704,15 @@ wnck_task_scale_icon (WnckHandle *handle,
static GdkPixbuf *
wnck_task_get_icon (WnckTask *task)
{
- WnckHandle *handle;
WnckWindowState state;
GdkPixbuf *pixbuf;
- handle = wnck_screen_get_handle (task->tasklist->priv->screen);
pixbuf = NULL;
switch (task->type)
{
case WNCK_TASK_CLASS_GROUP:
- pixbuf = wnck_task_scale_icon (handle,
+ pixbuf = wnck_task_scale_icon (task->tasklist->priv->handle,
wnck_class_group_get_mini_icon (task->class_group),
FALSE);
break;
@@ -3701,7 +3720,7 @@ wnck_task_get_icon (WnckTask *task)
case WNCK_TASK_WINDOW:
state = wnck_window_get_state (task->window);
- pixbuf = wnck_task_scale_icon (handle,
+ pixbuf = wnck_task_scale_icon (task->tasklist->priv->handle,
wnck_window_get_mini_icon (task->window),
state & WNCK_WINDOW_STATE_MINIMIZED);
break;
@@ -3718,7 +3737,7 @@ wnck_task_get_icon (WnckTask *task)
gsize mini_icon_size;
GdkPixbuf *loaded;
- mini_icon_size = _wnck_handle_get_default_mini_icon_size (handle);
+ mini_icon_size = _wnck_handle_get_default_mini_icon_size (task->tasklist->priv->handle);
loaded = (* task->tasklist->priv->icon_loader) (icon,
mini_icon_size,
@@ -3727,7 +3746,7 @@ wnck_task_get_icon (WnckTask *task)
if (loaded != NULL)
{
- pixbuf = wnck_task_scale_icon (handle, loaded, FALSE);
+ pixbuf = wnck_task_scale_icon (task->tasklist->priv->handle, loaded, FALSE);
g_object_unref (G_OBJECT (loaded));
}
}
@@ -3737,7 +3756,7 @@ wnck_task_get_icon (WnckTask *task)
{
gsize mini_icon_size;
- mini_icon_size = _wnck_handle_get_default_mini_icon_size (handle);
+ mini_icon_size = _wnck_handle_get_default_mini_icon_size (task->tasklist->priv->handle);
_wnck_get_fallback_icons (NULL, 0, &pixbuf, mini_icon_size);
}
@@ -3933,6 +3952,7 @@ static gboolean
wnck_task_motion_timeout (gpointer data)
{
WnckWorkspace *ws;
+ WnckScreen *screen;
WnckTask *task = WNCK_TASK (data);
task->button_activate = 0;
@@ -3942,7 +3962,9 @@ wnck_task_motion_timeout (gpointer data)
* There should only be *one* activate call.
*/
ws = wnck_window_get_workspace (task->window);
- if (ws && ws != wnck_screen_get_active_workspace (wnck_screen_get_default ()))
+ screen = wnck_handle_get_default_screen (task->tasklist->priv->handle);
+
+ if (ws && ws != wnck_screen_get_active_workspace (screen))
{
wnck_workspace_activate (ws, task->dnd_timestamp);
}
@@ -4281,7 +4303,7 @@ wnck_task_create_widgets (WnckTask *task, GtkReliefStyle relief)
task->button = wnck_button_new ();
wnck_button_set_handle (WNCK_BUTTON (task->button),
- wnck_screen_get_handle (task->tasklist->priv->screen));
+ task->tasklist->priv->handle);
gtk_button_set_relief (GTK_BUTTON (task->button), relief);
diff --git a/libwnck/tasklist.h b/libwnck/tasklist.h
index 0659f9d..5407d34 100644
--- a/libwnck/tasklist.h
+++ b/libwnck/tasklist.h
@@ -87,8 +87,11 @@ typedef enum {
GType wnck_tasklist_get_type (void) G_GNUC_CONST;
+G_DEPRECATED_FOR(wnck_tasklist_new_with_handle)
GtkWidget *wnck_tasklist_new (void);
+GtkWidget *wnck_tasklist_new_with_handle (WnckHandle *handle);
+
G_DEPRECATED
const int *wnck_tasklist_get_size_hint_list (WnckTasklist *tasklist,
int *n_elements);
diff --git a/libwnck/util.c b/libwnck/util.c
index 51e75ba..cd742f4 100644
--- a/libwnck/util.c
+++ b/libwnck/util.c
@@ -25,11 +25,9 @@
#include "util.h"
#include "xutils.h"
#include "private.h"
+#include "wnck-handle-private.h"
#include <gdk/gdkx.h>
#include <string.h>
-#ifdef HAVE_XRES
-#include <X11/extensions/XRes.h>
-#endif
/**
* SECTION:resource
@@ -60,81 +58,6 @@
* #WnckApplication.
*/
-typedef enum
-{
- WNCK_EXT_UNKNOWN = 0,
- WNCK_EXT_FOUND = 1,
- WNCK_EXT_MISSING = 2
-} WnckExtStatus;
-
-
-#if 0
-/* useful for debugging */
-static void
-_wnck_print_resource_usage (WnckResourceUsage *usage)
-{
- if (!usage)
- return;
-
- g_print ("\twindows : %d\n"
- "\tGCs : %d\n"
- "\tfonts : %d\n"
- "\tpixmaps : %d\n"
- "\tpictures : %d\n"
- "\tglyphsets : %d\n"
- "\tcolormaps : %d\n"
- "\tpassive grabs : %d\n"
- "\tcursors : %d\n"
- "\tunknowns : %d\n"
- "\tpixmap bytes : %ld\n"
- "\ttotal bytes : ~%ld\n",
- usage->n_windows,
- usage->n_gcs,
- usage->n_fonts,
- usage->n_pixmaps,
- usage->n_pictures,
- usage->n_glyphsets,
- usage->n_colormap_entries,
- usage->n_passive_grabs,
- usage->n_cursors,
- usage->n_other,
- usage->pixmap_bytes,
- usage->total_bytes_estimate);
-}
-#endif
-
-static WnckExtStatus
-wnck_init_resource_usage (GdkDisplay *gdisplay)
-{
- WnckExtStatus status;
-
- status = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (gdisplay),
- "wnck-xres-status"));
-
- if (status == WNCK_EXT_UNKNOWN)
- {
-#ifdef HAVE_XRES
- Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdisplay);
- int event, error;
-
- if (!XResQueryExtension (xdisplay, &event, &error))
- status = WNCK_EXT_MISSING;
- else
- status = WNCK_EXT_FOUND;
-#else
- status = WNCK_EXT_MISSING;
-#endif
-
- g_object_set_data (G_OBJECT (gdisplay),
- "wnck-xres-status",
- GINT_TO_POINTER (status));
- }
-
- g_assert (status != WNCK_EXT_UNKNOWN);
-
- return status;
-}
-
/**
* wnck_xid_read_resource_usage:
* @gdk_display: a <classname>GdkDisplay</classname>.
@@ -151,434 +74,13 @@ wnck_init_resource_usage (GdkDisplay *gdisplay)
* Since: 2.6
*/
void
-wnck_xid_read_resource_usage (GdkDisplay *gdisplay,
+wnck_xid_read_resource_usage (GdkDisplay *gdk_display,
gulong xid,
WnckResourceUsage *usage)
{
- g_return_if_fail (usage != NULL);
-
- memset (usage, '\0', sizeof (*usage));
-
- if (wnck_init_resource_usage (gdisplay) == WNCK_EXT_MISSING)
- return;
-
-#ifdef HAVE_XRES
- {
- Display *xdisplay;
- XResType *types;
- int n_types;
- unsigned long pixmap_bytes;
- int i;
- Atom pixmap_atom;
- Atom window_atom;
- Atom gc_atom;
- Atom picture_atom;
- Atom glyphset_atom;
- Atom font_atom;
- Atom colormap_entry_atom;
- Atom passive_grab_atom;
- Atom cursor_atom;
-
- types = NULL;
- n_types = 0;
- pixmap_bytes = 0;
-
- xdisplay = GDK_DISPLAY_XDISPLAY (gdisplay);
-
- _wnck_error_trap_push (xdisplay);
-
- XResQueryClientResources (xdisplay,
- xid, &n_types,
- &types);
-
- XResQueryClientPixmapBytes (xdisplay,
- xid, &pixmap_bytes);
- _wnck_error_trap_pop (xdisplay);
-
- usage->pixmap_bytes = pixmap_bytes;
-
- pixmap_atom = _wnck_atom_get ("PIXMAP");
- window_atom = _wnck_atom_get ("WINDOW");
- gc_atom = _wnck_atom_get ("GC");
- font_atom = _wnck_atom_get ("FONT");
- glyphset_atom = _wnck_atom_get ("GLYPHSET");
- picture_atom = _wnck_atom_get ("PICTURE");
- colormap_entry_atom = _wnck_atom_get ("COLORMAP ENTRY");
- passive_grab_atom = _wnck_atom_get ("PASSIVE GRAB");
- cursor_atom = _wnck_atom_get ("CURSOR");
-
- i = 0;
- while (i < n_types)
- {
- guint t = types[i].resource_type;
-
- if (t == pixmap_atom)
- usage->n_pixmaps += types[i].count;
- else if (t == window_atom)
- usage->n_windows += types[i].count;
- else if (t == gc_atom)
- usage->n_gcs += types[i].count;
- else if (t == picture_atom)
- usage->n_pictures += types[i].count;
- else if (t == glyphset_atom)
- usage->n_glyphsets += types[i].count;
- else if (t == font_atom)
- usage->n_fonts += types[i].count;
- else if (t == colormap_entry_atom)
- usage->n_colormap_entries += types[i].count;
- else if (t == passive_grab_atom)
- usage->n_passive_grabs += types[i].count;
- else if (t == cursor_atom)
- usage->n_cursors += types[i].count;
- else
- usage->n_other += types[i].count;
-
- ++i;
- }
-
- XFree(types);
-
- usage->total_bytes_estimate = usage->pixmap_bytes;
-
- /* FIXME look in the X server source and come up with better
- * answers here. Ideally we change XRes to return a number
- * like this since it can do things like divide the cost of
- * a shared resource among those sharing it.
- */
- usage->total_bytes_estimate += usage->n_windows * 24;
- usage->total_bytes_estimate += usage->n_gcs * 24;
- usage->total_bytes_estimate += usage->n_pictures * 24;
- usage->total_bytes_estimate += usage->n_glyphsets * 24;
- usage->total_bytes_estimate += usage->n_fonts * 1024;
- usage->total_bytes_estimate += usage->n_colormap_entries * 24;
- usage->total_bytes_estimate += usage->n_passive_grabs * 24;
- usage->total_bytes_estimate += usage->n_cursors * 24;
- usage->total_bytes_estimate += usage->n_other * 24;
- }
-#else /* HAVE_XRES */
- g_assert_not_reached ();
-#endif /* HAVE_XRES */
-}
-
-#ifdef HAVE_XRES
-static void
-wnck_pid_read_resource_usage_free_hash (gpointer data)
-{
- g_slice_free (gulong, data);
-}
-
-static guint
-wnck_gulong_hash (gconstpointer v)
-{
- /* FIXME: this is obvioulsy wrong, but nearly 100% of the time, the gulong
- * only contains guint values */
- return *(const guint *) v;
-}
-
-static gboolean
-wnck_gulong_equal (gconstpointer a,
- gconstpointer b)
-{
- return *((const gulong *) a) == *((const gulong *) b);
-}
-
-static gulong
-wnck_check_window_for_pid (Screen *screen,
- Window win,
- XID match_xid,
- XID mask)
-{
- if ((win & ~mask) == match_xid) {
- return _wnck_get_pid (screen, win);
- }
-
- return 0;
-}
-
-static void
-wnck_find_pid_for_resource_r (Display *xdisplay,
- Screen *screen,
- Window win_top,
- XID match_xid,
- XID mask,
- gulong *xid,
- gulong *pid)
-{
- Status qtres;
- int err;
- Window dummy;
- Window *children;
- guint n_children;
- guint i;
- gulong found_pid = 0;
-
- while (gtk_events_pending ())
- gtk_main_iteration ();
-
- found_pid = wnck_check_window_for_pid (screen, win_top, match_xid, mask);
- if (found_pid != 0)
- {
- *xid = win_top;
- *pid = found_pid;
- }
-
- _wnck_error_trap_push (xdisplay);
- qtres = XQueryTree (xdisplay, win_top, &dummy, &dummy,
- &children, &n_children);
- err = _wnck_error_trap_pop (xdisplay);
-
- if (!qtres || err != Success)
- return;
-
- for (i = 0; i < n_children; i++)
- {
- wnck_find_pid_for_resource_r (xdisplay, screen, children[i],
- match_xid, mask, xid, pid);
-
- if (*pid != 0)
- break;
- }
-
- if (children)
- XFree ((char *)children);
-}
-
-struct xresclient_state
-{
- XResClient *clients;
- int n_clients;
- int next;
- Display *xdisplay;
- GHashTable *hashtable_pid;
-};
-
-static struct xresclient_state xres_state = { NULL, 0, -1, NULL, NULL };
-static guint xres_idleid = 0;
-static GHashTable *xres_hashtable = NULL;
-static time_t start_update = 0;
-static time_t end_update = 0;
-static guint xres_removeid = 0;
-
-static void
-wnck_pid_read_resource_usage_xres_state_free (gpointer data)
-{
- struct xresclient_state *state;
-
- state = (struct xresclient_state *) data;
-
- if (state->clients)
- XFree (state->clients);
- state->clients = NULL;
-
- state->n_clients = 0;
- state->next = -1;
- state->xdisplay = NULL;
-
- if (state->hashtable_pid)
- g_hash_table_destroy (state->hashtable_pid);
- state->hashtable_pid = NULL;
+ wnck_handle_read_resource_usage_xid (_wnck_get_handle (), gdk_display, xid, usage);
}
-static gboolean
-wnck_pid_read_resource_usage_fill_cache (struct xresclient_state *state)
-{
- int i;
- gulong pid;
- gulong xid;
- XID match_xid;
-
- if (state->next >= state->n_clients)
- {
- if (xres_hashtable)
- g_hash_table_destroy (xres_hashtable);
- xres_hashtable = state->hashtable_pid;
- state->hashtable_pid = NULL;
-
- time (&end_update);
-
- xres_idleid = 0;
- return FALSE;
- }
-
- match_xid = (state->clients[state->next].resource_base &
- ~state->clients[state->next].resource_mask);
-
- pid = 0;
- xid = 0;
-
- for (i = 0; i < ScreenCount (state->xdisplay); i++)
- {
- Screen *screen;
- Window root;
-
- screen = ScreenOfDisplay (state->xdisplay, i);
- root = RootWindow (state->xdisplay, i);
-
- if (root == None)
- continue;
-
- wnck_find_pid_for_resource_r (state->xdisplay, screen, root, match_xid,
- state->clients[state->next].resource_mask,
- &xid, &pid);
-
- if (pid != 0 && xid != 0)
- break;
- }
-
- if (pid != 0 && xid != 0)
- {
- gulong *key;
- gulong *value;
-
- key = g_slice_new (gulong);
- value = g_slice_new (gulong);
- *key = pid;
- *value = xid;
- g_hash_table_insert (state->hashtable_pid, key, value);
- }
-
- state->next++;
-
- return TRUE;
-}
-
-static void
-wnck_pid_read_resource_usage_start_build_cache (GdkDisplay *gdisplay)
-{
- Display *xdisplay;
- int err;
-
- if (xres_idleid != 0)
- return;
-
- time (&start_update);
-
- xdisplay = GDK_DISPLAY_XDISPLAY (gdisplay);
-
- _wnck_error_trap_push (xdisplay);
- XResQueryClients (xdisplay, &xres_state.n_clients, &xres_state.clients);
- err = _wnck_error_trap_pop (xdisplay);
-
- if (err != Success)
- return;
-
- xres_state.next = (xres_state.n_clients > 0) ? 0 : -1;
- xres_state.xdisplay = xdisplay;
- xres_state.hashtable_pid = g_hash_table_new_full (
- wnck_gulong_hash,
- wnck_gulong_equal,
- wnck_pid_read_resource_usage_free_hash,
- wnck_pid_read_resource_usage_free_hash);
-
- xres_idleid = g_idle_add_full (
- G_PRIORITY_HIGH_IDLE,
- (GSourceFunc) wnck_pid_read_resource_usage_fill_cache,
- &xres_state, wnck_pid_read_resource_usage_xres_state_free);
-}
-
-static gboolean
-wnck_pid_read_resource_usage_destroy_hash_table (gpointer data)
-{
- xres_removeid = 0;
-
- if (xres_hashtable)
- g_hash_table_destroy (xres_hashtable);
-
- xres_hashtable = NULL;
-
- return FALSE;
-}
-
-#define XRES_UPDATE_RATE_SEC 30
-static gboolean
-wnck_pid_read_resource_usage_from_cache (GdkDisplay *gdisplay,
- gulong pid,
- WnckResourceUsage *usage)
-{
- gboolean need_rebuild;
- gulong *xid_p;
- int cache_validity;
-
- if (end_update == 0)
- time (&end_update);
-
- cache_validity = MAX (XRES_UPDATE_RATE_SEC, (end_update - start_update) * 2);
-
- /* we rebuild the cache if it was never built or if it's old */
- need_rebuild = (xres_hashtable == NULL ||
- (end_update < time (NULL) - cache_validity));
-
- if (xres_hashtable)
- {
- /* clear the cache after quite some time, because it might not be used
- * anymore */
- if (xres_removeid != 0)
- g_source_remove (xres_removeid);
- xres_removeid = g_timeout_add_seconds (cache_validity * 2,
- wnck_pid_read_resource_usage_destroy_hash_table,
- NULL);
- }
-
- if (need_rebuild)
- wnck_pid_read_resource_usage_start_build_cache (gdisplay);
-
- if (xres_hashtable)
- xid_p = g_hash_table_lookup (xres_hashtable, &pid);
- else
- xid_p = NULL;
-
- if (xid_p)
- {
- wnck_xid_read_resource_usage (gdisplay, *xid_p, usage);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-wnck_pid_read_resource_usage_no_cache (GdkDisplay *gdisplay,
- gulong pid,
- WnckResourceUsage *usage)
-{
- Display *xdisplay;
- int i;
-
- xdisplay = GDK_DISPLAY_XDISPLAY (gdisplay);
-
- i = 0;
- while (i < ScreenCount (xdisplay))
- {
- WnckScreen *screen;
- GList *windows;
- GList *tmp;
-
- screen = wnck_screen_get (i);
-
- g_assert (screen != NULL);
-
- windows = wnck_screen_get_windows (screen);
- tmp = windows;
- while (tmp != NULL)
- {
- if (wnck_window_get_pid (tmp->data) == (int) pid)
- {
- wnck_xid_read_resource_usage (gdisplay,
- wnck_window_get_xid (tmp->data),
- usage);
-
- /* stop on first window found */
- return;
- }
-
- tmp = tmp->next;
- }
-
- ++i;
- }
-}
-#endif /* HAVE_XRES */
-
/**
* wnck_pid_read_resource_usage:
* @gdk_display: a <classname>GdkDisplay</classname>.
@@ -604,23 +106,11 @@ wnck_pid_read_resource_usage_no_cache (GdkDisplay *gdisplay,
* Since: 2.6
*/
void
-wnck_pid_read_resource_usage (GdkDisplay *gdisplay,
+wnck_pid_read_resource_usage (GdkDisplay *gdk_display,
gulong pid,
WnckResourceUsage *usage)
{
- g_return_if_fail (usage != NULL);
-
- memset (usage, '\0', sizeof (*usage));
-
- if (wnck_init_resource_usage (gdisplay) == WNCK_EXT_MISSING)
- return;
-
-#ifdef HAVE_XRES
- if (!wnck_pid_read_resource_usage_from_cache (gdisplay, pid, usage))
- /* the cache might not be built, might be outdated or might not contain
- * data for a new X client, so try to fallback to something else */
- wnck_pid_read_resource_usage_no_cache (gdisplay, pid, usage);
-#endif /* HAVE_XRES */
+ wnck_handle_read_resource_usage_pid (_wnck_get_handle (), gdk_display, pid, usage);
}
static WnckClientType client_type = 0;
@@ -708,7 +198,8 @@ wnck_set_default_mini_icon_size (gsize size)
wnck_handle_set_default_mini_icon_size (_wnck_get_handle (), size);
default_screen = DefaultScreen (_wnck_get_default_display ());
- screen = _wnck_screen_get_existing (default_screen);
+ screen = _wnck_handle_get_existing_screen (_wnck_get_handle (),
+ default_screen);
if (WNCK_IS_SCREEN (screen))
{
@@ -815,32 +306,7 @@ _wnck_get_default_display (void)
void
wnck_shutdown (void)
{
- /* Warning: this is hacky :-)
- *
- * Shutting down all WnckScreen objects will automatically unreference (and
- * finalize) all WnckWindow objects, but not the WnckClassGroup and
- * WnckApplication objects.
- * Therefore we need to manually shut down all WnckClassGroup and
- * WnckApplication objects first, since they reference the WnckScreen they're
- * on.
- * On the other side, shutting down the WnckScreen objects will results in
- * all WnckWindow objects getting unreferenced and finalized, and must
- * actually be done before shutting down global WnckWindow structures
- * (because the WnckScreen has a list of WnckWindow that will get mis-used
- * otherwise). */
- _wnck_class_group_shutdown_all ();
- _wnck_application_shutdown_all ();
- _wnck_screen_shutdown_all ();
- _wnck_window_shutdown_all ();
-
g_clear_object (&wnck_handle);
-
-#ifdef HAVE_XRES
- if (xres_removeid != 0)
- g_source_remove (xres_removeid);
- xres_removeid = 0;
- wnck_pid_read_resource_usage_destroy_hash_table (NULL);
-#endif
}
void
diff --git a/libwnck/util.h b/libwnck/util.h
index 91a4e08..5e70127 100644
--- a/libwnck/util.h
+++ b/libwnck/util.h
@@ -114,10 +114,12 @@ void wnck_set_default_mini_icon_size (gsize size);
void wnck_shutdown (void);
+G_DEPRECATED_FOR(wnck_handle_read_resource_usage_xid)
void wnck_xid_read_resource_usage (GdkDisplay *gdk_display,
gulong xid,
WnckResourceUsage *usage);
+G_DEPRECATED_FOR(wnck_handle_read_resource_usage_pid)
void wnck_pid_read_resource_usage (GdkDisplay *gdk_display,
gulong pid,
WnckResourceUsage *usage);
diff --git a/libwnck/window.c b/libwnck/window.c
index 294f556..3098339 100644
--- a/libwnck/window.c
+++ b/libwnck/window.c
@@ -3105,9 +3105,12 @@ update_transient_for (WnckWindow *window)
&parent) &&
parent != window->priv->xwindow)
{
+ WnckHandle *handle;
+
window->priv->transient_for = parent;
- if (wnck_screen_get_for_root (window->priv->transient_for) != NULL)
+ handle = wnck_screen_get_handle (window->priv->screen);
+ if (wnck_handle_get_screen_for_root (handle, window->priv->transient_for) != NULL)
window->priv->transient_for_root = TRUE;
else
window->priv->transient_for_root = FALSE;
diff --git a/libwnck/wnck-handle-private.h b/libwnck/wnck-handle-private.h
index f77b4ba..c791560 100644
--- a/libwnck/wnck-handle-private.h
+++ b/libwnck/wnck-handle-private.h
@@ -23,11 +23,14 @@
G_BEGIN_DECLS
-WnckClientType _wnck_handle_get_client_type (WnckHandle *self);
+WnckClientType _wnck_handle_get_client_type (WnckHandle *self);
-gsize _wnck_handle_get_default_icon_size (WnckHandle *self);
+WnckScreen *_wnck_handle_get_existing_screen (WnckHandle *self,
+ int number);
-gsize _wnck_handle_get_default_mini_icon_size (WnckHandle *self);
+gsize _wnck_handle_get_default_icon_size (WnckHandle *self);
+
+gsize _wnck_handle_get_default_mini_icon_size (WnckHandle *self);
G_END_DECLS
diff --git a/libwnck/wnck-handle.c b/libwnck/wnck-handle.c
index 69438ae..9a7f565 100644
--- a/libwnck/wnck-handle.c
+++ b/libwnck/wnck-handle.c
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2001 Havoc Pennington
+ * Copyright (C) 2003 Kim Woelders
+ * Copyright (C) 2003 Red Hat, Inc.
* Copyright (C) 2005-2007 Vincent Untz
* Copyright (C) 2021 Alberts Muktupāvels
*
@@ -27,20 +29,53 @@
#include "config.h"
#include "wnck-handle-private.h"
+#include <gdk/gdkx.h>
+
+#ifdef HAVE_XRES
+#include <X11/extensions/XRes.h>
+#endif
+
#include "private.h"
#include "screen.h"
#include "window.h"
#include "wnck-enum-types.h"
#include "xutils.h"
+typedef struct
+{
+ WnckHandle *handle;
+
+ XResClient *clients;
+ int n_clients;
+ int next;
+ Display *xdisplay;
+ GHashTable *hashtable_pid;
+} xresclient_state;
+
+typedef enum
+{
+ WNCK_EXT_UNKNOWN = 0,
+ WNCK_EXT_FOUND = 1,
+ WNCK_EXT_MISSING = 2
+} WnckExtStatus;
+
struct _WnckHandle
{
- GObject parent;
+ GObject parent;
+
+ WnckScreen **screens;
- WnckClientType client_type;
+ WnckClientType client_type;
- gsize default_icon_size;
- gsize default_mini_icon_size;
+ gsize default_icon_size;
+ gsize default_mini_icon_size;
+
+ xresclient_state xres_state;
+ guint xres_idleid;
+ GHashTable *xres_hashtable;
+ time_t start_update;
+ time_t end_update;
+ guint xres_removeid;
};
enum
@@ -56,24 +91,373 @@ static GParamSpec *handle_properties[LAST_PROP] = { NULL };
G_DEFINE_TYPE (WnckHandle, wnck_handle, G_TYPE_OBJECT)
+static WnckExtStatus
+wnck_init_resource_usage (GdkDisplay *gdisplay)
+{
+ WnckExtStatus status;
+
+ status = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (gdisplay),
+ "wnck-xres-status"));
+
+ if (status == WNCK_EXT_UNKNOWN)
+ {
+#ifdef HAVE_XRES
+ Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdisplay);
+ int event, error;
+
+ if (!XResQueryExtension (xdisplay, &event, &error))
+ status = WNCK_EXT_MISSING;
+ else
+ status = WNCK_EXT_FOUND;
+#else
+ status = WNCK_EXT_MISSING;
+#endif
+
+ g_object_set_data (G_OBJECT (gdisplay),
+ "wnck-xres-status",
+ GINT_TO_POINTER (status));
+ }
+
+ g_assert (status != WNCK_EXT_UNKNOWN);
+
+ return status;
+}
+
+#ifdef HAVE_XRES
+static void
+wnck_pid_read_resource_usage_free_hash (gpointer data)
+{
+ g_slice_free (gulong, data);
+}
+
+static guint
+wnck_gulong_hash (gconstpointer v)
+{
+ /* FIXME: this is obvioulsy wrong, but nearly 100% of the time, the gulong
+ * only contains guint values */
+ return *(const guint *) v;
+}
+
+static gboolean
+wnck_gulong_equal (gconstpointer a,
+ gconstpointer b)
+{
+ return *((const gulong *) a) == *((const gulong *) b);
+}
+
+static gulong
+wnck_check_window_for_pid (Screen *screen,
+ Window win,
+ XID match_xid,
+ XID mask)
+{
+ if ((win & ~mask) == match_xid) {
+ return _wnck_get_pid (screen, win);
+ }
+
+ return 0;
+}
+
+static void
+wnck_find_pid_for_resource_r (Display *xdisplay,
+ Screen *screen,
+ Window win_top,
+ XID match_xid,
+ XID mask,
+ gulong *xid,
+ gulong *pid)
+{
+ Status qtres;
+ int err;
+ Window dummy;
+ Window *children;
+ guint n_children;
+ guint i;
+ gulong found_pid = 0;
+
+ while (gtk_events_pending ())
+ gtk_main_iteration ();
+
+ found_pid = wnck_check_window_for_pid (screen, win_top, match_xid, mask);
+ if (found_pid != 0)
+ {
+ *xid = win_top;
+ *pid = found_pid;
+ }
+
+ _wnck_error_trap_push (xdisplay);
+ qtres = XQueryTree (xdisplay, win_top, &dummy, &dummy,
+ &children, &n_children);
+ err = _wnck_error_trap_pop (xdisplay);
+
+ if (!qtres || err != Success)
+ return;
+
+ for (i = 0; i < n_children; i++)
+ {
+ wnck_find_pid_for_resource_r (xdisplay, screen, children[i],
+ match_xid, mask, xid, pid);
+
+ if (*pid != 0)
+ break;
+ }
+
+ if (children)
+ XFree ((char *)children);
+}
+
+static void
+wnck_pid_read_resource_usage_xres_state_free (gpointer data)
+{
+ xresclient_state *state;
+
+ state = (xresclient_state *) data;
+
+ if (state->clients)
+ XFree (state->clients);
+ state->clients = NULL;
+
+ state->n_clients = 0;
+ state->next = -1;
+ state->xdisplay = NULL;
+
+ if (state->hashtable_pid)
+ g_hash_table_destroy (state->hashtable_pid);
+ state->hashtable_pid = NULL;
+}
+
+static gboolean
+wnck_pid_read_resource_usage_fill_cache (xresclient_state *state)
+{
+ WnckHandle *self;
+ int i;
+ gulong pid;
+ gulong xid;
+ XID match_xid;
+
+ self = state->handle;
+
+ if (state->next >= state->n_clients)
+ {
+ if (self->xres_hashtable)
+ g_hash_table_destroy (self->xres_hashtable);
+ self->xres_hashtable = state->hashtable_pid;
+ state->hashtable_pid = NULL;
+
+ time (&self->end_update);
+
+ self->xres_idleid = 0;
+ return FALSE;
+ }
+
+ match_xid = (state->clients[state->next].resource_base &
+ ~state->clients[state->next].resource_mask);
+
+ pid = 0;
+ xid = 0;
+
+ for (i = 0; i < ScreenCount (state->xdisplay); i++)
+ {
+ Screen *screen;
+ Window root;
+
+ screen = ScreenOfDisplay (state->xdisplay, i);
+ root = RootWindow (state->xdisplay, i);
+
+ if (root == None)
+ continue;
+
+ wnck_find_pid_for_resource_r (state->xdisplay, screen, root, match_xid,
+ state->clients[state->next].resource_mask,
+ &xid, &pid);
+
+ if (pid != 0 && xid != 0)
+ break;
+ }
+
+ if (pid != 0 && xid != 0)
+ {
+ gulong *key;
+ gulong *value;
+
+ key = g_slice_new (gulong);
+ value = g_slice_new (gulong);
+ *key = pid;
+ *value = xid;
+ g_hash_table_insert (state->hashtable_pid, key, value);
+ }
+
+ state->next++;
+
+ return TRUE;
+}
+
+static void
+wnck_pid_read_resource_usage_start_build_cache (WnckHandle *self,
+ GdkDisplay *gdisplay)
+{
+ Display *xdisplay;
+ int err;
+
+ if (self->xres_idleid != 0)
+ return;
+
+ time (&self->start_update);
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdisplay);
+
+ _wnck_error_trap_push (xdisplay);
+ XResQueryClients (xdisplay, &self->xres_state.n_clients, &self->xres_state.clients);
+ err = _wnck_error_trap_pop (xdisplay);
+
+ if (err != Success)
+ return;
+
+ self->xres_state.next = (self->xres_state.n_clients > 0) ? 0 : -1;
+ self->xres_state.xdisplay = xdisplay;
+ self->xres_state.hashtable_pid = g_hash_table_new_full (wnck_gulong_hash,
+ wnck_gulong_equal,
+ wnck_pid_read_resource_usage_free_hash,
+ wnck_pid_read_resource_usage_free_hash);
+
+ self->xres_idleid = g_idle_add_full (G_PRIORITY_HIGH_IDLE,
+ (GSourceFunc) wnck_pid_read_resource_usage_fill_cache,
+ &self->xres_state,
+ wnck_pid_read_resource_usage_xres_state_free);
+}
+
+static gboolean
+wnck_pid_read_resource_usage_destroy_hash_table (gpointer data)
+{
+ WnckHandle *self;
+
+ self = WNCK_HANDLE (data);
+
+ self->xres_removeid = 0;
+
+ if (self->xres_hashtable)
+ {
+ g_hash_table_destroy (self->xres_hashtable);
+ self->xres_hashtable = NULL;
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+#define XRES_UPDATE_RATE_SEC 30
+static gboolean
+wnck_pid_read_resource_usage_from_cache (WnckHandle *self,
+ GdkDisplay *gdisplay,
+ gulong pid,
+ WnckResourceUsage *usage)
+{
+ gboolean need_rebuild;
+ gulong *xid_p;
+ int cache_validity;
+
+ if (self->end_update == 0)
+ time (&self->end_update);
+
+ cache_validity = MAX (XRES_UPDATE_RATE_SEC, (self->end_update - self->start_update) * 2);
+
+ /* we rebuild the cache if it was never built or if it's old */
+ need_rebuild = (self->xres_hashtable == NULL ||
+ (self->end_update < time (NULL) - cache_validity));
+
+ if (self->xres_hashtable)
+ {
+ /* clear the cache after quite some time, because it might not be used
+ * anymore */
+ if (self->xres_removeid != 0)
+ g_source_remove (self->xres_removeid);
+ self->xres_removeid = g_timeout_add_seconds (cache_validity * 2,
+ wnck_pid_read_resource_usage_destroy_hash_table,
+ self);
+ }
+
+ if (need_rebuild)
+ wnck_pid_read_resource_usage_start_build_cache (self, gdisplay);
+
+ if (self->xres_hashtable)
+ xid_p = g_hash_table_lookup (self->xres_hashtable, &pid);
+ else
+ xid_p = NULL;
+
+ if (xid_p)
+ {
+ wnck_handle_read_resource_usage_xid (self, gdisplay, *xid_p, usage);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+wnck_pid_read_resource_usage_no_cache (WnckHandle *self,
+ GdkDisplay *gdisplay,
+ gulong pid,
+ WnckResourceUsage *usage)
+{
+ Display *xdisplay;
+ int i;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdisplay);
+
+ i = 0;
+ while (i < ScreenCount (xdisplay))
+ {
+ WnckScreen *screen;
+ GList *windows;
+ GList *tmp;
+
+ screen = wnck_handle_get_screen (self, i);
+
+ g_assert (screen != NULL);
+
+ windows = wnck_screen_get_windows (screen);
+ tmp = windows;
+ while (tmp != NULL)
+ {
+ if (wnck_window_get_pid (tmp->data) == (int) pid)
+ {
+ wnck_handle_read_resource_usage_xid (self, gdisplay,
+ wnck_window_get_xid (tmp->data),
+ usage);
+
+ /* stop on first window found */
+ return;
+ }
+
+ tmp = tmp->next;
+ }
+
+ ++i;
+ }
+}
+#endif /* HAVE_XRES */
+
static GdkFilterReturn
filter_func (GdkXEvent *gdkxevent,
GdkEvent *event,
gpointer data)
{
+ WnckHandle *self;
XEvent *xevent = gdkxevent;
#ifdef HAVE_STARTUP_NOTIFICATION
int i;
Display *display;
#endif /* HAVE_STARTUP_NOTIFICATION */
+ self = WNCK_HANDLE (data);
+
switch (xevent->type)
{
case PropertyNotify:
{
WnckScreen *screen;
- screen = wnck_screen_get_for_root (xevent->xany.window);
+ screen = wnck_handle_get_screen_for_root (self, xevent->xany.window);
+
if (screen != NULL)
{
_wnck_screen_process_property_notify (screen, xevent);
@@ -122,11 +506,12 @@ filter_func (GdkXEvent *gdkxevent,
while (i < ScreenCount (display))
{
- WnckScreen *s;
+ WnckScreen *screen;
- s = _wnck_screen_get_existing (i);
- if (s != NULL)
- sn_display_process_event (_wnck_screen_get_sn_display (s),
+ screen = _wnck_handle_get_existing_screen (self, i);
+
+ if (screen != NULL)
+ sn_display_process_event (_wnck_screen_get_sn_display (screen),
xevent);
++i;
@@ -150,6 +535,44 @@ wnck_handle_finalize (GObject *object)
gdk_window_remove_filter (NULL, filter_func, self);
+ /* Warning: this is hacky :-)
+ *
+ * Shutting down all WnckScreen objects will automatically unreference (and
+ * finalize) all WnckWindow objects, but not the WnckClassGroup and
+ * WnckApplication objects.
+ * Therefore we need to manually shut down all WnckClassGroup and
+ * WnckApplication objects first, since they reference the WnckScreen they're
+ * on.
+ * On the other side, shutting down the WnckScreen objects will results in
+ * all WnckWindow objects getting unreferenced and finalized, and must
+ * actually be done before shutting down global WnckWindow structures
+ * (because the WnckScreen has a list of WnckWindow that will get mis-used
+ * otherwise). */
+ _wnck_class_group_shutdown_all ();
+ _wnck_application_shutdown_all ();
+ _wnck_window_shutdown_all ();
+
+ if (self->screens != NULL)
+ {
+ Display *display;
+ int i;
+
+ for (i = 0; i < ScreenCount (display); ++i)
+ g_clear_object (&self->screens[i]);
+
+ g_clear_pointer (&self->screens, g_free);
+ }
+
+#ifdef HAVE_XRES
+ if (self->xres_removeid != 0)
+ {
+ g_source_remove (self->xres_removeid);
+ self->xres_removeid = 0;
+ }
+
+ wnck_pid_read_resource_usage_destroy_hash_table (self);
+#endif
+
G_OBJECT_CLASS (wnck_handle_parent_class)->finalize (object);
}
@@ -234,6 +657,8 @@ wnck_handle_init (WnckHandle *self)
self->default_icon_size = WNCK_DEFAULT_ICON_SIZE;
self->default_mini_icon_size = WNCK_DEFAULT_MINI_ICON_SIZE;
+ self->xres_state = (xresclient_state) { self, NULL, 0, -1, NULL, NULL };
+
gdk_window_add_filter (NULL, filter_func, self);
}
@@ -259,6 +684,130 @@ _wnck_handle_get_client_type (WnckHandle *self)
return self->client_type;
}
+/**
+ * wnck_handle_get_default_screen:
+ * @self: a #WnckHandle
+ *
+ * Gets the default #WnckScreen on the default display.
+ *
+ * Returns: (transfer none) (nullable): the default #WnckScreen. The
+ * returned #WnckScreen is owned by #WnckHandle and must not be referenced
+ * or unreferenced. This can return %NULL if not on X11.
+ */
+WnckScreen *
+wnck_handle_get_default_screen (WnckHandle *self)
+{
+ Display *display;
+
+ g_return_val_if_fail (WNCK_IS_HANDLE (self), NULL);
+
+ display = _wnck_get_default_display ();
+ if (display == NULL)
+ return NULL;
+
+ return wnck_handle_get_screen (self, DefaultScreen (display));
+}
+
+/**
+ * wnck_handle_get_screen:
+ * @self: a #WnckHandle
+ * @index: screen number, starting from 0.
+ *
+ * Gets the #WnckScreen for a given screen on the default display.
+ *
+ * Returns: (transfer none): the #WnckScreen for screen @index, or %NULL
+ * if no such screen exists. The returned #WnckScreen is owned by #WnckHandle
+ * and must not be referenced or unreferenced.
+ */
+WnckScreen *
+wnck_handle_get_screen (WnckHandle *self,
+ int index)
+{
+ Display *display;
+
+ display = _wnck_get_default_display ();
+
+ g_return_val_if_fail (WNCK_IS_HANDLE (self), NULL);
+ g_return_val_if_fail (display != NULL, NULL);
+
+ if (index >= ScreenCount (display))
+ return NULL;
+
+ if (self->screens == NULL)
+ self->screens = g_new0 (WnckScreen*, ScreenCount (display));
+
+ if (self->screens[index] == NULL)
+ {
+ self->screens[index] = g_object_new (WNCK_TYPE_SCREEN, NULL);
+
+ _wnck_screen_construct (self->screens[index], self, display, index);
+ }
+
+ return self->screens[index];
+}
+
+/**
+ * wnck_handle_get_screen_for_root:
+ * @self: a #WnckHandle
+ * @root_window_id: an X window ID.
+ *
+ * Gets the #WnckScreen for the root window at @root_window_id, or
+ * %NULL if no #WnckScreen exists for this root window.
+ *
+ * This function does not work if wnck_handle_get_screen() was not called
+ * for the sought #WnckScreen before, and returns %NULL.
+ *
+ * Returns: (transfer none): the #WnckScreen for the root window at
+ * @root_window_id, or %NULL. The returned #WnckScreen is owned by
+ * #WnckHandle and must not be referenced or unreferenced.
+ */
+WnckScreen *
+wnck_handle_get_screen_for_root (WnckHandle *self,
+ gulong root_window_id)
+{
+ Display *display;
+ int i;
+
+ g_return_val_if_fail (WNCK_IS_HANDLE (self), NULL);
+
+ if (self->screens == NULL)
+ return NULL;
+
+ display = _wnck_get_default_display ();
+ i = 0;
+
+ while (i < ScreenCount (display))
+ {
+ WnckScreen *screen;
+
+ screen = self->screens[i];
+ if (screen != NULL && _wnck_screen_get_xroot (screen) == root_window_id)
+ return screen;
+
+ ++i;
+ }
+
+ return NULL;
+}
+
+WnckScreen *
+_wnck_handle_get_existing_screen (WnckHandle *self,
+ int number)
+{
+ Display *display;
+
+ display = _wnck_get_default_display ();
+
+ g_return_val_if_fail (WNCK_IS_HANDLE (self), NULL);
+ g_return_val_if_fail (display != NULL, NULL);
+ g_return_val_if_fail (number < ScreenCount (display), NULL);
+
+ if (self->screens != NULL)
+ return self->screens[number];
+
+ return NULL;
+}
+
/**
* wnck_handle_set_default_icon_size:
* @self: a #WnckHandle
@@ -308,3 +857,174 @@ _wnck_handle_get_default_mini_icon_size (WnckHandle *self)
return self->default_mini_icon_size;
}
+
+/**
+ * wnck_handle_read_resource_usage_xid:
+ * @self: a #WnckHandle
+ * @gdk_display: a <classname>GdkDisplay</classname>.
+ * @xid: an X window ID.
+ * @usage: return location for the X resource usage of the application owning
+ * the X window ID @xid.
+ *
+ * Looks for the X resource usage of the application owning the X window ID
+ * @xid on display @gdk_display. If no resource usage can be found, then all
+ * fields of @usage are set to 0.
+ *
+ * To properly work, this function requires the XRes extension on the X server.
+ */
+void
+wnck_handle_read_resource_usage_xid (WnckHandle *self,
+ GdkDisplay *gdk_display,
+ gulong xid,
+ WnckResourceUsage *usage)
+{
+ g_return_if_fail (WNCK_IS_HANDLE (self));
+ g_return_if_fail (usage != NULL);
+
+ memset (usage, '\0', sizeof (*usage));
+
+ if (wnck_init_resource_usage (gdk_display) == WNCK_EXT_MISSING)
+ return;
+
+#ifdef HAVE_XRES
+ {
+ Display *xdisplay;
+ XResType *types;
+ int n_types;
+ unsigned long pixmap_bytes;
+ int i;
+ Atom pixmap_atom;
+ Atom window_atom;
+ Atom gc_atom;
+ Atom picture_atom;
+ Atom glyphset_atom;
+ Atom font_atom;
+ Atom colormap_entry_atom;
+ Atom passive_grab_atom;
+ Atom cursor_atom;
+
+ types = NULL;
+ n_types = 0;
+ pixmap_bytes = 0;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display);
+
+ _wnck_error_trap_push (xdisplay);
+
+ XResQueryClientResources (xdisplay,
+ xid, &n_types,
+ &types);
+
+ XResQueryClientPixmapBytes (xdisplay,
+ xid, &pixmap_bytes);
+ _wnck_error_trap_pop (xdisplay);
+
+ usage->pixmap_bytes = pixmap_bytes;
+
+ pixmap_atom = _wnck_atom_get ("PIXMAP");
+ window_atom = _wnck_atom_get ("WINDOW");
+ gc_atom = _wnck_atom_get ("GC");
+ font_atom = _wnck_atom_get ("FONT");
+ glyphset_atom = _wnck_atom_get ("GLYPHSET");
+ picture_atom = _wnck_atom_get ("PICTURE");
+ colormap_entry_atom = _wnck_atom_get ("COLORMAP ENTRY");
+ passive_grab_atom = _wnck_atom_get ("PASSIVE GRAB");
+ cursor_atom = _wnck_atom_get ("CURSOR");
+
+ i = 0;
+ while (i < n_types)
+ {
+ guint t = types[i].resource_type;
+
+ if (t == pixmap_atom)
+ usage->n_pixmaps += types[i].count;
+ else if (t == window_atom)
+ usage->n_windows += types[i].count;
+ else if (t == gc_atom)
+ usage->n_gcs += types[i].count;
+ else if (t == picture_atom)
+ usage->n_pictures += types[i].count;
+ else if (t == glyphset_atom)
+ usage->n_glyphsets += types[i].count;
+ else if (t == font_atom)
+ usage->n_fonts += types[i].count;
+ else if (t == colormap_entry_atom)
+ usage->n_colormap_entries += types[i].count;
+ else if (t == passive_grab_atom)
+ usage->n_passive_grabs += types[i].count;
+ else if (t == cursor_atom)
+ usage->n_cursors += types[i].count;
+ else
+ usage->n_other += types[i].count;
+
+ ++i;
+ }
+
+ XFree(types);
+
+ usage->total_bytes_estimate = usage->pixmap_bytes;
+
+ /* FIXME look in the X server source and come up with better
+ * answers here. Ideally we change XRes to return a number
+ * like this since it can do things like divide the cost of
+ * a shared resource among those sharing it.
+ */
+ usage->total_bytes_estimate += usage->n_windows * 24;
+ usage->total_bytes_estimate += usage->n_gcs * 24;
+ usage->total_bytes_estimate += usage->n_pictures * 24;
+ usage->total_bytes_estimate += usage->n_glyphsets * 24;
+ usage->total_bytes_estimate += usage->n_fonts * 1024;
+ usage->total_bytes_estimate += usage->n_colormap_entries * 24;
+ usage->total_bytes_estimate += usage->n_passive_grabs * 24;
+ usage->total_bytes_estimate += usage->n_cursors * 24;
+ usage->total_bytes_estimate += usage->n_other * 24;
+ }
+#else /* HAVE_XRES */
+ g_assert_not_reached ();
+#endif /* HAVE_XRES */
+}
+
+/**
+ * wnck_handle_read_resource_usage_pid:
+ * @self: a #WnckHandle
+ * @gdk_display: a <classname>GdkDisplay</classname>.
+ * @pid: a process ID.
+ * @usage: return location for the X resource usage of the application with
+ * process ID @pid.
+ *
+ * Looks for the X resource usage of the application with process ID @pid on
+ * display @gdk_display. If no resource usage can be found, then all fields of
+ * @usage are set to 0.
+ *
+ * In order to find the resource usage of an application that does not have an
+ * X window visible to libwnck (panel applets do not have any toplevel windows,
+ * for example), wnck_pid_read_resource_usage() walks through the whole tree of
+ * X windows. Since this walk is expensive in CPU, a cache is created. This
+ * cache is updated in the background. This means there is a non-null
+ * probability that no resource usage will be found for an application, even if
+ * it is an X client. If this happens, calling wnck_pid_read_resource_usage()
+ * again after a few seconds should work.
+ *
+ * To properly work, this function requires the XRes extension on the X server.
+ */
+void
+wnck_handle_read_resource_usage_pid (WnckHandle *self,
+ GdkDisplay *gdk_display,
+ gulong pid,
+ WnckResourceUsage *usage)
+{
+ g_return_if_fail (WNCK_IS_HANDLE (self));
+ g_return_if_fail (usage != NULL);
+
+ memset (usage, '\0', sizeof (*usage));
+
+ if (wnck_init_resource_usage (gdk_display) == WNCK_EXT_MISSING)
+ return;
+
+#ifdef HAVE_XRES
+ if (!wnck_pid_read_resource_usage_from_cache (self, gdk_display, pid, usage))
+ /* the cache might not be built, might be outdated or might not contain
+ * data for a new X client, so try to fallback to something else */
+ wnck_pid_read_resource_usage_no_cache (self, gdk_display, pid, usage);
+#endif /* HAVE_XRES */
+}
diff --git a/libwnck/wnck-handle.h b/libwnck/wnck-handle.h
index 1f7aae1..0c76ab1 100644
--- a/libwnck/wnck-handle.h
+++ b/libwnck/wnck-handle.h
@@ -23,6 +23,7 @@
#define WNCK_HANDLE_H
#include <glib-object.h>
+#include <libwnck/screen.h>
#include <libwnck/util.h>
G_BEGIN_DECLS
@@ -30,13 +31,31 @@ G_BEGIN_DECLS
#define WNCK_TYPE_HANDLE (wnck_handle_get_type ())
G_DECLARE_FINAL_TYPE (WnckHandle, wnck_handle, WNCK, HANDLE, GObject)
-WnckHandle *wnck_handle_new (WnckClientType client_type);
+WnckHandle *wnck_handle_new (WnckClientType client_type);
-void wnck_handle_set_default_icon_size (WnckHandle *self,
- gsize icon_size);
+WnckScreen *wnck_handle_get_default_screen (WnckHandle *self);
-void wnck_handle_set_default_mini_icon_size (WnckHandle *self,
- gsize icon_size);
+WnckScreen *wnck_handle_get_screen (WnckHandle *self,
+ int index);
+
+WnckScreen *wnck_handle_get_screen_for_root (WnckHandle *self,
+ gulong root_window_id);
+
+void wnck_handle_set_default_icon_size (WnckHandle *self,
+ gsize icon_size);
+
+void wnck_handle_set_default_mini_icon_size (WnckHandle *self,
+ gsize icon_size);
+
+void wnck_handle_read_resource_usage_xid (WnckHandle *self,
+ GdkDisplay *gdk_display,
+ gulong xid,
+ WnckResourceUsage *usage);
+
+void wnck_handle_read_resource_usage_pid (WnckHandle *self,
+ GdkDisplay *gdk_display,
+ gulong pid,
+ WnckResourceUsage *usage);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]