summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/eval.txt1
-rw-r--r--runtime/doc/gui.txt11
-rw-r--r--runtime/doc/gui_x11.txt10
-rwxr-xr-xsrc/auto/configure264
-rw-r--r--src/channel.c33
-rw-r--r--src/config.h.in3
-rw-r--r--src/configure.in78
-rw-r--r--src/eval.c4
-rw-r--r--src/gui.h7
-rw-r--r--src/gui_beval.c163
-rw-r--r--src/gui_beval.h6
-rw-r--r--src/gui_gtk.c747
-rw-r--r--src/gui_gtk_f.c390
-rw-r--r--src/gui_gtk_f.h19
-rw-r--r--src/gui_gtk_x11.c1339
-rw-r--r--src/if_mzsch.c16
-rw-r--r--src/mbyte.c23
-rw-r--r--src/netbeans.c44
-rw-r--r--src/structs.h2
-rw-r--r--src/version.c14
20 files changed, 3087 insertions, 87 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 022a5da7a5..abc022d392 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -7315,6 +7315,7 @@ gui_athena Compiled with Athena GUI.
gui_gnome Compiled with Gnome support (gui_gtk is also defined).
gui_gtk Compiled with GTK+ GUI (any version).
gui_gtk2 Compiled with GTK+ 2 GUI (gui_gtk is also defined).
+gui_gtk3 Compiled with GTK+ 3 GUI (gui_gtk is also defined).
gui_mac Compiled with Macintosh GUI.
gui_motif Compiled with Motif GUI.
gui_photon Compiled with Photon GUI.
diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt
index d77976330b..520eba910b 100644
--- a/runtime/doc/gui.txt
+++ b/runtime/doc/gui.txt
@@ -25,7 +25,7 @@ Other GUI documentation:
First you must make sure you actually have a version of Vim with the GUI code
included. You can check this with the ":version" command, it says "with xxx
-GUI", where "xxx" is X11-Motif, X11-Athena, Photon, GTK, GTK2, etc., or
+GUI", where "xxx" is X11-Motif, X11-Athena, Photon, GTK2, GTK3, etc., or
"MS-Windows 32 bit GUI version".
How to start the GUI depends on the system used. Mostly you can run the
@@ -514,11 +514,14 @@ a menu entry. Hit <Enter> to execute it. Hit <Esc> if you want to cancel.
This does require the |+menu| feature enabled at compile time.
*tear-off-menus*
-GTK+ and Motif support Tear-off menus. These are sort of sticky menus or
+GTK+ 2 and Motif support Tear-off menus. These are sort of sticky menus or
pop-up menus that are present all the time. If the resizing does not work
correctly, this may be caused by using something like "Vim*geometry" in the
defaults. Use "Vim.geometry" instead.
+As to GTK+ 3, tear-off menus have been deprecated since GTK+ 3.4.
+Accordingly, they are disabled if gvim is linked against GTK+ 3.4 or later.
+
The Win32 GUI version emulates Motif's tear-off menus. Actually, a Motif user
will spot the differences easily, but hopefully they're just as useful. You
can also use the |:tearoff| command together with |hidden-menus| to create
@@ -650,8 +653,8 @@ When no or zero priority is given, 500 is used.
The priority for the PopUp menu is not used.
The Help menu will be placed on the far right side of the menu bar on systems
-which support this (Motif and GTK+). For GTK+ 2, this is not done anymore
-because right-aligning the Help menu is now discouraged UI design.
+which support this (Motif and GTK+). For GTK+ 2 and 3, this is not done
+anymore because right-aligning the Help menu is now discouraged UI design.
You can use a priority higher than 9999, to make it go after the Help menu,
but that is non-standard and is discouraged. The highest possible priority is
diff --git a/runtime/doc/gui_x11.txt b/runtime/doc/gui_x11.txt
index f085e2f2cb..605b998af4 100644
--- a/runtime/doc/gui_x11.txt
+++ b/runtime/doc/gui_x11.txt
@@ -369,6 +369,16 @@ Write this in the file ~/.gtkrc and it will be used by GTK+. For GTK+ 2
you might have to use the file ~/.gtkrc-2.0 instead, depending on your
distribution.
+For GTK+ 3, an effect similar to the above can be obtained by adding the
+following snippet of CSS code to $XDG_HOME_DIR/gtk-3.0/gtk.css (usually,
+$HOME/.config/gtk-3.0/gtk.css):
+ >
+ .tooltip {
+ background-color: #ffffcc;
+ color: #000000;
+ }
+<
+
Using Vim as a GTK+ plugin *gui-gtk-socketid*
When the GTK+ version of Vim starts up normally, it creates its own top level
diff --git a/src/auto/configure b/src/auto/configure
index 69aec67c65..1b3b0c70fc 100755
--- a/src/auto/configure
+++ b/src/auto/configure
@@ -821,6 +821,7 @@ with_x
enable_gui
enable_gtk2_check
enable_gnome_check
+enable_gtk3_check
enable_motif_check
enable_athena_check
enable_nextaw_check
@@ -1481,9 +1482,10 @@ Optional Features:
--enable-hangulinput Include Hangul input support.
--enable-xim Include XIM input support.
--enable-fontset Include X fontset output support.
- --enable-gui=OPTS X11 GUI default=auto OPTS=auto/no/gtk2/gnome2/motif/athena/neXtaw/photon/carbon
+ --enable-gui=OPTS X11 GUI default=auto OPTS=auto/no/gtk2/gnome2/gtk3/motif/athena/neXtaw/photon/carbon
--enable-gtk2-check If auto-select GUI, check for GTK+ 2 default=yes
--enable-gnome-check If GTK GUI, check for GNOME default=no
+ --enable-gtk3-check If auto-select GUI, check for GTK+ 3 default=yes
--enable-motif-check If auto-select GUI, check for Motif default=yes
--enable-athena-check If auto-select GUI, check for Athena default=yes
--enable-nextaw-check If auto-select GUI, check for neXtaw default=yes
@@ -4355,7 +4357,7 @@ fi
if test "x$CARBON" = "xyes"; then
- if test -z "$with_x" -a "X$enable_gui" != Xmotif -a "X$enable_gui" != Xathena -a "X$enable_gui" != Xgtk2; then
+ if test -z "$with_x" -a "X$enable_gui" != Xmotif -a "X$enable_gui" != Xathena -a "X$enable_gui" != Xgtk2 -a "X$enable_gui" != Xgtk3; then
with_x=no
fi
fi
@@ -8606,6 +8608,9 @@ $as_echo "GTK+ 2.x GUI support" >&6; }
$as_echo "GNOME 2.x GUI support" >&6; }
SKIP_GNOME=
SKIP_GTK2=;;
+ gtk3) { $as_echo "$as_me:${as_lineno-$LINENO}: result: GTK+ 3.x GUI support" >&5
+$as_echo "GTK+ 3.x GUI support" >&6; }
+ SKIP_GTK3=;;
motif) { $as_echo "$as_me:${as_lineno-$LINENO}: result: Motif GUI support" >&5
$as_echo "Motif GUI support" >&6; }
SKIP_MOTIF=;;
@@ -8657,6 +8662,23 @@ $as_echo "$enable_gnome_check" >&6; }
fi
fi
+if test "x$SKIP_GTK3" != "xYES" -a "$enable_gui_canon" != "gtk3"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether or not to look for GTK+ 3" >&5
+$as_echo_n "checking whether or not to look for GTK+ 3... " >&6; }
+ # Check whether --enable-gtk3-check was given.
+if test "${enable_gtk3_check+set}" = set; then :
+ enableval=$enable_gtk3_check;
+else
+ enable_gtk3_check="yes"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_gtk3_check" >&5
+$as_echo "$enable_gtk3_check" >&6; }
+ if test "x$enable_gtk3_check" = "xno"; then
+ SKIP_GTK3=YES
+ fi
+fi
+
if test "x$SKIP_MOTIF" != "xYES" -a "$enable_gui_canon" != "motif"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether or not to look for Motif" >&5
$as_echo_n "checking whether or not to look for Motif... " >&6; }
@@ -8831,13 +8853,13 @@ fi
if test "X$GTK_CONFIG" != "Xno" -o "X$PKG_CONFIG" != "Xno"; then
{
- min_gtk_version=2.2.0
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK - version >= $min_gtk_version" >&5
-$as_echo_n "checking for GTK - version >= $min_gtk_version... " >&6; }
no_gtk=""
if (test "X$SKIP_GTK2" != "XYES" -a "X$PKG_CONFIG" != "Xno") \
&& $PKG_CONFIG --exists gtk+-2.0; then
{
+ min_gtk_version=2.2.0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK - version >= $min_gtk_version" >&5
+$as_echo_n "checking for GTK - version >= $min_gtk_version... " >&6; }
GTK_CFLAGS=`$PKG_CONFIG --cflags gtk+-2.0`
GTK_LIBDIR=`$PKG_CONFIG --libs-only-L gtk+-2.0`
GTK_LIBS=`$PKG_CONFIG --libs gtk+-2.0`
@@ -8848,6 +8870,23 @@ $as_echo_n "checking for GTK - version >= $min_gtk_version... " >&6; }
gtk_micro_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
}
+ elif (test "X$SKIP_GTK3" != "XYES" -a "X$PKG_CONFIG" != "Xno") \
+ && $PKG_CONFIG --exists gtk+-3.0; then
+ {
+ min_gtk_version=2.2.0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK - version >= $min_gtk_version" >&5
+$as_echo_n "checking for GTK - version >= $min_gtk_version... " >&6; }
+
+ GTK_CFLAGS=`$PKG_CONFIG --cflags gtk+-3.0`
+ GTK_LIBDIR=`$PKG_CONFIG --libs-only-L gtk+-3.0`
+ GTK_LIBS=`$PKG_CONFIG --libs gtk+-3.0`
+ gtk_major_version=`$PKG_CONFIG --modversion gtk+-3.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'`
+ gtk_minor_version=`$PKG_CONFIG --modversion gtk+-3.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'`
+ gtk_micro_version=`$PKG_CONFIG --modversion gtk+-3.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
+ }
else
no_gtk=yes
fi
@@ -8943,6 +8982,7 @@ $as_echo "no" >&6; }
rm -f conf.gtktest
if test "x$GTK_CFLAGS" != "x"; then
+ SKIP_GTK3=YES
SKIP_ATHENA=YES
SKIP_NEXTAW=YES
SKIP_MOTIF=YES
@@ -9044,6 +9084,218 @@ $as_echo "not found" >&6; }
fi
fi
+
+if test -z "$SKIP_GTK3"; then
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking --disable-gtktest argument" >&5
+$as_echo_n "checking --disable-gtktest argument... " >&6; }
+ # Check whether --enable-gtktest was given.
+if test "${enable_gtktest+set}" = set; then :
+ enableval=$enable_gtktest;
+else
+ enable_gtktest=yes
+fi
+
+ if test "x$enable_gtktest" = "xyes" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: gtk test enabled" >&5
+$as_echo "gtk test enabled" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: gtk test disabled" >&5
+$as_echo "gtk test disabled" >&6; }
+ fi
+
+ if test "X$PKG_CONFIG" = "X"; then
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+
+ if test "x$PKG_CONFIG" != "xno"; then
+
+ if test "X$GTK_CONFIG" != "Xno" -o "X$PKG_CONFIG" != "Xno"; then
+ {
+ no_gtk=""
+ if (test "X$SKIP_GTK2" != "XYES" -a "X$PKG_CONFIG" != "Xno") \
+ && $PKG_CONFIG --exists gtk+-2.0; then
+ {
+ min_gtk_version=3.0.0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK - version >= $min_gtk_version" >&5
+$as_echo_n "checking for GTK - version >= $min_gtk_version... " >&6; }
+ GTK_CFLAGS=`$PKG_CONFIG --cflags gtk+-2.0`
+ GTK_LIBDIR=`$PKG_CONFIG --libs-only-L gtk+-2.0`
+ GTK_LIBS=`$PKG_CONFIG --libs gtk+-2.0`
+ gtk_major_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'`
+ gtk_minor_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'`
+ gtk_micro_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
+ }
+ elif (test "X$SKIP_GTK3" != "XYES" -a "X$PKG_CONFIG" != "Xno") \
+ && $PKG_CONFIG --exists gtk+-3.0; then
+ {
+ min_gtk_version=3.0.0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK - version >= $min_gtk_version" >&5
+$as_echo_n "checking for GTK - version >= $min_gtk_version... " >&6; }
+
+ GTK_CFLAGS=`$PKG_CONFIG --cflags gtk+-3.0`
+ GTK_LIBDIR=`$PKG_CONFIG --libs-only-L gtk+-3.0`
+ GTK_LIBS=`$PKG_CONFIG --libs gtk+-3.0`
+ gtk_major_version=`$PKG_CONFIG --modversion gtk+-3.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'`
+ gtk_minor_version=`$PKG_CONFIG --modversion gtk+-3.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'`
+ gtk_micro_version=`$PKG_CONFIG --modversion gtk+-3.0 | \
+ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
+ }
+ else
+ no_gtk=yes
+ fi
+
+ if test "x$enable_gtktest" = "xyes" -a "x$no_gtk" = "x"; then
+ {
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $GTK_CFLAGS"
+ LIBS="$LIBS $GTK_LIBS"
+
+ rm -f conf.gtktest
+ if test "$cross_compiling" = yes; then :
+ echo $ac_n "cross compiling; assumed OK... $ac_c"
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#endif
+
+int
+main ()
+{
+int major, minor, micro;
+char *tmp_version;
+
+system ("touch conf.gtktest");
+
+/* HP/UX 9 (%@#!) writes to sscanf strings */
+tmp_version = g_strdup("$min_gtk_version");
+if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+ printf("%s, bad version string\n", "$min_gtk_version");
+ exit(1);
+ }
+
+if ((gtk_major_version > major) ||
+ ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+ ((gtk_major_version == major) && (gtk_minor_version == minor) &&
+ (gtk_micro_version >= micro)))
+{
+ return 0;
+}
+return 1;
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ no_gtk=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ }
+ fi
+ if test "x$no_gtk" = x ; then
+ if test "x$enable_gtktest" = "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes; found version $gtk_major_version.$gtk_minor_version.$gtk_micro_version" >&5
+$as_echo "yes; found version $gtk_major_version.$gtk_minor_version.$gtk_micro_version" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: found version $gtk_major_version.$gtk_minor_version.$gtk_micro_version" >&5
+$as_echo "found version $gtk_major_version.$gtk_minor_version.$gtk_micro_version" >&6; }
+ fi
+ GUI_LIB_LOC="$GTK_LIBDIR"
+ GTK_LIBNAME="$GTK_LIBS"
+ GUI_INC_LOC="$GTK_CFLAGS"
+ else
+ {
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ GTK_CFLAGS=""
+ GTK_LIBS=""
+ :
+ }
+ fi
+ }
+ else
+ GTK_CFLAGS=""
+ GTK_LIBS=""
+ :
+ fi
+
+
+ rm -f conf.gtktest
+
+ if test "x$GTK_CFLAGS" != "x"; then
+ SKIP_GTK2=YES
+ SKIP_GNOME=YES
+ SKIP_ATHENA=YES
+ SKIP_NEXTAW=YES
+ SKIP_MOTIF=YES
+ GUITYPE=GTK
+
+ $as_echo "#define HAVE_GTK_MULTIHEAD 1" >>confdefs.h
+
+ $as_echo "#define USE_GTK3 1" >>confdefs.h
+
+ fi
+ fi
+fi
+
if test "x$GUITYPE" = "xGTK"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking version of Gdk-Pixbuf" >&5
$as_echo_n "checking version of Gdk-Pixbuf... " >&6; }
@@ -9546,7 +9798,7 @@ done
fi
-if test -z "$SKIP_ATHENA" -o -z "$SKIP_NEXTAW" -o -z "$SKIP_MOTIF" -o -z "$SKIP_GTK2"; then
+if test -z "$SKIP_ATHENA" -o -z "$SKIP_NEXTAW" -o -z "$SKIP_MOTIF" -o -z "$SKIP_GTK2" -o -z "$SKIP_GTK3"; then
cppflags_save=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $X_CFLAGS"
for ac_header in X11/xpm.h X11/Sunkeysym.h
diff --git a/src/channel.c b/src/channel.c
index e9068fee5e..c59758d853 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -361,6 +361,17 @@ messageFromNetbeans(XtPointer clientData,
#endif
#ifdef FEAT_GUI_GTK
+# if GTK_CHECK_VERSION(3,0,0)
+ static gboolean
+messageFromNetbeans(GIOChannel *unused1 UNUSED,
+ GIOCondition unused2 UNUSED,
+ gpointer clientData)
+{
+ channel_read_fd(GPOINTER_TO_INT(clientData));
+ return TRUE; /* Return FALSE instead in case the event source is to
+ * be removed after this function returns. */
+}
+# else
static void
messageFromNetbeans(gpointer clientData,
gint unused1 UNUSED,
@@ -368,6 +379,7 @@ messageFromNetbeans(gpointer clientData,
{
channel_read_fd((int)(long)clientData);
}
+# endif
#endif
static void
@@ -388,12 +400,27 @@ channel_gui_register_one(channel_T *channel, int part)
/* Tell gdk we are interested in being called when there
* is input on the editor connection socket. */
if (channel->ch_part[part].ch_inputHandler == 0)
+# if GTK_CHECK_VERSION(3,0,0)
+ {
+ GIOChannel *chnnl = g_io_channel_unix_new(
+ (gint)channel->ch_part[part].ch_fd);
+
+ channel->ch_part[part].ch_inputHandler = g_io_add_watch(
+ chnnl,
+ G_IO_IN|G_IO_HUP|G_IO_ERR|G_IO_PRI,
+ messageFromNetbeans,
+ GINT_TO_POINTER(channel->ch_part[part].ch_fd));
+
+ g_io_channel_unref(chnnl);
+ }
+# else
channel->ch_part[part].ch_inputHandler = gdk_input_add(
(gint)channel->ch_part[part].ch_fd,
(GdkInputCondition)
((int)GDK_INPUT_READ + (int)GDK_INPUT_EXCEPTION),
messageFromNetbeans,
(gpointer)(long)channel->ch_part[part].ch_fd);
+# endif
# else
# ifdef FEAT_GUI_W32
/* Tell Windows we are interested in receiving message when there
@@ -457,7 +484,11 @@ channel_gui_unregister(channel_T *channel)
# ifdef FEAT_GUI_GTK
if (channel->ch_part[part].ch_inputHandler != 0)
{
+# if GTK_CHECK_VERSION(3,0,0)
+ g_source_remove(channel->ch_part[part].ch_inputHandler);
+# else
gdk_input_remove(channel->ch_part[part].ch_inputHandler);
+# endif
channel->ch_part[part].ch_inputHandler = 0;
}
# else
@@ -606,7 +637,7 @@ channel_open(
fd_set wfds;
#if defined(__APPLE__) && __APPLE__ == 1
# define PASS_RFDS
- fd_set rfds;
+ fd_set rfds;
FD_ZERO(&rfds);
FD_SET(sd, &rfds);
diff --git a/src/config.h.in b/src/config.h.in
index 8e115f5f16..fd45c7332b 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -460,3 +460,6 @@
/* Define if GResource is used to load icons */
#undef USE_GRESOURCE
+
+/* Define if GTK+ GUI is to be linked against GTK+ 3 */
+#undef USE_GTK3
diff --git a/src/configure.in b/src/configure.in
index 9f19c137b6..930278c7de 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -213,7 +213,7 @@ if test "`(uname) 2>/dev/null`" = Darwin; then
dnl or Motif, Athena or GTK GUI is used.
AC_CHECK_HEADER(Carbon/Carbon.h, CARBON=yes)
if test "x$CARBON" = "xyes"; then
- if test -z "$with_x" -a "X$enable_gui" != Xmotif -a "X$enable_gui" != Xathena -a "X$enable_gui" != Xgtk2; then
+ if test -z "$with_x" -a "X$enable_gui" != Xmotif -a "X$enable_gui" != Xathena -a "X$enable_gui" != Xgtk2 -a "X$enable_gui" != Xgtk3; then
with_x=no
fi
fi
@@ -2198,7 +2198,7 @@ test "x$with_x" = xno -a "x$MACOSX" != "xyes" -a "x$QNX" != "xyes" && enable_gui
AC_MSG_CHECKING(--enable-gui argument)
AC_ARG_ENABLE(gui,
- [ --enable-gui[=OPTS] X11 GUI [default=auto] [OPTS=auto/no/gtk2/gnome2/motif/athena/neXtaw/photon/carbon]], , enable_gui="auto")
+ [ --enable-gui[=OPTS] X11 GUI [default=auto] [OPTS=auto/no/gtk2/gnome2/gtk3/motif/athena/neXtaw/photon/carbon]], , enable_gui="auto")
dnl Canonicalize the --enable-gui= argument so that it can be easily compared.
dnl Do not use character classes for portability with old tools.
@@ -2256,6 +2256,8 @@ else
gnome2) AC_MSG_RESULT(GNOME 2.x GUI support)
SKIP_GNOME=
SKIP_GTK2=;;
+ gtk3) AC_MSG_RESULT(GTK+ 3.x GUI support)
+ SKIP_GTK3=;;
motif) AC_MSG_RESULT(Motif GUI support)
SKIP_MOTIF=;;
athena) AC_MSG_RESULT(Athena GUI support)
@@ -2291,6 +2293,17 @@ if test "x$SKIP_GNOME" != "xYES" -a "$enable_gui_canon" != "gnome2"; then
fi
fi
+if test "x$SKIP_GTK3" != "xYES" -a "$enable_gui_canon" != "gtk3"; then
+ AC_MSG_CHECKING(whether or not to look for GTK+ 3)
+ AC_ARG_ENABLE(gtk3-check,
+ [ --enable-gtk3-check If auto-select GUI, check for GTK+ 3 [default=yes]],
+ , enable_gtk3_check="yes")
+ AC_MSG_RESULT($enable_gtk3_check)
+ if test "x$enable_gtk3_check" = "xno"; then
+ SKIP_GTK3=YES
+ fi
+fi
+
if test "x$SKIP_MOTIF" != "xYES" -a "$enable_gui_canon" != "motif"; then
AC_MSG_CHECKING(whether or not to look for Motif)
AC_ARG_ENABLE(motif-check,
@@ -2379,12 +2392,12 @@ AC_DEFUN(AM_PATH_GTK,
[
if test "X$GTK_CONFIG" != "Xno" -o "X$PKG_CONFIG" != "Xno"; then
{
- min_gtk_version=ifelse([$1], ,2.2.0,$1)
- AC_MSG_CHECKING(for GTK - version >= $min_gtk_version)
no_gtk=""
if (test "X$SKIP_GTK2" != "XYES" -a "X$PKG_CONFIG" != "Xno") \
&& $PKG_CONFIG --exists gtk+-2.0; then
{
+ min_gtk_version=ifelse([$1], ,2.2.0,$1)
+ AC_MSG_CHECKING(for GTK - version >= $min_gtk_version)
dnl We should be using PKG_CHECK_MODULES() instead of this hack.
dnl But I guess the dependency on pkgconfig.m4 is not wanted or
dnl something like that.
@@ -2398,6 +2411,22 @@ AC_DEFUN(AM_PATH_GTK,
gtk_micro_version=`$PKG_CONFIG --modversion gtk+-2.0 | \
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
}
+ elif (test "X$SKIP_GTK3" != "XYES" -a "X$PKG_CONFIG" != "Xno") \
+ && $PKG_CONFIG --exists gtk+-3.0; then
+ {
+ min_gtk_version=ifelse([$1], ,3.0.0,$1)
+ AC_MSG_CHECKING(for GTK - version >= $min_gtk_version)
+
+ GTK_CFLAGS=`$PKG_CONFIG --cflags gtk+-3.0`
+ GTK_LIBDIR=`$PKG_CONFIG --libs-only-L gtk+-3.0`
+ GTK_LIBS=`$PKG_CONFIG --libs gtk+-3.0`
+ gtk_major_version=`$PKG_CONFIG --modversion gtk+-3.0 | \
+ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
+ gtk_minor_version=`$PKG_CONFIG --modversion gtk+-3.0 | \
+ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
+ gtk_micro_version=`$PKG_CONFIG --modversion gtk+-3.0 | \
+ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
+ }
else
no_gtk=yes
fi
@@ -2573,6 +2602,7 @@ if test -z "$SKIP_GTK2"; then
GTK_LIBNAME="$GTK_LIBS"
GUI_INC_LOC="$GTK_CFLAGS"], )
if test "x$GTK_CFLAGS" != "x"; then
+ SKIP_GTK3=YES
SKIP_ATHENA=YES
SKIP_NEXTAW=YES
SKIP_MOTIF=YES
@@ -2601,6 +2631,44 @@ if test -z "$SKIP_GTK2"; then
fi
fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check for GTK3.
+dnl ---------------------------------------------------------------------------
+if test -z "$SKIP_GTK3"; then
+
+ AC_MSG_CHECKING(--disable-gtktest argument)
+ AC_ARG_ENABLE(gtktest, [ --disable-gtktest Do not try to compile and run a test GTK program],
+ , enable_gtktest=yes)
+ if test "x$enable_gtktest" = "xyes" ; then
+ AC_MSG_RESULT(gtk test enabled)
+ else
+ AC_MSG_RESULT(gtk test disabled)
+ fi
+
+ if test "X$PKG_CONFIG" = "X"; then
+ AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+ fi
+
+ if test "x$PKG_CONFIG" != "xno"; then
+ AM_PATH_GTK(3.0.0,
+ [GUI_LIB_LOC="$GTK_LIBDIR"
+ GTK_LIBNAME="$GTK_LIBS"
+ GUI_INC_LOC="$GTK_CFLAGS"], )
+ if test "x$GTK_CFLAGS" != "x"; then
+ SKIP_GTK2=YES
+ SKIP_GNOME=YES
+ SKIP_ATHENA=YES
+ SKIP_NEXTAW=YES
+ SKIP_MOTIF=YES
+ GUITYPE=GTK
+ AC_SUBST(GTK_LIBNAME)
+ AC_DEFINE(HAVE_GTK_MULTIHEAD)
+ AC_DEFINE(USE_GTK3)
+ fi
+ fi
+fi
+
dnl Check the version of Gdk-Pixbuf. If the version is 2.31 or later and
dnl glib-compile-resources is found in PATH, use GResource.
if test "x$GUITYPE" = "xGTK"; then
@@ -2823,7 +2891,7 @@ if test "$enable_xsmp" = "yes"; then
fi
-if test -z "$SKIP_ATHENA" -o -z "$SKIP_NEXTAW" -o -z "$SKIP_MOTIF" -o -z "$SKIP_GTK2"; then
+if test -z "$SKIP_ATHENA" -o -z "$SKIP_NEXTAW" -o -z "$SKIP_MOTIF" -o -z "$SKIP_GTK2" -o -z "$SKIP_GTK3"; then
dnl Check for X11/xpm.h and X11/Sunkeysym.h with the GUI include path
cppflags_save=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $X_CFLAGS"
diff --git a/src/eval.c b/src/eval.c
index 3b1172ecd8..1471568184 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -13671,7 +13671,11 @@ f_has(typval_T *argvars, typval_T *rettv)
#endif
#ifdef FEAT_GUI_GTK
"gui_gtk",
+# ifdef USE_GTK3
+ "gui_gtk3",
+# else
"gui_gtk2",
+# endif
#endif
#ifdef FEAT_GUI_GNOME
"gui_gnome",
diff --git a/src/gui.h b/src/gui.h
index d026664d37..f119de5c12 100644
--- a/src/gui.h
+++ b/src/gui.h
@@ -359,7 +359,9 @@ typedef struct Gui
#endif
#ifdef FEAT_GUI_GTK
+# ifndef USE_GTK3
int visibility; /* Is shell partially/fully obscured? */
+# endif
GdkCursor *blank_pointer; /* Blank pointer */
/* X Resources */
@@ -381,7 +383,12 @@ typedef struct Gui
GdkColor *fgcolor; /* GDK-styled foreground color */
GdkColor *bgcolor; /* GDK-styled background color */
GdkColor *spcolor; /* GDK-styled special color */
+# ifdef USE_GTK3
+ cairo_surface_t *surface; /* drawarea surface */
+ gboolean by_signal; /* cause of draw operation */
+# else
GdkGC *text_gc; /* cached GC for normal text */
+# endif
PangoContext *text_context; /* the context used for all text */
PangoFont *ascii_font; /* cached font for ASCII strings */
PangoGlyphString *ascii_glyphs; /* cached code point -> glyph map */
diff --git a/src/gui_beval.c b/src/gui_beval.c
index e96e67d3fd..258ba8aeb7 100644
--- a/src/gui_beval.c
+++ b/src/gui_beval.c
@@ -122,7 +122,11 @@ general_beval_cb(BalloonEval *beval, int state UNUSED)
#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 *, GdkEvent *, gpointer);
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, BalloonEval *beval)
* 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, BalloonEval *beval)
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, BalloonEval *beval)
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, GdkEvent *event, gpointer data)
* 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, int y, unsigned state)
}
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 keyval, int is_keypress)
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 *widget,
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, char_u *text)
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)