update drobilla's fascistic dir-locals.el to force emacs users into whitespace submis...
[ardour.git] / gtk2_ardour / utils.cc
index 2754ed0281544224ab7d524d65668f6f55d669e8..8cdf5e0b58650b3a04083b6d97308c2146e8da19 100644 (file)
 
 */
 
+#ifdef WAF_BUILD
+#include "gtk2ardour-config.h"
+#endif
+
 #include <pango/pangoft2.h> // for fontmap resolution control for GnomeCanvas
 #include <pango/pangocairo.h> // for fontmap resolution control for GnomeCanvas
 
 #include "ardour/filesystem_paths.h"
 
 #include "ardour_ui.h"
+#include "debug.h"
 #include "public_editor.h"
 #include "keyboard.h"
 #include "utils.h"
 #include "i18n.h"
 #include "rgb_macros.h"
 #include "canvas_impl.h"
+#include "gui_thread.h"
 
 using namespace std;
 using namespace Gtk;
-using namespace sigc;
 using namespace Glib;
 using namespace PBD;
+using Gtkmm2ext::Keyboard;
 
 sigc::signal<void>  DPIReset;
 
 int
-pixel_width (const ustring& str, Pango::FontDescription& font)
+pixel_width (const string& str, Pango::FontDescription& font)
 {
        Label foo;
        Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
@@ -70,20 +76,20 @@ pixel_width (const ustring& str, Pango::FontDescription& font)
        return width;
 }
 
