API: Add gtk_cairo_transform_to_window()

The function reverses the transform that GTK does before emitting a draw
event. So we can use it in "old" widgets to revert the coordinate system
properly.
This commit is contained in:
Benjamin Otte 2010-09-22 16:10:45 +02:00
parent e66129015d
commit 0795f1e0c9
4 changed files with 82 additions and 26 deletions

View File

@ -4893,6 +4893,7 @@ gtk_widget_set_has_tooltip
gtk_widget_trigger_tooltip_query
gtk_widget_get_window
gtk_cairo_should_draw_window
gtk_cairo_transform_to_window
gtk_widget_get_allocated_width
gtk_widget_get_allocated_height
gtk_widget_get_allocation

View File

@ -4237,6 +4237,7 @@ gtk_widget_get_tooltip_markup
gtk_widget_get_tooltip_text
gtk_widget_get_tooltip_window
gtk_widget_get_toplevel
gtk_cairo_transform_to_window
gtk_widget_get_type G_GNUC_CONST
gtk_widget_get_visible
gtk_widget_get_visual

View File

@ -5246,6 +5246,77 @@ gtk_widget_event (GtkWidget *widget,
return gtk_widget_event_internal (widget, event);
}
/* Returns TRUE if a translation should be done */
static gboolean
gtk_widget_get_translation_to_window (GtkWidget *widget,
GdkWindow *window,
int *x,
int *y)
{
GdkWindow *w, *widget_window;
if (!gtk_widget_get_has_window (widget))
{
*x = -widget->priv->allocation.x;
*y = -widget->priv->allocation.y;
}
else
{
*x = 0;
*y = 0;
}
widget_window = gtk_widget_get_window (widget);
for (w = window; w && w != widget_window; w = gdk_window_get_parent (w))
{
int wx, wy;
gdk_window_get_position (w, &wx, &wy);
*x += wx;
*y += wy;
}
if (w == NULL)
{
*x = 0;
*y = 0;
return FALSE;
}
return TRUE;
}
/**
* gtk_cairo_transform_to_window:
* @cr: the cairo context to transform
* @widget: the widget the context is currently centered for
* @window: the window to transform the context to
*
* Transforms the given cairo context @cr that from @widget-relative
* coordinates to @window-relative coordinates.
* If the @widget's window is not an ancestor of @window, no
* modification will be applied.
*
* This is the inverse to the transformation GTK applies when
* preparing an expose event to be emitted with the GtkWidget::draw
* signal. It is intended to help porting multiwindow widgets from
* GTK 2 to the rendering architecture of GTK 3.
**/
void
gtk_cairo_transform_to_window (cairo_t *cr,
GtkWidget *widget,
GdkWindow *window)
{
int x, y;
g_return_if_fail (cr != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (GDK_IS_WINDOW (window));
if (gtk_widget_get_translation_to_window (widget, window, &x, &y))
cairo_translate (cr, x, y);
}
/**
* gtk_widget_send_expose:
@ -5270,10 +5341,10 @@ gint
gtk_widget_send_expose (GtkWidget *widget,
GdkEvent *event)
{
GdkWindow *window, *w;
gboolean result = FALSE;
cairo_t *cr;
int x, y;
gboolean do_clip;
g_return_val_if_fail (GTK_IS_WIDGET (widget), TRUE);
g_return_val_if_fail (gtk_widget_get_realized (widget), TRUE);
@ -5286,32 +5357,12 @@ gtk_widget_send_expose (GtkWidget *widget,
gdk_cairo_region (cr, event->expose.region);
cairo_clip (cr);
if (!gtk_widget_get_has_window (widget))
{
x = widget->priv->allocation.x;
y = widget->priv->allocation.y;
}
else
{
x = 0;
y = 0;
}
do_clip = gtk_widget_get_translation_to_window (widget,
event->expose.window,
&x, &y);
cairo_translate (cr, -x, -y);
/* translate cairo context properly */
window = gtk_widget_get_window (widget);
for (w = event->expose.window; w && w != window; w = gdk_window_get_parent (w))
{
int wx, wy;
gdk_window_get_position (w, &wx, &wy);
x -= wx;
y -= wy;
}
if (w)
cairo_translate (cr, x, y);
_gtk_widget_draw_internal (widget, cr, w != NULL);
_gtk_widget_draw_internal (widget, cr, do_clip);
/* unset here, so if someone keeps a reference to cr we
* don't leak the window. */

View File

@ -979,6 +979,9 @@ gboolean gtk_widget_get_has_tooltip (GtkWidget *widget);
gboolean gtk_cairo_should_draw_window (cairo_t *cr,
GdkWindow *window);
void gtk_cairo_transform_to_window (cairo_t *cr,
GtkWidget *widget,
GdkWindow *window);
GType gtk_requisition_get_type (void) G_GNUC_CONST;
GtkRequisition *gtk_requisition_new (void) G_GNUC_MALLOC;