diff --git a/Recipe b/Recipe index a480e3cd..b13b12f4 100644 --- a/Recipe +++ b/Recipe @@ -217,7 +217,7 @@ GUITERM = TERMINAL window windlg winctrls sizetip winucs winprint # Same thing on Unix. UXTERM = TERMINAL uxcfg sercfg uxucs uxprint timing callback miscucs -GTKTERM = UXTERM gtkwin gtkcfg gtkdlg gtkfont gtkcols gtkmisc xkeysym +GTKTERM = UXTERM gtkwin gtkcfg gtkdlg gtkfont gtkcols gtkmisc xkeysym x11misc OSXTERM = UXTERM osxwin osxdlg osxctrls # Non-SSH back ends (putty, puttytel, plink). diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 192e20e1..e711458e 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -44,6 +44,8 @@ #include #endif +#include "x11misc.h" + #define CAT2(x,y) x ## y #define CAT(x,y) CAT2(x,y) #define ASSERT(x) enum {CAT(assertion_,__LINE__) = 1 / (x)} @@ -2961,20 +2963,28 @@ void init_clipboard(struct gui_data *inst) */ unsigned char empty[] = ""; Display *disp = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + x11_ignore_error(disp, BadMatch); XChangeProperty(disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER0, XA_STRING, 8, PropModeAppend, empty, 0); + x11_ignore_error(disp, BadMatch); XChangeProperty(disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER1, XA_STRING, 8, PropModeAppend, empty, 0); + x11_ignore_error(disp, BadMatch); XChangeProperty(disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER2, XA_STRING, 8, PropModeAppend, empty, 0); + x11_ignore_error(disp, BadMatch); XChangeProperty(disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER3, XA_STRING, 8, PropModeAppend, empty, 0); + x11_ignore_error(disp, BadMatch); XChangeProperty(disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER4, XA_STRING, 8, PropModeAppend, empty, 0); + x11_ignore_error(disp, BadMatch); XChangeProperty(disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER5, XA_STRING, 8, PropModeAppend, empty, 0); + x11_ignore_error(disp, BadMatch); XChangeProperty(disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER6, XA_STRING, 8, PropModeAppend, empty, 0); + x11_ignore_error(disp, BadMatch); XChangeProperty(disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER7, XA_STRING, 8, PropModeAppend, empty, 0); #endif diff --git a/unix/x11misc.c b/unix/x11misc.c new file mode 100644 index 00000000..b49aa489 --- /dev/null +++ b/unix/x11misc.c @@ -0,0 +1,88 @@ +/* + * x11misc.c: miscellaneous stuff for dealing directly with X servers. + */ + +#include +#include +#include +#include +#include + +#include "putty.h" + +#ifndef NOT_X_WINDOWS + +#include +#include +#include + +#include "x11misc.h" + +/* ---------------------------------------------------------------------- + * Error handling mechanism which permits us to ignore specific X11 + * errors from particular requests. We maintain a list of upcoming + * potential error events that we want to not treat as fatal errors. + */ + +static int (*orig_x11_error_handler)(Display *thisdisp, XErrorEvent *err); + +struct x11_err_to_ignore { + Display *display; + unsigned char error_code; + unsigned long serial; +}; + +struct x11_err_to_ignore *errs; + +int nerrs, errsize; + +static int x11_error_handler(Display *thisdisp, XErrorEvent *err) +{ + int i; + for (i = 0; i < nerrs; i++) { + if (thisdisp == errs[i].display && + err->serial == errs[i].serial && + err->error_code == errs[i].error_code) { + /* Ok, this is an error we're happy to ignore */ + return 0; + } + } + + return (*orig_x11_error_handler)(thisdisp, err); +} + +void x11_ignore_error(Display *disp, unsigned char errcode) +{ + /* + * Install our error handler, if we haven't already. + */ + if (!orig_x11_error_handler) + orig_x11_error_handler = XSetErrorHandler(x11_error_handler); + + /* + * This is as good a moment as any to winnow the ignore list based + * on requests we know to have been processed. + */ + { + unsigned long last = LastKnownRequestProcessed(disp); + int i, j; + for (i = j = 0; i < nerrs; i++) { + if (errs[i].display == disp && errs[i].serial <= last) + continue; + errs[j++] = errs[i]; + } + nerrs = j; + } + + if (nerrs >= errsize) { + errsize = nerrs * 5 / 4 + 16; + errs = sresize(errs, errsize, struct x11_err_to_ignore); + } + errs[nerrs].display = disp; + errs[nerrs].error_code = errcode; + errs[nerrs].serial = NextRequest(disp); + nerrs++; +} + +#endif + diff --git a/unix/x11misc.h b/unix/x11misc.h new file mode 100644 index 00000000..0ad14764 --- /dev/null +++ b/unix/x11misc.h @@ -0,0 +1,15 @@ +/* + * x11misc.h: header file for functions that need to refer to Xlib + * data types. Has to be separate from unix.h so that we can include + * it only after including the X headers, which in turn has to be done + * after putty.h has told us whether NOT_X_WINDOWS is defined. + */ + +#ifndef NOT_X_WINDOWS + +/* + * x11misc.c. + */ +void x11_ignore_error(Display *disp, unsigned char errcode); + +#endif