#endif
GdkCursor *rawcursor, *textcursor, *blankcursor, *waitcursor, *currcursor;
GdkColor cols[NALLCOLOURS];
+#if !GTK_CHECK_VERSION(3,0,0)
GdkColormap *colmap;
+#endif
wchar_t *pastein_data;
int direct_to_font;
int pastein_data_len;
char *x_get_default(const char *key)
{
#ifndef NOT_X_WINDOWS
- return XGetDefault(GDK_DISPLAY(), app_name, key);
+ return XGetDefault(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),
+ app_name, key);
#else
return NULL;
#endif
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)
{
struct gui_data *inst = (struct gui_data *)data;
#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,
return TRUE;
}
+#endif
#define KEY_PRESSED(k) \
(inst->keystate[(k) / 32] & (1 << ((k) % 32)))
timer_id = g_timeout_add(ticks, timer_trigger, LONG_TO_GPOINTER(next));
}
-void fd_input_func(gpointer data, gint sourcefd, GdkInputCondition condition)
+#if GTK_CHECK_VERSION(2,0,0)
+gboolean fd_input_func(GIOChannel *source, GIOCondition condition,
+ gpointer data)
{
+ int sourcefd = g_io_channel_unix_get_fd(source);
/*
* We must process exceptional notifications before ordinary
* readability ones, or we may go straight past the urgent
* marker.
*/
+ if (condition & G_IO_PRI)
+ select_result(sourcefd, 4);
+ if (condition & G_IO_IN)
+ select_result(sourcefd, 1);
+ if (condition & G_IO_OUT)
+ select_result(sourcefd, 2);
+
+ return TRUE;
+}
+#else
+void fd_input_func(gpointer data, gint sourcefd, GdkInputCondition condition)
+{
if (condition & GDK_INPUT_EXCEPTION)
select_result(sourcefd, 4);
if (condition & GDK_INPUT_READ)
if (condition & GDK_INPUT_WRITE)
select_result(sourcefd, 2);
}
+#endif
void destroy(GtkWidget *widget, gpointer data)
{
void request_resize(void *frontend, int w, int h)
{
struct gui_data *inst = (struct gui_data *)frontend;
+
+#if !GTK_CHECK_VERSION(3,0,0)
+
int large_x, large_y;
int offset_x, offset_y;
int area_x, area_y;
gdk_window_resize(gtk_widget_get_window(inst->window),
area_x + offset_x, area_y + offset_y);
#endif
+
+#else /* GTK_CHECK_VERSION(3,0,0) */
+
+ /*
+ * In GTK3, we can do this by using gtk_window_resize_to_geometry,
+ * which uses the fact that we've already set up the main window's
+ * WM hints to reflect the terminal drawing area's resize
+ * increment (i.e. character cell) and the fixed amount of stuff
+ * round the edges.
+ */
+ gtk_window_resize_to_geometry(GTK_WINDOW(inst->window), w, h);
+
+#endif
+
}
static void real_palette_set(struct gui_data *inst, int n, int r, int g, int b)
{
- gboolean success[1];
-
inst->cols[n].red = r * 0x0101;
inst->cols[n].green = g * 0x0101;
inst->cols[n].blue = b * 0x0101;
- gdk_colormap_free_colors(inst->colmap, inst->cols + n, 1);
- gdk_colormap_alloc_colors(inst->colmap, inst->cols + n, 1,
- FALSE, TRUE, success);
- if (!success[0])
- g_error("%s: couldn't allocate colour %d (#%02x%02x%02x)\n", appname,
- n, r, g, b);
+#if !GTK_CHECK_VERSION(3,0,0)
+ {
+ gboolean success[1];
+ gdk_colormap_free_colors(inst->colmap, inst->cols + n, 1);
+ gdk_colormap_alloc_colors(inst->colmap, inst->cols + n, 1,
+ FALSE, TRUE, success);
+ if (!success[0])
+ g_error("%s: couldn't allocate colour %d (#%02x%02x%02x)\n",
+ appname, n, r, g, b);
+ }
+#endif
+}
+
+void set_gdk_window_background(GdkWindow *win, const GdkColor *col)
+{
+#if GTK_CHECK_VERSION(3,0,0)
+ /* gdk_window_set_background is deprecated; work around its
+ * absence. */
+ GdkRGBA rgba;
+ rgba.red = col->red / 65535.0;
+ rgba.green = col->green / 65535.0;
+ rgba.blue = col->blue / 65535.0;
+ rgba.alpha = 1.0;
+ gdk_window_set_background_rgba(win, &rgba);
+#else
+ gdk_window_set_background(win, col);
+#endif
}
void set_window_background(struct gui_data *inst)
{
if (inst->area && gtk_widget_get_window(inst->area))
- gdk_window_set_background(gtk_widget_get_window(inst->area),
+ set_gdk_window_background(gtk_widget_get_window(inst->area),
&inst->cols[258]);
if (inst->window && gtk_widget_get_window(inst->window))
- gdk_window_set_background(gtk_widget_get_window(inst->window),
+ set_gdk_window_background(gtk_widget_get_window(inst->window),
&inst->cols[258]);
}
0, 8, 1, 9, 2, 10, 3, 11,
4, 12, 5, 13, 6, 14, 7, 15
};
- gboolean success[NALLCOLOURS];
int i;
assert(lenof(ww) == NCFGCOLOURS);
+#if !GTK_CHECK_VERSION(3,0,0)
if (!inst->colmap) {
inst->colmap = gdk_colormap_get_system();
} else {
gdk_colormap_free_colors(inst->colmap, inst->cols, NALLCOLOURS);
}
+#endif
for (i = 0; i < NCFGCOLOURS; i++) {
inst->cols[ww[i]].red =
}
}
- gdk_colormap_alloc_colors(inst->colmap, inst->cols, NALLCOLOURS,
- FALSE, TRUE, success);
- for (i = 0; i < NALLCOLOURS; i++) {
- if (!success[i])
- g_error("%s: couldn't allocate colour %d (#%02x%02x%02x)\n",
- appname, i,
- conf_get_int_int(inst->conf, CONF_colours, i*3+0),
- conf_get_int_int(inst->conf, CONF_colours, i*3+1),
- conf_get_int_int(inst->conf, CONF_colours, i*3+2));
+#if !GTK_CHECK_VERSION(3,0,0)
+ {
+ gboolean success[NALLCOLOURS];
+ gdk_colormap_alloc_colors(inst->colmap, inst->cols, NALLCOLOURS,
+ FALSE, TRUE, success);
+ for (i = 0; i < NALLCOLOURS; i++) {
+ if (!success[i])
+ g_error("%s: couldn't allocate colour %d (#%02x%02x%02x)\n",
+ appname, i,
+ conf_get_int_int(inst->conf, CONF_colours, i*3+0),
+ conf_get_int_int(inst->conf, CONF_colours, i*3+1),
+ conf_get_int_int(inst->conf, CONF_colours, i*3+2));
+ }
}
+#endif
/* Since Default Background may have changed, ensure that space
* between text area and window border is refreshed. */
{
#ifndef NOT_X_WINDOWS
unsigned char empty[] = "";
- XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
+ Display *disp = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+ XChangeProperty(disp, GDK_ROOT_WINDOW(),
XA_CUT_BUFFER0, XA_STRING, 8, PropModeAppend, empty, 0);
- XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
+ XChangeProperty(disp, GDK_ROOT_WINDOW(),
XA_CUT_BUFFER1, XA_STRING, 8, PropModeAppend, empty, 0);
- XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
+ XChangeProperty(disp, GDK_ROOT_WINDOW(),
XA_CUT_BUFFER2, XA_STRING, 8, PropModeAppend, empty, 0);
- XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
+ XChangeProperty(disp, GDK_ROOT_WINDOW(),
XA_CUT_BUFFER3, XA_STRING, 8, PropModeAppend, empty, 0);
- XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
+ XChangeProperty(disp, GDK_ROOT_WINDOW(),
XA_CUT_BUFFER4, XA_STRING, 8, PropModeAppend, empty, 0);
- XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
+ XChangeProperty(disp, GDK_ROOT_WINDOW(),
XA_CUT_BUFFER5, XA_STRING, 8, PropModeAppend, empty, 0);
- XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
+ XChangeProperty(disp, GDK_ROOT_WINDOW(),
XA_CUT_BUFFER6, XA_STRING, 8, PropModeAppend, empty, 0);
- XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
+ XChangeProperty(disp, GDK_ROOT_WINDOW(),
XA_CUT_BUFFER7, XA_STRING, 8, PropModeAppend, empty, 0);
#endif
}
void store_cutbuffer(char * ptr, int len)
{
#ifndef NOT_X_WINDOWS
+ Display *disp = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
/* ICCCM says we must rotate the buffers before storing to buffer 0. */
- XRotateBuffers(GDK_DISPLAY(), 1);
- XStoreBytes(GDK_DISPLAY(), ptr, len);
+ XRotateBuffers(disp, 1);
+ XStoreBytes(disp, ptr, len);
#endif
}
char * retrieve_cutbuffer(int * nbytes)
{
#ifndef NOT_X_WINDOWS
+ Display *disp = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
char * ptr;
- ptr = XFetchBytes(GDK_DISPLAY(), nbytes);
+ ptr = XFetchBytes(disp, nbytes);
if (*nbytes <= 0 && ptr != 0) {
XFree(ptr);
ptr = 0;
#ifndef NOT_X_WINDOWS
XTextProperty tp;
char *list[1];
+ Display *disp = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
#endif
inst->pasteout_data_utf8 = snewn(len*6, char);
*/
#ifndef NOT_X_WINDOWS
list[0] = inst->pasteout_data_utf8;
- if (Xutf8TextListToTextProperty(GDK_DISPLAY(), list, 1,
+ if (Xutf8TextListToTextProperty(disp, list, 1,
XCompoundTextStyle, &tp) == 0) {
inst->pasteout_data_ctext = snewn(tp.nitems+1, char);
memcpy(inst->pasteout_data_ctext, tp.value, tp.nitems);
#ifndef NOT_X_WINDOWS
XTextProperty tp;
int ret, count;
+ Display *disp = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
tp.value = (unsigned char *)seldata_data;
tp.encoding = (Atom) seldata_type;
tp.format = gtk_selection_data_get_format(seldata);
tp.nitems = seldata_length;
- ret = Xutf8TextPropertyToTextList(GDK_DISPLAY(), &tp,
- &list, &count);
+ ret = Xutf8TextPropertyToTextList(disp, &tp, &list, &count);
if (ret == 0 && count == 1) {
text = list[0];
length = strlen(list[0]);
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
dctx->uctx.u.cairo.widget = GTK_WIDGET(inst->area);
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);
- 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);
+ cairo_setup_dctx(dctx);
}
#endif
return dctx;
exit(1);
}
-char *get_x_display(void *frontend)
+const char *get_x_display(void *frontend)
{
return gdk_get_display();
}
long get_windowid(void *frontend)
{
struct gui_data *inst = (struct gui_data *)frontend;
- return (long)GDK_WINDOW_XWINDOW(gtk_widget_get_window(inst->area));
+ return (long)GDK_WINDOW_XID(gtk_widget_get_window(inst->area));
}
#endif
return err;
}
-int uxsel_input_add(int fd, int rwx) {
+struct uxsel_id {
+#if GTK_CHECK_VERSION(2,0,0)
+ GIOChannel *chan;
+ guint watch_id;
+#else
+ int id;
+#endif
+};
+
+uxsel_id *uxsel_input_add(int fd, int rwx) {
+ uxsel_id *id = snew(uxsel_id);
+
+#if GTK_CHECK_VERSION(2,0,0)
+ int flags = 0;
+ if (rwx & 1) flags |= G_IO_IN;
+ if (rwx & 2) flags |= G_IO_OUT;
+ if (rwx & 4) flags |= G_IO_PRI;
+ id->chan = g_io_channel_unix_new(fd);
+ g_io_channel_set_encoding(id->chan, NULL, NULL);
+ id->watch_id = g_io_add_watch(id->chan, flags, fd_input_func, NULL);
+#else
int flags = 0;
if (rwx & 1) flags |= GDK_INPUT_READ;
if (rwx & 2) flags |= GDK_INPUT_WRITE;
if (rwx & 4) flags |= GDK_INPUT_EXCEPTION;
assert(flags);
- return gdk_input_add(fd, flags, fd_input_func, NULL);
+ id->id = gdk_input_add(fd, flags, fd_input_func, NULL);
+#endif
+
+ return id;
}
-void uxsel_input_remove(int id) {
- gdk_input_remove(id);
+void uxsel_input_remove(uxsel_id *id) {
+#if GTK_CHECK_VERSION(2,0,0)
+ g_source_remove(id->watch_id);
+ g_io_channel_unref(id->chan);
+#else
+ gdk_input_remove(id->id);
+#endif
+ sfree(id);
}
char *setup_fonts_ucs(struct gui_data *inst)
void set_window_icon(GtkWidget *window, const char *const *const *icon,
int n_icon)
{
- GdkPixmap *iconpm;
- GdkBitmap *iconmask;
#if GTK_CHECK_VERSION(2,0,0)
GList *iconlist;
int n;
+#else
+ GdkPixmap *iconpm;
+ GdkBitmap *iconmask;
#endif
if (!n_icon)
return;
gtk_widget_realize(window);
+#if GTK_CHECK_VERSION(2,0,0)
+ gtk_window_set_icon(GTK_WINDOW(window),
+ gdk_pixbuf_new_from_xpm_data((const gchar **)icon[0]));
+#else
iconpm = gdk_pixmap_create_from_xpm_d(gtk_widget_get_window(window),
&iconmask, NULL, (gchar **)icon[0]);
gdk_window_set_icon(gtk_widget_get_window(window), NULL, iconpm, iconmask);
+#endif
#if GTK_CHECK_VERSION(2,0,0)
iconlist = NULL;
gdk_pixbuf_new_from_xpm_data((const gchar **)
icon[n]));
}
- gdk_window_set_icon_list(gtk_widget_get_window(window), iconlist);
+ gtk_window_set_icon_list(GTK_WINDOW(window), iconlist);
#endif
}
G_CALLBACK(focus_event), inst);
g_signal_connect(G_OBJECT(inst->area), "configure_event",
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_CALLBACK(expose_area), inst);
+#endif
g_signal_connect(G_OBJECT(inst->area), "button_press_event",
G_CALLBACK(button_event), inst);
g_signal_connect(G_OBJECT(inst->area), "button_release_event",