4 * Copyright (c) Tuomo Valkonen 1999-2007.
6 * See the included file LICENSE for details.
13 #include <sys/signal.h>
15 #include <libmainloop/select.h>
16 #include <libmainloop/signal.h>
17 #include <libmainloop/defer.h>
32 WHook *ioncore_handle_event_alt=NULL;
41 static void check_signals()
43 int kill_sig=mainloop_check_signals();
46 if(kill_sig==SIGUSR1){
50 if(kill_sig==SIGTERM){
51 /* Save state if not running under a session manager. */
52 ioncore_emergency_snapshot();
54 /* We may still return here if running under a session manager. */
56 ioncore_emergency_snapshot();
58 kill(getpid(), kill_sig);
67 /*{{{ Timestamp stuff */
69 #define CHKEV(E, T) case E: tm=((T*)ev)->time; break;
70 #define CLOCK_SKEW_MS 30000
72 static Time last_timestamp=CurrentTime;
74 void ioncore_update_timestamp(XEvent *ev)
79 CHKEV(ButtonPress, XButtonPressedEvent);
80 CHKEV(ButtonRelease, XButtonReleasedEvent);
81 CHKEV(EnterNotify, XEnterWindowEvent);
82 CHKEV(KeyPress, XKeyPressedEvent);
83 CHKEV(KeyRelease, XKeyReleasedEvent);
84 CHKEV(LeaveNotify, XLeaveWindowEvent);
85 CHKEV(MotionNotify, XPointerMovedEvent);
86 CHKEV(PropertyNotify, XPropertyEvent);
87 CHKEV(SelectionClear, XSelectionClearEvent);
88 CHKEV(SelectionNotify, XSelectionEvent);
89 CHKEV(SelectionRequest, XSelectionRequestEvent);
94 if(tm>last_timestamp || last_timestamp - tm > CLOCK_SKEW_MS)
99 Time ioncore_get_timestamp()
101 if(last_timestamp==CurrentTime){
102 /* Idea blatantly copied from wmx */
106 D(fprintf(stderr, "Attempting to get time from X server."));
108 dummy=XInternAtom(ioncore_g.dpy, "_ION_TIMEREQUEST", False);
110 warn(TR("Time request from X server failed."));
113 /* TODO: use some other window that should also function as a
114 * NET_WM support check window.
116 XChangeProperty(ioncore_g.dpy, ioncore_g.rootwins->dummy_win,
117 dummy, dummy, 8, PropModeAppend,
118 (unsigned char*)"", 0);
119 ioncore_get_event(&ev, PropertyChangeMask);
120 XPutBackEvent(ioncore_g.dpy, &ev);
123 return last_timestamp;
130 /*{{{ Event reading */
133 void ioncore_get_event(XEvent *ev, long mask)
140 if(XCheckMaskEvent(ioncore_g.dpy, mask, ev)){
141 ioncore_update_timestamp(ev);
146 FD_SET(ioncore_g.conn, &rfds);
148 /* Other FD:s are _not_ to be handled! */
149 select(ioncore_g.conn+1, &rfds, NULL, NULL, NULL);
160 static void skip_enterwindow()
164 XSync(ioncore_g.dpy, False);
166 while(XCheckMaskEvent(ioncore_g.dpy, EnterWindowMask, &ev)){
167 ioncore_update_timestamp(&ev);
172 void ioncore_flushfocus()
177 if(ioncore_g.input_mode!=IONCORE_INPUTMODE_NORMAL)
180 next=ioncore_g.focus_next;
181 warp=ioncore_g.warp_next;
186 ioncore_g.focus_next=NULL;
188 region_do_set_focus(next, warp);
190 /* Just greedily eating it all away that X has to offer
191 * seems to be the best we can do with Xlib.
201 /*{{{ X connection FD handler */
204 void ioncore_x_connection_handler(int conn, void *unused)
208 XNextEvent(ioncore_g.dpy, &ev);
209 ioncore_update_timestamp(&ev);
211 hook_call_alt_p(ioncore_handle_event_alt, &ev, NULL);
221 void ioncore_mainloop()
223 mainloop_trap_signals(NULL);
225 ioncore_g.opmode=IONCORE_OPMODE_NORMAL;
229 mainloop_execute_deferred();
231 if(QLength(ioncore_g.dpy)==0){
232 XSync(ioncore_g.dpy, False);
234 if(QLength(ioncore_g.dpy)==0){
235 ioncore_flushfocus();
236 XSync(ioncore_g.dpy, False);
238 if(QLength(ioncore_g.dpy)==0){
245 ioncore_x_connection_handler(ioncore_g.conn, NULL);