From 6d8249bd86a9ee4c7ebe45d6b89509cf8067cd7f Mon Sep 17 00:00:00 2001 From: Sven Neumann Date: Fri, 11 Apr 2003 08:37:26 +0000 Subject: [PATCH] made GimpPreview a NO_WINDOW widget that draws on the parent window. Added 2003-04-11 Sven Neumann * app/widgets/gimppreview.[ch]: made GimpPreview a NO_WINDOW widget that draws on the parent window. Added an INPUT_ONLY window for events. * app/widgets/gimpnavigationpreview.c: take the widget's allocation into account when rendering the marker and grab the mouse on the preview's event_window. * app/widgets/gimppreviewrenderer.[ch]: pass GdkRectangles as const. --- ChangeLog | 12 +++ app/widgets/gimpnavigationpreview.c | 28 +++-- app/widgets/gimpnavigationview.c | 28 +++-- app/widgets/gimppreview.c | 152 +++++++++++++++++++++++----- app/widgets/gimppreview.h | 10 +- app/widgets/gimppreviewrenderer.c | 10 +- app/widgets/gimppreviewrenderer.h | 4 +- app/widgets/gimpview.c | 152 +++++++++++++++++++++++----- app/widgets/gimpview.h | 10 +- app/widgets/gimpviewrenderer.c | 10 +- app/widgets/gimpviewrenderer.h | 4 +- 11 files changed, 324 insertions(+), 96 deletions(-) diff --git a/ChangeLog b/ChangeLog index fb000c0f0a..5e4cbdaa57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2003-04-11 Sven Neumann + + * app/widgets/gimppreview.[ch]: made GimpPreview a NO_WINDOW + widget that draws on the parent window. Added an INPUT_ONLY window + for events. + + * app/widgets/gimpnavigationpreview.c: take the widget's + allocation into account when rendering the marker and grab the + mouse on the preview's event_window. + + * app/widgets/gimppreviewrenderer.[ch]: pass GdkRectangles as const. + 2003-04-10 Michael Natterer * app/gui/file-new-dialog.c: added Portrait/Landscape radio diff --git a/app/widgets/gimpnavigationpreview.c b/app/widgets/gimpnavigationpreview.c index 1f3faee4cf..7d5b3c3ba3 100644 --- a/app/widgets/gimpnavigationpreview.c +++ b/app/widgets/gimpnavigationpreview.c @@ -292,6 +292,7 @@ gimp_navigation_preview_grab_pointer (GimpNavigationPreview *nav_preview) { GtkWidget *widget; GdkCursor *cursor; + GdkWindow *window; widget = GTK_WIDGET (nav_preview); @@ -301,12 +302,14 @@ gimp_navigation_preview_grab_pointer (GimpNavigationPreview *nav_preview) cursor = gdk_cursor_new (GDK_FLEUR); - gdk_pointer_grab (widget->window, TRUE, - GDK_BUTTON_RELEASE_MASK | + window = GIMP_PREVIEW (nav_preview)->event_window; + + gdk_pointer_grab (window, TRUE, + GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON_MOTION_MASK | + GDK_BUTTON_MOTION_MASK | GDK_EXTENSION_EVENTS_ALL, - widget->window, cursor, 0); + window, cursor, 0); gdk_cursor_unref (cursor); } @@ -449,9 +452,9 @@ gimp_navigation_preview_motion_notify (GtkWidget *widget, return FALSE; } else if (mevent->x >= nav_preview->p_x && - mevent->y >= nav_preview->p_y && - mevent->x < nav_preview->p_x + nav_preview->p_width && - mevent->y < nav_preview->p_y + nav_preview->p_height) + mevent->y >= nav_preview->p_y && + mevent->x < nav_preview->p_x + nav_preview->p_width && + mevent->y < nav_preview->p_y + nav_preview->p_height) { cursor = gdk_cursor_new (GDK_FLEUR); } @@ -466,7 +469,8 @@ gimp_navigation_preview_motion_notify (GtkWidget *widget, return FALSE; } - gdk_window_get_pointer (widget->window, &tx, &ty, &mask); + gdk_window_get_pointer (GIMP_PREVIEW (nav_preview)->event_window, + &tx, &ty, &mask); tx -= nav_preview->motion_offset_x; ty -= nav_preview->motion_offset_y; @@ -561,13 +565,15 @@ gimp_navigation_preview_draw_marker (GimpNavigationPreview *nav_preview, nav_preview->width < gimage->width || nav_preview->height < gimage->height) { + GtkWidget *widget = GTK_WIDGET (preview); + if (area) gdk_gc_set_clip_rectangle (nav_preview->gc, area); - gdk_draw_rectangle (GTK_WIDGET (preview)->window, nav_preview->gc, + gdk_draw_rectangle (widget->window, nav_preview->gc, FALSE, - nav_preview->p_x + 1, - nav_preview->p_y + 1, + widget->allocation.x + nav_preview->p_x + 1, + widget->allocation.y + nav_preview->p_y + 1, MAX (1, nav_preview->p_width - BORDER_PEN_WIDTH), MAX (1, nav_preview->p_height - BORDER_PEN_WIDTH)); diff --git a/app/widgets/gimpnavigationview.c b/app/widgets/gimpnavigationview.c index 1f3faee4cf..7d5b3c3ba3 100644 --- a/app/widgets/gimpnavigationview.c +++ b/app/widgets/gimpnavigationview.c @@ -292,6 +292,7 @@ gimp_navigation_preview_grab_pointer (GimpNavigationPreview *nav_preview) { GtkWidget *widget; GdkCursor *cursor; + GdkWindow *window; widget = GTK_WIDGET (nav_preview); @@ -301,12 +302,14 @@ gimp_navigation_preview_grab_pointer (GimpNavigationPreview *nav_preview) cursor = gdk_cursor_new (GDK_FLEUR); - gdk_pointer_grab (widget->window, TRUE, - GDK_BUTTON_RELEASE_MASK | + window = GIMP_PREVIEW (nav_preview)->event_window; + + gdk_pointer_grab (window, TRUE, + GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON_MOTION_MASK | + GDK_BUTTON_MOTION_MASK | GDK_EXTENSION_EVENTS_ALL, - widget->window, cursor, 0); + window, cursor, 0); gdk_cursor_unref (cursor); } @@ -449,9 +452,9 @@ gimp_navigation_preview_motion_notify (GtkWidget *widget, return FALSE; } else if (mevent->x >= nav_preview->p_x && - mevent->y >= nav_preview->p_y && - mevent->x < nav_preview->p_x + nav_preview->p_width && - mevent->y < nav_preview->p_y + nav_preview->p_height) + mevent->y >= nav_preview->p_y && + mevent->x < nav_preview->p_x + nav_preview->p_width && + mevent->y < nav_preview->p_y + nav_preview->p_height) { cursor = gdk_cursor_new (GDK_FLEUR); } @@ -466,7 +469,8 @@ gimp_navigation_preview_motion_notify (GtkWidget *widget, return FALSE; } - gdk_window_get_pointer (widget->window, &tx, &ty, &mask); + gdk_window_get_pointer (GIMP_PREVIEW (nav_preview)->event_window, + &tx, &ty, &mask); tx -= nav_preview->motion_offset_x; ty -= nav_preview->motion_offset_y; @@ -561,13 +565,15 @@ gimp_navigation_preview_draw_marker (GimpNavigationPreview *nav_preview, nav_preview->width < gimage->width || nav_preview->height < gimage->height) { + GtkWidget *widget = GTK_WIDGET (preview); + if (area) gdk_gc_set_clip_rectangle (nav_preview->gc, area); - gdk_draw_rectangle (GTK_WIDGET (preview)->window, nav_preview->gc, + gdk_draw_rectangle (widget->window, nav_preview->gc, FALSE, - nav_preview->p_x + 1, - nav_preview->p_y + 1, + widget->allocation.x + nav_preview->p_x + 1, + widget->allocation.y + nav_preview->p_y + 1, MAX (1, nav_preview->p_width - BORDER_PEN_WIDTH), MAX (1, nav_preview->p_height - BORDER_PEN_WIDTH)); diff --git a/app/widgets/gimppreview.c b/app/widgets/gimppreview.c index ca95efa234..6e1f52b220 100644 --- a/app/widgets/gimppreview.c +++ b/app/widgets/gimppreview.c @@ -62,6 +62,9 @@ static void gimp_preview_init (GimpPreview *preview) static void gimp_preview_destroy (GtkObject *object); static void gimp_preview_realize (GtkWidget *widget); +static void gimp_preview_unrealize (GtkWidget *widget); +static void gimp_preview_map (GtkWidget *widget); +static void gimp_preview_unmap (GtkWidget *widget); static void gimp_preview_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gimp_preview_size_allocate (GtkWidget *widget, @@ -83,12 +86,13 @@ static void gimp_preview_update_callback (GimpPreviewRenderer *renderer static GimpViewable * gimp_preview_drag_viewable (GtkWidget *widget, gpointer data); -static void gimp_preview_set_back_pixmap (GimpPreview *preview); +static void gimp_preview_draw_background (GimpPreview *preview, + const GdkRectangle *area); static guint preview_signals[LAST_SIGNAL] = { 0 }; -static GtkDrawingAreaClass *parent_class = NULL; +static GtkWidgetClass *parent_class = NULL; GType @@ -111,7 +115,7 @@ gimp_preview_get_type (void) (GInstanceInitFunc) gimp_preview_init, }; - preview_type = g_type_register_static (GTK_TYPE_DRAWING_AREA, + preview_type = g_type_register_static (GTK_TYPE_WIDGET, "GimpPreview", &preview_info, 0); } @@ -162,6 +166,9 @@ gimp_preview_class_init (GimpPreviewClass *klass) widget_class->activate_signal = preview_signals[CLICKED]; widget_class->realize = gimp_preview_realize; + widget_class->unrealize = gimp_preview_unrealize; + widget_class->map = gimp_preview_map; + widget_class->unmap = gimp_preview_unmap; widget_class->size_request = gimp_preview_size_request; widget_class->size_allocate = gimp_preview_size_allocate; widget_class->expose_event = gimp_preview_expose_event; @@ -178,6 +185,8 @@ gimp_preview_class_init (GimpPreviewClass *klass) static void gimp_preview_init (GimpPreview *preview) { + GTK_WIDGET_SET_FLAGS (preview, GTK_NO_WINDOW); + preview->viewable = NULL; preview->renderer = NULL; @@ -189,8 +198,7 @@ gimp_preview_init (GimpPreview *preview) preview->in_button = FALSE; preview->bg_stock_id = NULL; - - gtk_widget_set_events (GTK_WIDGET (preview), PREVIEW_EVENT_MASK); + preview->bg_pixmap = NULL; } static void @@ -213,6 +221,11 @@ gimp_preview_destroy (GtkObject *object) g_free (preview->bg_stock_id); preview->bg_stock_id = NULL; } + if (preview->bg_pixmap) + { + g_object_unref (preview->bg_pixmap); + preview->bg_pixmap = NULL; + } GTK_OBJECT_CLASS (parent_class)->destroy (object); } @@ -220,9 +233,66 @@ gimp_preview_destroy (GtkObject *object) static void gimp_preview_realize (GtkWidget *widget) { - GTK_WIDGET_CLASS (parent_class)->realize (widget); + GimpPreview *preview; + GdkWindowAttr attributes; + gint attributes_mask; - gimp_preview_set_back_pixmap (GIMP_PREVIEW (widget)); + preview = GIMP_PREVIEW (widget); + + GTK_WIDGET_CLASS (parent_class)->realize (widget); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + + attributes.wclass = GDK_INPUT_ONLY; + attributes.event_mask = gtk_widget_get_events (widget); + attributes.event_mask |= PREVIEW_EVENT_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y; + + preview->event_window = gdk_window_new (widget->window, + &attributes, attributes_mask); + gdk_window_set_user_data (preview->event_window, preview); +} + +static void +gimp_preview_unrealize (GtkWidget *widget) +{ + GimpPreview *preview = GIMP_PREVIEW (widget); + + if (preview->event_window) + { + gdk_window_set_user_data (preview->event_window, NULL); + gdk_window_destroy (preview->event_window); + preview->event_window = NULL; + } + + GTK_WIDGET_CLASS (parent_class)->unrealize (widget); +} + +static void +gimp_preview_map (GtkWidget *widget) +{ + GimpPreview *preview = GIMP_PREVIEW (widget); + + GTK_WIDGET_CLASS (parent_class)->map (widget); + + if (preview->event_window) + gdk_window_show (preview->event_window); +} + +static void +gimp_preview_unmap (GtkWidget *widget) +{ + GimpPreview *preview = GIMP_PREVIEW (widget); + + if (preview->event_window) + gdk_window_hide (preview->event_window); + + GTK_WIDGET_CLASS (parent_class)->unmap (widget); } static void @@ -334,29 +404,32 @@ gimp_preview_size_allocate (GtkWidget *widget, allocation->width = width; allocation->height = height; - if (GTK_WIDGET_CLASS (parent_class)->size_allocate) - GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); + widget->allocation = *allocation; + + if (GTK_WIDGET_REALIZED (widget)) + gdk_window_move_resize (preview->event_window, + allocation->x, + allocation->y, + allocation->width, + allocation->height); } static gboolean gimp_preview_expose_event (GtkWidget *widget, GdkEventExpose *event) { - GimpPreview *preview; - GdkRectangle rect; - - preview = GIMP_PREVIEW (widget); + GimpPreview *preview; if (! GTK_WIDGET_DRAWABLE (widget)) return FALSE; - rect = widget->allocation; + preview = GIMP_PREVIEW (widget); - rect.x = rect.y = 0; + gimp_preview_draw_background (preview, &event->area); gimp_preview_renderer_draw (preview->renderer, widget->window, widget, - &rect, + &widget->allocation, &event->area); return FALSE; @@ -402,6 +475,9 @@ gimp_preview_button_press_event (GtkWidget *widget, if (preview->show_popup) { + bevent->x += widget->allocation.x; + bevent->y += widget->allocation.y; + gimp_preview_popup_show (widget, bevent, preview->viewable, preview->renderer->width, @@ -682,8 +758,6 @@ gimp_preview_set_viewable (GimpPreview *preview, g_object_add_weak_pointer (G_OBJECT (preview->viewable), (gpointer *) &preview->viewable); } - - gimp_preview_set_back_pixmap (preview); } void @@ -762,7 +836,10 @@ gimp_preview_set_background (GimpPreview *preview, preview->bg_stock_id = g_strdup (stock_id); - gimp_preview_set_back_pixmap (preview); + if (preview->bg_pixmap) + g_object_unref (preview->bg_pixmap); + + preview->bg_pixmap = NULL; } @@ -803,19 +880,23 @@ gimp_preview_drag_viewable (GtkWidget *widget, } static void -gimp_preview_set_back_pixmap (GimpPreview *preview) +gimp_preview_draw_background (GimpPreview *preview, + const GdkRectangle *area) { GtkWidget *widget; - GdkPixmap *pixmap = NULL; - + + if (!preview->bg_stock_id) + return; + if (! GTK_WIDGET_REALIZED (preview)) return; widget = GTK_WIDGET (preview); - if (preview->bg_stock_id && preview->viewable) + if (!preview->bg_pixmap); { GdkPixbuf *pixbuf; + GdkPixmap *pixmap; pixbuf = gtk_widget_render_icon (widget, preview->bg_stock_id, @@ -846,11 +927,30 @@ gimp_preview_set_back_pixmap (GimpPreview *preview) GDK_RGB_DITHER_NORMAL, 0, 0); g_object_unref (pixbuf); + + preview->bg_pixmap = pixmap; } } - gdk_window_set_back_pixmap (widget->window, pixmap, FALSE); + if (preview->bg_pixmap) + { + GdkGC *gc; + GdkGCValues values; - if (pixmap) - g_object_unref (pixmap); + values.fill = GDK_TILED; + values.tile = preview->bg_pixmap; + values.ts_x_origin = 0; + values.ts_y_origin = 0; + + gc = gdk_gc_new_with_values (GDK_DRAWABLE (widget->window), + &values, + GDK_GC_FILL | GDK_GC_TILE | + GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN); + + gdk_draw_rectangle (GDK_DRAWABLE (widget->window), gc, + TRUE, + area->x, area->y, area->width, area->height); + + g_object_unref (gc); + } } diff --git a/app/widgets/gimppreview.h b/app/widgets/gimppreview.h index 429cd18750..5b228ab5aa 100644 --- a/app/widgets/gimppreview.h +++ b/app/widgets/gimppreview.h @@ -23,9 +23,6 @@ #define __GIMP_PREVIEW_H__ -#include - - #define GIMP_TYPE_PREVIEW (gimp_preview_get_type ()) #define GIMP_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_PREVIEW, GimpPreview)) #define GIMP_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PREVIEW, GimpPreviewClass)) @@ -38,7 +35,9 @@ typedef struct _GimpPreviewClass GimpPreviewClass; struct _GimpPreview { - GtkDrawingArea parent_instance; + GtkWidget parent_instance; + + GdkWindow *event_window; GimpViewable *viewable; GimpPreviewRenderer *renderer; @@ -52,11 +51,12 @@ struct _GimpPreview gboolean in_button; GdkModifierType press_state; gchar *bg_stock_id; + GdkPixmap *bg_pixmap; }; struct _GimpPreviewClass { - GtkDrawingAreaClass parent_class; + GtkWidgetClass parent_class; /* signals */ void (* clicked) (GimpPreview *preview, diff --git a/app/widgets/gimppreviewrenderer.c b/app/widgets/gimppreviewrenderer.c index 260a102914..814f76b417 100644 --- a/app/widgets/gimppreviewrenderer.c +++ b/app/widgets/gimppreviewrenderer.c @@ -488,8 +488,8 @@ void gimp_preview_renderer_draw (GimpPreviewRenderer *renderer, GdkWindow *window, GtkWidget *widget, - GdkRectangle *draw_area, - GdkRectangle *expose_area) + const GdkRectangle *draw_area, + const GdkRectangle *expose_area) { GdkRectangle border_rect; GdkRectangle buf_rect; @@ -528,7 +528,8 @@ gimp_preview_renderer_draw (GimpPreviewRenderer *renderer, buf_rect.x += draw_area->x; buf_rect.y += draw_area->y; - if (gdk_rectangle_intersect (&buf_rect, expose_area, &render_rect)) + if (gdk_rectangle_intersect (&buf_rect, (GdkRectangle *) expose_area, + &render_rect)) { gdk_draw_pixbuf (GDK_DRAWABLE (window), widget->style->bg_gc[widget->state], @@ -550,7 +551,8 @@ gimp_preview_renderer_draw (GimpPreviewRenderer *renderer, buf_rect.width = renderer->width; buf_rect.height = renderer->height; - if (gdk_rectangle_intersect (&buf_rect, expose_area, &render_rect)) + if (gdk_rectangle_intersect (&buf_rect, (GdkRectangle *) expose_area, + &render_rect)) { guchar *buf; diff --git a/app/widgets/gimppreviewrenderer.h b/app/widgets/gimppreviewrenderer.h index c3f0ec68a3..1c435348e0 100644 --- a/app/widgets/gimppreviewrenderer.h +++ b/app/widgets/gimppreviewrenderer.h @@ -110,8 +110,8 @@ void gimp_preview_renderer_remove_idle (GimpPreviewRenderer *renderer); void gimp_preview_renderer_draw (GimpPreviewRenderer *renderer, GdkWindow *window, GtkWidget *widget, - GdkRectangle *draw_area, - GdkRectangle *expose_area); + const GdkRectangle *draw_area, + const GdkRectangle *expose_area); /* protected */ diff --git a/app/widgets/gimpview.c b/app/widgets/gimpview.c index ca95efa234..6e1f52b220 100644 --- a/app/widgets/gimpview.c +++ b/app/widgets/gimpview.c @@ -62,6 +62,9 @@ static void gimp_preview_init (GimpPreview *preview) static void gimp_preview_destroy (GtkObject *object); static void gimp_preview_realize (GtkWidget *widget); +static void gimp_preview_unrealize (GtkWidget *widget); +static void gimp_preview_map (GtkWidget *widget); +static void gimp_preview_unmap (GtkWidget *widget); static void gimp_preview_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gimp_preview_size_allocate (GtkWidget *widget, @@ -83,12 +86,13 @@ static void gimp_preview_update_callback (GimpPreviewRenderer *renderer static GimpViewable * gimp_preview_drag_viewable (GtkWidget *widget, gpointer data); -static void gimp_preview_set_back_pixmap (GimpPreview *preview); +static void gimp_preview_draw_background (GimpPreview *preview, + const GdkRectangle *area); static guint preview_signals[LAST_SIGNAL] = { 0 }; -static GtkDrawingAreaClass *parent_class = NULL; +static GtkWidgetClass *parent_class = NULL; GType @@ -111,7 +115,7 @@ gimp_preview_get_type (void) (GInstanceInitFunc) gimp_preview_init, }; - preview_type = g_type_register_static (GTK_TYPE_DRAWING_AREA, + preview_type = g_type_register_static (GTK_TYPE_WIDGET, "GimpPreview", &preview_info, 0); } @@ -162,6 +166,9 @@ gimp_preview_class_init (GimpPreviewClass *klass) widget_class->activate_signal = preview_signals[CLICKED]; widget_class->realize = gimp_preview_realize; + widget_class->unrealize = gimp_preview_unrealize; + widget_class->map = gimp_preview_map; + widget_class->unmap = gimp_preview_unmap; widget_class->size_request = gimp_preview_size_request; widget_class->size_allocate = gimp_preview_size_allocate; widget_class->expose_event = gimp_preview_expose_event; @@ -178,6 +185,8 @@ gimp_preview_class_init (GimpPreviewClass *klass) static void gimp_preview_init (GimpPreview *preview) { + GTK_WIDGET_SET_FLAGS (preview, GTK_NO_WINDOW); + preview->viewable = NULL; preview->renderer = NULL; @@ -189,8 +198,7 @@ gimp_preview_init (GimpPreview *preview) preview->in_button = FALSE; preview->bg_stock_id = NULL; - - gtk_widget_set_events (GTK_WIDGET (preview), PREVIEW_EVENT_MASK); + preview->bg_pixmap = NULL; } static void @@ -213,6 +221,11 @@ gimp_preview_destroy (GtkObject *object) g_free (preview->bg_stock_id); preview->bg_stock_id = NULL; } + if (preview->bg_pixmap) + { + g_object_unref (preview->bg_pixmap); + preview->bg_pixmap = NULL; + } GTK_OBJECT_CLASS (parent_class)->destroy (object); } @@ -220,9 +233,66 @@ gimp_preview_destroy (GtkObject *object) static void gimp_preview_realize (GtkWidget *widget) { - GTK_WIDGET_CLASS (parent_class)->realize (widget); + GimpPreview *preview; + GdkWindowAttr attributes; + gint attributes_mask; - gimp_preview_set_back_pixmap (GIMP_PREVIEW (widget)); + preview = GIMP_PREVIEW (widget); + + GTK_WIDGET_CLASS (parent_class)->realize (widget); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + + attributes.wclass = GDK_INPUT_ONLY; + attributes.event_mask = gtk_widget_get_events (widget); + attributes.event_mask |= PREVIEW_EVENT_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y; + + preview->event_window = gdk_window_new (widget->window, + &attributes, attributes_mask); + gdk_window_set_user_data (preview->event_window, preview); +} + +static void +gimp_preview_unrealize (GtkWidget *widget) +{ + GimpPreview *preview = GIMP_PREVIEW (widget); + + if (preview->event_window) + { + gdk_window_set_user_data (preview->event_window, NULL); + gdk_window_destroy (preview->event_window); + preview->event_window = NULL; + } + + GTK_WIDGET_CLASS (parent_class)->unrealize (widget); +} + +static void +gimp_preview_map (GtkWidget *widget) +{ + GimpPreview *preview = GIMP_PREVIEW (widget); + + GTK_WIDGET_CLASS (parent_class)->map (widget); + + if (preview->event_window) + gdk_window_show (preview->event_window); +} + +static void +gimp_preview_unmap (GtkWidget *widget) +{ + GimpPreview *preview = GIMP_PREVIEW (widget); + + if (preview->event_window) + gdk_window_hide (preview->event_window); + + GTK_WIDGET_CLASS (parent_class)->unmap (widget); } static void @@ -334,29 +404,32 @@ gimp_preview_size_allocate (GtkWidget *widget, allocation->width = width; allocation->height = height; - if (GTK_WIDGET_CLASS (parent_class)->size_allocate) - GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); + widget->allocation = *allocation; + + if (GTK_WIDGET_REALIZED (widget)) + gdk_window_move_resize (preview->event_window, + allocation->x, + allocation->y, + allocation->width, + allocation->height); } static gboolean gimp_preview_expose_event (GtkWidget *widget, GdkEventExpose *event) { - GimpPreview *preview; - GdkRectangle rect; - - preview = GIMP_PREVIEW (widget); + GimpPreview *preview; if (! GTK_WIDGET_DRAWABLE (widget)) return FALSE; - rect = widget->allocation; + preview = GIMP_PREVIEW (widget); - rect.x = rect.y = 0; + gimp_preview_draw_background (preview, &event->area); gimp_preview_renderer_draw (preview->renderer, widget->window, widget, - &rect, + &widget->allocation, &event->area); return FALSE; @@ -402,6 +475,9 @@ gimp_preview_button_press_event (GtkWidget *widget, if (preview->show_popup) { + bevent->x += widget->allocation.x; + bevent->y += widget->allocation.y; + gimp_preview_popup_show (widget, bevent, preview->viewable, preview->renderer->width, @@ -682,8 +758,6 @@ gimp_preview_set_viewable (GimpPreview *preview, g_object_add_weak_pointer (G_OBJECT (preview->viewable), (gpointer *) &preview->viewable); } - - gimp_preview_set_back_pixmap (preview); } void @@ -762,7 +836,10 @@ gimp_preview_set_background (GimpPreview *preview, preview->bg_stock_id = g_strdup (stock_id); - gimp_preview_set_back_pixmap (preview); + if (preview->bg_pixmap) + g_object_unref (preview->bg_pixmap); + + preview->bg_pixmap = NULL; } @@ -803,19 +880,23 @@ gimp_preview_drag_viewable (GtkWidget *widget, } static void -gimp_preview_set_back_pixmap (GimpPreview *preview) +gimp_preview_draw_background (GimpPreview *preview, + const GdkRectangle *area) { GtkWidget *widget; - GdkPixmap *pixmap = NULL; - + + if (!preview->bg_stock_id) + return; + if (! GTK_WIDGET_REALIZED (preview)) return; widget = GTK_WIDGET (preview); - if (preview->bg_stock_id && preview->viewable) + if (!preview->bg_pixmap); { GdkPixbuf *pixbuf; + GdkPixmap *pixmap; pixbuf = gtk_widget_render_icon (widget, preview->bg_stock_id, @@ -846,11 +927,30 @@ gimp_preview_set_back_pixmap (GimpPreview *preview) GDK_RGB_DITHER_NORMAL, 0, 0); g_object_unref (pixbuf); + + preview->bg_pixmap = pixmap; } } - gdk_window_set_back_pixmap (widget->window, pixmap, FALSE); + if (preview->bg_pixmap) + { + GdkGC *gc; + GdkGCValues values; - if (pixmap) - g_object_unref (pixmap); + values.fill = GDK_TILED; + values.tile = preview->bg_pixmap; + values.ts_x_origin = 0; + values.ts_y_origin = 0; + + gc = gdk_gc_new_with_values (GDK_DRAWABLE (widget->window), + &values, + GDK_GC_FILL | GDK_GC_TILE | + GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN); + + gdk_draw_rectangle (GDK_DRAWABLE (widget->window), gc, + TRUE, + area->x, area->y, area->width, area->height); + + g_object_unref (gc); + } } diff --git a/app/widgets/gimpview.h b/app/widgets/gimpview.h index 429cd18750..5b228ab5aa 100644 --- a/app/widgets/gimpview.h +++ b/app/widgets/gimpview.h @@ -23,9 +23,6 @@ #define __GIMP_PREVIEW_H__ -#include - - #define GIMP_TYPE_PREVIEW (gimp_preview_get_type ()) #define GIMP_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_PREVIEW, GimpPreview)) #define GIMP_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PREVIEW, GimpPreviewClass)) @@ -38,7 +35,9 @@ typedef struct _GimpPreviewClass GimpPreviewClass; struct _GimpPreview { - GtkDrawingArea parent_instance; + GtkWidget parent_instance; + + GdkWindow *event_window; GimpViewable *viewable; GimpPreviewRenderer *renderer; @@ -52,11 +51,12 @@ struct _GimpPreview gboolean in_button; GdkModifierType press_state; gchar *bg_stock_id; + GdkPixmap *bg_pixmap; }; struct _GimpPreviewClass { - GtkDrawingAreaClass parent_class; + GtkWidgetClass parent_class; /* signals */ void (* clicked) (GimpPreview *preview, diff --git a/app/widgets/gimpviewrenderer.c b/app/widgets/gimpviewrenderer.c index 260a102914..814f76b417 100644 --- a/app/widgets/gimpviewrenderer.c +++ b/app/widgets/gimpviewrenderer.c @@ -488,8 +488,8 @@ void gimp_preview_renderer_draw (GimpPreviewRenderer *renderer, GdkWindow *window, GtkWidget *widget, - GdkRectangle *draw_area, - GdkRectangle *expose_area) + const GdkRectangle *draw_area, + const GdkRectangle *expose_area) { GdkRectangle border_rect; GdkRectangle buf_rect; @@ -528,7 +528,8 @@ gimp_preview_renderer_draw (GimpPreviewRenderer *renderer, buf_rect.x += draw_area->x; buf_rect.y += draw_area->y; - if (gdk_rectangle_intersect (&buf_rect, expose_area, &render_rect)) + if (gdk_rectangle_intersect (&buf_rect, (GdkRectangle *) expose_area, + &render_rect)) { gdk_draw_pixbuf (GDK_DRAWABLE (window), widget->style->bg_gc[widget->state], @@ -550,7 +551,8 @@ gimp_preview_renderer_draw (GimpPreviewRenderer *renderer, buf_rect.width = renderer->width; buf_rect.height = renderer->height; - if (gdk_rectangle_intersect (&buf_rect, expose_area, &render_rect)) + if (gdk_rectangle_intersect (&buf_rect, (GdkRectangle *) expose_area, + &render_rect)) { guchar *buf; diff --git a/app/widgets/gimpviewrenderer.h b/app/widgets/gimpviewrenderer.h index c3f0ec68a3..1c435348e0 100644 --- a/app/widgets/gimpviewrenderer.h +++ b/app/widgets/gimpviewrenderer.h @@ -110,8 +110,8 @@ void gimp_preview_renderer_remove_idle (GimpPreviewRenderer *renderer); void gimp_preview_renderer_draw (GimpPreviewRenderer *renderer, GdkWindow *window, GtkWidget *widget, - GdkRectangle *draw_area, - GdkRectangle *expose_area); + const GdkRectangle *draw_area, + const GdkRectangle *expose_area); /* protected */