-ustring
-fit_to_pixels (const ustring& str, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses)
+string
+fit_to_pixels (const string& str, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses)
 {
        Label foo;
        Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
-       ustring::size_type shorter_by = 0;
-       ustring txt;
+       string::size_type shorter_by = 0;
+       string txt;
 
        layout->set_font_description (font);
 
        actual_width = 0;
 
-       ustring ustr = str;
-       ustring::iterator last = ustr.end();
+       string ustr = str;
+       string::iterator last = ustr.end();
        --last; /* now points at final entry */
 
        txt = ustr;
@@ -346,31 +352,31 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s
        foo.set_name (style);
        foo.ensure_style ();
 
-       GtkRcStyle* waverc = foo.get_style()->gobj()->rc_style;
+       GtkRcStyle* rc = foo.get_style()->gobj()->rc_style;
 
-       if (waverc) {
+       if (rc) {
                if (attr == "fg") {
-                       r = waverc->fg[state].red / 257;
-                       g = waverc->fg[state].green / 257;
-                       b = waverc->fg[state].blue / 257;
+                       r = rc->fg[state].red / 257;
+                       g = rc->fg[state].green / 257;
+                       b = rc->fg[state].blue / 257;
 
                        /* what a hack ... "a" is for "active" */
                        if (state == Gtk::STATE_NORMAL && rgba) {
-                               a = waverc->fg[GTK_STATE_ACTIVE].red / 257;
+                               a = rc->fg[GTK_STATE_ACTIVE].red / 257;
                        }
                } else if (attr == "bg") {
                        r = g = b = 0;
-                       r = waverc->bg[state].red / 257;
-                       g = waverc->bg[state].green / 257;
-                       b = waverc->bg[state].blue / 257;
+                       r = rc->bg[state].red / 257;
+                       g = rc->bg[state].green / 257;
+                       b = rc->bg[state].blue / 257;
                } else if (attr == "base") {
-                       r = waverc->base[state].red / 257;
-                       g = waverc->base[state].green / 257;
-                       b = waverc->base[state].blue / 257;
+                       r = rc->base[state].red / 257;
+                       g = rc->base[state].green / 257;
+                       b = rc->base[state].blue / 257;
                } else if (attr == "text") {
-                       r = waverc->text[state].red / 257;
-                       g = waverc->text[state].green / 257;
-                       b = waverc->text[state].blue / 257;
+                       r = rc->text[state].red / 257;
+                       g = rc->text[state].green / 257;
+                       b = rc->text[state].blue / 257;
                }
        } else {
                warning << string_compose (_("missing RGBA style for \"%1\""), style) << endl;
@@ -503,12 +509,6 @@ set_color (Gdk::Color& c, int rgb)
        c.set_rgb((rgb >> 16)*256, ((rgb & 0xff00) >> 8)*256, (rgb & 0xff)*256);
 }
 
-#ifdef GTKOSX
-extern "C" {
-       gboolean gdk_quartz_possibly_forward (GdkEvent*);
-}
-#endif
-
 bool
 relay_key_press (GdkEventKey* ev, Gtk::Window* win)
 {
@@ -519,6 +519,79 @@ relay_key_press (GdkEventKey* ev, Gtk::Window* win)
        }
 }
 
+bool
+forward_key_press (GdkEventKey* ev)
+{
+        return PublicEditor::instance().on_key_press_event(ev);
+}
+
+#ifdef GTKOSX
+static guint
+osx_keyval_without_alt (guint accent_keyval)
+{
+       switch (accent_keyval) {
+       case GDK_oe:
+               return GDK_q;
+       case GDK_registered:
+               return GDK_r;
+       case GDK_dagger:
+               return GDK_t;
+       case GDK_yen:
+               return GDK_y;
+       case GDK_diaeresis:
+               return GDK_u;
+       case GDK_oslash:
+               return GDK_o;
+       case GDK_Greek_pi:
+               return GDK_p;
+       case GDK_leftdoublequotemark:
+               return GDK_bracketleft;
+       case GDK_leftsinglequotemark:
+               return GDK_bracketright;
+       case GDK_guillemotleft:
+               return GDK_backslash;
+       case GDK_aring:
+               return GDK_a;
+       case GDK_ssharp:
+               return GDK_s;
+       case GDK_partialderivative:
+               return GDK_d;
+       case GDK_function:
+               return GDK_f;
+       case GDK_copyright:
+               return GDK_g;
+       case GDK_abovedot:
+               return GDK_h;
+       case GDK_notsign:
+               return GDK_l;
+       case GDK_ellipsis:
+               return GDK_semicolon;
+       case GDK_ae:
+               return GDK_apostrophe;
+       case GDK_Greek_OMEGA:
+               return GDK_z;
+       case GDK_ccedilla:
+               return GDK_c;
+       case GDK_radical:
+               return GDK_v;
+       case GDK_integral:
+               return GDK_b;
+       case GDK_mu:
+               return GDK_m;
+       case GDK_lessthanequal:
+               return GDK_comma;
+       case GDK_greaterthanequal:
+               return GDK_period;
+       case GDK_division:
+               return GDK_slash;
+       default:
+               break;
+       }
+
+       return GDK_VoidSymbol;
+}
+#endif
+
 bool
 key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
 {
@@ -527,11 +600,6 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
        bool special_handling_of_unmodified_accelerators = false;
        bool allow_activating = true;
 
-#undef DEBUG_ACCELERATOR_HANDLING
-#ifdef  DEBUG_ACCELERATOR_HANDLING
-       //bool debug = (getenv ("ARDOUR_DEBUG_ACCELERATOR_HANDLING") != 0);
-       bool debug=true;
-#endif
        if (focus) {
                if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
                        special_handling_of_unmodified_accelerators = true;
@@ -545,18 +613,15 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
        }
 #endif
 
-#ifdef DEBUG_ACCELERATOR_HANDLING
-       if (debug) {
-               cerr << "Win = " << win << " Key event: code = " << ev->keyval << " state = " << hex << ev->state << dec << " special handling ? "
-                    << special_handling_of_unmodified_accelerators
-                    << " magic widget focus ? "
-                    << Keyboard::some_magic_widget_has_focus()
-                    << " allow_activation ? "
-                    << allow_activating
-                    << endl;
-       }
-#endif
-
+        
+        DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 Key event: code = %2  state = %3 special handling ? %4 magic widget focus ? %5 allow_activation ? %6\n",
+                                                          win,
+                                                          ev->keyval,
+                                                          ev->state,
+                                                          special_handling_of_unmodified_accelerators,
+                                                          Keyboard::some_magic_widget_has_focus(),
+                                                          allow_activating));
+        
        /* This exists to allow us to override the way GTK handles
           key events. The normal sequence is:
 
@@ -588,6 +653,22 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
           all "normal text" accelerators.
        */
 
