1 /*
2 * Copyright 2010-2014 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * John Scipione, jscipione@gmail.com
7 * Clemens Zeidler, haiku@clemens-zeidler.de
8 */
9
10
11 #include "StackAndTile.h"
12
13 #include <Debug.h>
14
15 #include "StackAndTilePrivate.h"
16
17 #include "Desktop.h"
18 #include "SATWindow.h"
19 #include "Tiling.h"
20 #include "Window.h"
21
22
23 static const int32 kRightOptionKey = 0x67;
24 static const int32 kTabKey = 0x26;
25 static const int32 kPageUpKey = 0x21;
26 static const int32 kPageDownKey = 0x36;
27 static const int32 kLeftArrowKey = 0x61;
28 static const int32 kUpArrowKey = 0x57;
29 static const int32 kRightArrowKey = 0x63;
30 static const int32 kDownArrowKey = 0x62;
31
32 static const int32 kModifiers = B_SHIFT_KEY | B_COMMAND_KEY
33 | B_CONTROL_KEY | B_OPTION_KEY | B_MENU_KEY;
34
35
36 using namespace std;
37
38
39 // #pragma mark - StackAndTile
40
41
StackAndTile()42 StackAndTile::StackAndTile()
43 :
44 fDesktop(NULL),
45 fSATKeyPressed(false),
46 fCurrentSATWindow(NULL)
47 {
48
49 }
50
51
~StackAndTile()52 StackAndTile::~StackAndTile()
53 {
54
55 }
56
57
58 int32
Identifier()59 StackAndTile::Identifier()
60 {
61 return BPrivate::kMagicSATIdentifier;
62 }
63
64
65 void
ListenerRegistered(Desktop * desktop)66 StackAndTile::ListenerRegistered(Desktop* desktop)
67 {
68 fDesktop = desktop;
69
70 WindowList& windows = desktop->AllWindows();
71 for (Window *window = windows.FirstWindow(); window != NULL;
72 window = window->NextWindow(kAllWindowList))
73 WindowAdded(window);
74 }
75
76
77 void
ListenerUnregistered()78 StackAndTile::ListenerUnregistered()
79 {
80 for (SATWindowMap::iterator it = fSATWindowMap.begin();
81 it != fSATWindowMap.end(); it++) {
82 SATWindow* satWindow = it->second;
83 delete satWindow;
84 }
85 fSATWindowMap.clear();
86 }
87
88
89 bool
HandleMessage(Window * sender,BPrivate::LinkReceiver & link,BPrivate::LinkSender & reply)90 StackAndTile::HandleMessage(Window* sender, BPrivate::LinkReceiver& link,
91 BPrivate::LinkSender& reply)
92 {
93 if (sender == NULL)
94 return _HandleMessage(link, reply);
95
96 SATWindow* satWindow = GetSATWindow(sender);
97 if (!satWindow)
98 return false;
99
100 return satWindow->HandleMessage(satWindow, link, reply);
101 }
102
103
104 void
WindowAdded(Window * window)105 StackAndTile::WindowAdded(Window* window)
106 {
107 SATWindow* satWindow = new (std::nothrow)SATWindow(this, window);
108 if (!satWindow)
109 return;
110
111 ASSERT(fSATWindowMap.find(window) == fSATWindowMap.end());
112 fSATWindowMap[window] = satWindow;
113 }
114
115
116 void
WindowRemoved(Window * window)117 StackAndTile::WindowRemoved(Window* window)
118 {
119 STRACE_SAT("StackAndTile::WindowRemoved %s\n", window->Title());
120
121 SATWindowMap::iterator it = fSATWindowMap.find(window);
122 if (it == fSATWindowMap.end())
123 return;
124
125 SATWindow* satWindow = it->second;
126 // delete SATWindow
127 delete satWindow;
128 fSATWindowMap.erase(it);
129 }
130
131
132 bool
KeyPressed(uint32 what,int32 key,int32 modifiers)133 StackAndTile::KeyPressed(uint32 what, int32 key, int32 modifiers)
134 {
135 if (what == B_MODIFIERS_CHANGED
136 || (what == B_UNMAPPED_KEY_DOWN && key == kRightOptionKey)
137 || (what == B_UNMAPPED_KEY_UP && key == kRightOptionKey)) {
138 // switch to and from stacking and snapping mode
139 bool wasPressed = fSATKeyPressed;
140 fSATKeyPressed = (what == B_MODIFIERS_CHANGED
141 && (modifiers & kModifiers) == B_OPTION_KEY)
142 || (what == B_UNMAPPED_KEY_DOWN && key == kRightOptionKey);
143 if (wasPressed && !fSATKeyPressed)
144 _StopSAT();
145 if (!wasPressed && fSATKeyPressed)
146 _StartSAT();
147 }
148
149 if (!SATKeyPressed() || what != B_KEY_DOWN)
150 return false;
151
152 SATWindow* frontWindow = GetSATWindow(fDesktop->FocusWindow());
153 SATGroup* currentGroup = _GetSATGroup(frontWindow);
154
155 switch (key) {
156 case kLeftArrowKey:
157 case kRightArrowKey:
158 case kTabKey:
159 {
160 // go to previous or next window tab in current window group
161 if (currentGroup == NULL)
162 return false;
163
164 int32 groupSize = currentGroup->CountItems();
165 if (groupSize <= 1)
166 return false;
167
168 for (int32 i = 0; i < groupSize; i++) {
169 SATWindow* targetWindow = currentGroup->WindowAt(i);
170 if (targetWindow == frontWindow) {
171 if (key == kLeftArrowKey
172 || (key == kTabKey && (modifiers & B_SHIFT_KEY) != 0)) {
173 // Go to previous window tab (wrap around)
174 int32 previousIndex = i > 0 ? i - 1 : groupSize - 1;
175 targetWindow = currentGroup->WindowAt(previousIndex);
176 } else {
177 // Go to next window tab (wrap around)
178 int32 nextIndex = i < groupSize - 1 ? i + 1 : 0;
179 targetWindow = currentGroup->WindowAt(nextIndex);
180 }
181
182 _ActivateWindow(targetWindow);
183 return true;
184 }
185 }
186 break;
187 }
188
189 case kUpArrowKey:
190 case kPageUpKey:
191 {
192 // go to previous window group
193 GroupIterator groups(this, fDesktop);
194 groups.SetCurrentGroup(currentGroup);
195 SATGroup* backmostGroup = NULL;
196
197 while (true) {
198 SATGroup* group = groups.NextGroup();
199 if (group == NULL || group == currentGroup)
200 break;
201 else if (group->CountItems() < 1)
202 continue;
203
204 if (currentGroup == NULL) {
205 SATWindow* activeWindow = group->ActiveWindow();
206 if (activeWindow != NULL)
207 _ActivateWindow(activeWindow);
208 else
209 _ActivateWindow(group->WindowAt(0));
210
211 return true;
212 }
213 backmostGroup = group;
214 }
215 if (backmostGroup != NULL && backmostGroup != currentGroup) {
216 SATWindow* activeWindow = backmostGroup->ActiveWindow();
217 if (activeWindow != NULL)
218 _ActivateWindow(activeWindow);
219 else
220 _ActivateWindow(backmostGroup->WindowAt(0));
221
222 return true;
223 }
224
225 break;
226 }
227
228 case kDownArrowKey:
229 case kPageDownKey:
230 {
231 // go to next window group
232 GroupIterator groups(this, fDesktop);
233 groups.SetCurrentGroup(currentGroup);
234
235 while (true) {
236 SATGroup* group = groups.NextGroup();
237 if (group == NULL || group == currentGroup)
238 break;
239 else if (group->CountItems() < 1)
240 continue;
241
242 SATWindow* activeWindow = group->ActiveWindow();
243 if (activeWindow != NULL)
244 _ActivateWindow(activeWindow);
245 else
246 _ActivateWindow(group->WindowAt(0));
247
248 if (currentGroup != NULL && frontWindow != NULL) {
249 Window* window = frontWindow->GetWindow();
250 fDesktop->SendWindowBehind(window);
251 WindowSentBehind(window, NULL);
252 }
253 return true;
254 }
255 break;
256 }
257 }
258
259 return false;
260 }
261
262
263 void
MouseDown(Window * window,BMessage * message,const BPoint & where)264 StackAndTile::MouseDown(Window* window, BMessage* message, const BPoint& where)
265 {
266 SATWindow* satWindow = GetSATWindow(window);
267 if (!satWindow || !satWindow->GetDecorator())
268 return;
269
270 // fCurrentSATWindow is not zero if e.g. the secondary and the primary
271 // mouse button are pressed at the same time
272 if ((message->FindInt32("buttons") & B_PRIMARY_MOUSE_BUTTON) == 0 ||
273 fCurrentSATWindow != NULL)
274 return;
275
276 // we are only interested in single clicks
277 if (message->FindInt32("clicks") == 2)
278 return;
279
280 int32 tab;
281 switch (satWindow->GetDecorator()->RegionAt(where, tab)) {
282 case Decorator::REGION_TAB:
283 case Decorator::REGION_LEFT_BORDER:
284 case Decorator::REGION_RIGHT_BORDER:
285 case Decorator::REGION_TOP_BORDER:
286 case Decorator::REGION_BOTTOM_BORDER:
287 case Decorator::REGION_LEFT_TOP_CORNER:
288 case Decorator::REGION_LEFT_BOTTOM_CORNER:
289 case Decorator::REGION_RIGHT_TOP_CORNER:
290 case Decorator::REGION_RIGHT_BOTTOM_CORNER:
291 break;
292
293 default:
294 return;
295 }
296
297 ASSERT(fCurrentSATWindow == NULL);
298 fCurrentSATWindow = satWindow;
299
300 if (!SATKeyPressed())
301 return;
302
303 _StartSAT();
304 }
305
306
307 void
MouseUp(Window * window,BMessage * message,const BPoint & where)308 StackAndTile::MouseUp(Window* window, BMessage* message, const BPoint& where)
309 {
310 if (fSATKeyPressed)
311 _StopSAT();
312
313 fCurrentSATWindow = NULL;
314 }
315
316
317 void
WindowMoved(Window * window)318 StackAndTile::WindowMoved(Window* window)
319 {
320 SATWindow* satWindow = GetSATWindow(window);
321 if (satWindow == NULL)
322 return;
323
324 if (SATKeyPressed() && fCurrentSATWindow)
325 satWindow->FindSnappingCandidates();
326 else
327 satWindow->DoGroupLayout();
328 }
329
330
331 void
WindowResized(Window * window)332 StackAndTile::WindowResized(Window* window)
333 {
334 SATWindow* satWindow = GetSATWindow(window);
335 if (satWindow == NULL)
336 return;
337 satWindow->Resized();
338
339 if (SATKeyPressed() && fCurrentSATWindow)
340 satWindow->FindSnappingCandidates();
341 else
342 satWindow->DoGroupLayout();
343 }
344
345
346 void
WindowActivated(Window * window)347 StackAndTile::WindowActivated(Window* window)
348 {
349 SATWindow* satWindow = GetSATWindow(window);
350 if (satWindow == NULL)
351 return;
352
353 _ActivateWindow(satWindow);
354 }
355
356
357 void
WindowSentBehind(Window * window,Window * behindOf)358 StackAndTile::WindowSentBehind(Window* window, Window* behindOf)
359 {
360 SATWindow* satWindow = GetSATWindow(window);
361 if (satWindow == NULL)
362 return;
363
364 SATGroup* group = satWindow->GetGroup();
365 if (group == NULL)
366 return;
367
368 Desktop* desktop = satWindow->GetWindow()->Desktop();
369 if (desktop == NULL)
370 return;
371
372 const WindowAreaList& areaList = group->GetAreaList();
373 for (int32 i = 0; i < areaList.CountItems(); i++) {
374 WindowArea* area = areaList.ItemAt(i);
375 SATWindow* topWindow = area->TopWindow();
376 if (topWindow == NULL || topWindow == satWindow)
377 continue;
378 desktop->SendWindowBehind(topWindow->GetWindow(), behindOf);
379 }
380 }
381
382
383 void
WindowWorkspacesChanged(Window * window,uint32 workspaces)384 StackAndTile::WindowWorkspacesChanged(Window* window, uint32 workspaces)
385 {
386 SATWindow* satWindow = GetSATWindow(window);
387 if (satWindow == NULL)
388 return;
389
390 SATGroup* group = satWindow->GetGroup();
391 if (group == NULL)
392 return;
393
394 Desktop* desktop = satWindow->GetWindow()->Desktop();
395 if (desktop == NULL)
396 return;
397
398 const WindowAreaList& areaList = group->GetAreaList();
399 for (int32 i = 0; i < areaList.CountItems(); i++) {
400 WindowArea* area = areaList.ItemAt(i);
401 if (area->WindowList().HasItem(satWindow))
402 continue;
403 SATWindow* topWindow = area->TopWindow();
404 desktop->SetWindowWorkspaces(topWindow->GetWindow(), workspaces);
405 }
406 }
407
408
409 void
WindowHidden(Window * window,bool fromMinimize)410 StackAndTile::WindowHidden(Window* window, bool fromMinimize)
411 {
412 SATWindow* satWindow = GetSATWindow(window);
413 if (satWindow == NULL)
414 return;
415
416 SATGroup* group = satWindow->GetGroup();
417 if (group == NULL)
418 return;
419
420 if (fromMinimize == false && group->CountItems() > 1)
421 group->RemoveWindow(satWindow, false);
422 }
423
424
425 void
WindowMinimized(Window * window,bool minimize)426 StackAndTile::WindowMinimized(Window* window, bool minimize)
427 {
428 SATWindow* satWindow = GetSATWindow(window);
429 if (satWindow == NULL)
430 return;
431
432 SATGroup* group = satWindow->GetGroup();
433 if (group == NULL)
434 return;
435
436 Desktop* desktop = satWindow->GetWindow()->Desktop();
437 if (desktop == NULL)
438 return;
439
440 for (int i = 0; i < group->CountItems(); i++) {
441 SATWindow* listWindow = group->WindowAt(i);
442 if (listWindow != satWindow)
443 listWindow->GetWindow()->ServerWindow()->NotifyMinimize(minimize);
444 }
445 }
446
447
448 void
WindowTabLocationChanged(Window * window,float location,bool isShifting)449 StackAndTile::WindowTabLocationChanged(Window* window, float location,
450 bool isShifting)
451 {
452
453 }
454
455
456 void
SizeLimitsChanged(Window * window,int32 minWidth,int32 maxWidth,int32 minHeight,int32 maxHeight)457 StackAndTile::SizeLimitsChanged(Window* window, int32 minWidth, int32 maxWidth,
458 int32 minHeight, int32 maxHeight)
459 {
460 SATWindow* satWindow = GetSATWindow(window);
461 if (!satWindow)
462 return;
463 satWindow->SetOriginalSizeLimits(minWidth, maxWidth, minHeight, maxHeight);
464
465 // trigger a relayout
466 WindowMoved(window);
467 }
468
469
470 void
WindowLookChanged(Window * window,window_look look)471 StackAndTile::WindowLookChanged(Window* window, window_look look)
472 {
473 SATWindow* satWindow = GetSATWindow(window);
474 if (!satWindow)
475 return;
476 satWindow->WindowLookChanged(look);
477 }
478
479
480 void
WindowFeelChanged(Window * window,window_feel feel)481 StackAndTile::WindowFeelChanged(Window* window, window_feel feel)
482 {
483 // check if it is still a compatible feel
484 if (feel == B_NORMAL_WINDOW_FEEL)
485 return;
486 SATWindow* satWindow = GetSATWindow(window);
487 if (satWindow == NULL)
488 return;
489
490 SATGroup* group = satWindow->GetGroup();
491 if (group == NULL)
492 return;
493
494 if (group->CountItems() > 1)
495 group->RemoveWindow(satWindow, false);
496 }
497
498
499 bool
SetDecoratorSettings(Window * window,const BMessage & settings)500 StackAndTile::SetDecoratorSettings(Window* window, const BMessage& settings)
501 {
502 SATWindow* satWindow = GetSATWindow(window);
503 if (!satWindow)
504 return false;
505
506 return satWindow->SetSettings(settings);
507 }
508
509
510 void
GetDecoratorSettings(Window * window,BMessage & settings)511 StackAndTile::GetDecoratorSettings(Window* window, BMessage& settings)
512 {
513 SATWindow* satWindow = GetSATWindow(window);
514 if (!satWindow)
515 return;
516
517 satWindow->GetSettings(settings);
518 }
519
520
521 SATWindow*
GetSATWindow(Window * window)522 StackAndTile::GetSATWindow(Window* window)
523 {
524 if (window == NULL)
525 return NULL;
526
527 SATWindowMap::const_iterator it = fSATWindowMap.find(
528 window);
529 if (it != fSATWindowMap.end())
530 return it->second;
531
532 // TODO fix race condition with WindowAdded this method is called before
533 // WindowAdded and a SATWindow is created twice!
534 return NULL;
535
536 // If we don't know this window, memory allocation might has been failed
537 // previously. Try to add the window now.
538 SATWindow* satWindow = new (std::nothrow)SATWindow(this, window);
539 if (satWindow)
540 fSATWindowMap[window] = satWindow;
541
542 return satWindow;
543 }
544
545
546 SATWindow*
FindSATWindow(uint64 id)547 StackAndTile::FindSATWindow(uint64 id)
548 {
549 for (SATWindowMap::const_iterator it = fSATWindowMap.begin();
550 it != fSATWindowMap.end(); it++) {
551 SATWindow* window = it->second;
552 if (window->Id() == id)
553 return window;
554 }
555
556 return NULL;
557 }
558
559
560 // #pragma mark - StackAndTile private methods
561
562
563 void
_StartSAT()564 StackAndTile::_StartSAT()
565 {
566 STRACE_SAT("StackAndTile::_StartSAT()\n");
567 if (!fCurrentSATWindow)
568 return;
569
570 // Remove window from the group.
571 SATGroup* group = fCurrentSATWindow->GetGroup();
572 if (group == NULL)
573 return;
574
575 group->RemoveWindow(fCurrentSATWindow, false);
576 // Bring window to the front. (in focus follow mouse this is not
577 // automatically the case)
578 _ActivateWindow(fCurrentSATWindow);
579
580 fCurrentSATWindow->FindSnappingCandidates();
581 }
582
583
584 void
_StopSAT()585 StackAndTile::_StopSAT()
586 {
587 STRACE_SAT("StackAndTile::_StopSAT()\n");
588 if (!fCurrentSATWindow)
589 return;
590 if (fCurrentSATWindow->JoinCandidates())
591 _ActivateWindow(fCurrentSATWindow);
592 }
593
594
595 void
_ActivateWindow(SATWindow * satWindow)596 StackAndTile::_ActivateWindow(SATWindow* satWindow)
597 {
598 if (satWindow == NULL)
599 return;
600
601 SATGroup* group = satWindow->GetGroup();
602 if (group == NULL)
603 return;
604
605 Desktop* desktop = satWindow->GetWindow()->Desktop();
606 if (desktop == NULL)
607 return;
608
609 WindowArea* area = satWindow->GetWindowArea();
610 if (area == NULL)
611 return;
612
613 area->MoveToTopLayer(satWindow);
614
615 // save the active window of the current group
616 SATWindow* frontWindow = GetSATWindow(fDesktop->FocusWindow());
617 SATGroup* currentGroup = _GetSATGroup(frontWindow);
618 if (currentGroup != NULL && currentGroup != group && frontWindow != NULL)
619 currentGroup->SetActiveWindow(frontWindow);
620 else
621 group->SetActiveWindow(satWindow);
622
623 const WindowAreaList& areas = group->GetAreaList();
624 int32 areasCount = areas.CountItems();
625 for (int32 i = 0; i < areasCount; i++) {
626 WindowArea* currentArea = areas.ItemAt(i);
627 if (currentArea == area)
628 continue;
629
630 desktop->ActivateWindow(currentArea->TopWindow()->GetWindow());
631 }
632
633 desktop->ActivateWindow(satWindow->GetWindow());
634 }
635
636
637 bool
_HandleMessage(BPrivate::LinkReceiver & link,BPrivate::LinkSender & reply)638 StackAndTile::_HandleMessage(BPrivate::LinkReceiver& link,
639 BPrivate::LinkSender& reply)
640 {
641 int32 what;
642 link.Read<int32>(&what);
643
644 switch (what) {
645 case BPrivate::kSaveAllGroups:
646 {
647 BMessage allGroupsArchive;
648 GroupIterator groups(this, fDesktop);
649 while (true) {
650 SATGroup* group = groups.NextGroup();
651 if (group == NULL)
652 break;
653 if (group->CountItems() <= 1)
654 continue;
655 BMessage groupArchive;
656 if (group->ArchiveGroup(groupArchive) != B_OK)
657 continue;
658 allGroupsArchive.AddMessage("group", &groupArchive);
659 }
660 int32 size = allGroupsArchive.FlattenedSize();
661 char buffer[size];
662 if (allGroupsArchive.Flatten(buffer, size) == B_OK) {
663 reply.StartMessage(B_OK);
664 reply.Attach<int32>(size);
665 reply.Attach(buffer, size);
666 } else
667 reply.StartMessage(B_ERROR);
668 reply.Flush();
669 break;
670 }
671
672 case BPrivate::kRestoreGroup:
673 {
674 int32 size;
675 if (link.Read<int32>(&size) == B_OK) {
676 char buffer[size];
677 BMessage group;
678 if (link.Read(buffer, size) == B_OK
679 && group.Unflatten(buffer) == B_OK) {
680 status_t status = SATGroup::RestoreGroup(group, this);
681 reply.StartMessage(status);
682 reply.Flush();
683 }
684 }
685 break;
686 }
687
688 default:
689 return false;
690 }
691
692 return true;
693 }
694
695
696 SATGroup*
_GetSATGroup(SATWindow * window)697 StackAndTile::_GetSATGroup(SATWindow* window)
698 {
699 if (window == NULL)
700 return NULL;
701
702 SATGroup* group = window->GetGroup();
703 if (group == NULL)
704 return NULL;
705
706 if (group->CountItems() < 1)
707 return NULL;
708
709 return group;
710 }
711
712
713 // #pragma mark - GroupIterator
714
715
GroupIterator(StackAndTile * sat,Desktop * desktop)716 GroupIterator::GroupIterator(StackAndTile* sat, Desktop* desktop)
717 :
718 fStackAndTile(sat),
719 fDesktop(desktop),
720 fCurrentGroup(NULL)
721 {
722 RewindToFront();
723 }
724
725
726 void
RewindToFront()727 GroupIterator::RewindToFront()
728 {
729 fCurrentWindow = fDesktop->CurrentWindows().LastWindow();
730 }
731
732
733 SATGroup*
NextGroup()734 GroupIterator::NextGroup()
735 {
736 SATGroup* group = NULL;
737 do {
738 Window* window = fCurrentWindow;
739 if (window == NULL) {
740 group = NULL;
741 break;
742 }
743 fCurrentWindow = fCurrentWindow->PreviousWindow(
744 fCurrentWindow->CurrentWorkspace());
745 if (window->IsHidden()
746 || strcmp(window->Title(), "Deskbar") == 0
747 || strcmp(window->Title(), "Desktop") == 0) {
748 continue;
749 }
750
751 SATWindow* satWindow = fStackAndTile->GetSATWindow(window);
752 group = satWindow->GetGroup();
753 } while (group == NULL || fCurrentGroup == group);
754
755 fCurrentGroup = group;
756 return fCurrentGroup;
757 }
758
759
760 // #pragma mark - WindowIterator
761
762
WindowIterator(SATGroup * group,bool reverseLayerOrder)763 WindowIterator::WindowIterator(SATGroup* group, bool reverseLayerOrder)
764 :
765 fGroup(group),
766 fReverseLayerOrder(reverseLayerOrder)
767 {
768 if (fReverseLayerOrder)
769 _ReverseRewind();
770 else
771 Rewind();
772 }
773
774
775 void
Rewind()776 WindowIterator::Rewind()
777 {
778 fAreaIndex = 0;
779 fWindowIndex = 0;
780 fCurrentArea = fGroup->GetAreaList().ItemAt(fAreaIndex);
781 }
782
783
784 SATWindow*
NextWindow()785 WindowIterator::NextWindow()
786 {
787 if (fReverseLayerOrder)
788 return _ReverseNextWindow();
789
790 if (fWindowIndex == fCurrentArea->LayerOrder().CountItems()) {
791 fAreaIndex++;
792 fWindowIndex = 0;
793 fCurrentArea = fGroup->GetAreaList().ItemAt(fAreaIndex);
794 if (!fCurrentArea)
795 return NULL;
796 }
797 SATWindow* window = fCurrentArea->LayerOrder().ItemAt(fWindowIndex);
798 fWindowIndex++;
799 return window;
800 }
801
802
803 // #pragma mark - WindowIterator private methods
804
805
806 SATWindow*
_ReverseNextWindow()807 WindowIterator::_ReverseNextWindow()
808 {
809 if (fWindowIndex < 0) {
810 fAreaIndex++;
811 fCurrentArea = fGroup->GetAreaList().ItemAt(fAreaIndex);
812 if (!fCurrentArea)
813 return NULL;
814 fWindowIndex = fCurrentArea->LayerOrder().CountItems() - 1;
815 }
816 SATWindow* window = fCurrentArea->LayerOrder().ItemAt(fWindowIndex);
817 fWindowIndex--;
818 return window;
819 }
820
821
822 void
_ReverseRewind()823 WindowIterator::_ReverseRewind()
824 {
825 Rewind();
826 if (fCurrentArea)
827 fWindowIndex = fCurrentArea->LayerOrder().CountItems() - 1;
828 }
829