comparison src/gui_beval.c @ 8218:3456e2ebebd4 v7.4.1402

commit https://github.com/vim/vim/commit/9892189d2e7ab94b750f99e6da4cbfc3c8014517 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Feb 23 17:14:37 2016 +0100 patch 7.4.1402 Problem: GTK 3 is not supported. Solution: Add GTK 3 support. (Kazunobu Kuriyama)
author Christian Brabandt <cb@256bit.org>
date Tue, 23 Feb 2016 17:15:05 +0100
parents 81794242a275
children fc69eed19ba7
comparison
equal deleted inserted replaced
8217:c52abf35df88 8218:3456e2ebebd4
120 120
121 /* on Win32 only get_beval_info() is required */ 121 /* on Win32 only get_beval_info() is required */
122 #if !defined(FEAT_GUI_W32) || defined(PROTO) 122 #if !defined(FEAT_GUI_W32) || defined(PROTO)
123 123
124 #ifdef FEAT_GUI_GTK 124 #ifdef FEAT_GUI_GTK
125 # include <gdk/gdkkeysyms.h> 125 # if GTK_CHECK_VERSION(3,0,0)
126 # include <gdk/gdkkeysyms-compat.h>
127 # else
128 # include <gdk/gdkkeysyms.h>
129 # endif
126 # include <gtk/gtk.h> 130 # include <gtk/gtk.h>
127 #else 131 #else
128 # include <X11/keysym.h> 132 # include <X11/keysym.h>
129 # ifdef FEAT_GUI_MOTIF 133 # ifdef FEAT_GUI_MOTIF
130 # include <Xm/PushB.h> 134 # include <Xm/PushB.h>
162 static void removeEventHandler(BalloonEval *); 166 static void removeEventHandler(BalloonEval *);
163 static gint target_event_cb(GtkWidget *, GdkEvent *, gpointer); 167 static gint target_event_cb(GtkWidget *, GdkEvent *, gpointer);
164 static gint mainwin_event_cb(GtkWidget *, GdkEvent *, gpointer); 168 static gint mainwin_event_cb(GtkWidget *, GdkEvent *, gpointer);
165 static void pointer_event(BalloonEval *, int, int, unsigned); 169 static void pointer_event(BalloonEval *, int, int, unsigned);
166 static void key_event(BalloonEval *, unsigned, int); 170 static void key_event(BalloonEval *, unsigned, int);
171 # if GTK_CHECK_VERSION(3,0,0)
172 static gboolean timeout_cb(gpointer);
173 # else
167 static gint timeout_cb(gpointer); 174 static gint timeout_cb(gpointer);
168 static gint balloon_expose_event_cb(GtkWidget *, GdkEventExpose *, gpointer); 175 # endif
176 # if GTK_CHECK_VERSION(3,0,0)
177 static gboolean balloon_draw_event_cb (GtkWidget *, cairo_t *, gpointer);
178 # else
179 static gint balloon_expose_event_cb (GtkWidget *, GdkEventExpose *, gpointer);
180 # endif
169 #else 181 #else
170 static void addEventHandler(Widget, BalloonEval *); 182 static void addEventHandler(Widget, BalloonEval *);
171 static void removeEventHandler(BalloonEval *); 183 static void removeEventHandler(BalloonEval *);
172 static void pointerEventEH(Widget, XtPointer, XEvent *, Boolean *); 184 static void pointerEventEH(Widget, XtPointer, XEvent *, Boolean *);
173 static void pointerEvent(BalloonEval *, XEvent *); 185 static void pointerEvent(BalloonEval *, XEvent *);
457 * Connect to the generic "event" signal instead of the individual 469 * Connect to the generic "event" signal instead of the individual
458 * signals for each event type, because the former is emitted earlier. 470 * signals for each event type, because the former is emitted earlier.
459 * This allows us to catch events independently of the signal handlers 471 * This allows us to catch events independently of the signal handlers
460 * in gui_gtk_x11.c. 472 * in gui_gtk_x11.c.
461 */ 473 */
474 # if GTK_CHECK_VERSION(3,0,0)
475 g_signal_connect(G_OBJECT(target), "event",
476 G_CALLBACK(target_event_cb),
477 beval);
478 # else
462 /* Should use GTK_OBJECT() here, but that causes a lint warning... */ 479 /* Should use GTK_OBJECT() here, but that causes a lint warning... */
463 gtk_signal_connect((GtkObject*)(target), "event", 480 gtk_signal_connect((GtkObject*)(target), "event",
464 GTK_SIGNAL_FUNC(target_event_cb), 481 GTK_SIGNAL_FUNC(target_event_cb),
465 beval); 482 beval);
483 # endif
466 /* 484 /*
467 * Nasty: Key press events go to the main window thus the drawing area 485 * Nasty: Key press events go to the main window thus the drawing area
468 * will never see them. This means we have to connect to the main window 486 * will never see them. This means we have to connect to the main window
469 * as well in order to catch those events. 487 * as well in order to catch those events.
470 */ 488 */
471 if (gtk_socket_id == 0 && gui.mainwin != NULL 489 if (gtk_socket_id == 0 && gui.mainwin != NULL
472 && gtk_widget_is_ancestor(target, gui.mainwin)) 490 && gtk_widget_is_ancestor(target, gui.mainwin))
473 { 491 {
492 # if GTK_CHECK_VERSION(3,0,0)
493 g_signal_connect(G_OBJECT(gui.mainwin), "event",
494 G_CALLBACK(mainwin_event_cb),
495 beval);
496 # else
474 gtk_signal_connect((GtkObject*)(gui.mainwin), "event", 497 gtk_signal_connect((GtkObject*)(gui.mainwin), "event",
475 GTK_SIGNAL_FUNC(mainwin_event_cb), 498 GTK_SIGNAL_FUNC(mainwin_event_cb),
476 beval); 499 beval);
500 # endif
477 } 501 }
478 } 502 }
479 503
480 static void 504 static void
481 removeEventHandler(BalloonEval *beval) 505 removeEventHandler(BalloonEval *beval)
482 { 506 {
483 /* LINTED: avoid warning: dubious operation on enum */ 507 /* LINTED: avoid warning: dubious operation on enum */
508 # if GTK_CHECK_VERSION(3,0,0)
509 g_signal_handlers_disconnect_by_func(G_OBJECT(beval->target),
510 G_CALLBACK(target_event_cb),
511 beval);
512 # else
484 gtk_signal_disconnect_by_func((GtkObject*)(beval->target), 513 gtk_signal_disconnect_by_func((GtkObject*)(beval->target),
485 GTK_SIGNAL_FUNC(target_event_cb), 514 GTK_SIGNAL_FUNC(target_event_cb),
486 beval); 515 beval);
516 # endif
487 517
488 if (gtk_socket_id == 0 && gui.mainwin != NULL 518 if (gtk_socket_id == 0 && gui.mainwin != NULL
489 && gtk_widget_is_ancestor(beval->target, gui.mainwin)) 519 && gtk_widget_is_ancestor(beval->target, gui.mainwin))
490 { 520 {
491 /* LINTED: avoid warning: dubious operation on enum */ 521 /* LINTED: avoid warning: dubious operation on enum */
522 # if GTK_CHECK_VERSION(3,0,0)
523 g_signal_handlers_disconnect_by_func(G_OBJECT(gui.mainwin),
524 G_CALLBACK(mainwin_event_cb),
525 beval);
526 # else
492 gtk_signal_disconnect_by_func((GtkObject*)(gui.mainwin), 527 gtk_signal_disconnect_by_func((GtkObject*)(gui.mainwin),
493 GTK_SIGNAL_FUNC(mainwin_event_cb), 528 GTK_SIGNAL_FUNC(mainwin_event_cb),
494 beval); 529 beval);
530 # endif
495 } 531 }
496 } 532 }
497 533
498 static gint 534 static gint
499 target_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data) 535 target_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
515 GdkModifierType state; 551 GdkModifierType state;
516 /* 552 /*
517 * GDK_POINTER_MOTION_HINT_MASK is set, thus we cannot obtain 553 * GDK_POINTER_MOTION_HINT_MASK is set, thus we cannot obtain
518 * the coordinates from the GdkEventMotion struct directly. 554 * the coordinates from the GdkEventMotion struct directly.
519 */ 555 */
556 # if GTK_CHECK_VERSION(3,0,0)
557 {
558 GdkWindow * const win = gtk_widget_get_window(widget);
559 GdkDisplay * const dpy = gdk_window_get_display(win);
560 GdkDeviceManager * const mngr = gdk_display_get_device_manager(dpy);
561 GdkDevice * const dev = gdk_device_manager_get_client_pointer(mngr);
562 gdk_window_get_device_position(win, dev , &x, &y, &state);
563 }
564 # else
520 gdk_window_get_pointer(widget->window, &x, &y, &state); 565 gdk_window_get_pointer(widget->window, &x, &y, &state);
566 # endif
521 pointer_event(beval, x, y, (unsigned int)state); 567 pointer_event(beval, x, y, (unsigned int)state);
522 } 568 }
523 else 569 else
524 { 570 {
525 pointer_event(beval, (int)event->motion.x, 571 pointer_event(beval, (int)event->motion.x,
607 (*beval->msgCB)(beval, state); 653 (*beval->msgCB)(beval, state);
608 } 654 }
609 } 655 }
610 else 656 else
611 { 657 {
658 # if GTK_CHECK_VERSION(3,0,0)
659 beval->timerID = g_timeout_add((guint)p_bdlay,
660 &timeout_cb, beval);
661 # else
612 beval->timerID = gtk_timeout_add((guint32)p_bdlay, 662 beval->timerID = gtk_timeout_add((guint32)p_bdlay,
613 &timeout_cb, beval); 663 &timeout_cb, beval);
664 # endif
614 } 665 }
615 } 666 }
616 } 667 }
617 } 668 }
618 669
645 } 696 }
646 else 697 else
647 cancelBalloon(beval); 698 cancelBalloon(beval);
648 } 699 }
649 700
701 # if GTK_CHECK_VERSION(3,0,0)
702 static gboolean
703 # else
650 static gint 704 static gint
705 # endif
651 timeout_cb(gpointer data) 706 timeout_cb(gpointer data)
652 { 707 {
653 BalloonEval *beval = (BalloonEval *)data; 708 BalloonEval *beval = (BalloonEval *)data;
654 709
655 beval->timerID = 0; 710 beval->timerID = 0;
661 requestBalloon(beval); 716 requestBalloon(beval);
662 717
663 return FALSE; /* don't call me again */ 718 return FALSE; /* don't call me again */
664 } 719 }
665 720
721 # if GTK_CHECK_VERSION(3,0,0)
722 static gboolean
723 balloon_draw_event_cb(GtkWidget *widget,
724 cairo_t *cr,
725 gpointer data UNUSED)
726 {
727 GtkStyleContext *context = NULL;
728 gint width = -1, height = -1;
729
730 if (widget == NULL)
731 return TRUE;
732
733 context = gtk_widget_get_style_context(widget);
734 width = gtk_widget_get_allocated_width(widget);
735 height = gtk_widget_get_allocated_height(widget);
736
737 gtk_style_context_save(context);
738
739 gtk_style_context_add_class(context, "tooltip");
740 gtk_style_context_set_state(context, GTK_STATE_FLAG_NORMAL);
741
742 cairo_save(cr);
743 gtk_render_frame(context, cr, 0, 0, width, height);
744 gtk_render_background(context, cr, 0, 0, width, height);
745 cairo_restore(cr);
746
747 gtk_style_context_restore(context);
748
749 return FALSE;
750 }
751 # else
666 static gint 752 static gint
667 balloon_expose_event_cb(GtkWidget *widget, 753 balloon_expose_event_cb(GtkWidget *widget,
668 GdkEventExpose *event, 754 GdkEventExpose *event,
669 gpointer data UNUSED) 755 gpointer data UNUSED)
670 { 756 {
673 &event->area, widget, "tooltip", 759 &event->area, widget, "tooltip",
674 0, 0, -1, -1); 760 0, 0, -1, -1);
675 761
676 return FALSE; /* continue emission */ 762 return FALSE; /* continue emission */
677 } 763 }
764 # endif /* !GTK_CHECK_VERSION(3,0,0) */
678 765
679 #else /* !FEAT_GUI_GTK */ 766 #else /* !FEAT_GUI_GTK */
680 767
681 static void 768 static void
682 addEventHandler(Widget target, BalloonEval *beval) 769 addEventHandler(Widget target, BalloonEval *beval)
955 1042
956 /* Look up the RGB values of the SpecialKey foreground color. */ 1043 /* Look up the RGB values of the SpecialKey foreground color. */
957 aep = syn_gui_attr2entry(hl_attr(HLF_8)); 1044 aep = syn_gui_attr2entry(hl_attr(HLF_8));
958 pixel = (aep != NULL) ? aep->ae_u.gui.fg_color : INVALCOLOR; 1045 pixel = (aep != NULL) ? aep->ae_u.gui.fg_color : INVALCOLOR;
959 if (pixel != INVALCOLOR) 1046 if (pixel != INVALCOLOR)
1047 # if GTK_CHECK_VERSION(3,0,0)
1048 {
1049 GdkVisual * const visual = gtk_widget_get_visual(gui.drawarea);
1050
1051 if (visual == NULL)
1052 {
1053 color.red = 0;
1054 color.green = 0;
1055 color.blue = 0;
1056 }
1057 else
1058 {
1059 guint32 r_mask, g_mask, b_mask;
1060 gint r_shift, g_shift, b_shift;
1061
1062 gdk_visual_get_red_pixel_details(visual, &r_mask, &r_shift,
1063 NULL);
1064 gdk_visual_get_green_pixel_details(visual, &g_mask, &g_shift,
1065 NULL);
1066 gdk_visual_get_blue_pixel_details(visual, &b_mask, &b_shift,
1067 NULL);
1068
1069 color.red = ((pixel & r_mask) >> r_shift) / 255.0 * 65535;
1070 color.green = ((pixel & g_mask) >> g_shift) / 255.0 * 65535;
1071 color.blue = ((pixel & b_mask) >> b_shift) / 255.0 * 65535;
1072 }
1073 }
1074 # else
960 gdk_colormap_query_color(gtk_widget_get_colormap(gui.drawarea), 1075 gdk_colormap_query_color(gtk_widget_get_colormap(gui.drawarea),
961 (unsigned long)pixel, &color); 1076 (unsigned long)pixel, &color);
1077 # endif
962 1078
963 pdest = buf; 1079 pdest = buf;
964 p = text; 1080 p = text;
965 while (*p != NUL) 1081 while (*p != NUL)
966 { 1082 {
1057 screen_h = gdk_screen_get_height(screen); 1173 screen_h = gdk_screen_get_height(screen);
1058 # else 1174 # else
1059 screen_w = gdk_screen_width(); 1175 screen_w = gdk_screen_width();
1060 screen_h = gdk_screen_height(); 1176 screen_h = gdk_screen_height();
1061 # endif 1177 # endif
1178 # if !GTK_CHECK_VERSION(3,0,0)
1062 gtk_widget_ensure_style(beval->balloonShell); 1179 gtk_widget_ensure_style(beval->balloonShell);
1063 gtk_widget_ensure_style(beval->balloonLabel); 1180 gtk_widget_ensure_style(beval->balloonLabel);
1181 # endif
1064 1182
1065 set_printable_label_text(GTK_LABEL(beval->balloonLabel), beval->msg); 1183 set_printable_label_text(GTK_LABEL(beval->balloonLabel), beval->msg);
1066 /* 1184 /*
1067 * Dirty trick: Enable wrapping mode on the label's layout behind its 1185 * Dirty trick: Enable wrapping mode on the label's layout behind its
1068 * back. This way GtkLabel won't try to constrain the wrap width to a 1186 * back. This way GtkLabel won't try to constrain the wrap width to a
1079 PANGO_SCALE * CLAMP(gui.num_cols * gui.char_width, 1197 PANGO_SCALE * CLAMP(gui.num_cols * gui.char_width,
1080 screen_w / 2, 1198 screen_w / 2,
1081 MAX(20, screen_w - 20))); 1199 MAX(20, screen_w - 20)));
1082 1200
1083 /* Calculate the balloon's width and height. */ 1201 /* Calculate the balloon's width and height. */
1202 # if GTK_CHECK_VERSION(3,0,0)
1203 gtk_widget_get_preferred_size(beval->balloonShell, &requisition, NULL);
1204 # else
1084 gtk_widget_size_request(beval->balloonShell, &requisition); 1205 gtk_widget_size_request(beval->balloonShell, &requisition);
1206 # endif
1085 1207
1086 /* Compute position of the balloon area */ 1208 /* Compute position of the balloon area */
1209 # if GTK_CHECK_VERSION(3,0,0)
1210 gdk_window_get_origin(gtk_widget_get_window(beval->target), &x, &y);
1211 # else
1087 gdk_window_get_origin(beval->target->window, &x, &y); 1212 gdk_window_get_origin(beval->target->window, &x, &y);
1213 # endif
1088 x += beval->x; 1214 x += beval->x;
1089 y += beval->y; 1215 y += beval->y;
1090 1216
1091 /* Get out of the way of the mouse pointer */ 1217 /* Get out of the way of the mouse pointer */
1092 if (x + x_offset + requisition.width > screen_w) 1218 if (x + x_offset + requisition.width > screen_w)
1097 /* Sanitize values */ 1223 /* Sanitize values */
1098 x = CLAMP(x + x_offset, 0, MAX(0, screen_w - requisition.width)); 1224 x = CLAMP(x + x_offset, 0, MAX(0, screen_w - requisition.width));
1099 y = CLAMP(y + y_offset, 0, MAX(0, screen_h - requisition.height)); 1225 y = CLAMP(y + y_offset, 0, MAX(0, screen_h - requisition.height));
1100 1226
1101 /* Show the balloon */ 1227 /* Show the balloon */
1228 # if GTK_CHECK_VERSION(3,0,0)
1229 gtk_window_move(GTK_WINDOW(beval->balloonShell), x, y);
1230 # else
1102 gtk_widget_set_uposition(beval->balloonShell, x, y); 1231 gtk_widget_set_uposition(beval->balloonShell, x, y);
1232 # endif
1103 gtk_widget_show(beval->balloonShell); 1233 gtk_widget_show(beval->balloonShell);
1104 1234
1105 beval->showState = ShS_SHOWING; 1235 beval->showState = ShS_SHOWING;
1106 } 1236 }
1107 } 1237 }
1124 || beval->showState == ShS_UPDATE_PENDING) 1254 || beval->showState == ShS_UPDATE_PENDING)
1125 undrawBalloon(beval); 1255 undrawBalloon(beval);
1126 1256
1127 if (beval->timerID != 0) 1257 if (beval->timerID != 0)
1128 { 1258 {
1259 # if GTK_CHECK_VERSION(3,0,0)
1260 g_source_remove(beval->timerID);
1261 # else
1129 gtk_timeout_remove(beval->timerID); 1262 gtk_timeout_remove(beval->timerID);
1263 # endif
1130 beval->timerID = 0; 1264 beval->timerID = 0;
1131 } 1265 }
1132 beval->showState = ShS_NEUTRAL; 1266 beval->showState = ShS_NEUTRAL;
1133 } 1267 }
1134 1268
1136 createBalloonEvalWindow(BalloonEval *beval) 1270 createBalloonEvalWindow(BalloonEval *beval)
1137 { 1271 {
1138 beval->balloonShell = gtk_window_new(GTK_WINDOW_POPUP); 1272 beval->balloonShell = gtk_window_new(GTK_WINDOW_POPUP);
1139 1273
1140 gtk_widget_set_app_paintable(beval->balloonShell, TRUE); 1274 gtk_widget_set_app_paintable(beval->balloonShell, TRUE);
1275 # if GTK_CHECK_VERSION(3,0,0)
1276 gtk_window_set_resizable(GTK_WINDOW(beval->balloonShell), FALSE);
1277 # else
1141 gtk_window_set_policy(GTK_WINDOW(beval->balloonShell), FALSE, FALSE, TRUE); 1278 gtk_window_set_policy(GTK_WINDOW(beval->balloonShell), FALSE, FALSE, TRUE);
1279 # endif
1142 gtk_widget_set_name(beval->balloonShell, "gtk-tooltips"); 1280 gtk_widget_set_name(beval->balloonShell, "gtk-tooltips");
1281 # if GTK_CHECK_VERSION(3,0,0)
1282 gtk_container_set_border_width(GTK_CONTAINER(beval->balloonShell), 4);
1283 # else
1143 gtk_container_border_width(GTK_CONTAINER(beval->balloonShell), 4); 1284 gtk_container_border_width(GTK_CONTAINER(beval->balloonShell), 4);
1144 1285 # endif
1286
1287 # if GTK_CHECK_VERSION(3,0,0)
1288 g_signal_connect(G_OBJECT(beval->balloonShell), "draw",
1289 G_CALLBACK(balloon_draw_event_cb), NULL);
1290 # else
1145 gtk_signal_connect((GtkObject*)(beval->balloonShell), "expose_event", 1291 gtk_signal_connect((GtkObject*)(beval->balloonShell), "expose_event",
1146 GTK_SIGNAL_FUNC(balloon_expose_event_cb), NULL); 1292 GTK_SIGNAL_FUNC(balloon_expose_event_cb), NULL);
1293 # endif
1147 beval->balloonLabel = gtk_label_new(NULL); 1294 beval->balloonLabel = gtk_label_new(NULL);
1148 1295
1149 gtk_label_set_line_wrap(GTK_LABEL(beval->balloonLabel), FALSE); 1296 gtk_label_set_line_wrap(GTK_LABEL(beval->balloonLabel), FALSE);
1150 gtk_label_set_justify(GTK_LABEL(beval->balloonLabel), GTK_JUSTIFY_LEFT); 1297 gtk_label_set_justify(GTK_LABEL(beval->balloonLabel), GTK_JUSTIFY_LEFT);
1298 # if GTK_CHECK_VERSION(3,16,0)
1299 gtk_label_set_xalign(GTK_LABEL(beval->balloonLabel), 0.5);
1300 gtk_label_set_yalign(GTK_LABEL(beval->balloonLabel), 0.5);
1301 # elif GTK_CHECK_VERSION(3,14,0)
1302 GValue align_val = G_VALUE_INIT;
1303 g_value_init(&align_val, G_TYPE_FLOAT);
1304 g_value_set_float(&align_val, 0.5);
1305 g_object_set_property(G_OBJECT(beval->balloonLabel), "xalign", &align_val);
1306 g_object_set_property(G_OBJECT(beval->balloonLabel), "yalign", &align_val);
1307 g_value_unset(&align_val);
1308 # else
1151 gtk_misc_set_alignment(GTK_MISC(beval->balloonLabel), 0.5f, 0.5f); 1309 gtk_misc_set_alignment(GTK_MISC(beval->balloonLabel), 0.5f, 0.5f);
1310 # endif
1152 gtk_widget_set_name(beval->balloonLabel, "vim-balloon-label"); 1311 gtk_widget_set_name(beval->balloonLabel, "vim-balloon-label");
1153 gtk_widget_show(beval->balloonLabel); 1312 gtk_widget_show(beval->balloonLabel);
1154 1313
1155 gtk_container_add(GTK_CONTAINER(beval->balloonShell), beval->balloonLabel); 1314 gtk_container_add(GTK_CONTAINER(beval->balloonShell), beval->balloonLabel);
1156 } 1315 }