+#ifdef GTKOSX
+       if (!special_handling_of_unmodified_accelerators) {
+               if (ev->state & GDK_MOD1_MASK) {
+                       /* we're not in a text entry or "magic focus" widget so we don't want OS X "special-character" 
+                          text-style handling of alt-<key>. change the keyval back to what it would be without
+                          the alt key. this way, we see <alt>-v rather than <alt>-radical and so on.
+                       */
+                       guint keyval_without_alt = osx_keyval_without_alt (ev->keyval);
+
+                       if (keyval_without_alt != GDK_VoidSymbol) {
+                                DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Remapped %1 to %2\n", gdk_keyval_name (ev->keyval), gdk_keyval_name (keyval_without_alt)));
+                               ev->keyval = keyval_without_alt;
+                       }
+               }
+       }
+#endif
 
        if (!special_handling_of_unmodified_accelerators) {
 
@@ -598,21 +679,10 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
 
                uint32_t fakekey = ev->keyval;
 
-               if (possibly_translate_keyval_to_make_legal_accelerator (fakekey)) {
+               if (Gtkmm2ext::possibly_translate_keyval_to_make_legal_accelerator (fakekey)) {
                        if (allow_activating && gtk_accel_groups_activate(G_OBJECT(win), fakekey, GdkModifierType(ev->state))) {
                                return true;
                        }
-
-#ifdef GTKOSX
-                       if (allow_activating) {
-                               int oldval = ev->keyval;
-                               ev->keyval = fakekey;
-                               if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
-                                       return true;
-                               }
-                               ev->keyval = oldval;
-                       }
-#endif
                }
        }
 
@@ -624,69 +694,35 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
 
                /* no special handling or there are modifiers in effect: accelerate first */
 
-#ifdef DEBUG_ACCELERATOR_HANDLING
-               if (debug) {
-                       cerr << "\tactivate, then propagate\n";
-               }
-#endif
+                DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
 
                if (allow_activating) {
-#ifdef GTKOSX
-                       if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
-                               return true;
-                       }
-#endif
                        if (gtk_window_activate_key (win, ev)) {
                                return true;
                        }
                }
 
-#ifdef DEBUG_ACCELERATOR_HANDLING
-               if (debug) {
-                       cerr << "\tnot accelerated, now propagate\n";
-               }
-#endif
+                DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
+
                return gtk_window_propagate_key_event (win, ev);
        }
 
        /* no modifiers, propagate first */
 
-#ifdef DEBUG_ACCELERATOR_HANDLING
-       if (debug) {
-               cerr << "\tpropagate, then activate\n";
-       }
-#endif
-       if (!gtk_window_propagate_key_event (win, ev)) {
-#ifdef DEBUG_ACCELERATOR_HANDLING
-               if (debug) {
-                       cerr << "\tpropagation didn't handle, so activate\n";
-               }
-#endif
+        DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
 
+       if (!gtk_window_propagate_key_event (win, ev)) {
+                DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
                if (allow_activating) {
-
-#ifdef GTKOSX
-                       if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
-                               return true;
-                       }
-#endif
                        return gtk_window_activate_key (win, ev);
                }
 
        } else {
-#ifdef DEBUG_ACCELERATOR_HANDLING
-               if (debug) {
-                       cerr << "\thandled by propagate\n";
-               }
-#endif
+                DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
                return true;
        }
 
-#ifdef DEBUG_ACCELERATOR_HANDLING
-       if (debug) {
-               cerr << "\tnot handled\n";
-       }
-#endif
+        DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
        return true;
 }
 
@@ -716,7 +752,7 @@ get_xpm (std::string name)
        return xpm_map[name];
 }
 
-Glib::ustring
+std::string
 get_icon_path (const char* cname)
 {
        string name = cname;
@@ -852,122 +888,6 @@ reset_dpi ()
        DPIReset();//Emit Signal
 }
 
