GDK_ACTION_COPY | GDK_ACTION_MOVE);
}
+#ifdef GDK_WINDOWING_WAYLAND
+static struct {
+ int left;
+ int top;
+ int right;
+ int bottom;
+ bool active;
+} wl_dirty_rect = {0, 0, 0, 0, false};
+
+ static void
+wl_queue_dirty_area(int x, int y, int width, int height)
+{
+ if (!wl_dirty_rect.active)
+ {
+ wl_dirty_rect.left = x;
+ wl_dirty_rect.top = y;
+ wl_dirty_rect.right = x + width;
+ wl_dirty_rect.bottom = y + height;
+ wl_dirty_rect.active = true;
+ }
+ else
+ {
+ // Expand to append further changes
+ if (x < wl_dirty_rect.left) wl_dirty_rect.left = x;
+ if (y < wl_dirty_rect.top) wl_dirty_rect.top = y;
+ if (x + width > wl_dirty_rect.right) wl_dirty_rect.right = x + width;
+ if (y + height > wl_dirty_rect.bottom) wl_dirty_rect.bottom = y + height;
+ }
+}
+
+ static void
+wl_flush(void)
+{
+ if (!wl_dirty_rect.active)
+ return;
+ int draw_x = wl_dirty_rect.left;
+ int draw_y = wl_dirty_rect.top;
+ int draw_w = wl_dirty_rect.right - wl_dirty_rect.left;
+ int draw_h = wl_dirty_rect.bottom - wl_dirty_rect.top;
+
+ if (draw_w > 0 && draw_h > 0)
+ {
+ gtk_widget_queue_draw_area(gui.drawarea, draw_x, draw_y, draw_w, draw_h);
+ }
+ wl_dirty_rect.active = false;
+}
+#endif
+
/*
* Initialize the GUI. Create all the windows, set up all the callbacks etc.
* Returns OK for success, FAIL when the GUI can't be started.
// too small. Schedule a corrective resize (now that offsets are
// known) so the window actually fits the geometry Vim has just set.
if ((mch_csd_height > 0 || mch_csd_width > 0) && gtk_socket_id == 0)
- g_idle_add(startup_resize_correction_cb, NULL);
+ g_idle_add_full(GTK_PRIORITY_RESIZE, startup_resize_correction_cb, NULL, NULL);
}
clear_resize_hists();
#endif
return len_sum;
}
+ static void
+queue_draw_area(
+ int x,
+ int y,
+ int width,
+ int height)
+{
+#ifdef GDK_WINDOWING_WAYLAND
+ if (gui.is_wayland)
+ wl_queue_dirty_area(x, y, width, height);
+ else
+#endif
+ gtk_widget_queue_draw_area(gui.drawarea, x, y, width, height);
+}
+
int
gui_gtk_draw_string_ext(
int row,
#if GTK_CHECK_VERSION(3,0,0)
cairo_destroy(cr);
- gtk_widget_queue_draw_area(gui.drawarea, area.x, area.y,
+ queue_draw_area(area.x, area.y,
area.width, area.height);
#else
gdk_gc_set_clip_rectangle(gui.text_gc, NULL);
cairo_destroy(cr);
- gtk_widget_queue_draw_area(gui.drawarea, rect.x, rect.y,
+ queue_draw_area(rect.x, rect.y,
rect.width, rect.height);
#else
GdkGCValues values;
int cnt = 0; // prevent endless loop
while (g_main_context_pending(NULL) && !vim_is_input_buf_full()
&& ++cnt < 100)
+ {
+#ifdef GDK_WINDOWING_WAYLAND
+ if (gui.is_wayland)
+ {
+ int prio = 0;
+ g_main_context_prepare(NULL, &prio);
+ // peek internal scheduling of redraw, honors 'lazyredraw'
+ if (prio == GDK_PRIORITY_REDRAW && redrawing())
+ gui_may_flush(); // prepares redraw: g_main_context_iteration
+ }
+#endif
g_main_context_iteration(NULL, TRUE);
+ }
}
static timeout_cb_type
gui_mch_flush(void)
{
if (gui.mainwin != NULL && gtk_widget_get_realized(gui.mainwin))
+ {
+#ifdef GDK_WINDOWING_WAYLAND
+ if (gui.is_wayland)
+ return wl_flush();
+#endif
#if GTK_CHECK_VERSION(2,4,0)
gdk_display_flush(gtk_widget_get_display(gui.mainwin));
#else
gdk_display_sync(gtk_widget_get_display(gui.mainwin));
#endif
+ }
}
/*
cairo_fill(cr);
cairo_destroy(cr);
- gtk_widget_queue_draw_area(gui.drawarea,
+ queue_draw_area(
rect.x, rect.y, rect.width, rect.height);
}
#else // !GTK_CHECK_VERSION(3,0,0)
cairo_fill(cr);
cairo_destroy(cr);
- gtk_widget_queue_draw_area(gui.drawarea,
+ queue_draw_area(
rect.x, rect.y, rect.width, rect.height);
}
#else
cairo_popup_image_paint(wp, gui.surface, x, y,
src_x, src_y, draw_w, draw_h);
if (gui.drawarea != NULL)
- gtk_widget_queue_draw_area(gui.drawarea, x, y, draw_w, draw_h);
+ queue_draw_area(x, y, draw_w, draw_h);
# else
cairo_popup_image_paint(wp, gui.drawarea->window, x, y,
src_x, src_y, draw_w, draw_h);
cairo_t * const cr = cairo_create(gui.surface);
# ifdef GDK_WINDOWING_WAYLAND
- /*
- Following optimizations are temporary until all callers are refactored
- to wayland deferred redraw; .. then it could be removed.
- */
static cairo_surface_t *scroll_scratch = NULL;
- static int scratch_w = 0;
- static int scratch_h = 0;
- int last_row = Rows - 1;
- int last_row_y = last_row * gui.char_height;
+ static int scratch_w = 0, scratch_h = 0;
+ int last_row = Rows - 1, last_row_y = last_row * gui.char_height;
bool last_row_overlap = (dest_y + height) > last_row_y;
if (gui.is_wayland && ( !(State & MODE_CMDLINE) || !last_row_overlap) )
{
- /*
- scrolling up
- */
- if (dest_y < src_y)
+ if (dest_y < src_y) // scroll up
{
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
- cairo_set_source_surface(cr, gui.surface,
- src_x - dest_x,
+ cairo_set_source_surface(cr, gui.surface, src_x - dest_x,
dest_y - src_y);
cairo_rectangle(cr, dest_x, dest_y, width, height);
cairo_clip(cr);
cairo_paint(cr);
}
else
- {
- // reusing surface when scrolling, only realloc if larger
+ { // reuse surface when scrolling, only realloc if larger
if (scroll_scratch == NULL || width > scratch_w || height > scratch_h)
{
cairo_surface_destroy(scroll_scratch); // safe even if NULL
scroll_scratch = cairo_surface_create_similar(gui.surface,
cairo_surface_get_content(gui.surface), width, height);
- scratch_w = width;
- scratch_h = height;
+ scratch_w = width, scratch_h = height;
}
-
// capture scroll source region
cairo_t *tcr = cairo_create(scroll_scratch);
cairo_set_source_surface(tcr, gui.surface, -src_x, -src_y);
cairo_paint(tcr);
cairo_destroy(tcr);
-
// reuse scroll source region
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_rectangle(cr, dest_x, dest_y, width, height);
cairo_pop_group_to_source(cr);
cairo_paint(cr);
}
-
cairo_destroy(cr);
}
#endif
gui_clear_block(
gui.scroll_region_bot - num_lines + 1, gui.scroll_region_left,
gui.scroll_region_bot, gui.scroll_region_right);
- gtk_widget_queue_draw_area(gui.drawarea,
+ queue_draw_area(
FILL_X(gui.scroll_region_left), FILL_Y(row),
gui.char_width * ncols + 1, gui.char_height * nrows);
#else
gui_clear_block(
row, gui.scroll_region_left,
row + num_lines - 1, gui.scroll_region_right);
- gtk_widget_queue_draw_area(gui.drawarea,
+ queue_draw_area(
FILL_X(gui.scroll_region_left), FILL_Y(row),
gui.char_width * ncols + 1, gui.char_height * nrows);
#else
cairo_surface_destroy(bg_surf);
cairo_destroy(cr);
- gtk_widget_queue_draw_area(gui.drawarea,
+ queue_draw_area(
FILL_X(col), FILL_Y(col), width, height);
}