From b99723a14b9bd4d81ed34fbc4195ae99f3adeabb Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 3 Feb 2018 23:52:41 +0100 Subject: Fixed the caret rendering for buffer displays. --- ChangeLog | 5 ++ src/gtkext/gtkbufferdisplay.c | 161 +++++++++++++++++++++++++++--------------- 2 files changed, 108 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index bcff8ed..9330f63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +18-02-03 Cyrille Bagard + + * src/gtkext/gtkbufferdisplay.c: + Fix the caret rendering for buffer displays. + 18-01-31 Cyrille Bagard * src/gtkext/gtkbufferdisplay.c: diff --git a/src/gtkext/gtkbufferdisplay.c b/src/gtkext/gtkbufferdisplay.c index d941ff2..e2335af 100644 --- a/src/gtkext/gtkbufferdisplay.c +++ b/src/gtkext/gtkbufferdisplay.c @@ -24,6 +24,9 @@ #include "gtkbufferdisplay.h" +#include + + #include "gtkbufferdisplay-int.h" @@ -90,11 +93,17 @@ static bool _gtk_buffer_display_move_caret_to(GtkBufferDisplay *, gint, gint); /* Déplace le curseur en effaçant son éventuelle position. */ static void gtk_buffer_display_relocate_caret(GtkBufferDisplay *, const cairo_rectangle_int_t *, const vmpa2t *); +/* Assure le clignotement du curseur à l'emplacement courant. */ +static gboolean gtk_buffer_display_refresh_caret(GtkBufferDisplay *); + /* Redémarre l'affichage du curseur à l'emplacement courant. */ static void gtk_buffer_display_restart_caret_blinking(GtkBufferDisplay *); -/* Bascule et relance l'affichage du curseur. */ -static gboolean gtk_buffer_display_refresh_caret(GtkBufferDisplay *); +/* Prépare l'actualisation de tout ou une partie de l'affichage. */ +static void gtk_buffer_display_queue_draw_caret(GtkBufferDisplay *, cairo_rectangle_int_t *); + +/* Affiche le curseur à l'écran, s'il doit l'être. */ +static void gtk_buffer_display_draw_caret(GtkBufferDisplay *, cairo_t *); @@ -252,7 +261,7 @@ static gboolean gtk_buffer_display_focus(GtkWidget *widget, GdkEventFocus *event display->caret_timer = 0; display->show_caret = true; - gtk_buffer_display_refresh_caret(display); + gtk_buffer_display_queue_draw_caret(display, NULL); } @@ -342,6 +351,7 @@ static gboolean gtk_buffer_display_draw(GtkWidget *widget, cairo_t *cr) window = gtk_widget_get_window(widget); cairo_save(cr); + gtk_cairo_transform_to_window(cr, widget, window); region = gdk_window_get_clip_region(window); @@ -435,17 +445,12 @@ static gboolean gtk_buffer_display_draw(GtkWidget *widget, cairo_t *cr) /* Curseur clignotant ? */ - /* if (gtk_widget_is_focus(widget)) - { - view->show_caret = !view->show_caret; - gtk_buffer_display_refresh_caret(view); - } - */ + gtk_buffer_display_draw_caret(display, cr); cairo_restore(cr); - return TRUE; + return FALSE; } @@ -942,19 +947,43 @@ static void gtk_buffer_display_relocate_caret(GtkBufferDisplay *display, const c else need_redraw = false; + if (!is_invalid_vmpa(&display->caret_addr)) + gtk_buffer_display_restart_caret_blinking(display); + if (need_redraw) - gtk_widget_queue_draw(GTK_WIDGET(display)); + gtk_buffer_display_queue_draw_caret(display, NULL); else if (clear_old) - { - gtk_display_panel_compute_relative_coords(GTK_DISPLAY_PANEL(display), &old_area.x, &old_area.y); + gtk_buffer_display_queue_draw_caret(display, &old_area); - gtk_widget_queue_draw_area(GTK_WIDGET(display), old_area.x, old_area.y, - old_area.width, old_area.height); +} - } - gtk_buffer_display_restart_caret_blinking(display); +/****************************************************************************** +* * +* Paramètres : display = composant GTK à manipuler. * +* * +* Description : Assure le clignotement du curseur à l'emplacement courant. * +* * +* Retour : TRUE pour poursuivre le clignotement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_buffer_display_refresh_caret(GtkBufferDisplay *display) +{ + /* Bascule l'affichage */ + display->show_caret = !display->show_caret; + + assert(!is_invalid_vmpa(&display->caret_addr)); + + if (!display->show_caret) + gtk_buffer_display_queue_draw_caret(display, &display->caret); + else + gtk_buffer_display_queue_draw_caret(display, NULL); + + return TRUE; } @@ -985,18 +1014,17 @@ static void gtk_buffer_display_restart_caret_blinking(GtkBufferDisplay *display) if (!is_invalid_vmpa(&display->caret_addr)) { - display->show_caret = false; - gtk_buffer_display_refresh_caret(display); - settings = gtk_settings_get_default(); g_object_get(settings, "gtk-cursor-blink-time", &interval, NULL); + display->show_caret = true; + g_object_ref(G_OBJECT(display)); - display->caret_timer = g_timeout_add_full(G_PRIORITY_DEFAULT, interval, - (GSourceFunc)gtk_buffer_display_refresh_caret, - display, g_object_unref); + display->caret_timer = gdk_threads_add_timeout_full(G_PRIORITY_DEFAULT, interval, + (GSourceFunc)gtk_buffer_display_refresh_caret, + display, g_object_unref); } @@ -1008,58 +1036,79 @@ static void gtk_buffer_display_restart_caret_blinking(GtkBufferDisplay *display) /****************************************************************************** * * * Paramètres : display = composant GTK à manipuler. * +* area = emplacement du curseur ou NULL toute la région. * * * -* Description : Bascule et relance l'affichage du curseur. * +* Description : Prépare l'actualisation de tout ou une partie de l'affichage.* * * -* Retour : TRUE pour poursuivre les basculements automatiques. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static gboolean gtk_buffer_display_refresh_caret(GtkBufferDisplay *display) +static void gtk_buffer_display_queue_draw_caret(GtkBufferDisplay *display, cairo_rectangle_int_t *area) { GtkWidget *widget; /* Autre version du composant */ - GdkWindow *window; /* Fenêtre de support associée */ - cairo_rectangle_int_t area; /* Zone adaptée à traiter */ - cairo_region_t *region; /* Région définie associée */ - GdkDrawingContext *drawing; /* Mécanisme de dessins */ - cairo_t *cr; /* Contexte graphique */ - GdkRGBA *color; /* Couleur du curseur */ + cairo_rectangle_int_t rect; /* Zone rectangulaire relative */ + cairo_region_t *region; /* Zone précise à redessiner */ widget = GTK_WIDGET(display); - window = gtk_widget_get_window(widget); - /** - * Si le composant n'est pas encore réalisé (ou caché, en cas de - * basculement entre les types de vues), gdk_cairo_create() ne va - * pas apprécier l'argument NULL. Donc on écourte l'opération. - */ - if (window == NULL) + if (area == NULL) + gtk_widget_queue_draw(widget); + + else { - display->show_caret = !display->show_caret; - return TRUE; - } + rect = *area; + gtk_display_panel_compute_relative_coords(GTK_DISPLAY_PANEL(display), &rect.x, &rect.y); - area = display->caret; - gtk_display_panel_compute_relative_coords(GTK_DISPLAY_PANEL(display), &area.x, &area.y); + region = cairo_region_create_rectangle(&rect); + gtk_widget_queue_draw_region(widget, region); + cairo_region_destroy(region); - /* Réinitialisation de la surface */ - if (display->show_caret) - { - display->show_caret = false; - gtk_widget_queue_draw_area(widget, area.x, area.y, area.width, area.height); } - /* Dessin */ - else + /** + * Pour une raison non comprise, le redessin n'est pris en compte que + * si le parent est concerné également... + */ + + widget = gtk_widget_get_parent(widget); + + if (GTK_IS_SCROLLED_WINDOW(widget)) + gtk_widget_queue_draw(widget); + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à manipuler. * +* cr = contexte graphique disponible pour l'opération. * +* * +* Description : Affiche le curseur à l'écran, s'il doit l'être. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_buffer_display_draw_caret(GtkBufferDisplay *display, cairo_t *cr) +{ + cairo_rectangle_int_t area; /* Zone adaptée à traiter */ + cairo_region_t *region; /* Région définie associée */ + GtkWidget *widget; /* Autre version du composant */ + GdkRGBA *color; /* Couleur du curseur */ + + if (!is_invalid_vmpa(&display->caret_addr) && display->show_caret) { - display->show_caret = true; + area = display->caret; + gtk_display_panel_compute_relative_coords(GTK_DISPLAY_PANEL(display), &area.x, &area.y); region = cairo_region_create_rectangle(&area); - drawing = gdk_window_begin_draw_frame(window, region); - cr = gdk_drawing_context_get_cairo_context(drawing); + widget = GTK_WIDGET(display); gtk_style_context_get(gtk_widget_get_style_context(widget), gtk_widget_get_state_flags(widget), @@ -1070,12 +1119,8 @@ static gboolean gtk_buffer_display_refresh_caret(GtkBufferDisplay *display) cairo_rectangle(cr, area.x, area.y, area.width, area.height); cairo_fill(cr); - gdk_window_end_draw_frame(window, drawing); - cairo_region_destroy(region); } - return TRUE; - } -- cgit v0.11.2-87-g4458