diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-02-23 17:14:37 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-02-23 17:14:37 +0100 |
commit | 9892189d2e7ab94b750f99e6da4cbfc3c8014517 (patch) | |
tree | 18634bacebb9e922feceff40c924cdc48550d7ac /src/gui_gtk_x11.c | |
parent | 6bd364e08461159ad3c153ffba4def5b896486a1 (diff) |
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.c | 1339 |
1 files changed, 1319 insertions, 20 deletions
diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c index 9f6775fb8c..440b401ab1 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); < |