-bool
-possibly_translate_keyval_to_make_legal_accelerator (uint32_t& keyval)
-{
-       int fakekey = GDK_VoidSymbol;
-
-       switch (keyval) {
-       case GDK_Tab:
-       case GDK_ISO_Left_Tab:
-               fakekey = GDK_nabla;
-               break;
-
-       case GDK_Up:
-               fakekey = GDK_uparrow;
-               break;
-
-       case GDK_Down:
-               fakekey = GDK_downarrow;
-               break;
-
-       case GDK_Right:
-               fakekey = GDK_rightarrow;
-               break;
-
-       case GDK_Left:
-               fakekey = GDK_leftarrow;
-               break;
-
-       case GDK_Return:
-               fakekey = GDK_3270_Enter;
-               break;
-
-       case GDK_KP_Enter:
-               fakekey = GDK_F35;
-               break;
-
-       default:
-               break;
-       }
-
-       if (fakekey != GDK_VoidSymbol) {
-               keyval = fakekey;
-               return true;
-       }
-
-       return false;
-}
-
-uint32_t
-possibly_translate_legal_accelerator_to_real_key (uint32_t keyval)
-{
-       switch (keyval) {
-       case GDK_nabla:
-               return GDK_Tab;
-               break;
-
-       case GDK_uparrow:
-               return GDK_Up;
-               break;
-
-       case GDK_downarrow:
-               return GDK_Down;
-               break;
-
-       case GDK_rightarrow:
-               return GDK_Right;
-               break;
-
-       case GDK_leftarrow:
-               return GDK_Left;
-               break;
-
-       case GDK_3270_Enter:
-               return GDK_Return;
-
-       case GDK_F35:
-               return GDK_KP_Enter;
-               break;
-       }
-
-       return keyval;
-}
-
-
-
-inline guint8
-convert_color_channel (guint8 src,
-                      guint8 alpha)
-{
-       return alpha ? ((guint (src) << 8) - src) / alpha : 0;
-}
-
-void
-convert_bgra_to_rgba (guint8 const* src,
-                     guint8*       dst,
-                     int           width,
-                     int           height)
-{
-       guint8 const* src_pixel = src;
-       guint8*       dst_pixel = dst;
-
-       for (int y = 0; y < height; y++)
-               for (int x = 0; x < width; x++)
-               {
-                       dst_pixel[0] = convert_color_channel (src_pixel[2],
-                                                             src_pixel[3]);
-                       dst_pixel[1] = convert_color_channel (src_pixel[1],
-                                                             src_pixel[3]);
-                       dst_pixel[2] = convert_color_channel (src_pixel[0],
-                                                             src_pixel[3]);
-                       dst_pixel[3] = src_pixel[3];
-
-                       dst_pixel += 4;
-                       src_pixel += 4;
-               }
-}
-
 void
 resize_window_to_proportion_of_monitor (Gtk::Window* window, int max_width, int max_height)
 {
@@ -975,45 +895,29 @@ resize_window_to_proportion_of_monitor (Gtk::Window* window, int max_width, int
        Gdk::Rectangle monitor_rect;
        screen->get_monitor_geometry (0, monitor_rect);
 
-       int const w = std::min (monitor_rect.get_width(), max_width) * 0.8;
-       int const h = std::min (monitor_rect.get_height(), max_height) * 0.8;
+       int const w = std::min (int (monitor_rect.get_width() * 0.8), max_width);
+       int const h = std::min (int (monitor_rect.get_height() * 0.8), max_height);
 
        window->resize (w, h);
 }
 
-Glib::RefPtr<Gdk::Pixbuf>
-pixbuf_from_ustring(const ustring& name, Pango::FontDescription* font, int clip_width, int clip_height, Gdk::Color fg)
+
+/** Replace _ with __ in a string; for use with menu item text to make underscores displayed correctly */
+string
+escape_underscores (string const & s)
 {
-       static Glib::RefPtr<Gdk::Pixbuf>* empty_pixbuf = 0;
+       string o;
+       string::size_type const N = s.length ();
 
-       if (name.empty()) {
-               if (empty_pixbuf == 0) {
-                       empty_pixbuf = new Glib::RefPtr<Gdk::Pixbuf>;
-                       *empty_pixbuf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
+       for (string::size_type i = 0; i < N; ++i) {
+               if (s[i] == '_') {
+                       o += "__";
+               } else {
+                       o += s[i];
                }
-               cerr << "\n\nUSE EMPTY PIXBUF\n";
-               return *empty_pixbuf;
-       }
-
-       Glib::RefPtr<Gdk::Pixbuf> buf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
-
-       cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, clip_width, clip_height);
-       cairo_t* cr = cairo_create (surface);
-       cairo_text_extents_t te;
-       
-       cairo_set_source_rgba (cr, fg.get_red_p(), fg.get_green_p(), fg.get_blue_p(), 1.0);
-       cairo_select_font_face (cr, font->get_family().c_str(),
-                               CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
-       cairo_set_font_size (cr,  font->get_size() / Pango::SCALE);
-       cairo_text_extents (cr, name.c_str(), &te);
-       
-       cairo_move_to (cr, 0.5, 0.5 - te.height / 2 - te.y_bearing + clip_height / 2);
-       cairo_show_text (cr, name.c_str());
-       
-       convert_bgra_to_rgba(cairo_image_surface_get_data (surface), buf->get_pixels(), clip_width, clip_height);
-
-       cairo_destroy(cr);
-       cairo_surface_destroy(surface);
-
-       return buf;
+       }
+
+       return o;
 }
+
+