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;
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
{
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
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;
unifontsel_draw_preview_text(fs);
}
+#endif
gdk_window_invalidate_rect(gtk_widget_get_window(widget), NULL, FALSE);
* 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;
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)
#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.
*/
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
need_size = 1;
}
+#ifndef NO_BACKING_PIXMAPS
if (inst->pixmap) {
gdk_pixmap_unref(inst->pixmap);
inst->pixmap = NULL;
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);
{
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.
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;
}
{
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);
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),
gdk_gc_unref(gc);
}
#endif
+#endif
}
static void draw_set_colour(struct draw_ctx *dctx, int col)
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
}
}
}
+#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,