4 * Copyright (c) Tuomo Valkonen 1999-2009.
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;
71 static Time last_timestamp
=CurrentTime
;
73 void ioncore_update_timestamp(XEvent
*ev
)
78 CHKEV(ButtonPress
, XButtonPressedEvent
);
79 CHKEV(ButtonRelease
, XButtonReleasedEvent
);
80 CHKEV(EnterNotify
, XEnterWindowEvent
);
81 CHKEV(KeyPress
, XKeyPressedEvent
);
82 CHKEV(KeyRelease
, XKeyReleasedEvent
);
83 CHKEV(LeaveNotify
, XLeaveWindowEvent
);
84 CHKEV(MotionNotify
, XPointerMovedEvent
);
85 CHKEV(PropertyNotify
, XPropertyEvent
);
86 CHKEV(SelectionClear
, XSelectionClearEvent
);
87 CHKEV(SelectionNotify
, XSelectionEvent
);
88 CHKEV(SelectionRequest
, XSelectionRequestEvent
);
93 if(tm
>last_timestamp
|| last_timestamp
- tm
> IONCORE_CLOCK_SKEW_MS
)
98 Time
ioncore_get_timestamp()
100 if(last_timestamp
==CurrentTime
){
101 /* Idea blatantly copied from wmx */
105 D(fprintf(stderr
, "Attempting to get time from X server."));
107 dummy
=XInternAtom(ioncore_g
.dpy
, "_ION_TIMEREQUEST", False
);
109 warn(TR("Time request from X server failed."));
112 /* TODO: use some other window that should also function as a
113 * NET_WM support check window.
115 XChangeProperty(ioncore_g
.dpy
, ioncore_g
.rootwins
->dummy_win
,
116 dummy
, dummy
, 8, PropModeAppend
,
117 (unsigned char*)"", 0);
118 ioncore_get_event(&ev
, PropertyChangeMask
);
119 XPutBackEvent(ioncore_g
.dpy
, &ev
);
122 return last_timestamp
;
129 /*{{{ Event reading */
132 void ioncore_get_event(XEvent
*ev
, long mask
)
139 if(XCheckMaskEvent(ioncore_g
.dpy
, mask
, ev
)){
140 ioncore_update_timestamp(ev
);
145 FD_SET(ioncore_g
.conn
, &rfds
);
147 /* Other FD:s are _not_ to be handled! */
148 select(ioncore_g
.conn
+1, &rfds
, NULL
, NULL
, NULL
);
159 static void skip_enterwindow()
163 XSync(ioncore_g
.dpy
, False
);
165 while(XCheckMaskEvent(ioncore_g
.dpy
, EnterWindowMask
, &ev
)){
166 ioncore_update_timestamp(&ev
);
171 void ioncore_flushfocus()
176 if(ioncore_g
.input_mode
!=IONCORE_INPUTMODE_NORMAL
)
179 next
=ioncore_g
.focus_next
;
180 warp
=ioncore_g
.warp_next
;
185 ioncore_g
.focus_next
=NULL
;
187 region_do_set_focus(next
, warp
);
189 /* Just greedily eating it all away that X has to offer
190 * seems to be the best we can do with Xlib.
200 /*{{{ X connection FD handler */
203 void ioncore_x_connection_handler(int conn
, void *unused
)
207 XNextEvent(ioncore_g
.dpy
, &ev
);
208 ioncore_update_timestamp(&ev
);
210 hook_call_alt_p(ioncore_handle_event_alt
, &ev
, NULL
);
220 void ioncore_mainloop()
222 mainloop_trap_signals(NULL
);
224 ioncore_g
.opmode
=IONCORE_OPMODE_NORMAL
;
228 mainloop_execute_deferred();
230 if(QLength(ioncore_g
.dpy
)==0){
231 XSync(ioncore_g
.dpy
, False
);
233 if(QLength(ioncore_g
.dpy
)==0){
234 ioncore_flushfocus();
235 XSync(ioncore_g
.dpy
, False
);
237 if(QLength(ioncore_g
.dpy
)==0){
244 ioncore_x_connection_handler(ioncore_g
.conn
, NULL
);