1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 09:58:01 +00:00

GTK3 port: support the new "draw" signal.

This replaces GTK 1/2's "expose_event", and provides a ready-made
cairo_t to do the drawing with. My previous work has already separated
all constructions of a cairo_t from the subsequent drawing with it, so
the new draw event handlers just have to call the latter without the
former.
This commit is contained in:
Simon Tatham 2015-08-16 14:34:19 +01:00
parent 280b14f129
commit afae35eb90
3 changed files with 103 additions and 24 deletions

View File

@ -185,6 +185,14 @@ static void askpass_redraw_gdk(GdkWindow *win, struct drawing_area_ctx *ctx)
} }
#endif #endif
#if GTK_CHECK_VERSION(3,0,0)
static gint draw_area(GtkWidget *widget, cairo_t *cr, gpointer data)
{
struct drawing_area_ctx *ctx = (struct drawing_area_ctx *)data;
askpass_redraw_cairo(cr, ctx);
return TRUE;
}
#else
static gint expose_area(GtkWidget *widget, GdkEventExpose *event, static gint expose_area(GtkWidget *widget, GdkEventExpose *event,
gpointer data) gpointer data)
{ {
@ -200,6 +208,7 @@ static gint expose_area(GtkWidget *widget, GdkEventExpose *event,
return TRUE; return TRUE;
} }
#endif
static int try_grab_keyboard(struct askpass_ctx *ctx) static int try_grab_keyboard(struct askpass_ctx *ctx)
{ {
@ -288,10 +297,17 @@ static const char *gtk_askpass_setup(struct askpass_ctx *ctx,
"configure_event", "configure_event",
G_CALLBACK(configure_area), G_CALLBACK(configure_area),
&ctx->drawingareas[i]); &ctx->drawingareas[i]);
#if GTK_CHECK_VERSION(3,0,0)
g_signal_connect(G_OBJECT(ctx->drawingareas[i].area),
"draw",
G_CALLBACK(draw_area),
&ctx->drawingareas[i]);
#else
g_signal_connect(G_OBJECT(ctx->drawingareas[i].area), g_signal_connect(G_OBJECT(ctx->drawingareas[i].area),
"expose_event", "expose_event",
G_CALLBACK(expose_area), G_CALLBACK(expose_area),
&ctx->drawingareas[i]); &ctx->drawingareas[i]);
#endif
gtk_widget_show(ctx->drawingareas[i].area); gtk_widget_show(ctx->drawingareas[i].area);
} }
ctx->active_area = rand() % N_DRAWING_AREAS; ctx->active_area = rand() % N_DRAWING_AREAS;

View File

@ -2841,6 +2841,20 @@ static void alias_resolve(GtkTreeView *treeview, GtkTreePath *path,
} }
} }
#if GTK_CHECK_VERSION(3,0,0)
static gint unifontsel_draw_area(GtkWidget *widget, cairo_t *cr, gpointer data)
{
unifontsel_internal *fs = (unifontsel_internal *)data;
unifont_drawctx dctx;
dctx.type = DRAWTYPE_CAIRO;
dctx.u.cairo.widget = widget;
dctx.u.cairo.cr = cr;
unifontsel_draw_preview_text_inner(&dctx, fs);
return TRUE;
}
#else
static gint unifontsel_expose_area(GtkWidget *widget, GdkEventExpose *event, static gint unifontsel_expose_area(GtkWidget *widget, GdkEventExpose *event,
gpointer data) gpointer data)
{ {
@ -2862,6 +2876,7 @@ static gint unifontsel_expose_area(GtkWidget *widget, GdkEventExpose *event,
return TRUE; return TRUE;
} }
#endif
static gint unifontsel_configure_area(GtkWidget *widget, static gint unifontsel_configure_area(GtkWidget *widget,
GdkEventConfigure *event, gpointer data) GdkEventConfigure *event, gpointer data)
@ -3097,8 +3112,13 @@ unifontsel *unifontsel_new(const char *wintitle)
FALSE, FALSE); FALSE, FALSE);
gdk_colormap_alloc_color(gdk_colormap_get_system(), &fs->preview_bg, gdk_colormap_alloc_color(gdk_colormap_get_system(), &fs->preview_bg,
FALSE, FALSE); FALSE, FALSE);
#if GTK_CHECK_VERSION(3,0,0)
g_signal_connect(G_OBJECT(fs->preview_area), "draw",
G_CALLBACK(unifontsel_draw_area), fs);
#else
g_signal_connect(G_OBJECT(fs->preview_area), "expose_event", g_signal_connect(G_OBJECT(fs->preview_area), "expose_event",
G_CALLBACK(unifontsel_expose_area), fs); G_CALLBACK(unifontsel_expose_area), fs);
#endif
g_signal_connect(G_OBJECT(fs->preview_area), "configure_event", g_signal_connect(G_OBJECT(fs->preview_area), "configure_event",
G_CALLBACK(unifontsel_configure_area), fs); G_CALLBACK(unifontsel_configure_area), fs);
gtk_widget_set_size_request(fs->preview_area, 1, preview_height); gtk_widget_set_size_request(fs->preview_area, 1, preview_height);

