mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
Make the use of server-side backing pixmaps in GTK optional.
We won't be able to use them in GTK3, or when compiling with GTK2 and -DGDK_DISABLE_DEPRECATED. This applies to the one we use for the main terminal window, and also the small one we use for the preview pane in the unified font selector.
This commit is contained in:
parent
066bce3d19
commit
5319c659ad
@ -1970,7 +1970,9 @@ typedef struct unifontsel_internal {
|
||||
GtkWidget *filter_buttons[4];
|
||||
int n_filter_buttons;
|
||||
GtkWidget *preview_area;
|
||||
#ifndef NO_BACKING_PIXMAPS
|
||||
GdkPixmap *preview_pixmap;
|
||||
#endif
|
||||
int preview_width, preview_height;
|
||||
GdkColor preview_fg, preview_bg;
|
||||
int filter_flags;
|
||||
@ -2379,21 +2381,27 @@ static void unifontsel_draw_preview_text_inner(unifont_drawctx *dctx,
|
||||
static void unifontsel_draw_preview_text(unifontsel_internal *fs)
|
||||
{
|
||||
unifont_drawctx dctx;
|
||||
GdkWindow *target;
|
||||
|
||||
if (!fs->preview_pixmap)
|
||||
#ifndef NO_BACKING_PIXMAPS
|
||||
target = fs->preview_pixmap;
|
||||
#else
|
||||
target = gtk_widget_get_window(fs->preview_area);
|
||||
#endif
|
||||
if (!target) /* we may be called when we haven't created everything yet */
|
||||
return;
|
||||
|
||||
dctx.type = DRAWTYPE_DEFAULT;
|
||||
#ifdef DRAW_TEXT_GDK
|
||||
if (dctx.type == DRAWTYPE_GDK) {
|
||||
dctx.u.gdk.target = fs->preview_pixmap;
|
||||
dctx.u.gdk.gc = gdk_gc_new(fs->preview_pixmap);
|
||||
dctx.u.gdk.target = target;
|
||||
dctx.u.gdk.gc = gdk_gc_new(target);
|
||||
}
|
||||
#endif
|
||||
#ifdef DRAW_TEXT_CAIRO
|
||||
if (dctx.type == DRAWTYPE_CAIRO) {
|
||||
dctx.u.cairo.widget = GTK_WIDGET(fs->preview_area);
|
||||
dctx.u.cairo.cr = gdk_cairo_create(fs->preview_pixmap);
|
||||
dctx.u.cairo.cr = gdk_cairo_create(target);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2839,6 +2847,7 @@ static gint unifontsel_expose_area(GtkWidget *widget, GdkEventExpose *event,
|
||||
{
|
||||
unifontsel_internal *fs = (unifontsel_internal *)data;
|
||||
|
||||
#ifndef NO_BACKING_PIXMAPS
|
||||
if (fs->preview_pixmap) {
|
||||
gdk_draw_pixmap(gtk_widget_get_window(widget),
|
||||
(gtk_widget_get_style(widget)->fg_gc
|
||||
@ -2848,12 +2857,17 @@ static gint unifontsel_expose_area(GtkWidget *widget, GdkEventExpose *event,
|
||||
event->area.x, event->area.y,
|
||||
event->area.width, event->area.height);
|
||||
}
|
||||
#else
|
||||
unifontsel_draw_preview_text(fs);
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint unifontsel_configure_area(GtkWidget *widget,
|
||||
GdkEventConfigure *event, gpointer data)
|
||||
{
|
||||
#ifndef NO_BACKING_PIXMAPS
|
||||
unifontsel_internal *fs = (unifontsel_internal *)data;
|
||||
int ox, oy, nx, ny, x, y;
|
||||
|
||||
@ -2877,6 +2891,7 @@ static gint unifontsel_configure_area(GtkWidget *widget,
|
||||
|
||||
unifontsel_draw_preview_text(fs);
|
||||
}
|
||||
#endif
|
||||
|
||||
gdk_window_invalidate_rect(gtk_widget_get_window(widget), NULL, FALSE);
|
||||
|
||||
@ -3071,7 +3086,9 @@ unifontsel *unifontsel_new(const char *wintitle)
|
||||
* Preview widget.
|
||||
*/
|
||||
fs->preview_area = gtk_drawing_area_new();
|
||||
#ifndef NO_BACKING_PIXMAPS
|
||||
fs->preview_pixmap = NULL;
|
||||
#endif
|
||||
fs->preview_width = 0;
|
||||
fs->preview_height = 0;
|
||||
fs->preview_fg.pixel = fs->preview_bg.pixel = 0;
|
||||
@ -3179,8 +3196,10 @@ void unifontsel_destroy(unifontsel *fontsel)
|
||||
unifontsel_internal *fs = (unifontsel_internal *)fontsel;
|
||||
fontinfo *info;
|
||||
|
||||
#ifndef NO_BACKING_PIXMAPS
|
||||
if (fs->preview_pixmap)
|
||||
gdk_pixmap_unref(fs->preview_pixmap);
|
||||
#endif
|
||||
|
||||
freetree234(fs->fonts_by_selorder);
|
||||
while ((info = delpos234(fs->fonts_by_realname, 0)) != NULL)
|
||||
|
@ -29,6 +29,23 @@
|
||||
#define DRAW_TEXT_CAIRO
|
||||
#endif
|
||||
|
||||
#if GTK_CHECK_VERSION(3,0,0) || defined GDK_DISABLE_DEPRECATED
|
||||
/*
|
||||
* Where the facility is available, we prefer to render text on to a
|
||||
* persistent server-side pixmap, and redraw windows by simply
|
||||
* blitting rectangles of that pixmap into them as needed. This is
|
||||
* better for performance since we avoid expensive font rendering
|
||||
* calls where possible, and it's particularly good over a non-local X
|
||||
* connection because the response to an expose event can now be a
|
||||
* very simple rectangle-copy operation rather than a lot of fiddly
|
||||
* drawing or bitmap transfer.
|
||||
*
|
||||
* However, GTK is deprecating the use of server-side pixmaps, so we
|
||||
* have to disable this mode under some circumstances.
|
||||
*/
|
||||
#define NO_BACKING_PIXMAPS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exports from gtkfont.c.
|
||||
*/
|
||||
|
@ -79,7 +79,9 @@ struct gui_data {
|
||||
GtkWidget *menu, *specialsmenu, *specialsitem1, *specialsitem2,
|
||||
*restartitem;
|
||||
GtkWidget *sessionsmenu;
|
||||
#ifndef NO_BACKING_PIXMAPS
|
||||
GdkPixmap *pixmap;
|
||||
#endif
|
||||
#if GTK_CHECK_VERSION(2,0,0)
|
||||
GtkIMContext *imc;
|
||||
#endif
|
||||
@ -491,6 +493,7 @@ gint configure_area(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
|
||||
need_size = 1;
|
||||
}
|
||||
|
||||
#ifndef NO_BACKING_PIXMAPS
|
||||
if (inst->pixmap) {
|
||||
gdk_pixmap_unref(inst->pixmap);
|
||||
inst->pixmap = NULL;
|
||||
@ -499,6 +502,7 @@ gint configure_area(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
|
||||
inst->pixmap = gdk_pixmap_new(gtk_widget_get_window(widget),
|
||||
(w * inst->font_width + 2*inst->window_border),
|
||||
(h * inst->font_height + 2*inst->window_border), -1);
|
||||
#endif
|
||||
|
||||
draw_backing_rect(inst);
|
||||
|
||||
@ -520,6 +524,7 @@ gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data)
|
||||
{
|
||||
struct gui_data *inst = (struct gui_data *)data;
|
||||
|
||||
#ifndef NO_BACKING_PIXMAPS
|
||||
/*
|
||||
* Pass the exposed rectangle to terminal.c, which will call us
|
||||
* back to do the actual painting.
|
||||
@ -533,6 +538,35 @@ gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data)
|
||||
event->area.x, event->area.y,
|
||||
event->area.width, event->area.height);
|
||||
}
|
||||
#else
|
||||
if (inst->term) {
|
||||
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,
|
||||
(event->area.x - inst->window_border) / inst->font_width,
|
||||
(event->area.y - inst->window_border) / inst->font_height,
|
||||
(event->area.x + event->area.width -
|
||||
inst->window_border) / inst->font_width,
|
||||
(event->area.y + event->area.height -
|
||||
inst->window_border) / inst->font_height,
|
||||
!inst->term->window_update_pending);
|
||||
free_ctx(ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -2283,23 +2317,30 @@ Context get_ctx(void *frontend)
|
||||
{
|
||||
struct gui_data *inst = (struct gui_data *)frontend;
|
||||
struct draw_ctx *dctx;
|
||||
GdkWindow *target;
|
||||
|
||||
if (!gtk_widget_get_window(inst->area))
|
||||
return NULL;
|
||||
|
||||
#ifndef NO_BACKING_PIXMAPS
|
||||
target = inst->pixmap;
|
||||
#else
|
||||
target = gtk_widget_get_window(inst->area);
|
||||
#endif
|
||||
|
||||
dctx = snew(struct draw_ctx);
|
||||
dctx->inst = inst;
|
||||
dctx->uctx.type = inst->drawtype;
|
||||
#ifdef DRAW_TEXT_GDK
|
||||
if (dctx->uctx.type == DRAWTYPE_GDK) {
|
||||
dctx->uctx.u.gdk.target = inst->pixmap;
|
||||
dctx->uctx.u.gdk.target = target;
|
||||
dctx->uctx.u.gdk.gc = gdk_gc_new(gtk_widget_get_window(inst->area));
|
||||
}
|
||||
#endif
|
||||
#ifdef DRAW_TEXT_CAIRO
|
||||
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
|
||||
dctx->uctx.u.cairo.widget = GTK_WIDGET(inst->area);
|
||||
dctx->uctx.u.cairo.cr = gdk_cairo_create(inst->pixmap);
|
||||
dctx->uctx.u.cairo.cr = gdk_cairo_create(target);
|
||||
cairo_get_matrix(dctx->uctx.u.cairo.cr,
|
||||
&dctx->uctx.u.cairo.origmatrix);
|
||||
cairo_set_line_width(dctx->uctx.u.cairo.cr, 1.0);
|
||||
@ -2335,6 +2376,7 @@ void free_ctx(Context ctx)
|
||||
|
||||
static void draw_update(struct draw_ctx *dctx, int x, int y, int w, int h)
|
||||
{
|
||||
#ifndef NO_BACKING_PIXMAPS
|
||||
#ifdef DRAW_TEXT_GDK
|
||||
if (dctx->uctx.type == DRAWTYPE_GDK) {
|
||||
gdk_draw_pixmap(gtk_widget_get_window(dctx->inst->area),
|
||||
@ -2350,6 +2392,7 @@ static void draw_update(struct draw_ctx *dctx, int x, int y, int w, int h)
|
||||
gdk_gc_unref(gc);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static void draw_set_colour(struct draw_ctx *dctx, int col)
|
||||
@ -2492,6 +2535,7 @@ static void draw_stretch_after(struct draw_ctx *dctx, int x, int y,
|
||||
int h, int hdouble, int hbothalf)
|
||||
{
|
||||
#ifdef DRAW_TEXT_GDK
|
||||
#ifndef NO_BACKING_PIXMAPS
|
||||
if (dctx->uctx.type == DRAWTYPE_GDK) {
|
||||
/*
|
||||
* I can't find any plausible StretchBlt equivalent in the X
|
||||
@ -2531,7 +2575,10 @@ static void draw_stretch_after(struct draw_ctx *dctx, int x, int y,
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error No way to implement stretching in GDK without a reliable backing pixmap
|
||||
#endif
|
||||
#endif /* DRAW_TEXT_GDK */
|
||||
#ifdef DRAW_TEXT_CAIRO
|
||||
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
|
||||
cairo_set_matrix(dctx->uctx.u.cairo.cr,
|
||||
|
Loading…
Reference in New Issue
Block a user