summaryrefslogtreecommitdiff
path: root/src
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 /src
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)
Diffstat (limited to 'src')
-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
17 files changed, 3069 insertions, 83 deletions
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."));