static void main_loop()//主要的循环,^_^
{ #ifdef SIGNAL_BLOCKING //阻塞信号
sigset_t newmask, oldmask;
sigemptyset(&newmask); sigaddset(&newmask,SIGINT); sigaddset(&newmask,SIGTERM); sigaddset(&newmask,SIGUSR1); #endif
#ifdef X11 Region region = XCreateRegion();//create a new empty region
#ifdef HAVE_XDAMAGE int event_base, error_base; if (!XDamageQueryExtension (display, &event_base, &error_base)) { ERR("Xdamage extension unavailable"); } Damage damage = XDamageCreate(display, window.window, XDamageReportNonEmpty); XserverRegion region2 = XFixesCreateRegionFromWindow(display, window.window, 0); XserverRegion part = XFixesCreateRegionFromWindow(display, window.window, 0); #endif /* HAVE_XDAMAGE */ #endif /* X11 */
info.looped = 0; while (total_run_times == 0 || info.looped < total_run_times) { info.looped++;
#ifdef SIGNAL_BLOCKING /* block signals. we will inspect for pending signals later *///首先阻塞信号,准备好以后再打开
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) CRIT_ERR("unable to sigprocmask()"); #endif
#ifdef X11 XFlush(display);// flushes the output buffer
/* wait for X event or timeout */
if (!XPending(display)) {//display Specifies the connection to the X server
fd_set fdsr; struct timeval tv; int s; double t = update_interval - (get_time() - last_update_time);
if (t < 0) t = 0;
tv.tv_sec = (long) t; tv.tv_usec = (long) (t * 1000000) % 1000000; FD_ZERO(&fdsr); FD_SET(ConnectionNumber(display), &fdsr);
s = select(ConnectionNumber(display) + 1, &fdsr, 0, 0, &tv); #else usleep(update_interval*1000000); /* FIXME just sleep for the interval time if no X11 */ #endif /* X11 */ #ifdef X11 if (s == -1) { if (errno != EINTR) ERR("can't select(): %s", strerror(errno)); } else { /* timeout */ if (s == 0) #endif /* X11 */ update_text();//更新显示的文本
#ifdef X11 } } if (need_to_update) { #ifdef OWN_WINDOW int wx = window.x, wy = window.y; #endif
need_to_update = 0; selected_font = 0; update_text_area();//更新文本显示区
#ifdef OWN_WINDOW if (own_window) { /* resize window if it isn't right size */ if (!fixed_size && (text_width + border_margin * 2 + 1 != window.width || text_height + border_margin * 2 + 1 != window.height)) { window.width = text_width + border_margin * 2 + 1; window.height = text_height + border_margin * 2 + 1; XResizeWindow(display, window.window, window.width, window.height); if (own_window) { set_transparent_background(window.window); } }
/* move window if it isn't in right position */ if (!fixed_pos && (window.x != wx || window.y != wy)) { XMoveWindow(display, window.window, window.x, window.y); } } #endif
clear_text(1);
#ifdef HAVE_XDBE if (use_xdbe) { XRectangle r; r.x = text_start_x - border_margin; r.y = text_start_y - border_margin; r.width = text_width + border_margin * 2; r.height = text_height + border_margin * 2; XUnionRectWithRegion(&r, region, region); } #endif }
/* handle X events *///支持X的事件
while (XPending(display)) { XEvent ev; XNextEvent(display, &ev); switch (ev.type) { case Expose: { XRectangle r; r.x = ev.xexpose.x; r.y = ev.xexpose.y; r.width = ev.xexpose.width; r.height = ev.xexpose.height; XUnionRectWithRegion(&r, region, region); } break;
#ifdef OWN_WINDOW case ReparentNotify: /* set background to ParentRelative for all parents */ if (own_window) { set_transparent_background(window. window); } break;
case ConfigureNotify: if (own_window) { /* if window size isn't what expected, set fixed size */ if (ev.xconfigure.width != window.width || ev.xconfigure.height != window.height) { if (window.width != 0 && window.height != 0) fixed_size = 1;
/* clear old stuff before screwing up size and pos */ clear_text(1);
{ XWindowAttributes attrs; if (XGetWindowAttributes(display, window.window, &attrs)) { window. width = attrs. width; window. height = attrs. height; } }
text_width = window.width - border_margin * 2 - 1; text_height = window.height - border_margin * 2 - 1; if (text_width > maximum_width && maximum_width > 0) text_width = maximum_width; }
/* if position isn't what expected, set fixed pos, total_updates * avoids setting fixed_pos when window is set to weird locations * when started */ /*if (total_updates >= 2 this is broken && !fixed_pos && (window.x != ev.xconfigure.x || window.y != ev.xconfigure.y) && (ev.xconfigure.x != 0 || ev.xconfigure.y != 0)) { fixed_pos = 1; }*/ set_font(); } break;
case ButtonPress: if (own_window) { /* forward the click to the desktop window */ XUngrabPointer(display, ev.xbutton.time); ev.xbutton.window = window.desktop; XSendEvent(display, ev.xbutton.window, False, ButtonPressMask, &ev); } break;
case ButtonRelease: if (own_window) { /* forward the release to the desktop window */ ev.xbutton.window = window.desktop; XSendEvent(display, ev.xbutton.window, False, ButtonReleaseMask, &ev); } break;
#endif
default: #ifdef HAVE_XDAMAGE if (ev.type == event_base + XDamageNotify) { XDamageNotifyEvent *dev = (XDamageNotifyEvent *) &ev; XFixesSetRegion(display, part, &dev->area, 1); XFixesUnionRegion(display, region2, region2, part); } #endif /* HAVE_XDAMAGE */ break; } } #ifdef HAVE_XDAMAGE XDamageSubtract(display, damage, region2, None); XFixesSetRegion(display, region2, 0, 0); #endif /* HAVE_XDAMAGE */
/* XDBE doesn't seem to provide a way to clear the back buffer without * interfering with the front buffer, other than passing XdbeBackground * to XdbeSwapBuffers. That means that if we're using XDBE, we need to * redraw the text even if it wasn't part of the exposed area. OTOH, * if we're not going to call draw_stuff at all, then no swap happens * and we can safely do nothing. */
if (!XEmptyRegion(region)) { #ifdef HAVE_XDBE if (use_xdbe) { XRectangle r; r.x = text_start_x - border_margin; r.y = text_start_y - border_margin; r.width = text_width + border_margin * 2; r.height = text_height + border_margin * 2; XUnionRectWithRegion(&r, region, region);//updates the destination region from a union of the specified rectangle and the specified source region.
} #endif XSetRegion(display, window.gc, region);//sets the clip-mask in the GC to the specified region
#ifdef XFT if (use_xft) { XftDrawSetClip(window.xftdraw, region);//X核心支持xft的显示
} #endif #endif /* X11 */ draw_stuff(); #ifdef X11 XDestroyRegion(region); region = XCreateRegion(); } #endif /* X11 */
#ifdef SIGNAL_BLOCKING /* unblock signals of interest and let handler fly *///解除我们感兴趣信号的阻塞,由我们处理
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) CRIT_ERR("unable to sigprocmask()"); #endif
switch(g_signal_pending) { case SIGUSR1: { ERR("received SIGUSR1. reloading the config file."); reload_config();//我们定义的一个重新加载config file的信号
break; } case SIGINT: case SIGTERM: { ERR("received SIGINT or SIGTERM to terminate. bye!"); clean_up(); #ifdef X11 XDestroyRegion(region); region = NULL; #endif /* X11 */ return; /* return from main_loop */ /*break;*/ } default: { /* Reaching here means someone set a signal( SIGXXXX, signal_handler ) * but didn't write any code to deal with it. if you don't want to * handle a signal, don't set a handler on it in the first place. */ if (g_signal_pending) ERR("ignoring signal (%d)", g_signal_pending); break; } } g_signal_pending=0; } #if defined(X11) && defined(HAVE_XDAMAGE) XDamageDestroy(display, damage); XFixesDestroyRegion(display, region2); XFixesDestroyRegion(display, part); XDestroyRegion(region); region = NULL; #endif /* X11 && HAVE_XDAMAGE */ }
|