Improve key rendering and eliminate two deprecation warnings
- Replace two calls to deprecated gdk_cairo_create() - Alleviate asymmetry between rendering pressed and released keys by consistenly clipping the same area up front to avoid artefacts - make sure pressed and released keys are shown immediately by calling gdk_window_invalidate_rect() - improve consistency between render_(pressed|locked|released)_key - improve code flow
This commit is contained in:
@ -31,6 +31,7 @@
|
|||||||
#include <canberra-gtk.h>
|
#include <canberra-gtk.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "eek-gtk-keyboard.h"
|
#include "eek-gtk-keyboard.h"
|
||||||
@ -479,6 +480,45 @@ magnify_bounds (GtkWidget *self,
|
|||||||
large_bounds->y = CLAMP(y, 0, allocation.height - large_bounds->height);
|
large_bounds->y = CLAMP(y, 0, allocation.height - large_bounds->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Alleviate the asymmetry between drawing a pressed key and a released key,
|
||||||
|
* and consistently draw to the exact same area.
|
||||||
|
*
|
||||||
|
* By saving the dirty rectangle we can limit drawing of the backbuffer to
|
||||||
|
* the screen as well, eg gdk_window_invalidate_rect() instead of
|
||||||
|
* gtk_widget_queue_draw() which redraws the entire widget.
|
||||||
|
*
|
||||||
|
* b1 is mandatory, b2 is optional
|
||||||
|
*/
|
||||||
|
static GdkRectangle
|
||||||
|
clip_bounds_to_dirty_rectangle (cairo_t *cr, EekBounds *b1, EekBounds *b2)
|
||||||
|
{
|
||||||
|
if (b2)
|
||||||
|
cairo_rectangle (cr, b2->x, b2->y, b2->width, b2->height);
|
||||||
|
|
||||||
|
cairo_rectangle (cr, b1->x, b1->y, b1->width, b1->height);
|
||||||
|
cairo_clip (cr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save the clipped region to a bounding box so we can limit
|
||||||
|
* the drawing of the backbuffer to the screen to the same area
|
||||||
|
*/
|
||||||
|
cairo_rectangle_t bbox;
|
||||||
|
|
||||||
|
cairo_clip_extents (cr, &bbox.x, &bbox.y, &bbox.width, &bbox.height);
|
||||||
|
|
||||||
|
/* convert double to int, making sure r strictly covers bbox to avoid
|
||||||
|
* artefacts. floor() is unnecessary, ceil() is not */
|
||||||
|
GdkRectangle r = {
|
||||||
|
floor (bbox.x),
|
||||||
|
floor (bbox.y),
|
||||||
|
ceil (bbox.width),
|
||||||
|
ceil (bbox.height)
|
||||||
|
};
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
render_pressed_key (GtkWidget *widget,
|
render_pressed_key (GtkWidget *widget,
|
||||||
EekKey *key)
|
EekKey *key)
|
||||||
@ -486,16 +526,20 @@ render_pressed_key (GtkWidget *widget,
|
|||||||
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
|
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
|
||||||
EekBounds bounds, large_bounds;
|
EekBounds bounds, large_bounds;
|
||||||
|
|
||||||
|
GdkWindow *window = gtk_widget_get_window (widget);
|
||||||
|
cairo_region_t *region = gdk_window_get_clip_region (window);
|
||||||
|
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
|
||||||
|
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
|
||||||
|
|
||||||
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
|
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
|
||||||
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
|
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
|
||||||
|
|
||||||
GdkWindow *window = GDK_DRAWABLE (gtk_widget_get_window (widget));
|
/*
|
||||||
cairo_region_t *region = gdk_window_get_clip_region (window);
|
* clip to limit drawing to backbuffer and save clip region to dirty_rect
|
||||||
|
* to limit redrawing of the backbuffer to the same area
|
||||||
|
*/
|
||||||
|
GdkRectangle dirty_rect = clip_bounds_to_dirty_rectangle (cr, &bounds, &large_bounds);
|
||||||
|
|
||||||
GdkDrawingContext *context = gdk_window_begin_draw_frame(
|
|
||||||
window, region
|
|
||||||
);
|
|
||||||
cairo_t *cr = gdk_drawing_context_get_cairo_context(context);
|
|
||||||
cairo_save (cr);
|
cairo_save (cr);
|
||||||
cairo_translate (cr, bounds.x, bounds.y);
|
cairo_translate (cr, bounds.x, bounds.y);
|
||||||
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
|
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
|
||||||
@ -506,8 +550,12 @@ render_pressed_key (GtkWidget *widget,
|
|||||||
eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE);
|
eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE);
|
||||||
cairo_restore (cr);
|
cairo_restore (cr);
|
||||||
|
|
||||||
gdk_window_end_draw_frame(window, context);
|
gdk_window_end_draw_frame (window, context);
|
||||||
cairo_region_destroy(region);
|
|
||||||
|
cairo_region_destroy (region);
|
||||||
|
|
||||||
|
/* force immediate drawing of the backbuffer to the screen */
|
||||||
|
gdk_window_invalidate_rect (window, &dirty_rect, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -516,15 +564,29 @@ render_locked_key (GtkWidget *widget,
|
|||||||
{
|
{
|
||||||
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
|
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
|
||||||
EekBounds bounds;
|
EekBounds bounds;
|
||||||
cairo_t *cr;
|
|
||||||
|
|
||||||
cr = gdk_cairo_create (GDK_DRAWABLE (gtk_widget_get_window (widget)));
|
GdkWindow *window = gtk_widget_get_window (widget);
|
||||||
|
cairo_region_t *region = gdk_window_get_clip_region (window);
|
||||||
|
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
|
||||||
|
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
|
||||||
|
|
||||||
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
|
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* clip to limit drawing to backbuffer and save clip region to dirty_rect
|
||||||
|
* to limit redrawing of the backbuffer to the same area
|
||||||
|
*/
|
||||||
|
GdkRectangle dirty_rect = clip_bounds_to_dirty_rectangle (cr, &bounds, NULL);
|
||||||
|
|
||||||
cairo_translate (cr, bounds.x, bounds.y);
|
cairo_translate (cr, bounds.x, bounds.y);
|
||||||
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
|
eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
|
||||||
|
|
||||||
cairo_destroy (cr);
|
gdk_window_end_draw_frame (window, context);
|
||||||
|
|
||||||
|
cairo_region_destroy (region);
|
||||||
|
|
||||||
|
/* force immediate drawing of the backbuffer to the screen */
|
||||||
|
gdk_window_invalidate_rect (window, &dirty_rect, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -533,26 +595,29 @@ render_released_key (GtkWidget *widget,
|
|||||||
{
|
{
|
||||||
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
|
EekGtkKeyboardPrivate *priv = EEK_GTK_KEYBOARD_GET_PRIVATE(widget);
|
||||||
EekBounds bounds, large_bounds;
|
EekBounds bounds, large_bounds;
|
||||||
cairo_t *cr;
|
|
||||||
|
|
||||||
cr = gdk_cairo_create (GDK_DRAWABLE (gtk_widget_get_window (widget)));
|
GdkWindow *window = gtk_widget_get_window (widget);
|
||||||
|
cairo_region_t *region = gdk_window_get_clip_region (window);
|
||||||
|
GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
|
||||||
|
cairo_t *cr = gdk_drawing_context_get_cairo_context (context);
|
||||||
|
|
||||||
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
|
eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
|
||||||
magnify_bounds (widget, &bounds, &large_bounds, 2.0);
|
magnify_bounds (widget, &bounds, &large_bounds, 1.5);
|
||||||
cairo_rectangle (cr,
|
|
||||||
large_bounds.x,
|
/*
|
||||||
large_bounds.y,
|
* clip to limit drawing to backbuffer and save clip region to dirty_rect
|
||||||
large_bounds.width,
|
* to limit redrawing of the backbuffer to the same area
|
||||||
large_bounds.height);
|
*/
|
||||||
cairo_rectangle (cr,
|
GdkRectangle dirty_rect = clip_bounds_to_dirty_rectangle(cr, &bounds, &large_bounds);
|
||||||
bounds.x,
|
|
||||||
bounds.y,
|
|
||||||
bounds.width,
|
|
||||||
bounds.height);
|
|
||||||
cairo_clip (cr);
|
|
||||||
|
|
||||||
eek_renderer_render_keyboard (priv->renderer, cr);
|
eek_renderer_render_keyboard (priv->renderer, cr);
|
||||||
cairo_destroy (cr);
|
|
||||||
|
gdk_window_end_draw_frame (window, context);
|
||||||
|
|
||||||
|
cairo_region_destroy (region);
|
||||||
|
|
||||||
|
/* force immediate drawing of the backbuffer to the screen */
|
||||||
|
gdk_window_invalidate_rect (window, &dirty_rect, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
Reference in New Issue
Block a user