1 /**
2  *
3  * Compiz group plugin
4  *
5  * queues.c
6  *
7  * Copyright : (C) 2006-2007 by Patrick Niklaus, Roi Cohen, Danny Baumann
8  * Authors: Patrick Niklaus <patrick.niklaus@googlemail.com>
9  *          Roi Cohen       <roico.beryl@gmail.com>
10  *          Danny Baumann   <maniac@opencompositing.org>
11  *
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  **/
24 
25 #include "group-internal.h"
26 
27 /*
28  * functions enqueuing pending notifies
29  *
30  */
31 
32 /* forward declaration */
33 static Bool groupDequeueTimer (void *closure);
34 
35 void
groupEnqueueMoveNotify(CompWindow * w,int dx,int dy,Bool immediate,Bool sync)36 groupEnqueueMoveNotify (CompWindow *w,
37 			int        dx,
38 			int        dy,
39 			Bool       immediate,
40 			Bool       sync)
41 {
42     GroupPendingMoves *move;
43 
44     GROUP_SCREEN (w->screen);
45 
46     move = malloc (sizeof (GroupPendingMoves));
47     if (!move)
48 	return;
49 
50     move->w  = w;
51     move->dx = dx;
52     move->dy = dy;
53 
54     move->immediate = immediate;
55     move->sync      = sync;
56     move->next      = NULL;
57 
58     if (gs->pendingMoves)
59     {
60 	GroupPendingMoves *temp;
61 	for (temp = gs->pendingMoves; temp->next; temp = temp->next);
62 
63 	temp->next = move;
64     }
65     else
66 	gs->pendingMoves = move;
67 
68     if (!gs->dequeueTimeoutHandle)
69     {
70 	gs->dequeueTimeoutHandle =
71 	    compAddTimeout (0, 0, groupDequeueTimer, (void *) w->screen);
72     }
73 }
74 
75 static void
groupDequeueSyncs(GroupPendingSyncs * syncs)76 groupDequeueSyncs (GroupPendingSyncs *syncs)
77 {
78     GroupPendingSyncs *sync;
79 
80     while (syncs)
81     {
82 	sync = syncs;
83 	syncs = sync->next;
84 
85 	GROUP_WINDOW (sync->w);
86 	if (gw->needsPosSync)
87 	{
88 	    syncWindowPosition (sync->w);
89 	    gw->needsPosSync = FALSE;
90 	}
91 
92 	free (sync);
93     }
94 
95 }
96 
97 void
groupDequeueMoveNotifies(CompScreen * s)98 groupDequeueMoveNotifies (CompScreen *s)
99 {
100     GroupPendingMoves *move;
101     GroupPendingSyncs *syncs = NULL, *sync;
102 
103     GROUP_SCREEN (s);
104 
105     gs->queued = TRUE;
106 
107     while (gs->pendingMoves)
108     {
109 	move = gs->pendingMoves;
110 	gs->pendingMoves = move->next;
111 
112 	moveWindow (move->w, move->dx, move->dy, TRUE, move->immediate);
113 	if (move->sync)
114 	{
115 	    sync = malloc (sizeof (GroupPendingSyncs));
116 	    if (sync)
117 	    {
118 		GROUP_WINDOW (move->w);
119 
120 		gw->needsPosSync = TRUE;
121 		sync->w          = move->w;
122 		sync->next       = syncs;
123 		syncs            = sync;
124 	    }
125 	}
126 	free (move);
127     }
128 
129     if (syncs)
130 	groupDequeueSyncs (syncs);
131 
132     gs->queued = FALSE;
133 }
134 
135 void
groupEnqueueGrabNotify(CompWindow * w,int x,int y,unsigned int state,unsigned int mask)136 groupEnqueueGrabNotify (CompWindow   *w,
137 			int          x,
138 			int          y,
139 			unsigned int state,
140 			unsigned int mask)
141 {
142     GroupPendingGrabs *grab;
143 
144     GROUP_SCREEN (w->screen);
145 
146     grab = malloc (sizeof (GroupPendingGrabs));
147     if (!grab)
148 	return;
149 
150     grab->w = w;
151     grab->x = x;
152     grab->y = y;
153 
154     grab->state = state;
155     grab->mask  = mask;
156     grab->next  = NULL;
157 
158     if (gs->pendingGrabs)
159     {
160 	GroupPendingGrabs *temp;
161 	for (temp = gs->pendingGrabs; temp->next; temp = temp->next);
162 
163 	temp->next = grab;
164     }
165     else
166 	gs->pendingGrabs = grab;
167 
168     if (!gs->dequeueTimeoutHandle)
169     {
170 	gs->dequeueTimeoutHandle =
171 	    compAddTimeout (0, 0, groupDequeueTimer, (void *) w->screen);
172     }
173 }
174 
175 static void
groupDequeueGrabNotifies(CompScreen * s)176 groupDequeueGrabNotifies (CompScreen *s)
177 {
178     GroupPendingGrabs *grab;
179 
180     GROUP_SCREEN (s);
181 
182     gs->queued = TRUE;
183 
184     while (gs->pendingGrabs)
185     {
186 	grab = gs->pendingGrabs;
187 	gs->pendingGrabs = gs->pendingGrabs->next;
188 
189 	(*(grab->w)->screen->windowGrabNotify) (grab->w,
190 						grab->x, grab->y,
191 						grab->state, grab->mask);
192 
193 	free (grab);
194     }
195 
196     gs->queued = FALSE;
197 }
198 
199 void
groupEnqueueUngrabNotify(CompWindow * w)200 groupEnqueueUngrabNotify (CompWindow *w)
201 {
202     GroupPendingUngrabs *ungrab;
203 
204     GROUP_SCREEN (w->screen);
205 
206     ungrab = malloc (sizeof (GroupPendingUngrabs));
207 
208     if (!ungrab)
209 	return;
210 
211     ungrab->w    = w;
212     ungrab->next = NULL;
213 
214     if (gs->pendingUngrabs)
215     {
216 	GroupPendingUngrabs *temp;
217 	for (temp = gs->pendingUngrabs; temp->next; temp = temp->next);
218 
219 	temp->next = ungrab;
220     }
221     else
222 	gs->pendingUngrabs = ungrab;
223 
224     if (!gs->dequeueTimeoutHandle)
225     {
226 	gs->dequeueTimeoutHandle =
227 	    compAddTimeout (0, 0, groupDequeueTimer, (void *) w->screen);
228     }
229 }
230 
231 static void
groupDequeueUngrabNotifies(CompScreen * s)232 groupDequeueUngrabNotifies (CompScreen *s)
233 {
234     GroupPendingUngrabs *ungrab;
235 
236     GROUP_SCREEN (s);
237 
238     gs->queued = TRUE;
239 
240     while (gs->pendingUngrabs)
241     {
242 	ungrab = gs->pendingUngrabs;
243 	gs->pendingUngrabs = gs->pendingUngrabs->next;
244 
245 	(*(ungrab->w)->screen->windowUngrabNotify) (ungrab->w);
246 
247 	free (ungrab);
248     }
249 
250     gs->queued = FALSE;
251 }
252 
253 static Bool
groupDequeueTimer(void * closure)254 groupDequeueTimer (void *closure)
255 {
256     CompScreen *s = (CompScreen *) closure;
257 
258     GROUP_SCREEN (s);
259 
260     groupDequeueMoveNotifies (s);
261     groupDequeueGrabNotifies (s);
262     groupDequeueUngrabNotifies (s);
263 
264     gs->dequeueTimeoutHandle = 0;
265 
266     return FALSE;
267 }
268