View File

@ -521,6 +521,66 @@ gint configure_area(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
return TRUE; return TRUE;
} }
#ifdef DRAW_TEXT_CAIRO
static void cairo_setup_dctx(struct draw_ctx *dctx)
{
cairo_get_matrix(dctx->uctx.u.cairo.cr,
&dctx->uctx.u.cairo.origmatrix);
cairo_set_line_width(dctx->uctx.u.cairo.cr, 1.0);
cairo_set_line_cap(dctx->uctx.u.cairo.cr, CAIRO_LINE_CAP_SQUARE);
cairo_set_line_join(dctx->uctx.u.cairo.cr, CAIRO_LINE_JOIN_MITER);
/* This antialiasing setting appears to be ignored for Pango
* font rendering but honoured for stroking and filling paths;
* I don't quite understand the logic of that, but I won't
* complain since it's exactly what I happen to want */
cairo_set_antialias(dctx->uctx.u.cairo.cr, CAIRO_ANTIALIAS_NONE);
}
#endif
#if GTK_CHECK_VERSION(3,0,0)
static gint draw_area(GtkWidget *widget, cairo_t *cr, gpointer data)
{
struct gui_data *inst = (struct gui_data *)data;
if (inst->term) {
struct draw_ctx adctx, *dctx = &adctx;
GdkRectangle dirtyrect;
dctx->inst = inst;
dctx->uctx.type = DRAWTYPE_CAIRO;
dctx->uctx.u.cairo.widget = widget;
dctx->uctx.u.cairo.cr = cr;
cairo_setup_dctx(dctx);
gdk_cairo_get_clip_rectangle(cr, &dirtyrect);
/*
* As in window.c, we clear the 'immediately' flag in the
* term_paint() call if the terminal has an update pending, in
* case we're constrained within this event to only draw on
* the exposed rectangle of the window. (Because if the whole
* of a character cell needs a redraw due to a terminal
* contents change, the last thing we want is to give it a
* _partial_ redraw here due to system-imposed clipping, and
* then have the next main terminal update believe it's been
* redrawn in full.)
*
* I don't actually know if GTK draw events will constrain us
* in this way, but it's best to be careful...
*/
term_paint(inst->term, dctx,
(dirtyrect.x - inst->window_border) / inst->font_width,
(dirtyrect.y - inst->window_border) / inst->font_height,
(dirtyrect.x + dirtyrect.width -
inst->window_border) / inst->font_width,
(dirtyrect.y + dirtyrect.height -
inst->window_border) / inst->font_height,
!inst->term->window_update_pending);
}
return TRUE;
}
#else
gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data) gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{ {
struct gui_data *inst = (struct gui_data *)data; struct gui_data *inst = (struct gui_data *)data;
@ -542,20 +602,6 @@ gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data)
#else #else
if (inst->term) { if (inst->term) {
Context ctx = get_ctx(inst); Context ctx = get_ctx(inst);
/*
* As in window.c, we clear the 'immediately' flag in the
* term_paint() call if the terminal has an update pending, in
* case we're constrained within this event to only draw on
* the exposed rectangle of the window. (Because if the whole
* of a character cell needs a redraw due to a terminal
* contents change, the last thing we want is to give it a
* _partial_ redraw here due to system-imposed clipping, and
* then have the next main terminal update believe it's been
* redrawn in full.)
*
* I don't actually know if GTK expose events will constrain
* us in this way, but it's best to be careful...
*/
term_paint(inst->term, ctx, term_paint(inst->term, ctx,
(event->area.x - inst->window_border) / inst->font_width, (event->area.x - inst->window_border) / inst->font_width,
(event->area.y - inst->window_border) / inst->font_height, (event->area.y - inst->window_border) / inst->font_height,
@ -570,6 +616,7 @@ gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data)
return TRUE; return TRUE;
} }
#endif
#define KEY_PRESSED(k) \ #define KEY_PRESSED(k) \
(inst->keystate[(k) / 32] & (1 << ((k) % 32))) (inst->keystate[(k) / 32] & (1 << ((k) % 32)))
@ -2362,16 +2409,7 @@ Context get_ctx(void *frontend)
if (dctx->uctx.type == DRAWTYPE_CAIRO) { if (dctx->uctx.type == DRAWTYPE_CAIRO) {
dctx->uctx.u.cairo.widget = GTK_WIDGET(inst->area); dctx->uctx.u.cairo.widget = GTK_WIDGET(inst->area);
dctx->uctx.u.cairo.cr = gdk_cairo_create(target); dctx->uctx.u.cairo.cr = gdk_cairo_create(target);
cairo_get_matrix(dctx->uctx.u.cairo.cr, cairo_setup_dctx(dctx);
&dctx->uctx.u.cairo.origmatrix);
cairo_set_line_width(dctx->uctx.u.cairo.cr, 1.0);
cairo_set_line_cap(dctx->uctx.u.cairo.cr, CAIRO_LINE_CAP_SQUARE);
cairo_set_line_join(dctx->uctx.u.cairo.cr, CAIRO_LINE_JOIN_MITER);
/* This antialiasing setting appears to be ignored for Pango
* font rendering but honoured for stroking and filling paths;
* I don't quite understand the logic of that, but I won't
* complain since it's exactly what I happen to want */
cairo_set_antialias(dctx->uctx.u.cairo.cr, CAIRO_ANTIALIAS_NONE);
} }
#endif #endif
return dctx; return dctx;
@ -4172,8 +4210,13 @@ int pt_main(int argc, char **argv)
G_CALLBACK(focus_event), inst); G_CALLBACK(focus_event), inst);
g_signal_connect(G_OBJECT(inst->area), "configure_event", g_signal_connect(G_OBJECT(inst->area), "configure_event",
G_CALLBACK(configure_area), inst); G_CALLBACK(configure_area), inst);
#if GTK_CHECK_VERSION(3,0,0)
g_signal_connect(G_OBJECT(inst->area), "draw",
G_CALLBACK(draw_area), inst);
#else
g_signal_connect(G_OBJECT(inst->area), "expose_event", g_signal_connect(G_OBJECT(inst->area), "expose_event",
G_CALLBACK(expose_area), inst); G_CALLBACK(expose_area), inst);
#endif
g_signal_connect(G_OBJECT(inst->area), "button_press_event", g_signal_connect(G_OBJECT(inst->area), "button_press_event",
G_CALLBACK(button_event), inst); G_CALLBACK(button_event), inst);
g_signal_connect(G_OBJECT(inst->area), "button_release_event", g_signal_connect(G_OBJECT(inst->area), "button_release_event",