X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Futils.cc;h=a52969268adb0b18b74efaab1f3e15d8b621f801;hb=e55e3fde7cec89c49e01046a2db276b2d8f30958;hp=76b237713adba8725cd99160f617e6faab8811ea;hpb=f95d814143060efc7a69164362a3311b3a3b54a4;p=ardour.git diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc index 76b237713a..a52969268a 100644 --- a/gtk2_ardour/utils.cc +++ b/gtk2_ardour/utils.cc @@ -15,22 +15,29 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id$ */ +#include // for fontmap resolution control for GnomeCanvas +#include // for fontmap resolution control for GnomeCanvas + #include #include #include #include #include +#include #include #include #include #include #include +#include + #include -#include +#include + +#include #include "ardour_ui.h" #include "keyboard.h" @@ -45,12 +52,30 @@ using namespace sigc; using namespace Glib; using namespace PBD; +sigc::signal DPIReset; + +int +pixel_width (const ustring& str, Pango::FontDescription& font) +{ + Label foo; + Glib::RefPtr layout = foo.create_pango_layout (""); + + layout->set_font_description (font); + layout->set_text (str); + + int width, height; + Gtkmm2ext::get_ink_pixel_size (layout, width, height); + return width; +} + ustring -fit_to_pixels (const ustring& str, int pixel_width, Pango::FontDescription& font, int& actual_width) +fit_to_pixels (const ustring& str, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses) { Label foo; Glib::RefPtr layout = foo.create_pango_layout (""); - + ustring::size_type shorter_by = 0; + ustring txt; + layout->set_font_description (font); actual_width = 0; @@ -59,9 +84,11 @@ fit_to_pixels (const ustring& str, int pixel_width, Pango::FontDescription& font ustring::iterator last = ustr.end(); --last; /* now points at final entry */ + txt = ustr; + while (!ustr.empty()) { - layout->set_text (ustr); + layout->set_text (txt); int width, height; Gtkmm2ext::get_ink_pixel_size (layout, width, height); @@ -72,15 +99,23 @@ fit_to_pixels (const ustring& str, int pixel_width, Pango::FontDescription& font } ustr.erase (last--); + shorter_by++; + + if (with_ellipses && shorter_by > 3) { + txt = ustr; + txt += "..."; + } else { + txt = ustr; + } } - return ustr; + return txt; } gint just_hide_it (GdkEventAny *ev, Gtk::Window *win) { - win->hide_all (); + win->hide (); return TRUE; } @@ -108,7 +143,7 @@ xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h) return 0; } - savergb = rgb = (unsigned char*)art_alloc (h * w * 3); + savergb = rgb = (unsigned char*) malloc (h * w * 3); // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION for (t = 0; t < colors; ++t) { @@ -151,7 +186,7 @@ xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h) return 0; } - savergb = rgb = (unsigned char*)art_alloc (h * w * 4); + savergb = rgb = (unsigned char*) malloc (h * w * 4); // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION @@ -209,7 +244,7 @@ get_canvas_points (string who, uint32_t npoints) return new ArdourCanvas::Points (npoints); } -Pango::FontDescription +Pango::FontDescription* get_font_for_style (string widgetname) { Gtk::Window window (WINDOW_TOPLEVEL); @@ -221,67 +256,23 @@ get_font_for_style (string widgetname) foobar.ensure_style(); style = foobar.get_style (); - return style->get_font(); -} - -gint -pane_handler (GdkEventButton* ev, Gtk::Paned* pane) -{ - if (ev->window != Gtkmm2ext::get_paned_handle (*pane)) { - return FALSE; - } - if (Keyboard::is_delete_event (ev)) { - - gint pos; - gint cmp; + Glib::RefPtr layout = foobar.get_layout(); + + PangoFontDescription *pfd = (PangoFontDescription *)pango_layout_get_font_description((PangoLayout *)layout->gobj()); + + if (!pfd) { - pos = pane->get_position (); - - if (dynamic_cast(pane)) { - cmp = pane->get_height(); - } else { - cmp = pane->get_width(); - } - - /* we have to use approximations here because we can't predict the - exact position or sizes of the pane (themes, etc) - */ - - if (pos < 10 || abs (pos - cmp) < 10) { - - /* already collapsed: restore it (note that this is cast from a pointer value to int, which is tricky on 64bit */ - - pane->set_position ((intptr_t) pane->get_data ("rpos")); - - } else { - - int collapse_direction; + /* layout inherited its font description from a PangoContext */ - /* store the current position */ - - pane->set_data ("rpos", (gpointer) pos); - - /* collapse to show the relevant child in full */ - - collapse_direction = (intptr_t) pane->get_data ("collapse-direction"); - - if (collapse_direction) { - pane->set_position (1); - } else { - if (dynamic_cast(pane)) { - pane->set_position (pane->get_height()); - } else { - pane->set_position (pane->get_width()); - } - } - } - - return TRUE; + PangoContext* ctxt = (PangoContext*) pango_layout_get_context ((PangoLayout*) layout->gobj()); + pfd = pango_context_get_font_description (ctxt); + return new Pango::FontDescription (pfd, true); /* make a copy */ } - return FALSE; + return new Pango::FontDescription (pfd, true); /* make a copy */ } + uint32_t rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, string attr, int state, bool rgba) { @@ -309,6 +300,7 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s r = waverc->fg[state].red / 257; g = waverc->fg[state].green / 257; b = waverc->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; @@ -340,6 +332,61 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s } } + +Gdk::Color +color_from_style (string widget_style_name, int state, string attr) +{ + GtkStyle* style; + + style = gtk_rc_get_style_by_paths (gtk_settings_get_default(), + widget_style_name.c_str(), + 0, G_TYPE_NONE); + + if (!style) { + error << string_compose (_("no style found for %1, using red"), style) << endmsg; + return Gdk::Color ("red"); + } + + cerr << "got style for " << widget_style_name << endl; + + if (attr == "fg") { + return Gdk::Color (&style->fg[state]); + } + + if (attr == "bg") { + cerr << "returning color from bg\n"; + return Gdk::Color (&style->bg[state]); + } + + if (attr == "light") { + return Gdk::Color (&style->light[state]); + } + + if (attr == "dark") { + return Gdk::Color (&style->dark[state]); + } + + if (attr == "mid") { + return Gdk::Color (&style->mid[state]); + } + + if (attr == "text") { + return Gdk::Color (&style->text[state]); + } + + if (attr == "base") { + return Gdk::Color (&style->base[state]); + } + + if (attr == "text_aa") { + return Gdk::Color (&style->text_aa[state]); + } + + error << string_compose (_("unknown style attribute %1 requested for color; using \"red\""), attr) << endmsg; + return Gdk::Color ("red"); +} + + bool canvas_item_visible (ArdourCanvas::Item* item) { @@ -352,6 +399,12 @@ 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 key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) { @@ -359,12 +412,24 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) GtkWidget* focus = gtk_window_get_focus (win); bool special_handling_of_unmodified_accelerators = false; +#undef DEBUG_ACCELERATOR_HANDLING +#ifdef DEBUG_ACCELERATOR_HANDLING + bool debug = (getenv ("ARDOUR_DEBUG_ACCELERATOR_HANDLING") != 0); +#endif if (focus) { - if (GTK_IS_ENTRY(focus)) { + if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) { special_handling_of_unmodified_accelerators = true; - } + } } +#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 + << endl; + } +#endif + /* This exists to allow us to override the way GTK handles key events. The normal sequence is: @@ -404,68 +469,139 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) it does allow. */ + int fakekey = GDK_VoidSymbol; int ret = false; switch (ev->keyval) { + case GDK_Tab: + case GDK_ISO_Left_Tab: + fakekey = GDK_nabla; + break; + case GDK_Up: - ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_uparrow, GdkModifierType(ev->state)); + fakekey = GDK_uparrow; break; case GDK_Down: - ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_downarrow, GdkModifierType(ev->state)); + fakekey = GDK_downarrow; break; case GDK_Right: - ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_rightarrow, GdkModifierType(ev->state)); + fakekey = GDK_rightarrow; break; case GDK_Left: - ret = gtk_accel_groups_activate(G_OBJECT(win), GDK_leftarrow, GdkModifierType(ev->state)); + fakekey = GDK_leftarrow; break; default: break; } - if (ret) { - return true; + if (fakekey != GDK_VoidSymbol) { + ret = gtk_accel_groups_activate(G_OBJECT(win), fakekey, GdkModifierType(ev->state)); + + if (ret) { + return true; + } + +#ifdef GTKOSX + int oldval = ev->keyval; + ev->keyval = fakekey; + if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) { + return true; + } + ev->keyval = oldval; +#endif } } - - if (!special_handling_of_unmodified_accelerators || - ev->state & (Gdk::MOD1_MASK| - Gdk::MOD3_MASK| - Gdk::MOD4_MASK| - Gdk::MOD5_MASK| - Gdk::CONTROL_MASK)) { - /* no special handling or modifiers in effect: accelerate first */ + /* consider all relevant modifiers but not LOCK or SHIFT */ + + guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK)); + if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) { + + /* no special handling or there are modifiers in effect: accelerate first */ + +#ifdef DEBUG_ACCELERATOR_HANDLING + if (debug) { + cerr << "\tactivate, then propagate\n"; + } +#endif +#ifdef GTKOSX + if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) { + return true; + } +#endif if (!gtk_window_activate_key (win, ev)) { +#ifdef DEBUG_ACCELERATOR_HANDLING + if (debug) { + cerr << "\tnot accelerated, now propagate\n"; + } +#endif return gtk_window_propagate_key_event (win, ev); } else { +#ifdef DEBUG_ACCELERATOR_HANDLING + if (debug) { + cerr << "\taccelerated - done.\n"; + } +#endif return true; } } /* 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 +#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 + return true; + } +#ifdef DEBUG_ACCELERATOR_HANDLING + if (debug) { + cerr << "\tnot handled\n"; + } +#endif return true; } Glib::RefPtr get_xpm (std::string name) { - if (!xpm_map[name]) { - xpm_map[name] = Gdk::Pixbuf::create_from_file (ARDOUR::find_data_file(name, "pixmaps")); + SearchPath spath(ARDOUR::ardour_search_path()); + spath += ARDOUR::system_data_search_path(); + + spath.add_subdirectory_to_paths("pixmaps"); + + sys::path data_file_path; + + if(!find_file_in_search_path (spath, name, data_file_path)) { + fatal << string_compose (_("cannot find XPM file for %1"), name) << endmsg; } - - return (xpm_map[name]); + + return Gdk::Pixbuf::create_from_file (data_file_path.to_string()); } Glib::RefPtr @@ -474,14 +610,31 @@ get_icon (const char* cname) string name = cname; name += X_(".png"); - string path = ARDOUR::find_data_file (name, "icons"); + SearchPath spath(ARDOUR::ardour_search_path()); + spath += ARDOUR::system_data_search_path(); + + spath.add_subdirectory_to_paths("icons"); - if (path.empty()) { + sys::path data_file_path; + + if (!find_file_in_search_path (spath, name, data_file_path)) { fatal << string_compose (_("cannot find icon image for %1"), name) << endmsg; - /*NOTREACHED*/ } - return Gdk::Pixbuf::create_from_file (path); + Glib::RefPtr img; + try { + img = Gdk::Pixbuf::create_from_file (data_file_path.to_string()); + } + catch (const Gdk::PixbufError &e) + { + cerr << "Caught PixbufError: " << e.what() << endl; + } + catch (...) + { + g_message("Caught ... "); + } + + return img; } string @@ -511,3 +664,77 @@ longest (vector& strings) return *longest; } + +bool +key_is_legal_for_numeric_entry (guint keyval) +{ + switch (keyval) { + case GDK_minus: + case GDK_plus: + case GDK_period: + case GDK_comma: + case GDK_0: + case GDK_1: + case GDK_2: + case GDK_3: + case GDK_4: + case GDK_5: + case GDK_6: + case GDK_7: + case GDK_8: + case GDK_9: + case GDK_KP_Add: + case GDK_KP_Subtract: + case GDK_KP_Decimal: + case GDK_KP_0: + case GDK_KP_1: + case GDK_KP_2: + case GDK_KP_3: + case GDK_KP_4: + case GDK_KP_5: + case GDK_KP_6: + case GDK_KP_7: + case GDK_KP_8: + case GDK_KP_9: + case GDK_Return: + case GDK_BackSpace: + case GDK_Delete: + case GDK_KP_Enter: + case GDK_Home: + case GDK_End: + case GDK_Left: + case GDK_Right: + return true; + + default: + break; + } + + return false; +} +void +set_pango_fontsize () +{ + long val = ARDOUR::Config->get_font_scale(); + + /* FT2 rendering */ + + pango_ft2_font_map_set_resolution ((PangoFT2FontMap*) pango_ft2_font_map_for_display(), val/1024, val/1024); + + /* Cairo rendering, in case there is any */ + + pango_cairo_font_map_set_resolution ((PangoCairoFontMap*) pango_cairo_font_map_get_default(), val/1024); +} + +void +reset_dpi () +{ + long val = ARDOUR::Config->get_font_scale(); + set_pango_fontsize (); + /* Xft rendering */ + + gtk_settings_set_long_property (gtk_settings_get_default(), + "gtk-xft-dpi", val, "ardour"); + DPIReset();//Emit Signal +} +