if CANVAS_DEBUG is defined, then the env variable CANVAS_HARLEQUIN_DEBUGGING will...
[ardour.git] / libs / canvas / canvas.cc
index 8c7960a217c8ef4341385c3fae0e45ce19818a84..242f8ecbfd20acadf161e7df36b3b121fd6b7ec4 100644 (file)
@@ -110,16 +110,17 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
 
                _root.render (*draw, context);
 
-#if 0
-               // This transparently colors the rect being rendered, after it has been drawn.
-               double r = (random() % 65536) /65536.0;
-               double g = (random() % 65536) /65536.0;
-               double b = (random() % 65536) /65536.0;
-               context->rectangle (draw->x0, draw->y0, draw->x1 - draw->x0, draw->y1 - draw->y0);
-               context->set_source_rgba (r, g, b, 0.25);
-               context->fill ();
+#ifdef CANVAS_DEBUG
+               if (getenv ("CANVAS_HARLEQUIN_DEBUGGING")) {
+                       // This transparently colors the rect being rendered, after it has been drawn.
+                       double r = (random() % 65536) /65536.0;
+                       double g = (random() % 65536) /65536.0;
+                       double b = (random() % 65536) /65536.0;
+                       context->rectangle (draw->x0, draw->y0, draw->x1 - draw->x0, draw->y1 - draw->y0);
+                       context->set_source_rgba (r, g, b, 0.25);
+                       context->fill ();
+               }
 #endif
-
        }
 
 }
@@ -231,8 +232,21 @@ Canvas::window_to_canvas (Duple const & d) const
        std::list<Item*> const& root_children (_root.items());
        ScrollGroup* sg = 0;
 
+       /* if the coordinates are negative, clamp to zero and find the item
+        * that covers that "edge" position.
+        */
+
+       Duple in_window (d);
+
+       if (in_window.x < 0) {
+               in_window.x = 0;
+       }
+       if (in_window.y < 0) {
+               in_window.y = 0;
+       }
+
        for (std::list<Item*>::const_iterator i = root_children.begin(); i != root_children.end(); ++i) {
-               if (((sg = dynamic_cast<ScrollGroup*>(*i)) != 0) && sg->covers_window (d)) {
+               if (((sg = dynamic_cast<ScrollGroup*>(*i)) != 0) && sg->covers_window (in_window)) {
                        break;
                }
        }
@@ -326,7 +340,7 @@ GtkCanvas::GtkCanvas ()
 {
        /* these are the events we want to know about */
        add_events (Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK |
-                   Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
+                   Gdk::SCROLL_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
 }
 
 void
@@ -392,15 +406,14 @@ GtkCanvas::pick_current_item (Duple const & point, int state)
 
        for (i = items.begin(); i != items.end(); ++i) {
 
-               Item const * new_item = *i;
+               Item const * possible_item = *i;
 
-               /* We ignore invisible items, groups and items that ignore events */
+               /* We ignore invisible items, containers and items that ignore events */
 
-               if (!new_item->visible() || new_item->ignore_events() || dynamic_cast<Container const *>(new_item) != 0) {
+               if (!possible_item->visible() || possible_item->ignore_events() || dynamic_cast<ArdourCanvas::Container const *>(possible_item) != 0) {
                        continue;
                }
-               
-               within_items.push_front (new_item);
+               within_items.push_front (possible_item);
        }
 
        if (within_items.empty()) {
@@ -690,6 +703,32 @@ GtkCanvas::context ()
        return w->create_cairo_context ();
 }
 
+/** Handler for GDK scroll events.
+ *  @param ev Event.
+ *  @return true if the event was handled.
+ */
+bool
+GtkCanvas::on_scroll_event (GdkEventScroll* ev)
+{
+       /* translate event coordinates from window to canvas */
+
+       GdkEvent copy = *((GdkEvent*)ev);
+       Duple winpos = Duple (ev->x, ev->y);
+       Duple where = window_to_canvas (winpos);
+       
+       pick_current_item (winpos, ev->state);
+
+       copy.button.x = where.x;
+       copy.button.y = where.y;
+       
+       /* Coordinates in the event will be canvas coordinates, correctly adjusted
+          for scroll if this GtkCanvas is in a GtkCanvasViewport.
+       */
+
+       DEBUG_TRACE (PBD::DEBUG::CanvasEvents, string_compose ("canvas scroll @ %1, %2 => %3\n", ev->x, ev->y, where));
+       return deliver_event (reinterpret_cast<GdkEvent*>(&copy));
+}
+
 /** Handler for GDK button press events.
  *  @param ev Event.
  *  @return true if the event was handled.
@@ -742,6 +781,28 @@ GtkCanvas::on_button_release_event (GdkEventButton* ev)
        return deliver_event (reinterpret_cast<GdkEvent*>(&copy));
 }
 
+bool
+GtkCanvas::get_mouse_position (Duple& winpos) const
+{
+       int x;
+       int y;
+       Gdk::ModifierType mask;
+       Glib::RefPtr<Gdk::Window> self = Glib::RefPtr<Gdk::Window>::cast_const (get_window ());
+
+       if (!self) {
+               std::cerr << " no self window\n";
+               winpos = Duple (0, 0);
+               return false;
+       }
+
+       Glib::RefPtr<Gdk::Window> win = self->get_pointer (x, y, mask);
+
+       winpos.x = x;
+       winpos.y = y;
+
+       return true;
+}
+
 /** Handler for GDK motion events.
  *  @param ev Event.
  *  @return true if the event was handled.
@@ -763,6 +824,8 @@ GtkCanvas::on_motion_notify_event (GdkEventMotion* ev)
 
        DEBUG_TRACE (PBD::DEBUG::CanvasEvents, string_compose ("canvas motion @ %1, %2 canvas @ %3, %4\n", ev->x, ev->y, copy.motion.x, copy.motion.y));
 
+       MouseMotion (point); /* EMIT SIGNAL */
+
        pick_current_item (point, ev->state);
 
        /* Now deliver the motion event.  It may seem a little inefficient