/* gtkDPSarea.c * Copyright (C) 1997, 1998, 1999 GYVE Development Team * * Author: Terumoto 'tel' HAYAKAWA * Maintainer: Masatake YAMATO * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include "gtkDPS.h" static GtkDPSWidgetClass *parent_class; enum { COORDTR_UPDATE, MAP_PIXMAP, SWITCH_CONTEXT_PIXMAP, DRAW_LAZY, DRAW_READY, BUTTON_PRESS_EVENT_DPS, BUTTON_RELEASE_EVENT_DPS, MOTION_NOTIFY_EVENT_DPS, ENTER_NOTIFY_EVENT_DPS, LEAVE_NOTIFY_EVENT_DPS, LAST_SIGNAL }; static guint dps_area_signals[LAST_SIGNAL] = { 0 }; /* Initializer */ static void gtk_dps_area_class_init(GtkDPSAreaClass * klass); static void gtk_dps_area_init(GtkDPSArea * area); /* Over riding */ static void gtk_dps_area_destroy (GtkObject * object); static void gtk_dps_area_realize(GtkWidget * widget); static void gtk_dps_area_size_allocate(GtkWidget * widget, GtkAllocation * allocation); static void gtk_dps_area_draw (GtkWidget *widget, GdkRectangle *area); static gint gtk_dps_area_expose_event (GtkWidget *widget, GdkEventExpose *event); static gint gtk_dps_area_configure_event (GtkWidget * widget, GdkEventConfigure *event, GtkDPSArea *area); static gint gtk_dps_area_button_press_event (GtkWidget *widget, GdkEventButton *event, GtkDPSArea *area); static gint gtk_dps_area_button_release_event (GtkWidget *widget, GdkEventButton *event, GtkDPSArea *area); static gint gtk_dps_area_motion_notify_event (GtkWidget *widget, GdkEventMotion *event, GtkDPSArea *area); static gint gtk_dps_area_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event, GtkDPSArea *area); static gint gtk_dps_area_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event, GtkDPSArea *area); /* Helper */ static void gtk_dps_area_send_configure (GtkDPSArea *area); /* static void gtk_dps_area_build_pixmaps(GtkDPSArea * area, guint number_of_pixmaps); */ static void gtk_dps_area_make_pixmaps_dirty(GtkDPSContext * ctxt, DPSContext raw_context, gpointer user_data); /* Methods of self */ static void gtk_real_dps_area_coordtr_update (GtkDPSArea * dps_area, GdkDPSCoordtr * coordtr); static void gtk_real_dps_area_map_pixmap(GtkDPSArea * widget, gint dist, gint src, GdkRectangle * x_rect, GdkDPSRectangle * dps_rect); static void gtk_real_dps_area_draw_lazy(GtkDPSArea * widget, GdkRectangle * x_rect, GdkDPSRectangle * dps_rect); static void gtk_real_dps_area_draw_ready(GtkDPSArea * widget); static void gtk_real_dps_area_switch_context_pixmap (GtkDPSArea * dps_area, gint old, gint new); static void gtk_real_dps_area_button_press_event_dps (GtkDPSArea *widget, GdkEventButton *event, GdkDPSPoint * dps_point); static void gtk_real_dps_area_button_release_event_dps (GtkDPSArea *widget, GdkEventButton *event, GdkDPSPoint * dps_point); static void gtk_real_dps_area_motion_notify_event_dps (GtkDPSArea *widget, GdkEventMotion *event, GdkDPSPoint * dps_point); static void gtk_real_dps_area_enter_notify_event_dps (GtkDPSArea *widget, GdkEventCrossing *event, GdkDPSPoint * dps_point); static void gtk_real_dps_area_leave_notify_event_dps (GtkDPSArea *widget, GdkEventCrossing *event, GdkDPSPoint * dps_point); /* Marshaler */ static void gtk_marshal_NONE__INT_INT_POINTER_POINTER (GtkObject *object, GtkSignalFunc func, gpointer func_data, GtkArg *args); guint gtk_dps_area_get_type() { static guint dps_area_type = 0; if (!dps_area_type) { GtkTypeInfo dps_area_info = { "GtkDPSArea", sizeof(GtkDPSArea), sizeof(GtkDPSAreaClass), (GtkClassInitFunc) gtk_dps_area_class_init, (GtkObjectInitFunc) gtk_dps_area_init, (GtkArgSetFunc) NULL, (GtkArgGetFunc) NULL }; dps_area_type = gtk_type_unique(gtk_dps_widget_get_type(), &dps_area_info); } return dps_area_type; } static void gtk_dps_area_class_init(GtkDPSAreaClass * klass) { GtkObjectClass *object_class; GtkWidgetClass *widget_class; object_class = (GtkObjectClass *) klass; widget_class = (GtkWidgetClass *) klass; parent_class = gtk_type_class (GTK_TYPE_DPS_WIDGET); dps_area_signals[COORDTR_UPDATE] = gtk_signal_new ("coordtr_update", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkDPSAreaClass, coordtr_update), gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); dps_area_signals[MAP_PIXMAP] = gtk_signal_new ("map_pixmap", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkDPSAreaClass, map_pixmap), gtk_marshal_NONE__INT_INT_POINTER_POINTER, GTK_TYPE_NONE, 4, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_POINTER, GTK_TYPE_POINTER); dps_area_signals[SWITCH_CONTEXT_PIXMAP] = gtk_signal_new ("switch_context_pixmap", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkDPSAreaClass, switch_context_pixmap), gtk_marshal_NONE__INT_INT, GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); dps_area_signals[DRAW_LAZY] = gtk_signal_new ("draw_lazy", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkDPSAreaClass, draw_lazy), gtk_marshal_NONE__POINTER_POINTER, GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER); dps_area_signals[DRAW_READY] = gtk_signal_new ("draw_ready", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkDPSAreaClass, draw_ready), gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); dps_area_signals[BUTTON_PRESS_EVENT_DPS] = gtk_signal_new ("button_press_event_dps", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkDPSAreaClass, button_press_event_dps), gtk_marshal_NONE__POINTER_POINTER, GTK_TYPE_NONE, 2, GTK_TYPE_GDK_EVENT, GTK_TYPE_POINTER); dps_area_signals[BUTTON_RELEASE_EVENT_DPS] = gtk_signal_new ("button_release_event_dps", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkDPSAreaClass, button_release_event_dps), gtk_marshal_NONE__POINTER_POINTER, GTK_TYPE_NONE, 2, GTK_TYPE_GDK_EVENT, GTK_TYPE_POINTER); dps_area_signals[MOTION_NOTIFY_EVENT_DPS] = gtk_signal_new ("motion_notify_event_dps", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkDPSAreaClass, motion_notify_event_dps), gtk_marshal_NONE__POINTER_POINTER, GTK_TYPE_NONE, 2, GTK_TYPE_GDK_EVENT, GTK_TYPE_POINTER); dps_area_signals[ENTER_NOTIFY_EVENT_DPS] = gtk_signal_new ("enter_notify_event_dps", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkDPSAreaClass, enter_notify_event_dps), gtk_marshal_NONE__POINTER_POINTER, GTK_TYPE_NONE, 2, GTK_TYPE_GDK_EVENT, GTK_TYPE_POINTER); dps_area_signals[LEAVE_NOTIFY_EVENT_DPS] = gtk_signal_new ("leave_notify_event_dps", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GtkDPSAreaClass, leave_notify_event_dps), gtk_marshal_NONE__POINTER_POINTER, GTK_TYPE_NONE, 2, GTK_TYPE_GDK_EVENT, GTK_TYPE_POINTER); gtk_object_class_add_signals (object_class, dps_area_signals, LAST_SIGNAL); object_class->destroy = gtk_dps_area_destroy; widget_class->realize = gtk_dps_area_realize; widget_class->size_allocate = gtk_dps_area_size_allocate; widget_class->draw = gtk_dps_area_draw; widget_class->expose_event = gtk_dps_area_expose_event; klass->coordtr_update = gtk_real_dps_area_coordtr_update; klass->map_pixmap = gtk_real_dps_area_map_pixmap; klass->switch_context_pixmap = gtk_real_dps_area_switch_context_pixmap; klass->draw_lazy = gtk_real_dps_area_draw_lazy; klass->draw_ready = gtk_real_dps_area_draw_ready; klass->button_press_event_dps = gtk_real_dps_area_button_press_event_dps; klass->button_release_event_dps = gtk_real_dps_area_button_release_event_dps; klass->motion_notify_event_dps = gtk_real_dps_area_motion_notify_event_dps; klass->enter_notify_event_dps = gtk_real_dps_area_enter_notify_event_dps; klass->leave_notify_event_dps = gtk_real_dps_area_leave_notify_event_dps; } static void gtk_dps_area_init(GtkDPSArea * area) { #ifdef GTK_BASIC GTK_WIDGET_SET_FLAGS(area, GTK_BASIC); #endif /* GTK_BASIC */ gdk_dps_coordtr_init(&area->coordtr); area->pixmaps = NULL; area->number_of_pixmaps = 0; area->context_pixmap = -1; gdk_dps_rectangle_set(&area->draw_rectangle, 0.0, 0.0, 0.0, 0.0); area->draw_lock_depth = 0; area->receiving_expose_events_sequence = FALSE; area->pixmaps_dirty = FALSE; area->exec_in_mapping = FALSE; } GtkWidget * gtk_dps_area_new(guint number_of_pixmaps) { GtkDPSArea * area; area = gtk_type_new(gtk_dps_area_get_type()); gtk_dps_area_build_pixmaps(area, number_of_pixmaps); return GTK_WIDGET(area); } void gtk_dps_area_build_pixmaps(GtkDPSArea * area, guint number_of_pixmaps) { g_return_if_fail(area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(area)); g_return_if_fail(area->number_of_pixmaps == 0); if (number_of_pixmaps != 0) { int i; area->pixmaps = g_new(GdkPixmap*, number_of_pixmaps); area->number_of_pixmaps = number_of_pixmaps; for (i = 0; i < number_of_pixmaps; i++) area->pixmaps[i] = NULL; if (area->context_pixmap == -1) area->context_pixmap = GTK_DPS_AREA_PIXMAP; else g_assert_not_reached(); } } static void gtk_dps_area_make_pixmaps_dirty(GtkDPSContext * ctxt, DPSContext raw_context, gpointer user_data) { GtkDPSArea * area; g_return_if_fail(ctxt); g_return_if_fail(user_data); g_return_if_fail(GTK_IS_DPS_CONTEXT(ctxt)); g_return_if_fail(GTK_IS_DPS_AREA(user_data)); area = GTK_DPS_AREA(user_data); g_return_if_fail(GTK_WIDGET_REALIZED(area)); area->pixmaps_dirty = TRUE; } guint gtk_dps_area_number_of_pixmaps(GtkDPSArea * area) { g_return_val_if_fail(area != NULL, 0); g_return_val_if_fail(GTK_IS_DPS_AREA(area), 0); return area->number_of_pixmaps; } static void gtk_dps_area_realize(GtkWidget * widget) { GtkDPSArea *dps_area; GtkDPSWidget *dps_widget; GdkWindowAttr attributes; gint attributes_mask; GdkGC * gc; gint i; g_return_if_fail(widget != NULL); g_return_if_fail(GTK_IS_DPS_AREA(widget)); dps_area = GTK_DPS_AREA(widget); dps_widget = GTK_DPS_WIDGET(widget); GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); 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_OUTPUT; attributes.visual = gtk_widget_get_visual(widget); attributes.colormap = gtk_widget_get_colormap(widget); attributes.event_mask = gtk_widget_get_events(widget); attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; widget->window = gdk_window_new(gtk_widget_get_parent_window(widget), &attributes, attributes_mask); for (i = 0; i < dps_area->number_of_pixmaps; i++) { dps_area->pixmaps[i] = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, gdk_visual_get_best_depth()); } gdk_window_set_user_data(widget->window, dps_area); widget->style = gtk_style_attach(widget->style, widget->window); gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL); dps_widget->gtk_dps_context = GTK_DPS_CONTEXT(gtk_dps_context_new(widget->window)); gc = gtk_dps_context_get_gc(dps_widget->gtk_dps_context); gdk_draw_rectangle (widget->window, gc, 1, /* filled */ 0, 0, widget->allocation.width, widget->allocation.height); for (i = 0; i < dps_area->number_of_pixmaps; i++) { gdk_draw_rectangle (dps_area->pixmaps[i], gc, 1, /* filled */ 0, 0, widget->allocation.width, widget->allocation.height); } if (dps_area->number_of_pixmaps > 0) gtk_dps_context_set_drawable(dps_widget->gtk_dps_context, dps_area->pixmaps[dps_area->context_pixmap]); gtk_signal_connect (GTK_OBJECT (dps_area), "configure_event", (GtkSignalFunc)gtk_dps_area_configure_event, dps_area); gtk_dps_area_send_configure (dps_area); gtk_signal_connect (GTK_OBJECT(dps_area), "button_press_event", (GtkSignalFunc)gtk_dps_area_button_press_event, dps_area); gtk_signal_connect (GTK_OBJECT(dps_area), "button_release_event", (GtkSignalFunc)gtk_dps_area_button_release_event, dps_area); gtk_signal_connect (GTK_OBJECT(dps_area), "motion_notify_event", (GtkSignalFunc)gtk_dps_area_motion_notify_event, dps_area); gtk_signal_connect (GTK_OBJECT(dps_area), "enter_notify_event", (GtkSignalFunc)gtk_dps_area_enter_notify_event, dps_area); gtk_signal_connect (GTK_OBJECT(dps_area), "leave_notify_event", (GtkSignalFunc)gtk_dps_area_leave_notify_event, dps_area); gtk_signal_connect (GTK_OBJECT(dps_widget->gtk_dps_context), "enter_context", (GtkSignalFunc)gtk_dps_area_make_pixmaps_dirty, dps_area); gtk_signal_emit (GTK_OBJECT(dps_area), dps_area_signals[DRAW_READY]); } static void gtk_dps_area_size_allocate(GtkWidget * widget, GtkAllocation * allocation) { GtkDPSArea *dps_area; GtkDPSWidget *dps_widget; g_return_if_fail(widget != NULL); g_return_if_fail(GTK_IS_DPS_AREA(widget)); g_return_if_fail(allocation != NULL); dps_area = GTK_DPS_AREA(widget); dps_widget = GTK_DPS_WIDGET(widget); widget->allocation = *allocation; if (GTK_WIDGET_REALIZED(widget)) { gdk_window_move_resize(widget->window, allocation->x, allocation->y, allocation->width, allocation->height); if (dps_area->number_of_pixmaps == 0) { gtk_dps_widget_begin(dps_widget); DPSsetXoffset(raw_ctxt, 0, allocation->height); /* ??? */ gtk_dps_widget_end(); gtk_dps_area_send_configure (dps_area); } else { gint i; gint current = dps_area->context_pixmap; GdkGC * gc = gtk_dps_context_get_gc(dps_widget->gtk_dps_context); GdkPixmap * tmp = NULL; if (current != -1) tmp = gdk_pixmap_ref(dps_area->pixmaps[current]); for (i = 0; i < dps_area->number_of_pixmaps; i++) { if (dps_area->pixmaps[i]) gdk_pixmap_unref(dps_area->pixmaps[i]); else g_assert_not_reached(); dps_area->pixmaps[i] = gdk_pixmap_new(widget->window, allocation->width, allocation->height, gdk_visual_get_best_depth()); gdk_draw_rectangle (dps_area->pixmaps[i], gc, 1, /* Filled */ 0, 0, allocation->width, allocation->height); } if (current != -1) gtk_dps_context_set_drawable(dps_widget->gtk_dps_context, dps_area->pixmaps[current]); dps_area->pixmaps_dirty = FALSE; gtk_dps_area_send_configure (dps_area); if (current != -1) gdk_pixmap_unref(tmp); } } } static void gtk_dps_area_send_configure (GtkDPSArea *area) { GtkWidget *widget; GdkEventConfigure event; widget = GTK_WIDGET (area); event.type = GDK_CONFIGURE; event.window = widget->window; event.send_event = TRUE; event.x = widget->allocation.x; event.y = widget->allocation.y; event.width = widget->allocation.width; event.height = widget->allocation.height; gtk_widget_event (widget, (GdkEvent*) &event); } static void gtk_dps_area_draw (GtkWidget *widget, GdkRectangle *area) { GtkDPSArea *dps_area; g_return_if_fail(widget != NULL); g_return_if_fail(GTK_IS_DPS_AREA(widget)); dps_area = GTK_DPS_AREA(widget); gtk_dps_area_draw_lazy(dps_area, GDK_DPS_WORLD_X, area); } static gint gtk_dps_area_expose_event (GtkWidget *widget, GdkEventExpose *event) { GtkDPSArea *dps_area; g_return_val_if_fail(widget != NULL, FALSE); g_return_val_if_fail(GTK_IS_DPS_AREA(widget), FALSE); g_return_val_if_fail(event != NULL, FALSE); dps_area = GTK_DPS_AREA(widget); if (event->count > 0) { /* Some expose_events follows after this EVENT. => Memorize region but draw */ if (FALSE == dps_area->receiving_expose_events_sequence) { /* This EVENT is the first of the expose_events sequence. => Lock the drawing */ gtk_dps_area_draw_lock_retain(dps_area); dps_area->receiving_expose_events_sequence = TRUE; } gtk_dps_area_draw_lazy(dps_area, GDK_DPS_WORLD_X, &event->area); } else { if (TRUE == dps_area->receiving_expose_events_sequence) { /* This EVENT is the last of the expose_events sequence. => expand region and release drawing locking */ gtk_dps_area_draw_lazy(dps_area, GDK_DPS_WORLD_X, &event->area); gtk_dps_area_draw_lock_release(dps_area); dps_area->receiving_expose_events_sequence = FALSE; } else { /* Single expose_event and not in the drawing locking */ gtk_dps_area_draw_lazy(dps_area, GDK_DPS_WORLD_X, &event->area); } } return FALSE; } static gint gtk_dps_area_configure_event (GtkWidget * widget, GdkEventConfigure *event, GtkDPSArea *area) { gtk_dps_area_coordtr_dirty(area); gtk_dps_area_coordtr_update(area); return FALSE; } void gtk_dps_area_switch_context_pixmap (GtkDPSArea * dps_area, gint pixmap) { GtkWidget * widget; g_return_if_fail(dps_area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(dps_area)); widget = GTK_WIDGET(dps_area); g_return_if_fail(GTK_WIDGET_REALIZED(widget)); g_return_if_fail(pixmap > -2); g_return_if_fail(pixmap < dps_area->number_of_pixmaps); if (pixmap == dps_area->context_pixmap) return ; gtk_signal_emit(GTK_OBJECT (dps_area), dps_area_signals[SWITCH_CONTEXT_PIXMAP], dps_area->context_pixmap, pixmap); } static void gtk_real_dps_area_switch_context_pixmap (GtkDPSArea * dps_area, gint old, gint new) { GtkWidget * widget; GtkDPSWidget * dps_widget; widget = GTK_WIDGET(dps_area); dps_widget = GTK_DPS_WIDGET(dps_area); dps_area->context_pixmap = new; if (dps_area->pixmaps_dirty) { gtk_dps_context_flush(dps_widget->gtk_dps_context); dps_area->pixmaps_dirty = FALSE; } if (new == -1) gtk_dps_context_set_drawable(dps_widget->gtk_dps_context, widget->window); else gtk_dps_context_set_drawable(dps_widget->gtk_dps_context, dps_area->pixmaps[new]); } gint gtk_dps_area_context_pixmap (GtkDPSArea * dps_area) { g_return_val_if_fail(dps_area != NULL, -1); g_return_val_if_fail(GTK_IS_DPS_AREA(dps_area), -1); return dps_area->context_pixmap; } /* * Coordtr */ void gtk_dps_area_coordtr_dirty (GtkDPSArea * dps_area) { g_return_if_fail(dps_area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(dps_area)); gdk_dps_coordtr_make_dirty(&(dps_area->coordtr)); } gboolean gtk_dps_area_coordtr_update (GtkDPSArea * dps_area) { GtkDPSWidget * dps_widget; gboolean emitp; g_return_val_if_fail (dps_area != NULL, FALSE); g_return_val_if_fail (GTK_IS_DPS_AREA (dps_area), FALSE); g_return_val_if_fail(GTK_WIDGET_REALIZED(dps_area), FALSE); dps_widget = GTK_DPS_WIDGET(dps_area); emitp = gtk_dps_context_try_update_coordtr(dps_widget->gtk_dps_context, &(dps_area->coordtr)); if (emitp) gtk_signal_emit (GTK_OBJECT (dps_area), dps_area_signals[COORDTR_UPDATE], &(dps_area->coordtr)); return emitp; } static void gtk_real_dps_area_coordtr_update (GtkDPSArea * dps_area, GdkDPSCoordtr * coordtr) { GtkDPSWidget * dps_widget = GTK_DPS_WIDGET(dps_area); if (gdk_dps_coordtr_is_dirty(coordtr)) gtk_dps_context_update_coordtr(dps_widget->gtk_dps_context, coordtr); } void gtk_dps_area_coordtr_point (GtkDPSArea * dps_area, GdkDPSTrDirection trdir, gpointer src, gpointer dist) { GtkDPSWidget *dps_widget; g_return_if_fail(dps_area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(dps_area)); g_return_if_fail(GTK_WIDGET_REALIZED(dps_area)); g_return_if_fail(trdir == GDK_DPS_TRDIR_DPS2X || trdir == GDK_DPS_TRDIR_X2DPS); g_return_if_fail(src); g_return_if_fail(dist); dps_widget = GTK_DPS_WIDGET(dps_area); gtk_dps_area_coordtr_update(dps_area); gdk_dps_coordtr_point(&(dps_area->coordtr), trdir, src, dist); } void gtk_dps_area_coordtr_rectangle (GtkDPSArea * dps_area, GdkDPSTrDirection trdir, gpointer src, gpointer dist) { GtkDPSWidget *dps_widget; g_return_if_fail(dps_area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(dps_area)); g_return_if_fail(GTK_WIDGET_REALIZED(dps_area)); g_return_if_fail(trdir == GDK_DPS_TRDIR_DPS2X || trdir == GDK_DPS_TRDIR_X2DPS); g_return_if_fail(src); g_return_if_fail(dist); dps_widget = GTK_DPS_WIDGET(dps_area); gtk_dps_area_coordtr_update(dps_area); gdk_dps_coordtr_rectangle(&(dps_area->coordtr), trdir, src, dist); } void gtk_dps_area_coordtr_size (GtkDPSArea * dps_area, GdkDPSTrDirection trdir, gpointer src, gpointer dist) { GtkDPSWidget *dps_widget; g_return_if_fail(dps_area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(dps_area)); g_return_if_fail(GTK_WIDGET_REALIZED(dps_area)); g_return_if_fail(trdir == GDK_DPS_TRDIR_DPS2X || trdir == GDK_DPS_TRDIR_X2DPS); g_return_if_fail(src); g_return_if_fail(dist); dps_widget = GTK_DPS_WIDGET(dps_area); gtk_dps_area_coordtr_update(dps_area); gdk_dps_coordtr_size(&(dps_area->coordtr), trdir, src, dist); } gfloat gtk_dps_area_coordtr_width (GtkDPSArea * dps_area, GdkDPSTrDirection trdir, gfloat width) { g_return_val_if_fail(dps_area != NULL, 0.0); g_return_val_if_fail(GTK_IS_DPS_AREA(dps_area), 0.0); g_return_val_if_fail(GTK_WIDGET_REALIZED(dps_area), 0.0); g_return_val_if_fail(trdir == GDK_DPS_TRDIR_DPS2X || trdir == GDK_DPS_TRDIR_X2DPS, 0.0); g_return_val_if_fail (width >= 0.0, 0.0); return gdk_dps_coordtr_width(&dps_area->coordtr, trdir, width); } gfloat gtk_dps_area_coordtr_height (GtkDPSArea * dps_area, GdkDPSTrDirection trdir, gfloat height) { g_return_val_if_fail(dps_area != NULL, 0.0); g_return_val_if_fail(GTK_IS_DPS_AREA(dps_area), 0.0); g_return_val_if_fail(GTK_WIDGET_REALIZED(dps_area), 0.0); g_return_val_if_fail(trdir == GDK_DPS_TRDIR_DPS2X || trdir == GDK_DPS_TRDIR_X2DPS, 0.0); g_return_val_if_fail (height >= 0.0, 0.0); return gdk_dps_coordtr_height(&dps_area->coordtr, trdir, height); } /* * Draw lock (emits draw_X) */ void gtk_dps_area_draw_lock_retain(GtkDPSArea * dps_area) { g_return_if_fail(dps_area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(dps_area)); g_return_if_fail(GTK_WIDGET_REALIZED(dps_area)); g_return_if_fail(!(dps_area->draw_lock_depth < 0)); dps_area->draw_lock_depth++; } void gtk_dps_area_draw_lazy(GtkDPSArea * dps_area, GdkDPSWorld world, gpointer rectangle) { GtkWidget * widget; GdkDPSRectangle dps_rect, union_rect; GdkRectangle x_rect; g_return_if_fail(dps_area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(dps_area)); g_return_if_fail(GTK_WIDGET_REALIZED(dps_area)); g_return_if_fail(world == GDK_DPS_WORLD_X || world == GDK_DPS_WORLD_DPS); if (rectangle == NULL) { /* Full screen */ widget = GTK_WIDGET(dps_area); x_rect.x = 0; x_rect.y = 0; x_rect.width = widget->allocation.width; x_rect.height = widget->allocation.height; gtk_dps_area_coordtr_rectangle(dps_area, GDK_DPS_TRDIR_X2DPS, &x_rect, &dps_rect); } else if (world == GDK_DPS_WORLD_X) { x_rect = *(GdkRectangle *)rectangle; gtk_dps_area_coordtr_rectangle(dps_area, GDK_DPS_TRDIR_X2DPS, &x_rect, &dps_rect); } else if (world == GDK_DPS_WORLD_DPS) { dps_rect = *(GdkDPSRectangle *)rectangle; } else g_assert_not_reached(); /* Expand draw rect */ gdk_dps_rectangle_union(&dps_area->draw_rectangle, &dps_rect, &union_rect); dps_rect = dps_area->draw_rectangle = union_rect; gtk_dps_area_coordtr_rectangle(dps_area, GDK_DPS_TRDIR_DPS2X, &dps_rect, &x_rect); if (dps_area->draw_lock_depth == 0) { gtk_signal_emit (GTK_OBJECT(dps_area), dps_area_signals[DRAW_LAZY], &x_rect, &dps_rect); /* _init should be in _real_? */ gdk_dps_rectangle_set(&dps_area->draw_rectangle, 0.0, 0.0, 0.0, 0.0); } } void gtk_dps_area_draw_lock_release(GtkDPSArea * dps_area) { GdkDPSRectangle dps_rect; GdkRectangle x_rect; g_return_if_fail(dps_area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(dps_area)); g_return_if_fail(GTK_WIDGET_REALIZED(dps_area)); dps_area->draw_lock_depth--; g_return_if_fail(!(dps_area->draw_lock_depth < 0)); dps_rect = dps_area->draw_rectangle; gtk_dps_area_coordtr_rectangle(dps_area, GDK_DPS_TRDIR_DPS2X, &dps_rect, &x_rect); if (dps_area->draw_lock_depth == 0) { gtk_signal_emit (GTK_OBJECT(dps_area), dps_area_signals[DRAW_LAZY], &x_rect, &dps_rect); /* _init should be in _real_? */ gdk_dps_rectangle_set(&dps_area->draw_rectangle, 0.0, 0.0, 0.0, 0.0); } } static void gtk_real_dps_area_draw_lazy(GtkDPSArea * widget, GdkRectangle * x_rect, GdkDPSRectangle * dps_rect) { /* Do nothing */ } static void gtk_real_dps_area_draw_ready(GtkDPSArea * widget) { /* Do nothing */ } /* * Mapping functions */ void gtk_dps_area_map_cache_on_screen(GtkDPSArea * dps_area, GdkDPSRectangle * dps_rect) { g_return_if_fail(dps_area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(dps_area)); g_return_if_fail(GTK_WIDGET_REALIZED(dps_area)); g_return_if_fail(dps_area->number_of_pixmaps > 1); gtk_dps_area_map_pixmap(dps_area, GTK_DPS_SCREEN, GTK_DPS_CACHE_PIXMAP, GDK_DPS_WORLD_DPS, dps_rect); } void gtk_dps_area_map_cache_on_area(GtkDPSArea * dps_area, GdkDPSRectangle * dps_rect) { g_return_if_fail(dps_area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(dps_area)); g_return_if_fail(GTK_WIDGET_REALIZED(dps_area)); g_return_if_fail(dps_area->number_of_pixmaps > 1); gtk_dps_area_map_pixmap(dps_area, GTK_DPS_AREA_PIXMAP, GTK_DPS_CACHE_PIXMAP, GDK_DPS_WORLD_DPS, dps_rect); } void gtk_dps_area_map_area_on_screen(GtkDPSArea * dps_area, GdkDPSRectangle * dps_rect) { g_return_if_fail(dps_area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(dps_area)); g_return_if_fail(GTK_WIDGET_REALIZED(dps_area)); g_return_if_fail(dps_area->number_of_pixmaps > 0); gtk_dps_area_map_pixmap(dps_area, GTK_DPS_SCREEN, GTK_DPS_AREA_PIXMAP, GDK_DPS_WORLD_DPS, dps_rect); } void gtk_dps_area_map_area_on_cache(GtkDPSArea * dps_area, GdkDPSRectangle * dps_rect) { g_return_if_fail(dps_area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(dps_area)); g_return_if_fail(GTK_WIDGET_REALIZED(dps_area)); g_return_if_fail(dps_area->number_of_pixmaps > 1); gtk_dps_area_map_pixmap(dps_area, GTK_DPS_CACHE_PIXMAP, GTK_DPS_AREA_PIXMAP, GDK_DPS_WORLD_DPS, dps_rect); } void gtk_dps_area_map_pixmap(GtkDPSArea * dps_area, gint dist, gint src, GdkDPSWorld world, gpointer rectangle) { GdkRectangle x_rect; GdkDPSRectangle dps_rect; GtkWidget * widget; GdkRectangle full_rect; g_return_if_fail(dps_area != NULL); g_return_if_fail(GTK_IS_DPS_AREA(dps_area)); g_return_if_fail(GTK_WIDGET_REALIZED(dps_area)); g_return_if_fail(src > -2); g_return_if_fail(dist > -2); g_return_if_fail(src < dps_area->number_of_pixmaps); g_return_if_fail(dist < dps_area->number_of_pixmaps); g_return_if_fail(world == GDK_DPS_WORLD_X || world == GDK_DPS_WORLD_DPS); if (src == dist) return ; /* Do nothing */ widget = GTK_WIDGET(dps_area); /* Get the max size of rect */ full_rect.x = 0; full_rect.y = 0; full_rect.width = widget->allocation.width; full_rect.height = widget->allocation.height; if (rectangle == NULL) { /* Full screen mapping */ x_rect = full_rect; /* X->DPS */ gtk_dps_area_coordtr_rectangle(dps_area, GDK_DPS_TRDIR_X2DPS, &x_rect, &dps_rect); } else if (world == GDK_DPS_WORLD_DPS) { dps_rect = *(GdkDPSRectangle *)rectangle; /* DPS->X */ gtk_dps_area_coordtr_rectangle(dps_area, GDK_DPS_TRDIR_DPS2X, &dps_rect, &x_rect); /* Range checking */ gdk_rectangle_intersect(&full_rect, &x_rect, &x_rect); } else if (world == GDK_DPS_WORLD_X) { x_rect = *(GdkRectangle *)rectangle; /* Range checking */ gdk_rectangle_intersect(&full_rect, &x_rect, &x_rect); /* X->DPS */ gtk_dps_area_coordtr_rectangle(dps_area, GDK_DPS_TRDIR_X2DPS, &x_rect, &dps_rect); } gtk_signal_emit(GTK_OBJECT (dps_area), dps_area_signals[MAP_PIXMAP], dist, src, &x_rect, &dps_rect); } static void gtk_real_dps_area_map_pixmap(GtkDPSArea * dps_area, gint dist, gint src, GdkRectangle * x_rect, GdkDPSRectangle * dps_rect) { GtkWidget * widget = GTK_WIDGET(dps_area); GtkDPSWidget * dps_widget = GTK_DPS_WIDGET(dps_area); GdkGC *gc; GdkPixmap * src_pixmap = NULL; GdkPixmap * dist_pixmap = NULL; if (dist < GTK_DPS_SCREEN) g_assert_not_reached(); else if (dist == GTK_DPS_SCREEN) dist_pixmap = widget->window; else if (dist < dps_area->number_of_pixmaps) dist_pixmap = dps_area->pixmaps[dist]; else g_assert_not_reached(); if (src < GTK_DPS_SCREEN) g_assert_not_reached(); else if (src == GTK_DPS_SCREEN) src_pixmap = widget->window; else if (src < dps_area->number_of_pixmaps) src_pixmap = dps_area->pixmaps[src]; else g_assert_not_reached(); gc = gtk_dps_context_get_gc(dps_widget->gtk_dps_context); g_return_if_fail(dps_area->exec_in_mapping == FALSE); dps_area->exec_in_mapping = TRUE; if (dps_area->pixmaps_dirty) { gtk_dps_context_flush(dps_widget->gtk_dps_context); dps_area->pixmaps_dirty = FALSE; } gdk_window_copy_area (dist_pixmap, gc, x_rect->x, x_rect->y, src_pixmap, x_rect->x, x_rect->y, x_rect->width, x_rect->height); dps_area->exec_in_mapping = FALSE; } static void gtk_dps_area_destroy (GtkObject * object) { GtkDPSArea * area; GtkDPSWidget * widget; int i; g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_DPS_AREA (object)); area = GTK_DPS_AREA(object); widget = GTK_DPS_WIDGET(object); gtk_object_unref(GTK_OBJECT(widget->gtk_dps_context)); widget->gtk_dps_context = NULL; for (i = 0; i < area->number_of_pixmaps; i++) { gdk_pixmap_unref(area->pixmaps[i]); area->pixmaps[i] = NULL; } if (area->number_of_pixmaps > 0) { g_free(area->pixmaps); area->pixmaps = NULL; area->number_of_pixmaps = 0; } if (GTK_OBJECT_CLASS (parent_class)->destroy) (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } void gtk_dps_area_size (GtkDPSArea *area, gint width, gint height) { g_return_if_fail (area != NULL); g_return_if_fail (GTK_IS_DPS_AREA (area)); gtk_widget_set_usize (GTK_WIDGET(area), width, height); } void gtk_dps_area_get_size (GtkDPSArea *area, gfloat * width, gfloat * height) { gint x_width, x_height; gfloat dps_width, dps_height; GdkWindow * gdk_window; g_return_if_fail (area != NULL); g_return_if_fail (GTK_IS_DPS_AREA (area)); g_return_if_fail(GTK_WIDGET_REALIZED(area)); gdk_window = GTK_WIDGET(area)->window; gdk_window_get_size(gdk_window, &x_width, &x_height); dps_width = gtk_dps_area_coordtr_width(GTK_DPS_AREA(area), GDK_DPS_TRDIR_X2DPS, x_width); dps_height = gtk_dps_area_coordtr_height(GTK_DPS_AREA(area), GDK_DPS_TRDIR_X2DPS, x_height); if (width) *width = dps_width; if (height) *height = dps_height; } typedef void (*GtkSignal_NONE__INT_INT_POINTER_POINTER) (GtkObject *object, gint arg1, gint arg2, gpointer arg3, gpointer arg4, gpointer user_data); static void gtk_marshal_NONE__INT_INT_POINTER_POINTER (GtkObject *object, GtkSignalFunc func, gpointer func_data, GtkArg *args) { GtkSignal_NONE__INT_INT_POINTER_POINTER rfunc; rfunc = (GtkSignal_NONE__INT_INT_POINTER_POINTER) func; (* rfunc) (object, GTK_VALUE_INT(args[0]), GTK_VALUE_INT(args[1]), GTK_VALUE_POINTER(args[2]), GTK_VALUE_POINTER(args[3]), func_data); } static gint gtk_dps_area_button_press_event (GtkWidget *widget, GdkEventButton *event, GtkDPSArea *area) { GdkDPSPoint dps_point; GdkPoint x_point; x_point.x = (gint)event->x; x_point.y = (gint)event->y; gtk_dps_area_coordtr_point(area, GDK_DPS_TRDIR_X2DPS, &x_point, &dps_point); gtk_signal_emit(GTK_OBJECT (widget), dps_area_signals[BUTTON_PRESS_EVENT_DPS], event, &dps_point); return FALSE; } static gint gtk_dps_area_button_release_event (GtkWidget *widget, GdkEventButton *event, GtkDPSArea *area) { GdkDPSPoint dps_point; GdkPoint x_point; x_point.x = (gint)event->x; x_point.y = (gint)event->y; gtk_dps_area_coordtr_point(area, GDK_DPS_TRDIR_X2DPS, &x_point, &dps_point); gtk_signal_emit(GTK_OBJECT (widget), dps_area_signals[BUTTON_RELEASE_EVENT_DPS], event, &dps_point); return FALSE; } static gint gtk_dps_area_motion_notify_event (GtkWidget *widget, GdkEventMotion *event, GtkDPSArea *area) { GdkDPSPoint dps_point; GdkPoint x_point; x_point.x = (gint)event->x; x_point.y = (gint)event->y; gtk_dps_area_coordtr_point(area, GDK_DPS_TRDIR_X2DPS, &x_point, &dps_point); gtk_signal_emit(GTK_OBJECT (widget), dps_area_signals[MOTION_NOTIFY_EVENT_DPS], event, &dps_point); return FALSE; } static gint gtk_dps_area_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event, GtkDPSArea *area) { GdkDPSPoint dps_point; GdkPoint x_point; x_point.x = (gint)event->x; x_point.y = (gint)event->y; gtk_dps_area_coordtr_point(area, GDK_DPS_TRDIR_X2DPS, &x_point, &dps_point); gtk_signal_emit(GTK_OBJECT (widget), dps_area_signals[ENTER_NOTIFY_EVENT_DPS], event, &dps_point); return FALSE; } static gint gtk_dps_area_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event, GtkDPSArea *area) { GdkDPSPoint dps_point; GdkPoint x_point; x_point.x = (gint)event->x; x_point.y = (gint)event->y; gtk_dps_area_coordtr_point(area, GDK_DPS_TRDIR_X2DPS, &x_point, &dps_point); gtk_signal_emit(GTK_OBJECT (widget), dps_area_signals[LEAVE_NOTIFY_EVENT_DPS], event, &dps_point); return FALSE; } static void gtk_real_dps_area_button_press_event_dps (GtkDPSArea *widget, GdkEventButton *event, GdkDPSPoint * dps_point) { } static void gtk_real_dps_area_button_release_event_dps (GtkDPSArea *widget, GdkEventButton *event, GdkDPSPoint * dps_point) { } static void gtk_real_dps_area_motion_notify_event_dps (GtkDPSArea *widget, GdkEventMotion *event, GdkDPSPoint * dps_point) { } static void gtk_real_dps_area_enter_notify_event_dps (GtkDPSArea *widget, GdkEventCrossing *event, GdkDPSPoint * dps_point) { } static void gtk_real_dps_area_leave_notify_event_dps (GtkDPSArea *widget, GdkEventCrossing *event, GdkDPSPoint * dps_point) { }