4 * Copyright (c) Tuomo Valkonen 1999-2006.
6 * Ion is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
16 #include <sys/signal.h>
18 #include <libmainloop/select.h>
19 #include <libmainloop/signal.h>
20 #include <libmainloop/defer.h>
35 WHook *ioncore_handle_event_alt=NULL;
44 static void check_signals()
46 int kill_sig=mainloop_check_signals();
49 if(kill_sig==SIGUSR1){
53 if(kill_sig==SIGTERM){
54 /* Save state if not running under a session manager. */
55 ioncore_emergency_snapshot();
57 /* We may still return here if running under a session manager. */
59 ioncore_emergency_snapshot();
61 kill(getpid(), kill_sig);
70 /*{{{ Timestamp stuff */
72 #define CHKEV(E, T) case E: tm=((T*)ev)->time; break;
73 #define CLOCK_SKEW_MS 30000
75 static Time last_timestamp=CurrentTime;
77 void ioncore_update_timestamp(XEvent *ev)
82 CHKEV(ButtonPress, XButtonPressedEvent);
83 CHKEV(ButtonRelease, XButtonReleasedEvent);
84 CHKEV(EnterNotify, XEnterWindowEvent);
85 CHKEV(KeyPress, XKeyPressedEvent);
86 CHKEV(KeyRelease, XKeyReleasedEvent);
87 CHKEV(LeaveNotify, XLeaveWindowEvent);
88 CHKEV(MotionNotify, XPointerMovedEvent);
89 CHKEV(PropertyNotify, XPropertyEvent);
90 CHKEV(SelectionClear, XSelectionClearEvent);
91 CHKEV(SelectionNotify, XSelectionEvent);
92 CHKEV(SelectionRequest, XSelectionRequestEvent);
97 if(tm>last_timestamp || last_timestamp - tm > CLOCK_SKEW_MS)
102 Time ioncore_get_timestamp()
104 if(last_timestamp==CurrentTime){
105 /* Idea blatantly copied from wmx */
109 D(fprintf(stderr, "Attempting to get time from X server."));
111 dummy=XInternAtom(ioncore_g.dpy, "_ION_TIMEREQUEST", False);
113 warn(TR("Time request from X server failed."));
116 /* TODO: use some other window that should also function as a
117 * NET_WM support check window.
119 XChangeProperty(ioncore_g.dpy, ioncore_g.rootwins->dummy_win,
120 dummy, dummy, 8, PropModeAppend,
121 (unsigned char*)"", 0);
122 ioncore_get_event(&ev, PropertyChangeMask);
123 XPutBackEvent(ioncore_g.dpy, &ev);
126 return last_timestamp;
133 /*{{{ Event reading */
136 void ioncore_get_event(XEvent *ev, long mask)
143 if(XCheckMaskEvent(ioncore_g.dpy, mask, ev)){
144 ioncore_update_timestamp(ev);
149 FD_SET(ioncore_g.conn, &rfds);
151 /* Other FD:s are _not_ to be handled! */
152 select(ioncore_g.conn+1, &rfds, NULL, NULL, NULL);
163 static void skip_enterwindow()
167 XSync(ioncore_g.dpy, False);
169 while(XCheckMaskEvent(ioncore_g.dpy, EnterWindowMask, &ev)){
170 ioncore_update_timestamp(&ev);
177 if(ioncore_g.focus_next!=NULL &&
178 ioncore_g.input_mode==IONCORE_INPUTMODE_NORMAL){
179 bool warp=ioncore_g.warp_next;
180 WRegion *next=ioncore_g.focus_next;
182 ioncore_g.focus_next=NULL;
184 region_do_set_focus(next, warp);
186 /* Just greedily eating it all away that X has to offer
187 * seems to be the best we can do with Xlib.
192 XFlush(ioncore_g.dpy);
199 /*{{{ X connection FD handler */
202 void ioncore_x_connection_handler(int conn, void *unused)
206 XNextEvent(ioncore_g.dpy, &ev);
207 ioncore_update_timestamp(&ev);
209 hook_call_alt_p(ioncore_handle_event_alt, &ev, NULL);
219 void ioncore_mainloop()
221 mainloop_trap_signals(NULL);
223 ioncore_g.opmode=IONCORE_OPMODE_NORMAL;
227 mainloop_execute_deferred();
230 if(QLength(ioncore_g.dpy)>0)
231 ioncore_x_connection_handler(ioncore_g.conn, NULL);