summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-02-23 17:14:37 +0100
committerBram Moolenaar <Bram@vim.org>2016-02-23 17:14:37 +0100
commit9892189d2e7ab94b750f99e6da4cbfc3c8014517 (patch)
tree18634bacebb9e922feceff40c924cdc48550d7ac
parent6bd364e08461159ad3c153ffba4def5b896486a1 (diff)
downloadvim-git-9892189d2e7ab94b750f99e6da4cbfc3c8014517.tar.gz
patch 7.4.1402v7.4.1402
Problem: GTK 3 is not supported. Solution: Add GTK 3 support. (Kazunobu Kuriyama)
-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 022a5da7a..abc022d39 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 d77976330..520eba910 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 f085e2f2c..605b998af 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 69aec67c6..1b3b0c70f 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 e9068fee5..c59758d85 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 8e115f5f1..fd45c7332 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 9f19c137b..930278c7d 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 3b1172ecd..147156818 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 d026664d3..f119de5c1 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 e96e67d3f..258ba8aeb 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)
+ {
+ 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 *beval)
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);
diff --git a/src/gui_beval.h b/src/gui_beval.h
index 859c08193..ead0fb172 100644
--- a/src/gui_beval.h
+++ b/src/gui_beval.h
@@ -11,7 +11,11 @@
#define GUI_BEVAL_H
#ifdef FEAT_GUI_GTK
-# include <gtk/gtkwidget.h>
+# ifdef USE_GTK3
+# include <gtk/gtk.h>
+# else
+# include <gtk/gtkwidget.h>
+# endif
#else
# if defined(FEAT_GUI_X11)
# include <X11/Intrinsic.h>
diff --git a/src/gui_gtk.c b/src/gui_gtk.c
index 99e4d70df..6decec0df 100644
--- a/src/gui_gtk.c
+++ b/src/gui_gtk.c
@@ -22,8 +22,17 @@
*
* Best supporting actor (He helped somewhat, aesthetically speaking):
* Maxime Romano <verbophobe@hotmail.com>
+ *
+ * Support for GTK+ 3 was added by:
+ *
+ * 2016 Kazunobu Kuriyama <kazunobu.kuriyama@gmail.com>
+ *
+ * With the help of Marius Gedminas and the word of Bram Moolenaar,
+ * "Let's give this some time to mature."
*/
+#include "vim.h"
+
#ifdef FEAT_GUI_GTK
# include "gui_gtk_f.h"
#endif
@@ -37,8 +46,6 @@
# undef MAX
#endif
-#include "vim.h"
-
#ifdef FEAT_GUI_GNOME
/* Gnome redefines _() and N_(). Grrr... */
# ifdef _
@@ -63,7 +70,11 @@
#endif
#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 <gdk/gdk.h>
# ifdef WIN3264
# include <gdk/gdkwin32.h>
@@ -104,6 +115,70 @@ static void recent_func_log_func(
* match toolbar_names[] in menu.c! All stock icons including the "vim-*"
* ones can be overridden in your gtkrc file.
*/
+# if GTK_CHECK_VERSION(3,10,0)
+static const char * const menu_themed_names[] =
+{
+ /* 00 */ "document-new", /* sub. GTK_STOCK_NEW */
+ /* 01 */ "document-open", /* sub. GTK_STOCK_OPEN */
+ /* 02 */ "document-save", /* sub. GTK_STOCK_SAVE */
+ /* 03 */ "edit-undo", /* sub. GTK_STOCK_UNDO */
+ /* 04 */ "edit-redo", /* sub. GTK_STOCK_REDO */
+ /* 05 */ "edit-cut", /* sub. GTK_STOCK_CUT */
+ /* 06 */ "edit-copy", /* sub. GTK_STOCK_COPY */
+ /* 07 */ "edit-paste", /* sub. GTK_STOCK_PASTE */
+ /* 08 */ "document-print", /* sub. GTK_STOCK_PRINT */
+ /* 09 */ "help-browser", /* sub. GTK_STOCK_HELP */
+ /* 10 */ "edit-find", /* sub. GTK_STOCK_FIND */
+# if GTK_CHECK_VERSION(3,14,0)
+ /* Use the file names in gui_gtk_res.xml, cutting off the extension.
+ * Similar changes follow. */
+ /* 11 */ "stock_vim_save_all",
+ /* 12 */ "stock_vim_session_save",
+ /* 13 */ "stock_vim_session_new",
+ /* 14 */ "stock_vim_session_load",
+# else
+ /* 11 */ "vim-save-all",
+ /* 12 */ "vim-session-save",
+ /* 13 */ "vim-session-new",
+ /* 14 */ "vim-session-load",
+# endif
+ /* 15 */ "system-run", /* sub. GTK_STOCK_EXECUTE */
+ /* 16 */ "edit-find-replace", /* sub. GTK_STOCK_FIND_AND_REPLACE */
+ /* 17 */ "window-close", /* sub. GTK_STOCK_CLOSE, FIXME: fuzzy */
+# if GTK_CHECK_VERSION(3,14,0)
+ /* 18 */ "stock_vim_window_maximize",
+ /* 19 */ "stock_vim_window_minimize",
+ /* 20 */ "stock_vim_window_split",
+ /* 21 */ "stock_vim_shell",
+# else
+ /* 18 */ "vim-window-maximize",
+ /* 19 */ "vim-window-minimize",
+ /* 20 */ "vim-window-split",
+ /* 21 */ "vim-shell",
+# endif
+ /* 22 */ "go-previous", /* sub. GTK_STOCK_GO_BACK */
+ /* 23 */ "go-next", /* sub. GTK_STOCK_GO_FORWARD */
+# if GTK_CHECK_VERSION(3,14,0)
+ /* 24 */ "stock_vim_find_help",
+# else
+ /* 24 */ "vim-find-help",
+# endif
+ /* 25 */ "gtk-convert", /* sub. GTK_STOCK_CONVERT */
+ /* 26 */ "go-jump", /* sub. GTK_STOCK_JUMP_TO */
+# if GTK_CHECK_VERSION(3,14,0)
+ /* 27 */ "stock_vim_build_tags",
+ /* 28 */ "stock_vim_window_split_vertical",
+ /* 29 */ "stock_vim_window_maximize_width",
+ /* 30 */ "stock_vim_window_minimize_width",
+# else
+ /* 27 */ "vim-build-tags",
+ /* 28 */ "vim-window-split-vertical",
+ /* 29 */ "vim-window-maximize-width",
+ /* 30 */ "vim-window-minimize-width",
+# endif
+ /* 31 */ "application-exit", /* GTK_STOCK_QUIT */
+};
+# else /* !GTK_CHECK_VERSION(3,10,0) */
static const char * const menu_stock_ids[] =
{
/* 00 */ GTK_STOCK_NEW,
@@ -139,8 +214,10 @@ static const char * const menu_stock_ids[] =
/* 30 */ "vim-window-minimize-width",
/* 31 */ GTK_STOCK_QUIT
};
+# endif /* !GTK_CHECK_VERSION(3,10,0) */
-#ifdef USE_GRESOURCE
+# ifdef USE_GRESOURCE
+# if !GTK_CHECK_VERSION(3,10,0)
typedef struct IconNames {
const char *icon_name;
const char *file_name;
@@ -162,9 +239,10 @@ static IconNames stock_vim_icons[] = {
{ "vim-window-split-vertical", "stock_vim_window_split_vertical.png" },
{ NULL, NULL }
};
-#endif
+# endif
+# endif /* USE_G_RESOURCE */
-#ifndef USE_GRESOURCE
+# ifndef USE_GRESOURCE
static void
add_stock_icon(GtkIconFactory *factory,
const char *stock_id,
@@ -182,7 +260,7 @@ add_stock_icon(GtkIconFactory *factory,
gtk_icon_set_unref(icon_set);
g_object_unref(pixbuf);
}
-#endif
+# endif
static int
lookup_menu_iconfile(char_u *iconfile, char_u *dest)
@@ -214,6 +292,52 @@ lookup_menu_iconfile(char_u *iconfile, char_u *dest)
load_menu_iconfile(char_u *name, GtkIconSize icon_size)
{
GtkWidget *image = NULL;
+# if GTK_CHECK_VERSION(3,10,0)
+ int pixel_size = -1;
+
+ switch (icon_size)
+ {
+ case GTK_ICON_SIZE_MENU:
+ pixel_size = 16;
+ break;
+ case GTK_ICON_SIZE_SMALL_TOOLBAR:
+ pixel_size = 16;
+ break;
+ case GTK_ICON_SIZE_LARGE_TOOLBAR:
+ pixel_size = 24;
+ break;
+ case GTK_ICON_SIZE_BUTTON:
+ pixel_size = 16;
+ break;
+ case GTK_ICON_SIZE_DND:
+ pixel_size = 32;
+ break;
+ case GTK_ICON_SIZE_DIALOG:
+ pixel_size = 48;
+ break;
+ case GTK_ICON_SIZE_INVALID:
+ /* FALLTHROUGH */
+ default:
+ pixel_size = 0;
+ break;
+ }
+
+ if (pixel_size > 0 || pixel_size == -1)
+ {
+ GdkPixbuf * const pixbuf
+ = gdk_pixbuf_new_from_file_at_scale((const char *)name,
+ pixel_size, pixel_size, TRUE, NULL);
+ if (pixbuf != NULL)
+ {
+ image = gtk_image_new_from_pixbuf(pixbuf);
+ g_object_unref(pixbuf);
+ }
+ }
+ if (image == NULL)
+ image = gtk_image_new_from_icon_name("image-missing", icon_size);
+
+ return image;
+# else /* !GTK_CHECK_VERSION(3,10,0) */
GtkIconSet *icon_set;
GtkIconSource *icon_source;
@@ -234,6 +358,7 @@ load_menu_iconfile(char_u *name, GtkIconSize icon_size)
gtk_icon_set_unref(icon_set);
return image;
+# endif /* !GTK_CHECK_VERSION(3,10,0) */
}
static GtkWidget *
@@ -254,6 +379,17 @@ create_menu_icon(vimmenu_T *menu, GtkIconSize icon_size)
/* Still not found? Then use a builtin icon, a blank one as fallback. */
if (image == NULL)
{
+# if GTK_CHECK_VERSION(3,10,0)
+ const char *icon_name = NULL;
+ const int n_names = G_N_ELEMENTS(menu_themed_names);
+
+ if (menu->iconidx >= 0 && menu->iconidx < n_names)
+ icon_name = menu_themed_names[menu->iconidx];
+ if (icon_name == NULL)
+ icon_name = "image-missing";
+
+ image = gtk_image_new_from_icon_name(icon_name, icon_size);
+# else
const char *stock_id;
const int n_ids = G_N_ELEMENTS(menu_stock_ids);
@@ -263,6 +399,7 @@ create_menu_icon(vimmenu_T *menu, GtkIconSize icon_size)
stock_id = GTK_STOCK_MISSING_IMAGE;
image = gtk_image_new_from_stock(stock_id, icon_size);
+# endif
}
return image;
@@ -288,12 +425,12 @@ toolbar_button_focus_in_event(GtkWidget *widget UNUSED,
void
gui_gtk_register_stock_icons(void)
{
-#ifndef USE_GRESOURCE
-# include "../pixmaps/stock_icons.h"
+# ifndef USE_GRESOURCE
+# include "../pixmaps/stock_icons.h"
GtkIconFactory *factory;
factory = gtk_icon_factory_new();
-# define ADD_ICON(Name, Data) add_stock_icon(factory, Name, Data, (int)sizeof(Data))
+# define ADD_ICON(Name, Data) add_stock_icon(factory, Name, Data, (int)sizeof(Data))
ADD_ICON("vim-build-tags", stock_vim_build_tags);
ADD_ICON("vim-find-help", stock_vim_find_help);
@@ -309,35 +446,91 @@ gui_gtk_register_stock_icons(void)
ADD_ICON("vim-window-split", stock_vim_window_split);
ADD_ICON("vim-window-split-vertical", stock_vim_window_split_vertical);
-# undef ADD_ICON
-#else
- GtkIconFactory * const factory = gtk_icon_factory_new();
+# undef ADD_ICON
+
+ gtk_icon_factory_add_default(factory);
+ g_object_unref(factory);
+# else /* defined(USE_GRESOURCE) */
const char * const path_prefix = "/org/vim/gui/icon";
+# if GTK_CHECK_VERSION(3,14,0)
+ GdkScreen *screen = NULL;
+ GtkIconTheme *icon_theme = NULL;
+
+ if (GTK_IS_WIDGET(gui.mainwin))
+ screen = gtk_widget_get_screen(gui.mainwin);
+ else
+ screen = gdk_screen_get_default();
+ icon_theme = gtk_icon_theme_get_for_screen(screen);
+ gtk_icon_theme_add_resource_path(icon_theme, path_prefix);
+# elif GTK_CHECK_VERSION(3,0,0)
IconNames *names;
for (names = stock_vim_icons; names->icon_name != NULL; names++)
{
- char path[MAXPATHL];
- GdkPixbuf *pixbuf;
-
- vim_snprintf(path, MAXPATHL, "%s/%s", path_prefix, names->file_name);
- pixbuf = gdk_pixbuf_new_from_resource(path, NULL);
- if (pixbuf != NULL)
- {
- GtkIconSet *icon_set = gtk_icon_set_new_from_pixbuf(pixbuf);
- gtk_icon_factory_add(factory, names->icon_name, icon_set);
- gtk_icon_set_unref(icon_set);
- g_object_unref(pixbuf);
- }
+ char path[MAXPATHL];
+
+ vim_snprintf(path, MAXPATHL, "%s/%s", path_prefix, names->file_name);
+ GdkPixbuf *pixbuf = NULL;
+ pixbuf = gdk_pixbuf_new_from_resource(path, NULL);
+ if (pixbuf != NULL)
+ {
+ const gint size = MAX(gdk_pixbuf_get_width(pixbuf),
+ gdk_pixbuf_get_height(pixbuf));
+ if (size > 16)
+ {
+ /* An icon theme is supposed to provide fixed-size
+ * image files for each size, e.g., 16, 22, 24, ...
+ * Naturally, in contrast to GtkIconSet, GtkIconTheme
+ * won't prepare size variants for us out of a single
+ * fixed-size image.
+ *
+ * Currently, Vim provides 24x24 images only while the
+ * icon size on the menu and the toolbar is set to 16x16
+ * by default.
+ *
+ * Resize them by ourselves until we have our own fully
+ * fledged icon theme. */
+ GdkPixbuf *src = pixbuf;
+ pixbuf = gdk_pixbuf_scale_simple(src,
+ 16, 16,
+ GDK_INTERP_BILINEAR);
+ if (pixbuf == NULL)
+ pixbuf = src;
+ else
+ g_object_unref(src);
+ }
+ gtk_icon_theme_add_builtin_icon(names->icon_name, size, pixbuf);
+ g_object_unref(pixbuf);
+ }
}
-#endif
+# else /* !GTK_CHECK_VERSION(3,0.0) */
+ GtkIconFactory * const factory = gtk_icon_factory_new();
+ IconNames *names;
+
+ for (names = stock_vim_icons; names->icon_name != NULL; names++)
+ {
+ char path[MAXPATHL];
+ GdkPixbuf *pixbuf;
+
+ vim_snprintf(path, MAXPATHL, "%s/%s", path_prefix, names->file_name);
+ pixbuf = gdk_pixbuf_new_from_resource(path, NULL);
+ if (pixbuf != NULL)
+ {
+ GtkIconSet *icon_set = gtk_icon_set_new_from_pixbuf(pixbuf);
+ gtk_icon_factory_add(factory, names->icon_name, icon_set);
+ gtk_icon_set_unref(icon_set);
+ g_object_unref(pixbuf);
+ }
+ }
+
gtk_icon_factory_add_default(factory);
g_object_unref(factory);
+# endif /* !GTK_CHECK_VERSION(3,0,0) */
+# endif /* defined(USE_GRESOURCE) */
}
#endif /* FEAT_TOOLBAR */
-
#if defined(FEAT_MENU) || defined(PROTO)
/*
@@ -408,7 +601,12 @@ menu_item_new(vimmenu_T *menu, GtkWidget *parent_widget)
* changes to Vim's menu system. Not to mention that all the translations
* had to be updated. */
menu->id = gtk_menu_item_new();
+# if GTK_CHECK_VERSION(3,2,0)
+ box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 20);
+ gtk_box_set_homogeneous(GTK_BOX(box), FALSE);
+# else
box = gtk_hbox_new(FALSE, 20);
+# endif
use_mnemonic = (p_wak[0] != 'n' || !GTK_IS_MENU_BAR(parent_widget));
text = translate_mnemonic_tag(menu->name, use_mnemonic);
@@ -465,10 +663,17 @@ gui_mch_add_menu(vimmenu_T *menu, int idx)
gtk_menu_set_accel_group(GTK_MENU(menu->submenu_id), gui.accel_group);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu->id), menu->submenu_id);
+# if !GTK_CHECK_VERSION(3,4,0)
menu->tearoff_handle = gtk_tearoff_menu_item_new();
if (vim_strchr(p_go, GO_TEAROFF) != NULL)
gtk_widget_show(menu->tearoff_handle);
+# if GTK_CHECK_VERSION(3,0,0)
+ gtk_menu_shell_prepend(GTK_MENU_SHELL(menu->submenu_id),
+ menu->tearoff_handle);
+# else
gtk_menu_prepend(GTK_MENU(menu->submenu_id), menu->tearoff_handle);
+# endif
+# endif
}
static void
@@ -494,7 +699,17 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)
if (menu_is_separator(menu->name))
{
+# if GTK_CHECK_VERSION(3,0,0)
+ GtkToolItem *item = gtk_separator_tool_item_new();
+ gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(item),
+ TRUE);
+ gtk_tool_item_set_expand(GTK_TOOL_ITEM(item), FALSE);
+ gtk_widget_show(GTK_WIDGET(item));
+
+ gtk_toolbar_insert(toolbar, item, idx);
+# else
gtk_toolbar_insert_space(toolbar, idx);
+# endif
menu->id = NULL;
}
else
@@ -509,6 +724,24 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)
* a nasty GTK error message, skip the tooltip. */
CONVERT_TO_UTF8_FREE(tooltip);
+# if GTK_CHECK_VERSION(3,0,0)
+ {
+ GtkWidget *icon;
+ GtkToolItem *item;
+
+ icon = create_menu_icon(menu,
+ gtk_toolbar_get_icon_size(toolbar));
+ item = gtk_tool_button_new(icon, (const gchar *)text);
+ gtk_tool_item_set_tooltip_text(item, (const gchar *)tooltip);
+ g_signal_connect(G_OBJECT(item), "clicked",
+ G_CALLBACK(&menu_item_activate), menu);
+ gtk_widget_show_all(GTK_WIDGET(item));
+
+ gtk_toolbar_insert(toolbar, item, idx);
+
+ menu->id = GTK_WIDGET(item);
+ }
+# else
menu->id = gtk_toolbar_insert_item(
toolbar,
(const char *)text,
@@ -518,10 +751,16 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)
G_CALLBACK(&menu_item_activate),
menu,
idx);
+# endif
if (gtk_socket_id != 0)
+# if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(menu->id), "focus-in-event",
+ G_CALLBACK(toolbar_button_focus_in_event), NULL);
+# else
gtk_signal_connect(GTK_OBJECT(menu->id), "focus_in_event",
GTK_SIGNAL_FUNC(toolbar_button_focus_in_event), NULL);
+# endif
CONVERT_TO_UTF8_FREE(text);
CONVERT_TO_UTF8_FREE(tooltip);
@@ -545,7 +784,12 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)
menu->id = gtk_menu_item_new();
gtk_widget_set_sensitive(menu->id, FALSE);
gtk_widget_show(menu->id);
+# if GTK_CHECK_VERSION(3,0,0)
+ gtk_menu_shell_insert(GTK_MENU_SHELL(parent->submenu_id),
+ menu->id, idx);
+# else
gtk_menu_insert(GTK_MENU(parent->submenu_id), menu->id, idx);
+# endif
return;
}
@@ -553,11 +797,21 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)
/* Add textual menu item. */
menu_item_new(menu, parent->submenu_id);
gtk_widget_show(menu->id);
+# if GTK_CHECK_VERSION(3,0,0)
+ gtk_menu_shell_insert(GTK_MENU_SHELL(parent->submenu_id),
+ menu->id, idx);
+# else
gtk_menu_insert(GTK_MENU(parent->submenu_id), menu->id, idx);
+# endif
if (menu->id != NULL)
+# if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(menu->id), "activate",
+ G_CALLBACK(menu_item_activate), menu);
+# else
gtk_signal_connect(GTK_OBJECT(menu->id), "activate",
GTK_SIGNAL_FUNC(menu_item_activate), menu);
+# endif
}
}
#endif /* FEAT_MENU */
@@ -592,6 +846,7 @@ gui_gtk_set_mnemonics(int enable)
}
}
+# if !GTK_CHECK_VERSION(3,4,0)
static void
recurse_tearoffs(vimmenu_T *menu, int val)
{
@@ -608,12 +863,21 @@ recurse_tearoffs(vimmenu_T *menu, int val)
recurse_tearoffs(menu->children, val);
}
}
+# endif
+# if GTK_CHECK_VERSION(3,4,0)
+ void
+gui_mch_toggle_tearoffs(int enable UNUSED)
+{
+ /* Do nothing */
+}
+# else
void
gui_mch_toggle_tearoffs(int enable)
{
recurse_tearoffs(root_menu, enable);
}
+# endif
#endif /* FEAT_MENU */
#if defined(FEAT_TOOLBAR)
@@ -644,10 +908,15 @@ gui_mch_menu_set_tip(vimmenu_T *menu)
char_u *tooltip;
tooltip = CONVERT_TO_UTF8(menu->strings[MENU_INDEX_TIP]);
- if (tooltip == NULL || utf_valid_string(tooltip, NULL))
+ if (tooltip != NULL && utf_valid_string(tooltip, NULL))
+# if GTK_CHECK_VERSION(3,0,0)
/* Only set the tooltip when it's valid utf-8. */
- gtk_tooltips_set_tip(GTK_TOOLBAR(gui.toolbar)->tooltips,
- menu->id, (const char *)tooltip, NULL);
+ gtk_widget_set_tooltip_text(menu->id, (const gchar *)tooltip);
+# else
+ /* Only set the tooltip when it's valid utf-8. */
+ gtk_tooltips_set_tip(GTK_TOOLBAR(gui.toolbar)->tooltips,
+ menu->id, (const char *)tooltip, NULL);
+# endif
CONVERT_TO_UTF8_FREE(tooltip);
}
}
@@ -676,8 +945,20 @@ gui_mch_destroy_menu(vimmenu_T *menu)
if (menu->parent != NULL && menu_is_toolbar(menu->parent->name))
{
if (menu_is_separator(menu->name))
+# if GTK_CHECK_VERSION(3,0,0)
+ {
+ GtkToolItem *item = NULL;
+
+ item = gtk_toolbar_get_nth_item(GTK_TOOLBAR(gui.toolbar),
+ get_menu_position(menu));
+ if (item != NULL)
+ gtk_container_remove(GTK_CONTAINER(gui.toolbar),
+ GTK_WIDGET(item));
+ }
+# else
gtk_toolbar_remove_space(GTK_TOOLBAR(gui.toolbar),
get_menu_position(menu));
+# endif
else if (menu->id != NULL)
gtk_widget_destroy(menu->id);
}
@@ -711,18 +992,42 @@ gui_mch_set_scrollbar_thumb(scrollbar_T *sb, long val, long size, long max)
adjustment = gtk_range_get_adjustment(GTK_RANGE(sb->id));
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_adjustment_set_lower(adjustment, 0.0);
+ gtk_adjustment_set_value(adjustment, val);
+ gtk_adjustment_set_upper(adjustment, max + 1);
+ gtk_adjustment_set_page_size(adjustment, size);
+ gtk_adjustment_set_page_increment(adjustment,
+ size < 3L ? 1L : size - 2L);
+ gtk_adjustment_set_step_increment(adjustment, 1.0);
+#else
adjustment->lower = 0.0;
adjustment->value = val;
adjustment->upper = max + 1;
adjustment->page_size = size;
adjustment->page_increment = size < 3L ? 1L : size - 2L;
adjustment->step_increment = 1.0;
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_handler_block(G_OBJECT(adjustment),
+ (gulong)sb->handler_id);
+#else
g_signal_handler_block(GTK_OBJECT(adjustment),
(gulong)sb->handler_id);
+#endif
+
+#if !GTK_CHECK_VERSION(3,18,0)
gtk_adjustment_changed(adjustment);
+#endif
+
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_handler_unblock(G_OBJECT(adjustment),
+ (gulong)sb->handler_id);
+#else
g_signal_handler_unblock(GTK_OBJECT(adjustment),
(gulong)sb->handler_id);
+#endif
}
}
@@ -750,7 +1055,12 @@ adjustment_value_changed(GtkAdjustment *adjustment, gpointer data)
#endif
sb = gui_find_scrollbar((long)data);
+#if GTK_CHECK_VERSION(3,0,0)
+ value = gtk_adjustment_get_value(adjustment);
+#else
value = (long)adjustment->value;
+#endif
+#if !GTK_CHECK_VERSION(3,0,0)
/*
* The dragging argument must be right for the scrollbar to work with
* closed folds. This isn't documented, hopefully this will keep on
@@ -793,7 +1103,7 @@ adjustment_value_changed(GtkAdjustment *adjustment, gpointer data)
}
}
}
-
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
gui_drag_scrollbar(sb, value, dragging);
}
@@ -802,23 +1112,42 @@ adjustment_value_changed(GtkAdjustment *adjustment, gpointer data)
gui_mch_create_scrollbar(scrollbar_T *sb, int orient)
{
if (orient == SBAR_HORIZ)
+#if GTK_CHECK_VERSION(3,2,0)
+ sb->id = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, NULL);
+#else
sb->id = gtk_hscrollbar_new(NULL);
+#endif
else if (orient == SBAR_VERT)
+#if GTK_CHECK_VERSION(3,2,0)
+ sb->id = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, NULL);
+#else
sb->id = gtk_vscrollbar_new(NULL);
+#endif
if (sb->id != NULL)
{
GtkAdjustment *adjustment;
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_can_focus(sb->id, FALSE);
+#else
GTK_WIDGET_UNSET_FLAGS(sb->id, GTK_CAN_FOCUS);
+#endif
gtk_form_put(GTK_FORM(gui.formwin), sb->id, 0, 0);
adjustment = gtk_range_get_adjustment(GTK_RANGE(sb->id));
+#if GTK_CHECK_VERSION(3,0,0)
+ sb->handler_id = g_signal_connect(
+ G_OBJECT(adjustment), "value-changed",
+ G_CALLBACK(adjustment_value_changed),
+ GINT_TO_POINTER(sb->ident));
+#else
sb->handler_id = gtk_signal_connect(
GTK_OBJECT(adjustment), "value_changed",
GTK_SIGNAL_FUNC(adjustment_value_changed),
GINT_TO_POINTER(sb->ident));
+#endif
gui_mch_update();
}
}
@@ -932,8 +1261,13 @@ gui_mch_browse(int saving UNUSED,
GTK_WINDOW(gui.mainwin),
saving ? GTK_FILE_CHOOSER_ACTION_SAVE
: GTK_FILE_CHOOSER_ACTION_OPEN,
+# if GTK_CHECK_VERSION(3,10,0)
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ saving ? _("_Save") : _("_Open"), GTK_RESPONSE_ACCEPT,
+# else
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
saving ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+# endif
NULL);
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fc),
(const gchar *)dirbuf);
@@ -991,7 +1325,7 @@ gui_mch_browse(int saving UNUSED,
}
gtk_widget_destroy(GTK_WIDGET(fc));
-#else
+#else /* !USE_FILE_CHOOSER */
if (gui.filedlg == NULL)
{
@@ -1027,7 +1361,7 @@ gui_mch_browse(int saving UNUSED,
gtk_widget_show(gui.filedlg);
gtk_main();
-#endif
+#endif /* !USE_FILE_CHOOSER */
g_log_remove_handler(domain, log_handler);
CONVERT_TO_UTF8_FREE(title);
@@ -1062,8 +1396,13 @@ gui_mch_browsedir(
(const gchar *)title,
GTK_WINDOW(gui.mainwin),
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+# if GTK_CHECK_VERSION(3,10,0)
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_OK"), GTK_RESPONSE_ACCEPT,
+# else
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+# endif
NULL);
CONVERT_TO_UTF8_FREE(title);
@@ -1096,10 +1435,10 @@ gui_mch_browsedir(
g_free(dirname);
return p;
-# else
+# else /* !defined(GTK_FILE_CHOOSER) */
/* For GTK 2.2 and earlier: fall back to ordinary file selector. */
return gui_mch_browse(0, title, NULL, NULL, initdir, NULL);
-# endif
+# endif /* !defined(GTK_FILE_CHOOSER) */
}
@@ -1266,6 +1605,11 @@ dialog_add_buttons(GtkDialog *dialog, char_u *button_string)
/* Check 'v' flag in 'guioptions': vertical button placement. */
if (vim_strchr(p_go, GO_VERTICAL) != NULL)
{
+# if GTK_CHECK_VERSION(3,0,0)
+ /* Add GTK+ 3 code if necessary. */
+ /* N.B. GTK+ 3 doesn't allow you to access vbox and action_area via
+ * the C API. */
+# else
GtkWidget *vbutton_box;
vbutton_box = gtk_vbutton_box_new();
@@ -1274,6 +1618,7 @@ dialog_add_buttons(GtkDialog *dialog, char_u *button_string)
vbutton_box, TRUE, FALSE, 0);
/* Overrule the "action_area" value, hopefully this works... */
GTK_DIALOG(dialog)->action_area = vbutton_box;
+# endif
}
/*
@@ -1308,6 +1653,16 @@ dialog_add_buttons(GtkDialog *dialog, char_u *button_string)
*/
if (ok != NULL && ync != NULL) /* almost impossible to fail */
{
+# if GTK_CHECK_VERSION(3,10,0)
+ if (button_equal(label, ok[0])) label = _("OK");
+ else if (button_equal(label, ync[0])) label = _("Yes");
+ else if (button_equal(label, ync[1])) label = _("No");
+ else if (button_equal(label, ync[2])) label = _("Cancel");
+ else if (button_equal(label, "Ok")) label = _("OK");
+ else if (button_equal(label, "Yes")) label = _("Yes");
+ else if (button_equal(label, "No")) label = _("No");
+ else if (button_equal(label, "Cancel")) label = _("Canccl");
+# else
if (button_equal(label, ok[0])) label = GTK_STOCK_OK;
else if (button_equal(label, ync[0])) label = GTK_STOCK_YES;
else if (button_equal(label, ync[1])) label = GTK_STOCK_NO;
@@ -1316,6 +1671,7 @@ dialog_add_buttons(GtkDialog *dialog, char_u *button_string)
else if (button_equal(label, "Yes")) label = GTK_STOCK_YES;
else if (button_equal(label, "No")) label = GTK_STOCK_NO;
else if (button_equal(label, "Cancel")) label = GTK_STOCK_CANCEL;
+# endif
}
label8 = CONVERT_TO_UTF8((char_u *)label);
gtk_dialog_add_button(dialog, (const gchar *)label8, idx);
@@ -1408,14 +1764,32 @@ gui_mch_dialog(int type, /* type of dialog */
gtk_entry_set_text(GTK_ENTRY(entry), (const char *)text);
CONVERT_TO_UTF8_FREE(text);
+# if GTK_CHECK_VERSION(3,14,0)
+ gtk_widget_set_halign(GTK_WIDGET(entry), GTK_ALIGN_CENTER);
+ gtk_widget_set_valign(GTK_WIDGET(entry), GTK_ALIGN_CENTER);
+ gtk_widget_set_hexpand(GTK_WIDGET(entry), TRUE);
+ gtk_widget_set_vexpand(GTK_WIDGET(entry), TRUE);
+
+ alignment = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+# else
alignment = gtk_alignment_new((float)0.5, (float)0.5,
(float)1.0, (float)1.0);
+# endif
gtk_container_add(GTK_CONTAINER(alignment), entry);
gtk_container_set_border_width(GTK_CONTAINER(alignment), 5);
gtk_widget_show(alignment);
+# if GTK_CHECK_VERSION(3,0,0)
+ {
+ GtkWidget * const vbox
+ = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_box_pack_start(GTK_BOX(vbox),
+ alignment, TRUE, FALSE, 0);
+ }
+# else
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
alignment, TRUE, FALSE, 0);
+# endif
dialoginfo.noalt = FALSE;
}
else
@@ -1473,6 +1847,7 @@ gui_mch_show_popupmenu(vimmenu_T *menu)
* Append a submenu for selecting an input method. This is
* currently the only way to switch input methods at runtime.
*/
+# if !GTK_CHECK_VERSION(3,10,0)
if (xic != NULL && g_object_get_data(G_OBJECT(menu->submenu_id),
"vim-has-im-menu") == NULL)
{
@@ -1499,6 +1874,7 @@ gui_mch_show_popupmenu(vimmenu_T *menu)
g_object_set_data(G_OBJECT(menu->submenu_id),
"vim-has-im-menu", GINT_TO_POINTER(TRUE));
}
+# endif
# endif /* FEAT_XIM */
gtk_menu_popup(GTK_MENU(menu->submenu_id),
@@ -1524,7 +1900,11 @@ popup_menu_position_func(GtkMenu *menu UNUSED,
gboolean *push_in UNUSED,
gpointer user_data UNUSED)
{
+# if GTK_CHECK_VERSION(3,0,0)
+ gdk_window_get_origin(gtk_widget_get_window(gui.drawarea), x, y);
+# else
gdk_window_get_origin(gui.drawarea->window, x, y);
+# endif
if (popup_mouse_pos)
{
@@ -1534,7 +1914,12 @@ popup_menu_position_func(GtkMenu *menu UNUSED,
*x += mx;
*y += my;
}
+# if GTK_CHECK_VERSION(3,0,0)
+ else if (curwin != NULL && gui.drawarea != NULL &&
+ gtk_widget_get_window(gui.drawarea) != NULL)
+# else
else if (curwin != NULL && gui.drawarea != NULL && gui.drawarea->window != NULL)
+# endif
{
/* Find the cursor position in the current window */
*x += FILL_X(W_WINCOL(curwin) + curwin->w_wcol + 1) + 1;
@@ -1612,7 +1997,13 @@ find_key_press_event(
}
static GtkWidget *
-create_image_button(const char *stock_id, const char *label)
+#if GTK_CHECK_VERSION(3,10,0)
+create_image_button(const char *stock_id UNUSED,
+ const char *label)
+#else
+create_image_button(const char *stock_id,
+ const char *label)
+#endif
{
char_u *text;
GtkWidget *box;
@@ -1621,18 +2012,35 @@ create_image_button(const char *stock_id, const char *label)
text = CONVERT_TO_UTF8((char_u *)label);
+#if GTK_CHECK_VERSION(3,2,0)
+ box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 3);
+ gtk_box_set_homogeneous(GTK_BOX(box), FALSE);
+#else
box = gtk_hbox_new(FALSE, 3);
- gtk_box_pack_start(GTK_BOX(box),
- gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_BUTTON),
- FALSE, FALSE, 0);
+#endif
+#if !GTK_CHECK_VERSION(3,10,0)
+ if (stock_id != NULL)
+ gtk_box_pack_start(GTK_BOX(box),
+ gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_BUTTON),
+ FALSE, FALSE, 0);
+#endif
gtk_box_pack_start(GTK_BOX(box),
gtk_label_new((const char *)text),
FALSE, FALSE, 0);
CONVERT_TO_UTF8_FREE(text);
+#if GTK_CHECK_VERSION(3,14,0)
+ gtk_widget_set_halign(GTK_WIDGET(box), GTK_ALIGN_CENTER);
+ gtk_widget_set_valign(GTK_WIDGET(box), GTK_ALIGN_CENTER);
+ gtk_widget_set_hexpand(GTK_WIDGET(box), TRUE);
+ gtk_widget_set_vexpand(GTK_WIDGET(box), TRUE);
+
+ alignment = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+#else
alignment = gtk_alignment_new((float)0.5, (float)0.5,
(float)0.0, (float)0.0);
+#endif
gtk_container_add(GTK_CONTAINER(alignment), box);
gtk_widget_show_all(alignment);
@@ -1695,10 +2103,17 @@ find_replace_dialog_create(char_u *arg, int do_replace)
if (entry_text != NULL)
{
gtk_entry_set_text(GTK_ENTRY(frdp->what), (char *)entry_text);
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(frdp->wword),
+ (gboolean)wword);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(frdp->mcase),
+ (gboolean)mcase);
+#else
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(frdp->wword),
(gboolean)wword);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(frdp->mcase),
(gboolean)mcase);
+#endif
}
gtk_window_present(GTK_WINDOW(frdp->dialog));
vim_free(entry_text);
@@ -1706,7 +2121,11 @@ find_replace_dialog_create(char_u *arg, int do_replace)
}
frdp->dialog = gtk_dialog_new();
+#if GTK_CHECK_VERSION(3,0,0)
+ /* Nothing equivalent to gtk_dialog_set_has_separator() in GTK+ 3. */
+#else
gtk_dialog_set_has_separator(GTK_DIALOG(frdp->dialog), FALSE);
+#endif
gtk_window_set_transient_for(GTK_WINDOW(frdp->dialog), GTK_WINDOW(gui.mainwin));
gtk_window_set_destroy_with_parent(GTK_WINDOW(frdp->dialog), TRUE);
@@ -1721,164 +2140,402 @@ find_replace_dialog_create(char_u *arg, int do_replace)
CONV(_("VIM - Search...")));
}
+#if GTK_CHECK_VERSION(3,2,0)
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_box_set_homogeneous(GTK_BOX(hbox), FALSE);
+#else
hbox = gtk_hbox_new(FALSE, 0);
+#endif
gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);
+#if GTK_CHECK_VERSION(3,0,0)
+ {
+ GtkWidget * const dialog_vbox
+ = gtk_dialog_get_content_area(GTK_DIALOG(frdp->dialog));
+ gtk_container_add(GTK_CONTAINER(dialog_vbox), hbox);
+ }
+#else
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(frdp->dialog)->vbox), hbox);
+#endif
if (do_replace)
+#if GTK_CHECK_VERSION(3,4,0)
+ table = gtk_grid_new();
+#else
table = gtk_table_new(1024, 4, FALSE);
+#endif
else
+#if GTK_CHECK_VERSION(3,4,0)
+ table = gtk_grid_new();
+#else
table = gtk_table_new(1024, 3, FALSE);
+#endif
gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, TRUE, 0);
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_container_set_border_width(GTK_CONTAINER(table), 4);
+#else
gtk_container_border_width(GTK_CONTAINER(table), 4);
+#endif
tmp = gtk_label_new(CONV(_("Find what:")));
+#if GTK_CHECK_VERSION(3,16,0)
+ gtk_label_set_xalign(GTK_LABEL(tmp), 0.0);
+ gtk_label_set_yalign(GTK_LABEL(tmp), 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.0);
+ g_object_set_property(G_OBJECT(tmp), "xalign", &align_val);
+
+ g_value_set_float(&align_val, 0.5);
+ g_object_set_property(G_OBJECT(tmp), "yalign", &align_val);
+
+ g_value_unset(&align_val);
+ }
+#else
gtk_misc_set_alignment(GTK_MISC(tmp), (gfloat)0.0, (gfloat)0.5);
+#endif
+#if GTK_CHECK_VERSION(3,4,0)
+ gtk_grid_attach(GTK_GRID(table), tmp, 0, 0, 2, 1);
+#else
gtk_table_attach(GTK_TABLE(table), tmp, 0, 1, 0, 1,
GTK_FILL, GTK_EXPAND, 2, 2);
+#endif
frdp->what = gtk_entry_new();
sensitive = (entry_text != NULL && entry_text[0] != NUL);
if (entry_text != NULL)
gtk_entry_set_text(GTK_ENTRY(frdp->what), (char *)entry_text);
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(frdp->what), "changed",
+ G_CALLBACK(entry_changed_cb), frdp->dialog);
+ g_signal_connect_after(G_OBJECT(frdp->what), "key-press-event",
+ G_CALLBACK(find_key_press_event),
+ (gpointer) frdp);
+#else
gtk_signal_connect(GTK_OBJECT(frdp->what), "changed",
GTK_SIGNAL_FUNC(entry_changed_cb), frdp->dialog);
gtk_signal_connect_after(GTK_OBJECT(frdp->what), "key_press_event",
GTK_SIGNAL_FUNC(find_key_press_event),
(gpointer) frdp);
+#endif
+#if GTK_CHECK_VERSION(3,4,0)
+ gtk_grid_attach(GTK_GRID(table), frdp->what, 2, 0, 5, 1);
+#else
gtk_table_attach(GTK_TABLE(table), frdp->what, 1, 1024, 0, 1,
GTK_EXPAND | GTK_FILL, GTK_EXPAND, 2, 2);
+#endif
if (do_replace)
{
tmp = gtk_label_new(CONV(_("Replace with:")));
+#if GTK_CHECK_VERSION(3,16,0)
+ gtk_label_set_xalign(GTK_LABEL(tmp), 0.0);
+ gtk_label_set_yalign(GTK_LABEL(tmp), 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.0);
+ g_object_set_property(G_OBJECT(tmp), "xalign", &align_val);
+
+ g_value_set_float(&align_val, 0.5);
+ g_object_set_property(G_OBJECT(tmp), "yalign", &align_val);
+
+ g_value_unset(&align_val);
+ }
+#else
gtk_misc_set_alignment(GTK_MISC(tmp), (gfloat)0.0, (gfloat)0.5);
+#endif
+#if GTK_CHECK_VERSION(3,4,0)
+ gtk_grid_attach(GTK_GRID(table), tmp, 0, 1, 2, 1);
+#else
gtk_table_attach(GTK_TABLE(table), tmp, 0, 1, 1, 2,
GTK_FILL, GTK_EXPAND, 2, 2);
+#endif
frdp->with = gtk_entry_new();
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(frdp->with), "activate",
+ G_CALLBACK(find_replace_cb),
+ GINT_TO_POINTER(FRD_R_FINDNEXT));
+ g_signal_connect_after(G_OBJECT(frdp->with), "key-press-event",
+ G_CALLBACK(find_key_press_event),
+ (gpointer) frdp);
+#else
gtk_signal_connect(GTK_OBJECT(frdp->with), "activate",
GTK_SIGNAL_FUNC(find_replace_cb),
GINT_TO_POINTER(FRD_R_FINDNEXT));
gtk_signal_connect_after(GTK_OBJECT(frdp->with), "key_press_event",
GTK_SIGNAL_FUNC(find_key_press_event),
(gpointer) frdp);
+#endif
+#if GTK_CHECK_VERSION(3,4,0)
+ gtk_grid_attach(GTK_GRID(table), frdp->with, 2, 1, 5, 1);
+#else
gtk_table_attach(GTK_TABLE(table), frdp->with, 1, 1024, 1, 2,
GTK_EXPAND | GTK_FILL, GTK_EXPAND, 2, 2);
+#endif
/*
* Make the entry activation only change the input focus onto the
* with item.
*/
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(frdp->what), "activate",
+ G_CALLBACK(entry_activate_cb), frdp->with);
+#else
gtk_signal_connect(GTK_OBJECT(frdp->what), "activate",
GTK_SIGNAL_FUNC(entry_activate_cb), frdp->with);
+#endif
}
else
{
/*
* Make the entry activation do the search.
*/
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(frdp->what), "activate",
+ G_CALLBACK(find_replace_cb),
+ GINT_TO_POINTER(FRD_FINDNEXT));
+#else
gtk_signal_connect(GTK_OBJECT(frdp->what), "activate",
GTK_SIGNAL_FUNC(find_replace_cb),
GINT_TO_POINTER(FRD_FINDNEXT));
+#endif
}
/* whole word only button */
frdp->wword = gtk_check_button_new_with_label(CONV(_("Match whole word only")));
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(frdp->wword),
+ (gboolean)wword);
+#else
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(frdp->wword),
(gboolean)wword);
+#endif
if (do_replace)
+#if GTK_CHECK_VERSION(3,4,0)
+ gtk_grid_attach(GTK_GRID(table), frdp->wword, 0, 2, 5, 1);
+#else
gtk_table_attach(GTK_TABLE(table), frdp->wword, 0, 1023, 2, 3,
GTK_FILL, GTK_EXPAND, 2, 2);
+#endif
else
+#if GTK_CHECK_VERSION(3,4,0)
+ gtk_grid_attach(GTK_GRID(table), frdp->wword, 0, 3, 5, 1);
+#else
gtk_table_attach(GTK_TABLE(table), frdp->wword, 0, 1023, 1, 2,
GTK_FILL, GTK_EXPAND, 2, 2);
+#endif
/* match case button */
frdp->mcase = gtk_check_button_new_with_label(CONV(_("Match case")));
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(frdp->mcase),
+ (gboolean)mcase);
+#else
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(frdp->mcase),
(gboolean)mcase);
+#endif
if (do_replace)
+#if GTK_CHECK_VERSION(3,4,0)
+ gtk_grid_attach(GTK_GRID(table), frdp->mcase, 0, 3, 5, 1);
+#else
gtk_table_attach(GTK_TABLE(table), frdp->mcase, 0, 1023, 3, 4,
GTK_FILL, GTK_EXPAND, 2, 2);
+#endif
else
+#if GTK_CHECK_VERSION(3,4,0)
+ gtk_grid_attach(GTK_GRID(table), frdp->mcase, 0, 4, 5, 1);
+#else
gtk_table_attach(GTK_TABLE(table), frdp->mcase, 0, 1023, 2, 3,
GTK_FILL, GTK_EXPAND, 2, 2);
+#endif
tmp = gtk_frame_new(CONV(_("Direction")));
if (do_replace)
+#if GTK_CHECK_VERSION(3,4,0)
+ gtk_grid_attach(GTK_GRID(table), tmp, 5, 2, 2, 4);
+#else
gtk_table_attach(GTK_TABLE(table), tmp, 1023, 1024, 2, 4,
GTK_FILL, GTK_FILL, 2, 2);
+#endif
else
+#if GTK_CHECK_VERSION(3,4,0)
+ gtk_grid_attach(GTK_GRID(table), tmp, 5, 2, 1, 3);
+#else
gtk_table_attach(GTK_TABLE(table), tmp, 1023, 1024, 1, 3,
GTK_FILL, GTK_FILL, 2, 2);
+#endif
+#if GTK_CHECK_VERSION(3,2,0)
+ vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_box_set_homogeneous(GTK_BOX(vbox), FALSE);
+#else
vbox = gtk_vbox_new(FALSE, 0);
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 0);
+#else
gtk_container_border_width(GTK_CONTAINER(vbox), 0);
+#endif
gtk_container_add(GTK_CONTAINER(tmp), vbox);
/* 'Up' and 'Down' buttons */
frdp->up = gtk_radio_button_new_with_label(NULL, CONV(_("Up")));
gtk_box_pack_start(GTK_BOX(vbox), frdp->up, TRUE, TRUE, 0);
+#if GTK_CHECK_VERSION(3,0,0)
+ frdp->down = gtk_radio_button_new_with_label(
+ gtk_radio_button_get_group(GTK_RADIO_BUTTON(frdp->up)),
+ CONV(_("Down")));
+#else
frdp->down = gtk_radio_button_new_with_label(
gtk_radio_button_group(GTK_RADIO_BUTTON(frdp->up)),
CONV(_("Down")));
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(frdp->down), TRUE);
+#else
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(frdp->down), TRUE);
+#endif
gtk_container_set_border_width(GTK_CONTAINER(vbox), 2);
gtk_box_pack_start(GTK_BOX(vbox), frdp->down, TRUE, TRUE, 0);
/* vbox to hold the action buttons */
+#if GTK_CHECK_VERSION(3,2,0)
+ actionarea = gtk_button_box_new(GTK_ORIENTATION_VERTICAL);
+#else
actionarea = gtk_vbutton_box_new();
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_container_set_border_width(GTK_CONTAINER(actionarea), 2);
+#else
gtk_container_border_width(GTK_CONTAINER(actionarea), 2);
+#endif
gtk_box_pack_end(GTK_BOX(hbox), actionarea, FALSE, FALSE, 0);
/* 'Find Next' button */
+#if GTK_CHECK_VERSION(3,10,0)
+ frdp->find = create_image_button(NULL, _("Find Next"));
+#else
frdp->find = create_image_button(GTK_STOCK_FIND, _("Find Next"));
+#endif
gtk_widget_set_sensitive(frdp->find, sensitive);
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(frdp->find), "clicked",
+ G_CALLBACK(find_replace_cb),
+ (do_replace) ? GINT_TO_POINTER(FRD_R_FINDNEXT)
+ : GINT_TO_POINTER(FRD_FINDNEXT));
+#else
gtk_signal_connect(GTK_OBJECT(frdp->find), "clicked",
GTK_SIGNAL_FUNC(find_replace_cb),
(do_replace) ? GINT_TO_POINTER(FRD_R_FINDNEXT)
: GINT_TO_POINTER(FRD_FINDNEXT));
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_can_default(frdp->find, TRUE);
+#else
GTK_WIDGET_SET_FLAGS(frdp->find, GTK_CAN_DEFAULT);
+#endif
gtk_box_pack_start(GTK_BOX(actionarea), frdp->find, FALSE, FALSE, 0);
gtk_widget_grab_default(frdp->find);
if (do_replace)
{
/* 'Replace' button */
+#if GTK_CHECK_VERSION(3,10,0)
+ frdp->replace = create_image_button(NULL, _("Replace"));
+#else
frdp->replace = create_image_button(GTK_STOCK_CONVERT, _("Replace"));
+#endif
gtk_widget_set_sensitive(frdp->replace, sensitive);
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_can_default(frdp->find, TRUE);
+#else
GTK_WIDGET_SET_FLAGS(frdp->replace, GTK_CAN_DEFAULT);
+#endif
gtk_box_pack_start(GTK_BOX(actionarea), frdp->replace, FALSE, FALSE, 0);
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(frdp->replace), "clicked",
+ G_CALLBACK(find_replace_cb),
+ GINT_TO_POINTER(FRD_REPLACE));
+#else
gtk_signal_connect(GTK_OBJECT(frdp->replace), "clicked",
GTK_SIGNAL_FUNC(find_replace_cb),
GINT_TO_POINTER(FRD_REPLACE));
+#endif
/* 'Replace All' button */
+#if GTK_CHECK_VERSION(3,10,0)
+ frdp->all = create_image_button(NULL, _("Replace All"));
+#else
frdp->all = create_image_button(GTK_STOCK_CONVERT, _("Replace All"));
+#endif
gtk_widget_set_sensitive(frdp->all, sensitive);
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_can_default(frdp->all, TRUE);
+#else
GTK_WIDGET_SET_FLAGS(frdp->all, GTK_CAN_DEFAULT);
+#endif
gtk_box_pack_start(GTK_BOX(actionarea), frdp->all, FALSE, FALSE, 0);
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(frdp->all), "clicked",
+ G_CALLBACK(find_replace_cb),
+ GINT_TO_POINTER(FRD_REPLACEALL));
+#else
gtk_signal_connect(GTK_OBJECT(frdp->all), "clicked",
GTK_SIGNAL_FUNC(find_replace_cb),
GINT_TO_POINTER(FRD_REPLACEALL));
+#endif
}
/* 'Cancel' button */
+#if GTK_CHECK_VERSION(3,10,0)
+ tmp = gtk_button_new_with_mnemonic(_("_Close"));
+#else
tmp = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_can_default(tmp, TRUE);
+#else
GTK_WIDGET_SET_FLAGS(tmp, GTK_CAN_DEFAULT);
+#endif
gtk_box_pack_end(GTK_BOX(actionarea), tmp, FALSE, FALSE, 0);
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect_swapped(G_OBJECT(tmp),
+ "clicked", G_CALLBACK(gtk_widget_hide),
+ G_OBJECT(frdp->dialog));
+ g_signal_connect_swapped(G_OBJECT(frdp->dialog),
+ "delete-event", G_CALLBACK(gtk_widget_hide_on_delete),
+ G_OBJECT(frdp->dialog));
+#else
gtk_signal_connect_object(GTK_OBJECT(tmp),
"clicked", GTK_SIGNAL_FUNC(gtk_widget_hide),
GTK_OBJECT(frdp->dialog));
gtk_signal_connect_object(GTK_OBJECT(frdp->dialog),
"delete_event", GTK_SIGNAL_FUNC(gtk_widget_hide_on_delete),
GTK_OBJECT(frdp->dialog));
+#endif
+#if GTK_CHECK_VERSION(3,2,0)
+ tmp = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
+#else
tmp = gtk_vseparator_new();
+#endif
gtk_box_pack_end(GTK_BOX(hbox), tmp, FALSE, FALSE, 10);
/* Suppress automatic show of the unused action area */
+#if GTK_CHECK_VERSION(3,0,0)
+# if !GTK_CHECK_VERSION(3,12,0)
+ gtk_widget_hide(gtk_dialog_get_action_area(GTK_DIALOG(frdp->dialog)));
+# endif
+#else
gtk_widget_hide(GTK_DIALOG(frdp->dialog)->action_area);
+#endif
gtk_widget_show_all(hbox);
gtk_widget_show(frdp->dialog);
@@ -1928,11 +2585,23 @@ find_replace_cb(GtkWidget *widget UNUSED, gpointer data)
}
find_text = (char_u *)gtk_entry_get_text(GTK_ENTRY(sfr->what));
+#if GTK_CHECK_VERSION(3,0,0)
+ direction_down = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sfr->down));
+#else
direction_down = GTK_TOGGLE_BUTTON(sfr->down)->active;
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sfr->wword)))
+#else
if (GTK_TOGGLE_BUTTON(sfr->wword)->active)
+#endif
flags |= FRD_WHOLE_WORD;
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sfr->mcase)))
+#else
if (GTK_TOGGLE_BUTTON(sfr->mcase)->active)
+#endif
flags |= FRD_MATCH_CASE;
repl_text = CONVERT_FROM_UTF8(repl_text);
diff --git a/src/gui_gtk_f.c b/src/gui_gtk_f.c
index 0eb50652c..838a4ca8f 100644
--- a/src/gui_gtk_f.c
+++ b/src/gui_gtk_f.c
@@ -19,13 +19,19 @@
* children at arbitrary positions width arbitrary sizes. This finally puts
* an end on our resize problems with which we where struggling for such a
* long time.
+ *
+ * Support for GTK+ 3 was added by:
+ *
+ * 2016 Kazunobu Kuriyama <kazunobu.kuriyama@gmail.com>
*/
#include "vim.h"
#include <gtk/gtk.h> /* without this it compiles, but gives errors at
runtime! */
#include "gui_gtk_f.h"
-#include <gtk/gtksignal.h>
+#if !GTK_CHECK_VERSION(3,0,0)
+# include <gtk/gtksignal.h>
+#endif
#ifdef WIN3264
# include <gdk/gdkwin32.h>
#else
@@ -52,10 +58,23 @@ static void gtk_form_unrealize(GtkWidget *widget);
static void gtk_form_map(GtkWidget *widget);
static void gtk_form_size_request(GtkWidget *widget,
GtkRequisition *requisition);
+#if GTK_CHECK_VERSION(3,0,0)
+static void gtk_form_get_preferred_width(GtkWidget *widget,
+ gint *minimal_width,
+ gint *natural_width);
+static void gtk_form_get_preferred_height(GtkWidget *widget,
+ gint *minimal_height,
+ gint *natural_height);
+#endif
static void gtk_form_size_allocate(GtkWidget *widget,
GtkAllocation *allocation);
+#if GTK_CHECK_VERSION(3,0,0)
+static gboolean gtk_form_draw(GtkWidget *widget,
+ cairo_t *cr);
+#else
static gint gtk_form_expose(GtkWidget *widget,
GdkEventExpose *event);
+#endif
static void gtk_form_remove(GtkContainer *container,
GtkWidget *widget);
@@ -73,22 +92,27 @@ static void gtk_form_position_child(GtkForm *form,
gboolean force_allocate);
static void gtk_form_position_children(GtkForm *form);
+#if !GTK_CHECK_VERSION(3,0,0)
static GdkFilterReturn gtk_form_filter(GdkXEvent *gdk_xevent,
GdkEvent *event,
gpointer data);
static GdkFilterReturn gtk_form_main_filter(GdkXEvent *gdk_xevent,
GdkEvent *event,
gpointer data);
-
+#endif
+#if !GTK_CHECK_VERSION(3,16,0)
static void gtk_form_set_static_gravity(GdkWindow *window,
gboolean use_static);
+#endif
static void gtk_form_send_configure(GtkForm *form);
static void gtk_form_child_map(GtkWidget *widget, gpointer user_data);
static void gtk_form_child_unmap(GtkWidget *widget, gpointer user_data);
+#if !GTK_CHECK_VERSION(3,0,0)
static GtkWidgetClass *parent_class = NULL;
+#endif
/* Public interface
*/
@@ -98,7 +122,11 @@ gtk_form_new(void)
{
GtkForm *form;
+#if GTK_CHECK_VERSION(3,0,0)
+ form = g_object_new(GTK_TYPE_FORM, NULL);
+#else
form = gtk_type_new(gtk_form_get_type());
+#endif
return GTK_WIDGET(form);
}
@@ -120,8 +148,12 @@ gtk_form_put(GtkForm *form,
child->window = NULL;
child->x = x;
child->y = y;
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_size_request(child->widget, -1, -1);
+#else
child->widget->requisition.width = 0;
child->widget->requisition.height = 0;
+#endif
child->mapped = FALSE;
form->children = g_list_append(form->children, child);
@@ -131,13 +163,24 @@ gtk_form_put(GtkForm *form,
* that gtk_widget_set_parent() realizes the widget if it's visible
* and its parent is mapped.
*/
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_realized(GTK_WIDGET(form)))
+#else
if (GTK_WIDGET_REALIZED(form))
+#endif
gtk_form_attach_child_window(form, child);
gtk_widget_set_parent(child_widget, GTK_WIDGET(form));
+#if !GTK_CHECK_VERSION(3,0,0)
gtk_widget_size_request(child->widget, NULL);
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_realized(GTK_WIDGET(form))
+ && !gtk_widget_get_realized(child_widget))
+#else
if (GTK_WIDGET_REALIZED(form) && !GTK_WIDGET_REALIZED(child_widget))
+#endif
gtk_form_realize_child(form, child);
gtk_form_position_child(form, child, TRUE);
@@ -193,6 +236,9 @@ gtk_form_thaw(GtkForm *form)
/* Basic Object handling procedures
*/
+#if GTK_CHECK_VERSION(3,0,0)
+G_DEFINE_TYPE(GtkForm, gtk_form, GTK_TYPE_CONTAINER)
+#else
GtkType
gtk_form_get_type(void)
{
@@ -213,6 +259,7 @@ gtk_form_get_type(void)
}
return form_type;
}
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
static void
gtk_form_class_init(GtkFormClass *klass)
@@ -223,14 +270,25 @@ gtk_form_class_init(GtkFormClass *klass)
widget_class = (GtkWidgetClass *) klass;
container_class = (GtkContainerClass *) klass;
+#if !GTK_CHECK_VERSION(3,0,0)
parent_class = gtk_type_class(gtk_container_get_type());
+#endif
widget_class->realize = gtk_form_realize;
widget_class->unrealize = gtk_form_unrealize;
widget_class->map = gtk_form_map;
+#if GTK_CHECK_VERSION(3,0,0)
+ widget_class->get_preferred_width = gtk_form_get_preferred_width;
+ widget_class->get_preferred_height = gtk_form_get_preferred_height;
+#else
widget_class->size_request = gtk_form_size_request;
+#endif
widget_class->size_allocate = gtk_form_size_allocate;
+#if GTK_CHECK_VERSION(3,0,0)
+ widget_class->draw = gtk_form_draw;
+#else
widget_class->expose_event = gtk_form_expose;
+#endif
container_class->remove = gtk_form_remove;
container_class->forall = gtk_form_forall;
@@ -239,15 +297,22 @@ gtk_form_class_init(GtkFormClass *klass)
static void
gtk_form_init(GtkForm *form)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_has_window(GTK_WIDGET(form), TRUE);
+#endif
form->children = NULL;
+#if !GTK_CHECK_VERSION(3,0,0)
form->width = 1;
form->height = 1;
+#endif
form->bin_window = NULL;
+#if !GTK_CHECK_VERSION(3,0,0)
form->configure_serial = 0;
form->visibility = GDK_VISIBILITY_PARTIAL;
+#endif
form->freeze_count = 0;
}
@@ -267,40 +332,92 @@ gtk_form_realize(GtkWidget *widget)
g_return_if_fail(GTK_IS_FORM(widget));
form = GTK_FORM(widget);
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_realized(widget, TRUE);
+#else
GTK_WIDGET_SET_FLAGS(form, GTK_REALIZED);
+#endif
attributes.window_type = GDK_WINDOW_CHILD;
+#if GTK_CHECK_VERSION(3,0,0)
+ {
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(widget, &allocation);
+ attributes.x = allocation.x;
+ attributes.y = allocation.y;
+ attributes.width = allocation.width;
+ attributes.height = allocation.height;
+ }
+#else
attributes.x = widget->allocation.x;
attributes.y = widget->allocation.y;
attributes.width = widget->allocation.width;
attributes.height = widget->allocation.height;
+#endif
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.visual = gtk_widget_get_visual(widget);
+#if GTK_CHECK_VERSION(3,0,0)
+ attributes.event_mask = GDK_EXPOSURE_MASK;
+#else
attributes.colormap = gtk_widget_get_colormap(widget);
attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+#else
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_window(widget,
+ gdk_window_new(gtk_widget_get_parent_window(widget),
+ &attributes, attributes_mask));
+ gdk_window_set_user_data(gtk_widget_get_window(widget), widget);
+#else
widget->window = gdk_window_new(gtk_widget_get_parent_window(widget),
&attributes, attributes_mask);
gdk_window_set_user_data(widget->window, widget);
+#endif
attributes.x = 0;
attributes.y = 0;
attributes.event_mask = gtk_widget_get_events(widget);
+#if GTK_CHECK_VERSION(3,0,0)
+ form->bin_window = gdk_window_new(gtk_widget_get_window(widget),
+ &attributes, attributes_mask);
+#else
form->bin_window = gdk_window_new(widget->window,
&attributes, attributes_mask);
+#endif
gdk_window_set_user_data(form->bin_window, widget);
+#if !GTK_CHECK_VERSION(3,16,0)
gtk_form_set_static_gravity(form->bin_window, TRUE);
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ {
+ GtkStyleContext * const sctx = gtk_widget_get_style_context(widget);
+
+ gtk_style_context_add_class(sctx, "gtk-form");
+ gtk_style_context_set_state(sctx, GTK_STATE_FLAG_NORMAL);
+# if !GTK_CHECK_VERSION(3,18,0)
+ gtk_style_context_set_background(sctx, gtk_widget_get_window(widget));
+ gtk_style_context_set_background(sctx, form->bin_window);
+# endif
+ }
+#else
widget->style = gtk_style_attach(widget->style, widget->window);
gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL);
gtk_style_set_background(widget->style, form->bin_window, GTK_STATE_NORMAL);
+#endif
+#if !GTK_CHECK_VERSION(3,0,0)
gdk_window_add_filter(widget->window, gtk_form_main_filter, form);
gdk_window_add_filter(form->bin_window, gtk_form_filter, form);
+#endif
for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
{
@@ -308,7 +425,11 @@ gtk_form_realize(GtkWidget *widget)
gtk_form_attach_child_window(form, child);
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_visible(child->widget))
+#else
if (GTK_WIDGET_VISIBLE(child->widget))
+#endif
gtk_form_realize_child(form, child);
}
}
@@ -332,17 +453,30 @@ gtk_form_map(GtkWidget *widget)
form = GTK_FORM(widget);
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_mapped(widget, TRUE);
+#else
GTK_WIDGET_SET_FLAGS(widget, GTK_MAPPED);
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ gdk_window_show(gtk_widget_get_window(widget));
+#else
gdk_window_show(widget->window);
+#endif
gdk_window_show(form->bin_window);
for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
{
GtkFormChild *child = tmp_list->data;
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_visible(child->widget)
+ && !gtk_widget_get_mapped(child->widget))
+#else
if (GTK_WIDGET_VISIBLE(child->widget)
&& !GTK_WIDGET_MAPPED(child->widget))
+#endif
gtk_widget_map(child->widget);
}
}
@@ -369,12 +503,21 @@ gtk_form_unrealize(GtkWidget *widget)
if (child->window != NULL)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_handlers_disconnect_by_func(G_OBJECT(child->widget),
+ G_CALLBACK(gtk_form_child_map),
+ child);
+ g_signal_handlers_disconnect_by_func(G_OBJECT(child->widget),
+ G_CALLBACK(gtk_form_child_unmap),
+ child);
+#else
gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
GTK_SIGNAL_FUNC(gtk_form_child_map),
child);
gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
GTK_SIGNAL_FUNC(gtk_form_child_unmap),
child);
+#endif
gdk_window_set_user_data(child->window, NULL);
gdk_window_destroy(child->window);
@@ -385,20 +528,33 @@ gtk_form_unrealize(GtkWidget *widget)
tmp_list = tmp_list->next;
}
+#if GTK_CHECK_VERSION(3,0,0)
+ if (GTK_WIDGET_CLASS (gtk_form_parent_class)->unrealize)
+ (* GTK_WIDGET_CLASS (gtk_form_parent_class)->unrealize) (widget);
+#else
if (GTK_WIDGET_CLASS (parent_class)->unrealize)
(* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+#endif
}
static void
gtk_form_size_request(GtkWidget *widget, GtkRequisition *requisition)
{
+#if !GTK_CHECK_VERSION(3,0,0)
GList *tmp_list;
GtkForm *form;
+#endif
g_return_if_fail(GTK_IS_FORM(widget));
+#if !GTK_CHECK_VERSION(3,0,0)
form = GTK_FORM(widget);
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ requisition->width = 1;
+ requisition->height = 1;
+#else
requisition->width = form->width;
requisition->height = form->height;
@@ -410,7 +566,36 @@ gtk_form_size_request(GtkWidget *widget, GtkRequisition *requisition)
gtk_widget_size_request(child->widget, NULL);
tmp_list = tmp_list->next;
}
+#endif
+}
+
+#if GTK_CHECK_VERSION(3,0,0)
+ static void
+gtk_form_get_preferred_width(GtkWidget *widget,
+ gint *minimal_width,
+ gint *natural_width)
+{
+ GtkRequisition requisition;
+
+ gtk_form_size_request(widget, &requisition);
+
+ *minimal_width = requisition.width;
+ *natural_width = requisition.width;
+}
+
+ static void
+gtk_form_get_preferred_height(GtkWidget *widget,
+ gint *minimal_height,
+ gint *natural_height)
+{
+ GtkRequisition requisition;
+
+ gtk_form_size_request(widget, &requisition);
+
+ *minimal_height = requisition.height;
+ *natural_height = requisition.height;
}
+#endif /* GTK_CHECK_VERSION(3,0,0) */
static void
gtk_form_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
@@ -418,17 +603,34 @@ gtk_form_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
GList *tmp_list;
GtkForm *form;
gboolean need_reposition;
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkAllocation cur_alloc;
+#endif
g_return_if_fail(GTK_IS_FORM(widget));
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_get_allocation(widget, &cur_alloc);
+
+ if (cur_alloc.x == allocation->x
+ && cur_alloc.y == allocation->y
+ && cur_alloc.width == allocation->width
+ && cur_alloc.height == allocation->height)
+#else
if (widget->allocation.x == allocation->x
&& widget->allocation.y == allocation->y
&& widget->allocation.width == allocation->width
&& widget->allocation.height == allocation->height)
+#endif
return;
+#if GTK_CHECK_VERSION(3,0,0)
+ need_reposition = cur_alloc.width != allocation->width
+ || cur_alloc.height != allocation->height;
+#else
need_reposition = widget->allocation.width != allocation->width
|| widget->allocation.height != allocation->height;
+#endif
form = GTK_FORM(widget);
if (need_reposition)
@@ -444,20 +646,81 @@ gtk_form_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
}
}
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_realized(widget))
+#else
if (GTK_WIDGET_REALIZED(widget))
+#endif
{
+#if GTK_CHECK_VERSION(3,0,0)
+ gdk_window_move_resize(gtk_widget_get_window(widget),
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+#else
gdk_window_move_resize(widget->window,
allocation->x, allocation->y,
allocation->width, allocation->height);
+#endif
gdk_window_move_resize(GTK_FORM(widget)->bin_window,
0, 0,
allocation->width, allocation->height);
}
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_allocation(widget, allocation);
+#else
widget->allocation = *allocation;
+#endif
if (need_reposition)
gtk_form_send_configure(form);
}
+#if GTK_CHECK_VERSION(3,0,0)
+ static void
+gtk_form_render_background(GtkWidget *widget, cairo_t *cr)
+{
+ gtk_render_background(gtk_widget_get_style_context(widget), cr,
+ 0, 0,
+ gtk_widget_get_allocated_width(widget),
+ gtk_widget_get_allocated_height(widget));
+}
+
+ static gboolean
+gtk_form_draw(GtkWidget *widget, cairo_t *cr)
+{
+ GList *tmp_list = NULL;
+ GtkForm *form = NULL;
+
+ g_return_val_if_fail(GTK_IS_FORM(widget), FALSE);
+
+ gtk_form_render_background(widget, cr);
+
+ form = GTK_FORM(widget);
+ for (tmp_list = form->children; tmp_list; tmp_list = tmp_list->next)
+ {
+ GtkFormChild * const formchild = tmp_list->data;
+
+ if (!gtk_widget_get_has_window(formchild->widget) &&
+ gtk_cairo_should_draw_window(cr, formchild->window))
+ {
+ /* To get gtk_widget_draw() to work, it is required to call
+ * gtk_widget_size_allocate() in advance with a well-posed
+ * allocation for a given child widget in order to set a
+ * certain private GtkWidget variable, called
+ * widget->priv->alloc_need, to the proper value; othewise,
+ * gtk_widget_draw() fails and the relevant scrollbar won't
+ * appear on the screen.
+ *
+ * Calling gtk_form_position_child() like this is one of ways
+ * to make sure of that. */
+ gtk_form_position_child(form, formchild, TRUE);
+
+ gtk_form_render_background(formchild->widget, cr);
+ }
+ }
+
+ return GTK_WIDGET_CLASS(gtk_form_parent_class)->draw(widget, cr);
+}
+#else /* !GTK_CHECK_VERSION(3,0,0) */
static gint
gtk_form_expose(GtkWidget *widget, GdkEventExpose *event)
{
@@ -497,6 +760,7 @@ gtk_form_expose(GtkWidget *widget, GdkEventExpose *event)
return FALSE;
}
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
/* Container method
*/
@@ -522,12 +786,22 @@ gtk_form_remove(GtkContainer *container, GtkWidget *widget)
if (tmp_list)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ const gboolean was_visible = gtk_widget_get_visible(widget);
+#endif
if (child->window)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_handlers_disconnect_by_func(G_OBJECT(child->widget),
+ G_CALLBACK(&gtk_form_child_map), child);
+ g_signal_handlers_disconnect_by_func(G_OBJECT(child->widget),
+ G_CALLBACK(&gtk_form_child_unmap), child);
+#else
gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
GTK_SIGNAL_FUNC(&gtk_form_child_map), child);
gtk_signal_disconnect_by_func(GTK_OBJECT(child->widget),
GTK_SIGNAL_FUNC(&gtk_form_child_unmap), child);
+#endif
/* FIXME: This will cause problems for reparenting NO_WINDOW
* widgets out of a GtkForm
@@ -536,7 +810,10 @@ gtk_form_remove(GtkContainer *container, GtkWidget *widget)
gdk_window_destroy(child->window);
}
gtk_widget_unparent(widget);
-
+#if GTK_CHECK_VERSION(3,0,0)
+ if (was_visible)
+ gtk_widget_queue_resize(GTK_WIDGET(container));
+#endif
form->children = g_list_remove_link(form->children, tmp_list);
g_list_free_1(tmp_list);
g_free(child);
@@ -577,7 +854,11 @@ gtk_form_attach_child_window(GtkForm *form, GtkFormChild *child)
if (child->window != NULL)
return; /* been there, done that */
+#if GTK_CHECK_VERSION(3,0,0)
+ if (!gtk_widget_get_has_window(child->widget))
+#else
if (GTK_WIDGET_NO_WINDOW(child->widget))
+#endif
{
GtkWidget *widget;
GdkWindowAttr attributes;
@@ -588,34 +869,75 @@ gtk_form_attach_child_window(GtkForm *form, GtkFormChild *child)
attributes.window_type = GDK_WINDOW_CHILD;
attributes.x = child->x;
attributes.y = child->y;
+#if GTK_CHECK_VERSION(3,0,0)
+ {
+ GtkRequisition requisition;
+
+ gtk_widget_get_preferred_size(child->widget, &requisition, NULL);
+
+ attributes.width = requisition.width;
+ attributes.height = requisition.height;
+ }
+#else
attributes.width = child->widget->requisition.width;
attributes.height = child->widget->requisition.height;
+#endif
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.visual = gtk_widget_get_visual(widget);
+#if !GTK_CHECK_VERSION(3,0,0)
attributes.colormap = gtk_widget_get_colormap(widget);
+#endif
attributes.event_mask = GDK_EXPOSURE_MASK;
+#if GTK_CHECK_VERSION(3,0,0)
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+#else
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+#endif
child->window = gdk_window_new(form->bin_window,
&attributes, attributes_mask);
gdk_window_set_user_data(child->window, widget);
+#if GTK_CHECK_VERSION(3,0,0)
+ {
+ GtkStyleContext * const sctx = gtk_widget_get_style_context(widget);
+
+ gtk_style_context_set_state(sctx, GTK_STATE_FLAG_NORMAL);
+# if !GTK_CHECK_VERSION(3,18,0)
+ gtk_style_context_set_background(sctx, child->window);
+# endif
+ }
+#else
gtk_style_set_background(widget->style,
child->window,
GTK_STATE_NORMAL);
+#endif
gtk_widget_set_parent_window(child->widget, child->window);
+#if !GTK_CHECK_VERSION(3,16,0)
gtk_form_set_static_gravity(child->window, TRUE);
+#endif
/*
* Install signal handlers to map/unmap child->window
* alongside with the actual widget.
*/
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(child->widget), "map",
+ G_CALLBACK(&gtk_form_child_map), child);
+ g_signal_connect(G_OBJECT(child->widget), "unmap",
+ G_CALLBACK(&gtk_form_child_unmap), child);
+#else
gtk_signal_connect(GTK_OBJECT(child->widget), "map",
GTK_SIGNAL_FUNC(&gtk_form_child_map), child);
gtk_signal_connect(GTK_OBJECT(child->widget), "unmap",
GTK_SIGNAL_FUNC(&gtk_form_child_unmap), child);
+#endif
}
+#if GTK_CHECK_VERSION(3,0,0)
+ else if (!gtk_widget_get_realized(child->widget))
+#else
else if (!GTK_WIDGET_REALIZED(child->widget))
+#endif
{
gtk_widget_set_parent_window(child->widget, form->bin_window);
}
@@ -627,8 +949,14 @@ gtk_form_realize_child(GtkForm *form, GtkFormChild *child)
gtk_form_attach_child_window(form, child);
gtk_widget_realize(child->widget);
+#if !GTK_CHECK_VERSION(3,16,0)
if (child->window == NULL) /* might be already set, see above */
+# if GTK_CHECK_VERSION(3,0,0)
+ gtk_form_set_static_gravity(gtk_widget_get_window(child->widget), TRUE);
+# else
gtk_form_set_static_gravity(child->widget->window, TRUE);
+# endif
+#endif
}
static void
@@ -646,9 +974,18 @@ gtk_form_position_child(GtkForm *form, GtkFormChild *child,
{
if (!child->mapped)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_mapped(GTK_WIDGET(form))
+ && gtk_widget_get_visible(child->widget))
+#else
if (GTK_WIDGET_MAPPED(form) && GTK_WIDGET_VISIBLE(child->widget))
+#endif
{
+#if GTK_CHECK_VERSION(3,0,0)
+ if (!gtk_widget_get_mapped(child->widget))
+#else
if (!GTK_WIDGET_MAPPED(child->widget))
+#endif
gtk_widget_map(child->widget);
child->mapped = TRUE;
@@ -659,15 +996,31 @@ gtk_form_position_child(GtkForm *form, GtkFormChild *child,
if (force_allocate)
{
GtkAllocation allocation;
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkRequisition requisition;
+ gtk_widget_get_preferred_size(child->widget, &requisition, NULL);
+#endif
+
+#if GTK_CHECK_VERSION(3,0,0)
+ if (!gtk_widget_get_has_window(child->widget))
+#else
if (GTK_WIDGET_NO_WINDOW(child->widget))
+#endif
{
if (child->window)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ gdk_window_move_resize(child->window,
+ x, y,
+ requisition.width,
+ requisition.height);
+#else
gdk_window_move_resize(child->window,
x, y,
child->widget->requisition.width,
child->widget->requisition.height);
+#endif
}
allocation.x = 0;
@@ -679,8 +1032,13 @@ gtk_form_position_child(GtkForm *form, GtkFormChild *child,
allocation.y = y;
}
+#if GTK_CHECK_VERSION(3,0,0)
+ allocation.width = requisition.width;
+ allocation.height = requisition.height;
+#else
allocation.width = child->widget->requisition.width;
allocation.height = child->widget->requisition.height;
+#endif
gtk_widget_size_allocate(child->widget, &allocation);
}
@@ -691,7 +1049,11 @@ gtk_form_position_child(GtkForm *form, GtkFormChild *child,
{
child->mapped = FALSE;
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_mapped(child->widget))
+#else
if (GTK_WIDGET_MAPPED(child->widget))
+#endif
gtk_widget_unmap(child->widget);
}
}
@@ -717,6 +1079,7 @@ gtk_form_position_children(GtkForm *form)
* them or discards them, depending on whether we are obscured
* or not.
*/
+#if !GTK_CHECK_VERSION(3,0,0)
static GdkFilterReturn
gtk_form_filter(GdkXEvent *gdk_xevent, GdkEvent *event UNUSED, gpointer data)
{
@@ -783,7 +1146,9 @@ gtk_form_main_filter(GdkXEvent *gdk_xevent,
}
return GDK_FILTER_CONTINUE;
}
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
+#if !GTK_CHECK_VERSION(3,16,0)
static void
gtk_form_set_static_gravity(GdkWindow *window, gboolean use_static)
{
@@ -791,13 +1156,18 @@ gtk_form_set_static_gravity(GdkWindow *window, gboolean use_static)
* results in an annoying assertion error message. */
gdk_window_set_static_gravities(window, use_static);
}
+#endif /* !GTK_CHECK_VERSION(3,16,0) */
void
gtk_form_move_resize(GtkForm *form, GtkWidget *widget,
gint x, gint y, gint w, gint h)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_size_request(widget, w, h);
+#else
widget->requisition.width = w;
widget->requisition.height = h;
+#endif
gtk_form_move(form, widget, x, y);
}
@@ -811,11 +1181,24 @@ gtk_form_send_configure(GtkForm *form)
widget = GTK_WIDGET(form);
event.type = GDK_CONFIGURE;
+#if GTK_CHECK_VERSION(3,0,0)
+ event.window = gtk_widget_get_window(widget);
+ {
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation(widget, &allocation);
+ event.x = allocation.x;
+ event.y = allocation.y;
+ event.width = allocation.width;
+ event.height = allocation.height;
+ }
+#else
event.window = widget->window;
event.x = widget->allocation.x;
event.y = widget->allocation.y;
event.width = widget->allocation.width;
event.height = widget->allocation.height;
+#endif
gtk_main_do_event((GdkEvent*)&event);
}
@@ -841,4 +1224,3 @@ gtk_form_child_unmap(GtkWidget *widget UNUSED, gpointer user_data)
child->mapped = FALSE;
gdk_window_hide(child->window);
}
-
diff --git a/src/gui_gtk_f.h b/src/gui_gtk_f.h
index 73b0024f8..fa0f40aa3 100644
--- a/src/gui_gtk_f.h
+++ b/src/gui_gtk_f.h
@@ -9,8 +9,12 @@
#ifndef __GTK_FORM_H__
#define __GTK_FORM_H__
+#ifdef USE_GTK3
+#include <gtk/gtk.h>
+#else
#include <gdk/gdk.h>
#include <gtk/gtkcontainer.h>
+#endif
#ifdef __cplusplus
@@ -18,10 +22,17 @@ extern "C" {
#endif
#define GTK_TYPE_FORM (gtk_form_get_type ())
+#ifdef USE_GTK3
+#define GTK_FORM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_FORM, GtkForm))
+#define GTK_FORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_FORM, GtkFormClass))
+#define GTK_IS_FORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_FORM))
+#define GTK_IS_FORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_FORM))
+#else
#define GTK_FORM(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_FORM, GtkForm))
#define GTK_FORM_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_FORM, GtkFormClass))
#define GTK_IS_FORM(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_FORM))
#define GTK_IS_FORM_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FORM))
+#endif
typedef struct _GtkForm GtkForm;
@@ -33,13 +44,17 @@ struct _GtkForm
GList *children;
+#ifndef USE_GTK3
guint width;
guint height;
+#endif
GdkWindow *bin_window;
+#ifndef USE_GTK3
GdkVisibilityState visibility;
gulong configure_serial;
+#endif
gint freeze_count;
};
@@ -49,7 +64,11 @@ struct _GtkFormClass
GtkContainerClass parent_class;
};
+#ifdef USE_GTK3
+GType gtk_form_get_type(void);
+#else
GtkType gtk_form_get_type(void);
+#endif
GtkWidget *gtk_form_new(void);
diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c
index 9f6775fb8..440b401ab 100644
--- a/src/gui_gtk_x11.c
+++ b/src/gui_gtk_x11.c
@@ -19,6 +19,10 @@
*
* (C) 2002,2003 Jason Hildebrand <jason@peaceworks.ca>
* Daniel Elstner <daniel.elstner@gmx.net>
+ *
+ * Support for GTK+ 3 was added by:
+ *
+ * 2016 Kazunobu Kuriyama <kazunobu.kuriyama@gmail.com>
*/
#include "vim.h"
@@ -75,14 +79,18 @@ extern void bonobo_dock_item_set_behavior(BonoboDockItem *dock_item, BonoboDockI
# define GdkEventConfigure int
# define GdkEventClient int
#else
-# include <gdk/gdkkeysyms.h>
+# if GTK_CHECK_VERSION(3,0,0)
+# include <gdk/gdkkeysyms-compat.h>
+# include <gtk/gtkx.h>
+# else
+# include <gdk/gdkkeysyms.h>
+# endif
# include <gdk/gdk.h>
# ifdef WIN3264
# include <gdk/gdkwin32.h>
# else
# include <gdk/gdkx.h>
# endif
-
# include <gtk/gtk.h>
# include "gui_gtk_f.h"
#endif
@@ -580,6 +588,7 @@ gui_mch_free_all(void)
}
#endif
+#if !GTK_CHECK_VERSION(3,0,0)
/*
* This should be maybe completely removed.
* Doesn't seem possible, since check_copy_area() relies on
@@ -601,10 +610,93 @@ visibility_event(GtkWidget *widget UNUSED,
gui.visibility != GDK_VISIBILITY_UNOBSCURED);
return FALSE;
}
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
/*
* Redraw the corresponding portions of the screen.
*/
+#if GTK_CHECK_VERSION(3,0,0)
+static gboolean is_key_pressed = FALSE;
+
+static gboolean gui_gtk_is_blink_on(void);
+static gboolean gui_gtk_is_no_blink(void);
+static void gui_gtk_window_clear(GdkWindow *win);
+
+ static void
+gui_gtk3_redraw(int x, int y, int width, int height)
+{
+ gui_redraw_block(Y_2_ROW(y), X_2_COL(x),
+ Y_2_ROW(y + height - 1), X_2_COL(x + width - 1),
+ GUI_MON_NOCLEAR);
+}
+
+ static void
+gui_gtk3_update_cursor(cairo_t *cr)
+{
+ if (gui.row == gui.cursor_row)
+ {
+ gui.by_signal = TRUE;
+ gui_update_cursor(TRUE, TRUE);
+ gui.by_signal = FALSE;
+ cairo_paint(cr);
+ }
+}
+
+ static gboolean
+gui_gtk3_should_draw_cursor(void)
+{
+ unsigned int cond = 0;
+ cond |= gui_gtk_is_blink_on();
+ cond |= is_key_pressed;
+ cond |= gui.in_focus == FALSE;
+ cond |= gui_gtk_is_no_blink();
+ return cond;
+}
+
+ static gboolean
+draw_event(GtkWidget *widget,
+ cairo_t *cr,
+ gpointer user_data UNUSED)
+{
+ /* Skip this when the GUI isn't set up yet, will redraw later. */
+ if (gui.starting)
+ return FALSE;
+
+ out_flush(); /* make sure all output has been processed */
+ /* for GTK+ 3, may induce other draw events. */
+
+ cairo_set_source_surface(cr, gui.surface, 0, 0);
+
+ /* Draw the window without the cursor. */
+ gui.by_signal = TRUE;
+ {
+ cairo_rectangle_list_t *list = NULL;
+
+ gui_gtk_window_clear(gtk_widget_get_window(widget));
+
+ list = cairo_copy_clip_rectangle_list(cr);
+ if (list->status != CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)
+ {
+ int i;
+ for (i = 0; i < list->num_rectangles; i++)
+ {
+ const cairo_rectangle_t rect = list->rectangles[i];
+ gui_gtk3_redraw(rect.x, rect.y, rect.width, rect.height);
+ }
+ }
+ cairo_rectangle_list_destroy(list);
+
+ cairo_paint(cr);
+ }
+ gui.by_signal = FALSE;
+
+ /* Add the cursor to the window if necessary.*/
+ if (gui_gtk3_should_draw_cursor())
+ gui_gtk3_update_cursor(cr);
+
+ return FALSE;
+}
+#else /* !GTK_CHECK_VERSION(3,0,0) */
static gint
expose_event(GtkWidget *widget UNUSED,
GdkEventExpose *event,
@@ -631,6 +723,7 @@ expose_event(GtkWidget *widget UNUSED,
return FALSE;
}
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
#ifdef FEAT_CLIENTSERVER
/*
@@ -643,7 +736,11 @@ property_event(GtkWidget *widget,
{
if (event->type == GDK_PROPERTY_NOTIFY
&& event->state == (int)GDK_PROPERTY_NEW_VALUE
+# if GTK_CHECK_VERSION(3,0,0)
+ && GDK_WINDOW_XID(event->window) == commWindow
+# else
&& GDK_WINDOW_XWINDOW(event->window) == commWindow
+# endif
&& GET_X_ATOM(event->atom) == commProperty)
{
XEvent xev;
@@ -653,11 +750,16 @@ property_event(GtkWidget *widget,
xev.xproperty.atom = commProperty;
xev.xproperty.window = commWindow;
xev.xproperty.state = PropertyNewValue;
+# if GTK_CHECK_VERSION(3,0,0)
+ serverEventProc(GDK_WINDOW_XDISPLAY(gtk_widget_get_window(widget)),
+ &xev, 0);
+# else
serverEventProc(GDK_WINDOW_XDISPLAY(widget->window), &xev, 0);
+# endif
}
return FALSE;
}
-#endif
+#endif /* defined(FEAT_CLIENTSERVER) */
/****************************************************************************
@@ -682,6 +784,20 @@ static long_u blink_ontime = 400;
static long_u blink_offtime = 250;
static guint blink_timer = 0;
+#if GTK_CHECK_VERSION(3,0,0)
+ static gboolean
+gui_gtk_is_blink_on(void)
+{
+ return blink_state == BLINK_ON;
+}
+
+ static gboolean
+gui_gtk_is_no_blink(void)
+{
+ return blink_waittime == 0 || blink_ontime == 0 || blink_offtime == 0;
+}
+#endif
+
void
gui_mch_set_blinking(long waittime, long on, long off)
{
@@ -698,7 +814,11 @@ gui_mch_stop_blink(void)
{
if (blink_timer)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ g_source_remove(blink_timer);
+#else
gtk_timeout_remove(blink_timer);
+#endif
blink_timer = 0;
}
if (blink_state == BLINK_OFF)
@@ -706,22 +826,36 @@ gui_mch_stop_blink(void)
blink_state = BLINK_NONE;
}
+#if GTK_CHECK_VERSION(3,0,0)
+ static gboolean
+#else
static gint
+#endif
blink_cb(gpointer data UNUSED)
{
if (blink_state == BLINK_ON)
{
gui_undraw_cursor();
blink_state = BLINK_OFF;
+#if GTK_CHECK_VERSION(3,0,0)
+ blink_timer = g_timeout_add((guint)blink_offtime,
+ (GSourceFunc) blink_cb, NULL);
+#else
blink_timer = gtk_timeout_add((guint32)blink_offtime,
(GtkFunction) blink_cb, NULL);
+#endif
}
else
{
gui_update_cursor(TRUE, FALSE);
blink_state = BLINK_ON;
+#if GTK_CHECK_VERSION(3,0,0)
+ blink_timer = g_timeout_add((guint)blink_ontime,
+ (GSourceFunc) blink_cb, NULL);
+#else
blink_timer = gtk_timeout_add((guint32)blink_ontime,
(GtkFunction) blink_cb, NULL);
+#endif
}
return FALSE; /* don't happen again */
@@ -736,14 +870,23 @@ gui_mch_start_blink(void)
{
if (blink_timer)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ g_source_remove(blink_timer);
+#else
gtk_timeout_remove(blink_timer);
+#endif
blink_timer = 0;
}
/* Only switch blinking on if none of the times is zero */
if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ blink_timer = g_timeout_add((guint)blink_waittime,
+ (GSourceFunc) blink_cb, NULL);
+#else
blink_timer = gtk_timeout_add((guint32)blink_waittime,
(GtkFunction) blink_cb, NULL);
+#endif
blink_state = BLINK_ON;
gui_update_cursor(TRUE, FALSE);
}
@@ -758,7 +901,11 @@ enter_notify_event(GtkWidget *widget UNUSED,
gui_mch_start_blink();
/* make sure keyboard input goes there */
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_socket_id == 0 || !gtk_widget_has_focus(gui.drawarea))
+#else
if (gtk_socket_id == 0 || !GTK_WIDGET_HAS_FOCUS(gui.drawarea))
+#endif
gtk_widget_grab_focus(gui.drawarea);
return FALSE;
@@ -938,6 +1085,11 @@ key_press_event(GtkWidget *widget UNUSED,
guint state;
char_u *s, *d;
+#if GTK_CHECK_VERSION(3,0,0)
+ is_key_pressed = TRUE;
+ gui_mch_stop_blink();
+#endif
+
gui.event_time = event->time;
key_sym = event->keyval;
state = event->state;
@@ -1127,12 +1279,17 @@ key_press_event(GtkWidget *widget UNUSED,
return TRUE;
}
-#if defined(FEAT_XIM)
+#if defined(FEAT_XIM) || GTK_CHECK_VERSION(3,0,0)
static gboolean
key_release_event(GtkWidget *widget UNUSED,
GdkEventKey *event,
gpointer data UNUSED)
{
+# if GTK_CHECK_VERSION(3,0,0)
+ is_key_pressed = FALSE;
+ gui_mch_start_blink();
+# endif
+# if defined(FEAT_XIM)
gui.event_time = event->time;
/*
* GTK+ 2 input methods may do fancy stuff on key release events too.
@@ -1140,6 +1297,9 @@ key_release_event(GtkWidget *widget UNUSED,
* by holding down CTRL-SHIFT and typing hexadecimal digits.
*/
return xim_queue_key_press_event(event, FALSE);
+# else
+ return TRUE;
+# endif
}
#endif
@@ -1179,13 +1339,22 @@ selection_received_cb(GtkWidget *widget UNUSED,
int len;
int motion_type = MAUTO;
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_selection_data_get_selection(data) == clip_plus.gtk_sel_atom)
+#else
if (data->selection == clip_plus.gtk_sel_atom)
+#endif
cbd = &clip_plus;
else
cbd = &clip_star;
+#if GTK_CHECK_VERSION(3,0,0)
+ text = (char_u *)gtk_selection_data_get_data(data);
+ len = gtk_selection_data_get_length(data);
+#else
text = (char_u *)data->data;
len = data->length;
+#endif
if (text == NULL || len <= 0)
{
@@ -1195,13 +1364,20 @@ selection_received_cb(GtkWidget *widget UNUSED,
return;
}
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_selection_data_get_data_type(data) == vim_atom)
+#else
if (data->type == vim_atom)
+#endif
{
motion_type = *text++;
--len;
}
-
+#if GTK_CHECK_VERSION(3,0,0)
+ else if (gtk_selection_data_get_data_type(data) == vimenc_atom)
+#else
else if (data->type == vimenc_atom)
+#endif
{
char_u *enc;
vimconv_T conv;
@@ -1292,7 +1468,12 @@ selection_get_cb(GtkWidget *widget UNUSED,
GdkAtom type;
VimClipboard *cbd;
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_selection_data_get_selection(selection_data)
+ == clip_plus.gtk_sel_atom)
+#else
if (selection_data->selection == clip_plus.gtk_sel_atom)
+#endif
cbd = &clip_plus;
else
cbd = &clip_star;
@@ -1361,8 +1542,12 @@ selection_get_cb(GtkWidget *widget UNUSED,
string = tmpbuf;
length += 2;
+#if !GTK_CHECK_VERSION(3,0,0)
+ /* Looks redandunt even for GTK2 because these values are
+ * overwritten by gtk_selection_data_set() that follows. */
selection_data->type = selection_data->target;
selection_data->format = 16; /* 16 bits per char */
+#endif
gtk_selection_data_set(selection_data, html_atom, 16,
string, length);
vim_free(string);
@@ -1411,9 +1596,12 @@ selection_get_cb(GtkWidget *widget UNUSED,
if (string != NULL)
{
+#if !GTK_CHECK_VERSION(3,0,0)
+ /* Looks redandunt even for GTK2 because these values are
+ * overwritten by gtk_selection_data_set() that follows. */
selection_data->type = selection_data->target;
selection_data->format = 8; /* 8 bits per char */
-
+#endif
gtk_selection_data_set(selection_data, type, 8, string, length);
vim_free(string);
}
@@ -1493,7 +1681,11 @@ static int mouse_timed_out = TRUE;
/*
* Timer used to recognize multiple clicks of the mouse button
*/
+#if GTK_CHECK_VERSION(3,0,0)
+ static gboolean
+#else
static gint
+#endif
mouse_click_timer_cb(gpointer data)
{
/* we don't use this information currently */
@@ -1505,13 +1697,20 @@ mouse_click_timer_cb(gpointer data)
static guint motion_repeat_timer = 0;
static int motion_repeat_offset = FALSE;
+#ifdef GTK_DEST_DEFAULT_ALL
+static gboolean motion_repeat_timer_cb(gpointer);
+#else
static gint motion_repeat_timer_cb(gpointer);
+#endif
static void
process_motion_notify(int x, int y, GdkModifierType state)
{
int button;
int_u vim_modifiers;
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkAllocation allocation;
+#endif
button = (state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK |
GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
@@ -1538,9 +1737,17 @@ process_motion_notify(int x, int y, GdkModifierType state)
/*
* Auto repeat timer handling.
*/
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_get_allocation(gui.drawarea, &allocation);
+
+ if (x < 0 || y < 0
+ || x >= allocation.width
+ || y >= allocation.height)
+#else
if (x < 0 || y < 0
|| x >= gui.drawarea->allocation.width
|| y >= gui.drawarea->allocation.height)
+#endif
{
int dx;
@@ -1551,8 +1758,13 @@ process_motion_notify(int x, int y, GdkModifierType state)
/* Calculate the maximal distance of the cursor from the drawing area.
* (offshoot can't become negative here!).
*/
+#if GTK_CHECK_VERSION(3,0,0)
+ dx = x < 0 ? -x : x - allocation.width;
+ dy = y < 0 ? -y : y - allocation.height;
+#else
dx = x < 0 ? -x : x - gui.drawarea->allocation.width;
dy = y < 0 ? -y : y - gui.drawarea->allocation.height;
+#endif
offshoot = dx > dy ? dx : dy;
@@ -1577,22 +1789,66 @@ process_motion_notify(int x, int y, GdkModifierType state)
/* shoot again */
if (!motion_repeat_timer)
+#if GTK_CHECK_VERSION(3,0,0)
+ motion_repeat_timer = g_timeout_add((guint)delay,
+ motion_repeat_timer_cb, NULL);
+#else
motion_repeat_timer = gtk_timeout_add((guint32)delay,
motion_repeat_timer_cb, NULL);
+#endif
}
}
+#if GTK_CHECK_VERSION(3,0,0)
+ static GdkDevice *
+gui_gtk_get_pointer_device(GtkWidget *widget)
+{
+ 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);
+ return gdk_device_manager_get_client_pointer(mngr);
+}
+
+ static GdkWindow *
+gui_gtk_get_pointer(GtkWidget *widget,
+ gint *x,
+ gint *y,
+ GdkModifierType *state)
+{
+ GdkWindow * const win = gtk_widget_get_window(widget);
+ GdkDevice * const dev = gui_gtk_get_pointer_device(widget);
+ return gdk_window_get_device_position(win, dev , x, y, state);
+}
+
+ static GdkWindow *
+gui_gtk_window_at_position(GtkWidget *widget,
+ gint *x,
+ gint *y)
+{
+ GdkDevice * const dev = gui_gtk_get_pointer_device(widget);
+ return gdk_device_get_window_at_position(dev, x, y);
+}
+#endif
+
/*
* Timer used to recognize multiple clicks of the mouse button.
*/
+#if GTK_CHECK_VERSION(3,0,0)
+ static gboolean
+#else
static gint
+#endif
motion_repeat_timer_cb(gpointer data UNUSED)
{
int x;
int y;
GdkModifierType state;
+#if GTK_CHECK_VERSION(3,0,0)
+ gui_gtk_get_pointer(gui.drawarea, &x, &y, &state);
+#else
gdk_window_get_pointer(gui.drawarea->window, &x, &y, &state);
+#endif
if (!(state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK |
GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
@@ -1637,7 +1893,11 @@ motion_notify_event(GtkWidget *widget,
int y;
GdkModifierType state;
+#if GTK_CHECK_VERSION(3,0,0)
+ gui_gtk_get_pointer(widget, &x, &y, &state);
+#else
gdk_window_get_pointer(widget->window, &x, &y, &state);
+#endif
process_motion_notify(x, y, state);
}
else
@@ -1668,7 +1928,11 @@ button_press_event(GtkWidget *widget,
gui.event_time = event->time;
/* Make sure we have focus now we've been selected */
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_socket_id != 0 && !gtk_widget_has_focus(widget))
+#else
if (gtk_socket_id != 0 && !GTK_WIDGET_HAS_FOCUS(widget))
+#endif
gtk_widget_grab_focus(widget);
/*
@@ -1684,14 +1948,23 @@ button_press_event(GtkWidget *widget,
/* Handle multiple clicks */
if (!mouse_timed_out && mouse_click_timer)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ g_source_remove(mouse_click_timer);
+#else
gtk_timeout_remove(mouse_click_timer);
+#endif
mouse_click_timer = 0;
repeated_click = TRUE;
}
mouse_timed_out = FALSE;
+#if GTK_CHECK_VERSION(3,0,0)
+ mouse_click_timer = g_timeout_add((guint)p_mouset,
+ mouse_click_timer_cb, &mouse_timed_out);
+#else
mouse_click_timer = gtk_timeout_add((guint32)p_mouset,
mouse_click_timer_cb, &mouse_timed_out);
+#endif
switch (event->button)
{
@@ -1730,7 +2003,11 @@ scroll_event(GtkWidget *widget,
int button;
int_u vim_modifiers;
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_socket_id != 0 && !gtk_widget_has_focus(widget))
+#else
if (gtk_socket_id != 0 && !GTK_WIDGET_HAS_FOCUS(widget))
+#endif
gtk_widget_grab_focus(widget);
switch (event->direction)
@@ -1781,7 +2058,11 @@ button_release_event(GtkWidget *widget UNUSED,
area .*/
if (motion_repeat_timer)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ g_source_remove(motion_repeat_timer);
+#else
gtk_timeout_remove(motion_repeat_timer);
+#endif
motion_repeat_timer = 0;
}
@@ -1896,7 +2177,13 @@ drag_handle_uri_list(GdkDragContext *context,
char_u **fnames;
int nfiles = 0;
+# if GTK_CHECK_VERSION(3,0,0)
+ fnames = parse_uri_list(&nfiles,
+ (char_u *)gtk_selection_data_get_data(data),
+ gtk_selection_data_get_length(data));
+# else
fnames = parse_uri_list(&nfiles, data->data, data->length);
+# endif
if (fnames != NULL && nfiles > 0)
{
@@ -1923,10 +2210,19 @@ drag_handle_text(GdkDragContext *context,
int len;
char_u *tmpbuf = NULL;
+# if GTK_CHECK_VERSION(3,0,0)
+ text = (char_u *)gtk_selection_data_get_data(data);
+ len = gtk_selection_data_get_length(data);
+# else
text = data->data;
len = data->length;
+# endif
+# if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_selection_data_get_data_type(data) == utf8_string_atom)
+# else
if (data->type == utf8_string_atom)
+# endif
{
if (input_conv.vc_type != CONV_NONE)
tmpbuf = string_convert(&input_conv, text, &len);
@@ -1962,10 +2258,21 @@ drag_data_received_cb(GtkWidget *widget,
GdkModifierType state;
/* Guard against trash */
+# if GTK_CHECK_VERSION(3,0,0)
+ const guchar * const data_data = gtk_selection_data_get_data(data);
+ const gint data_length = gtk_selection_data_get_length(data);
+ const gint data_format = gtk_selection_data_get_format(data);
+
+ if (data_data == NULL
+ || data_length <= 0
+ || data_format != 8
+ || data_data[data_length] != '\0')
+# else
if (data->data == NULL
|| data->length <= 0
|| data->format != 8
|| data->data[data->length] != '\0')
+# endif
{
gtk_drag_finish(context, FALSE, FALSE, time_);
return;
@@ -1973,7 +2280,11 @@ drag_data_received_cb(GtkWidget *widget,
/* Get the current modifier state for proper distinguishment between
* different operations later. */
+#if GTK_CHECK_VERSION(3,0,0)
+ gui_gtk_get_pointer(widget, NULL, NULL, &state);
+# else
gdk_window_get_pointer(widget->window, NULL, NULL, &state);
+# endif
/* Not sure about the role of "text/plain" here... */
if (info == (guint)TARGET_TEXT_URI_LIST)
@@ -2253,7 +2564,7 @@ setup_save_yourself(void)
Atom *existing_atoms = NULL;
int count = 0;
-#ifdef USE_XSMP
+# ifdef USE_XSMP
if (xsmp_icefd != -1)
{
/*
@@ -2264,16 +2575,25 @@ setup_save_yourself(void)
g_io_add_watch(g_io, G_IO_IN | G_IO_ERR | G_IO_HUP,
local_xsmp_handle_requests, (gpointer)g_io);
+ g_io_channel_unref(g_io);
}
else
-#endif
+# endif
{
/* Fall back to old method */
/* first get the existing value */
+# if GTK_CHECK_VERSION(3,0,0)
+ GdkWindow * const mainwin_win = gtk_widget_get_window(gui.mainwin);
+
+ if (XGetWMProtocols(GDK_WINDOW_XDISPLAY(mainwin_win),
+ GDK_WINDOW_XID(mainwin_win),
+ &existing_atoms, &count))
+# else
if (XGetWMProtocols(GDK_WINDOW_XDISPLAY(gui.mainwin->window),
GDK_WINDOW_XWINDOW(gui.mainwin->window),
&existing_atoms, &count))
+# endif
{
Atom *new_atoms;
Atom save_yourself_xatom;
@@ -2295,8 +2615,13 @@ setup_save_yourself(void)
{
memcpy(new_atoms, existing_atoms, count * sizeof(Atom));
new_atoms[count] = save_yourself_xatom;
+# if GTK_CHECK_VERSION(3,0,0)
+ XSetWMProtocols(GDK_WINDOW_XDISPLAY(mainwin_win),
+ GDK_WINDOW_XID(mainwin_win),
+# else
XSetWMProtocols(GDK_WINDOW_XDISPLAY(gui.mainwin->window),
GDK_WINDOW_XWINDOW(gui.mainwin->window),
+# endif
new_atoms, count + 1);
vim_free(new_atoms);
}
@@ -2341,8 +2666,13 @@ global_event_filter(GdkXEvent *xev,
* know we are done saving ourselves. We don't want to be
* restarted, thus set argv to NULL.
*/
+# if GTK_CHECK_VERSION(3,0,0)
+ XSetCommand(GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin)),
+ GDK_WINDOW_XID(gtk_widget_get_window(gui.mainwin)),
+# else
XSetCommand(GDK_WINDOW_XDISPLAY(gui.mainwin->window),
GDK_WINDOW_XWINDOW(gui.mainwin->window),
+# endif
NULL, 0);
return GDK_FILTER_REMOVE;
}
@@ -2376,10 +2706,18 @@ mainwin_realize(GtkWidget *widget UNUSED, gpointer data UNUSED)
#undef magick
# undef static
+#if GTK_CHECK_VERSION(3,0,0)
+ GdkWindow * const mainwin_win = gtk_widget_get_window(gui.mainwin);
+#endif
+
/* When started with "--echo-wid" argument, write window ID on stdout. */
if (echo_wid_arg)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ printf("WID: %ld\n", (long)GDK_WINDOW_XID(mainwin_win));
+#else
printf("WID: %ld\n", (long)GDK_WINDOW_XWINDOW(gui.mainwin->window));
+#endif
fflush(stdout);
}
@@ -2416,10 +2754,17 @@ mainwin_realize(GtkWidget *widget UNUSED, gpointer data UNUSED)
if (serverName == NULL && serverDelayedStartName != NULL)
{
/* This is a :gui command in a plain vim with no previous server */
+# if GTK_CHECK_VERSION(3,0,0)
+ commWindow = GDK_WINDOW_XID(mainwin_win);
+
+ (void)serverRegisterName(GDK_WINDOW_XDISPLAY(mainwin_win),
+ serverDelayedStartName);
+# else
commWindow = GDK_WINDOW_XWINDOW(gui.mainwin->window);
(void)serverRegisterName(GDK_WINDOW_XDISPLAY(gui.mainwin->window),
serverDelayedStartName);
+# endif
}
else
{
@@ -2428,12 +2773,22 @@ mainwin_realize(GtkWidget *widget UNUSED, gpointer data UNUSED)
* have to change the "server" registration to that of the main window
* If we have not registered a name yet, remember the window
*/
+# if GTK_CHECK_VERSION(3,0,0)
+ serverChangeRegisteredWindow(GDK_WINDOW_XDISPLAY(mainwin_win),
+ GDK_WINDOW_XID(mainwin_win));
+# else
serverChangeRegisteredWindow(GDK_WINDOW_XDISPLAY(gui.mainwin->window),
GDK_WINDOW_XWINDOW(gui.mainwin->window));
+# endif
}
gtk_widget_add_events(gui.mainwin, GDK_PROPERTY_CHANGE_MASK);
+# if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.mainwin), "property-notify-event",
+ G_CALLBACK(property_event), NULL);
+# else
gtk_signal_connect(GTK_OBJECT(gui.mainwin), "property_notify_event",
GTK_SIGNAL_FUNC(property_event), NULL);
+# endif
#endif
}
@@ -2441,21 +2796,60 @@ mainwin_realize(GtkWidget *widget UNUSED, gpointer data UNUSED)
create_blank_pointer(void)
{
GdkWindow *root_window = NULL;
+#if GTK_CHECK_VERSION(3,0,0)
+ GdkPixbuf *blank_mask;
+#else
GdkPixmap *blank_mask;
+#endif
GdkCursor *cursor;
GdkColor color = { 0, 0, 0, 0 };
+#if !GTK_CHECK_VERSION(3,0,0)
char blank_data[] = { 0x0 };
+#endif
#ifdef HAVE_GTK_MULTIHEAD
+# if GTK_CHECK_VERSION(3,12,0)
+ {
+ GdkWindow * const win = gtk_widget_get_window(gui.mainwin);
+ GdkScreen * const scrn = gdk_window_get_screen(win);
+ root_window = gdk_screen_get_root_window(scrn);
+ }
+# else
root_window = gtk_widget_get_root_window(gui.mainwin);
+# endif
#endif
/* Create a pseudo blank pointer, which is in fact one pixel by one pixel
* in size. */
+#if GTK_CHECK_VERSION(3,0,0)
+ {
+ cairo_surface_t *surf;
+ cairo_t *cr;
+
+ surf = cairo_image_surface_create(CAIRO_FORMAT_A1, 1, 1);
+ cr = cairo_create(surf);
+
+ cairo_set_source_rgb(cr,
+ color.red / 65535.0,
+ color.green / 65535.0,
+ color.blue / 65535.0);
+ cairo_rectangle(cr, 0, 0, 1, 1);
+ cairo_fill(cr);
+ cairo_destroy(cr);
+
+ blank_mask = gdk_pixbuf_get_from_surface(surf, 0, 0, 1, 1);
+ cairo_surface_destroy(surf);
+
+ cursor = gdk_cursor_new_from_pixbuf(gdk_window_get_display(root_window),
+ blank_mask, 0, 0);
+ g_object_unref(blank_mask);
+ }
+#else
blank_mask = gdk_bitmap_create_from_data(root_window, blank_data, 1, 1);
cursor = gdk_cursor_new_from_pixmap(blank_mask, blank_mask,
&color, &color, 0, 0);
gdk_bitmap_unref(blank_mask);
+#endif
return cursor;
}
@@ -2473,12 +2867,22 @@ mainwin_screen_changed_cb(GtkWidget *widget,
* Recreate the invisible mouse cursor.
*/
if (gui.blank_pointer != NULL)
+# if GTK_CHECK_VERSION(3,0,0)
+ g_object_unref(G_OBJECT(gui.blank_pointer));
+# else
gdk_cursor_unref(gui.blank_pointer);
+# endif
gui.blank_pointer = create_blank_pointer();
+# if GTK_CHECK_VERSION(3,0,0)
+ if (gui.pointer_hidden && gtk_widget_get_window(gui.drawarea) != NULL)
+ gdk_window_set_cursor(gtk_widget_get_window(gui.drawarea),
+ gui.blank_pointer);
+# else
if (gui.pointer_hidden && gui.drawarea->window != NULL)
gdk_window_set_cursor(gui.drawarea->window, gui.blank_pointer);
+# endif
/*
* Create a new PangoContext for this screen, and initialize it
@@ -2509,28 +2913,54 @@ mainwin_screen_changed_cb(GtkWidget *widget,
drawarea_realize_cb(GtkWidget *widget, gpointer data UNUSED)
{
GtkWidget *sbar;
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkAllocation allocation;
+#endif
#ifdef FEAT_XIM
xim_init();
#endif
gui_mch_new_colors();
+#if GTK_CHECK_VERSION(3,0,0)
+ gui.surface = gdk_window_create_similar_surface(
+ gtk_widget_get_window(widget),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ gtk_widget_get_allocated_width(widget),
+ gtk_widget_get_allocated_height(widget));
+#else
gui.text_gc = gdk_gc_new(gui.drawarea->window);
+#endif
gui.blank_pointer = create_blank_pointer();
if (gui.pointer_hidden)
+#if GTK_CHECK_VERSION(3,0,0)
+ gdk_window_set_cursor(gtk_widget_get_window(widget), gui.blank_pointer);
+#else
gdk_window_set_cursor(widget->window, gui.blank_pointer);
+#endif
/* get the actual size of the scrollbars, if they are realized */
sbar = firstwin->w_scrollbars[SBAR_LEFT].id;
if (!sbar || (!gui.which_scrollbars[SBAR_LEFT]
&& firstwin->w_scrollbars[SBAR_RIGHT].id))
sbar = firstwin->w_scrollbars[SBAR_RIGHT].id;
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_get_allocation(sbar, &allocation);
+ if (sbar && gtk_widget_get_realized(sbar) && allocation.width)
+ gui.scrollbar_width = allocation.width;
+#else
if (sbar && GTK_WIDGET_REALIZED(sbar) && sbar->allocation.width)
gui.scrollbar_width = sbar->allocation.width;
+#endif
sbar = gui.bottom_sbar.id;
+#if GTK_CHECK_VERSION(3,0,0)
+ if (sbar && gtk_widget_get_realized(sbar) && allocation.height)
+ gui.scrollbar_height = allocation.height;
+#else
if (sbar && GTK_WIDGET_REALIZED(sbar) && sbar->allocation.height)
gui.scrollbar_height = sbar->allocation.height;
+#endif
}
/*
@@ -2558,10 +2988,22 @@ drawarea_unrealize_cb(GtkWidget *widget UNUSED, gpointer data UNUSED)
g_object_unref(gui.text_context);
gui.text_context = NULL;
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gui.surface != NULL)
+ {
+ cairo_surface_destroy(gui.surface);
+ gui.surface = NULL;
+ }
+#else
g_object_unref(gui.text_gc);
gui.text_gc = NULL;
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ g_object_unref(G_OBJECT(gui.blank_pointer));
+#else
gdk_cursor_unref(gui.blank_pointer);
+#endif
gui.blank_pointer = NULL;
}
@@ -2573,6 +3015,38 @@ drawarea_style_set_cb(GtkWidget *widget UNUSED,
gui_mch_new_colors();
}
+#if GTK_CHECK_VERSION(3,0,0)
+ static gboolean
+drawarea_configure_event_cb(GtkWidget *widget,
+ GdkEventConfigure *event,
+ gpointer data UNUSED)
+{
+ static int cur_width = 0;
+ static int cur_height = 0;
+
+ g_return_val_if_fail(event
+ && event->width >= 1 && event->height >= 1, TRUE);
+
+ if (event->width == cur_width && event->height == cur_height)
+ return TRUE;
+
+ cur_width = event->width;
+ cur_height = event->height;
+
+ if (gui.surface != NULL)
+ cairo_surface_destroy(gui.surface);
+
+ gui.surface = gdk_window_create_similar_surface(
+ gtk_widget_get_window(widget),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ event->width, event->height);
+
+ gtk_widget_queue_draw(widget);
+
+ return TRUE;
+}
+#endif
+
/*
* Callback routine for the "delete_event" signal on the toplevel window.
* Tries to vim gracefully, or refuses to exit with changed buffers.
@@ -2592,7 +3066,7 @@ get_item_dimensions(GtkWidget *widget, GtkOrientation orientation)
{
GtkOrientation item_orientation = GTK_ORIENTATION_HORIZONTAL;
-#ifdef FEAT_GUI_GNOME
+# ifdef FEAT_GUI_GNOME
if (using_gnome && widget != NULL)
{
GtkWidget *parent;
@@ -2611,16 +3085,34 @@ get_item_dimensions(GtkWidget *widget, GtkOrientation orientation)
item_orientation = bonobo_dock_item_get_orientation(dockitem);
}
}
-#endif
+# endif
+# if GTK_CHECK_VERSION(3,0,0)
+ if (widget != NULL
+ && item_orientation == orientation
+ && gtk_widget_get_realized(widget)
+ && gtk_widget_get_visible(widget))
+# else
if (widget != NULL
&& item_orientation == orientation
&& GTK_WIDGET_REALIZED(widget)
&& GTK_WIDGET_VISIBLE(widget))
+# endif
{
+# if GTK_CHECK_VERSION(3,0,0)
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation(widget, &allocation);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ return allocation.height;
+ else
+ return allocation.width;
+# else
if (orientation == GTK_ORIENTATION_HORIZONTAL)
return widget->allocation.height;
else
return widget->allocation.width;
+# endif
}
return 0;
}
@@ -2774,6 +3266,17 @@ icon_size_changed_foreach(GtkWidget *widget, gpointer user_data)
{
GtkImage *image = (GtkImage *)widget;
+# if GTK_CHECK_VERSION(3,10,0)
+ if (gtk_image_get_storage_type(image) == GTK_IMAGE_ICON_NAME)
+ {
+ const GtkIconSize icon_size = GPOINTER_TO_INT(user_data);
+ const gchar *icon_name;
+
+ gtk_image_get_icon_name(image, &icon_name, NULL);
+
+ gtk_image_set_from_icon_name(image, icon_name, icon_size);
+ }
+# else
/* User-defined icons are stored in a GtkIconSet */
if (gtk_image_get_storage_type(image) == GTK_IMAGE_ICON_SET)
{
@@ -2787,6 +3290,7 @@ icon_size_changed_foreach(GtkWidget *widget, gpointer user_data)
gtk_image_set_from_icon_set(image, icon_set, icon_size);
gtk_icon_set_unref(icon_set);
}
+# endif
}
else if (GTK_IS_CONTAINER(widget))
{
@@ -2815,7 +3319,9 @@ set_toolbar_style(GtkToolbar *toolbar)
style = GTK_TOOLBAR_ICONS;
gtk_toolbar_set_style(toolbar, style);
+# if !GTK_CHECK_VERSION(3,0,0)
gtk_toolbar_set_tooltips(toolbar, (toolbar_flags & TOOLBAR_TOOLTIPS) != 0);
+# endif
switch (tbis_flags)
{
@@ -2847,7 +3353,9 @@ set_toolbar_style(GtkToolbar *toolbar)
#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
static int ignore_tabline_evt = FALSE;
static GtkWidget *tabline_menu;
+# if !GTK_CHECK_VERSION(3,0,0)
static GtkTooltips *tabline_tooltip;
+# endif
static int clicked_page; /* page clicked in tab line */
/*
@@ -2872,9 +3380,15 @@ add_tabline_menu_item(GtkWidget *menu, char_u *text, int resp)
CONVERT_TO_UTF8_FREE(utf_text);
gtk_container_add(GTK_CONTAINER(menu), item);
+# if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(item), "activate",
+ G_CALLBACK(tabline_menu_handler),
+ GINT_TO_POINTER(resp));
+# else
gtk_signal_connect(GTK_OBJECT(item), "activate",
GTK_SIGNAL_FUNC(tabline_menu_handler),
(gpointer)(long)resp);
+# endif
}
/*
@@ -2916,10 +3430,20 @@ on_tabline_menu(GtkWidget *widget, GdkEvent *event)
)
return TRUE;
+# if GTK_CHECK_VERSION(3,0,0)
+ tabwin = gui_gtk_window_at_position(gui.mainwin, &x, &y);
+# else
tabwin = gdk_window_at_pointer(&x, &y);
+# endif
+
gdk_window_get_user_data(tabwin, (gpointer)&tabwidget);
+# if GTK_CHECK_VERSION(3,0,0)
+ clicked_page = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(tabwidget),
+ "tab_num"));
+# else
clicked_page = (int)(long)gtk_object_get_user_data(
GTK_OBJECT(tabwidget));
+# endif
/* If the event was generated for 3rd button popup the menu. */
if (bevent->button == 3)
@@ -2950,7 +3474,11 @@ on_tabline_menu(GtkWidget *widget, GdkEvent *event)
static void
on_select_tab(
GtkNotebook *notebook UNUSED,
+# if GTK_CHECK_VERSION(3,0,0)
+ gpointer *page UNUSED,
+# else
GtkNotebookPage *page UNUSED,
+# endif
gint idx,
gpointer data UNUSED)
{
@@ -2975,7 +3503,11 @@ gui_mch_show_tabline(int showit)
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gui.tabline), showit);
update_window_manager_hints(0, 0);
if (showit)
+# if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_can_focus(GTK_WIDGET(gui.tabline), FALSE);
+# else
GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(gui.tabline), GTK_CAN_FOCUS);
+# endif
}
gui_mch_update();
@@ -3023,12 +3555,19 @@ gui_mch_update_tabline(void)
if (page == NULL)
{
/* Add notebook page */
+# if GTK_CHECK_VERSION(3,2,0)
+ page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_box_set_homogeneous(GTK_BOX(page), FALSE);
+# else
page = gtk_vbox_new(FALSE, 0);
+# endif
gtk_widget_show(page);
event_box = gtk_event_box_new();
gtk_widget_show(event_box);
label = gtk_label_new("-Empty-");
+# if !GTK_CHECK_VERSION(3,14,0)
gtk_misc_set_padding(GTK_MISC(label), 2, 2);
+# endif
gtk_container_add(GTK_CONTAINER(event_box), label);
gtk_widget_show(label);
gtk_notebook_insert_page(GTK_NOTEBOOK(gui.tabline),
@@ -3038,9 +3577,18 @@ gui_mch_update_tabline(void)
}
event_box = gtk_notebook_get_tab_label(GTK_NOTEBOOK(gui.tabline), page);
+# if GTK_CHECK_VERSION(3,0,0)
+ g_object_set_data(G_OBJECT(event_box), "tab_num",
+ GINT_TO_POINTER(tab_num));
+# else
gtk_object_set_user_data(GTK_OBJECT(event_box),
(gpointer)(long)tab_num);
+# endif
+# if GTK_CHECK_VERSION(3,0,0)
+ label = gtk_bin_get_child(GTK_BIN(event_box));
+# else
label = GTK_BIN(event_box)->child;
+# endif
get_tabline_label(tp, FALSE);
labeltext = CONVERT_TO_UTF8(NameBuff);
gtk_label_set_text(GTK_LABEL(label), (const char *)labeltext);
@@ -3048,8 +3596,12 @@ gui_mch_update_tabline(void)
get_tabline_label(tp, TRUE);
labeltext = CONVERT_TO_UTF8(NameBuff);
+# if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_tooltip_text(event_box, (const gchar *)labeltext);
+# else
gtk_tooltips_set_tip(GTK_TOOLTIPS(tabline_tooltip), event_box,
(const char *)labeltext, NULL);
+# endif
CONVERT_TO_UTF8_FREE(labeltext);
}
@@ -3057,8 +3609,13 @@ gui_mch_update_tabline(void)
while (gtk_notebook_get_nth_page(GTK_NOTEBOOK(gui.tabline), nr) != NULL)
gtk_notebook_remove_page(GTK_NOTEBOOK(gui.tabline), nr);
+# if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_notebook_get_current_page(GTK_NOTEBOOK(gui.tabline)) != curtabidx)
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(gui.tabline), curtabidx);
+# else
if (gtk_notebook_current_page(GTK_NOTEBOOK(gui.tabline)) != curtabidx)
gtk_notebook_set_page(GTK_NOTEBOOK(gui.tabline), curtabidx);
+# endif
/* Make sure everything is in place before drawing text. */
gui_mch_update();
@@ -3076,8 +3633,13 @@ gui_mch_set_curtab(int nr)
return;
ignore_tabline_evt = TRUE;
+# if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_notebook_get_current_page(GTK_NOTEBOOK(gui.tabline)) != nr - 1)
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(gui.tabline), nr - 1);
+# else
if (gtk_notebook_current_page(GTK_NOTEBOOK(gui.tabline)) != nr - 1)
gtk_notebook_set_page(GTK_NOTEBOOK(gui.tabline), nr - 1);
+# endif
ignore_tabline_evt = FALSE;
}
@@ -3187,8 +3749,10 @@ gui_mch_init(void)
#endif
/* FIXME: Need to install the classic icons and a gtkrc.classic file.
* The hard part is deciding install locations and the Makefile magic. */
-#if 0
+#if !GTK_CHECK_VERSION(3,0,0)
+# if 0
gtk_rc_parse("gtkrc");
+# endif
#endif
/* Initialize values */
@@ -3221,7 +3785,11 @@ gui_mch_init(void)
#else
plug = gtk_plug_new(gtk_socket_id);
#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ if (plug != NULL && gtk_plug_get_socket_window(GTK_PLUG(plug)) != NULL)
+#else
if (plug != NULL && GTK_PLUG(plug)->socket_window != NULL)
+#endif
{
gui.mainwin = plug;
}
@@ -3256,14 +3824,26 @@ gui_mch_init(void)
gui.text_context = gtk_widget_create_pango_context(gui.mainwin);
pango_context_set_base_dir(gui.text_context, PANGO_DIRECTION_LTR);
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_container_set_border_width(GTK_CONTAINER(gui.mainwin), 0);
+#else
gtk_container_border_width(GTK_CONTAINER(gui.mainwin), 0);
+#endif
gtk_widget_add_events(gui.mainwin, GDK_VISIBILITY_NOTIFY_MASK);
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.mainwin), "delete-event",
+ G_CALLBACK(&delete_event_cb), NULL);
+
+ g_signal_connect(G_OBJECT(gui.mainwin), "realize",
+ G_CALLBACK(&mainwin_realize), NULL);
+#else
gtk_signal_connect(GTK_OBJECT(gui.mainwin), "delete_event",
GTK_SIGNAL_FUNC(&delete_event_cb), NULL);
gtk_signal_connect(GTK_OBJECT(gui.mainwin), "realize",
GTK_SIGNAL_FUNC(&mainwin_realize), NULL);
+#endif
#ifdef HAVE_GTK_MULTIHEAD
g_signal_connect(G_OBJECT(gui.mainwin), "screen_changed",
G_CALLBACK(&mainwin_screen_changed_cb), NULL);
@@ -3272,7 +3852,12 @@ gui_mch_init(void)
gtk_window_add_accel_group(GTK_WINDOW(gui.mainwin), gui.accel_group);
/* A vertical box holds the menubar, toolbar and main text window. */
+#if GTK_CHECK_VERSION(3,2,0)
+ vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_box_set_homogeneous(GTK_BOX(vbox), FALSE);
+#else
vbox = gtk_vbox_new(FALSE, 0);
+#endif
#ifdef FEAT_GUI_GNOME
if (using_gnome)
@@ -3335,11 +3920,17 @@ gui_mch_init(void)
* Create the toolbar and handle
*/
/* some aesthetics on the toolbar */
+# ifdef USE_GTK3
+ /* TODO: Add GTK+ 3 code here using GtkCssProvider if neccessary. */
+ /* N.B. Since the default value of GtkToolbar::button-relief is
+ * GTK_RELIEF_NONE, there's no need to specify that, probably. */
+# else
gtk_rc_parse_string(
"style \"vim-toolbar-style\" {\n"
" GtkToolbar::button_relief = GTK_RELIEF_NONE\n"
"}\n"
"widget \"*.vim-toolbar\" style \"vim-toolbar-style\"\n");
+# endif
gui.toolbar = gtk_toolbar_new();
gtk_widget_set_name(gui.toolbar, "vim-toolbar");
set_toolbar_style(GTK_TOOLBAR(gui.toolbar));
@@ -3381,42 +3972,77 @@ gui_mch_init(void)
gtk_notebook_set_show_border(GTK_NOTEBOOK(gui.tabline), FALSE);
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(gui.tabline), FALSE);
gtk_notebook_set_scrollable(GTK_NOTEBOOK(gui.tabline), TRUE);
+# if !GTK_CHECK_VERSION(3,0,0)
gtk_notebook_set_tab_border(GTK_NOTEBOOK(gui.tabline), FALSE);
+# endif
+# if !GTK_CHECK_VERSION(3,0,0)
tabline_tooltip = gtk_tooltips_new();
gtk_tooltips_enable(GTK_TOOLTIPS(tabline_tooltip));
+# endif
{
GtkWidget *page, *label, *event_box;
/* Add the first tab. */
+# if GTK_CHECK_VERSION(3,2,0)
+ page = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_box_set_homogeneous(GTK_BOX(page), FALSE);
+# else
page = gtk_vbox_new(FALSE, 0);
+# endif
gtk_widget_show(page);
gtk_container_add(GTK_CONTAINER(gui.tabline), page);
label = gtk_label_new("-Empty-");
gtk_widget_show(label);
event_box = gtk_event_box_new();
gtk_widget_show(event_box);
+# if GTK_CHECK_VERSION(3,0,0)
+ g_object_set_data(G_OBJECT(event_box), "tab_num", GINT_TO_POINTER(1L));
+# else
gtk_object_set_user_data(GTK_OBJECT(event_box), (gpointer)1L);
+# endif
+# if !GTK_CHECK_VERSION(3,14,0)
gtk_misc_set_padding(GTK_MISC(label), 2, 2);
+# endif
gtk_container_add(GTK_CONTAINER(event_box), label);
gtk_notebook_set_tab_label(GTK_NOTEBOOK(gui.tabline), page, event_box);
}
+# if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.tabline), "switch-page",
+ G_CALLBACK(on_select_tab), NULL);
+# else
gtk_signal_connect(GTK_OBJECT(gui.tabline), "switch_page",
GTK_SIGNAL_FUNC(on_select_tab), NULL);
+# endif
/* Create a popup menu for the tab line and connect it. */
tabline_menu = create_tabline_menu();
+# if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect_swapped(G_OBJECT(gui.tabline), "button-press-event",
+ G_CALLBACK(on_tabline_menu), G_OBJECT(tabline_menu));
+# else
gtk_signal_connect_object(GTK_OBJECT(gui.tabline), "button_press_event",
GTK_SIGNAL_FUNC(on_tabline_menu), GTK_OBJECT(tabline_menu));
-#endif
+# endif
+#endif /* FEAT_GUI_TABLINE */
gui.formwin = gtk_form_new();
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_container_set_border_width(GTK_CONTAINER(gui.formwin), 0);
+#else
gtk_container_border_width(GTK_CONTAINER(gui.formwin), 0);
+#endif
+#if !GTK_CHECK_VERSION(3,0,0)
gtk_widget_set_events(gui.formwin, GDK_EXPOSURE_MASK);
+#endif
gui.drawarea = gtk_drawing_area_new();
+#if GTK_CHECK_VERSION(3,0,0)
+ gui.surface = NULL;
+ gui.by_signal = FALSE;
+#endif
/* Determine which events we will filter. */
gtk_widget_set_events(gui.drawarea,
@@ -3438,18 +4064,35 @@ gui_mch_init(void)
/* For GtkSockets, key-presses must go to the focus widget (drawarea)
* and not the window. */
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect((gtk_socket_id == 0) ? G_OBJECT(gui.mainwin)
+ : G_OBJECT(gui.drawarea),
+ "key-press-event",
+ G_CALLBACK(key_press_event), NULL);
+#else
gtk_signal_connect((gtk_socket_id == 0) ? GTK_OBJECT(gui.mainwin)
: GTK_OBJECT(gui.drawarea),
"key_press_event",
GTK_SIGNAL_FUNC(key_press_event), NULL);
-#if defined(FEAT_XIM)
+#endif
+#if defined(FEAT_XIM) || GTK_CHECK_VERSION(3,0,0)
/* Also forward key release events for the benefit of GTK+ 2 input
* modules. Try CTRL-SHIFT-xdigits to enter a Unicode code point. */
g_signal_connect((gtk_socket_id == 0) ? G_OBJECT(gui.mainwin)
: G_OBJECT(gui.drawarea),
- "key_release_event",
+ "key-release-event",
G_CALLBACK(&key_release_event), NULL);
#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.drawarea), "realize",
+ G_CALLBACK(drawarea_realize_cb), NULL);
+ g_signal_connect(G_OBJECT(gui.drawarea), "unrealize",
+ G_CALLBACK(drawarea_unrealize_cb), NULL);
+ g_signal_connect(G_OBJECT(gui.drawarea), "configure-event",
+ G_CALLBACK(drawarea_configure_event_cb), NULL);
+ g_signal_connect_after(G_OBJECT(gui.drawarea), "style-set",
+ G_CALLBACK(&drawarea_style_set_cb), NULL);
+#else
gtk_signal_connect(GTK_OBJECT(gui.drawarea), "realize",
GTK_SIGNAL_FUNC(drawarea_realize_cb), NULL);
gtk_signal_connect(GTK_OBJECT(gui.drawarea), "unrealize",
@@ -3457,8 +4100,11 @@ gui_mch_init(void)
gtk_signal_connect_after(GTK_OBJECT(gui.drawarea), "style_set",
GTK_SIGNAL_FUNC(&drawarea_style_set_cb), NULL);
+#endif
+#if !GTK_CHECK_VERSION(3,0,0)
gui.visibility = GDK_VISIBILITY_UNOBSCURED;
+#endif
#if !(defined(FEAT_GUI_GNOME) && defined(FEAT_SESSION))
wm_protocols_atom = gdk_atom_intern("WM_PROTOCOLS", FALSE);
@@ -3467,7 +4113,11 @@ gui_mch_init(void)
if (gtk_socket_id != 0)
/* make sure keyboard input can go to the drawarea */
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_can_focus(gui.drawarea, TRUE);
+#else
GTK_WIDGET_SET_FLAGS(gui.drawarea, GTK_CAN_FOCUS);
+#endif
/*
* Set clipboard specific atoms
@@ -3482,10 +4132,15 @@ gui_mch_init(void)
*/
gui.border_offset = gui.border_width;
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.drawarea), "draw",
+ G_CALLBACK(draw_event), NULL);
+#else
gtk_signal_connect(GTK_OBJECT(gui.mainwin), "visibility_notify_event",
GTK_SIGNAL_FUNC(visibility_event), NULL);
gtk_signal_connect(GTK_OBJECT(gui.drawarea), "expose_event",
GTK_SIGNAL_FUNC(expose_event), NULL);
+#endif
/*
* Only install these enter/leave callbacks when 'p' in 'guioptions'.
@@ -3493,10 +4148,17 @@ gui_mch_init(void)
*/
if (vim_strchr(p_go, GO_POINTER) != NULL)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.drawarea), "leave-notify-event",
+ G_CALLBACK(leave_notify_event), NULL);
+ g_signal_connect(G_OBJECT(gui.drawarea), "enter-notify-event",
+ G_CALLBACK(enter_notify_event), NULL);
+#else
gtk_signal_connect(GTK_OBJECT(gui.drawarea), "leave_notify_event",
GTK_SIGNAL_FUNC(leave_notify_event), NULL);
gtk_signal_connect(GTK_OBJECT(gui.drawarea), "enter_notify_event",
GTK_SIGNAL_FUNC(enter_notify_event), NULL);
+#endif
}
/* Real windows can get focus ... GtkPlug, being a mere container can't,
@@ -3505,25 +4167,56 @@ gui_mch_init(void)
*/
if (gtk_socket_id == 0)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.mainwin), "focus-out-event",
+ G_CALLBACK(focus_out_event), NULL);
+ g_signal_connect(G_OBJECT(gui.mainwin), "focus-in-event",
+ G_CALLBACK(focus_in_event), NULL);
+#else
gtk_signal_connect(GTK_OBJECT(gui.mainwin), "focus_out_event",
GTK_SIGNAL_FUNC(focus_out_event), NULL);
gtk_signal_connect(GTK_OBJECT(gui.mainwin), "focus_in_event",
GTK_SIGNAL_FUNC(focus_in_event), NULL);
+#endif
}
else
{
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.drawarea), "focus-out-event",
+ G_CALLBACK(focus_out_event), NULL);
+ g_signal_connect(G_OBJECT(gui.drawarea), "focus-in-event",
+ G_CALLBACK(focus_in_event), NULL);
+#else
gtk_signal_connect(GTK_OBJECT(gui.drawarea), "focus_out_event",
GTK_SIGNAL_FUNC(focus_out_event), NULL);
gtk_signal_connect(GTK_OBJECT(gui.drawarea), "focus_in_event",
GTK_SIGNAL_FUNC(focus_in_event), NULL);
+#endif
#ifdef FEAT_GUI_TABLINE
+# if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.tabline), "focus-out-event",
+ G_CALLBACK(focus_out_event), NULL);
+ g_signal_connect(G_OBJECT(gui.tabline), "focus-in-event",
+ G_CALLBACK(focus_in_event), NULL);
+# else
gtk_signal_connect(GTK_OBJECT(gui.tabline), "focus_out_event",
GTK_SIGNAL_FUNC(focus_out_event), NULL);
gtk_signal_connect(GTK_OBJECT(gui.tabline), "focus_in_event",
GTK_SIGNAL_FUNC(focus_in_event), NULL);
+# endif
#endif /* FEAT_GUI_TABLINE */
}
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.drawarea), "motion-notify-event",
+ G_CALLBACK(motion_notify_event), NULL);
+ g_signal_connect(G_OBJECT(gui.drawarea), "button-press-event",
+ G_CALLBACK(button_press_event), NULL);
+ g_signal_connect(G_OBJECT(gui.drawarea), "button-release-event",
+ G_CALLBACK(button_release_event), NULL);
+ g_signal_connect(G_OBJECT(gui.drawarea), "scroll-event",
+ G_CALLBACK(&scroll_event), NULL);
+#else
gtk_signal_connect(GTK_OBJECT(gui.drawarea), "motion_notify_event",
GTK_SIGNAL_FUNC(motion_notify_event), NULL);
gtk_signal_connect(GTK_OBJECT(gui.drawarea), "button_press_event",
@@ -3532,19 +4225,32 @@ gui_mch_init(void)
GTK_SIGNAL_FUNC(button_release_event), NULL);
g_signal_connect(G_OBJECT(gui.drawarea), "scroll_event",
G_CALLBACK(&scroll_event), NULL);
+#endif
/*
* Add selection handler functions.
*/
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.drawarea), "selection-clear-event",
+ G_CALLBACK(selection_clear_event), NULL);
+ g_signal_connect(G_OBJECT(gui.drawarea), "selection-received",
+ G_CALLBACK(selection_received_cb), NULL);
+#else
gtk_signal_connect(GTK_OBJECT(gui.drawarea), "selection_clear_event",
GTK_SIGNAL_FUNC(selection_clear_event), NULL);
gtk_signal_connect(GTK_OBJECT(gui.drawarea), "selection_received",
GTK_SIGNAL_FUNC(selection_received_cb), NULL);
+#endif
gui_gtk_set_selection_targets();
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.drawarea), "selection-get",
+ G_CALLBACK(selection_get_cb), NULL);
+#else
gtk_signal_connect(GTK_OBJECT(gui.drawarea), "selection_get",
GTK_SIGNAL_FUNC(selection_get_cb), NULL);
+#endif
/* Pretend we don't have input focus, we will get an event if we do. */
gui.in_focus = FALSE;
@@ -3572,6 +4278,67 @@ gui_mch_forked(void)
}
#endif /* FEAT_GUI_GNOME && FEAT_SESSION */
+#if GTK_CHECK_VERSION(3,0,0)
+ static void
+gui_gtk_get_rgb_from_pixel(guint32 pixel, GdkRGBA *result)
+{
+ GdkVisual * const visual = gtk_widget_get_visual(gui.drawarea);
+ guint32 r_mask, g_mask, b_mask;
+ gint r_shift, g_shift, b_shift;
+
+ if (visual == NULL)
+ {
+ result->red = 0.0;
+ result->green = 0.0;
+ result->blue = 0.0;
+ result->alpha = 0.0;
+ return;
+ }
+
+ 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);
+
+ result->red = ((pixel & r_mask) >> r_shift) / 255.0;
+ result->green = ((pixel & g_mask) >> g_shift) / 255.0;
+ result->blue = ((pixel & b_mask) >> b_shift) / 255.0;
+ result->alpha = 1.0;
+}
+
+/* Convert a GdRGBA into a pixel value using drawarea's visual */
+ static guint32
+gui_gtk_get_pixel_from_rgb(const GdkRGBA *rgba)
+{
+ GdkVisual * const visual = gtk_widget_get_visual(gui.drawarea);
+ guint32 r_mask, g_mask, b_mask;
+ gint r_shift, g_shift, b_shift;
+ guint32 r, g, b;
+
+ if (visual == NULL)
+ return 0;
+
+ 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);
+
+ r = rgba->red * 65535;
+ g = rgba->green * 65535;
+ b = rgba->blue * 65535;
+
+ return ((r << r_shift) & r_mask) |
+ ((g << g_shift) & g_mask) |
+ ((b << b_shift) & b_mask);
+}
+
+ static void
+set_cairo_source_rgb_from_pixel(cairo_t *cr, guint32 pixel)
+{
+ GdkRGBA result;
+ gui_gtk_get_rgb_from_pixel(pixel, &result);
+ cairo_set_source_rgb(cr, result.red, result.green, result.blue);
+}
+#endif /* GTK_CHECK_VERSION(3,0,0) */
+
/*
* Called when the foreground or background color has been changed.
* This used to change the graphics contexts directly but we are
@@ -3580,12 +4347,39 @@ gui_mch_forked(void)
void
gui_mch_new_colors(void)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ GdkWindow * const da_win = gtk_widget_get_window(gui.drawarea);
+
+ if (gui.drawarea != NULL && gtk_widget_get_window(gui.drawarea) != NULL)
+#else
if (gui.drawarea != NULL && gui.drawarea->window != NULL)
+#endif
{
+#if GTK_CHECK_VERSION(3,4,0)
+ GdkRGBA color;
+
+ gui_gtk_get_rgb_from_pixel(gui.back_pixel, &color);
+ {
+ cairo_pattern_t * const pat = cairo_pattern_create_rgba(
+ color.red, color.green, color.blue, color.alpha);
+ if (pat != NULL)
+ {
+ gdk_window_set_background_pattern(da_win, pat);
+ cairo_pattern_destroy(pat);
+ }
+ else
+ gdk_window_set_background_rgba(da_win, &color);
+ }
+#else /* !GTK_CHECK_VERSION(3,4,0) */
GdkColor color = { 0, 0, 0, 0 };
color.pixel = gui.back_pixel;
+# if GTK_CHECK_VERSION(3,0,0)
+ gdk_window_set_background(da_win, &color);
+# else
gdk_window_set_background(gui.drawarea->window, &color);
+# endif
+#endif /* !GTK_CHECK_VERSION(3,4,0) */
}
}
@@ -3618,8 +4412,13 @@ form_configure_event(GtkWidget *widget UNUSED,
* We can't do much more here than to trying to preserve what had been done,
* since the window is already inevitably going away.
*/
+#if GTK_CHECK_VERSION(3,0,0)
+ static void
+mainwin_destroy_cb(GObject *object UNUSED, gpointer data UNUSED)
+#else
static void
mainwin_destroy_cb(GtkObject *object UNUSED, gpointer data UNUSED)
+#endif
{
/* Don't write messages to the GUI anymore */
full_screen = FALSE;
@@ -3799,8 +4598,13 @@ gui_mch_open(void)
* changed them). */
highlight_gui_started(); /* re-init colors and fonts */
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.mainwin), "destroy",
+ G_CALLBACK(mainwin_destroy_cb), NULL);
+#else
gtk_signal_connect(GTK_OBJECT(gui.mainwin), "destroy",
GTK_SIGNAL_FUNC(mainwin_destroy_cb), NULL);
+#endif
#ifdef FEAT_HANGULIN
hangul_keyboard_set();
@@ -3816,15 +4620,25 @@ gui_mch_open(void)
* manager upon us and should not interfere with what VIM is requesting
* upon startup.
*/
+#if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.formwin), "configure-event",
+ G_CALLBACK(form_configure_event), NULL);
+#else
gtk_signal_connect(GTK_OBJECT(gui.formwin), "configure_event",
GTK_SIGNAL_FUNC(form_configure_event), NULL);
+#endif
#ifdef FEAT_DND
/* Set up for receiving DND items. */
gui_gtk_set_dnd_targets();
+# if GTK_CHECK_VERSION(3,0,0)
+ g_signal_connect(G_OBJECT(gui.drawarea), "drag-data-received",
+ G_CALLBACK(drag_data_received_cb), NULL);
+# else
gtk_signal_connect(GTK_OBJECT(gui.drawarea), "drag_data_received",
GTK_SIGNAL_FUNC(drag_data_received_cb), NULL);
+# endif
#endif
/* With GTK+ 2, we need to iconify the window before calling show()
@@ -3901,7 +4715,8 @@ gui_mch_set_winpos(int x, int y)
gtk_window_move(GTK_WINDOW(gui.mainwin), x, y);
}
-#if 0
+#if !GTK_CHECK_VERSION(3,0,0)
+# if 0
static int resize_idle_installed = FALSE;
/*
* Idle handler to force resize. Used by gui_mch_set_shellsize() to ensure
@@ -3937,7 +4752,8 @@ force_shell_resize_idle(gpointer data)
resize_idle_installed = FALSE;
return FALSE; /* don't call me again */
}
-#endif
+# endif
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
/*
* Return TRUE if the main window is maximized.
@@ -3945,9 +4761,15 @@ force_shell_resize_idle(gpointer data)
int
gui_mch_maximized(void)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ return (gui.mainwin != NULL && gtk_widget_get_window(gui.mainwin) != NULL
+ && (gdk_window_get_state(gtk_widget_get_window(gui.mainwin))
+ & GDK_WINDOW_STATE_MAXIMIZED));
+#else
return (gui.mainwin != NULL && gui.mainwin->window != NULL
&& (gdk_window_get_state(gui.mainwin->window)
& GDK_WINDOW_STATE_MAXIMIZED));
+#endif
}
/*
@@ -4002,14 +4824,16 @@ gui_mch_set_shellsize(int width, int height,
else
update_window_manager_hints(width, height);
-# if 0
+# if !GTK_CHECK_VERSION(3,0,0)
+# if 0
if (!resize_idle_installed)
{
g_idle_add_full(GDK_PRIORITY_EVENTS + 10,
&force_shell_resize_idle, NULL, NULL);
resize_idle_installed = TRUE;
}
-# endif
+# endif
+# endif /* !GTK_CHECK_VERSION(3,0,0) */
/*
* Wait until all events are processed to prevent a crash because the
* real size of the drawing area doesn't reflect Vim's internal ideas.
@@ -4084,7 +4908,11 @@ gui_mch_enable_menu(int showit)
widget = gui.menubar;
/* Do not disable the menu while starting up, otherwise F10 doesn't work. */
+# if GTK_CHECK_VERSION(3,0,0)
+ if (!showit != !gtk_widget_get_visible(widget) && !gui.starting)
+# else
if (!showit != !GTK_WIDGET_VISIBLE(widget) && !gui.starting)
+# endif
{
if (showit)
gtk_widget_show(widget);
@@ -4115,7 +4943,11 @@ gui_mch_show_toolbar(int showit)
if (showit)
set_toolbar_style(GTK_TOOLBAR(gui.toolbar));
+# if GTK_CHECK_VERSION(3,0,0)
+ if (!showit != !gtk_widget_get_visible(widget))
+# else
if (!showit != !GTK_WIDGET_VISIBLE(widget))
+# endif
{
if (showit)
gtk_widget_show(widget);
@@ -4200,6 +5032,17 @@ gui_mch_adjust_charheight(void)
return OK;
}
+#if GTK_CHECK_VERSION(3,0,0)
+/* Callback function used in gui_mch_font_dialog() */
+ static gboolean
+font_filter(const PangoFontFamily *family,
+ const PangoFontFace *face UNUSED,
+ gpointer data UNUSED)
+{
+ return pango_font_family_is_monospace((PangoFontFamily *)family);
+}
+#endif
+
/*
* Put up a font dialog and return the selected font name in allocated memory.
* "oldval" is the previous value. Return NULL when cancelled.
@@ -4217,7 +5060,13 @@ gui_mch_font_dialog(char_u *oldval)
char_u *fontname = NULL;
char_u *oldname;
+#if GTK_CHECK_VERSION(3,2,0)
+ dialog = gtk_font_chooser_dialog_new(NULL, NULL);
+ gtk_font_chooser_set_filter_func(GTK_FONT_CHOOSER(dialog), font_filter,
+ NULL, NULL);
+#else
dialog = gtk_font_selection_dialog_new(NULL);
+#endif
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(gui.mainwin));
gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE);
@@ -4244,15 +5093,25 @@ gui_mch_font_dialog(char_u *oldval)
}
}
+#if GTK_CHECK_VERSION(3,2,0)
+ gtk_font_chooser_set_font(
+ GTK_FONT_CHOOSER(dialog), (const gchar *)oldname);
+#else
gtk_font_selection_dialog_set_font_name(
GTK_FONT_SELECTION_DIALOG(dialog), (const char *)oldname);
+#endif
if (oldname != oldval)
vim_free(oldname);
}
else
+#if GTK_CHECK_VERSION(3,2,0)
+ gtk_font_chooser_set_font(
+ GTK_FONT_CHOOSER(dialog), DEFAULT_FONT);
+#else
gtk_font_selection_dialog_set_font_name(
GTK_FONT_SELECTION_DIALOG(dialog), DEFAULT_FONT);
+#endif
response = gtk_dialog_run(GTK_DIALOG(dialog));
@@ -4260,8 +5119,12 @@ gui_mch_font_dialog(char_u *oldval)
{
char *name;
+#if GTK_CHECK_VERSION(3,2,0)
+ name = gtk_font_chooser_get_font(GTK_FONT_CHOOSER(dialog));
+#else
name = gtk_font_selection_dialog_get_font_name(
GTK_FONT_SELECTION_DIALOG(dialog));
+#endif
if (name != NULL)
{
char_u *p;
@@ -4636,17 +5499,29 @@ gui_mch_get_color(char_u *name)
while (name != NULL)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ GdkRGBA color;
+#else
GdkColor color;
+#endif
int parsed;
int i;
+#if GTK_CHECK_VERSION(3,0,0)
+ parsed = gdk_rgba_parse(&color, (const gchar *)name);
+#else
parsed = gdk_color_parse((const char *)name, &color);
+#endif
if (parsed)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ return (guicolor_T)gui_gtk_get_pixel_from_rgb(&color);
+#else
gdk_colormap_alloc_color(gtk_widget_get_colormap(gui.drawarea),
&color, FALSE, TRUE);
return (guicolor_T)color.pixel;
+#endif
}
/* add a few builtin names and try again */
for (i = 0; ; ++i)
@@ -4838,12 +5713,26 @@ setup_zero_width_cluster(PangoItem *item, PangoGlyphInfo *glyph,
glyph->geometry.x_offset = -width + MAX(0, width - ink_rect.width) / 2;
}
+#if GTK_CHECK_VERSION(3,0,0)
+ static void
+draw_glyph_string(int row, int col, int num_cells, int flags,
+ PangoFont *font, PangoGlyphString *glyphs,
+ cairo_t *cr)
+#else
static void
draw_glyph_string(int row, int col, int num_cells, int flags,
PangoFont *font, PangoGlyphString *glyphs)
+#endif
{
if (!(flags & DRAW_TRANSP))
{
+#if GTK_CHECK_VERSION(3,0,0)
+ set_cairo_source_rgb_from_pixel(cr, gui.bgcolor->pixel);
+ cairo_rectangle(cr,
+ FILL_X(col), FILL_Y(row),
+ num_cells * gui.char_width, gui.char_height);
+ cairo_fill(cr);
+#else
gdk_gc_set_foreground(gui.text_gc, gui.bgcolor);
gdk_draw_rectangle(gui.drawarea->window,
@@ -4853,8 +5742,14 @@ draw_glyph_string(int row, int col, int num_cells, int flags,
FILL_Y(row),
num_cells * gui.char_width,
gui.char_height);
+#endif
}
+#if GTK_CHECK_VERSION(3,0,0)
+ set_cairo_source_rgb_from_pixel(cr, gui.fgcolor->pixel);
+ cairo_move_to(cr, TEXT_X(col), TEXT_Y(row));
+ pango_cairo_show_glyph_string(cr, font, glyphs);
+#else
gdk_gc_set_foreground(gui.text_gc, gui.fgcolor);
gdk_draw_glyphs(gui.drawarea->window,
@@ -4863,22 +5758,36 @@ draw_glyph_string(int row, int col, int num_cells, int flags,
TEXT_X(col),
TEXT_Y(row),
glyphs);
+#endif
/* redraw the contents with an offset of 1 to emulate bold */
if ((flags & DRAW_BOLD) && !gui.font_can_bold)
+#if GTK_CHECK_VERSION(3,0,0)
+ {
+ set_cairo_source_rgb_from_pixel(cr, gui.fgcolor->pixel);
+ cairo_move_to(cr, TEXT_X(col) + 1, TEXT_Y(row));
+ pango_cairo_show_glyph_string(cr, font, glyphs);
+ }
+#else
gdk_draw_glyphs(gui.drawarea->window,
gui.text_gc,
font,
TEXT_X(col) + 1,
TEXT_Y(row),
glyphs);
+#endif
}
/*
* Draw underline and undercurl at the bottom of the character cell.
*/
+#if GTK_CHECK_VERSION(3,0,0)
+ static void
+draw_under(int flags, int row, int col, int cells, cairo_t *cr)
+#else
static void
draw_under(int flags, int row, int col, int cells)
+#endif
{
int i;
int offset;
@@ -4888,6 +5797,17 @@ draw_under(int flags, int row, int col, int cells)
/* Undercurl: draw curl at the bottom of the character cell. */
if (flags & DRAW_UNDERC)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ cairo_set_line_width(cr, 1.0);
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
+ set_cairo_source_rgb_from_pixel(cr, gui.spcolor->pixel);
+ for (i = FILL_X(col); i < FILL_X(col + cells); ++i)
+ {
+ offset = val[i % 8];
+ cairo_line_to(cr, i, y - offset + 0.5);
+ }
+ cairo_stroke(cr);
+#else
gdk_gc_set_foreground(gui.text_gc, gui.spcolor);
for (i = FILL_X(col); i < FILL_X(col + cells); ++i)
{
@@ -4895,6 +5815,7 @@ draw_under(int flags, int row, int col, int cells)
gdk_draw_point(gui.drawarea->window, gui.text_gc, i, y - offset);
}
gdk_gc_set_foreground(gui.text_gc, gui.fgcolor);
+#endif
}
/* Underline: draw a line at the bottom of the character cell. */
@@ -4904,9 +5825,20 @@ draw_under(int flags, int row, int col, int cells)
* Otherwise put the line just below the character. */
if (p_linespace > 1)
y -= p_linespace - 1;
+#if GTK_CHECK_VERSION(3,0,0)
+ {
+ cairo_set_line_width(cr, 1.0);
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
+ set_cairo_source_rgb_from_pixel(cr, gui.fgcolor->pixel);
+ cairo_move_to(cr, FILL_X(col), y + 0.5);
+ cairo_line_to(cr, FILL_X(col + cells), y + 0.5);
+ cairo_stroke(cr);
+ }
+#else
gdk_draw_line(gui.drawarea->window, gui.text_gc,
FILL_X(col), y,
FILL_X(col + cells) - 1, y);
+#endif
}
}
@@ -4922,8 +5854,15 @@ gui_gtk2_draw_string(int row, int col, char_u *s, int len, int flags)
int convlen;
char_u *sp, *bp;
int plen;
+#if GTK_CHECK_VERSION(3,0,0)
+ cairo_t *cr;
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gui.text_context == NULL || gtk_widget_get_window(gui.drawarea) == NULL)
+#else
if (gui.text_context == NULL || gui.drawarea->window == NULL)
+#endif
return len;
if (output_conv.vc_type != CONV_NONE)
@@ -4976,8 +5915,14 @@ gui_gtk2_draw_string(int row, int col, char_u *s, int len, int flags)
area.width = gui.num_cols * gui.char_width;
area.height = gui.char_height;
+#if GTK_CHECK_VERSION(3,0,0)
+ cr = cairo_create(gui.surface);
+ cairo_rectangle(cr, area.x, area.y, area.width, area.height);
+ cairo_clip(cr);
+#else
gdk_gc_set_clip_origin(gui.text_gc, 0, 0);
gdk_gc_set_clip_rectangle(gui.text_gc, &area);
+#endif
glyphs = pango_glyph_string_new();
@@ -5004,7 +5949,11 @@ gui_gtk2_draw_string(int row, int col, char_u *s, int len, int flags)
glyphs->log_clusters[i] = i;
}
+#if GTK_CHECK_VERSION(3,0,0)
+ draw_glyph_string(row, col, len, flags, gui.ascii_font, glyphs, cr);
+#else
draw_glyph_string(row, col, len, flags, gui.ascii_font, glyphs);
+#endif
column_offset = len;
}
@@ -5162,8 +6111,14 @@ not_ascii:
}
/*** Aaaaand action! ***/
+#if GTK_CHECK_VERSION(3,0,0)
+ draw_glyph_string(row, col + column_offset, item_cells,
+ flags, item->analysis.font, glyphs,
+ cr);
+#else
draw_glyph_string(row, col + column_offset, item_cells,
flags, item->analysis.font, glyphs);
+#endif
pango_item_free(item);
@@ -5175,12 +6130,23 @@ not_ascii:
skipitall:
/* Draw underline and undercurl. */
+#if GTK_CHECK_VERSION(3,0,0)
+ draw_under(flags, row, col, column_offset, cr);
+#else
draw_under(flags, row, col, column_offset);
+#endif
pango_glyph_string_free(glyphs);
vim_free(conv_buf);
+#if GTK_CHECK_VERSION(3,0,0)
+ cairo_destroy(cr);
+ if (!gui.by_signal)
+ gdk_window_invalidate_rect(gtk_widget_get_window(gui.drawarea),
+ &area, FALSE);
+#else
gdk_gc_set_clip_rectangle(gui.text_gc, NULL);
+#endif
return column_offset;
}
@@ -5207,10 +6173,19 @@ gui_mch_haskey(char_u *name)
int
gui_get_x11_windis(Window *win, Display **dis)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gui.mainwin != NULL && gtk_widget_get_window(gui.mainwin) != NULL)
+#else
if (gui.mainwin != NULL && gui.mainwin->window != NULL)
+#endif
{
+#if GTK_CHECK_VERSION(3,0,0)
+ *dis = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin));
+ *win = GDK_WINDOW_XID(gtk_widget_get_window(gui.mainwin));
+#else
*dis = GDK_WINDOW_XDISPLAY(gui.mainwin->window);
*win = GDK_WINDOW_XWINDOW(gui.mainwin->window);
+#endif
return OK;
}
@@ -5226,8 +6201,13 @@ gui_get_x11_windis(Window *win, Display **dis)
Display *
gui_mch_get_display(void)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gui.mainwin != NULL && gtk_widget_get_window(gui.mainwin) != NULL)
+ return GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin));
+#else
if (gui.mainwin != NULL && gui.mainwin->window != NULL)
return GDK_WINDOW_XDISPLAY(gui.mainwin->window);
+#endif
else
return NULL;
}
@@ -5239,7 +6219,11 @@ gui_mch_beep(void)
#ifdef HAVE_GTK_MULTIHEAD
GdkDisplay *display;
+# if GTK_CHECK_VERSION(3,0,0)
+ if (gui.mainwin != NULL && gtk_widget_get_realized(gui.mainwin))
+# else
if (gui.mainwin != NULL && GTK_WIDGET_REALIZED(gui.mainwin))
+# endif
display = gtk_widget_get_display(gui.mainwin);
else
display = gdk_display_get_default();
@@ -5254,6 +6238,10 @@ gui_mch_beep(void)
void
gui_mch_flash(int msec)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ /* TODO Replace GdkGC with Cairo */
+ (void)msec;
+#else
GdkGCValues values;
GdkGC *invert_gc;
@@ -5293,6 +6281,7 @@ gui_mch_flash(int msec)
FILL_Y((int)Rows) + gui.border_offset);
gdk_gc_destroy(invert_gc);
+#endif
}
/*
@@ -5301,6 +6290,10 @@ gui_mch_flash(int msec)
void
gui_mch_invert_rectangle(int r, int c, int nr, int nc)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ /* TODO Replace GdkGC with Cairo */
+ (void)r; (void)c; (void)nr; (void)nc;
+#else
GdkGCValues values;
GdkGC *invert_gc;
@@ -5322,6 +6315,7 @@ gui_mch_invert_rectangle(int r, int c, int nr, int nc)
FILL_X(c), FILL_Y(r),
(nc) * gui.char_width, (nr) * gui.char_height);
gdk_gc_destroy(invert_gc);
+#endif
}
/*
@@ -5351,19 +6345,44 @@ gui_mch_set_foreground(void)
gui_mch_draw_hollow_cursor(guicolor_T color)
{
int i = 1;
+#if GTK_CHECK_VERSION(3,0,0)
+ cairo_t *cr;
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_window(gui.drawarea) == NULL)
+#else
if (gui.drawarea->window == NULL)
+#endif
return;
+#if GTK_CHECK_VERSION(3,0,0)
+ cr = cairo_create(gui.surface);
+#endif
+
gui_mch_set_fg_color(color);
+#if GTK_CHECK_VERSION(3,0,0)
+ set_cairo_source_rgb_from_pixel(cr, gui.fgcolor->pixel);
+#else
gdk_gc_set_foreground(gui.text_gc, gui.fgcolor);
+#endif
if (mb_lefthalve(gui.row, gui.col))
i = 2;
+#if GTK_CHECK_VERSION(3,0,0)
+ cairo_set_line_width(cr, 1.0);
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
+ cairo_rectangle(cr,
+ FILL_X(gui.col) + 0.5, FILL_Y(gui.row) + 0.5,
+ i * gui.char_width - 1, gui.char_height - 1);
+ cairo_stroke(cr);
+ cairo_destroy(cr);
+#else
gdk_draw_rectangle(gui.drawarea->window, gui.text_gc,
FALSE,
FILL_X(gui.col), FILL_Y(gui.row),
i * gui.char_width - 1, gui.char_height - 1);
+#endif
}
/*
@@ -5373,21 +6392,43 @@ gui_mch_draw_hollow_cursor(guicolor_T color)
void
gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_window(gui.drawarea) == NULL)
+#else
if (gui.drawarea->window == NULL)
+#endif
return;
gui_mch_set_fg_color(color);
+#if GTK_CHECK_VERSION(3,0,0)
+ {
+ cairo_t *cr;
+
+ cr = cairo_create(gui.surface);
+ set_cairo_source_rgb_from_pixel(cr, gui.fgcolor->pixel);
+ cairo_rectangle(cr,
+# ifdef FEAT_RIGHTLEFT
+ /* vertical line should be on the right of current point */
+ CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
+# endif
+ FILL_X(gui.col), FILL_Y(gui.row) + gui.char_height - h,
+ w, h);
+ cairo_fill(cr);
+ cairo_destroy(cr);
+ }
+#else /* !GTK_CHECK_VERSION(3,0,0) */
gdk_gc_set_foreground(gui.text_gc, gui.fgcolor);
gdk_draw_rectangle(gui.drawarea->window, gui.text_gc,
TRUE,
-#ifdef FEAT_RIGHTLEFT
+# ifdef FEAT_RIGHTLEFT
/* vertical line should be on the right of current point */
CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w :
-#endif
+# endif
FILL_X(gui.col),
FILL_Y(gui.row) + gui.char_height - h,
w, h);
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
}
@@ -5404,7 +6445,11 @@ gui_mch_update(void)
g_main_context_iteration(NULL, TRUE);
}
+#if GTK_CHECK_VERSION(3,0,0)
+ static gboolean
+#else
static gint
+#endif
input_timer_cb(gpointer data)
{
int *timed_out = (int *) data;
@@ -5473,7 +6518,11 @@ gui_mch_wait_for_chars(long wtime)
* time */
if (wtime > 0)
+#if GTK_CHECK_VERSION(3,0,0)
+ timer = g_timeout_add((guint)wtime, input_timer_cb, &timed_out);
+#else
timer = gtk_timeout_add((guint32)wtime, input_timer_cb, &timed_out);
+#endif
else
timer = 0;
@@ -5507,7 +6556,11 @@ gui_mch_wait_for_chars(long wtime)
if (input_available())
{
if (timer != 0 && !timed_out)
+#if GTK_CHECK_VERSION(3,0,0)
+ g_source_remove(timer);
+#else
gtk_timeout_remove(timer);
+#endif
return OK;
}
} while (wtime < 0 || !timed_out);
@@ -5531,15 +6584,24 @@ gui_mch_wait_for_chars(long wtime)
gui_mch_flush(void)
{
#ifdef HAVE_GTK_MULTIHEAD
+# if GTK_CHECK_VERSION(3,0,0)
+ if (gui.mainwin != NULL && gtk_widget_get_realized(gui.mainwin))
+# else
if (gui.mainwin != NULL && GTK_WIDGET_REALIZED(gui.mainwin))
+# endif
gdk_display_sync(gtk_widget_get_display(gui.mainwin));
#else
gdk_flush(); /* historical misnomer: calls XSync(), not XFlush() */
#endif
/* This happens to actually do what gui_mch_flush() is supposed to do,
* according to the comment above. */
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gui.drawarea != NULL && gtk_widget_get_window(gui.drawarea) != NULL)
+ gdk_window_process_updates(gtk_widget_get_window(gui.drawarea), FALSE);
+#else
if (gui.drawarea != NULL && gui.drawarea->window != NULL)
gdk_window_process_updates(gui.drawarea->window, FALSE);
+#endif
}
/*
@@ -5549,13 +6611,42 @@ gui_mch_flush(void)
void
gui_mch_clear_block(int row1, int col1, int row2, int col2)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_window(gui.drawarea) == NULL)
+ return;
+#else
GdkColor color;
if (gui.drawarea->window == NULL)
return;
color.pixel = gui.back_pixel;
+#endif
+
+#if GTK_CHECK_VERSION(3,0,0)
+ {
+ /* Add one pixel to the far right column in case a double-stroked
+ * bold glyph may sit there. */
+ const GdkRectangle rect = {
+ FILL_X(col1), FILL_Y(row1),
+ (col2 - col1 + 1) * gui.char_width + (col2 == Columns - 1),
+ (row2 - row1 + 1) * gui.char_height
+ };
+ GdkWindow * const win = gtk_widget_get_window(gui.drawarea);
+ cairo_t * const cr = cairo_create(gui.surface);
+ cairo_pattern_t * const pat = gdk_window_get_background_pattern(win);
+ if (pat != NULL)
+ cairo_set_source(cr, pat);
+ else
+ set_cairo_source_rgb_from_pixel(cr, gui.back_pixel);
+ gdk_cairo_rectangle(cr, &rect);
+ cairo_fill(cr);
+ cairo_destroy(cr);
+ if (!gui.by_signal)
+ gdk_window_invalidate_rect(win, &rect, FALSE);
+ }
+#else /* !GTK_CHECK_VERSION(3,0,0) */
gdk_gc_set_foreground(gui.text_gc, &color);
/* Clear one extra pixel at the far right, for when bold characters have
@@ -5565,15 +6656,44 @@ gui_mch_clear_block(int row1, int col1, int row2, int col2)
(col2 - col1 + 1) * gui.char_width
+ (col2 == Columns - 1),
(row2 - row1 + 1) * gui.char_height);
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
}
+#if GTK_CHECK_VERSION(3,0,0)
+ static void
+gui_gtk_window_clear(GdkWindow *win)
+{
+ const GdkRectangle rect = {
+ 0, 0, gdk_window_get_width(win), gdk_window_get_height(win)
+ };
+ cairo_t * const cr = cairo_create(gui.surface);
+ cairo_pattern_t * const pat = gdk_window_get_background_pattern(win);
+ if (pat != NULL)
+ cairo_set_source(cr, pat);
+ else
+ set_cairo_source_rgb_from_pixel(cr, gui.back_pixel);
+ gdk_cairo_rectangle(cr, &rect);
+ cairo_fill(cr);
+ cairo_destroy(cr);
+
+ if (!gui.by_signal)
+ gdk_window_invalidate_rect(win, &rect, FALSE);
+}
+#endif
+
void
gui_mch_clear_all(void)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_window(gui.drawarea) != NULL)
+ gui_gtk_window_clear(gtk_widget_get_window(gui.drawarea));
+#else
if (gui.drawarea->window != NULL)
gdk_window_clear(gui.drawarea->window);
+#endif
}
+#if !GTK_CHECK_VERSION(3,0,0)
/*
* Redraw any text revealed by scrolling up/down.
*/
@@ -5610,6 +6730,27 @@ check_copy_area(void)
gui_can_update_cursor();
}
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
+
+#if GTK_CHECK_VERSION(3,0,0)
+ static void
+gui_gtk_surface_copy_rect(int dest_x, int dest_y,
+ int src_x, int src_y,
+ int width, int height)
+{
+ cairo_t * const cr = cairo_create(gui.surface);
+
+ cairo_rectangle(cr, dest_x, dest_y, width, height);
+ cairo_clip(cr);
+ cairo_push_group(cr);
+ cairo_set_source_surface(cr, gui.surface, dest_x - src_x, dest_y - src_y);
+ cairo_paint(cr);
+ cairo_pop_group_to_source(cr);
+ cairo_paint(cr);
+
+ cairo_destroy(cr);
+}
+#endif
/*
* Delete the given number of lines from the given row, scrolling up any
@@ -5618,6 +6759,26 @@ check_copy_area(void)
void
gui_mch_delete_lines(int row, int num_lines)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ const int ncols = gui.scroll_region_right - gui.scroll_region_left + 1;
+ const int nrows = gui.scroll_region_bot - row + 1;
+ const int src_nrows = nrows - num_lines;
+
+ gui_gtk_surface_copy_rect(
+ FILL_X(gui.scroll_region_left), FILL_Y(row),
+ FILL_X(gui.scroll_region_left), FILL_Y(row + num_lines),
+ gui.char_width * ncols + 1, gui.char_height * src_nrows);
+ gui_clear_block(
+ gui.scroll_region_bot - num_lines + 1, gui.scroll_region_left,
+ gui.scroll_region_bot, gui.scroll_region_right);
+ gui_gtk3_redraw(
+ FILL_X(gui.scroll_region_left), FILL_Y(row),
+ gui.char_width * ncols + 1, gui.char_height * nrows);
+ if (!gui.by_signal)
+ gtk_widget_queue_draw_area(gui.drawarea,
+ FILL_X(gui.scroll_region_left), FILL_Y(row),
+ gui.char_width * ncols + 1, gui.char_height * nrows);
+#else
if (gui.visibility == GDK_VISIBILITY_FULLY_OBSCURED)
return; /* Can't see the window */
@@ -5638,6 +6799,7 @@ gui_mch_delete_lines(int row, int num_lines)
gui.scroll_region_left,
gui.scroll_region_bot, gui.scroll_region_right);
check_copy_area();
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
}
/*
@@ -5647,6 +6809,26 @@ gui_mch_delete_lines(int row, int num_lines)
void
gui_mch_insert_lines(int row, int num_lines)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ const int ncols = gui.scroll_region_right - gui.scroll_region_left + 1;
+ const int nrows = gui.scroll_region_bot - row + 1;
+ const int src_nrows = nrows - num_lines;
+
+ gui_gtk_surface_copy_rect(
+ FILL_X(gui.scroll_region_left), FILL_Y(row + num_lines),
+ FILL_X(gui.scroll_region_left), FILL_Y(row),
+ gui.char_width * ncols + 1, gui.char_height * src_nrows);
+ gui_mch_clear_block(
+ row, gui.scroll_region_left,
+ row + num_lines - 1, gui.scroll_region_right);
+ gui_gtk3_redraw(
+ FILL_X(gui.scroll_region_left), FILL_Y(row),
+ gui.char_width * ncols + 1, gui.char_height * nrows);
+ if (!gui.by_signal)
+ gtk_widget_queue_draw_area(gui.drawarea,
+ FILL_X(gui.scroll_region_left), FILL_Y(row),
+ gui.char_width * ncols + 1, gui.char_height * nrows);
+#else
if (gui.visibility == GDK_VISIBILITY_FULLY_OBSCURED)
return; /* Can't see the window */
@@ -5665,6 +6847,7 @@ gui_mch_insert_lines(int row, int num_lines)
gui_clear_block(row, gui.scroll_region_left,
row + num_lines - 1, gui.scroll_region_right);
check_copy_area();
+#endif /* !GTK_CHECK_VERSION(3,0,0) */
}
/*
@@ -5700,7 +6883,12 @@ clip_mch_request_selection(VimClipboard *cbd)
}
/* Final fallback position - use the X CUT_BUFFER0 store */
+#if GTK_CHECK_VERSION(3,0,0)
+ yank_cut_buffer0(GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.mainwin)),
+ cbd);
+#else
yank_cut_buffer0(GDK_WINDOW_XDISPLAY(gui.mainwin->window), cbd);
+#endif
}
/*
@@ -5758,7 +6946,11 @@ gui_mch_menu_grey(vimmenu_T *menu, int grey)
gui_mch_menu_hidden(menu, FALSE);
/* Be clever about bitfields versus true booleans here! */
+# if GTK_CHECK_VERSION(3,0,0)
+ if (!gtk_widget_get_sensitive(menu->id) == !grey)
+# else
if (!GTK_WIDGET_SENSITIVE(menu->id) == !grey)
+# endif
{
gtk_widget_set_sensitive(menu->id, !grey);
gui_mch_update();
@@ -5776,7 +6968,11 @@ gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
if (hidden)
{
+# if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_visible(menu->id))
+# else
if (GTK_WIDGET_VISIBLE(menu->id))
+# endif
{
gtk_widget_hide(menu->id);
gui_mch_update();
@@ -5784,7 +6980,11 @@ gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
}
else
{
+# if GTK_CHECK_VERSION(3,0,0)
+ if (!gtk_widget_get_visible(menu->id))
+# else
if (!GTK_WIDGET_VISIBLE(menu->id))
+# endif
{
gtk_widget_show(menu->id);
gui_mch_update();
@@ -5812,10 +7012,14 @@ gui_mch_enable_scrollbar(scrollbar_T *sb, int flag)
if (sb->id == NULL)
return;
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_visible(sb->id, flag);
+#else
if (flag)
gtk_widget_show(sb->id);
else
gtk_widget_hide(sb->id);
+#endif
update_window_manager_hints(0, 0);
}
@@ -5828,8 +7032,18 @@ gui_mch_enable_scrollbar(scrollbar_T *sb, int flag)
gui_mch_get_rgb(guicolor_T pixel)
{
GdkColor color;
+#if GTK_CHECK_VERSION(3,0,0)
+ GdkRGBA rgba;
+
+ gui_gtk_get_rgb_from_pixel(pixel, &rgba);
+
+ color.red = rgba.red * 65535;
+ color.green = rgba.green * 65535;
+ color.blue = rgba.blue * 65535;
+#else
gdk_colormap_query_color(gtk_widget_get_colormap(gui.drawarea),
(unsigned long)pixel, &color);
+#endif
return (((unsigned)color.red & 0xff00) << 8)
| ((unsigned)color.green & 0xff00)
@@ -5842,7 +7056,11 @@ gui_mch_get_rgb(guicolor_T pixel)
void
gui_mch_getmouse(int *x, int *y)
{
+#if GTK_CHECK_VERSION(3,0,0)
+ gui_gtk_get_pointer(gui.drawarea, x, y, NULL);
+#else
gdk_window_get_pointer(gui.drawarea->window, x, y, NULL);
+#endif
}
void
@@ -5851,9 +7069,15 @@ gui_mch_setmouse(int x, int y)
/* Sorry for the Xlib call, but we can't avoid it, since there is no
* internal GDK mechanism present to accomplish this. (and for good
* reason...) */
+#if GTK_CHECK_VERSION(3,0,0)
+ XWarpPointer(GDK_WINDOW_XDISPLAY(gtk_widget_get_window(gui.drawarea)),
+ (Window)0, GDK_WINDOW_XID(gtk_widget_get_window(gui.drawarea)),
+ 0, 0, 0U, 0U, x, y);
+#else
XWarpPointer(GDK_WINDOW_XDISPLAY(gui.drawarea->window),
(Window)0, GDK_WINDOW_XWINDOW(gui.drawarea->window),
0, 0, 0U, 0U, x, y);
+#endif
}
@@ -5874,10 +7098,19 @@ gui_mch_mousehide(int hide)
if (gui.pointer_hidden != hide)
{
gui.pointer_hidden = hide;
+#if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_window(gui.drawarea) && gui.blank_pointer != NULL)
+#else
if (gui.drawarea->window && gui.blank_pointer != NULL)
+#endif
{
if (hide)
+#if GTK_CHECK_VERSION(3,0,0)
+ gdk_window_set_cursor(gtk_widget_get_window(gui.drawarea),
+ gui.blank_pointer);
+#else
gdk_window_set_cursor(gui.drawarea->window, gui.blank_pointer);
+#endif
else
#ifdef FEAT_MOUSESHAPE
mch_set_mouse_shape(last_shape);
@@ -5919,11 +7152,20 @@ mch_set_mouse_shape(int shape)
int id;
GdkCursor *c;
+# if GTK_CHECK_VERSION(3,0,0)
+ if (gtk_widget_get_window(gui.drawarea) == NULL)
+# else
if (gui.drawarea->window == NULL)
+# endif
return;
if (shape == MSHAPE_HIDE || gui.pointer_hidden)
+# if GTK_CHECK_VERSION(3,0,0)
+ gdk_window_set_cursor(gtk_widget_get_window(gui.drawarea),
+ gui.blank_pointer);
+# else
gdk_window_set_cursor(gui.drawarea->window, gui.blank_pointer);
+# endif
else
{
if (shape >= MSHAPE_NUMBERED)
@@ -5944,8 +7186,16 @@ mch_set_mouse_shape(int shape)
# else
c = gdk_cursor_new((GdkCursorType)id);
# endif
+# if GTK_CHECK_VERSION(3,0,0)
+ gdk_window_set_cursor(gtk_widget_get_window(gui.drawarea), c);
+# else
gdk_window_set_cursor(gui.drawarea->window, c);
+# endif
+# if GTK_CHECK_VERSION(3,0,0)
+ g_object_unref(G_OBJECT(c));
+# else
gdk_cursor_destroy(c); /* Unref, actually. Bloody GTK+ 1. */
+# endif
}
if (shape != MSHAPE_HIDE)
last_shape = shape;
@@ -5972,7 +7222,12 @@ gui_mch_drawsign(int row, int col, int typenr)
sign = (GdkPixbuf *)sign_get_image(typenr);
+# if GTK_CHECK_VERSION(3,0,0)
+ if (sign != NULL && gui.drawarea != NULL
+ && gtk_widget_get_window(gui.drawarea) != NULL)
+# else
if (sign != NULL && gui.drawarea != NULL && gui.drawarea->window != NULL)
+# endif
{
int width;
int height;
@@ -6036,6 +7291,49 @@ gui_mch_drawsign(int row, int col, int typenr)
xoffset = (width - SIGN_WIDTH) / 2;
yoffset = (height - SIGN_HEIGHT) / 2;
+# if GTK_CHECK_VERSION(3,0,0)
+ {
+ cairo_t *cr;
+ cairo_surface_t *bg_surf;
+ cairo_t *bg_cr;
+ cairo_surface_t *sign_surf;
+ cairo_t *sign_cr;
+
+ cr = cairo_create(gui.surface);
+
+ bg_surf = cairo_surface_create_similar(gui.surface,
+ cairo_surface_get_content(gui.surface),
+ SIGN_WIDTH, SIGN_HEIGHT);
+ bg_cr = cairo_create(bg_surf);
+ set_cairo_source_rgb_from_pixel(bg_cr, gui.bgcolor->pixel);
+ cairo_paint(bg_cr);
+
+ sign_surf = cairo_surface_create_similar(gui.surface,
+ cairo_surface_get_content(gui.surface),
+ SIGN_WIDTH, SIGN_HEIGHT);
+ sign_cr = cairo_create(sign_surf);
+ gdk_cairo_set_source_pixbuf(sign_cr, sign, -xoffset, -yoffset);
+ cairo_paint(sign_cr);
+
+ cairo_set_operator(sign_cr, CAIRO_OPERATOR_DEST_OVER);
+ cairo_set_source_surface(sign_cr, bg_surf, 0, 0);
+ cairo_paint(sign_cr);
+
+ cairo_set_source_surface(cr, sign_surf, FILL_X(col), FILL_Y(row));
+ cairo_paint(cr);
+
+ cairo_destroy(sign_cr);
+ cairo_surface_destroy(sign_surf);
+ cairo_destroy(bg_cr);
+ cairo_surface_destroy(bg_surf);
+ cairo_destroy(cr);
+
+ if (!gui.by_signal)
+ gtk_widget_queue_draw_area(gui.drawarea,
+ FILL_X(col), FILL_Y(col), width, height);
+
+ }
+# else /* !GTK_CHECK_VERSION(3,0,0) */
gdk_gc_set_foreground(gui.text_gc, gui.bgcolor);
gdk_draw_rectangle(gui.drawarea->window,
@@ -6058,6 +7356,7 @@ gui_mch_drawsign(int row, int col, int typenr)
127,
GDK_RGB_DITHER_NORMAL,
0, 0);
+# endif /* !GTK_CHECK_VERSION(3,0,0) */
if (need_scale)
g_object_unref(sign);
}
diff --git a/src/if_mzsch.c b/src/if_mzsch.c
index 0a3c201f3..4be3c7201 100644
--- a/src/if_mzsch.c
+++ b/src/if_mzsch.c
@@ -852,7 +852,11 @@ static int mz_threads_allow = 0;
static void CALLBACK timer_proc(HWND, UINT, UINT, DWORD);
static UINT timer_id = 0;
#elif defined(FEAT_GUI_GTK)
+# if GTK_CHECK_VERSION(3,0,0)
+static gboolean timer_proc(gpointer);
+# else
static gint timer_proc(gpointer);
+# endif
static guint timer_id = 0;
#elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)
static void timer_proc(XtPointer, XtIntervalId *);
@@ -892,7 +896,11 @@ static void remove_timer(void);
static void CALLBACK
timer_proc(HWND hwnd UNUSED, UINT uMsg UNUSED, UINT idEvent UNUSED, DWORD dwTime UNUSED)
# elif defined(FEAT_GUI_GTK)
+# if GTK_CHECK_VERSION(3,0,0)
+ static gboolean
+# else
static gint
+# endif
timer_proc(gpointer data UNUSED)
# elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)
static void
@@ -919,7 +927,11 @@ setup_timer(void)
# if defined(FEAT_GUI_W32)
timer_id = SetTimer(NULL, 0, p_mzq, timer_proc);
# elif defined(FEAT_GUI_GTK)
+# if GTK_CHECK_VERSION(3,0,0)
+ timer_id = g_timeout_add((guint)p_mzq, (GSourceFunc)timer_proc, NULL);
+# else
timer_id = gtk_timeout_add((guint32)p_mzq, (GtkFunction)timer_proc, NULL);
+# endif
# elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)
timer_id = XtAppAddTimeOut(app_context, p_mzq, timer_proc, NULL);
# elif defined(FEAT_GUI_MAC)
@@ -935,7 +947,11 @@ remove_timer(void)
# if defined(FEAT_GUI_W32)
KillTimer(NULL, timer_id);
# elif defined(FEAT_GUI_GTK)
+# if GTK_CHECK_VERSION(3,0,0)
+ g_source_remove(timer_id);
+# else
gtk_timeout_remove(timer_id);
+# endif
# elif defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA)
XtRemoveTimeOut(timer_id);
# elif defined(FEAT_GUI_MAC)
diff --git a/src/mbyte.c b/src/mbyte.c
index 16092843b..b44168ded 100644
--- a/src/mbyte.c
+++ b/src/mbyte.c
@@ -109,7 +109,11 @@
#endif
#if defined(FEAT_GUI_GTK) && defined(FEAT_XIM)
-# include <gdk/gdkkeysyms.h>
+# if GTK_CHECK_VERSION(3,0,0)
+# include <gdk/gdkkeysyms-compat.h>
+# else
+# include <gdk/gdkkeysyms.h>
+# endif
# ifdef WIN3264
# include <gdk/gdkwin32.h>
# else
@@ -4941,7 +4945,11 @@ xim_init(void)
#endif
g_return_if_fail(gui.drawarea != NULL);
+#if GTK_CHECK_VERSION(3,0,0)
+ g_return_if_fail(gtk_widget_get_window(gui.drawarea) != NULL);
+#else
g_return_if_fail(gui.drawarea->window != NULL);
+#endif
xic = gtk_im_multicontext_new();
g_object_ref(xic);
@@ -4955,7 +4963,11 @@ xim_init(void)
g_signal_connect(G_OBJECT(xic), "preedit_end",
G_CALLBACK(&im_preedit_end_cb), NULL);
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_im_context_set_client_window(xic, gtk_widget_get_window(gui.drawarea));
+#else
gtk_im_context_set_client_window(xic, gui.drawarea->window);
+#endif
}
void
@@ -5054,12 +5066,21 @@ im_synthesize_keypress(unsigned int keyval, unsigned int state)
# ifdef HAVE_GTK_MULTIHEAD
event = (GdkEventKey *)gdk_event_new(GDK_KEY_PRESS);
+# if GTK_CHECK_VERSION(3,0,0)
+ g_object_ref(gtk_widget_get_window(gui.drawarea));
+ /* unreffed by gdk_event_free() */
+# else
g_object_ref(gui.drawarea->window); /* unreffed by gdk_event_free() */
+# endif
# else
event = (GdkEventKey *)g_malloc0((gulong)sizeof(GdkEvent));
event->type = GDK_KEY_PRESS;
# endif
+# if GTK_CHECK_VERSION(3,0,0)
+ event->window = gtk_widget_get_window(gui.drawarea);
+# else
event->window = gui.drawarea->window;
+# endif
event->send_event = TRUE;
event->time = GDK_CURRENT_TIME;
event->state = state;
diff --git a/src/netbeans.c b/src/netbeans.c
index ca0278eee..44a725e1e 100644
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -3055,17 +3055,56 @@ netbeans_draw_multisign_indicator(int row)
int i;
int y;
int x;
+#if GTK_CHECK_VERSION(3,0,0)
+ cairo_t *cr = NULL;
+#else
GdkDrawable *drawable = gui.drawarea->window;
+#endif
if (!NETBEANS_OPEN)
return;
+#if GTK_CHECK_VERSION(3,0,0)
+ cr = cairo_create(gui.surface);
+ {
+ GdkVisual *visual = NULL;
+ guint32 r_mask, g_mask, b_mask;
+ gint r_shift, g_shift, b_shift;
+
+ visual = gdk_window_get_visual(gtk_widget_get_window(gui.drawarea));
+ if (visual != NULL)
+ {
+ 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);
+
+ cairo_set_source_rgb(cr,
+ ((gui.fgcolor->red & r_mask) >> r_shift) / 255.0,
+ ((gui.fgcolor->green & g_mask) >> g_shift) / 255.0,
+ ((gui.fgcolor->blue & b_mask) >> b_shift) / 255.0);
+ }
+ }
+#endif
+
x = 0;
y = row * gui.char_height + 2;
for (i = 0; i < gui.char_height - 3; i++)
+#if GTK_CHECK_VERSION(3,0,0)
+ cairo_rectangle(cr, x+2, y++, 1, 1);
+#else
gdk_draw_point(drawable, gui.text_gc, x+2, y++);
+#endif
+#if GTK_CHECK_VERSION(3,0,0)
+ cairo_rectangle(cr, x+0, y, 1, 1);
+ cairo_rectangle(cr, x+2, y, 1, 1);
+ cairo_rectangle(cr, x+4, y++, 1, 1);
+ cairo_rectangle(cr, x+1, y, 1, 1);
+ cairo_rectangle(cr, x+2, y, 1, 1);
+ cairo_rectangle(cr, x+3, y++, 1, 1);
+ cairo_rectangle(cr, x+2, y, 1, 1);
+#else
gdk_draw_point(drawable, gui.text_gc, x+0, y);
gdk_draw_point(drawable, gui.text_gc, x+2, y);
gdk_draw_point(drawable, gui.text_gc, x+4, y++);
@@ -3073,6 +3112,11 @@ netbeans_draw_multisign_indicator(int row)
gdk_draw_point(drawable, gui.text_gc, x+2, y);
gdk_draw_point(drawable, gui.text_gc, x+3, y++);
gdk_draw_point(drawable, gui.text_gc, x+2, y);
+#endif
+
+#if GTK_CHECK_VERSION(3,0,0)
+ cairo_destroy(cr);
+#endif
}
#endif /* FEAT_GUI_GTK */
diff --git a/src/structs.h b/src/structs.h
index c47eef31a..95b33c3a0 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -2736,7 +2736,9 @@ struct VimMenu
#ifdef FEAT_GUI_GTK
GtkWidget *id; /* Manage this to enable item */
GtkWidget *submenu_id; /* If this is submenu, add children here */
+# if defined(GTK_CHECK_VERSION) && !GTK_CHECK_VERSION(3,4,0)
GtkWidget *tearoff_handle;
+# endif
GtkWidget *label; /* Used by "set wak=" code. */
#endif
#ifdef FEAT_GUI_MOTIF
diff --git a/src/version.c b/src/version.c
index f3fc7c942..94f7b36e7 100644
--- a/src/version.c
+++ b/src/version.c
@@ -749,6 +749,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1402,
+/**/
1401,
/**/
1400,
@@ -3824,11 +3826,15 @@ list_version(void)
MSG_PUTS(_("without GUI."));
#else
# ifdef FEAT_GUI_GTK
-# ifdef FEAT_GUI_GNOME
- MSG_PUTS(_("with GTK2-GNOME GUI."));
+# ifdef USE_GTK3
+ MSG_PUTS(_("with GTK3 GUI."));
# else
- MSG_PUTS(_("with GTK2 GUI."));
-# endif
+# ifdef FEAT_GUI_GNOME
+ MSG_PUTS(_("with GTK2-GNOME GUI."));
+# else
+ MSG_PUTS(_("with GTK2 GUI."));
+# endif
+# endif
# else
# ifdef FEAT_GUI_MOTIF
MSG_PUTS(_("with X11-Motif GUI."));