mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-03-22 13:40:17 +00:00
fixed the delayed selection paint by changing gtk_xtext_render_ents() to queue a GTK redraw when called outside ::draw on GTK3, instead of attempting direct window painting. This addresses the “double-click/drag selection only appears after some other window change” behavior.
Added an in-code comment explaining why this path is needed (GTK3/Wayland frame-driven presentation).
This commit is contained in:
@@ -195,6 +195,8 @@ static void gtk_xtext_search_textentry_fini (gpointer, gpointer);
|
|||||||
static void gtk_xtext_search_fini (xtext_buffer *);
|
static void gtk_xtext_search_fini (xtext_buffer *);
|
||||||
static gboolean gtk_xtext_search_init (xtext_buffer *buf, const gchar *text, gtk_xtext_search_flags flags, GError **perr);
|
static gboolean gtk_xtext_search_init (xtext_buffer *buf, const gchar *text, gtk_xtext_search_flags flags, GError **perr);
|
||||||
static char * gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent, int *ret_off, int *ret_len, GSList **slp);
|
static char * gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent, int *ret_off, int *ret_len, GSList **slp);
|
||||||
|
static gboolean gtk_xtext_word_select_char (const unsigned char *ch);
|
||||||
|
static gboolean gtk_xtext_get_word_select_range (GtkXText *xtext, int x, int y, textentry **ret_ent, int *ret_off, int *ret_len);
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
gtk_xtext_cursor_unref (GdkCursor *cursor)
|
gtk_xtext_cursor_unref (GdkCursor *cursor)
|
||||||
@@ -1856,10 +1858,12 @@ gtk_xtext_selection_draw (GtkXText * xtext, GdkEventMotion * event, gboolean ren
|
|||||||
if (xtext->word_select)
|
if (xtext->word_select)
|
||||||
{
|
{
|
||||||
/* a word selection cannot be started if the cursor is out of bounds in gtk_xtext_button_press */
|
/* a word selection cannot be started if the cursor is out of bounds in gtk_xtext_button_press */
|
||||||
gtk_xtext_get_word (xtext, low_x, low_y, NULL, &low_offs, NULL, NULL);
|
if (!gtk_xtext_get_word_select_range (xtext, low_x, low_y, NULL, &low_offs, NULL))
|
||||||
|
gtk_xtext_get_word (xtext, low_x, low_y, NULL, &low_offs, NULL, NULL);
|
||||||
|
|
||||||
/* in case the cursor is out of bounds we keep offset_end from gtk_xtext_find_char and fix the length */
|
/* in case the cursor is out of bounds we keep offset_end from gtk_xtext_find_char and fix the length */
|
||||||
if (gtk_xtext_get_word (xtext, high_x, high_y, NULL, &high_offs, &high_len, NULL) == NULL)
|
if (!gtk_xtext_get_word_select_range (xtext, high_x, high_y, NULL, &high_offs, &high_len) &&
|
||||||
|
gtk_xtext_get_word (xtext, high_x, high_y, NULL, &high_offs, &high_len, NULL) == NULL)
|
||||||
high_len = high_offs == high_ent->str_len? 0: -1; /* -1 for the space, 0 if at the end */
|
high_len = high_offs == high_ent->str_len? 0: -1; /* -1 for the space, 0 if at the end */
|
||||||
high_offs += high_len;
|
high_offs += high_len;
|
||||||
if (low_y < 0)
|
if (low_y < 0)
|
||||||
@@ -2134,6 +2138,57 @@ gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent,
|
|||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_xtext_word_select_char (const unsigned char *ch)
|
||||||
|
{
|
||||||
|
gunichar uc;
|
||||||
|
|
||||||
|
if (!ch || !*ch)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
uc = g_utf8_get_char_validated ((const gchar *)ch, -1);
|
||||||
|
if (uc == (gunichar)-1 || uc == (gunichar)-2)
|
||||||
|
return FALSE;
|
||||||
|
return g_unichar_isalnum (uc) || uc == '_' || uc == '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_xtext_get_word_select_range (GtkXText *xtext, int x, int y, textentry **ret_ent, int *ret_off, int *ret_len)
|
||||||
|
{
|
||||||
|
textentry *ent;
|
||||||
|
int offset;
|
||||||
|
unsigned char *start, *end;
|
||||||
|
|
||||||
|
ent = gtk_xtext_find_char (xtext, x, y, &offset, NULL);
|
||||||
|
if (!ent || offset < 0 || offset >= ent->str_len)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
start = ent->str + offset;
|
||||||
|
end = g_utf8_find_next_char (start, ent->str + ent->str_len);
|
||||||
|
if (!gtk_xtext_word_select_char (start))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
while (start > ent->str)
|
||||||
|
{
|
||||||
|
unsigned char *prev = g_utf8_find_prev_char (ent->str, start);
|
||||||
|
if (!prev || !gtk_xtext_word_select_char (prev))
|
||||||
|
break;
|
||||||
|
start = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (end && end < ent->str + ent->str_len && gtk_xtext_word_select_char (end))
|
||||||
|
end = g_utf8_find_next_char (end, ent->str + ent->str_len);
|
||||||
|
|
||||||
|
if (ret_ent)
|
||||||
|
*ret_ent = ent;
|
||||||
|
if (ret_off)
|
||||||
|
*ret_off = (int)(start - ent->str);
|
||||||
|
if (ret_len)
|
||||||
|
*ret_len = (int)(end - start);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_xtext_unrender_hilight (GtkXText *xtext)
|
gtk_xtext_unrender_hilight (GtkXText *xtext)
|
||||||
{
|
{
|
||||||
@@ -2581,7 +2636,8 @@ gtk_xtext_button_press (GtkWidget * widget, GdkEventButton * event)
|
|||||||
if (event->type == GDK_2BUTTON_PRESS) /* WORD select */
|
if (event->type == GDK_2BUTTON_PRESS) /* WORD select */
|
||||||
{
|
{
|
||||||
gtk_xtext_check_mark_stamp (xtext, mask);
|
gtk_xtext_check_mark_stamp (xtext, mask);
|
||||||
if (gtk_xtext_get_word (xtext, x, y, &ent, &offset, &len, 0))
|
if (gtk_xtext_get_word_select_range (xtext, x, y, &ent, &offset, &len) ||
|
||||||
|
gtk_xtext_get_word (xtext, x, y, &ent, &offset, &len, 0))
|
||||||
{
|
{
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -4324,6 +4380,21 @@ gtk_xtext_nth (GtkXText *xtext, int line, int *subline)
|
|||||||
static int
|
static int
|
||||||
gtk_xtext_render_ents (GtkXText * xtext, textentry * enta, textentry * entb)
|
gtk_xtext_render_ents (GtkXText * xtext, textentry * enta, textentry * entb)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* On GTK3 (especially Wayland), event handlers are outside ::draw and direct
|
||||||
|
* window painting may not be presented immediately. Queue a frame instead so
|
||||||
|
* selections appear right away.
|
||||||
|
*/
|
||||||
|
#if HAVE_GTK3
|
||||||
|
if (xtext->draw_cr == NULL)
|
||||||
|
{
|
||||||
|
GtkWidget *w = GTK_WIDGET (xtext);
|
||||||
|
if (gtk_widget_get_realized (w))
|
||||||
|
gtk_widget_queue_draw (w);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
textentry *ent, *orig_ent, *tmp_ent;
|
textentry *ent, *orig_ent, *tmp_ent;
|
||||||
int line;
|
int line;
|
||||||
int lines_max;
|
int lines_max;
|
||||||
|
|||||||
Reference in New Issue
Block a user