From 9efcca800087241ed5c296789ff14a0c8c24cd02 Mon Sep 17 00:00:00 2001 From: Maciej Stachowiak Date: Mon, 19 Feb 2001 20:46:26 +0000 Subject: reviewed by: Gene Z. Ragan Added auto-prelighting feature to NautilusClickableImage, and fixed a major bug that occurs for clickable images in scrolled areas. * libnautilus-extensions/nautilus-clickable-image.h, libnautilus-extensions/nautilus-clickable-image.c: (nautilus_clickable_image_set_prelight): New public API call that allows for automatic prelight handling direct in NautilusClickableImage; made it settable because some users of this code want to manually prelight with an alternate image. (nautilus_clickable_image_set_up_pixbufs): helper function for the above that keeps track of the normal and prelit buffers. (label_enter, label_leave): When in prelight mode, switch images on enter and leave. Also, remove unnecessary queue_draw calls. (adjust_coordinates_for_window, ancestor_enter_notify_event, ancestor_leave_notify_event, ancestor_motion_notify_event): Do some coordinate adjustments so that if the NautilusClickableImage is in a scrolled area with NO_WINDOW widgets all the way in between, we do an appropriate coordinate adjustment. This should also handle other containers that put their children in a different window than their own. This was breaking for the summary view when I set it to use clickable images for the service icons. * libnautilus/nautilus-view-standard-main.c (nautilus_view_standard_main_multi): Do a g_thread_init to make views that use gnome-vfs happy. --- ChangeLog | 32 +++++ libnautilus-extensions/nautilus-clickable-image.c | 136 ++++++++++++++++++++-- libnautilus-extensions/nautilus-clickable-image.h | 3 + libnautilus-private/nautilus-clickable-image.c | 136 ++++++++++++++++++++-- libnautilus-private/nautilus-clickable-image.h | 3 + libnautilus/nautilus-view-standard-main.c | 1 + 6 files changed, 295 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index bd172abc4..f2d01ab45 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2001-02-19 Maciej Stachowiak + + reviewed by: Gene Z. Ragan + + Added auto-prelighting feature to NautilusClickableImage, and + fixed a major bug that occurs for clickable images in scrolled + areas. + + * libnautilus-extensions/nautilus-clickable-image.h, + libnautilus-extensions/nautilus-clickable-image.c: + (nautilus_clickable_image_set_prelight): New public API call that + allows for automatic prelight handling direct in + NautilusClickableImage; made it settable because some users of + this code want to manually prelight with an alternate image. + (nautilus_clickable_image_set_up_pixbufs): helper function for the + above that keeps track of the normal and prelit buffers. + (label_enter, label_leave): When in prelight mode, switch images + on enter and leave. Also, remove unnecessary queue_draw calls. + + (adjust_coordinates_for_window, ancestor_enter_notify_event, + ancestor_leave_notify_event, ancestor_motion_notify_event): Do + some coordinate adjustments so that if the NautilusClickableImage + is in a scrolled area with NO_WINDOW widgets all the way in + between, we do an appropriate coordinate adjustment. This should + also handle other containers that put their children in a + different window than their own. This was breaking for the summary + view when I set it to use clickable images for the service icons. + + * libnautilus/nautilus-view-standard-main.c + (nautilus_view_standard_main_multi): Do a g_thread_init to make + views that use gnome-vfs happy. + 2001-02-18 Ian McKellar reviewed by: Robey Pointer diff --git a/libnautilus-extensions/nautilus-clickable-image.c b/libnautilus-extensions/nautilus-clickable-image.c index b5330e44c..705b63a63 100644 --- a/libnautilus-extensions/nautilus-clickable-image.c +++ b/libnautilus-extensions/nautilus-clickable-image.c @@ -29,6 +29,7 @@ #include "nautilus-gtk-macros.h" #include "nautilus-gtk-extensions.h" #include "nautilus-art-gtk-extensions.h" +#include "nautilus-graphic-effects.h" #include @@ -55,6 +56,10 @@ static guint clickable_image_signals[LAST_SIGNAL] = { 0 }; struct _NautilusClickableImageDetails { gboolean pointer_inside; + gboolean prelight; + + GdkPixbuf *pixbuf; + GdkPixbuf *prelight_pixbuf; }; /* GtkObjectClass methods */ @@ -241,10 +246,14 @@ label_enter (NautilusClickableImage *clickable_image) { g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); - clickable_image->details->pointer_inside = TRUE; + clickable_image->details->pointer_inside = TRUE; + + if (clickable_image->details->prelight) { + nautilus_labeled_image_set_pixbuf (NAUTILUS_LABELED_IMAGE (clickable_image), + clickable_image->details->prelight_pixbuf); + } gtk_widget_set_state (GTK_WIDGET (clickable_image), GTK_STATE_PRELIGHT); - gtk_widget_queue_draw (GTK_WIDGET (clickable_image)); gtk_signal_emit (GTK_OBJECT (clickable_image), clickable_image_signals[ENTER], @@ -257,10 +266,14 @@ label_leave (NautilusClickableImage *clickable_image) { g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); - clickable_image->details->pointer_inside = FALSE; + clickable_image->details->pointer_inside = FALSE; + + if (clickable_image->details->prelight) { + nautilus_labeled_image_set_pixbuf (NAUTILUS_LABELED_IMAGE (clickable_image), + clickable_image->details->pixbuf); + } gtk_widget_set_state (GTK_WIDGET (clickable_image), GTK_STATE_NORMAL); - gtk_widget_queue_draw (GTK_WIDGET (clickable_image)); gtk_signal_emit (GTK_OBJECT (clickable_image), clickable_image_signals[LEAVE], @@ -275,7 +288,7 @@ label_handle_motion (NautilusClickableImage *clickable_image, ArtIRect bounds; g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); - + bounds = nautilus_gtk_widget_get_bounds (GTK_WIDGET (clickable_image)); if (nautilus_art_irect_contains_point (&bounds, x, y)) { @@ -313,16 +326,54 @@ label_handle_button_release (NautilusClickableImage *clickable_image) clickable_image); } +static void +adjust_coordinates_for_window (GdkWindow *widget_window, + GdkWindow *event_window, + int *x, + int *y) +{ + GdkWindow *window; + int wx, wy; + + /* Viewports place their children in a different GdkWindow + * than their own widget window (perhaps other containers do + * this to). Therefore if the event we got is on a different + * GdkWindow than our own, adjust the coordinates. + */ + + window = widget_window; + + while (window != event_window && window != NULL) { + gdk_window_get_position (window, + &wx, + &wy); + + *x -= wx; + *y -= wy; + + window = gdk_window_get_parent (window); + } +} + static int ancestor_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event, gpointer event_data) { + int x, y; + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); g_return_val_if_fail (event != NULL, FALSE); - label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), event->x, event->y); + x = event->x; + y = event->y; + + adjust_coordinates_for_window (GTK_WIDGET (event_data)->window, + widget->window, + &x, &y); + + label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), x, y); return FALSE; } @@ -332,11 +383,20 @@ ancestor_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event, gpointer event_data) { + int x, y; + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); g_return_val_if_fail (event != NULL, FALSE); - label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), event->x, event->y); + x = event->x; + y = event->y; + + adjust_coordinates_for_window (GTK_WIDGET (event_data)->window, + widget->window, + &x, &y); + + label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), x, y); return FALSE; } @@ -346,11 +406,20 @@ ancestor_motion_notify_event (GtkWidget *widget, GdkEventMotion *event, gpointer event_data) { + int x, y; + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); g_return_val_if_fail (event != NULL, FALSE); - label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), event->x, event->y); + x = event->x; + y = event->y; + + adjust_coordinates_for_window (GTK_WIDGET (event_data)->window, + widget->window, + &x, &y); + + label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), x, y); return FALSE; } @@ -416,6 +485,16 @@ nautilus_clickable_image_expose_event (GtkWidget *widget, return NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, expose_event, (widget, event)); } +static void +nautilus_clickable_image_set_up_pixbufs (NautilusClickableImage *clickable_image) +{ + clickable_image->details->pixbuf = + nautilus_labeled_image_get_pixbuf (NAUTILUS_LABELED_IMAGE (clickable_image)); + + clickable_image->details->prelight_pixbuf = nautilus_create_spotlight_pixbuf + (clickable_image->details->pixbuf); +} + /* Public NautilusClickableImage methods */ /** @@ -529,4 +608,45 @@ nautilus_clickable_image_new_solid (const char *text, return GTK_WIDGET (clickable_image); } +/** + * nautilus_clickable_image_new: + * + * @clickable_image: A NautilusClickableImage + * @prelight: a gboolean specifying wether to prelight + * + * Enable or disable auto-prelight mode. You can't change the pixbuf + * while prelight mode is on; as a workaround, you can turn prelight + * off, change the pixbuf, and then turn it back on. + * + */ + +void +nautilus_clickable_image_set_prelight (NautilusClickableImage *clickable_image, + gboolean prelight) +{ + /* FIXME: you can't change the pixbuf with prelight mode on */ + + if (!clickable_image->details->prelight && prelight) { + nautilus_clickable_image_set_up_pixbufs (clickable_image); + clickable_image->details->prelight = TRUE; + if (clickable_image->details->pointer_inside) { + nautilus_labeled_image_set_pixbuf + (NAUTILUS_LABELED_IMAGE (clickable_image), + clickable_image->details->prelight_pixbuf); + } + } + + if (clickable_image->details->prelight && !prelight) { + if (clickable_image->details->pointer_inside) { + nautilus_labeled_image_set_pixbuf + (NAUTILUS_LABELED_IMAGE (clickable_image), + clickable_image->details->pixbuf); + } + gdk_pixbuf_unref (clickable_image->details->pixbuf); + clickable_image->details->pixbuf = NULL; + gdk_pixbuf_unref (clickable_image->details->prelight_pixbuf); + clickable_image->details->prelight_pixbuf = NULL; + clickable_image->details->prelight = FALSE; + } +} diff --git a/libnautilus-extensions/nautilus-clickable-image.h b/libnautilus-extensions/nautilus-clickable-image.h index f4c49efc2..7f1eb458d 100644 --- a/libnautilus-extensions/nautilus-clickable-image.h +++ b/libnautilus-extensions/nautilus-clickable-image.h @@ -89,6 +89,9 @@ GtkWidget *nautilus_clickable_image_new_solid (const char *text, guint32 background_color, GdkPixbuf *tile_pixbuf); +void nautilus_clickable_image_set_prelight (NautilusClickableImage *clickable_image, + gboolean prelight); + END_GNOME_DECLS #endif /* NAUTILUS_CLICKABLE_IMAGE_H */ diff --git a/libnautilus-private/nautilus-clickable-image.c b/libnautilus-private/nautilus-clickable-image.c index b5330e44c..705b63a63 100644 --- a/libnautilus-private/nautilus-clickable-image.c +++ b/libnautilus-private/nautilus-clickable-image.c @@ -29,6 +29,7 @@ #include "nautilus-gtk-macros.h" #include "nautilus-gtk-extensions.h" #include "nautilus-art-gtk-extensions.h" +#include "nautilus-graphic-effects.h" #include @@ -55,6 +56,10 @@ static guint clickable_image_signals[LAST_SIGNAL] = { 0 }; struct _NautilusClickableImageDetails { gboolean pointer_inside; + gboolean prelight; + + GdkPixbuf *pixbuf; + GdkPixbuf *prelight_pixbuf; }; /* GtkObjectClass methods */ @@ -241,10 +246,14 @@ label_enter (NautilusClickableImage *clickable_image) { g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); - clickable_image->details->pointer_inside = TRUE; + clickable_image->details->pointer_inside = TRUE; + + if (clickable_image->details->prelight) { + nautilus_labeled_image_set_pixbuf (NAUTILUS_LABELED_IMAGE (clickable_image), + clickable_image->details->prelight_pixbuf); + } gtk_widget_set_state (GTK_WIDGET (clickable_image), GTK_STATE_PRELIGHT); - gtk_widget_queue_draw (GTK_WIDGET (clickable_image)); gtk_signal_emit (GTK_OBJECT (clickable_image), clickable_image_signals[ENTER], @@ -257,10 +266,14 @@ label_leave (NautilusClickableImage *clickable_image) { g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); - clickable_image->details->pointer_inside = FALSE; + clickable_image->details->pointer_inside = FALSE; + + if (clickable_image->details->prelight) { + nautilus_labeled_image_set_pixbuf (NAUTILUS_LABELED_IMAGE (clickable_image), + clickable_image->details->pixbuf); + } gtk_widget_set_state (GTK_WIDGET (clickable_image), GTK_STATE_NORMAL); - gtk_widget_queue_draw (GTK_WIDGET (clickable_image)); gtk_signal_emit (GTK_OBJECT (clickable_image), clickable_image_signals[LEAVE], @@ -275,7 +288,7 @@ label_handle_motion (NautilusClickableImage *clickable_image, ArtIRect bounds; g_return_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (clickable_image)); - + bounds = nautilus_gtk_widget_get_bounds (GTK_WIDGET (clickable_image)); if (nautilus_art_irect_contains_point (&bounds, x, y)) { @@ -313,16 +326,54 @@ label_handle_button_release (NautilusClickableImage *clickable_image) clickable_image); } +static void +adjust_coordinates_for_window (GdkWindow *widget_window, + GdkWindow *event_window, + int *x, + int *y) +{ + GdkWindow *window; + int wx, wy; + + /* Viewports place their children in a different GdkWindow + * than their own widget window (perhaps other containers do + * this to). Therefore if the event we got is on a different + * GdkWindow than our own, adjust the coordinates. + */ + + window = widget_window; + + while (window != event_window && window != NULL) { + gdk_window_get_position (window, + &wx, + &wy); + + *x -= wx; + *y -= wy; + + window = gdk_window_get_parent (window); + } +} + static int ancestor_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event, gpointer event_data) { + int x, y; + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); g_return_val_if_fail (event != NULL, FALSE); - label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), event->x, event->y); + x = event->x; + y = event->y; + + adjust_coordinates_for_window (GTK_WIDGET (event_data)->window, + widget->window, + &x, &y); + + label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), x, y); return FALSE; } @@ -332,11 +383,20 @@ ancestor_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event, gpointer event_data) { + int x, y; + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); g_return_val_if_fail (event != NULL, FALSE); - label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), event->x, event->y); + x = event->x; + y = event->y; + + adjust_coordinates_for_window (GTK_WIDGET (event_data)->window, + widget->window, + &x, &y); + + label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), x, y); return FALSE; } @@ -346,11 +406,20 @@ ancestor_motion_notify_event (GtkWidget *widget, GdkEventMotion *event, gpointer event_data) { + int x, y; + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); g_return_val_if_fail (NAUTILUS_IS_CLICKABLE_IMAGE (event_data), FALSE); g_return_val_if_fail (event != NULL, FALSE); - label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), event->x, event->y); + x = event->x; + y = event->y; + + adjust_coordinates_for_window (GTK_WIDGET (event_data)->window, + widget->window, + &x, &y); + + label_handle_motion (NAUTILUS_CLICKABLE_IMAGE (event_data), x, y); return FALSE; } @@ -416,6 +485,16 @@ nautilus_clickable_image_expose_event (GtkWidget *widget, return NAUTILUS_CALL_PARENT_CLASS (GTK_WIDGET_CLASS, expose_event, (widget, event)); } +static void +nautilus_clickable_image_set_up_pixbufs (NautilusClickableImage *clickable_image) +{ + clickable_image->details->pixbuf = + nautilus_labeled_image_get_pixbuf (NAUTILUS_LABELED_IMAGE (clickable_image)); + + clickable_image->details->prelight_pixbuf = nautilus_create_spotlight_pixbuf + (clickable_image->details->pixbuf); +} + /* Public NautilusClickableImage methods */ /** @@ -529,4 +608,45 @@ nautilus_clickable_image_new_solid (const char *text, return GTK_WIDGET (clickable_image); } +/** + * nautilus_clickable_image_new: + * + * @clickable_image: A NautilusClickableImage + * @prelight: a gboolean specifying wether to prelight + * + * Enable or disable auto-prelight mode. You can't change the pixbuf + * while prelight mode is on; as a workaround, you can turn prelight + * off, change the pixbuf, and then turn it back on. + * + */ + +void +nautilus_clickable_image_set_prelight (NautilusClickableImage *clickable_image, + gboolean prelight) +{ + /* FIXME: you can't change the pixbuf with prelight mode on */ + + if (!clickable_image->details->prelight && prelight) { + nautilus_clickable_image_set_up_pixbufs (clickable_image); + clickable_image->details->prelight = TRUE; + if (clickable_image->details->pointer_inside) { + nautilus_labeled_image_set_pixbuf + (NAUTILUS_LABELED_IMAGE (clickable_image), + clickable_image->details->prelight_pixbuf); + } + } + + if (clickable_image->details->prelight && !prelight) { + if (clickable_image->details->pointer_inside) { + nautilus_labeled_image_set_pixbuf + (NAUTILUS_LABELED_IMAGE (clickable_image), + clickable_image->details->pixbuf); + } + gdk_pixbuf_unref (clickable_image->details->pixbuf); + clickable_image->details->pixbuf = NULL; + gdk_pixbuf_unref (clickable_image->details->prelight_pixbuf); + clickable_image->details->prelight_pixbuf = NULL; + clickable_image->details->prelight = FALSE; + } +} diff --git a/libnautilus-private/nautilus-clickable-image.h b/libnautilus-private/nautilus-clickable-image.h index f4c49efc2..7f1eb458d 100644 --- a/libnautilus-private/nautilus-clickable-image.h +++ b/libnautilus-private/nautilus-clickable-image.h @@ -89,6 +89,9 @@ GtkWidget *nautilus_clickable_image_new_solid (const char *text, guint32 background_color, GdkPixbuf *tile_pixbuf); +void nautilus_clickable_image_set_prelight (NautilusClickableImage *clickable_image, + gboolean prelight); + END_GNOME_DECLS #endif /* NAUTILUS_CLICKABLE_IMAGE_H */ diff --git a/libnautilus/nautilus-view-standard-main.c b/libnautilus/nautilus-view-standard-main.c index 424d46a42..88625723f 100644 --- a/libnautilus/nautilus-view-standard-main.c +++ b/libnautilus/nautilus-view-standard-main.c @@ -120,6 +120,7 @@ nautilus_view_standard_main_multi (const char *executable_name, gnome_init (executable_name, version, argc, argv); gdk_rgb_init (); + g_thread_init (NULL); gnome_vfs_init (); bonobo_init (orb, CORBA_OBJECT_NIL, CORBA_OBJECT_NIL); -- cgit v1.2.1