2 Copyright (C) 1999 Paul Barton-Davis
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.
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.
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.
24 #include <gtk/gtkpaned.h>
27 #include <gtkmm/widget.h>
28 #include <gtkmm/button.h>
29 #include <gtkmm/window.h>
30 #include <gtkmm/paned.h>
31 #include <gtkmm/label.h>
32 #include <gtkmm/comboboxtext.h>
33 #include <gtkmm/tooltip.h>
35 #include "gtkmm2ext/utils.h"
42 Gtkmm2ext::init (const char* localedir)
45 (void) bindtextdomain(PACKAGE, localedir);
46 (void) bind_textdomain_codeset (PACKAGE, "UTF-8");
51 Gtkmm2ext::get_ink_pixel_size (Glib::RefPtr<Pango::Layout> layout,
55 Pango::Rectangle ink_rect = layout->get_ink_extents ();
57 width = (ink_rect.get_width() + PANGO_SCALE / 2) / PANGO_SCALE;
58 height = (ink_rect.get_height() + PANGO_SCALE / 2) / PANGO_SCALE;
62 Gtkmm2ext::get_pixel_size (Glib::RefPtr<Pango::Layout> layout,
66 layout->get_pixel_size (width, height);
70 Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget &w, const gchar *text,
71 gint hpadding, gint vpadding)
76 get_pixel_size (w.create_pango_layout (text), width, height);
77 w.set_size_request(width + hpadding, height + vpadding);
80 /** Set width request to display given text, and height to display anything.
81 This is useful for setting many widgets to the same height for consistency. */
83 Gtkmm2ext::set_size_request_to_display_given_text_width (Gtk::Widget& w,
88 static const gchar* vtext = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
93 get_pixel_size (w.create_pango_layout (htext), hwidth, hheight);
96 get_pixel_size (w.create_pango_layout (vtext), vwidth, vheight);
98 w.set_size_request(hwidth + hpadding, vheight + vpadding);
102 Gtkmm2ext::set_height_request_to_display_any_text (Gtk::Widget& w, gint vpadding)
104 static const gchar* vtext = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
109 get_pixel_size (w.create_pango_layout (vtext), width, height);
111 w.set_size_request(-1, height + vpadding);
115 Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget &w, std::string const & text,
116 gint hpadding, gint vpadding)
121 get_pixel_size (w.create_pango_layout (text), width, height);
122 w.set_size_request(width + hpadding, height + vpadding);
126 Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget &w,
127 const std::vector<std::string>& strings,
128 gint hpadding, gint vpadding)
135 const vector<string>* to_use;
136 vector<string>::const_iterator i;
138 for (i = strings.begin(); i != strings.end(); ++i) {
139 if ((*i).find_first_of ("gy") != string::npos) {
140 /* contains a descender */
145 if (i == strings.end()) {
146 /* make a copy of the strings then add one that has a descender */
148 copy.push_back ("g");
154 for (vector<string>::const_iterator i = to_use->begin(); i != to_use->end(); ++i) {
155 get_pixel_size (w.create_pango_layout (*i), width, height);
156 width_max = max(width_max,width);
157 height_max = max(height_max, height);
160 w.set_size_request(width_max + hpadding, height_max + vpadding);
163 /** This version specifies horizontal padding in text to avoid assumptions
164 about font size. Should be used anywhere padding is used to avoid text,
167 Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget& w,
168 const std::vector<std::string>& strings,
169 const std::string& hpadding,
176 for (vector<string>::const_iterator i = strings.begin(); i != strings.end(); ++i) {
178 get_pixel_size (w.create_pango_layout (*i), width, height);
179 width_max = max(width_max,width);
180 height_max = max(height_max, height);
185 get_pixel_size (w.create_pango_layout (hpadding), pad_width, pad_height);
187 w.set_size_request(width_max + pad_width, height_max + vpadding);
191 demultiply_alpha (guint8 src,
194 /* cairo pixel buffer data contains RGB values with the alpha
195 values premultiplied.
197 GdkPixbuf pixel buffer data contains RGB values without the
200 this removes the alpha component from the cairo version and
201 returns the GdkPixbuf version.
203 return alpha ? ((guint (src) << 8) - src) / alpha : 0;
207 Gtkmm2ext::convert_bgra_to_rgba (guint8 const* src,
212 guint8 const* src_pixel = src;
213 guint8* dst_pixel = dst;
215 /* cairo pixel data is endian-dependent ARGB with A in the most significant 8 bits,
216 with premultipled alpha values (see preceding function)
218 GdkPixbuf pixel data is non-endian-dependent RGBA with R in the lowest addressable
219 8 bits, and non-premultiplied alpha values.
221 convert from the cairo values to the GdkPixbuf ones.
224 for (int y = 0; y < height; y++) {
225 for (int x = 0; x < width; x++) {
226 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
227 /* Cairo [ B G R A ] is actually [ B G R A ] in memory SOURCE
229 Pixbuf [ R G B A ] is actually [ R G B A ] in memory DEST
231 dst_pixel[0] = demultiply_alpha (src_pixel[2],
232 src_pixel[3]); // R [0] <= [ 2 ]
233 dst_pixel[1] = demultiply_alpha (src_pixel[1],
234 src_pixel[3]); // G [1] <= [ 1 ]
235 dst_pixel[2] = demultiply_alpha (src_pixel[0],
236 src_pixel[3]); // B [2] <= [ 0 ]
237 dst_pixel[3] = src_pixel[3]; // alpha
239 #elif G_BYTE_ORDER == G_BIG_ENDIAN
240 /* Cairo [ B G R A ] is actually [ A R G B ] in memory SOURCE
242 Pixbuf [ R G B A ] is actually [ R G B A ] in memory DEST
244 dst_pixel[0] = demultiply_alpha (src_pixel[1],
245 src_pixel[0]); // R [0] <= [ 1 ]
246 dst_pixel[1] = demultiply_alpha (src_pixel[2],
247 src_pixel[0]); // G [1] <= [ 2 ]
248 dst_pixel[2] = demultiply_alpha (src_pixel[3],
249 src_pixel[0]); // B [2] <= [ 3 ]
250 dst_pixel[3] = src_pixel[0]; // alpha
253 #error ardour does not currently support PDP-endianess
262 Glib::RefPtr<Gdk::Pixbuf>
263 Gtkmm2ext::pixbuf_from_string(const string& name, const Pango::FontDescription& font, int clip_width, int clip_height, Gdk::Color fg)
265 static Glib::RefPtr<Gdk::Pixbuf>* empty_pixbuf = 0;
268 if (empty_pixbuf == 0) {
269 empty_pixbuf = new Glib::RefPtr<Gdk::Pixbuf>;
270 *empty_pixbuf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
272 return *empty_pixbuf;
275 Glib::RefPtr<Gdk::Pixbuf> buf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
277 cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, clip_width, clip_height);
278 cairo_t* cr = cairo_create (surface);
279 cairo_text_extents_t te;
281 cairo_set_source_rgba (cr, fg.get_red_p(), fg.get_green_p(), fg.get_blue_p(), 1.0);
282 cairo_select_font_face (cr, font.get_family().c_str(),
283 CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
284 cairo_set_font_size (cr, font.get_size() / Pango::SCALE);
285 cairo_text_extents (cr, name.c_str(), &te);
287 cairo_move_to (cr, 0.5, int (0.5 - te.height / 2 - te.y_bearing + clip_height / 2));
288 cairo_show_text (cr, name.c_str());
290 convert_bgra_to_rgba(cairo_image_surface_get_data (surface), buf->get_pixels(), clip_width, clip_height);
293 cairo_surface_destroy(surface);
299 Gtkmm2ext::set_popdown_strings (Gtk::ComboBoxText& cr, const vector<string>& strings)
301 vector<string>::const_iterator i;
305 for (i = strings.begin(); i != strings.end(); ++i) {
311 Gtkmm2ext::get_popdown_strings (Gtk::ComboBoxText& cr, std::vector<std::string>& strings)
314 Glib::RefPtr<const Gtk::TreeModel> m = cr.get_model();
318 for(Gtk::TreeModel::iterator i = m->children().begin(); i != m->children().end(); ++i) {
320 (*i)->get_value(0, txt);
321 strings.push_back (txt);
326 Gtkmm2ext::contains_value (Gtk::ComboBoxText& cr, const std::string text)
328 std::vector<std::string> s;
329 get_popdown_strings (cr, s);
330 return (std::find (s.begin(), s.end(), text) != s.end());
334 Gtkmm2ext::set_active_text_if_present (Gtk::ComboBoxText& cr, const std::string text)
336 if (contains_value(cr, text)) {
337 cr.set_active_text (text);
344 Gtkmm2ext::get_paned_handle (Gtk::Paned& paned)
346 return GTK_PANED(paned.gobj())->handle;
350 Gtkmm2ext::set_decoration (Gtk::Window* win, Gdk::WMDecoration decor)
352 win->get_window()->set_decorations (decor);
355 void Gtkmm2ext::set_treeview_header_as_default_label(Gtk::TreeViewColumn* c)
357 gtk_tree_view_column_set_widget( c->gobj(), GTK_WIDGET(0) );
361 Gtkmm2ext::detach_menu (Gtk::Menu& menu)
363 /* its possible for a Gtk::Menu to have no gobj() because it has
364 not yet been instantiated. Catch this and provide a safe
368 if (menu.get_attach_widget()) {
375 Gtkmm2ext::possibly_translate_mod_to_make_legal_accelerator (GdkModifierType& mod)
378 /* GTK on OS X is currently (February 2012) setting both
379 the Meta and Mod2 bits in the event modifier state if
380 the Command key is down.
382 gtk_accel_groups_activate() does not invoke any of the logic
383 that gtk_window_activate_key() will that sorts out that stupid
384 state of affairs, and as a result it fails to find a match
385 for the key event and the current set of accelerators.
387 to fix this, if the meta bit is set, remove the mod2 bit
388 from the modifier. this assumes that our bindings use Primary
389 which will have set the meta bit in the accelerator entry.
391 if (mod & GDK_META_MASK) {
392 mod = GdkModifierType (mod & ~GDK_MOD2_MASK);
399 Gtkmm2ext::possibly_translate_keyval_to_make_legal_accelerator (uint32_t& keyval)
401 int fakekey = GDK_VoidSymbol;
405 case GDK_ISO_Left_Tab:
410 fakekey = GDK_uparrow;
414 fakekey = GDK_downarrow;
418 fakekey = GDK_rightarrow;
422 fakekey = GDK_leftarrow;
426 fakekey = GDK_3270_Enter;
437 if (fakekey != GDK_VoidSymbol) {
446 Gtkmm2ext::possibly_translate_legal_accelerator_to_real_key (uint32_t keyval)
481 Gtkmm2ext::physical_screen_height (Glib::RefPtr<Gdk::Window> win)
483 GdkScreen* scr = gdk_screen_get_default();
487 gint monitor = gdk_screen_get_monitor_at_window (scr, win->gobj());
488 gdk_screen_get_monitor_geometry (scr, monitor, &r);
491 return gdk_screen_get_height (scr);
496 Gtkmm2ext::physical_screen_width (Glib::RefPtr<Gdk::Window> win)
498 GdkScreen* scr = gdk_screen_get_default();
502 gint monitor = gdk_screen_get_monitor_at_window (scr, win->gobj());
503 gdk_screen_get_monitor_geometry (scr, monitor, &r);
506 return gdk_screen_get_width (scr);
511 Gtkmm2ext::container_clear (Gtk::Container& c)
513 list<Gtk::Widget*> children = c.get_children();
514 for (list<Gtk::Widget*>::iterator child = children.begin(); child != children.end(); ++child) {
520 Gtkmm2ext::rounded_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
522 rounded_rectangle (context->cobj(), x, y, w, h, r);
525 Gtkmm2ext::rounded_top_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
527 rounded_top_rectangle (context->cobj(), x, y, w, h, r);
530 Gtkmm2ext::rounded_top_left_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
532 rounded_top_left_rectangle (context->cobj(), x, y, w, h, r);
535 Gtkmm2ext::rounded_top_right_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
537 rounded_top_right_rectangle (context->cobj(), x, y, w, h, r);
540 Gtkmm2ext::rounded_top_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
542 rounded_top_half_rectangle (context->cobj(), x, y, w, h, r);
545 Gtkmm2ext::rounded_bottom_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
547 rounded_bottom_half_rectangle (context->cobj(), x, y, w, h, r);
551 Gtkmm2ext::rounded_left_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
553 rounded_left_half_rectangle (context->cobj(), x, y, w, h, r);
557 Gtkmm2ext::rounded_right_half_rectangle (Cairo::RefPtr<Cairo::Context> context, double x, double y, double w, double h, double r)
559 rounded_right_half_rectangle (context->cobj(), x, y, w, h, r);
563 Gtkmm2ext::rounded_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
565 double degrees = M_PI / 180.0;
567 cairo_new_sub_path (cr);
568 cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees); //tr
569 cairo_arc (cr, x + w - r, y + h - r, r, 0 * degrees, 90 * degrees); //br
570 cairo_arc (cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees); //bl
571 cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees); //tl
572 cairo_close_path (cr);
576 Gtkmm2ext::rounded_left_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
578 double degrees = M_PI / 180.0;
580 cairo_new_sub_path (cr);
581 cairo_line_to (cr, x+w, y); // tr
582 cairo_line_to (cr, x+w, y + h); // br
583 cairo_arc (cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees); //bl
584 cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees); //tl
585 cairo_close_path (cr);
589 Gtkmm2ext::rounded_right_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
591 double degrees = M_PI / 180.0;
593 cairo_new_sub_path (cr);
594 cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees); //tr
595 cairo_arc (cr, x + w - r, y + h - r, r, 0 * degrees, 90 * degrees); //br
596 cairo_line_to (cr, x, y + h); // bl
597 cairo_line_to (cr, x, y); // tl
598 cairo_close_path (cr);
602 Gtkmm2ext::rounded_top_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
604 double degrees = M_PI / 180.0;
606 cairo_new_sub_path (cr);
607 cairo_move_to (cr, x+w, y+h);
608 cairo_line_to (cr, x, y+h);
609 cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees); //tl
610 cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees); //tr
611 cairo_close_path (cr);
615 Gtkmm2ext::rounded_bottom_half_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
617 double degrees = M_PI / 180.0;
619 cairo_new_sub_path (cr);
620 cairo_move_to (cr, x, y);
621 cairo_line_to (cr, x+w, y);
622 cairo_arc (cr, x + w - r, y + h - r, r, 0 * degrees, 90 * degrees); //br
623 cairo_arc (cr, x + r, y + h - r, r, 90 * degrees, 180 * degrees); //bl
624 cairo_close_path (cr);
629 Gtkmm2ext::rounded_top_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
631 double degrees = M_PI / 180.0;
633 cairo_new_sub_path (cr);
634 cairo_move_to (cr, x+w, y+h);
635 cairo_line_to (cr, x, y+h);
636 cairo_arc (cr, x + r, y + r, r, 180 * degrees, 270 * degrees); //tl
637 cairo_arc (cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees); //tr
638 cairo_close_path (cr);
642 Gtkmm2ext::rounded_top_left_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
650 cairo_move_to (cr, x+r,y); // Move to A
651 cairo_line_to (cr, x+w,y); // Straight line to B
652 cairo_line_to (cr, x+w,y+h); // Move to E
653 cairo_line_to (cr, x,y+h); // Line to F
654 cairo_line_to (cr, x,y+r); // Line to H
655 cairo_curve_to (cr, x,y,x,y,x+r,y); // Curve to A
659 Gtkmm2ext::rounded_top_right_rectangle (cairo_t* cr, double x, double y, double w, double h, double r)
667 cairo_move_to (cr, x,y); // Move to A
668 cairo_line_to (cr, x+w-r,y); // Straight line to B
669 cairo_curve_to (cr, x+w,y,x+w,y,x+w,y+r); // Curve to C, Control points are both at Q
670 cairo_line_to (cr, x+w,y+h); // Move to E
671 cairo_line_to (cr, x,y+h); // Line to F
672 cairo_line_to (cr, x,y); // Line to A
675 Glib::RefPtr<Gdk::Window>
676 Gtkmm2ext::window_to_draw_on (Gtk::Widget& w, Gtk::Widget** parent)
678 if (w.get_has_window()) {
679 return w.get_window();
682 (*parent) = w.get_parent();
685 if ((*parent)->get_has_window()) {
686 return (*parent)->get_window ();
688 (*parent) = (*parent)->get_parent ();
691 return Glib::RefPtr<Gdk::Window> ();
695 Gtkmm2ext::pixel_width (const string& str, Pango::FontDescription& font)
698 Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
700 layout->set_font_description (font);
701 layout->set_text (str);
704 Gtkmm2ext::get_ink_pixel_size (layout, width, height);
709 Gtkmm2ext::pixel_size (const string& str, Pango::FontDescription& font, int& width, int& height)
712 Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout ("");
714 layout->set_font_description (font);
715 layout->set_text (str);
717 Gtkmm2ext::get_ink_pixel_size (layout, width, height);
722 Gtkmm2ext::fit_to_pixels (const string& str, int pixel_width, Pango::FontDescription& font, int& actual_width, bool with_ellipses)
724 /* DECEMBER 2011: THIS PROTOTYPE OF fit_to_pixels() IS NOT USED
725 ANYWHERE AND HAS NOT BEEN TESTED.
728 Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout (str);
729 Glib::RefPtr<const Pango::LayoutLine> line;
731 layout->set_font_description (font);
732 layout->set_width (pixel_width * PANGO_SCALE);
735 layout->set_ellipsize (Pango::ELLIPSIZE_END);
737 layout->set_wrap (Pango::WRAP_CHAR);
740 line = layout->get_line (0);
742 /* XXX: might need special care to get the ellipsis character, not sure
746 string s = string (layout->get_text ().substr(line->get_start_index(), line->get_length()));
748 cerr << "fit to pixels of " << str << " returns " << s << endl;
754 /** Try to fit a string into a given horizontal space by ellipsizing it.
755 * @param cr Cairo context in which the text will be plotted.
757 * @param avail Available horizontal space.
758 * @return (Text, possibly ellipsized) and (horizontal size of text)
761 std::pair<std::string, double>
762 Gtkmm2ext::fit_to_pixels (cairo_t* cr, std::string name, double avail)
764 /* XXX hopefully there exists a more efficient way of doing this */
766 bool abbreviated = false;
770 cairo_text_extents_t ext;
771 cairo_text_extents (cr, name.c_str(), &ext);
773 if (ext.width < avail || name.length() <= 4) {
779 name = name.substr (0, name.length() - 4) + "...";
781 name = name.substr (0, name.length() - 3) + "...";
786 return std::make_pair (name, width);
790 Gtkmm2ext::left_aligned_label (string const & t)
792 Gtk::Label* l = new Gtk::Label (t);
793 l->set_alignment (0, 0.5);
798 make_null_tooltip (int, int, bool, const Glib::RefPtr<Gtk::Tooltip>& t)
800 t->set_tip_area (Gdk::Rectangle (0, 0, 0, 0));
804 /** Hackily arrange for the provided widget to have no tooltip,
805 * and also to stop any other widget from providing one while
806 * the mouse is over w.
809 Gtkmm2ext::set_no_tooltip_whatsoever (Gtk::Widget& w)
811 w.property_has_tooltip() = true;
812 w.signal_query_tooltip().connect (sigc::ptr_fun (make_null_tooltip));
816 Gtkmm2ext::enable_tooltips ()
818 gtk_rc_parse_string ("gtk-enable-tooltips = 1");
822 Gtkmm2ext::disable_tooltips ()
824 gtk_rc_parse_string ("gtk-enable-tooltips = 0");
828 Gtkmm2ext::event_inside_widget_window (Gtk::Widget& widget, GdkEvent* ev)
832 if (!gdk_event_get_root_coords (ev, &evx, &evy)) {
838 gint width, height, depth;
841 Glib::RefPtr<Gdk::Window> widget_window = widget.get_window();
843 widget_window->get_geometry (x, y, width, height, depth);
844 widget_window->get_root_origin (wx, wy);
846 if ((evx >= wx && evx < wx + width) &&
847 (evy >= wy && evy < wy + height)) {
855 Gtkmm2ext::event_type_string (int event_type)
857 switch (event_type) {
866 case GDK_MOTION_NOTIFY:
867 return "motion_notify";
868 case GDK_BUTTON_PRESS:
869 return "button_press";
870 case GDK_2BUTTON_PRESS:
871 return "2button_press";
872 case GDK_3BUTTON_PRESS:
873 return "3button_press";
874 case GDK_BUTTON_RELEASE:
875 return "button_release";
878 case GDK_KEY_RELEASE:
879 return "key_release";
880 case GDK_ENTER_NOTIFY:
881 return "enter_notify";
882 case GDK_LEAVE_NOTIFY:
883 return "leave_notify";
884 case GDK_FOCUS_CHANGE:
885 return "focus_change";
892 case GDK_PROPERTY_NOTIFY:
893 return "property_notify";
894 case GDK_SELECTION_CLEAR:
895 return "selection_clear";
896 case GDK_SELECTION_REQUEST:
897 return "selection_request";
898 case GDK_SELECTION_NOTIFY:
899 return "selection_notify";
900 case GDK_PROXIMITY_IN:
901 return "proximity_in";
902 case GDK_PROXIMITY_OUT:
903 return "proximity_out";
908 case GDK_DRAG_MOTION:
909 return "drag_motion";
910 case GDK_DRAG_STATUS:
911 return "drag_status";
914 case GDK_DROP_FINISHED:
915 return "drop_finished";
916 case GDK_CLIENT_EVENT:
917 return "client_event";
918 case GDK_VISIBILITY_NOTIFY:
919 return "visibility_notify";
924 case GDK_WINDOW_STATE:
925 return "window_state";
928 case GDK_OWNER_CHANGE:
929 return "owner_change";
930 case GDK_GRAB_BROKEN:
931 return "grab_broken";