1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
// *** new helper feature 1-4/99
// to enable delayed popup (with signals : asynchr) open a new Display connection
// where to show the popups, closing is done from *any* Xevent in "handle_event" !!
// (if asynchronuous popups do not work: set twait = 0;)
// little problem : when pointer moves over helpwin -> LeaveNotify event (of the button) unmaps it
// then EnterNotify maps it again
class dhelper;
static dhelper *acthlp = 0; // the one and only active helper window
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
static void schedule(int tw, void (*handler)(int)) { // calls handler after tw microseconds
signal(SIGALRM,handler); // alarm(tw); works, but 1 sec is too slow ->
itimerval itv = { { 0, 0 }, {0, tw } } ;
setitimer(ITIMER_REAL,&itv,0);
}
static void show_help(int);
static void clear_help();
class dhelper { // for dynamic help on EnterCB
char **text; // to display in popup
int w,h,nl,xp,yp; // window size, line nr, position
Window Win;
unsigned twait; // time to wait for map (in microseconds)
Display *hdisplay;
public:
dhelper(char** text, Display *hdisplay) : text(text), hdisplay(hdisplay) {
int cl;
compute_text_size(text,cl,nl);
w = cl*6 + 10; h = nl*14 + 6;
Win = 0;
if (hdisplay) twait = 200000; // 0.2 sec delay (only if we have new display variable)
else { hdisplay = display; twait = 0; }
}
void popup(int x, int y) { // prepare for popup : after twait sec delay
xp = x; yp = y;
clear_help();
acthlp = this; // fprintf(stderr,"<");
if (twait > 0) schedule(twait,show_help);
else map(); // undelayed display
}
void map() { // if called from alarm_popup = asynchron !!
unsigned backgr = 0xfff8; // light yellow
Win = XCreateSimpleWindow(hdisplay, DefaultRootWindow(hdisplay),xp,yp,w,h,1, black, backgr);
XSetWindowAttributes attr;
attr.override_redirect = TRUE; // not handled by window manager
attr.save_under = TRUE;
XChangeWindowAttributes(hdisplay, Win, CWOverrideRedirect | CWSaveUnder, &attr);
XMapWindow(hdisplay, Win);
static XGCValues gcv = { GXcopy, 0, black };
static GC gc = XCreateGC(hdisplay, DefaultRootWindow(hdisplay),GCFunction | GCForeground, &gcv);
for (int l = 0, y = 0; l < nl; l++) {
char *tt = text[l]; y += 14;
XDrawString(hdisplay, Win, gc, 5, y, tt, strlen(tt));
}
XFlush(hdisplay);
}
void close() {
if (Win) { XDestroyWindow(hdisplay,Win); Win = 0; XFlush(hdisplay); }
acthlp = 0; // fprintf(stderr,">");
}
};
void clear_help() { if (acthlp) acthlp->close(); } // active helper !!
void show_help(int) { if (acthlp) acthlp->map(); } // asynch. from alarm !!
void window::add_help(char* help[]) {
static Display *hdisplay = XOpenDisplay("");
dhlp = new dhelper(help,hdisplay);
selection_mask |= EnterWindowMask | LeaveWindowMask;
XSelectInput(display, Win, selection_mask);
}
void window::add_help(char* arg0, ...) {
va_list args; va_start(args,arg0);
char *cp[50];
int nl = 1; cp[0] = arg0;
while ((cp[nl++] = va_arg(args,char*)) != NULL) if (nl == 50) break;
cp[nl-1] = 0;
// for (int i=0; i<nl; i++) printf("%s\n",cp[i]);
char **help = new char*[nl];
for (int i=0; i<nl; i++) help[i] = cp[i];
add_help(help);
va_end(args);
}
void window::Enter_CB(XCrossingEvent ev) { // clearing is done in handle_event
if (dhlp) dhlp->popup(ev.x_root + 10, ev.y_root + 5);
}
|