2 Copyright 2004-2005 Chris Tallon
4 This file is part of VOMP.
6 VOMP 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 VOMP 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 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 pthread_mutex_lock(&boxLock);
27 WaitForSingleObject(boxLock, INFINITE);
32 pthread_mutex_unlock(&boxLock);
34 ReleaseMutex(boxLock);
51 BoxStack* BoxStack::instance = NULL;
66 BoxStack* BoxStack::getInstance()
73 if (initted) return 0;
77 pthread_mutex_init(&boxLock, NULL);
79 boxLock = CreateMutex(NULL,FALSE,NULL);
85 int BoxStack::shutdown()
87 if (!initted) return 0;
89 // FIXME don't think this can work properly, removeAll leaves the wallpaper there!
96 int BoxStack::add(Boxx* v)
98 if (!initted) return 0;
101 pthread_mutex_lock(&boxLock);
103 WaitForSingleObject(boxLock, INFINITE);
106 if (numBoxes == 16) return 0;
107 boxes[numBoxes++] = v;
110 pthread_mutex_unlock(&boxLock);
112 ReleaseMutex(boxLock);
118 // ---------------------------------------------------- REMOVE CODE
120 int BoxStack::remove(Boxx* toDelete)
122 if (!initted) return 0;
125 pthread_mutex_lock(&boxLock);
127 WaitForSingleObject(boxLock, INFINITE);
130 if (numBoxes == 0) return 0;
132 // Log::getInstance()->log("BoxStack", Log::DEBUG, "entering remove, numBoxes=%i", numBoxes);
136 if (toDelete == NULL)
138 toDelete = boxes[numBoxes-1];
143 // to be deleted box is more likely to be at the top
144 for (i = numBoxes-1; i >= 0; i--)
146 // Log::getInstance()->log("BoxStack", Log::DEBUG, "todel: %p, i=%i, boxes[i]=%p", toDelete, i, boxes[i]);
147 if (boxes[i] == toDelete) break;
152 // not a Box we have!
157 // Log::getInstance()->log("BoxStack", Log::DEBUG, "Starting deleteBox");
159 // Log::getInstance()->log("BoxStack", Log::DEBUG, "Done deleteBox");
161 // Shift the boxes on top down one
163 for(int j = i; j < numBoxes; j++) boxes[j] = boxes[j+1];
168 // If there is only the wallpaper left signal command
171 Message* m = new Message();
172 m->to = Command::getInstance();
173 m->message = Message::LAST_VIEW_CLOSE;
174 Command::getInstance()->postMessageNoLock(m);
178 pthread_mutex_unlock(&boxLock);
180 ReleaseMutex(boxLock);
186 /////////////////////////////////////////////////////////////////////////////
188 /////////////////////////////////////////////////////////////////////////////
190 void BoxStack::deleteBox(int z)
192 // Log::getInstance()->log("BoxStack", Log::DEBUG, "Delete box %i of %i", z, numBoxes);
194 boxSplit(boxes[z]->area, z + 1, numBoxes, 1, rl);
197 repaintRevealed(z, rl.front());
202 void BoxStack::update(Boxx* toUpdate, Region* regionToUpdate)
204 // Log::getInstance()->log("BoxStack", Log::DEBUG, "Update called");
205 // Get the z index of the box
208 pthread_mutex_lock(&boxLock);
210 WaitForSingleObject(boxLock, INFINITE);
212 Log::getInstance()->log("BoxStack", Log::DEBUG, "Locked for update");
215 for (z = 0; z < numBoxes; z++)
217 if (boxes[z] == toUpdate) break;
222 // not a Box we have!
226 // get the region for the whole box, could be less than that
227 // for smaller updates
229 Region r = toUpdate->area;
233 // Can be null if the whole box should be updated
234 // If this is given the numbers are relative to the size of the box, not the screen
236 r.x += regionToUpdate->x;
237 r.y += regionToUpdate->y;
238 r.w = regionToUpdate->w;
239 r.h = regionToUpdate->h;
245 boxSplit(r, z+1, numBoxes, 1, rl);
254 Log::getInstance()->log("BoxStack", Log::DEBUG, "Unlocking");
256 pthread_mutex_unlock(&boxLock);
258 ReleaseMutex(boxLock);
262 void BoxStack::repaintRevealed(int x, Region r)
265 boxSplit(r, x - 1, -1, -1, rl);
271 boxes[r2.z]->blt(r2);
276 void BoxStack::boxSplit(Region r, int start, int end, int direction, RegionList& rl)
278 // printf("Y= S=%i E=%i D=%i: Boxsplit: %i %i %i %i\n", start, end, direction, r.x, r.y, r.w, r.h);
280 for(int z = start; z != end; z += direction)
282 if (r.overlappedBy(boxes[z]->area))
284 // printf("Z=%i S=%i E=%i D=%i: %i overlaps\n", z, start, end, direction, z);
289 if (boxes[z]->area.y > r.y)
291 // printf("Z=%i S=%i E=%i D=%i: Case 1 for %i %i %i %i split by %i: %i %i %i %i\n", z, start, end, direction, r.x, r.y, r.w, r.h, z, boxes[z]->area.x, boxes[z]->area.y, boxes[z]->area.w, boxes[z]->area.h);
292 top = boxes[z]->area.y;
297 newR.h = boxes[z]->area.y - r.y;
298 boxSplit(newR, z + direction, end, direction, rl);
304 newR2.y = boxes[z]->area.y;
306 newR2.h = r.h - newR.h;
307 boxSplit(newR2, z, end, -1, rl);
312 if (boxes[z]->area.y2() < r.y2())
314 // printf("Z=%i S=%i E=%i D=%i: Case 2 for %i %i %i %i split by %i: %i %i %i %i\n", z, start, end, direction, r.x, r.y, r.w, r.h, z, boxes[z]->area.x, boxes[z]->area.y, boxes[z]->area.w, boxes[z]->area.h);
315 btm = boxes[z]->area.y2();
318 newR.y = boxes[z]->area.y2() + 1;
320 newR.h = r.y2() - newR.y + 1;
321 boxSplit(newR, z + direction, end, direction, rl);
329 newR2.h = r.h - newR.h;
330 boxSplit(newR2, z, end, -1, rl);
335 if (boxes[z]->area.x > r.x)
337 // printf("Z=%i S=%i E=%i D=%i: Case 3 for %i %i %i %i split by %i: %i %i %i %i\n", z, start, end, direction, r.x, r.y, r.w, r.h, z, boxes[z]->area.x, boxes[z]->area.y, boxes[z]->area.w, boxes[z]->area.h);
341 newR.w = boxes[z]->area.x - r.x;
342 newR.h = btm - top + 1;
343 boxSplit(newR, z + direction, end, direction, rl);
348 newR2.x = r.x + newR.w;
350 newR2.w = r.w - newR.w;
352 boxSplit(newR2, z, end, -1, rl);
357 if (boxes[z]->area.x2() < r.x2())
359 // printf("Z=%i S=%i E=%i D=%i: Case 4 for %i %i %i %i split by %i: %i %i %i %i\n", z, start, end, direction, r.x, r.y, r.w, r.h, z, boxes[z]->area.x, boxes[z]->area.y, boxes[z]->area.w, boxes[z]->area.h);
361 newR.x = boxes[z]->area.x2() + 1;
363 newR.w = r.x2() - newR.x + 1;
364 newR.h = btm - top + 1;
365 boxSplit(newR, z + direction, end, direction, rl);
372 newR2.w = r.w - newR.w;
374 boxSplit(newR2, z, end, -1, rl);
381 // we are going down the stack
382 // r is underlapped by boxes[z]
383 // but we have not split
384 // Therefore this region under test is
385 // completely covering boxes[z]
387 // don't go any further down, generate a region and quit
389 // printf("Repaint region: %i %i %i %i\n", r.x, r.y, r.w, r.h);
394 // printf("Returning from Z=%i\n", z);
399 // printf("Z=%i S=%i E=%i D=%i: %i does not overlap\n", z, start, end, direction, z);
403 // if direction = 1 then we have come to a region that is
404 // entirely clear of higher boxes and needs to be redrawn
406 // if direction = -1 then we have come to a region that is on
407 // the very bottom with nothing below it to repaint.
408 // do nothing. stale window data will be left on screen?
416 /////////////////////////////////////////////////////////////////////////////
418 /////////////////////////////////////////////////////////////////////////////
420 // ---------------------------------------------------- END OF REMOVE CODE
423 void BoxStack::removeAll()
425 // 1.. Don't delete wallpaper. No point.
427 // Need locking on this one??
430 pthread_mutex_lock(&boxLock);
432 WaitForSingleObject(boxLock, INFINITE);
436 for (; numBoxes > 1; --numBoxes)
438 delete boxes[numBoxes-1];
442 pthread_mutex_unlock(&boxLock);
444 ReleaseMutex(boxLock);
449 int BoxStack::handleCommand(int command)
455 if (command != Remote::NA_NONE)
457 // handle command return values
458 // 0 - drop through to next box
459 // 1 - dont drop to next box, but not handled
460 // 2 - handled - stop command here
461 // 4 - handled - delete this box
463 for (i=numBoxes-1; i>=0; i--)
465 // Log::getInstance()->log("BoxStack", Log::DEBUG, "Giving command to i=%i", i);
466 retVal = boxes[i]->handleCommand(command);
469 // not handled but don't give to any more boxes
479 else if (retVal == 4)
481 // Log::getInstance()->log("BoxStack", Log::DEBUG, "Return 4: i=%i, boxes[i]=%p", i, boxes[i]);
490 // fake the return code
497 void BoxStack::processMessage(Message* m)
501 for (int i = numBoxes-1; i >= 0; i--)
503 if (boxes[i] == m->to)
505 Log::getInstance()->log("BoxStack", Log::DEBUG, "sending message from box %p to box %p %lu", m->from, m->to, m->message);
506 boxes[i]->processMessage(m);
513 /* Handle mouse events*/
514 // They come in with m->to = NULL? and just need to be delivered to top box?
515 if ((numBoxes > 1) && ((m->message == Message::MOUSE_MOVE) || (m->message == Message::MOUSE_LBDOWN)))
517 boxes[numBoxes-1]->processMessage(m);
521 Log::getInstance()->log("BoxStack", Log::DEBUG, "it's for meeee!");
525 case Message::CLOSE_ME:
527 remove((Boxx*)m->from);
530 case Message::ADD_VIEW: // currently not used by anything but it might come in useful again
532 Boxx* toAdd = (Boxx*)m->parameter;
538 case Message::REDRAW:
540 Log::getInstance()->log("BoxStack", Log::DEBUG, "==================================================================");
541 Log::getInstance()->log("BoxStack", Log::DEBUG, "DEPRECATED BOXSTACK REDRAW MESSAGE CALL --------------------------");
542 Log::getInstance()->log("BoxStack", Log::DEBUG, "==================================================================");
544 Boxx* toRedraw = (Boxx*)m->from;
545 Region* toRedrawRegion = (Region*)m->parameter;
546 update(toRedraw, toRedrawRegion);