diff 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
line wrap: on
line diff
--- a/src/gui_beval.c
+++ b/src/gui_beval.c
@@ -122,7 +122,11 @@ general_beval_cb(BalloonEval *beval, int
 #if !defined(FEAT_GUI_W32) || defined(PROTO)
 
 #ifdef FEAT_GUI_GTK
-# include <gdk/gdkkeysyms.h>
+# if GTK_CHECK_VERSION(3,0,0)
+#  include <gdk/gdkkeysyms-compat.h>
+# else
+#  include <gdk/gdkkeysyms.h>
+# endif
 # include <gtk/gtk.h>
 #else
 # include <X11/keysym.h>
@@ -164,8 +168,16 @@ static gint target_event_cb(GtkWidget *,
 static gint mainwin_event_cb(GtkWidget *, GdkEvent *, gpointer);
 static void pointer_event(BalloonEval *, int, int, unsigned);
 static void key_event(BalloonEval *, unsigned, int);
+# if GTK_CHECK_VERSION(3,0,0)
+static gboolean timeout_cb(gpointer);
+# else
 static gint timeout_cb(gpointer);
-static gint balloon_expose_event_cb(GtkWidget *, GdkEventExpose *, gpointer);
+# endif
+# if GTK_CHECK_VERSION(3,0,0)
+static gboolean balloon_draw_event_cb (GtkWidget *, cairo_t *, gpointer);
+# else
+static gint balloon_expose_event_cb (GtkWidget *, GdkEventExpose *, gpointer);
+# endif
 #else
 static void addEventHandler(Widget, BalloonEval *);
 static void removeEventHandler(BalloonEval *);
@@ -459,10 +471,16 @@ addEventHandler(GtkWidget *target, Ballo
      * This allows us to catch events independently of the signal handlers
      * in gui_gtk_x11.c.
      */
+# if GTK_CHECK_VERSION(3,0,0)
+    g_signal_connect(G_OBJECT(target), "event",
+		     G_CALLBACK(target_event_cb),
+		     beval);
+# else
     /* Should use GTK_OBJECT() here, but that causes a lint warning... */
     gtk_signal_connect((GtkObject*)(target), "event",
 		       GTK_SIGNAL_FUNC(target_event_cb),
 		       beval);
+# endif
     /*
      * Nasty:  Key press events go to the main window thus the drawing area
      * will never see them.  This means we have to connect to the main window
@@ -471,9 +489,15 @@ addEventHandler(GtkWidget *target, Ballo
     if (gtk_socket_id == 0 && gui.mainwin != NULL
 	    && gtk_widget_is_ancestor(target, gui.mainwin))
     {
+# if GTK_CHECK_VERSION(3,0,0)
+	g_signal_connect(G_OBJECT(gui.mainwin), "event",
+			 G_CALLBACK(mainwin_event_cb),
+			 beval);
+# else
 	gtk_signal_connect((GtkObject*)(gui.mainwin), "event",
 			   GTK_SIGNAL_FUNC(mainwin_event_cb),
 			   beval);
+# endif
     }
 }
 
@@ -481,17 +505,29 @@ addEventHandler(GtkWidget *target, Ballo
 removeEventHandler(BalloonEval *beval)
 {
     /* LINTED: avoid warning: dubious operation on enum */
+# if GTK_CHECK_VERSION(3,0,0)
+    g_signal_handlers_disconnect_by_func(G_OBJECT(beval->target),
+					 G_CALLBACK(target_event_cb),
+					 beval);
+# else
     gtk_signal_disconnect_by_func((GtkObject*)(beval->target),
 				  GTK_SIGNAL_FUNC(target_event_cb),
 				  beval);
+# endif
 
     if (gtk_socket_id == 0 && gui.mainwin != NULL
 	    && gtk_widget_is_ancestor(beval->target, gui.mainwin))
     {
 	/* LINTED: avoid warning: dubious operation on enum */
+# if GTK_CHECK_VERSION(3,0,0)
+	g_signal_handlers_disconnect_by_func(G_OBJECT(gui.mainwin),
+					     G_CALLBACK(mainwin_event_cb),
+					     beval);
+# else
 	gtk_signal_disconnect_by_func((GtkObject*)(gui.mainwin),
 				      GTK_SIGNAL_FUNC(mainwin_event_cb),
 				      beval);
+# endif
     }
 }
 
@@ -517,7 +553,17 @@ target_event_cb(GtkWidget *widget, GdkEv
 		 * GDK_POINTER_MOTION_HINT_MASK is set, thus we cannot obtain
 		 * the coordinates from the GdkEventMotion struct directly.
 		 */
+# if GTK_CHECK_VERSION(3,0,0)
+		{
+		    GdkWindow * const win = gtk_widget_get_window(widget);
+		    GdkDisplay * const dpy = gdk_window_get_display(win);
+		    GdkDeviceManager * const mngr = gdk_display_get_device_manager(dpy);
+		    GdkDevice * const dev = gdk_device_manager_get_client_pointer(mngr);
+		    gdk_window_get_device_position(win, dev , &x, &y, &state);
+		}
+# else
 		gdk_window_get_pointer(widget->window, &x, &y, &state);
+# endif
 		pointer_event(beval, x, y, (unsigned int)state);
 	    }
 	    else
@@ -609,8 +655,13 @@ pointer_event(BalloonEval *beval, int x,
 	    }
 	    else
 	    {
+# if GTK_CHECK_VERSION(3,0,0)
+		beval->timerID = g_timeout_add((guint)p_bdlay,
+					       &timeout_cb, beval);
+# else
 		beval->timerID = gtk_timeout_add((guint32)p_bdlay,
 						 &timeout_cb, beval);
+# endif
 	    }
 	}
     }
