]>
Dogcows Code - chaz/openbox/blob - obt/xqueue.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 obt/display.c for the Openbox window manager
4 Copyright (c) 2007 Dana Jansens
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 See the COPYING file for a copy of the GNU General Public License.
19 #include "obt/xqueue.h"
20 #include "obt/display.h"
24 static XEvent
*q
= NULL
;
25 static gulong qsz
= 0;
26 static gulong qstart
; /* the first event in the queue */
27 static gulong qend
; /* the last event in the queue */
28 static gulong qnum
= 0;
30 static inline void shrink(void) {
31 if (qsz
> MINSZ
&& qnum
< qsz
/ 4) {
32 const gulong newsz
= qsz
/2;
40 /* all in the shinking part, move it to pos 0 */
41 else if (qstart
>= newsz
&& qend
>= newsz
) {
42 for (i
= 0; i
< qnum
; ++i
)
48 /* it wraps around to 0 right now, move the part between newsz and qsz
50 else if (qstart
>= newsz
) {
51 const gulong n
= qsz
- qstart
;
52 for (i
= 0; i
< n
; ++i
)
53 q
[newsz
-n
+i
] = q
[qstart
+i
];
57 /* it needs to wrap around to 0, move the stuff after newsz to pos 0 */
58 else if (qend
>= newsz
) {
59 const gulong n
= qend
+ 1 - newsz
;
60 for (i
= 0; i
< n
; ++i
)
65 q
= g_renew(XEvent
, q
, newsz
);
70 static inline void grow(void) {
72 const gulong newsz
= qsz
*2;
75 q
= g_renew(XEvent
, q
, newsz
);
79 if (qend
< qstart
) { /* it wraps around to 0 right now */
80 for (i
= 0; i
<= qend
; ++i
)
89 /* Grab all pending X events */
90 static gboolean
read_events(gboolean block
)
94 n
= XEventsQueued(obt_display
, QueuedAfterFlush
) > 0;
97 while ((block
&& !sth
) || n
> 0) {
100 if (XNextEvent(obt_display
, &e
) != Success
)
103 grow(); /* make sure there is room */
106 qend
= (qend
+ 1) % qsz
; /* move the end */
107 q
[qend
] = e
; /* stick the event at the end */
113 return sth
; /* return if we read anything */
116 static void pop(const gulong p
)
118 /* remove the event */
124 else if (p
== qstart
)
125 qstart
= (qstart
+ 1) % qsz
;
129 /* is it cheaper to move the start or the end ? */
130 if ((p
>= qstart
&& p
< qstart
+ qnum
/2) ||
131 (p
< qstart
&& p
< (qstart
+ qnum
/2) % qsz
))
135 while (pi
!= qstart
) {
136 const gulong pi_next
= (pi
== 0 ? qsz
-1 : pi
-1);
141 qstart
= (qstart
+ 1) % qsz
;
147 const gulong pi_next
= (pi
+ 1) % qsz
;
152 qend
= (qend
== 0 ? qsz
-1 : qend
-1);
156 shrink(); /* shrink the q if too little in it */
159 void xqueue_init(void)
161 if (q
!= NULL
) return;
163 q
= g_new(XEvent
, qsz
);
168 void xqueue_destroy(void)
170 if (q
== NULL
) return;
176 gboolean
xqueue_match_window(XEvent
*e
, gpointer data
)
178 const Window w
= *(Window
*)data
;
179 return e
->xany
.window
== w
;
182 gboolean
xqueue_match_type(XEvent
*e
, gpointer data
)
184 return e
->type
== GPOINTER_TO_INT(data
);
187 gboolean
xqueue_match_window_type(XEvent
*e
, gpointer data
)
189 const ObtXQueueWindowType x
= *(ObtXQueueWindowType
*)data
;
190 return e
->xany
.window
== x
.window
&& e
->type
== x
.type
;
193 gboolean
xqueue_match_window_message(XEvent
*e
, gpointer data
)
195 const ObtXQueueWindowMessage x
= *(ObtXQueueWindowMessage
*)data
;
196 return e
->xany
.window
== x
.window
&& e
->type
== ClientMessage
&&
197 e
->xclient
.message_type
== x
.message
;
200 gboolean
xqueue_peek(XEvent
*event_return
)
202 g_return_val_if_fail(q
!= NULL
, FALSE
);
203 g_return_val_if_fail(event_return
!= NULL
, FALSE
);
205 if (!qnum
) read_events(TRUE
);
206 if (!qnum
) return FALSE
;
207 *event_return
= q
[qstart
]; /* get the head */
211 gboolean
xqueue_peek_local(XEvent
*event_return
)
213 g_return_val_if_fail(q
!= NULL
, FALSE
);
214 g_return_val_if_fail(event_return
!= NULL
, FALSE
);
216 if (!qnum
) read_events(FALSE
);
217 if (!qnum
) return FALSE
;
218 *event_return
= q
[qstart
]; /* get the head */
222 gboolean
xqueue_next(XEvent
*event_return
)
224 g_return_val_if_fail(q
!= NULL
, FALSE
);
225 g_return_val_if_fail(event_return
!= NULL
, FALSE
);
227 if (!qnum
) read_events(TRUE
);
229 *event_return
= q
[qstart
]; /* get the head */
237 gboolean
xqueue_next_local(XEvent
*event_return
)
239 g_return_val_if_fail(q
!= NULL
, FALSE
);
240 g_return_val_if_fail(event_return
!= NULL
, FALSE
);
242 if (!qnum
) read_events(FALSE
);
244 *event_return
= q
[qstart
]; /* get the head */
252 gboolean
xqueue_exists(xqueue_match_func match
, gpointer data
)
256 g_return_val_if_fail(q
!= NULL
, FALSE
);
257 g_return_val_if_fail(match
!= NULL
, FALSE
);
261 for (i
= checked
; i
< qnum
; ++i
, ++checked
) {
262 const gulong p
= (qstart
+ i
) % qsz
;
263 if (match(&q
[p
], data
))
266 if (!read_events(TRUE
)) break; /* error */
271 gboolean
xqueue_exists_local(xqueue_match_func match
, gpointer data
)
275 g_return_val_if_fail(q
!= NULL
, FALSE
);
276 g_return_val_if_fail(match
!= NULL
, FALSE
);
280 for (i
= checked
; i
< qnum
; ++i
, ++checked
) {
281 const gulong p
= (qstart
+ i
) % qsz
;
282 if (match(&q
[p
], data
))
285 if (!read_events(FALSE
)) break;
290 gboolean
xqueue_remove_local(XEvent
*event_return
,
291 xqueue_match_func match
, gpointer data
)
295 g_return_val_if_fail(q
!= NULL
, FALSE
);
296 g_return_val_if_fail(event_return
!= NULL
, FALSE
);
297 g_return_val_if_fail(match
!= NULL
, FALSE
);
301 for (i
= checked
; i
< qnum
; ++i
, ++checked
) {
302 const gulong p
= (qstart
+ i
) % qsz
;
303 if (match(&q
[p
], data
)) {
304 *event_return
= q
[p
];
309 if (!read_events(FALSE
)) break;
314 gboolean
xqueue_pending_local(void)
316 g_return_val_if_fail(q
!= NULL
, FALSE
);
318 if (!qnum
) read_events(FALSE
);
This page took 0.045672 seconds and 4 git commands to generate.