To: vim_dev@googlegroups.com Subject: Patch 8.0.0089 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.0089 Problem: Various problems with GTK 3.22.2. Solution: Fix the problems, add #ifdefs. (Kazunobu Kuriyama) Files: src/gui_beval.c, src/gui_gtk.c, src/gui_gtk_x11.c *** ../vim-8.0.0088/src/gui_beval.c 2016-11-10 20:01:41.189582944 +0100 --- src/gui_beval.c 2016-11-17 19:09:58.650122624 +0100 *************** *** 1178,1189 **** --- 1178,1200 ---- int y_offset = EVAL_OFFSET_Y; PangoLayout *layout; # ifdef HAVE_GTK_MULTIHEAD + # if GTK_CHECK_VERSION(3,22,2) + GdkRectangle rect; + GdkMonitor * const mon = gdk_display_get_monitor_at_window( + gtk_widget_get_display(beval->balloonShell), + gtk_widget_get_window(beval->balloonShell)); + gdk_monitor_get_geometry(mon, &rect); + + screen_w = rect.width; + screen_h = rect.height; + # else GdkScreen *screen; screen = gtk_widget_get_screen(beval->target); gtk_window_set_screen(GTK_WINDOW(beval->balloonShell), screen); screen_w = gdk_screen_get_width(screen); screen_h = gdk_screen_get_height(screen); + # endif # else screen_w = gdk_screen_width(); screen_h = gdk_screen_height(); *** ../vim-8.0.0088/src/gui_gtk.c 2016-08-29 22:42:20.000000000 +0200 --- src/gui_gtk.c 2016-11-17 19:09:58.650122624 +0100 *************** *** 1881,1890 **** --- 1881,1916 ---- # endif # endif /* FEAT_XIM */ + # if GTK_CHECK_VERSION(3,22,2) + { + GdkEventButton trigger; + + /* A pseudo event to have gtk_menu_popup_at_pointer() work. Since the + * function calculates the popup menu position on the basis of the + * actual pointer position when it is invoked, the fields x, y, x_root + * and y_root are set to zero for convenience. */ + trigger.type = GDK_BUTTON_PRESS; + trigger.window = gtk_widget_get_window(gui.drawarea); + trigger.send_event = FALSE; + trigger.time = gui.event_time; + trigger.x = 0.0; + trigger.y = 0.0; + trigger.axes = NULL; + trigger.state = 0; + trigger.button = 3; + trigger.device = NULL; + trigger.x_root = 0.0; + trigger.y_root = 0.0; + + gtk_menu_popup_at_pointer(GTK_MENU(menu->submenu_id), + (GdkEvent *)&trigger); + } + #else gtk_menu_popup(GTK_MENU(menu->submenu_id), NULL, NULL, (GtkMenuPositionFunc)NULL, NULL, 3U, gui.event_time); + #endif } /* Ugly global variable to pass "mouse_pos" flag from gui_make_popup() to *************** *** 1942,1951 **** --- 1968,2022 ---- if (menu != NULL && menu->submenu_id != NULL) { + # if GTK_CHECK_VERSION(3,22,2) + GdkWindow * const win = gtk_widget_get_window(gui.drawarea); + GdkEventButton trigger; + + /* A pseudo event to have gtk_menu_popup_at_*() functions work. Since + * the position where the menu pops up is automatically adjusted by + * the functions, none of the fields x, y, x_root and y_root has to be + * set to a specific value here; therefore, they are set to zero for + * convenience.*/ + trigger.type = GDK_BUTTON_PRESS; + trigger.window = win; + trigger.send_event = FALSE; + trigger.time = GDK_CURRENT_TIME; + trigger.x = 0.0; + trigger.y = 0.0; + trigger.axes = NULL; + trigger.state = 0; + trigger.button = 0; + trigger.device = NULL; + trigger.x_root = 0.0; + trigger.y_root = 0.0; + + if (mouse_pos) + gtk_menu_popup_at_pointer(GTK_MENU(menu->submenu_id), + (GdkEvent *)&trigger); + else + { + gint origin_x, origin_y; + GdkRectangle rect = { 0, 0, 0, 0 }; + + gdk_window_get_origin(win, &origin_x, &origin_y); + popup_menu_position_func(NULL, &rect.x, &rect.y, NULL, NULL); + + rect.x -= origin_x; + rect.y -= origin_y; + + gtk_menu_popup_at_rect(GTK_MENU(menu->submenu_id), + win, + &rect, + GDK_GRAVITY_SOUTH_EAST, + GDK_GRAVITY_NORTH_WEST, + (GdkEvent *)&trigger); + } + # else gtk_menu_popup(GTK_MENU(menu->submenu_id), NULL, NULL, &popup_menu_position_func, NULL, 0U, (guint32)GDK_CURRENT_TIME); + # endif } } *** ../vim-8.0.0088/src/gui_gtk_x11.c 2016-08-29 22:42:20.000000000 +0200 --- src/gui_gtk_x11.c 2016-11-17 19:09:58.650122624 +0100 *************** *** 3076,3085 **** --- 3076,3091 ---- gui.blank_pointer = NULL; } + #if GTK_CHECK_VERSION(3,22,2) + static void + drawarea_style_updated_cb(GtkWidget *widget UNUSED, + gpointer data UNUSED) + #else static void drawarea_style_set_cb(GtkWidget *widget UNUSED, GtkStyle *previous_style UNUSED, gpointer data UNUSED) + #endif { gui_mch_new_colors(); } *************** *** 3096,3101 **** --- 3102,3132 ---- g_return_val_if_fail(event && event->width >= 1 && event->height >= 1, TRUE); + # if GTK_CHECK_VERSION(3,22,2) + /* As of 3.22.2, GdkWindows have started distributing configure events to + * their "native" children (https://git.gnome.org/browse/gtk+/commit/?h=gtk-3-22&id=12579fe71b3b8f79eb9c1b80e429443bcc437dd0). + * + * As can be seen from the implementation of move_native_children() and + * configure_native_child() in gdkwindow.c, those functions actually + * propagate configure events to every child, failing to distinguish + * "native" one from non-native one. + * + * Naturally, configure events propagated to here like that are fallacious + * and, as a matter of fact, they trigger a geometric collapse of + * gui.drawarea in fullscreen and miximized modes. + * + * To filter out such nuisance events, we are making use of the fact that + * the field send_event of such GdkEventConfigures is set to FALSE in + * configure_native_child(). + * + * Obviously, this is a terrible hack making GVim depend on GTK's + * implementation details. Therefore, watch out any relevant internal + * changes happening in GTK in the feature (sigh). + */ + if (event->send_event == FALSE) + return TRUE; + # endif + if (event->width == cur_width && event->height == cur_height) return TRUE; *************** *** 3519,3526 **** --- 3550,3561 ---- /* If the event was generated for 3rd button popup the menu. */ if (bevent->button == 3) { + # if GTK_CHECK_VERSION(3,22,2) + gtk_menu_popup_at_pointer(GTK_MENU(widget), event); + # else gtk_menu_popup(GTK_MENU(widget), NULL, NULL, NULL, NULL, bevent->button, bevent->time); + # endif /* We handled the event. */ return TRUE; } *************** *** 4116,4121 **** --- 4151,4159 ---- #endif gui.drawarea = gtk_drawing_area_new(); + #if GTK_CHECK_VERSION(3,22,2) + gtk_widget_set_name(gui.drawarea, "vim-gui-drawarea"); + #endif #if GTK_CHECK_VERSION(3,0,0) gui.surface = NULL; gui.by_signal = FALSE; *************** *** 4167,4174 **** --- 4205,4217 ---- G_CALLBACK(drawarea_unrealize_cb), NULL); g_signal_connect(G_OBJECT(gui.drawarea), "configure-event", G_CALLBACK(drawarea_configure_event_cb), NULL); + # if GTK_CHECK_VERSION(3,22,2) + g_signal_connect_after(G_OBJECT(gui.drawarea), "style-updated", + G_CALLBACK(&drawarea_style_updated_cb), NULL); + # else g_signal_connect_after(G_OBJECT(gui.drawarea), "style-set", G_CALLBACK(&drawarea_style_set_cb), NULL); + # endif #else gtk_signal_connect(GTK_OBJECT(gui.drawarea), "realize", GTK_SIGNAL_FUNC(drawarea_realize_cb), NULL); *************** *** 4384,4397 **** 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 rgba; rgba = color_to_rgba(gui.back_pixel); --- 4427,4460 ---- gui_mch_new_colors(void) { #if GTK_CHECK_VERSION(3,0,0) + # if !GTK_CHECK_VERSION(3,22,2) GdkWindow * const da_win = gtk_widget_get_window(gui.drawarea); + # endif 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,22,2) ! GtkStyleContext * const context ! = gtk_widget_get_style_context(gui.drawarea); ! GtkCssProvider * const provider = gtk_css_provider_new(); ! gchar * const css = g_strdup_printf( ! "widget#vim-gui-drawarea {\n" ! " background-color: #%.2lx%.2lx%.2lx;\n" ! "}\n", ! (gui.back_pixel >> 16) & 0xff, ! (gui.back_pixel >> 8) & 0xff, ! gui.back_pixel & 0xff); ! ! gtk_css_provider_load_from_data(provider, css, -1, NULL); ! gtk_style_context_add_provider(context, ! GTK_STYLE_PROVIDER(provider), G_MAXUINT); ! ! g_free(css); ! g_object_unref(provider); ! #elif GTK_CHECK_VERSION(3,4,0) /* !GTK_CHECK_VERSION(3,22,2) */ GdkRGBA rgba; rgba = color_to_rgba(gui.back_pixel); *************** *** 4415,4421 **** # else gdk_window_set_background(gui.drawarea->window, &color); # endif ! #endif /* !GTK_CHECK_VERSION(3,4,0) */ } } --- 4478,4484 ---- # else gdk_window_set_background(gui.drawarea->window, &color); # endif ! #endif /* !GTK_CHECK_VERSION(3,22,2) */ } } *************** *** 4429,4434 **** --- 4492,4517 ---- { int usable_height = event->height; + #if GTK_CHECK_VERSION(3,22,2) + /* As of 3.22.2, GdkWindows have started distributing configure events to + * their "native" children (https://git.gnome.org/browse/gtk+/commit/?h=gtk-3-22&id=12579fe71b3b8f79eb9c1b80e429443bcc437dd0). + * + * As can be seen from the implementation of move_native_children() and + * configure_native_child() in gdkwindow.c, those functions actually + * propagate configure events to every child, failing to distinguish + * "native" one from non-native one. + * + * Naturally, configure events propagated to here like that are fallacious + * and, as a matter of fact, they trigger a geometric collapse of + * gui.formwin. + * + * To filter out such fallacious events, check if the given event is the + * one that was sent out to the right place. Ignore it if not. + */ + if (event->window != gtk_widget_get_window(gui.formwin)) + return TRUE; + #endif + /* When in a GtkPlug, we can't guarantee valid heights (as a round * no. of char-heights), so we have to manually sanitise them. * Widths seem to sort themselves out, don't ask me why. *************** *** 4890,4895 **** --- 4973,4988 ---- gui_mch_get_screen_dimensions(int *screen_w, int *screen_h) { #ifdef HAVE_GTK_MULTIHEAD + # if GTK_CHECK_VERSION(3,22,2) + GdkRectangle rect; + GdkMonitor * const mon = gdk_display_get_monitor_at_window( + gtk_widget_get_display(gui.mainwin), + gtk_widget_get_window(gui.mainwin)); + gdk_monitor_get_geometry(mon, &rect); + + *screen_w = rect.width; + *screen_h = rect.height - p_ghr; + # else GdkScreen* screen; if (gui.mainwin != NULL && gtk_widget_has_screen(gui.mainwin)) *************** *** 4899,4904 **** --- 4992,4998 ---- *screen_w = gdk_screen_get_width(screen); *screen_h = gdk_screen_get_height(screen) - p_ghr; + # endif #else *screen_w = gdk_screen_width(); /* Subtract 'guiheadroom' from the height to allow some room for the *************** *** 6626,6636 **** --- 6720,6734 ---- }; GdkWindow * const win = gtk_widget_get_window(gui.drawarea); cairo_t * const cr = cairo_create(gui.surface); + # if GTK_CHECK_VERSION(3,22,2) + set_cairo_source_rgba_from_color(cr, gui.back_pixel); + # else cairo_pattern_t * const pat = gdk_window_get_background_pattern(win); if (pat != NULL) cairo_set_source(cr, pat); else set_cairo_source_rgba_from_color(cr, gui.back_pixel); + # endif gdk_cairo_rectangle(cr, &rect); cairo_fill(cr); cairo_destroy(cr); *************** *** 6659,6669 **** --- 6757,6771 ---- 0, 0, gdk_window_get_width(win), gdk_window_get_height(win) }; cairo_t * const cr = cairo_create(gui.surface); + # if GTK_CHECK_VERSION(3,22,2) + set_cairo_source_rgba_from_color(cr, gui.back_pixel); + # else cairo_pattern_t * const pat = gdk_window_get_background_pattern(win); if (pat != NULL) cairo_set_source(cr, pat); else set_cairo_source_rgba_from_color(cr, gui.back_pixel); + # endif gdk_cairo_rectangle(cr, &rect); cairo_fill(cr); cairo_destroy(cr); *** ../vim-8.0.0088/src/version.c 2016-11-17 17:56:10.103449001 +0100 --- src/version.c 2016-11-17 19:10:50.549780930 +0100 *************** *** 766,767 **** --- 766,769 ---- { /* Add new patch number below this line */ + /**/ + 89, /**/ -- What a wonderfully exciting cough! Do you mind if I join you? -- Douglas Adams, "The Hitchhiker's Guide to the Galaxy" /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///