#if !GTK_CHECK_VERSION(3,0,0)
#include <gdk/gdkkeysyms.h>
#endif
-#ifndef NOT_X_WINDOWS
-#include <gdk/gdkx.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#endif
#if GTK_CHECK_VERSION(2,0,0)
#include <gtk/gtkimmodule.h>
#include "gtkcompat.h"
#include "gtkfont.h"
+#ifndef NOT_X_WINDOWS
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#endif
+
#define CAT2(x,y) x ## y
#define CAT(x,y) CAT2(x,y)
#define ASSERT(x) enum {CAT(assertion_,__LINE__) = 1 / (x)}
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
#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;
int bold_style;
int window_border;
int cursor_type;
+ int drawtype;
};
static void cache_conf_values(struct gui_data *inst)
}
struct draw_ctx {
- GdkGC *gc;
struct gui_data *inst;
+ unifont_drawctx uctx;
};
static int send_raw_mouse;
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
update_mouseptr(inst);
}
-void draw_backing_rect(struct gui_data *inst)
-{
- GdkGC *gc = gdk_gc_new(gtk_widget_get_window(inst->area));
- gdk_gc_set_foreground(gc, &inst->cols[258]); /* default background */
- gdk_draw_rectangle(inst->pixmap, gc, 1, 0, 0,
- inst->width * inst->font_width + 2*inst->window_border,
- inst->height * inst->font_height + 2*inst->window_border);
- gdk_gc_unref(gc);
-}
+static void draw_backing_rect(struct gui_data *inst);
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;
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);
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;
+#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);
+ 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;
}
+#endif
#define KEY_PRESSED(k) \
(inst->keystate[(k) / 32] & (1 << ((k) % 32)))
special = use_ucsoutput = FALSE;
output_charset = CS_ISO8859_1;
+#ifdef KEY_EVENT_DIAGNOSTICS
+ /*
+ * Condition this mess in if you want to debug keyboard events as
+ * they come in to this function (e.g. because some particular
+ * port of GDK is producing an unexpected arrangement of
+ * modifiers).
+ */
+#define TRY(val, prefix, string) \
+ if ((val) == prefix ## string) printf("%s", #string); else
+#define GIVE_UP(val) \
+ printf("%d", (int)(val))
+#define TRY_MASK(val, prefix, string, suffix) \
+ if ((val) & prefix ## string ## suffix) { \
+ (val) &= ~ prefix ## string ## suffix; \
+ printf("%s", #string); \
+ if (val) printf("|"); \
+ }
+#define GIVE_UP_MASK(val) \
+ do \
+ { \
+ if ((val)) printf("%d", (int)(val)); \
+ } while (0)
+
+ printf("key_event: type=");
+ TRY(event->type, GDK_KEY_, PRESS)
+ TRY(event->type, GDK_KEY_, RELEASE)
+ GIVE_UP(event->type);
+ printf(" keyval=");
+ TRY(event->keyval, GDK_KEY_, Alt_L)
+ TRY(event->keyval, GDK_KEY_, Alt_R)
+ TRY(event->keyval, GDK_KEY_, BackSpace)
+ TRY(event->keyval, GDK_KEY_, Begin)
+ TRY(event->keyval, GDK_KEY_, Break)
+ TRY(event->keyval, GDK_KEY_, Delete)
+ TRY(event->keyval, GDK_KEY_, Down)
+ TRY(event->keyval, GDK_KEY_, End)
+ TRY(event->keyval, GDK_KEY_, Escape)
+ TRY(event->keyval, GDK_KEY_, F10)
+ TRY(event->keyval, GDK_KEY_, F11)
+ TRY(event->keyval, GDK_KEY_, F12)
+ TRY(event->keyval, GDK_KEY_, F13)
+ TRY(event->keyval, GDK_KEY_, F14)
+ TRY(event->keyval, GDK_KEY_, F15)
+ TRY(event->keyval, GDK_KEY_, F16)
+ TRY(event->keyval, GDK_KEY_, F17)
+ TRY(event->keyval, GDK_KEY_, F18)
+ TRY(event->keyval, GDK_KEY_, F19)
+ TRY(event->keyval, GDK_KEY_, F1)
+ TRY(event->keyval, GDK_KEY_, F20)
+ TRY(event->keyval, GDK_KEY_, F2)
+ TRY(event->keyval, GDK_KEY_, F3)
+ TRY(event->keyval, GDK_KEY_, F4)
+ TRY(event->keyval, GDK_KEY_, F5)
+ TRY(event->keyval, GDK_KEY_, F6)
+ TRY(event->keyval, GDK_KEY_, F7)
+ TRY(event->keyval, GDK_KEY_, F8)
+ TRY(event->keyval, GDK_KEY_, F9)
+ TRY(event->keyval, GDK_KEY_, Home)
+ TRY(event->keyval, GDK_KEY_, Insert)
+ TRY(event->keyval, GDK_KEY_, ISO_Left_Tab)
+ TRY(event->keyval, GDK_KEY_, KP_0)
+ TRY(event->keyval, GDK_KEY_, KP_1)
+ TRY(event->keyval, GDK_KEY_, KP_2)
+ TRY(event->keyval, GDK_KEY_, KP_3)
+ TRY(event->keyval, GDK_KEY_, KP_4)
+ TRY(event->keyval, GDK_KEY_, KP_5)
+ TRY(event->keyval, GDK_KEY_, KP_6)
+ TRY(event->keyval, GDK_KEY_, KP_7)
+ TRY(event->keyval, GDK_KEY_, KP_8)
+ TRY(event->keyval, GDK_KEY_, KP_9)
+ TRY(event->keyval, GDK_KEY_, KP_Add)
+ TRY(event->keyval, GDK_KEY_, KP_Begin)
+ TRY(event->keyval, GDK_KEY_, KP_Decimal)
+ TRY(event->keyval, GDK_KEY_, KP_Delete)
+ TRY(event->keyval, GDK_KEY_, KP_Divide)
+ TRY(event->keyval, GDK_KEY_, KP_Down)
+ TRY(event->keyval, GDK_KEY_, KP_End)
+ TRY(event->keyval, GDK_KEY_, KP_Enter)
+ TRY(event->keyval, GDK_KEY_, KP_Home)
+ TRY(event->keyval, GDK_KEY_, KP_Insert)
+ TRY(event->keyval, GDK_KEY_, KP_Left)
+ TRY(event->keyval, GDK_KEY_, KP_Multiply)
+ TRY(event->keyval, GDK_KEY_, KP_Page_Down)
+ TRY(event->keyval, GDK_KEY_, KP_Page_Up)
+ TRY(event->keyval, GDK_KEY_, KP_Right)
+ TRY(event->keyval, GDK_KEY_, KP_Subtract)
+ TRY(event->keyval, GDK_KEY_, KP_Up)
+ TRY(event->keyval, GDK_KEY_, Left)
+ TRY(event->keyval, GDK_KEY_, Meta_L)
+ TRY(event->keyval, GDK_KEY_, Meta_R)
+ TRY(event->keyval, GDK_KEY_, Num_Lock)
+ TRY(event->keyval, GDK_KEY_, Page_Down)
+ TRY(event->keyval, GDK_KEY_, Page_Up)
+ TRY(event->keyval, GDK_KEY_, Return)
+ TRY(event->keyval, GDK_KEY_, Right)
+ TRY(event->keyval, GDK_KEY_, Tab)
+ TRY(event->keyval, GDK_KEY_, Up)
+ TRY(event->keyval, GDK_KEY_, Shift_L)
+ TRY(event->keyval, GDK_KEY_, Shift_R)
+ TRY(event->keyval, GDK_KEY_, Control_L)
+ TRY(event->keyval, GDK_KEY_, Control_R)
+ TRY(event->keyval, GDK_KEY_, Caps_Lock)
+ TRY(event->keyval, GDK_KEY_, Shift_Lock)
+ TRY(event->keyval, GDK_KEY_, Super_L)
+ TRY(event->keyval, GDK_KEY_, Super_R)
+ TRY(event->keyval, GDK_KEY_, Hyper_L)
+ TRY(event->keyval, GDK_KEY_, Hyper_R)
+ GIVE_UP(event->keyval);
+ printf(" state=");
+ {
+ int val = event->state;
+ TRY_MASK(val, GDK_, SHIFT, _MASK)
+ TRY_MASK(val, GDK_, LOCK, _MASK)
+ TRY_MASK(val, GDK_, CONTROL, _MASK)
+ TRY_MASK(val, GDK_, MOD1, _MASK)
+ TRY_MASK(val, GDK_, MOD2, _MASK)
+ TRY_MASK(val, GDK_, MOD3, _MASK)
+ TRY_MASK(val, GDK_, MOD4, _MASK)
+ TRY_MASK(val, GDK_, MOD5, _MASK)
+ TRY_MASK(val, GDK_, SUPER, _MASK)
+ TRY_MASK(val, GDK_, HYPER, _MASK)
+ TRY_MASK(val, GDK_, META, _MASK)
+ GIVE_UP_MASK(val);
+ }
+ printf(" hardware_keycode=%d is_modifier=%s\n",
+ (int)event->hardware_keycode, event->is_modifier ? "TRUE" : "FALSE");
+#endif /* KEY_EVENT_DIAGNOSTICS */
+
/*
* If Alt is being released after typing an Alt+numberpad
* sequence, we should generate the code that was typed.
end = 2;
}
+ /* Some GTK backends (e.g. Quartz) do not change event->string
+ * in response to the Control modifier. So we do it ourselves
+ * here, if it's not already happened.
+ *
+ * The translations below are in line with X11 policy as far
+ * as I know. */
+ if ((event->state & GDK_CONTROL_MASK) && end == 2) {
+ if (output[1] >= '3' && output[1] <= '7') {
+ /* ^3,...,^7 map to 0x1B,...,0x1F */
+ output[1] += '\x1B' - '3';
+ } else if (output[1] == '2') {
+ /* ^2 is ^@, i.e. \0 */
+ output[1] = '\0';
+ } else if (output[1] == '8') {
+ /* ^8 is DEL */
+ output[1] = '\x7F';
+ } else if (output[1] == '/') {
+ /* ^/ is the same as ^_ */
+ output[1] = '\x1F';
+ } else if (output[1] >= 0x40 && output[1] < 0x7F) {
+ /* Everything anywhere near the alphabetics just gets
+ * masked. */
+ output[1] &= 0x1F;
+ }
+ /* Anything else, e.g. '0', is unchanged. */
+ }
+
/* Control-Break sends a Break special to the backend */
if (event->keyval == GDK_KEY_Break &&
(event->state & GDK_CONTROL_MASK)) {
* when we get out of the next one. */
request_post_main(inst);
}
-
- return 0;
}
static gint idle_toplevel_callback_func(gpointer data)
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
+ {
+ /* For GTK1, which doesn't have a 'const' on
+ * gdk_window_set_background's second parameter type. */
+ GdkColor col_mutable = *col;
+ gdk_window_set_background(win, &col_mutable);
+ }
+#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]);
{
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->gc = gdk_gc_new(gtk_widget_get_window(inst->area));
+ dctx->uctx.type = inst->drawtype;
+#ifdef DRAW_TEXT_GDK
+ if (dctx->uctx.type == DRAWTYPE_GDK) {
+ 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(target);
+ cairo_setup_dctx(dctx);
+ }
+#endif
return dctx;
}
{
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
/* struct gui_data *inst = dctx->inst; */
- GdkGC *gc = dctx->gc;
- gdk_gc_unref(gc);
+#ifdef DRAW_TEXT_GDK
+ if (dctx->uctx.type == DRAWTYPE_GDK) {
+ gdk_gc_unref(dctx->uctx.u.gdk.gc);
+ }
+#endif
+#ifdef DRAW_TEXT_CAIRO
+ if (dctx->uctx.type == DRAWTYPE_CAIRO) {
+ cairo_destroy(dctx->uctx.u.cairo.cr);
+ }
+#endif
sfree(dctx);
}
+
+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),
+ dctx->uctx.u.gdk.gc, dctx->inst->pixmap,
+ x, y, x, y, w, h);
+ }
+#endif
+#ifdef DRAW_TEXT_CAIRO /* FIXME: and not GTK3 where a cairo_t is all we have */
+ if (dctx->uctx.type == DRAWTYPE_CAIRO) {
+ GdkGC *gc = gdk_gc_new(gtk_widget_get_window(dctx->inst->area));
+ gdk_draw_pixmap(gtk_widget_get_window(dctx->inst->area),
+ gc, dctx->inst->pixmap, x, y, x, y, w, h);
+ gdk_gc_unref(gc);
+ }
+#endif
+#endif
+}
+
+static void draw_set_colour(struct draw_ctx *dctx, int col)
+{
+#ifdef DRAW_TEXT_GDK
+ if (dctx->uctx.type == DRAWTYPE_GDK) {
+ gdk_gc_set_foreground(dctx->uctx.u.gdk.gc, &dctx->inst->cols[col]);
+ }
+#endif
+#ifdef DRAW_TEXT_CAIRO
+ if (dctx->uctx.type == DRAWTYPE_CAIRO) {
+ cairo_set_source_rgb(dctx->uctx.u.cairo.cr,
+ dctx->inst->cols[col].red / 65535.0,
+ dctx->inst->cols[col].green / 65535.0,
+ dctx->inst->cols[col].blue / 65535.0);
+ }
+#endif
+}
+
+static void draw_rectangle(struct draw_ctx *dctx, int filled,
+ int x, int y, int w, int h)
+{
+#ifdef DRAW_TEXT_GDK
+ if (dctx->uctx.type == DRAWTYPE_GDK) {
+ gdk_draw_rectangle(dctx->uctx.u.gdk.target, dctx->uctx.u.gdk.gc,
+ filled, x, y, w, h);
+ }
+#endif
+#ifdef DRAW_TEXT_CAIRO
+ if (dctx->uctx.type == DRAWTYPE_CAIRO) {
+ cairo_new_path(dctx->uctx.u.cairo.cr);
+ if (filled) {
+ cairo_rectangle(dctx->uctx.u.cairo.cr, x, y, w, h);
+ cairo_fill(dctx->uctx.u.cairo.cr);
+ } else {
+ cairo_rectangle(dctx->uctx.u.cairo.cr,
+ x + 0.5, y + 0.5, w, h);
+ cairo_close_path(dctx->uctx.u.cairo.cr);
+ cairo_stroke(dctx->uctx.u.cairo.cr);
+ }
+ }
+#endif
+}
+
+static void draw_clip(struct draw_ctx *dctx, int x, int y, int w, int h)
+{
+#ifdef DRAW_TEXT_GDK
+ if (dctx->uctx.type == DRAWTYPE_GDK) {
+ GdkRectangle r;
+
+ r.x = x;
+ r.y = y;
+ r.width = w;
+ r.height = h;
+
+ gdk_gc_set_clip_rectangle(dctx->uctx.u.gdk.gc, &r);
+ }
+#endif
+#ifdef DRAW_TEXT_CAIRO
+ if (dctx->uctx.type == DRAWTYPE_CAIRO) {
+ cairo_reset_clip(dctx->uctx.u.cairo.cr);
+ cairo_new_path(dctx->uctx.u.cairo.cr);
+ cairo_rectangle(dctx->uctx.u.cairo.cr, x, y, w, h);
+ cairo_clip(dctx->uctx.u.cairo.cr);
+ }
+#endif
+}
+
+static void draw_point(struct draw_ctx *dctx, int x, int y)
+{
+#ifdef DRAW_TEXT_GDK
+ if (dctx->uctx.type == DRAWTYPE_GDK) {
+ gdk_draw_point(dctx->uctx.u.gdk.target, dctx->uctx.u.gdk.gc, x, y);
+ }
+#endif
+#ifdef DRAW_TEXT_CAIRO
+ if (dctx->uctx.type == DRAWTYPE_CAIRO) {
+ cairo_new_path(dctx->uctx.u.cairo.cr);
+ cairo_rectangle(dctx->uctx.u.cairo.cr, x, y, 1, 1);
+ cairo_fill(dctx->uctx.u.cairo.cr);
+ }
+#endif
+}
+
+static void draw_line(struct draw_ctx *dctx, int x0, int y0, int x1, int y1)
+{
+#ifdef DRAW_TEXT_GDK
+ if (dctx->uctx.type == DRAWTYPE_GDK) {
+ gdk_draw_line(dctx->uctx.u.gdk.target, dctx->uctx.u.gdk.gc,
+ x0, y0, x1, y1);
+ }
+#endif
+#ifdef DRAW_TEXT_CAIRO
+ if (dctx->uctx.type == DRAWTYPE_CAIRO) {
+ cairo_new_path(dctx->uctx.u.cairo.cr);
+ cairo_move_to(dctx->uctx.u.cairo.cr, x0 + 0.5, y0 + 0.5);
+ cairo_line_to(dctx->uctx.u.cairo.cr, x1 + 0.5, y1 + 0.5);
+ cairo_stroke(dctx->uctx.u.cairo.cr);
+ }
+#endif
+}
+
+static void draw_stretch_before(struct draw_ctx *dctx, int x, int y,
+ int w, int wdouble,
+ int h, int hdouble, int hbothalf)
+{
+#ifdef DRAW_TEXT_CAIRO
+ if (dctx->uctx.type == DRAWTYPE_CAIRO) {
+ cairo_matrix_t matrix;
+
+ matrix.xy = 0;
+ matrix.yx = 0;
+
+ if (wdouble) {
+ matrix.xx = 2;
+ matrix.x0 = -x;
+ } else {
+ matrix.xx = 1;
+ matrix.x0 = 0;
+ }
+
+ if (hdouble) {
+ matrix.yy = 2;
+ if (hbothalf) {
+ matrix.y0 = -(y+h);
+ } else {
+ matrix.y0 = -y;
+ }
+ } else {
+ matrix.yy = 1;
+ matrix.y0 = 0;
+ }
+ cairo_transform(dctx->uctx.u.cairo.cr, &matrix);
+ }
+#endif
+}
+
+static void draw_stretch_after(struct draw_ctx *dctx, int x, int y,
+ int w, int wdouble,
+ 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
+ * server, so I'm going to do this the slow and painful way.
+ * This will involve repeated calls to gdk_draw_pixmap() to
+ * stretch the text horizontally. It's O(N^2) in time and O(N)
+ * in network bandwidth, but you try thinking of a better way.
+ * :-(
+ */
+ int i;
+ if (wdouble) {
+ for (i = 0; i < w; i++) {
+ gdk_draw_pixmap(dctx->uctx.u.gdk.target,
+ dctx->uctx.u.gdk.gc,
+ dctx->uctx.u.gdk.target,
+ x + 2*i, y,
+ x + 2*i+1, y,
+ w - i, h);
+ }
+ w *= 2;
+ }
+
+ if (hdouble) {
+ int dt, db;
+ /* Now stretch vertically, in the same way. */
+ if (hbothalf)
+ dt = 0, db = 1;
+ else
+ dt = 1, db = 0;
+ for (i = 0; i < h; i += 2) {
+ gdk_draw_pixmap(dctx->uctx.u.gdk.target,
+ dctx->uctx.u.gdk.gc,
+ dctx->uctx.u.gdk.target,
+ x, y + dt*i + db,
+ x, y + dt*(i+1),
+ w, h-i-1);
+ }
+ }
+ }
+#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,
+ &dctx->uctx.u.cairo.origmatrix);
+ }
+#endif
+}
+
+static void draw_backing_rect(struct gui_data *inst)
+{
+ struct draw_ctx *dctx = get_ctx(inst);
+ draw_set_colour(dctx, 258);
+ draw_rectangle(dctx, 1, 0, 0,
+ inst->width * inst->font_width + 2*inst->window_border,
+ inst->height * inst->font_height + 2*inst->window_border);
+ free_ctx(dctx);
+}
+
/*
* Draw a line of text in the window, at given character
* coordinates, in given attributes.
{
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
struct gui_data *inst = dctx->inst;
- GdkGC *gc = dctx->gc;
int ncombining, combining;
int nfg, nbg, t, fontid, shadow, rlen, widefactor, bold;
int monochrome =
} else
rlen = len;
- {
- GdkRectangle r;
+ draw_clip(dctx,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border,
+ rlen*widefactor*inst->font_width,
+ inst->font_height);
- r.x = x*inst->font_width+inst->window_border;
- r.y = y*inst->font_height+inst->window_border;
- r.width = rlen*widefactor*inst->font_width;
- r.height = inst->font_height;
- gdk_gc_set_clip_rectangle(gc, &r);
+ if ((lattr & LATTR_MODE) != LATTR_NORM) {
+ draw_stretch_before(dctx,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border,
+ rlen*widefactor*inst->font_width, TRUE,
+ inst->font_height,
+ ((lattr & LATTR_MODE) != LATTR_WIDE),
+ ((lattr & LATTR_MODE) == LATTR_BOT));
}
- gdk_gc_set_foreground(gc, &inst->cols[nbg]);
- gdk_draw_rectangle(inst->pixmap, gc, 1,
- x*inst->font_width+inst->window_border,
- y*inst->font_height+inst->window_border,
- rlen*widefactor*inst->font_width, inst->font_height);
+ draw_set_colour(dctx, nbg);
+ draw_rectangle(dctx, TRUE,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border,
+ rlen*widefactor*inst->font_width, inst->font_height);
- gdk_gc_set_foreground(gc, &inst->cols[nfg]);
+ draw_set_colour(dctx, nfg);
for (combining = 0; combining < ncombining; combining++) {
- unifont_draw_text(inst->pixmap, gc, inst->fonts[fontid],
+ unifont_draw_text(&dctx->uctx, inst->fonts[fontid],
x*inst->font_width+inst->window_border,
y*inst->font_height+inst->window_border+inst->fonts[0]->ascent,
text + combining, len, widefactor > 1,
int uheight = inst->fonts[0]->ascent + 1;
if (uheight >= inst->font_height)
uheight = inst->font_height - 1;
- gdk_draw_line(inst->pixmap, gc, x*inst->font_width+inst->window_border,
- y*inst->font_height + uheight + inst->window_border,
- (x+len)*widefactor*inst->font_width-1+inst->window_border,
- y*inst->font_height + uheight + inst->window_border);
+ draw_line(dctx, x*inst->font_width+inst->window_border,
+ y*inst->font_height + uheight + inst->window_border,
+ (x+len)*widefactor*inst->font_width-1+inst->window_border,
+ y*inst->font_height + uheight + inst->window_border);
}
if ((lattr & LATTR_MODE) != LATTR_NORM) {
- /*
- * I can't find any plausible StretchBlt equivalent in the
- * X server, so I'm going to do this the slow and painful
- * way. This will involve repeated calls to
- * gdk_draw_pixmap() to stretch the text horizontally. It's
- * O(N^2) in time and O(N) in network bandwidth, but you
- * try thinking of a better way. :-(
- */
- int i;
- for (i = 0; i < len * widefactor * inst->font_width; i++) {
- gdk_draw_pixmap(inst->pixmap, gc, inst->pixmap,
- x*inst->font_width+inst->window_border + 2*i,
- y*inst->font_height+inst->window_border,
- x*inst->font_width+inst->window_border + 2*i+1,
- y*inst->font_height+inst->window_border,
- len * widefactor * inst->font_width - i, inst->font_height);
- }
- len *= 2;
- if ((lattr & LATTR_MODE) != LATTR_WIDE) {
- int dt, db;
- /* Now stretch vertically, in the same way. */
- if ((lattr & LATTR_MODE) == LATTR_BOT)
- dt = 0, db = 1;
- else
- dt = 1, db = 0;
- for (i = 0; i < inst->font_height; i+=2) {
- gdk_draw_pixmap(inst->pixmap, gc, inst->pixmap,
- x*inst->font_width+inst->window_border,
- y*inst->font_height+inst->window_border+dt*i+db,
- x*inst->font_width+inst->window_border,
- y*inst->font_height+inst->window_border+dt*(i+1),
- len * widefactor * inst->font_width, inst->font_height-i-1);
- }
- }
+ draw_stretch_after(dctx,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border,
+ rlen*widefactor*inst->font_width, TRUE,
+ inst->font_height,
+ ((lattr & LATTR_MODE) != LATTR_WIDE),
+ ((lattr & LATTR_MODE) == LATTR_BOT));
}
}
{
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
struct gui_data *inst = dctx->inst;
- GdkGC *gc = dctx->gc;
int widefactor;
do_text_internal(ctx, x, y, text, len, attr, lattr);
len *= 2;
}
- gdk_draw_pixmap(gtk_widget_get_window(inst->area), gc, inst->pixmap,
- x*inst->font_width+inst->window_border,
- y*inst->font_height+inst->window_border,
- x*inst->font_width+inst->window_border,
- y*inst->font_height+inst->window_border,
- len*widefactor*inst->font_width, inst->font_height);
+ draw_update(dctx,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border,
+ len*widefactor*inst->font_width, inst->font_height);
}
void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
{
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
struct gui_data *inst = dctx->inst;
- GdkGC *gc = dctx->gc;
int active, passive, widefactor;
* if it's passive.
*/
if (passive) {
- gdk_gc_set_foreground(gc, &inst->cols[261]);
- gdk_draw_rectangle(inst->pixmap, gc, 0,
- x*inst->font_width+inst->window_border,
- y*inst->font_height+inst->window_border,
- len*widefactor*inst->font_width-1, inst->font_height-1);
+ draw_set_colour(dctx, 261);
+ draw_rectangle(dctx, FALSE,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border,
+ len*widefactor*inst->font_width-1,
+ inst->font_height-1);
}
} else {
int uheight;
length = inst->font_height;
}
- gdk_gc_set_foreground(gc, &inst->cols[261]);
+ draw_set_colour(dctx, 261);
if (passive) {
for (i = 0; i < length; i++) {
if (i % 2 == 0) {
- gdk_draw_point(inst->pixmap, gc, startx, starty);
+ draw_point(dctx, startx, starty);
}
startx += dx;
starty += dy;
}
} else if (active) {
- gdk_draw_line(inst->pixmap, gc, startx, starty,
- startx + (length-1) * dx, starty + (length-1) * dy);
+ draw_line(dctx, startx, starty,
+ startx + (length-1) * dx, starty + (length-1) * dy);
} /* else no cursor (e.g., blinked off) */
}
- gdk_draw_pixmap(gtk_widget_get_window(inst->area), gc, inst->pixmap,
- x*inst->font_width+inst->window_border,
- y*inst->font_height+inst->window_border,
- x*inst->font_width+inst->window_border,
- y*inst->font_height+inst->window_border,
- len*widefactor*inst->font_width, inst->font_height);
+ draw_update(dctx,
+ x*inst->font_width+inst->window_border,
+ y*inst->font_height+inst->window_border,
+ len*widefactor*inst->font_width, inst->font_height);
#if GTK_CHECK_VERSION(2,0,0)
{
GdkCursor *make_mouse_ptr(struct gui_data *inst, int cursor_val)
{
- /*
- * Truly hideous hack: GTK doesn't allow us to set the mouse
- * cursor foreground and background colours unless we've _also_
- * created our own cursor from bitmaps. Therefore, I need to
- * load the `cursor' font and draw glyphs from it on to
- * pixmaps, in order to construct my cursors with the fg and bg
- * I want. This is a gross hack, but it's more self-contained
- * than linking in Xlib to find the X window handle to
- * inst->area and calling XRecolorCursor, and it's more
- * futureproof than hard-coding the shapes as bitmap arrays.
- */
- static GdkFont *cursor_font = NULL;
- GdkPixmap *source, *mask;
- GdkGC *gc;
- GdkColor cfg = { 0, 65535, 65535, 65535 };
- GdkColor cbg = { 0, 0, 0, 0 };
- GdkColor dfg = { 1, 65535, 65535, 65535 };
- GdkColor dbg = { 0, 0, 0, 0 };
- GdkCursor *ret;
- gchar text[2];
- gint lb, rb, wid, asc, desc, w, h, x, y;
-
- if (cursor_val == -2) {
- gdk_font_unref(cursor_font);
- return NULL;
- }
-
- if (cursor_val >= 0 && !cursor_font) {
- cursor_font = gdk_font_load("cursor");
- if (cursor_font)
- gdk_font_ref(cursor_font);
- }
-
- /*
- * Get the text extent of the cursor in question. We use the
- * mask character for this, because it's typically slightly
- * bigger than the main character.
- */
- if (cursor_val >= 0) {
- text[1] = '\0';
- text[0] = (char)cursor_val + 1;
- gdk_string_extents(cursor_font, text, &lb, &rb, &wid, &asc, &desc);
- w = rb-lb; h = asc+desc; x = -lb; y = asc;
- } else {
- w = h = 1;
- x = y = 0;
- }
-
- source = gdk_pixmap_new(NULL, w, h, 1);
- mask = gdk_pixmap_new(NULL, w, h, 1);
-
- /*
- * Draw the mask character on the mask pixmap.
- */
- gc = gdk_gc_new(mask);
- gdk_gc_set_foreground(gc, &dbg);
- gdk_draw_rectangle(mask, gc, 1, 0, 0, w, h);
- if (cursor_val >= 0) {
- text[1] = '\0';
- text[0] = (char)cursor_val + 1;
- gdk_gc_set_foreground(gc, &dfg);
- gdk_draw_text(mask, cursor_font, gc, x, y, text, 1);
- }
- gdk_gc_unref(gc);
-
- /*
- * Draw the main character on the source pixmap.
- */
- gc = gdk_gc_new(source);
- gdk_gc_set_foreground(gc, &dbg);
- gdk_draw_rectangle(source, gc, 1, 0, 0, w, h);
- if (cursor_val >= 0) {
- text[1] = '\0';
- text[0] = (char)cursor_val;
- gdk_gc_set_foreground(gc, &dfg);
- gdk_draw_text(source, cursor_font, gc, x, y, text, 1);
+ if (cursor_val == -1) {
+#if GTK_CHECK_VERSION(2,16,0)
+ cursor_val = GDK_BLANK_CURSOR;
+#else
+ /*
+ * Work around absence of GDK_BLANK_CURSOR by inventing a
+ * blank pixmap.
+ */
+ GdkCursor *ret;
+ GdkColor bg = { 0, 0, 0, 0 };
+ GdkPixmap *pm = gdk_pixmap_new(NULL, 1, 1, 1);
+ GdkGC *gc = gdk_gc_new(pm);
+ gdk_gc_set_foreground(gc, &bg);
+ gdk_draw_rectangle(pm, gc, 1, 0, 0, 1, 1);
+ gdk_gc_unref(gc);
+ ret = gdk_cursor_new_from_pixmap(pm, pm, &bg, &bg, 1, 1);
+ gdk_pixmap_unref(pm);
+ return ret;
+#endif
}
- gdk_gc_unref(gc);
- /*
- * Create the cursor.
- */
- ret = gdk_cursor_new_from_pixmap(source, mask, &cfg, &cbg, x, y);
-
- /*
- * Clean up.
- */
- gdk_pixmap_unref(source);
- gdk_pixmap_unref(mask);
-
- return ret;
+ return gdk_cursor_new(cursor_val);
}
void modalfatalbox(const char *p, ...)
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)
inst->fonts[0]->public_charset,
conf_get_int(inst->conf, CONF_vtmode));
+ inst->drawtype = inst->fonts[0]->preferred_drawtype;
+
return NULL;
}
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
}
inst->wintitle = inst->icontitle = NULL;
inst->quit_fn_scheduled = FALSE;
inst->idle_fn_scheduled = FALSE;
+ inst->drawtype = DRAWTYPE_DEFAULT;
/* defer any child exit handling until we're ready to deal with
* it */
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",
inst->rawcursor = make_mouse_ptr(inst, GDK_LEFT_PTR);
inst->waitcursor = make_mouse_ptr(inst, GDK_WATCH);
inst->blankcursor = make_mouse_ptr(inst, -1);
- make_mouse_ptr(inst, -2); /* clean up cursor font */
inst->currcursor = inst->textcursor;
show_mouseptr(inst, 1);