gtk+ r22145 - in trunk: . gdk gdk/x11
- From: matthiasc svn gnome org
- To: svn-commits-list gnome org
- Subject: gtk+ r22145 - in trunk: . gdk gdk/x11
- Date: Tue, 20 Jan 2009 02:16:00 +0000 (UTC)
Author: matthiasc
Date: Tue Jan 20 02:15:59 2009
New Revision: 22145
URL: http://svn.gnome.org/viewvc/gtk+?rev=22145&view=rev
Log:
Cache cursors to avoid libXcursor theme lookup overhead.
Patch by David Alan Gilbert.
* gdk/gdkcursor.h: Add a GDK_BLANK_CURSOR cursor type.
* gdk/x11/gdkcursor-x11.c: Cache font cursors and named cursors.
* gdk/x11/gdkprivate-x11.h:
* gdk/x11/gdkcdisplay-x11.c: Remove cached cursors when a
display if finalized.
Modified:
trunk/ChangeLog
trunk/gdk/gdkcursor.h
trunk/gdk/x11/gdkcursor-x11.c
trunk/gdk/x11/gdkdisplay-x11.c
trunk/gdk/x11/gdkprivate-x11.h
Modified: trunk/gdk/gdkcursor.h
==============================================================================
--- trunk/gdk/gdkcursor.h (original)
+++ trunk/gdk/gdkcursor.h Tue Jan 20 02:15:59 2009
@@ -120,7 +120,8 @@
GDK_WATCH = 150,
GDK_XTERM = 152,
GDK_LAST_CURSOR,
- GDK_CURSOR_IS_PIXMAP = -1
+ GDK_BLANK_CURSOR = -2,
+ GDK_CURSOR_IS_PIXMAP = -1
} GdkCursorType;
struct _GdkCursor
Modified: trunk/gdk/x11/gdkcursor-x11.c
==============================================================================
--- trunk/gdk/x11/gdkcursor-x11.c (original)
+++ trunk/gdk/x11/gdkcursor-x11.c Tue Jan 20 02:15:59 2009
@@ -49,6 +49,140 @@
static guint theme_serial = 0;
+/* cursor_cache holds a cache of non-pixmap cursors to avoid expensive
+ * libXcursor searches, cursors are added to it but never removed. We make
+ * the assumption that since there are a small number of GdkDisplay's and
+ * a small number of cursor's that this list will stay small enough
+ * not to be a problem.
+ */
+static GSList* cursor_cache = NULL;
+
+struct cursor_cache_key
+{
+ GdkDisplay* display;
+ GdkCursorType type;
+ const char* name;
+};
+
+/* Caller should check if there is already a match first.
+ * Cursor MUST be either a typed cursor or a pixmap with
+ * a non-NULL name.
+ */
+static void
+add_to_cache (GdkCursorPrivate* cursor)
+{
+ cursor_cache = g_slist_prepend (cursor_cache, cursor);
+
+ /* Take a ref so that if the caller frees it we still have it */
+ gdk_cursor_ref ((GdkCursor*) cursor);
+}
+
+/* Returns 0 on a match
+ */
+static gint
+cache_compare_func (gconstpointer listelem,
+ gconstpointer target)
+{
+ GdkCursorPrivate* cursor = (GdkCursorPrivate*)listelem;
+ struct cursor_cache_key* key = (struct cursor_cache_key*)target;
+
+ if ((cursor->cursor.type != key->type) ||
+ (cursor->display != key->display))
+ return 1; /* No match */
+
+ /* Elements marked as pixmap must be named cursors
+ * (since we don't store normal pixmap cursors
+ */
+ if (key->type == GDK_CURSOR_IS_PIXMAP)
+ return strcmp (key->name, cursor->name);
+
+ return 0; /* Match */
+}
+
+/* Returns the cursor if there is a match, NULL if not
+ * For named cursors type shall be GDK_CURSOR_IS_PIXMAP
+ * For unnamed, typed cursors, name shall be NULL
+ */
+static GdkCursorPrivate*
+find_in_cache (GdkDisplay *display,
+ GdkCursorType type,
+ const char *name)
+{
+ GSList* res;
+ struct cursor_cache_key key;
+
+ key.display = display;
+ key.type = type;
+ key.name = name;
+
+ res = g_slist_find_custom (cursor_cache, &key, cache_compare_func);
+
+ if (res)
+ return (GdkCursorPrivate *) res->data;
+
+ return NULL;
+}
+
+/* Called by gdk_display_x11_finalize to flush any cached cursors
+ * for a dead display.
+ */
+void
+_gdk_x11_cursor_display_finalize (GdkDisplay *display)
+{
+ GSList* item;
+ GSList** itemp; /* Pointer to the thing to fix when we delete an item */
+ item = cursor_cache;
+ itemp = &cursor_cache;
+ while (item)
+ {
+ GdkCursorPrivate* cursor = (GdkCursorPrivate*)(item->data);
+ if (cursor->display == display)
+ {
+ GSList* olditem;
+ gdk_cursor_unref ((GdkCursor*) cursor);
+ /* Remove this item from the list */
+ *(itemp) = item->next;
+ olditem = item;
+ item = g_slist_next (item);
+ g_slist_free_1 (olditem);
+ }
+ else
+ {
+ itemp = &(item->next);
+ item = g_slist_next (item);
+ }
+ }
+}
+
+static Cursor
+get_blank_cursor (GdkDisplay *display)
+{
+ GdkScreen *screen;
+ GdkPixmap *pixmap;
+ Pixmap source_pixmap;
+ XColor color;
+ Cursor cursor;
+
+ screen = gdk_display_get_default_screen (display);
+ pixmap = gdk_bitmap_create_from_data (gdk_screen_get_root_window (screen),
+ "\0\0\0\0\0\0\0\0", 1, 1);
+
+ source_pixmap = GDK_PIXMAP_XID (pixmap);
+
+ color.pixel = 0;
+ color.red = color.blue = color.green = 0;
+
+ if (display->closed)
+ cursor = None;
+ else
+ cursor = XCreatePixmapCursor (GDK_DISPLAY_XDISPLAY (display),
+ source_pixmap, source_pixmap,
+ &color, &color, 1, 1);
+ g_object_unref (pixmap);
+
+ return cursor;
+}
+
/**
* gdk_cursor_new_for_display:
* @display: the #GdkDisplay for which the cursor will be created
@@ -108,11 +242,11 @@
* <listitem><para>
* <inlinegraphic format="PNG" fileref="sb_v_double_arrow.png"></inlinegraphic> #GDK_SB_V_DOUBLE_ARROW (move horizontal splitter)
* </para></listitem>
+ * <listitem><para>
+ * #GDK_BLANK_CURSOR (Blank cursor). Since 2.16
+ * </para></listitem>
* </itemizedlist>
*
- * To make the cursor invisible, use gdk_cursor_new_from_pixmap() to create
- * a cursor with no pixels in it.
- *
* Return value: a new #GdkCursor
*
* Since: 2.2
@@ -128,9 +262,29 @@
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
if (display->closed)
- xcursor = None;
- else
- xcursor = XCreateFontCursor (GDK_DISPLAY_XDISPLAY (display), cursor_type);
+ {
+ xcursor = None;
+ }
+ else
+ {
+ private = find_in_cache (display, cursor_type, NULL);
+
+ if (private)
+ {
+ /* Cache had it, add a ref for this user */
+ gdk_cursor_ref ((GdkCursor*) private);
+
+ return (GdkCursor*) private;
+ }
+ else
+ {
+ if (cursor_type != GDK_BLANK_CURSOR)
+ xcursor = XCreateFontCursor (GDK_DISPLAY_XDISPLAY (display),
+ cursor_type);
+ else
+ xcursor = get_blank_cursor (display);
+ }
+ }
private = g_new (GdkCursorPrivate, 1);
private->display = display;
@@ -142,6 +296,9 @@
cursor->type = cursor_type;
cursor->ref_count = 1;
+ if (xcursor != None)
+ add_to_cache (private);
+
return cursor;
}
@@ -427,25 +584,20 @@
new_cursor = XcursorShapeLoadCursor (xdisplay, cursor->type);
if (new_cursor != None)
- XFixesChangeCursor (xdisplay, new_cursor, private->xcursor);
+ {
+ XFixesChangeCursor (xdisplay, new_cursor, private->xcursor);
+ private->xcursor = new_cursor;
+ }
}
}
static void
-update_cursor (gpointer key,
- gpointer value,
- gpointer data)
+update_cursor (gpointer data,
+ gpointer user_data)
{
- XID *xid = key;
GdkCursor *cursor;
- if (*xid & XID_FONT_BIT)
- return;
-
- if (!GDK_IS_WINDOW (value))
- return;
-
- cursor = _gdk_x11_window_get_cursor (GDK_WINDOW (value));
+ cursor = (GdkCursor*)(data);
if (!cursor)
return;
@@ -503,7 +655,7 @@
if (size > 0)
XcursorSetDefaultSize (xdisplay, size);
- g_hash_table_foreach (display_x11->xid_ht, update_cursor, NULL);
+ g_slist_foreach (cursor_cache, update_cursor, NULL);
}
#else
@@ -679,6 +831,16 @@
xcursor = None;
else
{
+ private = find_in_cache (display, GDK_CURSOR_IS_PIXMAP, name);
+
+ if (private)
+ {
+ /* Cache had it, add a ref for this user */
+ gdk_cursor_ref ((GdkCursor*) private);
+
+ return (GdkCursor*) private;
+ }
+
xdisplay = GDK_DISPLAY_XDISPLAY (display);
xcursor = XcursorLibraryLoadCursor (xdisplay, name);
if (xcursor == None)
@@ -694,7 +856,8 @@
cursor = (GdkCursor *) private;
cursor->type = GDK_CURSOR_IS_PIXMAP;
cursor->ref_count = 1;
-
+ add_to_cache (private);
+
return cursor;
}
Modified: trunk/gdk/x11/gdkdisplay-x11.c
==============================================================================
--- trunk/gdk/x11/gdkdisplay-x11.c (original)
+++ trunk/gdk/x11/gdkdisplay-x11.c Tue Jan 20 02:15:59 2009
@@ -838,6 +838,8 @@
g_free (display_x11->motif_target_lists);
}
+ _gdk_x11_cursor_display_finalize (GDK_DISPLAY_OBJECT(display_x11));
+
/* Atom Hashtable */
g_hash_table_destroy (display_x11->atom_from_virtual);
g_hash_table_destroy (display_x11->atom_to_virtual);
Modified: trunk/gdk/x11/gdkprivate-x11.h
==============================================================================
--- trunk/gdk/x11/gdkprivate-x11.h (original)
+++ trunk/gdk/x11/gdkprivate-x11.h Tue Jan 20 02:15:59 2009
@@ -191,6 +191,7 @@
GdkGC *gc);
void _gdk_x11_cursor_update_theme (GdkCursor *cursor);
+void _gdk_x11_cursor_display_finalize (GdkDisplay *display);
gboolean _gdk_x11_get_xft_setting (GdkScreen *screen,
const gchar *name,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]