merge with master and fix 4 conflicts by hand
[ardour.git] / libs / gtkmm2ext / utils.cc
1 /*
2     Copyright (C) 1999 Paul Barton-Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18     $Id$
19 */
20
21 #include <map>
22
23 #include <gtk/gtkpaned.h>
24 #include <gtk/gtk.h>
25
26 #include <gtkmm/widget.h>
27 #include <gtkmm/button.h>
28 #include <gtkmm/window.h>
29 #include <gtkmm/paned.h>
30 #include <gtkmm/label.h>
31 #include <gtkmm/comboboxtext.h>
32 #include <gtkmm/tooltip.h>
33
34 #include "gtkmm2ext/utils.h"
35
36 #include "i18n.h"
37
38 using namespace std;
39
40 void
41 Gtkmm2ext::init (const char* localedir)
42 {
43 #ifdef ENABLE_NLS
44         (void) bindtextdomain(PACKAGE, localedir);
45         (void) bind_textdomain_codeset (PACKAGE, "UTF-8");
46 #endif
47 }
48
49 void
50 Gtkmm2ext::get_ink_pixel_size (Glib::RefPtr<Pango::Layout> layout,
51                                int& width,
52                                int& height)
53 {
54         Pango::Rectangle ink_rect = layout->get_ink_extents ();
55         
56         width = (ink_rect.get_width() + PANGO_SCALE / 2) / PANGO_SCALE;
57         height = (ink_rect.get_height() + PANGO_SCALE / 2) / PANGO_SCALE;
58 }
59
60 void
61 Gtkmm2ext::get_pixel_size (Glib::RefPtr<Pango::Layout> layout,
62                            int& width,
63                            int& height)
64 {
65         layout->get_pixel_size (width, height);
66 }
67
68 void
69 Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget &w, const gchar *text,
70                                                    gint hpadding, gint vpadding)
71 {
72         int width, height;
73         w.ensure_style ();
74         
75         get_pixel_size (w.create_pango_layout (text), width, height);
76         w.set_size_request(width + hpadding, height + vpadding);
77 }
78
79 void
80 Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget &w, 
81                                                    const std::vector<std::string>& strings,
82                                                    gint hpadding, gint vpadding)
83 {
84         int width, height;
85         int width_max = 0;
86         int height_max = 0;
87         w.ensure_style ();
88         vector<string> copy;
89         const vector<string>* to_use;
90         vector<string>::const_iterator i;
91
92         for (i = strings.begin(); i != strings.end(); ++i) {
93                 if ((*i).find_first_of ("gy") != string::npos) {
94                         /* contains a descender */
95                         break;
96                 }
97         }
98         
99         if (i == strings.end()) {
100                 /* make a copy of the strings then add one that has a descender */
101                 copy = strings;
102                 copy.push_back ("g");
103                 to_use = &copy;
104         } else {
105                 to_use = &strings;
106         }
107         
108         for (vector<string>::const_iterator i = to_use->begin(); i != to_use->end(); ++i) {
109                 get_pixel_size (w.create_pango_layout (*i), width, height);
110                 width_max = max(width_max,width);
111                 height_max = max(height_max, height);
112         }
113
114         w.set_size_request(width_max + hpadding, height_max + vpadding);
115 }
116
117 static inline guint8
118 demultiply_alpha (guint8 src,
119                   guint8 alpha)
120 {
121         /* cairo pixel buffer data contains RGB values with the alpha
122            values premultiplied.
123
124            GdkPixbuf pixel buffer data contains RGB values without the
125            alpha value applied.
126
127            this removes the alpha component from the cairo version and
128            returns the GdkPixbuf version.
129         */
130         return alpha ? ((guint (src) << 8) - src) / alpha : 0;
131 }
132
133 void
134 Gtkmm2ext::convert_bgra_to_rgba (guint8 const* src,
135                                  guint8*       dst,
136                                  int           width,
137                                  int           height)
138 {
139         guint8 const* src_pixel = src;
140         guint8*       dst_pixel = dst;
141         
142         /* cairo pixel data is endian-dependent ARGB with A in the most significant 8 bits,
143            with premultipled alpha values (see preceding function)
144
145            GdkPixbuf pixel data is non-endian-dependent RGBA with R in the lowest addressable
146            8 bits, and non-premultiplied alpha values.
147
148            convert from the cairo values to the GdkPixbuf ones.
149         */
150
151         for (int y = 0; y < height; y++) {
152                 for (int x = 0; x < width; x++) {
153 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
154                         /* Cairo [ B G R A ] is actually  [ B G R A ] in memory SOURCE
155                                                             0 1 2 3
156                            Pixbuf [ R G B A ] is actually [ R G B A ] in memory DEST
157                         */
158                         dst_pixel[0] = demultiply_alpha (src_pixel[2],
159                                                          src_pixel[3]); // R [0] <= [ 2 ]
160                         dst_pixel[1] = demultiply_alpha (src_pixel[1],
161                                                          src_pixel[3]); // G [1] <= [ 1 ]
162                         dst_pixel[2] = demultiply_alpha (src_pixel[0],  
163                                                          src_pixel[3]); // B [2] <= [ 0 ]
164                         dst_pixel[3] = src_pixel[3]; // alpha
165                         
166 #elif G_BYTE_ORDER == G_BIG_ENDIAN
167                         /* Cairo [ B G R A ] is actually  [ A R G B ] in memory SOURCE
168                                                             0 1 2 3
169                            Pixbuf [ R G B A ] is actually [ R G B A ] in memory DEST
170                         */
171                         dst_pixel[0] = demultiply_alpha (src_pixel[1],
172                                                          src_pixel[0]); // R [0] <= [ 1 ]
173                         dst_pixel[1] = demultiply_alpha (src_pixel[2],
174                                                          src_pixel[0]); // G [1] <= [ 2 ]
175                         dst_pixel[2] = demultiply_alpha (src_pixel[3],
176                                                          src_pixel[0]); // B [2] <= [ 3 ]
177                         dst_pixel[3] = src_pixel[0]; // alpha
178                         
179 #else
180 #error ardour does not currently support PDP-endianess
181 #endif                  
182                         
183                         dst_pixel += 4;
184                         src_pixel += 4;
185                 }
186         }
187 }
188
189 Glib::RefPtr<Gdk::Pixbuf>
190 Gtkmm2ext::pixbuf_from_string(const string& name, const Pango::FontDescription& font, int clip_width, int clip_height, Gdk::Color fg)
191 {
192         static Glib::RefPtr<Gdk::Pixbuf>* empty_pixbuf = 0;
193
194         if (name.empty()) {
195                 if (empty_pixbuf == 0) {
196                         empty_pixbuf = new Glib::RefPtr<Gdk::Pixbuf>;
197                         *empty_pixbuf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
198                 }
199                 return *empty_pixbuf;
200         }
201
202         Glib::RefPtr<Gdk::Pixbuf> buf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
203
204         cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, clip_width, clip_height);
205         cairo_t* cr = cairo_create (surface);
206         cairo_text_extents_t te;
207         
208         cairo_set_source_rgba (cr, fg.get_red_p(), fg.get_green_p(), fg.get_blue_p(), 1.0);
209         cairo_select_font_face (cr, font.get_family().c_str(),
210                                 CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
211         cairo_set_font_size (cr,  font.get_size() / Pango::SCALE);
212         cairo_text_extents (cr, name.c_str(), &te);
213         
214         cairo_move_to (cr, 0.5, int (0.5 - te.height / 2 - te.y_bearing + clip_height / 2));
215         cairo_show_text (cr, name.c_str());
216         
217         convert_bgra_to_rgba(cairo_image_surface_get_data (surface), buf->get_pixels(), clip_width, clip_height);
218
219         cairo_destroy(cr);
220         cairo_surface_destroy(surface);
221
222         return buf;
223 }
224
225 void
226 Gtkmm2ext::set_popdown_strings (Gtk::ComboBoxText& cr, const vector<string>& strings)
227 {
228         vector<string>::const_iterator i;
229
230         cr.clear ();
231
232         for (i = strings.begin(); i != strings.end(); ++i) {
233                 cr.append_text (*i);
234         }
235 }
236
237 GdkWindow*
238 Gtkmm2ext::get_paned_handle (Gtk::Paned& paned)
239 {
240         return GTK_PANED(paned.gobj())->handle;
241 }
242
243 void
244 Gtkmm2ext::set_decoration (Gtk::Window* win, Gdk::WMDecoration decor)
245 {
246         win->get_window()->set_decorations (decor);
247 }
248
249 void Gtkmm2ext::set_treeview_header_as_default_label(Gtk::TreeViewColumn* c)
250 {
251         gtk_tree_view_column_set_widget( c->gobj(), GTK_WIDGET(0) );
252 }
253
254 void
255 Gtkmm2ext::detach_menu (Gtk::Menu& menu)
256 {
257         /* its possible for a Gtk::Menu to have no gobj() because it has
258            not yet been instantiated. Catch this and provide a safe
259            detach method.
260         */
261         if (menu.gobj()) {
262                 if (menu.get_attach_widget()) {
263                         menu.detach ();
264                 }
265         }
266 }
267
268 bool
269 Gtkmm2ext::possibly_translate_keyval_to_make_legal_accelerator (uint32_t& keyval)
270 {
271         int fakekey = GDK_VoidSymbol;
272
273         switch (keyval) {
274         case GDK_Tab:
275         case GDK_ISO_Left_Tab:
276                 fakekey = GDK_nabla;
277                 break;
278
279         case GDK_Up:
280                 fakekey = GDK_uparrow;
281                 break;
282
283         case GDK_Down:
284                 fakekey = GDK_downarrow;
285                 break;
286
287         case GDK_Right:
288                 fakekey = GDK_rightarrow;
289                 break;
290
291         case GDK_Left:
292                 fakekey = GDK_leftarrow;
293                 break;
294
295         case GDK_Return:
296                 fakekey = GDK_3270_Enter;
297                 break;
298
299         case GDK_KP_Enter:
300                 fakekey = GDK_F35;
301                 break;
302
303         default:
304                 break;
305         }
306
307         if (fakekey != GDK_VoidSymbol) {
308                 keyval = fakekey;
309                 return true;
310         }
311
312         return false;
313 }
314
315 uint32_t
316 Gtkmm2ext::possibly_translate_legal_accelerator_to_real_key (uint32_t keyval)
317 {
318         switch (keyval) {
319         case GDK_nabla:
320                 return GDK_Tab;
321                 break;
322
323         case GDK_uparrow:
324                 return GDK_Up;
325                 break;
326
327         case GDK_downarrow:
328                 return GDK_Down;
329                 break;
330
331         case GDK_rightarrow:
332                 return GDK_Right;
333                 break;
334
335         case GDK_leftarrow:
336                 return GDK_Left;
337                 break;
338
339         case GDK_3270_Enter:
340                 return GDK_Return;
341
342         case GDK_F35:
343                 return GDK_KP_Enter;
344                 break;
345         }
346
347         return keyval;
348 }
349
350 int
351 Gtkmm2ext::physical_screen_height (Glib::RefPtr<Gdk::Window> win)
352 {
353         GdkScreen* scr = gdk_screen_get_default();
354
355         if (win) {
356                 GdkRectangle r;
357                 gint monitor = gdk_screen_get_monitor_at_window (scr, win->gobj());
358                 gdk_screen_get_monitor_geometry (scr, monitor, &r);
359                 return r.height;
360         } else {
361                 return gdk_screen_get_height (scr);
362         }
363 }
364
365 int
366 Gtkmm2ext::physical_screen_width (Glib::RefPtr<Gdk::Window> win)
367 {
368         GdkScreen* scr = gdk_screen_get_default();
369         
370         if (win) {
371                 GdkRectangle r;
372                 gint monitor = gdk_screen_get_monitor_at_window (scr, win->gobj());
373                 gdk_screen_get_monitor_geometry (scr, monitor, &r);
374                 return r.width;
375         } else {
376                 return gdk_screen_get_width (scr);
377         }
378 }
379
380 void
381 Gtkmm2ext::container_clear (Gtk::Container& c)
382 {
383         list<Gtk::Widget*> children = c.get_children();
384         for (list<Gtk::Widget*>::iterator child = children.begin(); child != children.end(); ++child) {
385                 c.remove (**child);
386         }
387 }
388
389 void
390 Gtkmm2ext::rounded_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
391 {
392         rounded_rectangle (context->cobj(), x, y, w, h, r);
393 }
394 void
395 Gtkmm2ext::rounded_top_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
396 {
397         rounded_top_rectangle (context->cobj(), x, y, w, h, r);
398 }
399 void
400 Gtkmm2ext::rounded_top_left_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
401 {
402         rounded_top_left_rectangle (context->cobj(), x, y, w, h, r);
403 }
404 void
405 Gtkmm2ext::rounded_top_right_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
406 {
407         rounded_top_right_rectangle (context->cobj(), x, y, w, h, r);
408 }
409 void
410 Gtkmm2ext::rounded_top_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
411 {
412         rounded_top_half_rectangle (context->cobj(), x, y, w, h, r);
413 }
414 void
415 Gtkmm2ext::rounded_bottom_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
416 {
417         rounded_bottom_half_rectangle (context->cobj(), x, y, w, h, r);
418 }
419
420 void
421 Gtkmm2ext::rounded_left_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
422 {
423         rounded_left_half_rectangle (context->cobj(), x, y, w, h, r);
424 }
425
426 void
427 Gtkmm2ext::rounded_right_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
428 {
429         rounded_right_half_rectangle (context->cobj(), x, y, w, h, r);
430 }
431
432 void
433 Gtkmm2ext::rounded_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
434 {
435         double degrees = M_PI / 180.0;
436
437         cairo_new_sub_path (cr);
438         cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees);  //tr
439         cairo_arc (cr, x + w - r, y + h - r, r, 0 * degrees, 90 * degrees);  //br
440         cairo_arc (cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees);  //bl
441         cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees);  //tl
442         cairo_close_path (cr);
443 }
444
445 void
446 Gtkmm2ext::rounded_left_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
447 {
448         double degrees = M_PI / 180.0;
449
450         cairo_new_sub_path (cr);
451         cairo_line_to (cr, x+w, y); // tr
452         cairo_line_to (cr, x+w, y + h); // br
453         cairo_arc (cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees);  //bl
454         cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees);  //tl
455         cairo_close_path (cr);
456 }
457
458 void
459 Gtkmm2ext::rounded_right_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
460 {
461         double degrees = M_PI / 180.0;
462
463         cairo_new_sub_path (cr);
464         cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees);  //tr
465         cairo_arc (cr, x + w - r, y + h - r, r, 0 * degrees, 90 * degrees);  //br
466         cairo_line_to (cr, x, y + h); // bl
467         cairo_line_to (cr, x, y); // tl
468         cairo_close_path (cr);
469 }
470
471 void
472 Gtkmm2ext::rounded_top_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
473 {
474         double degrees = M_PI / 180.0;
475
476         cairo_new_sub_path (cr);
477         cairo_move_to (cr, x+w, y+h);
478         cairo_line_to (cr, x, y+h);
479         cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees);  //tl
480         cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees);  //tr
481         cairo_close_path (cr);
482 }
483
484 void
485 Gtkmm2ext::rounded_bottom_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
486 {
487         double degrees = M_PI / 180.0;
488
489         cairo_new_sub_path (cr);
490         cairo_move_to (cr, x, y);
491         cairo_line_to (cr, x+w, y);
492         cairo_arc (cr, x + w - r, y + h - r, r, 0 * degrees, 90 * degrees);  //br
493         cairo_arc (cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees);  //bl
494         cairo_close_path (cr);
495 }
496
497
498 void
499 Gtkmm2ext::rounded_top_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
500 {
501         double degrees = M_PI / 180.0;
502
503         cairo_new_sub_path (cr);
504         cairo_move_to (cr, x+w, y+h);
505         cairo_line_to (cr, x, y+h);
506         cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees);  //tl
507         cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees);  //tr
508         cairo_close_path (cr);
509 }
510
511 void
512 Gtkmm2ext::rounded_top_left_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
513 {
514 /*    A****B
515       H    *
516       *    *
517       *    *
518       F****E
519 */
520         cairo_move_to (cr, x+r,y); // Move to A
521         cairo_line_to (cr, x+w,y); // Straight line to B
522         cairo_line_to (cr, x+w,y+h); // Move to E
523         cairo_line_to (cr, x,y+h); // Line to F
524         cairo_line_to (cr, x,y+r); // Line to H
525         cairo_curve_to (cr, x,y,x,y,x+r,y); // Curve to A
526 }
527
528 void
529 Gtkmm2ext::rounded_top_right_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
530 {
531 /*    A****BQ
532       *    C
533       *    *
534       *    *
535       F****E
536 */
537         cairo_move_to (cr, x,y); // Move to A
538         cairo_line_to (cr, x+w-r,y); // Straight line to B
539         cairo_curve_to (cr, x+w,y,x+w,y,x+w,y+r); // Curve to C, Control points are both at Q
540         cairo_line_to (cr, x+w,y+h); // Move to E
541         cairo_line_to (cr, x,y+h); // Line to F
542         cairo_line_to (cr, x,y); // Line to A
543 }
544
545 Glib::RefPtr<Gdk::Window>
546 Gtkmm2ext::window_to_draw_on (Gtk::Widget& w, Gtk::Widget** parent)
547 {
548         if (w.get_has_window()) {
549                 return w.get_window();
550         }
551
552         (*parent) = w.get_parent();
553
554         while (*parent) {
555                 if ((*parent)->get_has_window()) {
556                         return (*parent)->get_window ();
557                 }
558                 (*parent) = (*parent)->get_parent ();
559         }
560
561         return Glib::RefPtr<Gdk::Window> ();
562 }
563
564 int
565 Gtkmm2ext::pixel_width (const string& str, Pango::FontDescription& font)
566 {
567         Gtk::Label foo;
568         Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
569
570         layout->set_font_description (font);
571         layout->set_text (str);
572
573         int width, height;
574         Gtkmm2ext::get_ink_pixel_size (layout, width, height);
575         return width;
576 }
577
578 #if 0
579 string
580 Gtkmm2ext::fit_to_pixels (const string& str, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses)
581 {
582         /* DECEMBER 2011: THIS PROTOTYPE OF fit_to_pixels() IS NOT USED
583            ANYWHERE AND HAS NOT BEEN TESTED.
584         */
585         Gtk::Label foo;
586         Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout (str);
587         Glib::RefPtr<const Pango::LayoutLine> line;
588
589         layout->set_font_description (font);
590         layout->set_width (pixel_width * PANGO_SCALE);
591
592         if (with_ellipses) {
593                 layout->set_ellipsize (Pango::ELLIPSIZE_END);
594         } else {
595                 layout->set_wrap (Pango::WRAP_CHAR);
596         }
597
598         line = layout->get_line (0);
599
600         /* XXX: might need special care to get the ellipsis character, not sure
601            how that works 
602         */      
603
604         string s = string (layout->get_text ().substr(line->get_start_index(), line->get_length()));
605         
606         cerr << "fit to pixels of " << str << " returns " << s << endl;
607
608         return s;
609 }
610 #endif
611
612 /** Try to fit a string into a given horizontal space by ellipsizing it.
613  *  @param cr Cairo context in which the text will be plotted.
614  *  @param name Text.
615  *  @param avail Available horizontal space.
616  *  @return (Text, possibly ellipsized) and (horizontal size of text)
617  */
618
619 std::pair<std::string, double>
620 Gtkmm2ext::fit_to_pixels (cairo_t* cr, std::string name, double avail)
621 {
622         /* XXX hopefully there exists a more efficient way of doing this */
623
624         bool abbreviated = false;
625         uint32_t width = 0;
626
627         while (1) {
628                 cairo_text_extents_t ext;
629                 cairo_text_extents (cr, name.c_str(), &ext);
630
631                 if (ext.width < avail || name.length() <= 4) {
632                         width = ext.width;
633                         break;
634                 }
635
636                 if (abbreviated) {
637                         name = name.substr (0, name.length() - 4) + "...";
638                 } else {
639                         name = name.substr (0, name.length() - 3) + "...";
640                         abbreviated = true;
641                 }
642         }
643
644         return std::make_pair (name, width);
645 }
646
647 Gtk::Label *
648 Gtkmm2ext::left_aligned_label (string const & t)
649 {
650         Gtk::Label* l = new Gtk::Label (t);
651         l->set_alignment (0, 0.5);
652         return l;
653 }
654
655 static bool
656 make_null_tooltip (int, int, bool, const Glib::RefPtr<Gtk::Tooltip>& t)
657 {
658         t->set_tip_area (Gdk::Rectangle (0, 0, 0, 0));
659         return true;
660 }
661
662 /** Hackily arrange for the provided widget to have no tooltip,
663  *  and also to stop any other widget from providing one while
664  * the mouse is over w.
665  */
666 void
667 Gtkmm2ext::set_no_tooltip_whatsoever (Gtk::Widget& w)
668 {
669         w.property_has_tooltip() = true;
670         w.signal_query_tooltip().connect (sigc::ptr_fun (make_null_tooltip));
671 }
672
673 void
674 Gtkmm2ext::enable_tooltips ()
675 {
676         gtk_rc_parse_string ("gtk-enable-tooltips = 1");
677 }
678
679 void
680 Gtkmm2ext::disable_tooltips ()
681 {
682         gtk_rc_parse_string ("gtk-enable-tooltips = 0");
683 }
684
685 const char*
686 Gtkmm2ext::event_type_string (int event_type)
687 {
688         switch (event_type) {
689         case GDK_NOTHING:
690                 return "nothing";
691         case GDK_DELETE:
692                 return "delete";
693         case GDK_DESTROY:
694                 return "destroy";
695         case GDK_EXPOSE:
696                 return "expose";
697         case GDK_MOTION_NOTIFY:
698                 return "motion_notify";
699         case GDK_BUTTON_PRESS:
700                 return "button_press";
701         case GDK_2BUTTON_PRESS:
702                 return "2button_press";
703         case GDK_3BUTTON_PRESS:
704                 return "3button_press";
705         case GDK_BUTTON_RELEASE:
706                 return "button_release";
707         case GDK_KEY_PRESS:
708                 return "key_press";
709         case GDK_KEY_RELEASE:
710                 return "key_release";
711         case GDK_ENTER_NOTIFY:
712                 return "enter_notify";
713         case GDK_LEAVE_NOTIFY:
714                 return "leave_notify";
715         case GDK_FOCUS_CHANGE:
716                 return "focus_change";
717         case GDK_CONFIGURE:
718                 return "configure";
719         case GDK_MAP:
720                 return "map";
721         case GDK_UNMAP:
722                 return "unmap";
723         case GDK_PROPERTY_NOTIFY:
724                 return "property_notify";
725         case GDK_SELECTION_CLEAR:
726                 return "selection_clear";
727         case GDK_SELECTION_REQUEST:
728                 return "selection_request";
729         case GDK_SELECTION_NOTIFY:
730                 return "selection_notify";
731         case GDK_PROXIMITY_IN:
732                 return "proximity_in";
733         case GDK_PROXIMITY_OUT:
734                 return "proximity_out";
735         case GDK_DRAG_ENTER:
736                 return "drag_enter";
737         case GDK_DRAG_LEAVE:
738                 return "drag_leave";
739         case GDK_DRAG_MOTION:
740                 return "drag_motion";
741         case GDK_DRAG_STATUS:
742                 return "drag_status";
743         case GDK_DROP_START:
744                 return "drop_start";
745         case GDK_DROP_FINISHED:
746                 return "drop_finished";
747         case GDK_CLIENT_EVENT:
748                 return "client_event";
749         case GDK_VISIBILITY_NOTIFY:
750                 return "visibility_notify";
751         case GDK_NO_EXPOSE:
752                 return "no_expose";
753         case GDK_SCROLL:
754                 return "scroll";
755         case GDK_WINDOW_STATE:
756                 return "window_state";
757         case GDK_SETTING:
758                 return "setting";
759         case GDK_OWNER_CHANGE:
760                 return "owner_change";
761         case GDK_GRAB_BROKEN:
762                 return "grab_broken";
763         case GDK_DAMAGE:
764                 return "damage";
765         }
766
767         return "unknown";
768 }