From 3c96358fd1b79dcd8999fce6d7bf1efa7fb8584a Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 15 Jun 2005 18:37:18 +0000 Subject: [PATCH] Keep a reference to the GdkCursor and add a private getter for it, so that 2005-06-15 Matthias Clasen * gdk/x11/gdkwindow-x11.[hc]: Keep a reference to the GdkCursor and add a private getter for it, so that we can update the cursor when the cursor theme changes. * gdk/gdk.symbols: * gdk/x11/gdkx.h: * gdk/x11/gdkcursor-x11.c (gdk_x11_display_set_cursor_theme): New function to change the cursor theme. --- ChangeLog | 9 ++ ChangeLog.pre-2-10 | 9 ++ ChangeLog.pre-2-8 | 9 ++ docs/reference/gdk/gdk-sections.txt | 1 + gdk/gdk.symbols | 1 + gdk/x11/gdkcursor-x11.c | 154 ++++++++++++++++++---------- gdk/x11/gdkwindow-x11.c | 38 ++++++- gdk/x11/gdkwindow-x11.h | 3 + gdk/x11/gdkx.h | 4 + 9 files changed, 170 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ffaa39825..9fd51f2302 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2005-06-15 Matthias Clasen + * gdk/x11/gdkwindow-x11.[hc]: Keep a reference to the + GdkCursor and add a private getter for it, so that we can + update the cursor when the cursor theme changes. + + * gdk/gdk.symbols: + * gdk/x11/gdkx.h: + * gdk/x11/gdkcursor-x11.c (gdk_x11_display_set_cursor_theme): + New function to change the cursor theme. + * gdk/x11/gdkwindow-x11.c: Remove a lot of pointless g_return_if_fail() non-NULL checks. diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 5ffaa39825..9fd51f2302 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,5 +1,14 @@ 2005-06-15 Matthias Clasen + * gdk/x11/gdkwindow-x11.[hc]: Keep a reference to the + GdkCursor and add a private getter for it, so that we can + update the cursor when the cursor theme changes. + + * gdk/gdk.symbols: + * gdk/x11/gdkx.h: + * gdk/x11/gdkcursor-x11.c (gdk_x11_display_set_cursor_theme): + New function to change the cursor theme. + * gdk/x11/gdkwindow-x11.c: Remove a lot of pointless g_return_if_fail() non-NULL checks. diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 5ffaa39825..9fd51f2302 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,5 +1,14 @@ 2005-06-15 Matthias Clasen + * gdk/x11/gdkwindow-x11.[hc]: Keep a reference to the + GdkCursor and add a private getter for it, so that we can + update the cursor when the cursor theme changes. + + * gdk/gdk.symbols: + * gdk/x11/gdkx.h: + * gdk/x11/gdkcursor-x11.c (gdk_x11_display_set_cursor_theme): + New function to change the cursor theme. + * gdk/x11/gdkwindow-x11.c: Remove a lot of pointless g_return_if_fail() non-NULL checks. diff --git a/docs/reference/gdk/gdk-sections.txt b/docs/reference/gdk/gdk-sections.txt index 0331e211d8..b2434a900e 100644 --- a/docs/reference/gdk/gdk-sections.txt +++ b/docs/reference/gdk/gdk-sections.txt @@ -1262,6 +1262,7 @@ gdk_x11_cursor_get_xdisplay gdk_x11_display_get_xdisplay gdk_x11_display_grab gdk_x11_display_ungrab +gdk_x11_display_set_cursor_theme gdk_x11_register_standard_event_type gdk_x11_drawable_get_xdisplay gdk_x11_drawable_get_xid diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols index 5f5b1c0161..c5f5239887 100644 --- a/gdk/gdk.symbols +++ b/gdk/gdk.symbols @@ -1111,6 +1111,7 @@ gdkx_colormap_get #if IN_FILE(__GDK_CURSOR_X11_C__) gdk_x11_cursor_get_xcursor gdk_x11_cursor_get_xdisplay +gdk_x11_display_set_cursor_theme #endif #if IN_FILE(__GDK_DISPLAY_X11_C__) diff --git a/gdk/x11/gdkcursor-x11.c b/gdk/x11/gdkcursor-x11.c index 3373ecdcfb..69a2b49892 100644 --- a/gdk/x11/gdkcursor-x11.c +++ b/gdk/x11/gdkcursor-x11.c @@ -25,6 +25,9 @@ */ #include + +#define GDK_PIXBUF_ENABLE_BACKEND + #include #include #ifdef HAVE_XCURSOR @@ -40,7 +43,6 @@ #include "gdkpixmap-x11.h" #include "gdkx.h" #include -#define GDK_PIXBUF_ENABLE_BACKEND #include #include "gdkalias.h" @@ -312,34 +314,6 @@ gdk_cursor_get_display (GdkCursor *cursor) #if defined(HAVE_XCURSOR) && defined(HAVE_XFIXES) && XFIXES_MAJOR >= 2 -#if 0 -XcursorComments * -load_comments (const char *file, - const char *theme) -{ - FILE *f = 0; - XcursorImages *images = 0; - XcursorComments *comments = 0; - - if (theme) - f = XcursorScanTheme (theme, file); - if (!f) - f = XcursorScanTheme ("default", file); - if (f == XCURSOR_SCAN_CORE) - return 0; - if (f) - { - XcursorFileLoad (f, &comments, &images); - fclose (f); - - if (images) - XcursorImagesDestroy (images); - } - - return comments; -} -#endif - /** * gdk_cursor_get_image: * @cursor: a #GdkCursor @@ -361,14 +335,11 @@ gdk_cursor_get_image (GdkCursor *cursor) GdkCursorPrivate *private; XcursorImages *images = NULL; XcursorImage *image; - XcursorComments *comments; - Atom atom; gint size; gchar buf[32]; guchar *data; GdkPixbuf *pixbuf; gchar *theme; - gint i, j; g_return_val_if_fail (cursor != NULL, NULL); @@ -407,34 +378,97 @@ gdk_cursor_get_image (GdkCursor *cursor) g_snprintf (buf, 32, "%d", image->yhot); gdk_pixbuf_set_option (pixbuf, "y_hot", buf); -#if 0 - comments = load_comments (images->name, theme); - - j = 0; - for (i = 0; i < comments->ncomment; i++) - { - switch (comments->comments[i].comment_type) - { - case XCURSOR_COMMENT_COPYRIGHT: - gdk_pixbuf_set_option (pixbuf, "copyright", comments->comments[i].comment); - break; - case XCURSOR_COMMENT_LICENSE: - gdk_pixbuf_set_option (pixbuf, "license", comments->comments[i].comment); - break; - default: - g_snprintf (buf, 32, "comment%d", j++); - gdk_pixbuf_set_option (pixbuf, buf, comments->comments[i].comment); - break; - } - } - XcursorCommentsDestroy (comments); -#endif - XcursorImagesDestroy (images); return pixbuf; } +static void +update_cursor (gpointer key, + gpointer value, + gpointer data) +{ + Display *xdisplay; + GdkWindow *window; + GdkCursor *cursor; + GdkCursorPrivate *private; + Cursor new_cursor = None; + + if (!GDK_IS_WINDOW (value)) + return; + + cursor = _gdk_x11_window_get_cursor (GDK_WINDOW (value)); + + if (!cursor) + return; + + private = (GdkCursorPrivate *) cursor; + xdisplay = (Display *)data; + + if (private->xcursor != None) + { + if (cursor->type == GDK_CURSOR_IS_PIXMAP) + { + if (private->name) + new_cursor = XcursorLibraryLoadCursor (xdisplay, private->name); + } + else + new_cursor = XcursorShapeLoadCursor (xdisplay, cursor->type); + + if (new_cursor != None) + XFixesChangeCursor (xdisplay, new_cursor, private->xcursor); + } +} + +/** + * gdk_x11_display_set_cursor_theme: + * @display: a #GdkDisplay + * @theme: the name of the cursor theme to use + * @size: the cursor size to use + * + * Sets the cursor theme from which the images for cursor + * should be taken. + * + * If the windowing system supports it, existing cursors created + * with gdk_cursor_new(), gdk_cursor_new_for_display() and + * gdk_cursor_new_for_name() are updated to reflect the theme + * change. Custom cursors constructed with gdk_cursor_new_from_pixmap() + * or gdk_cursor_new_from_pixbuf() will have to be handled + * by the application (GTK+ applications can learn about + * cursor theme changes by listening for change notification + * for the corresponding #GtkSetting). + * + * Since: 2.8 + */ +void +gdk_x11_display_set_cursor_theme (GdkDisplay *display, + const gchar *theme, + const gint size) +{ + GdkDisplayX11 *display_x11; + Display *xdisplay; + gchar *old_theme; + gint old_size; + + g_return_if_fail (GDK_IS_DISPLAY (display)); + + display_x11 = GDK_DISPLAY_X11 (display); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + old_theme = XcursorGetTheme (xdisplay); + old_size = XcursorGetDefaultSize (xdisplay); + + if (old_size == size && + old_theme && strcmp (old_theme, theme) == 0) + return; + + XcursorSetTheme (xdisplay, theme); + XcursorSetDefaultSize (xdisplay, size); + + g_hash_table_foreach (display_x11->xid_ht, + update_cursor, xdisplay); +} + #else GdkPixbuf* @@ -445,6 +479,16 @@ gdk_cursor_get_image (GdkCursor *cursor) return NULL; } +void +gdk_x11_display_set_cursor_theme (GdkDisplay *display, + const gchar *theme, + const gint size) +{ + g_return_if_fail (GDK_IS_DISPLAY (display)); + + /* nothing to do */ +} + #endif #ifdef HAVE_XCURSOR diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index a1b6c2c61e..83082c0278 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -224,6 +224,9 @@ gdk_window_impl_x11_finalize (GObject *object) if (window_impl->toplevel) g_free (window_impl->toplevel); + if (window_impl->cursor) + gdk_cursor_unref (window_impl->cursor); + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -2854,22 +2857,51 @@ void gdk_window_set_cursor (GdkWindow *window, GdkCursor *cursor) { + GdkWindowObject *private; + GdkWindowImplX11 *impl; GdkCursorPrivate *cursor_private; Cursor xcursor; g_return_if_fail (GDK_IS_WINDOW (window)); + private = (GdkWindowObject *)window; + impl = GDK_WINDOW_IMPL_X11 (private->impl); cursor_private = (GdkCursorPrivate*) cursor; + if (impl->cursor) + { + gdk_cursor_unref (impl->cursor); + impl->cursor = NULL; + } + if (!cursor) xcursor = None; else xcursor = cursor_private->xcursor; if (!GDK_WINDOW_DESTROYED (window)) - XDefineCursor (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - xcursor); + { + XDefineCursor (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + xcursor); + + if (cursor) + impl->cursor = gdk_cursor_ref (cursor); + } +} + +GdkCursor * +_gdk_x11_window_get_cursor (GdkWindow *window) +{ + GdkWindowObject *private; + GdkWindowImplX11 *impl; + + g_return_if_fail (GDK_IS_WINDOW (window)); + + private = (GdkWindowObject *)window; + impl = GDK_WINDOW_IMPL_X11 (private->impl); + + return impl->cursor; } /** diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h index f95505aaff..63e721e4e2 100644 --- a/gdk/x11/gdkwindow-x11.h +++ b/gdk/x11/gdkwindow-x11.h @@ -75,6 +75,7 @@ struct _GdkWindowImplX11 GdkXPositionInfo position_info; GdkToplevelX11 *toplevel; /* Toplevel-specific information */ + GdkCursor *cursor; gint8 toplevel_window_type; guint override_redirect : 1; guint use_synchronized_configure : 1; @@ -158,6 +159,8 @@ void _gdk_x11_window_tmp_reset_bg (GdkWindow *window, gboolean recurse); +GdkCursor *_gdk_x11_window_get_cursor (GdkWindow *window); + G_END_DECLS #endif /* __GDK_WINDOW_X11_H__ */ diff --git a/gdk/x11/gdkx.h b/gdk/x11/gdkx.h index 2e933b7069..ac6ee44421 100644 --- a/gdk/x11/gdkx.h +++ b/gdk/x11/gdkx.h @@ -141,6 +141,10 @@ gpointer gdk_xid_table_lookup_for_display (GdkDisplay *display, guint32 gdk_x11_get_server_time (GdkWindow *window); guint32 gdk_x11_display_get_user_time (GdkDisplay *display); +void gdk_x11_display_set_cursor_theme (GdkDisplay *display, + const gchar *theme, + const gint size); + /* returns TRUE if we support the given WM spec feature */ gboolean gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen, GdkAtom property);