summaryrefslogtreecommitdiff
path: root/src/gui_gtk_x11.c
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/gui_gtk_x11.c
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/gui_gtk_x11.c')
-rw-r--r--src/gui_gtk_x11.c1339
1 files changed, 1319 insertions, 20 deletions
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);
}