index 104172b63a9a3f6df465492ff651b87d63f59f63..a558774c451dd35933405a22f40da46d439e5cea 100644 (file)
#include <gtk/gtkmain.h>
#include <gtk/gtksignal.h>
+#include <gtk/gtkversion.h>
#include <gtkmm.h>
#include "display/rendermode.h"
#include "libnr/nr-blit.h"
#include "display/inkscape-cairo.h"
+#include "debug/gdk-event-latency-tracker.h"
+
+using Inkscape::Debug::GdkEventLatencyTracker;
+
+// GTK_CHECK_VERSION returns false on failure
+#define HAS_GDK_EVENT_REQUEST_MOTIONS GTK_CHECK_VERSION(2, 12, 0)
+
+// gtk_check_version returns non-NULL on failure
+static bool const HAS_BROKEN_MOTION_HINTS =
+ true || gtk_check_version(2, 12, 0) != NULL || !HAS_GDK_EVENT_REQUEST_MOTIONS;
// Define this to visualize the regions to be redrawn
//#define DEBUG_REDRAW 1;
static void sp_canvas_request_update (SPCanvas *canvas);
+static void track_latency(GdkEvent const *event);
static void sp_canvas_item_class_init (SPCanvasItemClass *klass);
static void sp_canvas_item_init (SPCanvasItem *item);
static void sp_canvas_item_dispose (GObject *object);
@@ -531,6 +543,10 @@ sp_canvas_item_grab (SPCanvasItem *item, guint event_mask, GdkCursor *cursor, gu
if (!(item->flags & SP_CANVAS_ITEM_VISIBLE))
return -1;
+ if (HAS_BROKEN_MOTION_HINTS) {
+ event_mask &= ~GDK_POINTER_MOTION_HINT_MASK;
+ }
+
/* fixme: Top hack (Lauris) */
/* fixme: If we add key masks to event mask, Gdk will abort (Lauris) */
/* fixme: But Canvas actualle does get key events, so all we need is routing these here */
@@ -776,7 +792,7 @@ sp_canvas_group_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned i
}
}
- NR::Maybe<NR::Rect> const bounds = corners.bounds();
+ boost::optional<NR::Rect> const bounds = corners.bounds();
if (bounds) {
item->x1 = bounds->min()[NR::X];
item->y1 = bounds->min()[NR::Y];
(* GTK_OBJECT_CLASS (canvas_parent_class)->destroy) (object);
}
+static void track_latency(GdkEvent const *event) {
+ GdkEventLatencyTracker &tracker = GdkEventLatencyTracker::default_tracker();
+ boost::optional<double> latency = tracker.process(event);
+ if (latency && *latency > 2.0) {
+ g_warning("Event latency reached %f sec (%1.4f)", *latency, tracker.getSkew());
+ }
+}
+
/**
* Returns new canvas as widget.
*/
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_POINTER_MOTION_MASK |
+ ( HAS_BROKEN_MOTION_HINTS ?
+ 0 : GDK_POINTER_MOTION_HINT_MASK ) |
GDK_PROXIMITY_IN_MASK |
GDK_PROXIMITY_OUT_MASK |
GDK_KEY_PRESS_MASK |
return emit_event (SP_CANVAS (widget), (GdkEvent *) event);
}
+static inline void request_motions(GdkWindow *w, GdkEventMotion *event) {
+ gdk_window_get_pointer(w, NULL, NULL, NULL);
+#if HAS_GDK_EVENT_REQUEST_MOTIONS
+ gdk_event_request_motions(event);
+#endif
+}
+
/**
* Motion event handler for the canvas.
*/
static int
sp_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
{
+ int status;
SPCanvas *canvas = SP_CANVAS (widget);
+ track_latency((GdkEvent *)event);
+
if (event->window != SP_CANVAS_WINDOW (canvas))
return FALSE;
if (canvas->pixmap_gc == NULL) // canvas being deleted
return FALSE;
- if (canvas->grabbed_event_mask & GDK_POINTER_MOTION_HINT_MASK) {
- gint x, y;
- gdk_window_get_pointer (widget->window, &x, &y, NULL);
- event->x = x;
- event->y = y;
- }
-
canvas->state = event->state;
pick_current_item (canvas, (GdkEvent *) event);
- return emit_event (canvas, (GdkEvent *) event);
+ status = emit_event (canvas, (GdkEvent *) event);
+
+ if (event->is_hint) {
+ request_motions(widget->window, event);
+ }
+
+ return status;
}
static void
@@ -1673,7 +1708,7 @@ sp_canvas_paint_single_buffer (SPCanvas *canvas, int x0, int y0, int x1, int y1,
x0 - canvas->x0, y0 - canvas->y0,
x1 - x0, y1 - y0,
GDK_RGB_DITHER_MAX,
- b3.data.px,
+ NR_PIXBLOCK_PX(&b3),
sw * 3,
x0 - canvas->x0, y0 - canvas->y0);