Committed underlay support (from Audun).
[ardour.git] / libs / gtkmm2ext / tearoff.cc
index c9dd89ac5232ba55371d350999cb090d547896ba..92bde5541e510f778650dbe3b22502950601ec10 100644 (file)
 
 #include <cmath>
 #include <gtkmm2ext/tearoff.h>
+#include <gtkmm2ext/utils.h>
 
 using namespace Gtkmm2ext;
 using namespace Gtk;
+using namespace Gdk;
+using namespace Glib;
 using namespace std;
 
-TearOff::TearOff (Gtk::Widget& c)
+TearOff::TearOff (Widget& c, bool allow_resize)
        : contents (c),
-         tearoff_arrow (Gtk::ARROW_DOWN, Gtk::SHADOW_OUT),
-         close_arrow (Gtk::ARROW_UP, Gtk::SHADOW_OUT)
+         own_window (Gtk::WINDOW_TOPLEVEL),
+         tearoff_arrow (ARROW_DOWN, SHADOW_OUT),
+         close_arrow (ARROW_UP, SHADOW_OUT)
 {
        dragging = false;
+       _visible = true;
 
        tearoff_event_box.add (tearoff_arrow);
-       tearoff_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
+       tearoff_event_box.set_events (BUTTON_PRESS_MASK|BUTTON_RELEASE_MASK);
        tearoff_event_box.signal_button_release_event().connect (mem_fun (*this, &TearOff::tearoff_click));
 
        close_event_box.add (close_arrow);
-       close_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
+       close_event_box.set_events (BUTTON_PRESS_MASK|BUTTON_RELEASE_MASK);
        close_event_box.signal_button_release_event().connect (mem_fun (*this, &TearOff::close_click));
        
-       own_window = new Gtk::Window (Gtk::WINDOW_TOPLEVEL);
-       own_window->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::POINTER_MOTION_HINT_MASK);
-       own_window->set_resizable (false);
-//     own_window->realize ();
-
-       Glib::RefPtr<Gdk::Window> win (own_window->get_window());
-       win->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
+       own_window.add_events (BUTTON_PRESS_MASK|BUTTON_RELEASE_MASK|POINTER_MOTION_MASK|POINTER_MOTION_HINT_MASK);
+       own_window.set_resizable (allow_resize);
+       own_window.set_type_hint (WINDOW_TYPE_HINT_TOOLBAR);
        
        VBox* box1;
        box1 = manage (new VBox);
-       box1->pack_start (close_event_box, false, false, 5);
+       box1->pack_start (close_event_box, false, false, 2);
        
        window_box.pack_end (*box1, false, false, 2);
-       own_window->add (window_box);
-       
-       own_window->signal_button_press_event().connect (mem_fun (*this, &TearOff::window_button_press));
-       own_window->signal_button_release_event().connect (mem_fun (*this, &TearOff::window_button_release));
-       own_window->signal_motion_notify_event().connect (mem_fun (*this, &TearOff::window_motion));
-       own_window->signal_delete_event().connect (mem_fun (*this, &TearOff::window_delete_event));
+       own_window.add (window_box);
        
+       own_window.signal_button_press_event().connect (mem_fun (*this, &TearOff::window_button_press));
+       own_window.signal_button_release_event().connect (mem_fun (*this, &TearOff::window_button_release));
+       own_window.signal_motion_notify_event().connect (mem_fun (*this, &TearOff::window_motion));
+       own_window.signal_delete_event().connect (mem_fun (*this, &TearOff::window_delete_event));
+       own_window.signal_realize().connect (bind (sigc::ptr_fun (Gtkmm2ext::set_decoration), &own_window, WMDecoration (DECOR_BORDER|DECOR_RESIZEH)));
+
        tearoff_arrow.set_name ("TearOffArrow");
        close_arrow.set_name ("TearOffArrow");
 
        VBox* box2;
        box2 = manage (new VBox);
-       box2->pack_start (tearoff_event_box, false, false, 5);
+       box2->pack_start (tearoff_event_box, false, false, 2);
 
        pack_start (contents);
        pack_start (*box2, false, false, 2);
@@ -74,7 +76,27 @@ TearOff::TearOff (Gtk::Widget& c)
 
 TearOff::~TearOff ()
 {
-       delete own_window;
+}
+
+void
+TearOff::set_visible (bool yn)
+{
+       /* don't change visibility if torn off */
+
+       if (own_window.is_visible()) {
+               return;
+       }
+
+       if (_visible != yn) {
+               _visible = yn;
+               if (yn) {
+                       show_all();
+                       Visible ();
+               } else {
+                       hide ();
+                       Hidden ();
+               }
+       }
 }
 
 gint
@@ -82,13 +104,12 @@ TearOff::tearoff_click (GdkEventButton* ev)
 {
        remove (contents);
        window_box.pack_start (contents);
-       own_window->set_name (get_name());
+       own_window.set_name (get_name());
        close_event_box.set_name (get_name());
-       own_window->show_all ();
-//     own_window->realize ();
+       own_window.show_all ();
        hide ();
        Detach ();
-       return TRUE;
+       return true;
 }
 
 gint
@@ -97,30 +118,36 @@ TearOff::close_click (GdkEventButton* ev)
        window_box.remove (contents);
        pack_start (contents);
        reorder_child (contents, 0);
-       own_window->hide ();
+       own_window.hide ();
        show_all ();
        Attach ();
-       return TRUE;
+       return true;
 }              
 
 gint
 TearOff::window_button_press (GdkEventButton* ev)
 {
+       if (dragging || ev->button != 1) {
+               dragging = false;
+               own_window.remove_modal_grab();
+               return true;
+       }
+
        dragging = true;
        drag_x = ev->x_root;
        drag_y = ev->y_root;
 
-       own_window->add_modal_grab();
+       own_window.add_modal_grab();
 
-       return TRUE;
+       return true;
 }
 
 gint
 TearOff::window_button_release (GdkEventButton* ev)
 {
        dragging = false;
-       own_window->remove_modal_grab();
-       return TRUE;
+       own_window.remove_modal_grab();
+       return true;
 }
 
 gint
@@ -137,12 +164,18 @@ TearOff::window_motion (GdkEventMotion* ev)
        gint mx, my;
        double x_delta;
        double y_delta;
-       Glib::RefPtr<Gdk::Window> win (own_window->get_window());
+       RefPtr<Gdk::Window> win (own_window.get_window());
        
-       own_window->get_pointer (mx, my);
+       own_window.get_pointer (mx, my);
 
        if (!dragging) {
-               return TRUE;
+               return true;
+       }
+
+       if (!(ev->state & GDK_BUTTON1_MASK)) {
+               dragging = false;
+               own_window.remove_modal_grab();
+               return true;
        }
 
        x_delta = ev->x_root - drag_x;
@@ -154,11 +187,11 @@ TearOff::window_motion (GdkEventMotion* ev)
        drag_x = ev->x_root;
        drag_y = ev->y_root;
        
-       return TRUE;
+       return true;
 }
 
 bool
 TearOff::torn_off() const
 {
-       return own_window->is_visible();
+       return own_window.is_visible();
 }