diff --git a/Makefile b/Makefile index 4f80428..67900d9 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ APPDIR ?= $(PREFIX)/share/applications ICODIR ?= $(PREFIX)/share/icons/hicolor/ PACKAGES = x11 x11-xcb xcb-renderutil xcb-render xcb-damage xcb-randr xcb-composite xcb-shape xcb-image xcb-xfixes xext pixman-1 -LIBS = -lm -lrt +LIBS = -lm -lrt -lev INCS = OBJS = compton.o config.o win.o x.o diff --git a/src/common.h b/src/common.h index f19cea1..1997e1f 100644 --- a/src/common.h +++ b/src/common.h @@ -94,6 +94,7 @@ #ifdef CONFIG_XINERAMA #include #endif +#include #include // libdbus @@ -180,7 +181,6 @@ #define TIME_MS_MAX LONG_MAX #define FADE_DELTA_TOLERANCE 0.2 #define SWOPTI_TOLERANCE 3000 -#define TIMEOUT_RUN_TOLERANCE 0.05 #define WIN_GET_LEADER_MAX_RECURSION 20 #define SEC_WRAP (15L * 24L * 60L * 60L) @@ -504,9 +504,10 @@ typedef struct _latom { #define REG_DATA_INIT { NULL, 0 } -struct _timeout_t; - typedef struct win win; +typedef struct ev_session_timer ev_session_timer; +typedef struct ev_session_idle ev_session_idle; +typedef struct ev_session_prepare ev_session_prepare; /// Structure representing all options. typedef struct options_t { @@ -764,6 +765,10 @@ typedef struct { /// Structure containing all necessary data for a compton session. typedef struct session { + /// ev_io for X connection + ev_io xiow; + /// libev mainloop + struct ev_loop *loop; // === Display related === /// Display in use. Display *dpy; @@ -813,25 +818,27 @@ typedef struct session { // === Operation related === /// Program options. options_t o; - /// File descriptors to check for reading. - fd_set *pfds_read; - /// File descriptors to check for writing. - fd_set *pfds_write; - /// File descriptors to check for exceptions. - fd_set *pfds_except; - /// Largest file descriptor in fd_set-s above. - int nfds_max; - /// Linked list of all timeouts. - struct _timeout_t *tmout_lst; /// Timeout for delayed unredirection. - struct _timeout_t *tmout_unredir; + ev_session_timer *unredir_timer; + /// Timer for fading + ev_session_timer *fade_timer; + /// Timer for delayed drawing, right now only used by + /// swopti + ev_session_timer *delayed_draw_timer; + /// Use an ev_idle callback for drawing + /// So we only start drawing when events are processed + ev_session_idle *draw_idle; + /// Called everytime we have timeouts or new data on socket, + /// so we can be sure if xcb read from X socket at anytime during event + /// handling, we will not left any event unhandled in the queue + ev_session_prepare *event_check; /// Whether we have hit unredirection timeout. bool tmout_unredir_hit; - /// Whether we have received an event in this cycle. - bool ev_received; + /// Whether we need to redraw the screen + bool redraw_needed; /// Whether the program is idling. I.e. no fading, no potential window /// changes. - bool idling; + bool fade_running; /// Program start time. struct timeval time_start; /// The region needs to painted on next paint. @@ -853,6 +860,8 @@ typedef struct session { xcb_render_fixed_t *blur_kerns_cache[MAX_BLUR_PASS]; /// Reset program after next paint. bool reset; + /// If compton should quit + bool quit; // === Expose event related === /// Pointer to an array of XRectangle-s of exposed region. @@ -1206,17 +1215,6 @@ struct options_tmp { double menu_opacity; }; -/// Structure for a recorded timeout. -typedef struct _timeout_t { - bool enabled; - void *data; - bool (*callback)(session_t *ps, struct _timeout_t *ptmout); - time_ms_t interval; - time_ms_t firstrun; - time_ms_t lastrun; - struct _timeout_t *next; -} timeout_t; - /// Enumeration for window event hints. typedef enum { WIN_EVMODE_UNKNOWN, @@ -1453,7 +1451,7 @@ print_timestamp(session_t *ps) { if (gettimeofday(&tm, NULL)) return; timeval_subtract(&diff, &tm, &ps->time_start); - fprintf(stderr, "[ %5ld.%02ld ] ", diff.tv_sec, diff.tv_usec / 10000); + fprintf(stderr, "[ %5ld.%06ld ] ", diff.tv_sec, diff.tv_usec); } /** @@ -1684,68 +1682,6 @@ parse_glx_swap_method(session_t *ps, const char *str) { return true; } -timeout_t * -timeout_insert(session_t *ps, time_ms_t interval, - bool (*callback)(session_t *ps, timeout_t *ptmout), void *data); - -void -timeout_invoke(session_t *ps, timeout_t *ptmout); - -bool -timeout_drop(session_t *ps, timeout_t *prm); - -void -timeout_reset(session_t *ps, timeout_t *ptmout); - -/** - * Add a file descriptor to a select() fd_set. - */ -static inline void -fds_insert_select(fd_set **ppfds, int fd) { - assert(fd <= FD_SETSIZE); - - if (!*ppfds) { - if ((*ppfds = malloc(sizeof(fd_set)))) { - FD_ZERO(*ppfds); - } - else { - fprintf(stderr, "Failed to allocate memory for select() fdset.\n"); - abort(); - } - } - - FD_SET(fd, *ppfds); -} - -/** - * Add a new file descriptor to wait for. - */ -static inline void -fds_insert(session_t *ps, int fd, short events) { - ps->nfds_max = max_i(fd + 1, ps->nfds_max); - - if (POLLIN & events) - fds_insert_select(&ps->pfds_read, fd); - if (POLLOUT & events) - fds_insert_select(&ps->pfds_write, fd); - if (POLLPRI & events) - fds_insert_select(&ps->pfds_except, fd); -} - -/** - * Delete a file descriptor to wait for. - */ -static inline void -fds_drop(session_t *ps, int fd, short events) { - // Drop fd from respective fd_set-s - if (POLLIN & events && ps->pfds_read) - FD_CLR(fd, ps->pfds_read); - if (POLLOUT & events && ps->pfds_write) - FD_CLR(fd, ps->pfds_write); - if (POLLPRI & events && ps->pfds_except) - FD_CLR(fd, ps->pfds_except); -} - /** * Wrapper of XFree() for convenience. * diff --git a/src/compton.c b/src/compton.c index ef7fdeb..56872ee 100644 --- a/src/compton.c +++ b/src/compton.c @@ -15,6 +15,8 @@ #include #include +#include + #include "compton.h" #ifdef CONFIG_OPENGL #include "opengl.h" @@ -38,9 +40,6 @@ update_refresh_rate(session_t *ps); static bool swopti_init(session_t *ps); -static void -swopti_handle_timeout(session_t *ps, struct timeval *ptv); - static void cxinerama_upd_scrs(session_t *ps); @@ -113,6 +112,24 @@ restack_win(session_t *ps, win *w, Window new_above); static void update_ewmh_active_win(session_t *ps); +static void +draw_callback(EV_P_ ev_idle *w, int revents); + +typedef struct ev_session_timer { + ev_timer w; + session_t *ps; +} ev_session_timer; + +typedef struct ev_session_idle { + ev_idle w; + session_t *ps; +} ev_session_idle; + +typedef struct ev_session_prepare { + ev_prepare w; + session_t *ps; +} ev_session_prepare; + // === Global constants === /// Name strings for window types. @@ -214,6 +231,13 @@ set_tgt_clip(session_t *ps, region_t *reg) { } } +void queue_redraw(session_t *ps) { + // If --benchmark is used, redraw is always queued + if (!ps->redraw_needed && !ps->o.benchmark) + ev_idle_start(ps->loop, &ps->draw_idle->w); + ps->redraw_needed = true; +} + static inline void paint_region(session_t *ps, win *w, int x, int y, int wid, int hei, double opacity, const region_t *reg_paint, xcb_render_picture_t pict) { @@ -281,40 +305,6 @@ void add_damage(session_t *ps, const region_t *damage) { pixman_region32_union(&ps->all_damage, &ps->all_damage, (region_t *)damage); } -#define CPY_FDS(key) \ - fd_set * key = NULL; \ - if (ps->key) { \ - key = malloc(sizeof(fd_set)); \ - memcpy(key, ps->key, sizeof(fd_set)); \ - if (!key) { \ - fprintf(stderr, "Failed to allocate memory for copying select() fdset.\n"); \ - exit(1); \ - } \ - } \ - -/** - * Poll for changes. - * - * poll() is much better than select(), but ppoll() does not exist on - * *BSD. - */ -static inline int -fds_poll(session_t *ps, struct timeval *ptv) { - // Copy fds - CPY_FDS(pfds_read); - CPY_FDS(pfds_write); - CPY_FDS(pfds_except); - - int ret = select(ps->nfds_max, pfds_read, pfds_write, pfds_except, ptv); - - free(pfds_read); - free(pfds_write); - free(pfds_except); - - return ret; -} -#undef CPY_FDS - // === Fading === /** @@ -322,13 +312,13 @@ fds_poll(session_t *ps, struct timeval *ptv) { * * In milliseconds. */ -static int +static double fade_timeout(session_t *ps) { int diff = ps->o.fade_delta - get_time_ms() + ps->fade_time; diff = normalize_i_range(diff, 0, ps->o.fade_delta * 2); - return diff; + return diff / 1000.0; } /** @@ -359,7 +349,7 @@ run_fade(session_t *ps, win *w, unsigned steps) { } if (w->opacity != w->opacity_tgt) { - ps->idling = false; + ps->fade_running = true; } } @@ -367,6 +357,9 @@ run_fade(session_t *ps, win *w, unsigned steps) { * Set fade callback of a window, and possibly execute the previous * callback. * + * If a callback can cause rendering result to change, it should call + * `queue_redraw`. + * * @param exec_callback whether the previous callback is to be executed */ void set_fade_callback(session_t *ps, win **_w, @@ -376,12 +369,8 @@ void set_fade_callback(session_t *ps, win **_w, w->fade_callback = callback; // Must be the last line as the callback could destroy w! - if (exec_callback && old_callback) { + if (exec_callback && old_callback) old_callback(ps, _w); - // Although currently no callback function affects window state on - // next paint, it could, in the future - ps->idling = false; - } } /** @@ -1228,14 +1217,15 @@ paint_preprocess(session_t *ps, win *list) { if (ps->redirected) { if (!ps->o.unredir_if_possible_delay || ps->tmout_unredir_hit) redir_stop(ps); - else if (!ps->tmout_unredir->enabled) { - timeout_reset(ps, ps->tmout_unredir); - ps->tmout_unredir->enabled = true; + else if (!ev_is_active(&ps->unredir_timer->w)) { + ev_timer_set(&ps->unredir_timer->w, + ps->o.unredir_if_possible_delay / 1000.0, 0); + ev_timer_start(ps->loop, &ps->unredir_timer->w); } } } else { - ps->tmout_unredir->enabled = false; + ev_timer_stop(ps->loop, &ps->unredir_timer->w); redir_start(ps); } @@ -2466,7 +2456,7 @@ expose_root(session_t *ps, const rect_t *rects, int nrects) { void force_repaint(session_t *ps) { assert(pixman_region32_not_empty(&ps->screen_reg)); - ps->ev_received = true; + queue_redraw(ps); add_damage(ps, &ps->screen_reg); } @@ -2483,7 +2473,7 @@ win_set_shadow_force(session_t *ps, win *w, switch_t val) { if (val != w->shadow_force) { w->shadow_force = val; win_determine_shadow(ps, w); - ps->ev_received = true; + queue_redraw(ps); } } @@ -2495,7 +2485,7 @@ win_set_fade_force(session_t *ps, win *w, switch_t val) { if (val != w->fade_force) { w->fade_force = val; win_determine_fade(ps, w); - ps->ev_received = true; + queue_redraw(ps); } } @@ -2507,7 +2497,7 @@ win_set_focused_force(session_t *ps, win *w, switch_t val) { if (val != w->focused_force) { w->focused_force = val; win_update_focused(ps, w); - ps->ev_received = true; + queue_redraw(ps); } } @@ -2519,7 +2509,7 @@ win_set_invert_color_force(session_t *ps, win *w, switch_t val) { if (val != w->invert_color_force) { w->invert_color_force = val; win_determine_invert_color(ps, w); - ps->ev_received = true; + queue_redraw(ps); } } @@ -2555,7 +2545,7 @@ opts_set_no_fading_openclose(session_t *ps, bool newval) { ps->o.no_fading_openclose = newval; for (win *w = ps->list; w; w = w->next) win_determine_fade(ps, w); - ps->ev_received = true; + queue_redraw(ps); } } @@ -3075,6 +3065,9 @@ ev_handle(session_t *ps, xcb_generic_event_t *ev) { } #endif + // XXX redraw needs to be more fine grained + queue_redraw(ps); + switch (ev->response_type) { case FocusIn: ev_focus_in(ps, (xcb_focus_in_event_t *)ev); @@ -4215,31 +4208,22 @@ swopti_init(session_t *ps) { * @param ps current session * @param[in,out] ptv pointer to the timeout */ -static void -swopti_handle_timeout(session_t *ps, struct timeval *ptv) { - if (!ptv) - return; - +static double +swopti_handle_timeout(session_t *ps) { // Get the microsecond offset of the time when the we reach the timeout // I don't think a 32-bit long could overflow here. - long offset = (ptv->tv_usec + get_time_timeval().tv_usec - ps->paint_tm_offset) % ps->refresh_intv; + long offset = (get_time_timeval().tv_usec - ps->paint_tm_offset) % ps->refresh_intv; if (offset < 0) offset += ps->refresh_intv; - assert(offset >= 0 && offset < ps->refresh_intv); - // If the target time is sufficiently close to a refresh time, don't add // an offset, to avoid certain blocking conditions. if (offset < SWOPTI_TOLERANCE || offset > ps->refresh_intv - SWOPTI_TOLERANCE) - return; + return 0; // Add an offset so we wait until the next refresh after timeout - ptv->tv_usec += ps->refresh_intv - offset; - if (ptv->tv_usec > US_PER_SEC) { - ptv->tv_usec -= US_PER_SEC; - ++ptv->tv_sec; - } + return (ps->refresh_intv - offset) / 1e6; } /** @@ -4663,150 +4647,6 @@ redir_start(session_t *ps) { } } -/** - * Get the poll time. - */ -static time_ms_t -timeout_get_poll_time(session_t *ps) { - const time_ms_t now = get_time_ms(); - time_ms_t wait = TIME_MS_MAX; - - // Traverse throught the timeout linked list - for (timeout_t *ptmout = ps->tmout_lst; ptmout; ptmout = ptmout->next) { - if (ptmout->enabled) { - time_ms_t newrun = timeout_get_newrun(ptmout); - if (newrun <= now) { - wait = 0; - break; - } - else { - time_ms_t newwait = newrun - now; - if (newwait < wait) - wait = newwait; - } - } - } - - return wait; -} - -/** - * Insert a new timeout. - */ -timeout_t * -timeout_insert(session_t *ps, time_ms_t interval, - bool (*callback)(session_t *ps, timeout_t *ptmout), void *data) { - static const timeout_t tmout_def = { - .enabled = true, - .data = NULL, - .callback = NULL, - .firstrun = 0L, - .lastrun = 0L, - .interval = 0L, - }; - - const time_ms_t now = get_time_ms(); - timeout_t *ptmout = malloc(sizeof(timeout_t)); - if (!ptmout) - printf_errfq(1, "(): Failed to allocate memory for timeout."); - memcpy(ptmout, &tmout_def, sizeof(timeout_t)); - - ptmout->interval = interval; - ptmout->firstrun = now; - ptmout->lastrun = now; - ptmout->data = data; - ptmout->callback = callback; - ptmout->next = ps->tmout_lst; - ps->tmout_lst = ptmout; - - return ptmout; -} - -/** - * Drop a timeout. - * - * @return true if we have found the timeout and removed it, false - * otherwise - */ -bool -timeout_drop(session_t *ps, timeout_t *prm) { - timeout_t **pplast = &ps->tmout_lst; - - for (timeout_t *ptmout = ps->tmout_lst; ptmout; - pplast = &ptmout->next, ptmout = ptmout->next) { - if (prm == ptmout) { - *pplast = ptmout->next; - free(ptmout); - - return true; - } - } - - return false; -} - -/** - * Clear all timeouts. - */ -static void -timeout_clear(session_t *ps) { - timeout_t *ptmout = ps->tmout_lst; - timeout_t *next = NULL; - while (ptmout) { - next = ptmout->next; - free(ptmout); - ptmout = next; - } -} - -/** - * Run timeouts. - * - * @return true if we have ran a timeout, false otherwise - */ -static bool -timeout_run(session_t *ps) { - const time_ms_t now = get_time_ms(); - bool ret = false; - timeout_t *pnext = NULL; - - for (timeout_t *ptmout = ps->tmout_lst; ptmout; ptmout = pnext) { - pnext = ptmout->next; - if (ptmout->enabled) { - const time_ms_t max = now + - (time_ms_t) (ptmout->interval * TIMEOUT_RUN_TOLERANCE); - time_ms_t newrun = timeout_get_newrun(ptmout); - if (newrun <= max) { - ret = true; - timeout_invoke(ps, ptmout); - } - } - } - - return ret; -} - -/** - * Invoke a timeout. - */ -void -timeout_invoke(session_t *ps, timeout_t *ptmout) { - const time_ms_t now = get_time_ms(); - ptmout->lastrun = now; - // Avoid modifying the timeout structure after running timeout, to - // make it possible to remove timeout in callback - if (ptmout->callback) - ptmout->callback(ps, ptmout); -} - -/** - * Reset a timeout to initial state. - */ -void -timeout_reset(session_t *ps, timeout_t *ptmout) { - ptmout->firstrun = ptmout->lastrun = get_time_ms(); -} - /** * Unredirect all windows. */ @@ -4836,99 +4676,156 @@ redir_stop(session_t *ps) { } } -/** - * Unredirection timeout callback. - */ -static bool -tmout_unredir_callback(session_t *ps, timeout_t *tmout) { - ps->tmout_unredir_hit = true; - tmout->enabled = false; - - return true; +// Handle queued events before we go to sleep +static void +handle_queued_x_events(EV_P_ ev_prepare *w, int revents) { + ev_session_prepare *sw = (void *)w; + session_t *ps = sw->ps; + xcb_generic_event_t *ev; + xcb_connection_t *c = XGetXCBConnection(ps->dpy); + while ((ev = xcb_poll_for_queued_event(c))) { + ev_handle(ps, ev); + free(ev); + }; + XFlush(ps->dpy); + xcb_flush(c); } /** - * Main loop. + * Unredirection timeout callback. */ -static bool -mainloop(session_t *ps) { - // Don't miss timeouts even when we have a LOT of other events! - timeout_run(ps); +static void +tmout_unredir_callback(EV_P_ ev_timer *w, int revents) { + ev_session_timer *sw = (void *)w; + sw->ps->tmout_unredir_hit = true; + queue_redraw(sw->ps); +} - // Process existing events - // Sometimes poll() returns 1 but no events are actually read, - // causing XNextEvent() to block, I have no idea what's wrong, so we - // check for the number of events here. +static void +fade_timer_callback(EV_P_ ev_timer *w, int revents) { + ev_session_timer *sw = (void *)w; + queue_redraw(sw->ps); +} + +static void +_draw_callback(EV_P_ session_t *ps, int revents) { + if (ps->o.benchmark) { + if (ps->o.benchmark_wid) { + win *wi = find_win(ps, ps->o.benchmark_wid); + if (!wi) { + printf_errf("(): Couldn't find specified benchmark window."); + exit(1); + } + add_damage_from_win(ps, wi); + } + else { + force_repaint(ps); + } + } + + ps->fade_running = false; + win *t = paint_preprocess(ps, ps->list); + ps->tmout_unredir_hit = false; + + // Start/stop fade timer depends on whether window are fading + if (!ps->fade_running && ev_is_active(&ps->fade_timer->w)) + ev_timer_stop(ps->loop, &ps->fade_timer->w); + else if (ps->fade_running && !ev_is_active(&ps->fade_timer->w)) { + ev_timer_set(&ps->fade_timer->w, fade_timeout(ps), 0); + ev_timer_start(ps->loop, &ps->fade_timer->w); + } + + // If the screen is unredirected, free all_damage to stop painting + if (!ps->redirected || ps->o.stoppaint_force == ON) + pixman_region32_clear(&ps->all_damage); + + if (pixman_region32_not_empty(&ps->all_damage)) { + region_t all_damage_orig, *region_real = NULL; + pixman_region32_init(&all_damage_orig); + + // keep a copy of non-resized all_damage for region_real + if (ps->o.resize_damage > 0) { + copy_region(&all_damage_orig, &ps->all_damage); + resize_region(ps, &ps->all_damage, ps->o.resize_damage); + region_real = &all_damage_orig; + } + + static int paint = 0; + paint_all(ps, &ps->all_damage, region_real, t); + + pixman_region32_clear(&ps->all_damage); + pixman_region32_fini(&all_damage_orig); + + paint++; + if (ps->o.benchmark && paint >= ps->o.benchmark) + exit(0); + } + + if (!ps->fade_running) + ps->fade_time = 0L; + + ps->redraw_needed = false; +} + +static void +draw_callback(EV_P_ ev_idle *w, int revents) { + // This function is not used if we are using --swopti + ev_session_idle *sw = (void *)w; + + _draw_callback(EV_A_ sw->ps, revents); + + // Don't do painting non-stop unless we are in benchmark mode + if (!sw->ps->o.benchmark) + ev_idle_stop(sw->ps->loop, &sw->ps->draw_idle->w); +} + +static void +delayed_draw_timer_callback(EV_P_ ev_timer *w, int revents) { + ev_session_timer *sw = (void *)w; + _draw_callback(EV_A_ sw->ps, revents); + + // We might have stopped the ev_idle in delayed_draw_callback, + // so we restart it if we are in benchmark mode + if (sw->ps->o.benchmark) + ev_idle_start(EV_A_ &sw->ps->draw_idle->w); +} + +static void +delayed_draw_callback(EV_P_ ev_idle *w, int revents) { + // This function is only used if we are using --swopti + ev_session_idle *sw = (void *)w; + if (ev_is_active(sw->ps->delayed_draw_timer)) + return; + + double delay = swopti_handle_timeout(sw->ps); + printf_errf("(): %lf", delay); + if (delay < 1e-6) + return _draw_callback(EV_A_ sw->ps, revents); + + // This is a little bit hacky. When we get to this point in code, we need + // to update the screen , but we will only be updated after a delay, So + // we want to stop the ev_idle, so this callback doesn't get call repeatedly + // during the delay, we also want queue_redraw to not restart the ev_idle. + // So we stop ev_idle and leave ps->redraw_needed to be true. + // + // We do this anyway even if we are in benchmark mode. That means we will + // have to restart draw_idle after the draw actually happened when we are in + // benchmark mode. + ev_idle_stop(sw->ps->loop, &sw->ps->draw_idle->w); + + ev_timer_set(&sw->ps->delayed_draw_timer->w, delay, 0); + ev_timer_start(sw->ps->loop, &sw->ps->delayed_draw_timer->w); +} + +static void +x_event_callback(EV_P_ ev_io *w, int revents) { + session_t *ps = (session_t *)w; xcb_connection_t *c = XGetXCBConnection(ps->dpy); xcb_generic_event_t *ev = xcb_poll_for_event(c); if (ev) { ev_handle(ps, ev); - ps->ev_received = true; free(ev); - - return true; } - -#ifdef CONFIG_DBUS - if (ps->o.dbus) { - cdbus_loop(ps); - } -#endif - - if (ps->reset) - return false; - - // Calculate timeout - struct timeval *ptv = NULL; - { - // Consider ev_received firstly - if (ps->ev_received || ps->o.benchmark) { - ptv = malloc(sizeof(struct timeval)); - ptv->tv_sec = 0L; - ptv->tv_usec = 0L; - } - // Then consider fading timeout - else if (!ps->idling) { - ptv = malloc(sizeof(struct timeval)); - *ptv = ms_to_tv(fade_timeout(ps)); - } - - // Software optimization is to be applied on timeouts that require - // immediate painting only - if (ptv && ps->o.sw_opti) - swopti_handle_timeout(ps, ptv); - - // Don't continue looping for 0 timeout - if (ptv && timeval_isempty(ptv)) { - free(ptv); - return false; - } - - // Now consider the waiting time of other timeouts - time_ms_t tmout_ms = timeout_get_poll_time(ps); - if (tmout_ms < TIME_MS_MAX) { - if (!ptv) { - ptv = malloc(sizeof(struct timeval)); - *ptv = ms_to_tv(tmout_ms); - } - else if (timeval_ms_cmp(ptv, tmout_ms) > 0) { - *ptv = ms_to_tv(tmout_ms); - } - } - - // Don't continue looping for 0 timeout - if (ptv && timeval_isempty(ptv)) { - free(ptv); - return false; - } - } - - // Polling - fds_poll(ps, ptv); - free(ptv); - ptv = NULL; - - return true; } static void @@ -5073,20 +4970,14 @@ session_init(session_t *ps_old, int argc, char **argv) { .track_leader = false, }, - .pfds_read = NULL, - .pfds_write = NULL, - .pfds_except = NULL, - .nfds_max = 0, - .tmout_lst = NULL, - .time_start = { 0, 0 }, .redirected = false, .alpha_picts = NULL, - .idling = false, + .fade_running = false, .fade_time = 0L, .ignore_head = NULL, .ignore_tail = NULL, - .reset = false, + .quit = false, .expose_rects = NULL, .size_expose = 0, @@ -5159,6 +5050,7 @@ session_init(session_t *ps_old, int argc, char **argv) { // Allocate a session and copy default values into it session_t *ps = malloc(sizeof(session_t)); *ps = s_def; + ps->loop = EV_DEFAULT; pixman_region32_init(&ps->screen_reg); pixman_region32_init(&ps->all_damage); for (int i = 0; i < CGLX_MAX_BUFFER_AGE; i ++) @@ -5456,10 +5348,44 @@ session_init(session_t *ps_old, int argc, char **argv) { ps->o.shadow_red, ps->o.shadow_green, ps->o.shadow_blue); } - fds_insert(ps, ConnectionNumber(ps->dpy), POLLIN); - ps->tmout_unredir = timeout_insert(ps, ps->o.unredir_if_possible_delay, - tmout_unredir_callback, NULL); - ps->tmout_unredir->enabled = false; + ev_io_init(&ps->xiow, x_event_callback, ConnectionNumber(ps->dpy), EV_READ); + ev_io_start(ps->loop, &ps->xiow); + ps->unredir_timer = calloc(1, sizeof(ev_session_timer)); + ps->unredir_timer->ps = ps; + ev_init(&ps->unredir_timer->w, tmout_unredir_callback); + ps->draw_idle = calloc(1, sizeof(ev_session_idle)); + ps->draw_idle->ps = ps; + if (ps->o.sw_opti) + ev_idle_init(&ps->draw_idle->w, delayed_draw_callback); + else + ev_idle_init(&ps->draw_idle->w, draw_callback); + + ps->fade_timer = calloc(1, sizeof(ev_session_timer)); + ps->fade_timer->ps = ps; + ev_init(&ps->fade_timer->w, fade_timer_callback); + + ps->delayed_draw_timer = calloc(1, sizeof(ev_session_timer)); + ps->delayed_draw_timer->ps = ps; + ev_init(&ps->delayed_draw_timer->w, delayed_draw_timer_callback); + + // xcb can read multiple events from the socket anytime a request which requires + // reply is made. + // + // Use an ev_prepare to make sure we cannot accidentally forget to handle them + // before we go to sleep. + // + // If we don't drain the queue before goes to sleep (i.e. blocking on socket + // input), we will be sleeping with events available in queue. Which might + // cause us to block indefinitely because arrival of new events could be + // dependent on processing of existing events (e.g. if we don't process damage + // event and do damage subtract, new damage event won't be generated. + ps->event_check = calloc(1, sizeof(ev_session_prepare)); + ps->event_check->ps = ps; + ev_prepare_init(&ps->event_check->w, handle_queued_x_events); + // Make sure nothing can cause xcb to read from the X socket after events are + // handled and before we going to sleep. + ev_set_priority(&ps->event_check->w, EV_MINPRI); + ev_prepare_start(ps->loop, &ps->event_check->w); XGrabServer(ps->dpy); @@ -5647,9 +5573,6 @@ session_destroy(session_t *ps) { free(ps->o.blur_kerns[i]); free(ps->blur_kerns_cache[i]); } - free(ps->pfds_read); - free(ps->pfds_write); - free(ps->pfds_except); free(ps->o.glx_fshader_win_str); free_xinerama_info(ps); free(ps->pictfmts); @@ -5686,6 +5609,7 @@ session_destroy(session_t *ps) { // Flush all events XSync(ps->dpy, True); + ev_io_stop(ps->loop, &ps->xiow); #ifdef DEBUG_XRC // Report about resource leakage @@ -5693,8 +5617,21 @@ session_destroy(session_t *ps) { #endif // Free timeouts - ps->tmout_unredir = NULL; - timeout_clear(ps); + ev_timer_stop(ps->loop, &ps->unredir_timer->w); + free(ps->unredir_timer); + ps->unredir_timer = NULL; + + ev_timer_stop(ps->loop, &ps->fade_timer->w); + free(ps->fade_timer); + ps->fade_timer = NULL; + + ev_idle_stop(ps->loop, &ps->draw_idle->w); + free(ps->draw_idle); + ps->draw_idle = NULL; + + ev_prepare_stop(ps->loop, &ps->event_check->w); + free(ps->event_check); + ps->event_check = NULL; if (ps == ps_g) ps_g = NULL; @@ -5727,68 +5664,10 @@ session_run(session_t *ps) { if (ps->redirected) paint_all(ps, NULL, NULL, t); - // Initialize idling - ps->idling = false; + if (ps->o.benchmark) + ev_idle_start(ps->loop, &ps->draw_idle->w); - // Main loop - while (!ps->reset) { - ps->ev_received = false; - - while (mainloop(ps)) - continue; - - if (ps->o.benchmark) { - if (ps->o.benchmark_wid) { - win *w = find_win(ps, ps->o.benchmark_wid); - if (!w) { - printf_errf("(): Couldn't find specified benchmark window."); - session_destroy(ps); - exit(1); - } - add_damage_from_win(ps, w); - } - else { - force_repaint(ps); - } - } - - // idling will be turned off during paint_preprocess() if needed - ps->idling = true; - - t = paint_preprocess(ps, ps->list); - ps->tmout_unredir_hit = false; - - // If the screen is unredirected, free all_damage to stop painting - if (!ps->redirected || ON == ps->o.stoppaint_force) - pixman_region32_clear(&ps->all_damage); - - if (pixman_region32_not_empty(&ps->all_damage)) { - region_t all_damage_orig, *region_real = NULL; - pixman_region32_init(&all_damage_orig); - - // keep a copy of non-resized all_damage for region_real - if (ps->o.resize_damage > 0) { - copy_region(&all_damage_orig, &ps->all_damage); - resize_region(ps, &ps->all_damage, ps->o.resize_damage); - region_real = &all_damage_orig; - } - - static int paint = 0; - paint_all(ps, &ps->all_damage, region_real, t); - - pixman_region32_clear(&ps->all_damage); - pixman_region32_fini(&all_damage_orig); - - paint++; - if (ps->o.benchmark && paint >= ps->o.benchmark) - exit(0); - - XSync(ps->dpy, False); - } - - if (ps->idling) - ps->fade_time = 0L; - } + ev_run(ps->loop, 0); } /** @@ -5799,8 +5678,7 @@ session_run(session_t *ps) { static void reset_enable(int __attribute__((unused)) signum) { session_t * const ps = ps_g; - - ps->reset = true; + ev_break(ps->loop, EVBREAK_ALL); } /** @@ -5826,7 +5704,8 @@ main(int argc, char **argv) { // Main loop session_t *ps_old = ps_g; - while (1) { + bool quit = false; + while (!quit) { ps_g = session_init(ps_old, argc, argv); if (!ps_g) { printf_errf("(): Failed to create new session."); @@ -5834,6 +5713,7 @@ main(int argc, char **argv) { } session_run(ps_g); ps_old = ps_g; + quit = ps_g->quit; session_destroy(ps_g); } diff --git a/src/compton.h b/src/compton.h index bd32a11..d7af1cc 100644 --- a/src/compton.h +++ b/src/compton.h @@ -491,11 +491,6 @@ ensure_glx_context(session_t *ps) { } #endif -static inline time_ms_t -timeout_get_newrun(const timeout_t *ptmout) { - return ptmout->firstrun + (max_l((ptmout->lastrun + (time_ms_t) (ptmout->interval * TIMEOUT_RUN_TOLERANCE) - ptmout->firstrun) / ptmout->interval, (ptmout->lastrun + (time_ms_t) (ptmout->interval * (1 - TIMEOUT_RUN_TOLERANCE)) - ptmout->firstrun) / ptmout->interval) + 1) * ptmout->interval; -} - /** * Get the Xinerama screen a window is on. * diff --git a/src/dbus.c b/src/dbus.c index a8a4025..028cc6c 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -10,6 +10,27 @@ #include "dbus.h" +static DBusHandlerResult +cdbus_process(DBusConnection *conn, DBusMessage *m, void *); + +static dbus_bool_t +cdbus_callback_add_timeout(DBusTimeout *timeout, void *data); + +static void +cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data); + +static void +cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data); + +static dbus_bool_t +cdbus_callback_add_watch(DBusWatch *watch, void *data); + +static void +cdbus_callback_remove_watch(DBusWatch *watch, void *data); + +static void +cdbus_callback_watch_toggled(DBusWatch *watch, void *data); + /** * Initialize D-Bus connection. */ @@ -84,7 +105,7 @@ cdbus_init(session_t *ps) { dbus_error_free(&err); return false; } - + dbus_connection_add_filter(ps->dbus_conn, cdbus_process, ps, NULL); return true; } @@ -117,6 +138,20 @@ cdbus_destroy(session_t *ps) { */ ///@{ +typedef struct ev_dbus_timer { + ev_timer w; + DBusTimeout *t; +} ev_dbus_timer; + +/** + * Callback for handling a D-Bus timeout. + */ +static void +cdbus_callback_handle_timeout(EV_P_ ev_timer *w, int revents) { + ev_dbus_timer *t = (void *)w; + dbus_timeout_handle(t->t); +} + /** * Callback for adding D-Bus timeout. */ @@ -124,12 +159,16 @@ static dbus_bool_t cdbus_callback_add_timeout(DBusTimeout *timeout, void *data) { session_t *ps = data; - timeout_t *ptmout = timeout_insert(ps, dbus_timeout_get_interval(timeout), - cdbus_callback_handle_timeout, timeout); - if (ptmout) - dbus_timeout_set_data(timeout, ptmout, NULL); + ev_dbus_timer *t = calloc(1, sizeof *t); + double i = dbus_timeout_get_interval(timeout) / 1000.0; + ev_timer_init(&t->w, cdbus_callback_handle_timeout, i, i); + t->t = timeout; + dbus_timeout_set_data(timeout, t, NULL); - return (bool) ptmout; + if (dbus_timeout_get_enabled(timeout)) + ev_timer_start(ps->loop, &t->w); + + return true; } /** @@ -139,10 +178,10 @@ static void cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data) { session_t *ps = data; - timeout_t *ptmout = dbus_timeout_get_data(timeout); - assert(ptmout); - if (ptmout) - timeout_drop(ps, ptmout); + ev_dbus_timer *t = dbus_timeout_get_data(timeout); + assert(t); + ev_timer_stop(ps->loop, &t->w); + free(t); } /** @@ -150,52 +189,77 @@ cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data) { */ static void cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data) { - timeout_t *ptmout = dbus_timeout_get_data(timeout); + session_t *ps = data; + ev_dbus_timer *t = dbus_timeout_get_data(timeout); - assert(ptmout); - if (ptmout) { - ptmout->enabled = dbus_timeout_get_enabled(timeout); - // Refresh interval as libdbus doc says: "Whenever a timeout is toggled, - // its interval may change." - ptmout->interval = dbus_timeout_get_interval(timeout); + assert(t); + ev_timer_stop(ps->loop, &t->w); + if (dbus_timeout_get_enabled(timeout)) { + double i = dbus_timeout_get_interval(timeout) / 1000.0; + ev_timer_set(&t->w, i, i); + ev_timer_start(ps->loop, &t->w); } } -/** - * Callback for handling a D-Bus timeout. - */ -static bool -cdbus_callback_handle_timeout(session_t *ps, timeout_t *ptmout) { - assert(ptmout && ptmout->data); - if (ptmout && ptmout->data) - return dbus_timeout_handle(ptmout->data); - - return false; -} - ///@} /** @name DBusWatch handling */ ///@{ +typedef struct ev_dbus_io { + ev_io w; + session_t *ps; + DBusWatch *dw; +} ev_dbus_io; + +void cdbus_io_callback(EV_P_ ev_io *w, int revents) { + ev_dbus_io *dw = (void *)w; + DBusWatchFlags flags = 0; + if (revents & EV_READ) + flags |= DBUS_WATCH_READABLE; + if (revents & EV_WRITE) + flags |= DBUS_WATCH_WRITABLE; + dbus_watch_handle(dw->dw, flags); + while (dbus_connection_dispatch(dw->ps->dbus_conn) != DBUS_DISPATCH_COMPLETE); +} + +/** + * Determine the poll condition of a DBusWatch. + */ +static inline int +cdbus_get_watch_cond(DBusWatch *watch) { + const unsigned flags = dbus_watch_get_flags(watch); + int condition = 0; + if (flags & DBUS_WATCH_READABLE) + condition |= EV_READ; + if (flags & DBUS_WATCH_WRITABLE) + condition |= EV_WRITE; + + return condition; +} + /** * Callback for adding D-Bus watch. */ static dbus_bool_t cdbus_callback_add_watch(DBusWatch *watch, void *data) { - // Leave disabled watches alone - if (!dbus_watch_get_enabled(watch)) - return TRUE; - session_t *ps = data; - // Insert the file descriptor - fds_insert(ps, dbus_watch_get_unix_fd(watch), - cdbus_get_watch_cond(watch)); + ev_dbus_io *w = calloc(1, sizeof *w); + w->dw = watch; + w->ps = ps; + ev_io_init(&w->w, cdbus_io_callback, dbus_watch_get_unix_fd(watch), + cdbus_get_watch_cond(watch)); + + // Leave disabled watches alone + if (dbus_watch_get_enabled(watch)) + ev_io_start(ps->loop, &w->w); + + dbus_watch_set_data(watch, w, NULL); // Always return true - return TRUE; + return true; } /** @@ -204,9 +268,9 @@ cdbus_callback_add_watch(DBusWatch *watch, void *data) { static void cdbus_callback_remove_watch(DBusWatch *watch, void *data) { session_t *ps = data; - - fds_drop(ps, dbus_watch_get_unix_fd(watch), - cdbus_get_watch_cond(watch)); + ev_dbus_io *w = dbus_watch_get_data(watch); + ev_io_stop(ps->loop, &w->w); + free(w); } /** @@ -214,12 +278,12 @@ cdbus_callback_remove_watch(DBusWatch *watch, void *data) { */ static void cdbus_callback_watch_toggled(DBusWatch *watch, void *data) { - if (dbus_watch_get_enabled(watch)) { - cdbus_callback_add_watch(watch, data); - } - else { - cdbus_callback_remove_watch(watch, data); - } + session_t *ps = data; + ev_io *w = dbus_watch_get_data(watch); + if (dbus_watch_get_enabled(watch)) + ev_io_start(ps->loop, w); + else + ev_io_stop(ps->loop, w); } ///@} @@ -534,110 +598,10 @@ cdbus_msg_get_arg(DBusMessage *msg, int count, const int type, void *pdest) { return true; } -void -cdbus_loop(session_t *ps) { - dbus_connection_read_write(ps->dbus_conn, 0); - DBusMessage *msg = NULL; - while ((msg = dbus_connection_pop_message(ps->dbus_conn))) - cdbus_process(ps, msg); -} - /** @name Message processing */ ///@{ -/** - * Process a message from D-Bus. - */ -static void -cdbus_process(session_t *ps, DBusMessage *msg) { - bool success = false; - -#define cdbus_m_ismethod(method) \ - dbus_message_is_method_call(msg, CDBUS_INTERFACE_NAME, method) - - if (cdbus_m_ismethod("reset")) { - ps->reset = true; - if (!dbus_message_get_no_reply(msg)) - cdbus_reply_bool(ps, msg, true); - success = true; - } - else if (cdbus_m_ismethod("repaint")) { - force_repaint(ps); - if (!dbus_message_get_no_reply(msg)) - cdbus_reply_bool(ps, msg, true); - success = true; - } - else if (cdbus_m_ismethod("list_win")) { - success = cdbus_process_list_win(ps, msg); - } - else if (cdbus_m_ismethod("win_get")) { - success = cdbus_process_win_get(ps, msg); - } - else if (cdbus_m_ismethod("win_set")) { - success = cdbus_process_win_set(ps, msg); - } - else if (cdbus_m_ismethod("find_win")) { - success = cdbus_process_find_win(ps, msg); - } - else if (cdbus_m_ismethod("opts_get")) { - success = cdbus_process_opts_get(ps, msg); - } - else if (cdbus_m_ismethod("opts_set")) { - success = cdbus_process_opts_set(ps, msg); - } -#undef cdbus_m_ismethod - else if (dbus_message_is_method_call(msg, - "org.freedesktop.DBus.Introspectable", "Introspect")) { - success = cdbus_process_introspect(ps, msg); - } - else if (dbus_message_is_method_call(msg, - "org.freedesktop.DBus.Peer", "Ping")) { - cdbus_reply(ps, msg, NULL, NULL); - success = true; - } - else if (dbus_message_is_method_call(msg, - "org.freedesktop.DBus.Peer", "GetMachineId")) { - char *uuid = dbus_get_local_machine_id(); - if (uuid) { - cdbus_reply_string(ps, msg, uuid); - dbus_free(uuid); - success = true; - } - } - else if (dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameAcquired") - || dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameLost")) { - success = true; - } - else { - if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(msg)) { - printf_errf("(): Error message of path \"%s\" " - "interface \"%s\", member \"%s\", error \"%s\"", - dbus_message_get_path(msg), dbus_message_get_interface(msg), - dbus_message_get_member(msg), dbus_message_get_error_name(msg)); - } - else { - printf_errf("(): Illegal message of type \"%s\", path \"%s\" " - "interface \"%s\", member \"%s\"", - cdbus_repr_msgtype(msg), dbus_message_get_path(msg), - dbus_message_get_interface(msg), dbus_message_get_member(msg)); - } - if (DBUS_MESSAGE_TYPE_METHOD_CALL == dbus_message_get_type(msg) - && !dbus_message_get_no_reply(msg)) - cdbus_reply_err(ps, msg, CDBUS_ERROR_BADMSG, CDBUS_ERROR_BADMSG_S); - success = true; - } - - // If the message could not be processed, and an reply is expected, return - // an empty reply. - if (!success && DBUS_MESSAGE_TYPE_METHOD_CALL == dbus_message_get_type(msg) - && !dbus_message_get_no_reply(msg)) - cdbus_reply_err(ps, msg, CDBUS_ERROR_UNKNOWN, CDBUS_ERROR_UNKNOWN_S); - - // Free the message - dbus_message_unref(msg); -} - /** * Process a list_win D-Bus request. */ @@ -993,6 +957,9 @@ cdbus_process_opts_get(session_t *ps, DBusMessage *msg) { return true; } +// XXX Remove this after header clean up +void queue_redraw(session_t *ps); + /** * Process a opts_set D-Bus request. */ @@ -1055,7 +1022,7 @@ cdbus_process_opts_set(session_t *ps, DBusMessage *msg) { return false; if (ps->o.unredir_if_possible != val) { ps->o.unredir_if_possible = val; - ps->ev_received = true; + queue_redraw(ps); } goto cdbus_process_opts_set_success; } @@ -1171,6 +1138,100 @@ cdbus_process_introspect(session_t *ps, DBusMessage *msg) { } ///@} +/** + * Process a message from D-Bus. + */ +static DBusHandlerResult +cdbus_process(DBusConnection *c, DBusMessage *msg, void *ud) { + session_t *ps = ud; + bool handled = false; + +#define cdbus_m_ismethod(method) \ + dbus_message_is_method_call(msg, CDBUS_INTERFACE_NAME, method) + + if (cdbus_m_ismethod("reset")) { + ps->reset = true; + if (!dbus_message_get_no_reply(msg)) + cdbus_reply_bool(ps, msg, true); + handled = true; + } + else if (cdbus_m_ismethod("repaint")) { + force_repaint(ps); + if (!dbus_message_get_no_reply(msg)) + cdbus_reply_bool(ps, msg, true); + handled = true; + } + else if (cdbus_m_ismethod("list_win")) { + handled = cdbus_process_list_win(ps, msg); + } + else if (cdbus_m_ismethod("win_get")) { + handled = cdbus_process_win_get(ps, msg); + } + else if (cdbus_m_ismethod("win_set")) { + handled = cdbus_process_win_set(ps, msg); + } + else if (cdbus_m_ismethod("find_win")) { + handled = cdbus_process_find_win(ps, msg); + } + else if (cdbus_m_ismethod("opts_get")) { + handled = cdbus_process_opts_get(ps, msg); + } + else if (cdbus_m_ismethod("opts_set")) { + handled = cdbus_process_opts_set(ps, msg); + } +#undef cdbus_m_ismethod + else if (dbus_message_is_method_call(msg, + "org.freedesktop.DBus.Introspectable", "Introspect")) { + handled = cdbus_process_introspect(ps, msg); + } + else if (dbus_message_is_method_call(msg, + "org.freedesktop.DBus.Peer", "Ping")) { + cdbus_reply(ps, msg, NULL, NULL); + handled = true; + } + else if (dbus_message_is_method_call(msg, + "org.freedesktop.DBus.Peer", "GetMachineId")) { + char *uuid = dbus_get_local_machine_id(); + if (uuid) { + cdbus_reply_string(ps, msg, uuid); + dbus_free(uuid); + handled = true; + } + } + else if (dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameAcquired") + || dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameLost")) { + handled = true; + } + else { + if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(msg)) { + printf_errf("(): Error message of path \"%s\" " + "interface \"%s\", member \"%s\", error \"%s\"", + dbus_message_get_path(msg), dbus_message_get_interface(msg), + dbus_message_get_member(msg), dbus_message_get_error_name(msg)); + } + else { + printf_errf("(): Illegal message of type \"%s\", path \"%s\" " + "interface \"%s\", member \"%s\"", + cdbus_repr_msgtype(msg), dbus_message_get_path(msg), + dbus_message_get_interface(msg), dbus_message_get_member(msg)); + } + if (DBUS_MESSAGE_TYPE_METHOD_CALL == dbus_message_get_type(msg) + && !dbus_message_get_no_reply(msg)) + cdbus_reply_err(ps, msg, CDBUS_ERROR_BADMSG, CDBUS_ERROR_BADMSG_S); + handled = true; + } + + // If the message could not be processed, and an reply is expected, return + // an empty reply. + if (!handled && DBUS_MESSAGE_TYPE_METHOD_CALL == dbus_message_get_type(msg) + && !dbus_message_get_no_reply(msg)) { + cdbus_reply_err(ps, msg, CDBUS_ERROR_UNKNOWN, CDBUS_ERROR_UNKNOWN_S); + handled = true; + } + + return handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + /** @name Core callbacks */ ///@{ diff --git a/src/dbus.h b/src/dbus.h index b924a5e..804fa19 100644 --- a/src/dbus.h +++ b/src/dbus.h @@ -42,42 +42,6 @@ typedef uint16_t cdbus_enum_t; #define CDBUS_TYPE_ENUM DBUS_TYPE_UINT16 #define CDBUS_TYPE_ENUM_STR DBUS_TYPE_UINT16_AS_STRING -static dbus_bool_t -cdbus_callback_add_timeout(DBusTimeout *timeout, void *data); - -static void -cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data); - -static void -cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data); - -static bool -cdbus_callback_handle_timeout(session_t *ps, timeout_t *ptmout); - -/** - * Determine the poll condition of a DBusWatch. - */ -static inline short -cdbus_get_watch_cond(DBusWatch *watch) { - const unsigned flags = dbus_watch_get_flags(watch); - short condition = POLLERR | POLLHUP; - if (flags & DBUS_WATCH_READABLE) - condition |= POLLIN; - if (flags & DBUS_WATCH_WRITABLE) - condition |= POLLOUT; - - return condition; -} - -static dbus_bool_t -cdbus_callback_add_watch(DBusWatch *watch, void *data); - -static void -cdbus_callback_remove_watch(DBusWatch *watch, void *data); - -static void -cdbus_callback_watch_toggled(DBusWatch *watch, void *data); - static bool cdbus_apdarg_bool(session_t *ps, DBusMessage *msg, const void *data); @@ -221,32 +185,4 @@ cdbus_repr_msgtype(DBusMessage *msg) { return dbus_message_type_to_string(dbus_message_get_type(msg)); } -/** @name Message processing - */ -///@{ - -static void -cdbus_process(session_t *ps, DBusMessage *msg); - -static bool -cdbus_process_list_win(session_t *ps, DBusMessage *msg); - -static bool -cdbus_process_win_get(session_t *ps, DBusMessage *msg); - -static bool -cdbus_process_win_set(session_t *ps, DBusMessage *msg); - -static bool -cdbus_process_find_win(session_t *ps, DBusMessage *msg); - -static bool -cdbus_process_opts_get(session_t *ps, DBusMessage *msg); - -static bool -cdbus_process_opts_set(session_t *ps, DBusMessage *msg); - -static bool -cdbus_process_introspect(session_t *ps, DBusMessage *msg); - ///@}