@@ -647,7 +698,11 @@ key_event(BalloonEval *beval, unsigned k
 	cancelBalloon(beval);
 }
 
+# if GTK_CHECK_VERSION(3,0,0)
+    static gboolean
+# else
     static gint
+# endif
 timeout_cb(gpointer data)
 {
     BalloonEval *beval = (BalloonEval *)data;
@@ -663,6 +718,37 @@ timeout_cb(gpointer data)
     return FALSE; /* don't call me again */
 }
 
+# if GTK_CHECK_VERSION(3,0,0)
+    static gboolean
+balloon_draw_event_cb(GtkWidget *widget,
+		      cairo_t	*cr,
+		      gpointer	 data UNUSED)
+{
+    GtkStyleContext *context = NULL;
+    gint width = -1, height = -1;
+
+    if (widget == NULL)
+	return TRUE;
+
+    context = gtk_widget_get_style_context(widget);
+    width = gtk_widget_get_allocated_width(widget);
+    height = gtk_widget_get_allocated_height(widget);
+
+    gtk_style_context_save(context);
+
+    gtk_style_context_add_class(context, "tooltip");
+    gtk_style_context_set_state(context, GTK_STATE_FLAG_NORMAL);
+
+    cairo_save(cr);
+    gtk_render_frame(context, cr, 0, 0, width, height);
+    gtk_render_background(context, cr, 0, 0, width, height);
+    cairo_restore(cr);
+
+    gtk_style_context_restore(context);
+
+    return FALSE;
+}
+# else
     static gint
 balloon_expose_event_cb(GtkWidget *widget,
 			GdkEventExpose *event,
@@ -675,6 +761,7 @@ balloon_expose_event_cb(GtkWidget *widge
 
     return FALSE; /* continue emission */
 }
+# endif /* !GTK_CHECK_VERSION(3,0,0) */
 
 #else /* !FEAT_GUI_GTK */
 
@@ -957,8 +1044,37 @@ set_printable_label_text(GtkLabel *label
 	aep = syn_gui_attr2entry(hl_attr(HLF_8));
 	pixel = (aep != NULL) ? aep->ae_u.gui.fg_color : INVALCOLOR;
 	if (pixel != INVALCOLOR)
+# if GTK_CHECK_VERSION(3,0,0)
+	{
+	    GdkVisual * const visual = gtk_widget_get_visual(gui.drawarea);
+
+	    if (visual == NULL)
+	    {
+		color.red = 0;
+		color.green = 0;
+		color.blue = 0;
+	    }
+	    else
+	    {
+		guint32 r_mask, g_mask, b_mask;
+		gint r_shift, g_shift, b_shift;
+
+		gdk_visual_get_red_pixel_details(visual, &r_mask, &r_shift,
+						 NULL);
+		gdk_visual_get_green_pixel_details(visual, &g_mask, &g_shift,
+						   NULL);
+		gdk_visual_get_blue_pixel_details(visual, &b_mask, &b_shift,
+						  NULL);
+
+		color.red = ((pixel & r_mask) >> r_shift) / 255.0 * 65535;
+		color.green = ((pixel & g_mask) >> g_shift) / 255.0 * 65535;
+		color.blue = ((pixel & b_mask) >> b_shift) / 255.0 * 65535;
+	    }
+	}
+# else
 	    gdk_colormap_query_color(gtk_widget_get_colormap(gui.drawarea),
 				     (unsigned long)pixel, &color);
+# endif
 
 	pdest = buf;
 	p = text;
@@ -1059,8 +1175,10 @@ drawBalloon(BalloonEval *beval)
 	screen_w = gdk_screen_width();
 	screen_h = gdk_screen_height();
 # endif
+# if !GTK_CHECK_VERSION(3,0,0)
 	gtk_widget_ensure_style(beval->balloonShell);
 	gtk_widget_ensure_style(beval->balloonLabel);
+# endif
 
 	set_printable_label_text(GTK_LABEL(beval->balloonLabel), beval->msg);
 	/*
@@ -1081,10 +1199,18 @@ drawBalloon(BalloonEval *beval)
 				    MAX(20, screen_w - 20)));
 
 	/* Calculate the balloon's width and height. */
+# if GTK_CHECK_VERSION(3,0,0)
+	gtk_widget_get_preferred_size(beval->balloonShell, &requisition, NULL);
+# else
 	gtk_widget_size_request(beval->balloonShell, &requisition);
+# endif
 
 	/* Compute position of the balloon area */
+# if GTK_CHECK_VERSION(3,0,0)
+	gdk_window_get_origin(gtk_widget_get_window(beval->target), &x, &y);
+# else
 	gdk_window_get_origin(beval->target->window, &x, &y);
+# endif
 	x += beval->x;
 	y += beval->y;
 
@@ -1099,7 +1225,11 @@ drawBalloon(BalloonEval *beval)
 	y = CLAMP(y + y_offset, 0, MAX(0, screen_h - requisition.height));
 
 	/* Show the balloon */
+# if GTK_CHECK_VERSION(3,0,0)
+	gtk_window_move(GTK_WINDOW(beval->balloonShell), x, y);
+# else
 	gtk_widget_set_uposition(beval->balloonShell, x, y);
+# endif
 	gtk_widget_show(beval->balloonShell);
 
 	beval->showState = ShS_SHOWING;
@@ -1126,7 +1256,11 @@ cancelBalloon(BalloonEval *beval)
 
     if (beval->timerID != 0)
     {
+# if GTK_CHECK_VERSION(3,0,0)
+	g_source_remove(beval->timerID);
+# else
 	gtk_timeout_remove(beval->timerID);
+# endif
 	beval->timerID = 0;
     }
     beval->showState = ShS_NEUTRAL;
@@ -1138,17 +1272,42 @@ createBalloonEvalWindow(BalloonEval *bev
     beval->balloonShell = gtk_window_new(GTK_WINDOW_POPUP);
 
     gtk_widget_set_app_paintable(beval->balloonShell, TRUE);
+# if GTK_CHECK_VERSION(3,0,0)
+    gtk_window_set_resizable(GTK_WINDOW(beval->balloonShell), FALSE);
+# else
     gtk_window_set_policy(GTK_WINDOW(beval->balloonShell), FALSE, FALSE, TRUE);
+# endif
     gtk_widget_set_name(beval->balloonShell, "gtk-tooltips");
+# if GTK_CHECK_VERSION(3,0,0)
+    gtk_container_set_border_width(GTK_CONTAINER(beval->balloonShell), 4);
+# else
     gtk_container_border_width(GTK_CONTAINER(beval->balloonShell), 4);
+# endif
 
+# if GTK_CHECK_VERSION(3,0,0)
+    g_signal_connect(G_OBJECT(beval->balloonShell), "draw",
+		     G_CALLBACK(balloon_draw_event_cb), NULL);
+# else
     gtk_signal_connect((GtkObject*)(beval->balloonShell), "expose_event",
 		       GTK_SIGNAL_FUNC(balloon_expose_event_cb), NULL);
+# endif
     beval->balloonLabel = gtk_label_new(NULL);
 
     gtk_label_set_line_wrap(GTK_LABEL(beval->balloonLabel), FALSE);
     gtk_label_set_justify(GTK_LABEL(beval->balloonLabel), GTK_JUSTIFY_LEFT);
+# if GTK_CHECK_VERSION(3,16,0)
+    gtk_label_set_xalign(GTK_LABEL(beval->balloonLabel), 0.5);
+    gtk_label_set_yalign(GTK_LABEL(beval->balloonLabel), 0.5);
+# elif GTK_CHECK_VERSION(3,14,0)
+    GValue align_val = G_VALUE_INIT;
+    g_value_init(&align_val, G_TYPE_FLOAT);
+    g_value_set_float(&align_val, 0.5);
+    g_object_set_property(G_OBJECT(beval->balloonLabel), "xalign", &align_val);
+    g_object_set_property(G_OBJECT(beval->balloonLabel), "yalign", &align_val);
+    g_value_unset(&align_val);
+# else
     gtk_misc_set_alignment(GTK_MISC(beval->balloonLabel), 0.5f, 0.5f);
+# endif
     gtk_widget_set_name(beval->balloonLabel, "vim-balloon-label");
     gtk_widget_show(beval->balloonLabel);