made GimpPreview a NO_WINDOW widget that draws on the parent window. Added

2003-04-11  Sven Neumann  <sven@gimp.org>

	* 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.
This commit is contained in:
Sven Neumann
2003-04-11 08:37:26 +00:00
committed by Sven Neumann
parent df228e7814
commit 6d8249bd86
11 changed files with 324 additions and 96 deletions

View File

@ -1,3 +1,15 @@
2003-04-11 Sven Neumann <sven@gimp.org>
* 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 <mitch@gimp.org> 2003-04-10 Michael Natterer <mitch@gimp.org>
* app/gui/file-new-dialog.c: added Portrait/Landscape radio * app/gui/file-new-dialog.c: added Portrait/Landscape radio

View File

@ -292,6 +292,7 @@ gimp_navigation_preview_grab_pointer (GimpNavigationPreview *nav_preview)
{ {
GtkWidget *widget; GtkWidget *widget;
GdkCursor *cursor; GdkCursor *cursor;
GdkWindow *window;
widget = GTK_WIDGET (nav_preview); widget = GTK_WIDGET (nav_preview);
@ -301,12 +302,14 @@ gimp_navigation_preview_grab_pointer (GimpNavigationPreview *nav_preview)
cursor = gdk_cursor_new (GDK_FLEUR); cursor = gdk_cursor_new (GDK_FLEUR);
gdk_pointer_grab (widget->window, TRUE, window = GIMP_PREVIEW (nav_preview)->event_window;
GDK_BUTTON_RELEASE_MASK |
gdk_pointer_grab (window, TRUE,
GDK_BUTTON_RELEASE_MASK |
GDK_POINTER_MOTION_HINT_MASK | GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON_MOTION_MASK | GDK_BUTTON_MOTION_MASK |
GDK_EXTENSION_EVENTS_ALL, GDK_EXTENSION_EVENTS_ALL,
widget->window, cursor, 0); window, cursor, 0);
gdk_cursor_unref (cursor); gdk_cursor_unref (cursor);
} }
@ -449,9 +452,9 @@ gimp_navigation_preview_motion_notify (GtkWidget *widget,
return FALSE; return FALSE;
} }
else if (mevent->x >= nav_preview->p_x && else if (mevent->x >= nav_preview->p_x &&
mevent->y >= nav_preview->p_y && mevent->y >= nav_preview->p_y &&
mevent->x < nav_preview->p_x + nav_preview->p_width && 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 + nav_preview->p_height)
{ {
cursor = gdk_cursor_new (GDK_FLEUR); cursor = gdk_cursor_new (GDK_FLEUR);
} }
@ -466,7 +469,8 @@ gimp_navigation_preview_motion_notify (GtkWidget *widget,
return FALSE; 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; tx -= nav_preview->motion_offset_x;
ty -= nav_preview->motion_offset_y; 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->width < gimage->width ||
nav_preview->height < gimage->height) nav_preview->height < gimage->height)
{ {
GtkWidget *widget = GTK_WIDGET (preview);
if (area) if (area)
gdk_gc_set_clip_rectangle (nav_preview->gc, 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, FALSE,
nav_preview->p_x + 1, widget->allocation.x + nav_preview->p_x + 1,
nav_preview->p_y + 1, widget->allocation.y + nav_preview->p_y + 1,
MAX (1, nav_preview->p_width - BORDER_PEN_WIDTH), MAX (1, nav_preview->p_width - BORDER_PEN_WIDTH),
MAX (1, nav_preview->p_height - BORDER_PEN_WIDTH)); MAX (1, nav_preview->p_height - BORDER_PEN_WIDTH));

View File

@ -292,6 +292,7 @@ gimp_navigation_preview_grab_pointer (GimpNavigationPreview *nav_preview)
{ {
GtkWidget *widget; GtkWidget *widget;
GdkCursor *cursor; GdkCursor *cursor;
GdkWindow *window;
widget = GTK_WIDGET (nav_preview); widget = GTK_WIDGET (nav_preview);
@ -301,12 +302,14 @@ gimp_navigation_preview_grab_pointer (GimpNavigationPreview *nav_preview)
cursor = gdk_cursor_new (GDK_FLEUR); cursor = gdk_cursor_new (GDK_FLEUR);
gdk_pointer_grab (widget->window, TRUE, window = GIMP_PREVIEW (nav_preview)->event_window;
GDK_BUTTON_RELEASE_MASK |
gdk_pointer_grab (window, TRUE,
GDK_BUTTON_RELEASE_MASK |
GDK_POINTER_MOTION_HINT_MASK | GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON_MOTION_MASK | GDK_BUTTON_MOTION_MASK |
GDK_EXTENSION_EVENTS_ALL, GDK_EXTENSION_EVENTS_ALL,
widget->window, cursor, 0); window, cursor, 0);
gdk_cursor_unref (cursor); gdk_cursor_unref (cursor);
} }
@ -449,9 +452,9 @@ gimp_navigation_preview_motion_notify (GtkWidget *widget,
return FALSE; return FALSE;
} }
else if (mevent->x >= nav_preview->p_x && else if (mevent->x >= nav_preview->p_x &&
mevent->y >= nav_preview->p_y && mevent->y >= nav_preview->p_y &&
mevent->x < nav_preview->p_x + nav_preview->p_width && 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 + nav_preview->p_height)
{ {
cursor = gdk_cursor_new (GDK_FLEUR); cursor = gdk_cursor_new (GDK_FLEUR);
} }
@ -466,7 +469,8 @@ gimp_navigation_preview_motion_notify (GtkWidget *widget,
return FALSE; 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; tx -= nav_preview->motion_offset_x;
ty -= nav_preview->motion_offset_y; 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->width < gimage->width ||
nav_preview->height < gimage->height) nav_preview->height < gimage->height)
{ {
GtkWidget *widget = GTK_WIDGET (preview);
if (area) if (area)
gdk_gc_set_clip_rectangle (nav_preview->gc, 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, FALSE,
nav_preview->p_x + 1, widget->allocation.x + nav_preview->p_x + 1,
nav_preview->p_y + 1, widget->allocation.y + nav_preview->p_y + 1,
MAX (1, nav_preview->p_width - BORDER_PEN_WIDTH), MAX (1, nav_preview->p_width - BORDER_PEN_WIDTH),
MAX (1, nav_preview->p_height - BORDER_PEN_WIDTH)); MAX (1, nav_preview->p_height - BORDER_PEN_WIDTH));

View File

@ -62,6 +62,9 @@ static void gimp_preview_init (GimpPreview *preview)
static void gimp_preview_destroy (GtkObject *object); static void gimp_preview_destroy (GtkObject *object);
static void gimp_preview_realize (GtkWidget *widget); 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, static void gimp_preview_size_request (GtkWidget *widget,
GtkRequisition *requisition); GtkRequisition *requisition);
static void gimp_preview_size_allocate (GtkWidget *widget, 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, static GimpViewable * gimp_preview_drag_viewable (GtkWidget *widget,
gpointer data); 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 guint preview_signals[LAST_SIGNAL] = { 0 };
static GtkDrawingAreaClass *parent_class = NULL; static GtkWidgetClass *parent_class = NULL;
GType GType
@ -111,7 +115,7 @@ gimp_preview_get_type (void)
(GInstanceInitFunc) gimp_preview_init, (GInstanceInitFunc) gimp_preview_init,
}; };
preview_type = g_type_register_static (GTK_TYPE_DRAWING_AREA, preview_type = g_type_register_static (GTK_TYPE_WIDGET,
"GimpPreview", "GimpPreview",
&preview_info, 0); &preview_info, 0);
} }
@ -162,6 +166,9 @@ gimp_preview_class_init (GimpPreviewClass *klass)
widget_class->activate_signal = preview_signals[CLICKED]; widget_class->activate_signal = preview_signals[CLICKED];
widget_class->realize = gimp_preview_realize; 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_request = gimp_preview_size_request;
widget_class->size_allocate = gimp_preview_size_allocate; widget_class->size_allocate = gimp_preview_size_allocate;
widget_class->expose_event = gimp_preview_expose_event; widget_class->expose_event = gimp_preview_expose_event;
@ -178,6 +185,8 @@ gimp_preview_class_init (GimpPreviewClass *klass)
static void static void
gimp_preview_init (GimpPreview *preview) gimp_preview_init (GimpPreview *preview)
{ {
GTK_WIDGET_SET_FLAGS (preview, GTK_NO_WINDOW);
preview->viewable = NULL; preview->viewable = NULL;
preview->renderer = NULL; preview->renderer = NULL;
@ -189,8 +198,7 @@ gimp_preview_init (GimpPreview *preview)
preview->in_button = FALSE; preview->in_button = FALSE;
preview->bg_stock_id = NULL; preview->bg_stock_id = NULL;
preview->bg_pixmap = NULL;
gtk_widget_set_events (GTK_WIDGET (preview), PREVIEW_EVENT_MASK);
} }
static void static void
@ -213,6 +221,11 @@ gimp_preview_destroy (GtkObject *object)
g_free (preview->bg_stock_id); g_free (preview->bg_stock_id);
preview->bg_stock_id = NULL; 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); GTK_OBJECT_CLASS (parent_class)->destroy (object);
} }
@ -220,9 +233,66 @@ gimp_preview_destroy (GtkObject *object)
static void static void
gimp_preview_realize (GtkWidget *widget) 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 static void
@ -334,29 +404,32 @@ gimp_preview_size_allocate (GtkWidget *widget,
allocation->width = width; allocation->width = width;
allocation->height = height; allocation->height = height;
if (GTK_WIDGET_CLASS (parent_class)->size_allocate) widget->allocation = *allocation;
GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
if (GTK_WIDGET_REALIZED (widget))
gdk_window_move_resize (preview->event_window,
allocation->x,
allocation->y,
allocation->width,
allocation->height);
} }
static gboolean static gboolean
gimp_preview_expose_event (GtkWidget *widget, gimp_preview_expose_event (GtkWidget *widget,
GdkEventExpose *event) GdkEventExpose *event)
{ {
GimpPreview *preview; GimpPreview *preview;
GdkRectangle rect;
preview = GIMP_PREVIEW (widget);
if (! GTK_WIDGET_DRAWABLE (widget)) if (! GTK_WIDGET_DRAWABLE (widget))
return FALSE; 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, gimp_preview_renderer_draw (preview->renderer,
widget->window, widget, widget->window, widget,
&rect, &widget->allocation,
&event->area); &event->area);
return FALSE; return FALSE;
@ -402,6 +475,9 @@ gimp_preview_button_press_event (GtkWidget *widget,
if (preview->show_popup) if (preview->show_popup)
{ {
bevent->x += widget->allocation.x;
bevent->y += widget->allocation.y;
gimp_preview_popup_show (widget, bevent, gimp_preview_popup_show (widget, bevent,
preview->viewable, preview->viewable,
preview->renderer->width, preview->renderer->width,
@ -682,8 +758,6 @@ gimp_preview_set_viewable (GimpPreview *preview,
g_object_add_weak_pointer (G_OBJECT (preview->viewable), g_object_add_weak_pointer (G_OBJECT (preview->viewable),
(gpointer *) &preview->viewable); (gpointer *) &preview->viewable);
} }
gimp_preview_set_back_pixmap (preview);
} }
void void
@ -762,7 +836,10 @@ gimp_preview_set_background (GimpPreview *preview,
preview->bg_stock_id = g_strdup (stock_id); 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 static void
gimp_preview_set_back_pixmap (GimpPreview *preview) gimp_preview_draw_background (GimpPreview *preview,
const GdkRectangle *area)
{ {
GtkWidget *widget; GtkWidget *widget;
GdkPixmap *pixmap = NULL;
if (!preview->bg_stock_id)
return;
if (! GTK_WIDGET_REALIZED (preview)) if (! GTK_WIDGET_REALIZED (preview))
return; return;
widget = GTK_WIDGET (preview); widget = GTK_WIDGET (preview);
if (preview->bg_stock_id && preview->viewable) if (!preview->bg_pixmap);
{ {
GdkPixbuf *pixbuf; GdkPixbuf *pixbuf;
GdkPixmap *pixmap;
pixbuf = gtk_widget_render_icon (widget, pixbuf = gtk_widget_render_icon (widget,
preview->bg_stock_id, preview->bg_stock_id,
@ -846,11 +927,30 @@ gimp_preview_set_back_pixmap (GimpPreview *preview)
GDK_RGB_DITHER_NORMAL, 0, 0); GDK_RGB_DITHER_NORMAL, 0, 0);
g_object_unref (pixbuf); 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) values.fill = GDK_TILED;
g_object_unref (pixmap); 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);
}
} }

View File

@ -23,9 +23,6 @@
#define __GIMP_PREVIEW_H__ #define __GIMP_PREVIEW_H__
#include <gtk/gtkdrawingarea.h>
#define GIMP_TYPE_PREVIEW (gimp_preview_get_type ()) #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(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)) #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 struct _GimpPreview
{ {
GtkDrawingArea parent_instance; GtkWidget parent_instance;
GdkWindow *event_window;
GimpViewable *viewable; GimpViewable *viewable;
GimpPreviewRenderer *renderer; GimpPreviewRenderer *renderer;
@ -52,11 +51,12 @@ struct _GimpPreview
gboolean in_button; gboolean in_button;
GdkModifierType press_state; GdkModifierType press_state;
gchar *bg_stock_id; gchar *bg_stock_id;
GdkPixmap *bg_pixmap;
}; };
struct _GimpPreviewClass struct _GimpPreviewClass
{ {
GtkDrawingAreaClass parent_class; GtkWidgetClass parent_class;
/* signals */ /* signals */
void (* clicked) (GimpPreview *preview, void (* clicked) (GimpPreview *preview,

View File

@ -488,8 +488,8 @@ void
gimp_preview_renderer_draw (GimpPreviewRenderer *renderer, gimp_preview_renderer_draw (GimpPreviewRenderer *renderer,
GdkWindow *window, GdkWindow *window,
GtkWidget *widget, GtkWidget *widget,
GdkRectangle *draw_area, const GdkRectangle *draw_area,
GdkRectangle *expose_area) const GdkRectangle *expose_area)
{ {
GdkRectangle border_rect; GdkRectangle border_rect;
GdkRectangle buf_rect; GdkRectangle buf_rect;
@ -528,7 +528,8 @@ gimp_preview_renderer_draw (GimpPreviewRenderer *renderer,
buf_rect.x += draw_area->x; buf_rect.x += draw_area->x;
buf_rect.y += draw_area->y; 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), gdk_draw_pixbuf (GDK_DRAWABLE (window),
widget->style->bg_gc[widget->state], widget->style->bg_gc[widget->state],
@ -550,7 +551,8 @@ gimp_preview_renderer_draw (GimpPreviewRenderer *renderer,
buf_rect.width = renderer->width; buf_rect.width = renderer->width;
buf_rect.height = renderer->height; 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; guchar *buf;

View File

@ -110,8 +110,8 @@ void gimp_preview_renderer_remove_idle (GimpPreviewRenderer *renderer);
void gimp_preview_renderer_draw (GimpPreviewRenderer *renderer, void gimp_preview_renderer_draw (GimpPreviewRenderer *renderer,
GdkWindow *window, GdkWindow *window,
GtkWidget *widget, GtkWidget *widget,
GdkRectangle *draw_area, const GdkRectangle *draw_area,
GdkRectangle *expose_area); const GdkRectangle *expose_area);
/* protected */ /* protected */

View File

@ -62,6 +62,9 @@ static void gimp_preview_init (GimpPreview *preview)
static void gimp_preview_destroy (GtkObject *object); static void gimp_preview_destroy (GtkObject *object);
static void gimp_preview_realize (GtkWidget *widget); 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, static void gimp_preview_size_request (GtkWidget *widget,
GtkRequisition *requisition); GtkRequisition *requisition);
static void gimp_preview_size_allocate (GtkWidget *widget, 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, static GimpViewable * gimp_preview_drag_viewable (GtkWidget *widget,
gpointer data); 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 guint preview_signals[LAST_SIGNAL] = { 0 };
static GtkDrawingAreaClass *parent_class = NULL; static GtkWidgetClass *parent_class = NULL;
GType GType
@ -111,7 +115,7 @@ gimp_preview_get_type (void)
(GInstanceInitFunc) gimp_preview_init, (GInstanceInitFunc) gimp_preview_init,
}; };
preview_type = g_type_register_static (GTK_TYPE_DRAWING_AREA, preview_type = g_type_register_static (GTK_TYPE_WIDGET,
"GimpPreview", "GimpPreview",
&preview_info, 0); &preview_info, 0);
} }
@ -162,6 +166,9 @@ gimp_preview_class_init (GimpPreviewClass *klass)
widget_class->activate_signal = preview_signals[CLICKED]; widget_class->activate_signal = preview_signals[CLICKED];
widget_class->realize = gimp_preview_realize; 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_request = gimp_preview_size_request;
widget_class->size_allocate = gimp_preview_size_allocate; widget_class->size_allocate = gimp_preview_size_allocate;
widget_class->expose_event = gimp_preview_expose_event; widget_class->expose_event = gimp_preview_expose_event;
@ -178,6 +185,8 @@ gimp_preview_class_init (GimpPreviewClass *klass)
static void static void
gimp_preview_init (GimpPreview *preview) gimp_preview_init (GimpPreview *preview)
{ {
GTK_WIDGET_SET_FLAGS (preview, GTK_NO_WINDOW);
preview->viewable = NULL; preview->viewable = NULL;
preview->renderer = NULL; preview->renderer = NULL;
@ -189,8 +198,7 @@ gimp_preview_init (GimpPreview *preview)
preview->in_button = FALSE; preview->in_button = FALSE;
preview->bg_stock_id = NULL; preview->bg_stock_id = NULL;
preview->bg_pixmap = NULL;
gtk_widget_set_events (GTK_WIDGET (preview), PREVIEW_EVENT_MASK);
} }
static void static void
@ -213,6 +221,11 @@ gimp_preview_destroy (GtkObject *object)
g_free (preview->bg_stock_id); g_free (preview->bg_stock_id);
preview->bg_stock_id = NULL; 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); GTK_OBJECT_CLASS (parent_class)->destroy (object);
} }
@ -220,9 +233,66 @@ gimp_preview_destroy (GtkObject *object)
static void static void
gimp_preview_realize (GtkWidget *widget) 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 static void
@ -334,29 +404,32 @@ gimp_preview_size_allocate (GtkWidget *widget,
allocation->width = width; allocation->width = width;
allocation->height = height; allocation->height = height;
if (GTK_WIDGET_CLASS (parent_class)->size_allocate) widget->allocation = *allocation;
GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
if (GTK_WIDGET_REALIZED (widget))
gdk_window_move_resize (preview->event_window,
allocation->x,
allocation->y,
allocation->width,
allocation->height);
} }
static gboolean static gboolean
gimp_preview_expose_event (GtkWidget *widget, gimp_preview_expose_event (GtkWidget *widget,
GdkEventExpose *event) GdkEventExpose *event)
{ {
GimpPreview *preview; GimpPreview *preview;
GdkRectangle rect;
preview = GIMP_PREVIEW (widget);
if (! GTK_WIDGET_DRAWABLE (widget)) if (! GTK_WIDGET_DRAWABLE (widget))
return FALSE; 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, gimp_preview_renderer_draw (preview->renderer,
widget->window, widget, widget->window, widget,
&rect, &widget->allocation,
&event->area); &event->area);
return FALSE; return FALSE;
@ -402,6 +475,9 @@ gimp_preview_button_press_event (GtkWidget *widget,
if (preview->show_popup) if (preview->show_popup)
{ {
bevent->x += widget->allocation.x;
bevent->y += widget->allocation.y;
gimp_preview_popup_show (widget, bevent, gimp_preview_popup_show (widget, bevent,
preview->viewable, preview->viewable,
preview->renderer->width, preview->renderer->width,
@ -682,8 +758,6 @@ gimp_preview_set_viewable (GimpPreview *preview,
g_object_add_weak_pointer (G_OBJECT (preview->viewable), g_object_add_weak_pointer (G_OBJECT (preview->viewable),
(gpointer *) &preview->viewable); (gpointer *) &preview->viewable);
} }
gimp_preview_set_back_pixmap (preview);
} }
void void
@ -762,7 +836,10 @@ gimp_preview_set_background (GimpPreview *preview,
preview->bg_stock_id = g_strdup (stock_id); 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 static void
gimp_preview_set_back_pixmap (GimpPreview *preview) gimp_preview_draw_background (GimpPreview *preview,
const GdkRectangle *area)
{ {
GtkWidget *widget; GtkWidget *widget;
GdkPixmap *pixmap = NULL;
if (!preview->bg_stock_id)
return;
if (! GTK_WIDGET_REALIZED (preview)) if (! GTK_WIDGET_REALIZED (preview))
return; return;
widget = GTK_WIDGET (preview); widget = GTK_WIDGET (preview);
if (preview->bg_stock_id && preview->viewable) if (!preview->bg_pixmap);
{ {
GdkPixbuf *pixbuf; GdkPixbuf *pixbuf;
GdkPixmap *pixmap;
pixbuf = gtk_widget_render_icon (widget, pixbuf = gtk_widget_render_icon (widget,
preview->bg_stock_id, preview->bg_stock_id,
@ -846,11 +927,30 @@ gimp_preview_set_back_pixmap (GimpPreview *preview)
GDK_RGB_DITHER_NORMAL, 0, 0); GDK_RGB_DITHER_NORMAL, 0, 0);
g_object_unref (pixbuf); 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) values.fill = GDK_TILED;
g_object_unref (pixmap); 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);
}
} }

View File

@ -23,9 +23,6 @@
#define __GIMP_PREVIEW_H__ #define __GIMP_PREVIEW_H__
#include <gtk/gtkdrawingarea.h>
#define GIMP_TYPE_PREVIEW (gimp_preview_get_type ()) #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(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)) #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 struct _GimpPreview
{ {
GtkDrawingArea parent_instance; GtkWidget parent_instance;
GdkWindow *event_window;
GimpViewable *viewable; GimpViewable *viewable;
GimpPreviewRenderer *renderer; GimpPreviewRenderer *renderer;
@ -52,11 +51,12 @@ struct _GimpPreview
gboolean in_button; gboolean in_button;
GdkModifierType press_state; GdkModifierType press_state;
gchar *bg_stock_id; gchar *bg_stock_id;
GdkPixmap *bg_pixmap;
}; };
struct _GimpPreviewClass struct _GimpPreviewClass
{ {
GtkDrawingAreaClass parent_class; GtkWidgetClass parent_class;
/* signals */ /* signals */
void (* clicked) (GimpPreview *preview, void (* clicked) (GimpPreview *preview,

View File

@ -488,8 +488,8 @@ void
gimp_preview_renderer_draw (GimpPreviewRenderer *renderer, gimp_preview_renderer_draw (GimpPreviewRenderer *renderer,
GdkWindow *window, GdkWindow *window,
GtkWidget *widget, GtkWidget *widget,
GdkRectangle *draw_area, const GdkRectangle *draw_area,
GdkRectangle *expose_area) const GdkRectangle *expose_area)
{ {
GdkRectangle border_rect; GdkRectangle border_rect;
GdkRectangle buf_rect; GdkRectangle buf_rect;
@ -528,7 +528,8 @@ gimp_preview_renderer_draw (GimpPreviewRenderer *renderer,
buf_rect.x += draw_area->x; buf_rect.x += draw_area->x;
buf_rect.y += draw_area->y; 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), gdk_draw_pixbuf (GDK_DRAWABLE (window),
widget->style->bg_gc[widget->state], widget->style->bg_gc[widget->state],
@ -550,7 +551,8 @@ gimp_preview_renderer_draw (GimpPreviewRenderer *renderer,
buf_rect.width = renderer->width; buf_rect.width = renderer->width;
buf_rect.height = renderer->height; 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; guchar *buf;

View File

@ -110,8 +110,8 @@ void gimp_preview_renderer_remove_idle (GimpPreviewRenderer *renderer);
void gimp_preview_renderer_draw (GimpPreviewRenderer *renderer, void gimp_preview_renderer_draw (GimpPreviewRenderer *renderer,
GdkWindow *window, GdkWindow *window,
GtkWidget *widget, GtkWidget *widget,
GdkRectangle *draw_area, const GdkRectangle *draw_area,
GdkRectangle *expose_area); const GdkRectangle *expose_area);
/* protected */ /* protected */