* Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
* Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
* - extensive modifications
- * Copyright (c) 2003-2006 Marc Lehmann <pcg@goof.com>
+ * Copyright (c) 2003-2008 Marc Lehmann <pcg@goof.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <csignal>
#include <cstring>
-#ifdef TTY_GID_SUPPORT
-# include <grp.h>
-#endif
+#include <termios.h>
-#ifdef HAVE_TERMIOS_H
-# include <termios.h>
+#ifdef HAVE_XSETLOCALE
+# define X_LOCALE
+# include <X11/Xlocale.h>
+#else
+# ifdef HAVE_SETLOCALE
+# include <clocale>
+# endif
#endif
vector<rxvt_term *> rxvt_term::termlist;
bool
rxvt_set_locale (const char *locale) NOTHROW
{
- if (!locale || !strncmp (locale, curlocale, 128))
+ int size = strlen (locale) + 1;
+
+ if (size > sizeof (curlocale))
+ rxvt_fatal ("locale string too long, aborting.\n");
+
+ if (!locale || !memcmp (locale, curlocale, size))
return false;
- strncpy (curlocale, locale, 128);
+ memcpy (curlocale, locale, size);
setlocale (LC_CTYPE, curlocale);
return true;
}
text_t rxvt_composite_vec::compose (unicode_t c1, unicode_t c2)
{
compose_char *cc;
-
+
// break compose chains, as stupid readline really likes to duplicate
// composing characters for some reason near the end of a line.
cc = (*this)[c1];
#endif
rxvt_term::rxvt_term ()
- :
-#if TRANSPARENT || ENABLE_PERL
- rootwin_ev (this, &rxvt_term::rootwin_cb),
-#endif
-#ifdef HAVE_SCROLLBARS
- scrollbar_ev (this, &rxvt_term::x_cb),
+{
+#if HAVE_BG_PIXMAP
+ update_background_ev.set<rxvt_term, &rxvt_term::update_background_cb> (this);
#endif
#ifdef CURSOR_BLINK
- cursor_blink_ev (this, &rxvt_term::cursor_blink_cb),
+ cursor_blink_ev.set <rxvt_term, &rxvt_term::cursor_blink_cb> (this); cursor_blink_ev.set (0., CURSOR_BLINK_INTERVAL);
#endif
#ifdef TEXT_BLINK
- text_blink_ev (this, &rxvt_term::text_blink_cb),
+ text_blink_ev.set <rxvt_term, &rxvt_term::text_blink_cb> (this); text_blink_ev.set (0., TEXT_BLINK_INTERVAL);
#endif
#ifndef NO_SCROLLBAR_BUTTON_CONTINUAL_SCROLLING
- cont_scroll_ev (this, &rxvt_term::cont_scroll_cb),
+ cont_scroll_ev.set <rxvt_term, &rxvt_term::cont_scroll_cb> (this);
#endif
#ifdef SELECTION_SCROLLING
- sel_scroll_ev (this, &rxvt_term::sel_scroll_cb),
+ sel_scroll_ev.set <rxvt_term, &rxvt_term::sel_scroll_cb> (this);
#endif
#if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
- slip_wheel_ev (this, &rxvt_term::slip_wheel_cb),
+ slip_wheel_ev.set <rxvt_term, &rxvt_term::slip_wheel_cb> (this);
#endif
-#ifdef POINTER_BLANK
- pointer_ev (this, &rxvt_term::pointer_cb),
+#if ENABLE_TRANSPARENCY || ENABLE_PERL
+ rootwin_ev.set <rxvt_term, &rxvt_term::rootwin_cb> (this),
#endif
+ scrollbar_ev.set <rxvt_term, &rxvt_term::x_cb> (this),
#ifdef USE_XIM
- im_ev (this, &rxvt_term::im_cb),
+ im_ev.set <rxvt_term, &rxvt_term::im_cb> (this),
+#endif
+#ifdef POINTER_BLANK
+ pointer_ev.set <rxvt_term, &rxvt_term::pointer_cb> (this);
#endif
-#ifndef NO_BELL
- bell_ev (this, &rxvt_term::bell_cb),
+#ifndef NO_BELL
+ bell_ev.set <rxvt_term, &rxvt_term::bell_cb> (this);
#endif
- termwin_ev (this, &rxvt_term::x_cb),
- vt_ev (this, &rxvt_term::x_cb),
- child_ev (this, &rxvt_term::child_cb),
- check_ev (this, &rxvt_term::check_cb),
- flush_ev (this, &rxvt_term::flush_cb),
- destroy_ev (this, &rxvt_term::destroy_cb),
- pty_ev (this, &rxvt_term::pty_cb),
- incr_ev (this, &rxvt_term::incr_cb)
-{
+ child_ev.set <rxvt_term, &rxvt_term::child_cb> (this);
+ flush_ev.set <rxvt_term, &rxvt_term::flush_cb> (this);
+ destroy_ev.set <rxvt_term, &rxvt_term::destroy_cb> (this);
+ pty_ev.set <rxvt_term, &rxvt_term::pty_cb> (this);
+ incr_ev.set <rxvt_term, &rxvt_term::incr_cb> (this);
+ termwin_ev.set <rxvt_term, &rxvt_term::x_cb> (this);
+ vt_ev.set <rxvt_term, &rxvt_term::x_cb> (this);
+
cmdbuf_ptr = cmdbuf_endp = cmdbuf_base;
termlist.push_back (this);
// clean up the most important stuff, do *not* call x or free mem etc.
// for use before an emergency exit
-void rxvt_term::emergency_cleanup ()
+void
+rxvt_term::emergency_cleanup ()
{
if (cmd_pid)
kill (-cmd_pid, SIGHUP);
#endif
delete fontset[0];
+#ifdef HAVE_BG_PIXMAP
+ bgPixmap.destroy ();
+#endif
+#ifdef HAVE_AFTERIMAGE
+ if (asv)
+ destroy_asvisual (asv, 0);
+ if (asimman)
+ destroy_image_manager (asimman, 0);
+#endif
+
if (display)
{
selection_clear ();
+ selection_clear (true);
#ifdef USE_XIM
im_destroy ();
#endif
-#ifdef XTERM_SCROLLBAR
- if (xscrollbarGC) XFreeGC (dpy, xscrollbarGC);
- if (ShadowGC) XFreeGC (dpy, ShadowGC);
-#endif
-#ifdef PLAIN_SCROLLBAR
- if (pscrollbarGC) XFreeGC (dpy, pscrollbarGC);
-#endif
-#ifdef NEXT_SCROLLBAR
- if (blackGC) XFreeGC (dpy, blackGC);
- if (whiteGC) XFreeGC (dpy, whiteGC);
- if (grayGC) XFreeGC (dpy, grayGC);
- if (darkGC) XFreeGC (dpy, darkGC);
- if (stippleGC) XFreeGC (dpy, stippleGC);
- if (dimple) XFreePixmap (dpy, dimple);
- if (upArrow) XFreePixmap (dpy, upArrow);
- if (downArrow) XFreePixmap (dpy, downArrow);
- if (upArrowHi) XFreePixmap (dpy, upArrowHi);
- if (downArrowHi) XFreePixmap (dpy, downArrowHi);
-#endif
-#ifdef RXVT_SCROLLBAR
- if (topShadowGC) XFreeGC (dpy, topShadowGC);
- if (botShadowGC) XFreeGC (dpy, botShadowGC);
- if (scrollbarGC) XFreeGC (dpy, scrollbarGC);
-#endif
+ scrollBar.destroy ();
if (gc) XFreeGC (dpy, gc);
delete drawable;
}
clear ();
- }
-
- delete pix_colors_focused;
-#if OFF_FOCUS_FADING
- delete pix_colors_unfocused;
-#endif
- displays.put (display);
+ display->flush (); /* ideally .put should do this */
+ displays.put (display);
+ }
scr_release ();
free (allocated [i]);
free (selection.text);
+ free (selection.clip_text);
// TODO: manage env vars in child only(!)
free (env_display);
free (env_term);
#ifdef KEYSYM_RESOURCE
delete keyboard;
#endif
+#ifndef NO_RESOURCES
+ XrmDestroyDatabase (option_db);
+#endif
}
// child has exited, usually destroys
void
-rxvt_term::child_cb (child_watcher &w, int status)
+rxvt_term::child_cb (ev::child &w, int status)
{
HOOK_INVOKE ((this, HOOK_CHILD_EXIT, DT_INT, status, DT_END));
cmd_pid = 0;
- if (!OPTION (Opt_hold))
+ if (!option (Opt_hold))
destroy ();
}
void
rxvt_term::destroy ()
{
- if (destroy_ev.active)
+ if (destroy_ev.is_active ())
return;
HOOK_INVOKE ((this, HOOK_DESTROY, DT_END));
#if USE_XIM
im_ev.stop (display);
#endif
-#if HAVE_SCROLLBARS
scrollbar_ev.stop (display);
-#endif
-#if TRANSPARENT || ENABLE_PERL
+#if ENABLE_TRANSPARENCY || ENABLE_PERL
rootwin_ev.stop (display);
#endif
incr_ev.stop ();
vt_ev.stop (display);
}
- check_ev.stop ();
+ flush_ev.stop ();
pty_ev.stop ();
#ifdef CURSOR_BLINK
cursor_blink_ev.stop ();
pointer_ev.stop ();
#endif
- destroy_ev.start (0);
+ destroy_ev.start ();
}
void
-rxvt_term::destroy_cb (time_watcher &w)
+rxvt_term::destroy_cb (ev::idle &w, int revents)
{
make_current ();
mesg, BUFSIZ);
rxvt_warn (strncat (mesg, "\n", BUFSIZ), event->resourceid);
}
- XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
+ XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
mesg, BUFSIZ);
rxvt_warn (strncat (mesg, "\n", BUFSIZ), event->serial);
}
_exit (EXIT_FAILURE);
}
-/*----------------------------------------------------------------------*/
-bool
-rxvt_term::init (int argc, const char *const *argv, stringvec *envv)
-{
- this->envv = envv;
-
- SET_R (this);
- set_locale ("");
- set_environ (envv); // few things in X do not call setlocale :(
-
- if (!init_vars ())
- return false;
-
- init_secondary ();
-
- const char **cmd_argv = init_resources (argc, argv);
-
-#ifdef KEYSYM_RESOURCE
- keyboard->register_done ();
-#endif
-
-#ifdef HAVE_SCROLLBARS
- if (OPTION (Opt_scrollBar))
- scrollBar.setIdle (); /* set existence for size calculations */
-#endif
-
- pty = ptytty::create ();
-
- create_windows (argc, argv);
-
- init_xlocale ();
-
- scr_reset (); // initialize screen
-
-#if 0
- XSynchronize (dpy, True);
-#endif
-
-#ifdef HAVE_SCROLLBARS
- if (OPTION (Opt_scrollBar))
- resize_scrollbar (); /* create and map scrollbar */
-#endif
-#ifdef TRANSPARENT
- if (OPTION (Opt_transparent))
- {
- XSelectInput (dpy, display->root, PropertyChangeMask);
- check_our_parents ();
- rootwin_ev.start (display, display->root);
- }
-#endif
-#if ENABLE_PERL
- rootwin_ev.start (display, display->root);
-#endif
-
- set_colorfgbg ();
-
- init_command (cmd_argv);
-
- free (cmd_argv);
-
- if (pty->pty >= 0)
- pty_ev.start (pty->pty, EVENT_READ);
-
- check_ev.start ();
-
- HOOK_INVOKE ((this, HOOK_START, DT_END));
-
-#if ENABLE_XEMBED
- if (rs[Rs_embed])
- {
- long info[2] = { 0, XEMBED_MAPPED };
-
- XChangeProperty (dpy, parent[0], xa[XA_XEMBED_INFO], xa[XA_XEMBED_INFO],
- 32, PropModeReplace, (unsigned char *)&info, 2);
- }
-#endif
-
- XMapWindow (dpy, vt);
- XMapWindow (dpy, parent[0]);
-
- return true;
-}
-
static struct sig_handlers
{
- sig_watcher sw_term, sw_int;
-
+ ev::sig sw_term, sw_int;
+
/*
* Catch a fatal signal and tidy up before quitting
*/
- void
- sig_term (sig_watcher &w)
- {
- rxvt_emergency_cleanup ();
- signal (w.signum, SIG_DFL);
- kill (getpid (), w.signum);
- }
+ void sig_term (ev::sig &w, int revents);
sig_handlers ()
- : sw_term (this, &sig_handlers::sig_term),
- sw_int (this, &sig_handlers::sig_term)
{
+ sw_term.set<sig_handlers, &sig_handlers::sig_term> (this);
+ sw_int .set<sig_handlers, &sig_handlers::sig_term> (this);
}
} sig_handlers;
+void
+sig_handlers::sig_term (ev::sig &w, int revents)
+{
+ rxvt_emergency_cleanup ();
+ w.stop ();
+ kill (getpid (), w.signum);
+}
+
char **rxvt_environ; // startup environment
void
{
ptytty::init ();
+ if (!ev_default_loop (0))
+ rxvt_fatal ("cannot initialise libev (bad value for LIBEV_METHODS?)\n");
+
rxvt_environ = environ;
signal (SIGHUP, SIG_IGN);
signal (SIGPIPE, SIG_IGN);
- sig_handlers.sw_term.start (SIGTERM);
- sig_handlers.sw_int.start (SIGINT);
+ sig_handlers.sw_term.start (SIGTERM); ev_unref ();
+ sig_handlers.sw_int.start (SIGINT); ev_unref ();
/* need to trap SIGURG for SVR4 (Unixware) rlogin */
/* signal (SIGURG, SIG_DFL); */
XrmInitialize ();
}
-/* ------------------------------------------------------------------------- *
- * MEMORY ALLOCATION WRAPPERS *
- * ------------------------------------------------------------------------- */
-void *
-rxvt_malloc (size_t size)
-{
- void *p = malloc (size);
-
- if (!p)
- rxvt_fatal ("memory allocation failure. aborting.\n");
-
- return p;
-}
-
-void *
-rxvt_calloc (size_t number, size_t size)
-{
- void *p = calloc (number, size);
-
- if (!p)
- rxvt_fatal ("memory allocation failure. aborting.\n");
-
- return p;
-}
-
-void *
-rxvt_realloc (void *ptr, size_t size)
-{
- void *p = realloc (ptr, size);
-
- if (!p)
- rxvt_fatal ("memory allocation failure. aborting.\n");
-
- return p;
-}
-
/*----------------------------------------------------------------------*/
/*
- * window size/position calculcations for XSizeHint and other storage.
+ * window size/position calculations for XSizeHint and other storage.
* if width/height are non-zero then override calculated width/height
*/
void
rxvt_term::window_calc (unsigned int newwidth, unsigned int newheight)
{
short recalc_x, recalc_y;
- int x, y, sb_w, flags;
+ int x, y, flags;
unsigned int w, h;
unsigned int max_width, max_height;
if (flags & WidthValue)
{
- ncol = clamp (w, 0, std::numeric_limits<int16_t>::max ());
+ if (!w)
+ rxvt_fatal ("illegal window geometry (width and height must be non-zero), aborting.\n");
+
+ ncol = clamp (w, 1, std::numeric_limits<int16_t>::max ());
szHint.flags |= USSize;
}
if (flags & HeightValue)
{
- nrow = clamp (h, 0, std::numeric_limits<int16_t>::max ());
+ if (!h)
+ rxvt_fatal ("illegal window geometry (width and height must be non-zero), aborting.\n");
+
+ nrow = clamp (h, 1, std::numeric_limits<int16_t>::max ());
szHint.flags |= USSize;
}
szHint.base_width = szHint.base_height = 2 * int_bwidth;
- sb_w = 0;
window_vt_x = window_vt_y = int_bwidth;
if (scrollBar.state)
{
- sb_w = scrollbar_TotalWidth ();
+ int sb_w = scrollBar.total_width ();
szHint.base_width += sb_w;
- if (!OPTION (Opt_scrollBar_right))
+ if (!option (Opt_scrollBar_right))
window_vt_x += sb_w;
}
szHint.height = szHint.base_height + height;
}
- if (scrollBar.state && OPTION (Opt_scrollBar_right))
- window_sb_x = szHint.width - sb_w;
-
if (recalc_x)
szHint.x += DisplayWidth (dpy, display->screen) - szHint.width - 2 * ext_bwidth;
if (recalc_y)
szHint.y += DisplayHeight (dpy, display->screen) - szHint.height - 2 * ext_bwidth;
- ncol = width / fwidth;
+ ncol = width / fwidth;
nrow = height / fheight;
}
ws.ws_row = nrow;
ws.ws_xpixel = width;
ws.ws_ypixel = height;
- (void)ioctl (pty->pty, TIOCSWINSZ, &ws);
+ ioctl (pty->pty, TIOCSWINSZ, &ws);
#if 0
- // TIOCSWINSZ⎈ is supposed to do this automatically and correctly
+ // TIOCSWINSZ is supposed to do this automatically and correctly
if (cmd_pid) /* force through to the command */
kill (-cmd_pid, SIGWINCH);
#endif
prop = (*fs)[1]->properties ();
prop.height += lineSpace;
- fs->set_prop (prop);
+ prop.width += letterSpace;
+
+ fs->set_prop (prop, false);
fwidth = prop.width;
fheight = prop.height;
rxvt_fontprop prop2 = prop;
if (res)
- prop2.weight = prop2.slant = rxvt_fontprop::unset;
+ {
+ fs->populate (res);
+ fs->set_prop (prop2, false);
+ }
else
{
- res = fontset[0]->fontdesc;
+ fs->populate (fontset[0]->fontdesc);
if (SET_STYLE (0, style) & RS_Bold) prop2.weight = rxvt_fontprop::bold;
if (SET_STYLE (0, style) & RS_Italic) prop2.slant = rxvt_fontprop::italic;
+
+ fs->set_prop (prop2, true);
}
- fs->populate (res);
- fs->set_prop (prop2);
}
#else
fontset[style] = fontset[0];
resize_all_windows (0, 0, 0);
scr_remap_chars ();
scr_touch (true);
- }
+ }
return true;
}
-void rxvt_term::set_string_property (Atom prop, const char *str, int len)
+void
+rxvt_term::set_string_property (Atom prop, const char *str, int len)
{
XChangeProperty (dpy, parent[0],
prop, XA_STRING, 8, PropModeReplace,
(const unsigned char *)str, len >= 0 ? len : strlen (str));
}
-void rxvt_term::set_utf8_property (Atom prop, const char *str, int len)
+void
+rxvt_term::set_utf8_property (Atom prop, const char *str, int len)
{
wchar_t *ws = rxvt_mbstowcs (str, len);
char *s = rxvt_wcstoutf8 (ws);
#endif
}
-#ifdef XTERM_COLOR_CHANGE
void
rxvt_term::set_window_color (int idx, const char *color)
{
+#ifdef XTERM_COLOR_CHANGE
rxvt_color xcol;
- int i;
-
+
if (color == NULL || *color == '\0')
return;
/* handle color aliases */
if (isdigit (*color))
{
- i = atoi (color);
+ int i = atoi (color);
if (i >= 8 && i <= 15)
- { /* bright colors */
- i -= 8;
- pix_colors_focused[idx] = pix_colors_focused[minBrightCOLOR + i];
+ {
+ /* bright colors */
+ pix_colors_focused[idx] = pix_colors_focused[minBrightCOLOR + i - 8];
goto done;
}
if (i >= 0 && i <= 7)
- { /* normal colors */
+ {
+ /* normal colors */
pix_colors_focused[idx] = pix_colors_focused[minCOLOR + i];
goto done;
}
pix_colors_focused[idx] = xcol;
- /* XSetWindowAttributes attr; */
- /* Cursor cursor; */
done:
/*TODO: handle Color_BD, scrollbar background, etc. */
update_fade_color (idx);
recolour_cursor ();
scr_recolour ();
+#endif /* XTERM_COLOR_CHANGE */
}
-#else
-# define set_window_color (idx,color) ((void)0)
-#endif /* XTERM_COLOR_CHANGE */
-
void
rxvt_term::recolour_cursor ()
{
rxvt_term::set_colorfgbg ()
{
unsigned int i;
- const char *xpmb = "\0";
+ const char *xpmb = "";
char fstr[sizeof ("default") + 1], bstr[sizeof ("default") + 1];
strcpy (fstr, "default");
if (pix_colors[Color_bg] == pix_colors[i])
{
sprintf (bstr, "%d", (i - Color_Black));
-#ifdef XPM_BACKGROUND
+#ifdef BG_IMAGE_FROM_FILE
xpmb = "default;";
#endif
break;
window_calc (newwidth, newheight);
- if (!HOOK_INVOKE ((this, HOOK_RESIZE_ALL_WINDOWS, DT_INT, newwidth, DT_INT, newheight, DT_END)))
- XSetWMNormalHints (dpy, parent[0], &szHint);
+ bool set_hint = !HOOK_INVOKE ((this, HOOK_RESIZE_ALL_WINDOWS, DT_INT, newwidth, DT_INT, newheight, DT_END));
+
+ // to avoid races between us and the wm, we clear the incremental size hints around the xresizewindow
+ if (set_hint)
+ {
+ szHint.flags &= ~(PBaseSize | PResizeInc);
+ XSetWMNormalHints (dpy, parent[0], &szHint);
+ szHint.flags |= PBaseSize | PResizeInc;
+ }
if (!ignoreparent)
{
#endif
}
+ if (set_hint)
+ XSetWMNormalHints (dpy, parent[0], &szHint);
+
fix_screen = ncol != prev_ncol || nrow != prev_nrow;
if (fix_screen || newwidth != old_width || newheight != old_height)
{
if (scrollBar.state)
- {
- XMoveResizeWindow (dpy, scrollBar.win,
- window_sb_x, 0,
- scrollbar_TotalWidth (), szHint.height);
- resize_scrollbar ();
- }
+ scrollBar.resize ();
XMoveResizeWindow (dpy, vt,
window_vt_x, window_vt_y,
width, height);
- scr_clear ();
-#ifdef XPM_BACKGROUND
- resize_pixmap ();
+#ifdef HAVE_BG_PIXMAP
+ if (bgPixmap.window_size_sensitive ())
+ update_background ();
#endif
}
// TODO, with nvidia-8178, resizes kill the alpha channel, report if not fixed in newer version
//scr_touch (false);
-#ifdef XPM_BACKGROUND
- if (pixmap)
- scr_touch (false);
+#ifdef HAVE_BG_PIXMAP
+// TODO: this don't seem to have any effect - do we still need it ? If so - in which case exactly ?
+// if (bgPixmap.pixmap)
+// scr_touch (false);
#endif
#ifdef USE_XIM
bool
rxvt_term::IMisRunning ()
{
- char *p;
Atom atom;
Window win;
char server[IMBUFSIZ];
/* get current locale modifier */
- if ((p = XSetLocaleModifiers (NULL)) != NULL)
+ if (char *p = XSetLocaleModifiers (0))
{
strcpy (server, "@server=");
- strncat (server, & (p[4]), IMBUFSIZ - 9); /* skip "@im=" */
+ strncat (server, p + 4, IMBUFSIZ - 9); /* skip "@im=" */
- if ((p = strchr (server + 1, '@')) != NULL) /* first one only */
+ if (p = strchr (server + 1, '@')) /* first one only */
*p = '\0';
atom = XInternAtom (dpy, server, False);
if (text)
{
- void *str;
+ wchar_t *str;
if (!text->encoding_is_wchar && text->string.multi_byte)
{
if (term->rs[Rs_imLocale])
SET_LOCALE (term->rs[Rs_imLocale]);
- str = rxvt_temp_buf ((text->length + 1) * sizeof (wchar_t));
- mbstowcs ((wchar_t *)str, text->string.multi_byte, text->length + 1);
+ str = rxvt_temp_buf<wchar_t> (text->length + 1);
+ mbstowcs (str, text->string.multi_byte, text->length + 1);
if (term->rs[Rs_imLocale])
SET_LOCALE (term->locale);
}
else
- str = (void *)text->string.wide_char;
-
+ str = text->string.wide_char;
+
HOOK_INVOKE ((term, HOOK_XIM_PREEDIT_DRAW,
DT_INT, call_data->caret,
DT_INT, call_data->chg_first,
{
im_set_size (preedit_rect);
preedit_attr = XVaCreateNestedList (0, XNArea, &preedit_rect, NULL);
-
+
XSetICValues (Input_Context,
XNPreeditAttributes, preedit_attr, NULL);
}
XFree (preedit_attr);
}
-#endif /* USE_XIM */
+#endif /* USE_XIM */
+
+void
+rxvt_term::get_window_origin (int &x, int &y)
+{
+ Window cr;
+ XTranslateCoordinates (dpy, parent[0], display->root, 0, 0, &x, &y, &cr);
+/* fprintf (stderr, "origin is %+d%+d\n", x, y);*/
+}
+
+Pixmap
+rxvt_term::get_pixmap_property (int prop_id)
+{
+ if (prop_id > 0 && prop_id < NUM_XA)
+ if (xa[prop_id])
+ {
+ int aformat;
+ unsigned long nitems, bytes_after;
+ Atom atype;
+ unsigned char *prop = NULL;
+ int result = XGetWindowProperty (dpy, display->root, xa[prop_id],
+ 0L, 1L, False, XA_PIXMAP, &atype, &aformat,
+ &nitems, &bytes_after, &prop);
+ if (result == Success && prop && atype == XA_PIXMAP)
+ return *(Pixmap *)prop;
+ }
+
+ return None;
+}
+
+#ifdef HAVE_BG_PIXMAP
+# if TRACE_PIXMAPS
+# undef update_background
+void
+rxvt_term::trace_update_background (const char *file, int line)
+{
+ fprintf (stderr, "%s:%d:update_background()\n", file, line);
+ update_background ();
+}
+# endif
+
+void
+rxvt_term::update_background ()
+{
+ if (update_background_ev.is_active ())
+ return;
+
+ bgPixmap.invalidate ();
+
+ ev_tstamp to_wait = 0.5 - (ev::now () - bgPixmap.valid_since);
+
+ if (to_wait <= 0.)
+ bgPixmap.render ();
+ else
+ update_background_ev.start (to_wait);
+}
+
+void
+rxvt_term::update_background_cb (ev::timer &w, int revents)
+{
+ make_current ();
+
+ update_background_ev.stop ();
+ bgPixmap.render ();
+ refresh_check ();
+}
+
+#endif /* HAVE_BG_PIXMAP */
/*----------------------- end-of-file (C source) -----------------------*/