115
115
groupClearWindowInputShape (CompWindow *w,
116
GroupWindowHideInfo *hideInfo)
116
GroupWindowHideInfo *hideInfo)
121
rects = XShapeGetRectangles (w->screen->display->display,
122
w->id, ShapeInput, &count, &ordering);
130
/* check if the returned shape exactly matches the window shape -
131
if that is true, the window currently has no set input shape */
133
(rects[0].x == -w->serverBorderWidth) &&
134
(rects[0].y == -w->serverBorderWidth) &&
135
(rects[0].width == (w->serverWidth + w->serverBorderWidth)) &&
136
(rects[0].height == (w->serverHeight + w->serverBorderWidth)))
141
if (hideInfo->inputRects)
142
XFree (hideInfo->inputRects);
144
hideInfo->inputRects = rects;
145
hideInfo->nInputRects = count;
146
hideInfo->inputRectOrdering = ordering;
148
XShapeSelectInput (w->screen->display->display, w->id, NoEventMask);
150
XShapeCombineRectangles (w->screen->display->display, w->id,
151
ShapeInput, 0, 0, NULL, 0, ShapeSet, 0);
153
XShapeSelectInput (w->screen->display->display, w->id, ShapeNotify);
119
int count = 0, ordering;
120
CompDisplay *d = w->screen->display;
122
rects = XShapeGetRectangles (d->display, w->id, ShapeInput,
128
/* check if the returned shape exactly matches the window shape -
129
if that is true, the window currently has no set input shape */
131
(rects[0].x == -w->serverBorderWidth) &&
132
(rects[0].y == -w->serverBorderWidth) &&
133
(rects[0].width == (w->serverWidth + w->serverBorderWidth)) &&
134
(rects[0].height == (w->serverHeight + w->serverBorderWidth)))
139
if (hideInfo->inputRects)
140
XFree (hideInfo->inputRects);
142
hideInfo->inputRects = rects;
143
hideInfo->nInputRects = count;
144
hideInfo->inputRectOrdering = ordering;
146
XShapeSelectInput (d->display, w->id, NoEventMask);
148
XShapeCombineRectangles (d->display, w->id, ShapeInput, 0, 0,
149
NULL, 0, ShapeSet, 0);
151
XShapeSelectInput (d->display, w->id, ShapeNotify);
161
159
groupSetWindowVisibility (CompWindow *w,
166
if (!visible && !gw->windowHideInfo)
168
GroupWindowHideInfo *info;
170
gw->windowHideInfo = info = malloc (sizeof (GroupWindowHideInfo));
171
if (!gw->windowHideInfo)
174
info->inputRects = NULL;
175
info->nInputRects = 0;
176
info->shapeMask = XShapeInputSelected (w->screen->display->display,
178
groupClearWindowInputShape (w, info);
182
info->frameWindow = w->frame;
183
XUnmapWindow (w->screen->display->display, w->frame);
185
info->frameWindow = None;
187
info->skipState = w->state & (CompWindowStateSkipPagerMask |
188
CompWindowStateSkipTaskbarMask);
190
changeWindowState (w,
191
w->state | CompWindowStateSkipPagerMask |
192
CompWindowStateSkipTaskbarMask);
194
else if (visible && gw->windowHideInfo)
196
GroupWindowHideInfo *info = gw->windowHideInfo;
198
if (info->nInputRects)
200
XShapeCombineRectangles (w->screen->display->display,
201
w->id, ShapeInput, 0, 0,
205
info->inputRectOrdering);
209
XShapeCombineMask (w->screen->display->display, w->id,
210
ShapeInput, 0, 0, None, ShapeSet);
213
if (info->inputRects)
214
XFree (info->inputRects);
216
XShapeSelectInput (w->screen->display->display, w->id,
219
if (info->frameWindow)
221
if (w->attrib.map_state != IsUnmapped)
222
XMapWindow (w->screen->display->display, w->frame);
225
changeWindowState (w,
226
(w->state & ~(CompWindowStateSkipPagerMask |
227
CompWindowStateSkipTaskbarMask)) |
231
gw->windowHideInfo = NULL;
162
CompDisplay *d = w->screen->display;
166
if (!visible && !gw->windowHideInfo)
168
GroupWindowHideInfo *info;
170
gw->windowHideInfo = info = malloc (sizeof (GroupWindowHideInfo));
171
if (!gw->windowHideInfo)
174
info->inputRects = NULL;
175
info->nInputRects = 0;
176
info->shapeMask = XShapeInputSelected (d->display, w->id);
177
groupClearWindowInputShape (w, info);
181
info->frameWindow = w->frame;
182
XUnmapWindow (d->display, w->frame);
184
info->frameWindow = None;
186
info->skipState = w->state & (CompWindowStateSkipPagerMask |
187
CompWindowStateSkipTaskbarMask);
189
changeWindowState (w, w->state |
190
CompWindowStateSkipPagerMask |
191
CompWindowStateSkipTaskbarMask);
193
else if (visible && gw->windowHideInfo)
195
GroupWindowHideInfo *info = gw->windowHideInfo;
197
if (info->nInputRects)
199
XShapeCombineRectangles (d->display, w->id, ShapeInput, 0, 0,
200
info->inputRects, info->nInputRects,
201
ShapeSet, info->inputRectOrdering);
205
XShapeCombineMask (d->display, w->id, ShapeInput,
206
0, 0, None, ShapeSet);
209
if (info->inputRects)
210
XFree (info->inputRects);
212
XShapeSelectInput (d->display, w->id, info->shapeMask);
214
if (info->frameWindow)
216
if (w->attrib.map_state != IsUnmapped)
217
XMapWindow (d->display, w->frame);
220
changeWindowState (w,
221
(w->state & ~(CompWindowStateSkipPagerMask |
222
CompWindowStateSkipTaskbarMask)) |
226
gw->windowHideInfo = NULL;
331
297
* This mask affects how the visible parameter is handled, for example if
332
298
* visibule is set to TRUE and the mask to PERMANENT state it will set
333
299
* PaintPermanentOn state for the tab bar. When visibile is FALSE, mask 0
334
* and the current state of the tab bar is PaintPermanentOn it won't do anything
335
* because its not strong enough to disable a Permanent-State, for those you need
300
* and the current state of the tab bar is PaintPermanentOn it won't do
301
* anything because its not strong enough to disable a
302
* Permanent-State, for those you need the mask.
340
306
groupTabSetVisibility (GroupSelection *group,
348
if (!group || !group->windows || !group->tabBar || !HAS_TOP_WIN (group))
352
topTab = TOP_TAB (group);
353
oldState = bar->state;
355
/* hide tab bars for invisible top windows */
356
if ((topTab->state & CompWindowStateHiddenMask) || topTab->invisible)
358
bar->state = PaintOff;
359
groupSwitchTopTabInput (group, TRUE);
362
else if (visible && bar->state != PaintPermanentOn &&
365
bar->state = PaintPermanentOn;
366
groupSwitchTopTabInput (group, FALSE);
370
else if (visible && bar->state == PaintPermanentOn &&
373
bar->state = PaintOn;
377
(bar->state == PaintOff || bar->state == PaintFadeOut))
379
if (groupGetBarAnimations (group->screen))
381
bar->bgAnimation = AnimationReflex;
382
bar->bgAnimationTime = groupGetReflexTime (group->screen) * 1000.0;
384
bar->state = PaintFadeIn;
385
groupSwitchTopTabInput (group, FALSE);
389
(bar->state != PaintPermanentOn || (mask & PERMANENT)) &&
390
(bar->state == PaintOn || bar->state == PaintPermanentOn ||
391
bar->state == PaintFadeIn))
393
bar->state = PaintFadeOut;
394
groupSwitchTopTabInput (group, TRUE);
397
if (bar->state == PaintFadeIn || bar->state == PaintFadeOut)
398
bar->animationTime = (groupGetFadeTime (group->screen) * 1000) -
401
if (bar->state != oldState)
402
groupDamageTabBarRegion (group);
404
groupCheckForVisibleTabBars (group->screen);
315
if (!group || !group->windows || !group->tabBar || !HAS_TOP_WIN (group))
320
topTab = TOP_TAB (group);
321
oldState = bar->state;
323
/* hide tab bars for invisible top windows */
324
if ((topTab->state & CompWindowStateHiddenMask) || topTab->invisible)
326
bar->state = PaintOff;
327
groupSwitchTopTabInput (group, TRUE);
329
else if (visible && bar->state != PaintPermanentOn && (mask & PERMANENT))
331
bar->state = PaintPermanentOn;
332
groupSwitchTopTabInput (group, FALSE);
334
else if (visible && bar->state == PaintPermanentOn && !(mask & PERMANENT))
336
bar->state = PaintOn;
338
else if (visible && (bar->state == PaintOff || bar->state == PaintFadeOut))
340
if (groupGetBarAnimations (s))
342
bar->bgAnimation = AnimationReflex;
343
bar->bgAnimationTime = groupGetReflexTime (s) * 1000.0;
345
bar->state = PaintFadeIn;
346
groupSwitchTopTabInput (group, FALSE);
349
(bar->state != PaintPermanentOn || (mask & PERMANENT)) &&
350
(bar->state == PaintOn || bar->state == PaintPermanentOn ||
351
bar->state == PaintFadeIn))
353
bar->state = PaintFadeOut;
354
groupSwitchTopTabInput (group, TRUE);
357
if (bar->state == PaintFadeIn || bar->state == PaintFadeOut)
358
bar->animationTime = (groupGetFadeTime (s) * 1000) - bar->animationTime;
360
if (bar->state != oldState)
361
groupDamageTabBarRegion (group);
476
431
* the hover detection. This is needed for the text showing up,
477
432
* when you hover a thumb on the thumb bar.
434
* FIXME: we should better have a timer for that ...
481
437
groupHandleHoverDetection (GroupSelection *group)
483
GroupTabBar *bar = group->tabBar;
486
if (!HAS_TOP_WIN (group))
439
GroupTabBar *bar = group->tabBar;
440
CompWindow *topTab = TOP_TAB (group);
442
Bool mouseOnScreen, inLastSlot;
444
/* first get the current mouse position */
445
mouseOnScreen = groupGetCurrentMousePosition (group->screen,
451
/* then check if the mouse is in the last hovered slot --
452
this saves a lot of CPU usage */
453
inLastSlot = bar->hoveredSlot &&
454
XPointInRegion (bar->hoveredSlot->region, mouseX, mouseY);
459
GroupTabBarSlot *slot;
461
bar->hoveredSlot = NULL;
462
clip = groupGetClippingRegion (topTab);
464
for (slot = bar->slots; slot; slot = slot->next)
466
/* We need to clip the slot region with the clip region first.
467
This is needed to respect the window stack, so if a window
468
covers a port of that slot, this part won't be used
469
for in-slot-detection. */
470
Region reg = XCreateRegion();
473
XDestroyRegion(clip);
489
topTab = TOP_TAB(group);
491
if (bar->state != PaintOff)
477
XSubtractRegion (slot->region, clip, reg);
479
if (XPointInRegion (reg, mouseX, mouseY))
481
bar->hoveredSlot = slot;
482
XDestroyRegion (reg);
486
XDestroyRegion (reg);
489
XDestroyRegion (clip);
493
/* Tab-bar is visible. */
497
/* first get the current mouse position */
498
mouseOnScreen = groupGetCurrentMousePosition (group->screen,
501
/* then check if the mouse is in the last hovered slot --
502
this saves a lot of CPU usage */
504
!(bar->hoveredSlot &&
505
XPointInRegion (bar->hoveredSlot->region, mouseX, mouseY)))
508
GroupTabBarSlot *slot;
510
bar->hoveredSlot = NULL;
511
clip = groupGetClippingRegion (topTab);
513
for (slot = bar->slots; slot; slot = slot->next)
515
/* We need to clip the slot region with the clip region first.
516
This is needed to respect the window stack, so if a window
517
covers a port of that slot, this part won't be used
518
for in-slot-detection. */
519
Region reg = XCreateRegion();
522
XDestroyRegion(clip);
526
XSubtractRegion (slot->region, clip, reg);
528
if (XPointInRegion (reg, mouseX, mouseY))
530
bar->hoveredSlot = slot;
531
XDestroyRegion (reg);
535
XDestroyRegion (reg);
538
XDestroyRegion (clip);
542
/* trigger a FadeOut of the text */
543
if ((bar->hoveredSlot != bar->textSlot) &&
544
(bar->textLayer->state == PaintFadeIn ||
545
bar->textLayer->state == PaintOn))
547
bar->textLayer->animationTime =
548
(groupGetFadeTextTime (group->screen) * 1000) -
549
bar->textLayer->animationTime;
550
bar->textLayer->state = PaintFadeOut;
553
// or trigger a FadeIn of the text
554
else if (bar->textLayer->state == PaintFadeOut &&
555
bar->hoveredSlot == bar->textSlot && bar->hoveredSlot)
557
bar->textLayer->animationTime =
558
(groupGetFadeTextTime (group->screen) * 1000) -
559
bar->textLayer->animationTime;
560
bar->textLayer->state = PaintFadeIn;
493
/* trigger a FadeOut of the text */
494
if ((bar->hoveredSlot != bar->textSlot) &&
495
(bar->textLayer->state == PaintFadeIn ||
496
bar->textLayer->state == PaintOn))
498
bar->textLayer->animationTime =
499
(groupGetFadeTextTime (group->screen) * 1000) -
500
bar->textLayer->animationTime;
501
bar->textLayer->state = PaintFadeOut;
504
/* or trigger a FadeIn of the text */
505
else if (bar->textLayer->state == PaintFadeOut &&
506
bar->hoveredSlot == bar->textSlot && bar->hoveredSlot)
508
bar->textLayer->animationTime =
509
(groupGetFadeTextTime (group->screen) * 1000) -
510
bar->textLayer->animationTime;
511
bar->textLayer->state = PaintFadeIn;
629
groupHandleTextFade(GroupSelection *group, int msSinceLastPaint)
572
groupHandleTextFade (GroupSelection *group,
573
int msSinceLastPaint)
631
GroupTabBar *bar = group->tabBar;
632
GroupCairoLayer *textLayer = bar->textLayer;
637
/* Fade in progress... */
638
if ((textLayer->state == PaintFadeIn || textLayer->state == PaintFadeOut) &&
639
textLayer->animationTime > 0)
641
textLayer->animationTime -= msSinceLastPaint;
643
if (textLayer->animationTime < 0)
644
textLayer->animationTime = 0;
646
/* Fade has finished. */
647
if (textLayer->animationTime == 0)
649
if (textLayer->state == PaintFadeIn)
650
textLayer->state = PaintOn;
652
else if (textLayer->state == PaintFadeOut)
653
textLayer->state = PaintOff;
657
if (textLayer->state == PaintOff && bar->hoveredSlot)
659
/* Start text animation for the new hovered slot. */
660
bar->textSlot = bar->hoveredSlot;
661
textLayer->state = PaintFadeIn;
662
textLayer->animationTime =
663
(groupGetFadeTextTime (group->screen) * 1000);
665
groupRenderWindowTitle (group);
668
else if (textLayer->state == PaintOff && bar->textSlot)
671
bar->textSlot = NULL;
672
groupRenderWindowTitle (group);
575
GroupTabBar *bar = group->tabBar;
576
GroupCairoLayer *textLayer = bar->textLayer;
578
/* Fade in progress... */
579
if ((textLayer->state == PaintFadeIn || textLayer->state == PaintFadeOut) &&
580
textLayer->animationTime > 0)
582
textLayer->animationTime -= msSinceLastPaint;
584
if (textLayer->animationTime < 0)
585
textLayer->animationTime = 0;
587
/* Fade has finished. */
588
if (textLayer->animationTime == 0)
590
if (textLayer->state == PaintFadeIn)
591
textLayer->state = PaintOn;
593
else if (textLayer->state == PaintFadeOut)
594
textLayer->state = PaintOff;
598
if (textLayer->state == PaintOff && bar->hoveredSlot)
600
/* Start text animation for the new hovered slot. */
601
bar->textSlot = bar->hoveredSlot;
602
textLayer->state = PaintFadeIn;
603
textLayer->animationTime =
604
(groupGetFadeTextTime (group->screen) * 1000);
606
groupRenderWindowTitle (group);
609
else if (textLayer->state == PaintOff && bar->textSlot)
612
bar->textSlot = NULL;
613
groupRenderWindowTitle (group);
677
* groupHanldeTabBarAnimation
618
* groupHandleTabBarAnimation
679
620
* Description: Handles the different animations for the tab bar defined in
680
621
* GroupAnimationType. Basically that means this function updates
723
661
o[1].value.b = activating;
725
663
(*s->display->handleCompizEvent) (s->display,
726
"group", "tabChangeActivate", o, 2);
730
* groupHandleTabChange
733
* This function is also called from groupHandleChanges to handle
734
* the tab change. It moved the new topTab on the screen as well as doing
735
* the initial set for the tab change animation.
739
groupHandleTabChange (GroupSelection *group)
744
if (!group || !HAS_TOP_WIN (group) || !group->changeTab)
751
// exit when there is a rotate or plane animation
752
if (screenGrabExist (s, "rotate", "plane", "wall", 0))
755
topTab = TOP_TAB (group);
757
if (group->tabbingState != PaintOff)
759
/* if the previous top-tab window is being removed
760
from the group, move the new top-tab window onscreen. */
761
if (group->ungroupState == UngroupSingle && !group->prevTopTab)
764
groupSetWindowVisibility (topTab, TRUE);
766
group->oldTopTabCenterX -
767
WIN_X (topTab) - WIN_WIDTH (topTab) / 2,
768
group->oldTopTabCenterY -
769
WIN_Y (topTab) - WIN_HEIGHT (topTab) / 2,
771
syncWindowPosition (topTab);
774
/* recalc here is needed (for y value)! */
775
groupRecalcTabBarPos (group,
776
(group->tabBar->region->extents.x1 +
777
group->tabBar->region->extents.x2) / 2,
779
WIN_REAL_X (topTab) +
780
WIN_REAL_WIDTH (topTab));
782
group->prevTopTab = group->topTab;
789
groupSetWindowVisibility (topTab, TRUE);
791
group->oldTopTabCenterX -
792
WIN_X (topTab) - WIN_WIDTH (topTab) / 2,
793
group->oldTopTabCenterY -
794
WIN_Y (topTab) - WIN_HEIGHT (topTab) / 2,
796
syncWindowPosition (topTab);
799
if (group->prevTopTab)
801
/* we use only the half time here -
802
the second half will be PaintFadeOut */
803
group->changeAnimationTime = groupGetChangeAnimationTime (s) * 500;
804
groupTabChangeActivateEvent (s, TRUE);
805
group->changeState = PaintFadeIn;
807
group->changeTab = FALSE;
811
/* No window to do animation with. */
812
group->prevTopTab = group->topTab;
813
group->changeTab = FALSE;
814
activateWindow (TOP_TAB (group));
664
"group", "tabChangeActivate", o, 2);
832
679
groupHandleAnimation (GroupSelection *group)
834
CompScreen *s = group->screen;
836
if (group->tabbingState != PaintOff || !HAS_TOP_WIN (group))
839
if (screenGrabExist (s, "rotate", "plane", "wall", 0))
842
if (group->changeState == PaintFadeIn && group->changeAnimationTime <= 0)
844
/* recalc here is needed (for y value)! */
845
groupRecalcTabBarPos (group,
846
(group->tabBar->region->extents.x1 +
847
group->tabBar->region->extents.x2) / 2,
848
WIN_REAL_X (TOP_TAB (group)),
849
WIN_REAL_X (TOP_TAB (group)) +
850
WIN_REAL_WIDTH (TOP_TAB (group)));
852
group->changeAnimationTime += groupGetChangeAnimationTime (s) * 500;
854
if (group->changeAnimationTime <= 0)
855
group->changeAnimationTime = 0;
857
group->changeState = PaintFadeOut;
859
if (HAS_TOP_WIN (group))
860
activateWindow (TOP_TAB (group));
863
if (group->changeState == PaintFadeOut && group->changeAnimationTime <= 0)
865
int oldChangeAnimationTime = group->changeAnimationTime;
867
groupTabChangeActivateEvent (s, FALSE);
869
if (group->prevTopTab)
870
groupSetWindowVisibility (PREV_TOP_TAB (group), FALSE);
872
group->prevTopTab = group->topTab;
873
group->changeState = PaintOff;
875
if (group->nextTopTab)
877
groupChangeTab (group->nextTopTab, group->nextDirection);
878
group->nextTopTab = NULL;
880
groupHandleTabChange (group);
882
if (group->changeState == PaintFadeIn)
884
/* If a new animation was started. */
885
group->changeAnimationTime += oldChangeAnimationTime;
889
if (group->changeAnimationTime <= 0)
891
group->changeAnimationTime = 0;
893
else if (groupGetVisibilityTime (s) != 0.0f &&
894
group->changeState == PaintOff)
896
groupTabSetVisibility (group, TRUE,
897
PERMANENT | SHOW_BAR_INSTANTLY_MASK);
899
if (group->tabBar->timeoutHandle)
900
compRemoveTimeout (group->tabBar->timeoutHandle);
902
group->tabBar->timeoutHandle =
903
compAddTimeout (groupGetVisibilityTime (s) * 1000,
904
groupTabBarTimeout, group);
913
* This functions handes the offscreen moves of the tabs
914
* after the animation has finished. It's called from
915
* groupHandleChanges.
919
groupHandleTab (GroupSelection *group)
921
GroupTabBarSlot *slot;
923
if (group->tabbingState == PaintOff || group->doTabbing ||
924
!HAS_TOP_WIN (group) || !group->changeTab)
929
for (slot = group->tabBar->slots; slot; slot = slot->next)
931
CompWindow *w = slot->window;
937
if (slot == group->topTab ||
938
!(gw->animateState & FINISHED_ANIMATION) || gw->ungroup)
943
groupSetWindowVisibility (w, FALSE);
946
group->changeTab = FALSE;
947
group->prevTopTab = group->topTab;
951
* groupHandleTabbingAnimation
954
* This function handles the end of the tab
955
* animation. Actually its just sets some
956
* states and sync the window positions with X.
957
* It's called from groupHandleChanges.
961
groupHandleTabbingAnimation (GroupSelection *group)
965
if (group->tabbingState == PaintOff || group->doTabbing)
968
GROUP_SCREEN (group->screen);
970
/* Not animated any more. */
971
group->tabbingState = PaintOff;
973
for (i = 0; i < group->nWins; i++)
975
CompWindow *w = group->windows[i];
978
/* move window to target position */
980
moveWindow (w, gw->destination.x - WIN_X (w),
981
gw->destination.y - WIN_Y (w),
984
syncWindowPosition (w);
986
gw->animateState = 0;
987
gw->tx = gw->ty = gw->xVelocity = gw->yVelocity = 0.0f;
995
* This function handles the beginning of the untab
996
* animation. It deletes the tab bar and set's
997
* group->prevTopTab. It's called from groupHandleChanges.
1001
groupHandleUntab (GroupSelection *group)
1003
if (group->tabbingState == PaintOff || !group->doTabbing)
1006
if (group->topTab || !group->changeTab)
1009
groupDeleteTabBar (group);
1011
group->changeAnimationTime = 0;
1012
group->changeState = PaintOff;
1013
group->nextTopTab = NULL;
1015
group->changeTab = FALSE;
1016
group->prevTopTab = group->topTab;
1020
* groupHandleUngroup
1023
* This function handles the ungroup animation for tabbed groups.
1024
* It moved the windows on screen and also it calles groupDeleteGroupWindow
1025
* when its a "single ungroup", which means only one window gets removed
1026
* from the group. Another task of this function is to check if the group
1027
* which is before the given group in the linked list needs to be deleted.
1028
* This is needed to avoid problems with the linked list.
1029
* It's called from groupHandleChanges.
1033
groupHandleUngroup (GroupSelection *group)
1037
GROUP_SCREEN (group->screen);
1039
if ((group->ungroupState == UngroupSingle) &&
1040
group->doTabbing && group->changeTab)
1042
for (i = 0; i < group->nWins; i++)
1044
CompWindow *w = group->windows[i];
1050
groupSetWindowVisibility (w, TRUE);
1052
group->oldTopTabCenterX -
1053
WIN_X (w) - WIN_WIDTH (w) / 2,
1054
group->oldTopTabCenterY -
1055
WIN_Y (w) - WIN_HEIGHT (w) / 2,
1057
syncWindowPosition (w);
1062
group->changeTab = FALSE;
1065
if ((group->ungroupState == UngroupSingle) && !group->doTabbing)
1071
morePending = FALSE;
1073
for (i = 0;i < group->nWins; i++)
1075
CompWindow *w = group->windows[i];
1080
groupDeleteGroupWindow (w, TRUE);
1081
gw->ungroup = FALSE;
1086
while (morePending);
1088
group->ungroupState = UngroupNone;
1093
if ((group->prev->ungroupState == UngroupAll) &&
1094
!group->prev->doTabbing)
1096
groupDeleteGroup (group->prev);
1101
if ((group->ungroupState == UngroupAll) && !group->doTabbing)
1103
groupDeleteGroup (group);
1112
* groupHandleChanges
1115
* This function is called from groupPreparePaintScreen to
1116
* go through all groups and apply the other "handle functions"
1121
groupHandleChanges (CompScreen *s)
1123
GroupSelection *group;
1127
for (group = gs->groups; group; group = group ? group->next : NULL)
1129
groupHandleUntab (group);
1130
groupHandleTab (group);
1131
groupHandleTabbingAnimation (group);
1132
groupHandleTabChange (group);
1133
groupHandleAnimation (group);
1135
if (!groupHandleUngroup (group))
681
CompScreen *s = group->screen;
683
if (group->changeState == TabChangeOldOut)
685
CompWindow *top = TOP_TAB (group);
687
/* recalc here is needed (for y value)! */
688
groupRecalcTabBarPos (group,
689
(group->tabBar->region->extents.x1 +
690
group->tabBar->region->extents.x2) / 2,
692
WIN_REAL_X (top) + WIN_REAL_WIDTH (top));
694
group->changeAnimationTime += groupGetChangeAnimationTime (s) * 500;
696
if (group->changeAnimationTime <= 0)
697
group->changeAnimationTime = 0;
699
group->changeState = TabChangeNewIn;
701
activateWindow (top);
704
if (group->changeState == TabChangeNewIn &&
705
group->changeAnimationTime <= 0)
707
int oldChangeAnimationTime = group->changeAnimationTime;
709
groupTabChangeActivateEvent (s, FALSE);
711
if (group->prevTopTab)
712
groupSetWindowVisibility (PREV_TOP_TAB (group), FALSE);
714
group->prevTopTab = group->topTab;
715
group->changeState = NoTabChange;
717
if (group->nextTopTab)
719
GroupTabBarSlot *next = group->nextTopTab;
720
group->nextTopTab = NULL;
722
groupChangeTab (next, group->nextDirection);
724
if (group->changeState == TabChangeOldOut)
726
/* If a new animation was started. */
727
group->changeAnimationTime += oldChangeAnimationTime;
731
if (group->changeAnimationTime <= 0)
733
group->changeAnimationTime = 0;
735
else if (groupGetVisibilityTime (s) != 0.0f &&
736
group->changeState == NoTabChange)
738
groupTabSetVisibility (group, TRUE,
739
PERMANENT | SHOW_BAR_INSTANTLY_MASK);
741
if (group->tabBar->timeoutHandle)
742
compRemoveTimeout (group->tabBar->timeoutHandle);
744
group->tabBar->timeoutHandle =
745
compAddTimeout (groupGetVisibilityTime (s) * 1000,
746
groupTabBarTimeout, group);
1140
751
/* adjust velocity for each animation step (adapted from the scale plugin) */
1142
753
adjustTabVelocity (CompWindow *w)
1144
float dx, dy, adjust, amount;
755
float dx, dy, adjust, amount;
760
x1 = gw->destination.x;
761
y1 = gw->destination.y;
763
dx = x1 - (gw->orgPos.x + gw->tx);
765
amount = fabs (dx) * 1.5f;
768
else if (amount > 5.0f)
771
gw->xVelocity = (amount * gw->xVelocity + adjust) / (amount + 1.0f);
773
dy = y1 - (gw->orgPos.y + gw->ty);
775
amount = fabs (dy) * 1.5f;
778
else if (amount > 5.0f)
781
gw->yVelocity = (amount * gw->yVelocity + adjust) / (amount + 1.0f);
783
if (fabs (dx) < 0.1f && fabs (gw->xVelocity) < 0.2f &&
784
fabs (dy) < 0.1f && fabs (gw->yVelocity) < 0.2f)
786
gw->xVelocity = gw->yVelocity = 0.0f;
787
gw->tx = x1 - w->serverX;
788
gw->ty = y1 - w->serverY;
796
groupFinishTabbing (GroupSelection *group)
798
CompScreen *s = group->screen;
803
group->tabbingState = NoTabbing;
804
groupTabChangeActivateEvent (s, FALSE);
808
/* tabbing case - hide all non-toptab windows */
809
GroupTabBarSlot *slot;
811
for (slot = group->tabBar->slots; slot; slot = slot->next)
813
CompWindow *w = slot->window;
819
if (slot == group->topTab || (gw->animateState & IS_UNGROUPING))
822
groupSetWindowVisibility (w, FALSE);
824
group->prevTopTab = group->topTab;
827
for (i = 0; i < group->nWins; i++)
829
CompWindow *w = group->windows[i];
1147
830
GROUP_WINDOW (w);
1149
if (!(gw->animateState & IS_ANIMATED))
1152
x1 = gw->destination.x;
1153
y1 = gw->destination.y;
1155
dx = x1 - (gw->orgPos.x + gw->tx);
1156
adjust = dx * 0.15f;
1157
amount = fabs (dx) * 1.5f;
1160
else if (amount > 5.0f)
1163
gw->xVelocity = (amount * gw->xVelocity + adjust) / (amount + 1.0f);
1165
dy = y1 - (gw->orgPos.y + gw->ty);
1166
adjust = dy * 0.15f;
1167
amount = fabs (dy) * 1.5f;
1170
else if (amount > 5.0f)
1173
gw->yVelocity = (amount * gw->yVelocity + adjust) / (amount + 1.0f);
1175
if (fabs (dx) < 0.1f && fabs (gw->xVelocity) < 0.2f &&
1176
fabs (dy) < 0.1f && fabs (gw->yVelocity) < 0.2f)
832
/* move window to target position */
834
moveWindow (w, gw->destination.x - WIN_X (w),
835
gw->destination.y - WIN_Y (w), TRUE, TRUE);
837
syncWindowPosition (w);
839
if (group->ungroupState == UngroupSingle &&
840
(gw->animateState & IS_UNGROUPING))
1178
gw->xVelocity = gw->yVelocity = 0.0f;
1179
gw->tx = x1 - w->serverX;
1180
gw->ty = y1 - w->serverY;
842
groupRemoveWindowFromGroup (w);
845
gw->animateState = 0;
846
gw->tx = gw->ty = gw->xVelocity = gw->yVelocity = 0.0f;
849
if (group->ungroupState == UngroupAll)
850
groupDeleteGroup (group);
851
group->ungroupState = UngroupNone;
1267
930
groupUpdateTabBars (CompScreen *s,
1271
GroupSelection *hoveredGroup = NULL;
1275
/* first check if the entered window is a frame */
1276
for (w = s->windows; w; w = w->next)
1278
if (w->frame == enteredWin)
1284
/* is the window the entered frame belongs to inside
1285
a tabbed group? if no, it's not interesting for us */
1287
if (gw->group && gw->group->tabBar)
1290
/* it is grouped and tabbed, so now we have to
1291
check if we hovered the title bar or the frame */
1292
if (groupGetCurrentMousePosition (s, &mouseX, &mouseY))
1295
Region reg = XCreateRegion();
1299
rect.x = WIN_X (w) - w->input.left;
1300
rect.y = WIN_Y (w) - w->input.top;
1301
rect.width = WIN_WIDTH (w) + w->input.right;
1302
rect.height = WIN_Y (w) - rect.y;
1303
XUnionRectWithRegion (&rect, reg, reg);
1305
if (XPointInRegion (reg, mouseX, mouseY))
1306
hoveredGroup = gw->group;
1308
XDestroyRegion (reg);
1313
/* if we didn't hover a title bar, check if we hovered
1314
a tab bar (means: input prevention window) */
1317
GroupSelection *group;
1319
for (group = gs->groups; group; group = group->next)
1321
if (group->inputPrevention == enteredWin)
1323
/* only accept it if the IPW is mapped */
1324
if (group->ipwMapped)
1326
hoveredGroup = group;
1333
/* if we found a hovered a tab bar different than the last one
1334
(or left a tab bar), hide the old one */
1335
if (gs->lastHoveredGroup && (hoveredGroup != gs->lastHoveredGroup))
1336
groupTabSetVisibility (gs->lastHoveredGroup, FALSE, 0);
1338
/* if we entered a tab bar (or title bar), show the tab bar */
1339
if (hoveredGroup && HAS_TOP_WIN(hoveredGroup) &&
1340
!TOP_TAB(hoveredGroup)->grabbed)
1342
GroupTabBar *bar = hoveredGroup->tabBar;
1344
if (bar && ((bar->state == PaintOff) || (bar->state == PaintFadeOut)))
1346
int showDelayTime = groupGetTabbarShowDelay (s) * 1000;
1348
/* Show the tab-bar after a delay,
1349
only if the tab-bar wasn't fading out. */
1350
if (showDelayTime > 0 && (bar->state == PaintOff))
1352
if (gs->showDelayTimeoutHandle)
1353
compRemoveTimeout (gs->showDelayTimeoutHandle);
1354
gs->showDelayTimeoutHandle =
1355
compAddTimeout (showDelayTime,
1356
groupShowDelayTimeout, hoveredGroup);
1359
groupShowDelayTimeout (hoveredGroup);
1363
gs->lastHoveredGroup = hoveredGroup;
934
GroupSelection *hoveredGroup = NULL;
938
/* first check if the entered window is a frame */
939
for (w = s->windows; w; w = w->next)
941
if (w->frame == enteredWin)
947
/* is the window the entered frame belongs to inside
948
a tabbed group? if no, it's not interesting for us */
951
if (gw->group && gw->group->tabBar)
954
/* it is grouped and tabbed, so now we have to
955
check if we hovered the title bar or the frame */
956
if (groupGetCurrentMousePosition (s, &mouseX, &mouseY))
959
Region reg = XCreateRegion();
963
rect.x = WIN_X (w) - w->input.left;
964
rect.y = WIN_Y (w) - w->input.top;
965
rect.width = WIN_WIDTH (w) + w->input.right;
966
rect.height = WIN_Y (w) - rect.y;
967
XUnionRectWithRegion (&rect, reg, reg);
969
if (XPointInRegion (reg, mouseX, mouseY))
970
hoveredGroup = gw->group;
972
XDestroyRegion (reg);
977
/* if we didn't hover a title bar, check if we hovered
978
a tab bar (means: input prevention window) */
981
GroupSelection *group;
983
for (group = gs->groups; group; group = group->next)
985
if (group->inputPrevention == enteredWin)
987
/* only accept it if the IPW is mapped */
988
if (group->ipwMapped)
990
hoveredGroup = group;
997
/* if we found a hovered tab bar different than the last one
998
(or left a tab bar), hide the old one */
999
if (gs->lastHoveredGroup && (hoveredGroup != gs->lastHoveredGroup))
1000
groupTabSetVisibility (gs->lastHoveredGroup, FALSE, 0);
1002
/* if we entered a tab bar (or title bar), show the tab bar */
1003
if (hoveredGroup && HAS_TOP_WIN (hoveredGroup) &&
1004
!TOP_TAB (hoveredGroup)->grabbed)
1006
GroupTabBar *bar = hoveredGroup->tabBar;
1008
if (bar && ((bar->state == PaintOff) || (bar->state == PaintFadeOut)))
1010
int showDelayTime = groupGetTabbarShowDelay (s) * 1000;
1012
/* Show the tab-bar after a delay,
1013
only if the tab-bar wasn't fading out. */
1014
if (showDelayTime > 0 && (bar->state == PaintOff))
1016
if (gs->showDelayTimeoutHandle)
1017
compRemoveTimeout (gs->showDelayTimeoutHandle);
1018
gs->showDelayTimeoutHandle =
1019
compAddTimeout (showDelayTime,
1020
groupShowDelayTimeout, hoveredGroup);
1023
groupShowDelayTimeout (hoveredGroup);
1027
gs->lastHoveredGroup = hoveredGroup;
1371
1035
groupGetConstrainRegion (CompScreen *s)
1378
region = XCreateRegion ();
1382
for (i = 0;i < s->nOutputDev; i++)
1383
XUnionRegion (&s->outputDev[i].region, region, region);
1385
r.rects = &r.extents;
1386
r.numRects = r.size = 1;
1388
for (w = s->windows; w; w = w->next)
1042
region = XCreateRegion ();
1046
for (i = 0;i < s->nOutputDev; i++)
1047
XUnionRegion (&s->outputDev[i].region, region, region);
1049
r.rects = &r.extents;
1050
r.numRects = r.size = 1;
1052
for (w = s->windows; w; w = w->next)
1395
r.extents.x1 = w->struts->top.x;
1396
r.extents.y1 = w->struts->top.y;
1397
r.extents.x2 = r.extents.x1 + w->struts->top.width;
1398
r.extents.y2 = r.extents.y1 + w->struts->top.height;
1400
XSubtractRegion (region, &r, region);
1402
r.extents.x1 = w->struts->bottom.x;
1403
r.extents.y1 = w->struts->bottom.y;
1404
r.extents.x2 = r.extents.x1 + w->struts->bottom.width;
1405
r.extents.y2 = r.extents.y1 + w->struts->bottom.height;
1407
XSubtractRegion (region, &r, region);
1409
r.extents.x1 = w->struts->left.x;
1410
r.extents.y1 = w->struts->left.y;
1411
r.extents.x2 = r.extents.x1 + w->struts->left.width;
1412
r.extents.y2 = r.extents.y1 + w->struts->left.height;
1414
XSubtractRegion (region, &r, region);
1416
r.extents.x1 = w->struts->right.x;
1417
r.extents.y1 = w->struts->right.y;
1418
r.extents.x2 = r.extents.x1 + w->struts->right.width;
1419
r.extents.y2 = r.extents.y1 + w->struts->right.height;
1421
XSubtractRegion (region, &r, region);
1059
r.extents.x1 = w->struts->top.x;
1060
r.extents.y1 = w->struts->top.y;
1061
r.extents.x2 = r.extents.x1 + w->struts->top.width;
1062
r.extents.y2 = r.extents.y1 + w->struts->top.height;
1064
XSubtractRegion (region, &r, region);
1066
r.extents.x1 = w->struts->bottom.x;
1067
r.extents.y1 = w->struts->bottom.y;
1068
r.extents.x2 = r.extents.x1 + w->struts->bottom.width;
1069
r.extents.y2 = r.extents.y1 + w->struts->bottom.height;
1071
XSubtractRegion (region, &r, region);
1073
r.extents.x1 = w->struts->left.x;
1074
r.extents.y1 = w->struts->left.y;
1075
r.extents.x2 = r.extents.x1 + w->struts->left.width;
1076
r.extents.y2 = r.extents.y1 + w->struts->left.height;
1078
XSubtractRegion (region, &r, region);
1080
r.extents.x1 = w->struts->right.x;
1081
r.extents.y1 = w->struts->right.y;
1082
r.extents.x2 = r.extents.x1 + w->struts->right.width;
1083
r.extents.y2 = r.extents.y1 + w->struts->right.height;
1085
XSubtractRegion (region, &r, region);
1433
1097
groupConstrainMovement (CompWindow *w,
1434
Region constrainRegion,
1098
Region constrainRegion,
1440
int status, xStatus;
1441
int origDx = dx, origDy = dy;
1442
int x, y, width, height;
1104
int status, xStatus;
1105
int origDx = dx, origDy = dy;
1106
int x, y, width, height;
1116
x = gw->orgPos.x - w->input.left + dx;
1117
y = gw->orgPos.y - w->input.top + dy;
1118
width = WIN_REAL_WIDTH (w);
1119
height = WIN_REAL_HEIGHT (w);
1121
status = XRectInRegion (constrainRegion, x, y, width, height);
1124
while (dx && (xStatus != RectangleIn))
1126
xStatus = XRectInRegion (constrainRegion, x, y - dy, width, height);
1128
if (xStatus != RectangleIn)
1129
dx += (dx < 0) ? 1 : -1;
1452
1131
x = gw->orgPos.x - w->input.left + dx;
1134
while (dy && (status != RectangleIn))
1136
status = XRectInRegion(constrainRegion, x, y, width, height);
1138
if (status != RectangleIn)
1139
dy += (dy < 0) ? 1 : -1;
1453
1141
y = gw->orgPos.y - w->input.top + dy;
1454
width = WIN_REAL_WIDTH (w);
1455
height = WIN_REAL_HEIGHT (w);
1457
status = XRectInRegion (constrainRegion, x, y, width, height);
1460
while (dx && (xStatus != RectangleIn))
1462
xStatus = XRectInRegion (constrainRegion, x, y - dy, width, height);
1464
if (xStatus != RectangleIn)
1465
dx += (dx < 0) ? 1 : -1;
1467
x = gw->orgPos.x - w->input.left + dx;
1470
while (dy && (status != RectangleIn))
1472
status = XRectInRegion(constrainRegion, x, y, width, height);
1474
if (status != RectangleIn)
1475
dy += (dy < 0) ? 1 : -1;
1477
y = gw->orgPos.y - w->input.top + dy;
1486
return ((dx != origDx) || (dy != origDy));
1150
return ((dx != origDx) || (dy != origDy));
1490
* groupApplyConstrainingToWindows
1154
* groupApplyConstraining
1494
groupApplyConstrainingToWindows (GroupSelection *group,
1495
Region constrainRegion,
1496
Window constrainedWindow,
1158
groupApplyConstraining (GroupSelection *group,
1159
Region constrainRegion,
1160
Window constrainedWindow,
1170
for (i = 0; i < group->nWins; i++)
1172
w = group->windows[i];
1175
/* ignore certain windows: we don't want to apply the constraining
1176
results on the constrained window itself, nor do we want to
1177
change the target position of unamimated windows and of
1178
windows which already are constrained */
1179
if (w->id == constrainedWindow)
1182
if (!(gw->animateState & IS_ANIMATED))
1185
if (gw->animateState & DONT_CONSTRAIN)
1188
if (!(gw->animateState & CONSTRAINED_X))
1190
gw->animateState |= IS_ANIMATED;
1192
/* applying the constraining result of another window
1193
might move the window offscreen, too, so check
1194
if this is not the case */
1195
if (groupConstrainMovement (w, constrainRegion, dx, 0, &dx, NULL))
1196
gw->animateState |= CONSTRAINED_X;
1198
gw->destination.x += dx;
1201
if (!(gw->animateState & CONSTRAINED_Y))
1203
gw->animateState |= IS_ANIMATED;
1205
/* analog to X case */
1206
if (groupConstrainMovement (w, constrainRegion, 0, dy, NULL, &dy))
1207
gw->animateState |= CONSTRAINED_Y;
1209
gw->destination.y += dy;
1215
* groupStartTabbingAnimation
1219
groupStartTabbingAnimation (GroupSelection *group,
1225
int constrainStatus;
1227
if (!group || (group->tabbingState != NoTabbing))
1231
group->tabbingState = (tab) ? Tabbing : Untabbing;
1232
groupTabChangeActivateEvent (s, TRUE);
1236
/* we need to set up the X/Y constraining on untabbing */
1237
Region constrainRegion = groupGetConstrainRegion (s);
1238
Bool constrainedWindows = TRUE;
1240
if (!constrainRegion)
1243
/* reset all flags */
1506
1244
for (i = 0; i < group->nWins; i++)
1508
w = group->windows[i];
1246
GROUP_WINDOW (group->windows[i]);
1247
gw->animateState &= ~(CONSTRAINED_X | CONSTRAINED_Y |
1251
/* as we apply the constraining in a flat loop,
1252
we may need to run multiple times through this
1253
loop until all constraining dependencies are met */
1254
while (constrainedWindows)
1256
constrainedWindows = FALSE;
1257
/* loop through all windows and try to constrain their
1258
animation path (going from gw->orgPos to
1259
gw->destination) to the active screen area */
1260
for (i = 0; i < group->nWins; i++)
1262
CompWindow *w = group->windows[i];
1509
1263
GROUP_WINDOW (w);
1511
/* ignore certain windows: we don't want to apply the constraining
1512
results on the constrained window itself, nor do we want to
1513
change the target position of unamimated windows and of
1514
windows which already are constrained */
1515
if (w->id == constrainedWindow)
1265
/* ignore windows which aren't animated and/or
1266
already are at the edge of the screen area */
1518
1267
if (!(gw->animateState & IS_ANIMATED))
1521
1270
if (gw->animateState & DONT_CONSTRAIN)
1524
if (!(gw->animateState & CONSTRAINED_X))
1526
gw->animateState |= IS_ANIMATED;
1528
/* applying the constraining result of another window
1529
might move the window offscreen, too, so check
1530
if this is not the case */
1531
if (groupConstrainMovement (w, constrainRegion, dx, 0, &dx, NULL))
1532
gw->animateState |= CONSTRAINED_X;
1534
gw->destination.x += dx;
1538
if (!(gw->animateState & CONSTRAINED_Y))
1540
gw->animateState |= IS_ANIMATED;
1542
/* analog to X case */
1543
if (groupConstrainMovement (w, constrainRegion, 0, dy, NULL, &dy))
1544
gw->animateState |= CONSTRAINED_Y;
1546
gw->destination.y += dy;
1553
* groupStartTabbingAnimation
1557
groupStartTabbingAnimation (GroupSelection *group,
1563
int constrainStatus;
1565
if (!group || (group->tabbingState != PaintOff))
1569
group->doTabbing = TRUE;
1570
group->changeTab = TRUE;
1572
group->tabbingState = (tab) ? PaintFadeIn : PaintFadeOut;
1576
/* we need to set up the X/Y constraining on untabbing */
1577
Region constrainRegion = groupGetConstrainRegion (s);
1578
Bool constrainedWindows = TRUE;
1580
if (!constrainRegion)
1583
/* reset all flags */
1584
for (i = 0; i < group->nWins; i++)
1586
GROUP_WINDOW (group->windows[i]);
1587
gw->animateState &= ~(CONSTRAINED_X | CONSTRAINED_Y |
1591
/* as we apply the constraining in a flat loop,
1592
we may need to run multiple times through this
1593
loop until all constraining dependencies are met */
1594
while (constrainedWindows)
1596
constrainedWindows = FALSE;
1597
/* loop through all windows and try to constrain their
1598
animation path (going from gw->orgPos to
1599
gw->destination) to the active screen area */
1600
for (i = 0; i < group->nWins; i++)
1602
CompWindow *w = group->windows[i];
1605
/* ignore windows which aren't animated and/or
1606
already are at the edge of the screen area */
1607
if (!(gw->animateState & IS_ANIMATED))
1610
if (gw->animateState & DONT_CONSTRAIN)
1613
/* is the original position inside the screen area? */
1614
constrainStatus = XRectInRegion (constrainRegion,
1615
gw->orgPos.x - w->input.left,
1616
gw->orgPos.y - w->input.top,
1618
WIN_REAL_HEIGHT (w));
1620
/* constrain the movement */
1621
if (groupConstrainMovement (w, constrainRegion,
1622
gw->destination.x - gw->orgPos.x,
1623
gw->destination.y - gw->orgPos.y,
1626
/* handle the case where the window is outside the screen
1627
area on its whole animation path */
1628
if (constrainStatus != RectangleIn && !dx && !dy)
1630
gw->animateState |= DONT_CONSTRAIN;
1631
gw->animateState |= CONSTRAINED_X | CONSTRAINED_Y;
1633
/* use the original position as last resort */
1634
gw->destination.x = gw->mainTabOffset.x;
1635
gw->destination.y = gw->mainTabOffset.y;
1639
/* if we found a valid target position, apply
1640
the change also to other windows to retain
1641
the distance between the windows */
1642
groupApplyConstrainingToWindows (group,
1652
/* if we hit constraints, adjust the mask and the
1653
target position accordingly */
1654
if (dx != (gw->destination.x - gw->orgPos.x))
1656
gw->animateState |= CONSTRAINED_X;
1657
gw->destination.x = gw->orgPos.x + dx;
1660
if (dy != (gw->destination.y - gw->orgPos.y))
1662
gw->animateState |= CONSTRAINED_Y;
1663
gw->destination.y = gw->orgPos.y + dy;
1666
constrainedWindows = TRUE;
1671
XDestroyRegion (constrainRegion);
1273
/* is the original position inside the screen area? */
1274
constrainStatus = XRectInRegion (constrainRegion,
1275
gw->orgPos.x - w->input.left,
1276
gw->orgPos.y - w->input.top,
1278
WIN_REAL_HEIGHT (w));
1280
/* constrain the movement */
1281
if (groupConstrainMovement (w, constrainRegion,
1282
gw->destination.x - gw->orgPos.x,
1283
gw->destination.y - gw->orgPos.y,
1286
/* handle the case where the window is outside the screen
1287
area on its whole animation path */
1288
if (constrainStatus != RectangleIn && !dx && !dy)
1290
gw->animateState |= DONT_CONSTRAIN;
1291
gw->animateState |= CONSTRAINED_X | CONSTRAINED_Y;
1293
/* use the original position as last resort */
1294
gw->destination.x = gw->mainTabOffset.x;
1295
gw->destination.y = gw->mainTabOffset.y;
1299
/* if we found a valid target position, apply
1300
the change also to other windows to retain
1301
the distance between the windows */
1302
groupApplyConstraining (group, constrainRegion, w->id,
1303
dx - gw->destination.x +
1305
dy - gw->destination.y +
1308
/* if we hit constraints, adjust the mask and the
1309
target position accordingly */
1310
if (dx != (gw->destination.x - gw->orgPos.x))
1312
gw->animateState |= CONSTRAINED_X;
1313
gw->destination.x = gw->orgPos.x + dx;
1316
if (dy != (gw->destination.y - gw->orgPos.y))
1318
gw->animateState |= CONSTRAINED_Y;
1319
gw->destination.y = gw->orgPos.y + dy;
1322
constrainedWindows = TRUE;
1327
XDestroyRegion (constrainRegion);
1680
1336
groupTabGroup (CompWindow *main)
1682
GroupSelection *group;
1683
GroupTabBarSlot *slot;
1685
int space, thumbSize;
1687
GROUP_WINDOW (main);
1690
if (!group || group->tabBar)
1693
if (!main->screen->display->shapeExtension)
1695
compLogMessage (main->screen->display, "group", CompLogLevelError,
1696
"No X shape extension! Tabbing disabled.");
1700
groupInitTabBar (group, main);
1704
groupCreateInputPreventionWindow (group);
1706
group->tabbingState = PaintOff;
1707
/* Slot is initialized after groupInitTabBar(group); */
1708
groupChangeTab (gw->slot, RotateUncertain);
1709
groupRecalcTabBarPos (gw->group,
1710
WIN_X (main) + WIN_WIDTH (main) / 2,
1711
WIN_X (main), WIN_X (main) + WIN_WIDTH (main));
1713
width = group->tabBar->region->extents.x2 -
1714
group->tabBar->region->extents.x1;
1715
height = group->tabBar->region->extents.y2 -
1716
group->tabBar->region->extents.y1;
1718
group->tabBar->textLayer = groupCreateCairoLayer (main->screen,
1720
if (group->tabBar->textLayer)
1722
GroupCairoLayer *layer;
1724
layer = group->tabBar->textLayer;
1725
layer->state = PaintOff;
1726
layer->animationTime = 0;
1727
groupRenderWindowTitle (group);
1729
if (group->tabBar->textLayer)
1731
GroupCairoLayer *layer;
1733
layer = group->tabBar->textLayer;
1734
layer->animationTime = groupGetFadeTextTime (main->screen) *
1736
layer->state = PaintFadeIn;
1739
// we need a buffer for DnD here
1740
space = groupGetThumbSpace (main->screen);
1741
thumbSize = groupGetThumbSize (main->screen);
1742
group->tabBar->bgLayer = groupCreateCairoLayer (main->screen,
1743
width + space + thumbSize,
1745
if (group->tabBar->bgLayer)
1747
group->tabBar->bgLayer->state = PaintOn;
1748
group->tabBar->bgLayer->animationTime = 0;
1749
groupRenderTabBarBackground (group);
1752
width = group->topTab->region->extents.x2 -
1753
group->topTab->region->extents.x1;
1754
height = group->topTab->region->extents.y2 -
1755
group->topTab->region->extents.y1;
1757
group->tabBar->selectionLayer = groupCreateCairoLayer (main->screen,
1759
if (group->tabBar->selectionLayer)
1761
group->tabBar->selectionLayer->state = PaintOn;
1762
group->tabBar->selectionLayer->animationTime = 0;
1763
groupRenderTopTabHighlight (group);
1766
if (!HAS_TOP_WIN (group))
1769
for (slot = group->tabBar->slots; slot; slot = slot->next)
1771
CompWindow *cw = slot->window;
1775
if (gw->animateState & (IS_ANIMATED | FINISHED_ANIMATION))
1777
gw->destination.x - WIN_X (cw),
1778
gw->destination.y - WIN_Y (cw),
1781
/* center the window to the main window */
1782
gw->destination.x = WIN_X (main) +
1783
(WIN_WIDTH (main) / 2) - (WIN_WIDTH (cw) / 2);
1784
gw->destination.y = WIN_Y (main) +
1785
(WIN_HEIGHT (main) / 2) - (WIN_HEIGHT (cw) / 2);
1787
/* Distance from destination. */
1788
gw->mainTabOffset.x = WIN_X (cw) - gw->destination.x;
1789
gw->mainTabOffset.y = WIN_Y (cw) - gw->destination.y;
1791
if (gw->tx || gw->ty)
1793
gw->tx -= (WIN_X (cw) - gw->orgPos.x);
1794
gw->ty -= (WIN_Y (cw) - gw->orgPos.y);
1797
gw->orgPos.x = WIN_X (cw);
1798
gw->orgPos.y = WIN_Y (cw);
1800
gw->animateState = IS_ANIMATED;
1801
gw->xVelocity = gw->yVelocity = 0.0f;
1804
groupStartTabbingAnimation (group, TRUE);
1338
GroupSelection *group;
1339
GroupTabBarSlot *slot;
1340
CompScreen *s = main->screen;
1342
int space, thumbSize;
1344
GROUP_WINDOW (main);
1347
if (!group || group->tabBar)
1350
if (!s->display->shapeExtension)
1352
compLogMessage (s->display, "group", CompLogLevelError,
1353
"No X shape extension! Tabbing disabled.");
1357
groupInitTabBar (group, main);
1361
groupCreateInputPreventionWindow (group);
1363
group->tabbingState = NoTabbing;
1364
/* Slot is initialized after groupInitTabBar(group); */
1365
groupChangeTab (gw->slot, RotateUncertain);
1366
groupRecalcTabBarPos (gw->group, WIN_CENTER_X (main),
1367
WIN_X (main), WIN_X (main) + WIN_WIDTH (main));
1369
width = group->tabBar->region->extents.x2 -
1370
group->tabBar->region->extents.x1;
1371
height = group->tabBar->region->extents.y2 -
1372
group->tabBar->region->extents.y1;
1374
group->tabBar->textLayer = groupCreateCairoLayer (s, width, height);
1375
if (group->tabBar->textLayer)
1377
GroupCairoLayer *layer;
1379
layer = group->tabBar->textLayer;
1380
layer->state = PaintOff;
1381
layer->animationTime = 0;
1382
groupRenderWindowTitle (group);
1384
if (group->tabBar->textLayer)
1386
GroupCairoLayer *layer;
1388
layer = group->tabBar->textLayer;
1389
layer->animationTime = groupGetFadeTextTime (s) * 1000;
1390
layer->state = PaintFadeIn;
1393
/* we need a buffer for DnD here */
1394
space = groupGetThumbSpace (s);
1395
thumbSize = groupGetThumbSize (s);
1396
group->tabBar->bgLayer = groupCreateCairoLayer (s,
1397
width + space + thumbSize,
1399
if (group->tabBar->bgLayer)
1401
group->tabBar->bgLayer->state = PaintOn;
1402
group->tabBar->bgLayer->animationTime = 0;
1403
groupRenderTabBarBackground (group);
1406
width = group->topTab->region->extents.x2 -
1407
group->topTab->region->extents.x1;
1408
height = group->topTab->region->extents.y2 -
1409
group->topTab->region->extents.y1;
1411
group->tabBar->selectionLayer = groupCreateCairoLayer (s, width, height);
1412
if (group->tabBar->selectionLayer)
1414
group->tabBar->selectionLayer->state = PaintOn;
1415
group->tabBar->selectionLayer->animationTime = 0;
1416
groupRenderTopTabHighlight (group);
1419
if (!HAS_TOP_WIN (group))
1422
for (slot = group->tabBar->slots; slot; slot = slot->next)
1424
CompWindow *cw = slot->window;
1428
if (gw->animateState & (IS_ANIMATED | FINISHED_ANIMATION))
1430
gw->destination.x - WIN_X (cw),
1431
gw->destination.y - WIN_Y (cw),
1434
/* center the window to the main window */
1435
gw->destination.x = WIN_CENTER_X (main) - (WIN_WIDTH (cw) / 2);
1436
gw->destination.y = WIN_CENTER_Y (main) - (WIN_HEIGHT (cw) / 2);
1438
/* Distance from destination. */
1439
gw->mainTabOffset.x = WIN_X (cw) - gw->destination.x;
1440
gw->mainTabOffset.y = WIN_Y (cw) - gw->destination.y;
1442
if (gw->tx || gw->ty)
1444
gw->tx -= (WIN_X (cw) - gw->orgPos.x);
1445
gw->ty -= (WIN_Y (cw) - gw->orgPos.y);
1448
gw->orgPos.x = WIN_X (cw);
1449
gw->orgPos.y = WIN_Y (cw);
1451
gw->animateState = IS_ANIMATED;
1452
gw->xVelocity = gw->yVelocity = 0.0f;
1455
groupStartTabbingAnimation (group, TRUE);
1812
groupUntabGroup(GroupSelection *group)
1463
groupUntabGroup (GroupSelection *group)
1815
CompWindow *prevTopTab;
1816
GroupTabBarSlot *slot;
1818
if (!HAS_TOP_WIN (group))
1821
GROUP_SCREEN (TOP_TAB (group)->screen);
1823
if (group->prevTopTab)
1824
prevTopTab = PREV_TOP_TAB (group);
1827
/* If prevTopTab isn't set, we have no choice but using topTab.
1828
It happens when there is still animation, which
1829
means the tab wasn't changed anyway. */
1830
prevTopTab = TOP_TAB (group);
1833
group->oldTopTabCenterX = WIN_X (prevTopTab) + WIN_WIDTH (prevTopTab) / 2;
1834
group->oldTopTabCenterY = WIN_Y (prevTopTab) + WIN_HEIGHT (prevTopTab) / 2;
1836
group->lastTopTab = TOP_TAB (group);
1837
group->topTab = NULL;
1839
for (slot = group->tabBar->slots; slot; slot = slot->next)
1841
CompWindow *cw = slot->window;
1846
groupSetWindowVisibility (cw, TRUE);
1847
if (gw->animateState & (IS_ANIMATED | FINISHED_ANIMATION))
1849
gw->destination.x - WIN_X (cw),
1850
gw->destination.y - WIN_Y (cw),
1853
group->oldTopTabCenterX - WIN_X (cw) - WIN_WIDTH (cw) / 2,
1854
group->oldTopTabCenterY - WIN_Y (cw) - WIN_HEIGHT (cw) / 2,
1856
syncWindowPosition (cw);
1859
/* save the old original position - we might need it
1860
if constraining fails */
1861
oldX = gw->orgPos.x;
1862
oldY = gw->orgPos.y;
1864
gw->orgPos.x = group->oldTopTabCenterX - WIN_WIDTH (cw) / 2;
1865
gw->orgPos.y = group->oldTopTabCenterY - WIN_HEIGHT (cw) / 2;
1867
gw->destination.x = gw->orgPos.x + gw->mainTabOffset.x;
1868
gw->destination.y = gw->orgPos.y + gw->mainTabOffset.y;
1870
if (gw->tx || gw->ty)
1872
gw->tx -= (gw->orgPos.x - oldX);
1873
gw->ty -= (gw->orgPos.y - oldY);
1876
gw->mainTabOffset.x = oldX;
1877
gw->mainTabOffset.y = oldY;
1879
gw->animateState = IS_ANIMATED;
1880
gw->xVelocity = gw->yVelocity = 0.0f;
1883
group->tabbingState = PaintOff;
1884
groupStartTabbingAnimation (group, FALSE);
1886
damageScreen (group->screen);
1466
CompWindow *prevTopTab;
1467
GroupTabBarSlot *slot;
1469
if (!HAS_TOP_WIN (group))
1472
GROUP_SCREEN (group->screen);
1474
if (group->prevTopTab)
1475
prevTopTab = PREV_TOP_TAB (group);
1478
/* If prevTopTab isn't set, we have no choice but using topTab.
1479
It happens when there is still animation, which
1480
means the tab wasn't changed anyway. */
1481
prevTopTab = TOP_TAB (group);
1484
group->lastTopTab = TOP_TAB (group);
1485
group->topTab = NULL;
1487
for (slot = group->tabBar->slots; slot; slot = slot->next)
1489
CompWindow *cw = slot->window;
1493
if (gw->animateState & (IS_ANIMATED | FINISHED_ANIMATION))
1497
gw->destination.x - WIN_X (cw),
1498
gw->destination.y - WIN_Y (cw),
1502
groupSetWindowVisibility (cw, TRUE);
1504
/* save the old original position - we might need it
1505
if constraining fails */
1506
oldX = gw->orgPos.x;
1507
oldY = gw->orgPos.y;
1509
gw->orgPos.x = WIN_CENTER_X (prevTopTab) - WIN_WIDTH (cw) / 2;
1510
gw->orgPos.y = WIN_CENTER_Y (prevTopTab) - WIN_HEIGHT (cw) / 2;
1512
gw->destination.x = gw->orgPos.x + gw->mainTabOffset.x;
1513
gw->destination.y = gw->orgPos.y + gw->mainTabOffset.y;
1515
if (gw->tx || gw->ty)
1517
gw->tx -= (gw->orgPos.x - oldX);
1518
gw->ty -= (gw->orgPos.y - oldY);
1521
gw->mainTabOffset.x = oldX;
1522
gw->mainTabOffset.y = oldY;
1524
gw->animateState = IS_ANIMATED;
1525
gw->xVelocity = gw->yVelocity = 0.0f;
1528
group->tabbingState = NoTabbing;
1529
groupStartTabbingAnimation (group, FALSE);
1531
groupDeleteTabBar (group);
1532
group->changeAnimationTime = 0;
1533
group->changeState = NoTabChange;
1534
group->nextTopTab = NULL;
1535
group->prevTopTab = NULL;
1537
damageScreen (group->screen);
1894
1545
groupChangeTab (GroupTabBarSlot *topTab,
1895
ChangeTabAnimationDirection direction)
1898
GroupSelection *group;
1903
GROUP_WINDOW (topTab->window);
1908
if (!group || group->tabbingState != PaintOff)
1911
if (group->changeState == PaintOff && group->topTab == topTab)
1914
if (group->changeState != PaintOff && group->nextTopTab == topTab)
1917
if (group->prevTopTab && group->changeState == PaintOff)
1919
group->oldTopTabCenterX = WIN_X (PREV_TOP_TAB (group)) +
1920
WIN_WIDTH (PREV_TOP_TAB (group)) / 2;
1921
group->oldTopTabCenterY = WIN_Y (PREV_TOP_TAB (group)) +
1922
WIN_HEIGHT (PREV_TOP_TAB (group)) / 2;
1925
if (group->changeState != PaintOff)
1926
group->nextDirection = direction;
1927
else if (direction == RotateLeft)
1928
group->changeAnimationDirection = 1;
1929
else if (direction == RotateRight)
1930
group->changeAnimationDirection = -1;
1933
int distanceOld = 0, distanceNew = 0;
1934
GroupTabBarSlot *slot;
1937
for (slot = group->tabBar->slots; slot && (slot != group->topTab);
1938
slot = slot->next, distanceOld++);
1940
for (slot = group->tabBar->slots; slot && (slot != topTab);
1941
slot = slot->next, distanceNew++);
1943
if (distanceNew < distanceOld)
1944
group->changeAnimationDirection = 1; /*left */
1946
group->changeAnimationDirection = -1; /* right */
1948
/* check if the opposite direction is shorter */
1949
if (abs (distanceNew - distanceOld) > (group->tabBar->nSlots / 2))
1950
group->changeAnimationDirection *= -1;
1953
if (group->changeState != PaintOff)
1955
if (group->prevTopTab == topTab)
1957
/* Reverse animation. */
1958
GroupTabBarSlot *tmp = group->topTab;
1959
group->topTab = group->prevTopTab;
1960
group->prevTopTab = tmp;
1962
group->changeAnimationDirection *= -1;
1963
group->changeAnimationTime =
1964
groupGetChangeAnimationTime (w->screen) * 500 -
1965
group->changeAnimationTime;
1966
group->changeState =
1967
(group->changeState == PaintFadeIn) ? PaintFadeOut: PaintFadeIn;
1969
group->nextTopTab = NULL;
1972
group->nextTopTab = topTab;
1976
group->topTab = topTab;
1977
group->changeTab = (group->prevTopTab != topTab);
1979
groupRenderWindowTitle (group);
1980
groupRenderTopTabHighlight (group);
1981
addWindowDamage (w);
1988
* groupRebuildCairoLayer
1992
groupRebuildCairoLayer (CompScreen *s,
1993
GroupCairoLayer *layer,
1997
int timeBuf = layer->animationTime;
1998
PaintState stateBuf = layer->state;
2000
groupDestroyCairoLayer (s, layer);
2001
layer = groupCreateCairoLayer (s, width, height);
2005
layer->animationTime = timeBuf;
2006
layer->state = stateBuf;
2012
* groupClearCairoLayer
2016
groupClearCairoLayer (GroupCairoLayer *layer)
2018
cairo_t *cr = layer->cairo;
2021
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
2027
* groupDestroyCairoLayer
2031
groupDestroyCairoLayer (CompScreen *s,
2032
GroupCairoLayer *layer)
2035
cairo_destroy (layer->cairo);
2038
cairo_surface_destroy (layer->surface);
2040
finiTexture (s, &layer->texture);
2043
free (layer->buffer);
2049
* groupCreateCairoLayer
2053
groupCreateCairoLayer (CompScreen *s,
2057
GroupCairoLayer *layer;
2060
layer = malloc (sizeof (GroupCairoLayer));
2062
layer->surface = NULL;
2063
layer->cairo = NULL;
2064
layer->buffer = NULL;
2065
layer->animationTime = 0;
2066
layer->state = PaintOff;
2067
layer->texWidth = width;
2068
layer->texHeight = height;
2070
initTexture (s, &layer->texture);
2072
layer->buffer = calloc (4 * width * height, sizeof (unsigned char));
2075
printf ("ERROR: Failed to alloc buffer!\n");
2076
groupDestroyCairoLayer (s, layer);
2080
layer->surface = cairo_image_surface_create_for_data (layer->buffer,
2081
CAIRO_FORMAT_ARGB32,
2084
if (cairo_surface_status (layer->surface) != CAIRO_STATUS_SUCCESS)
2086
printf ("ERROR: Failed to create surface!\n");
2087
groupDestroyCairoLayer (s, layer);
2091
layer->cairo = cairo_create (layer->surface);
2092
if (cairo_status (layer->cairo) != CAIRO_STATUS_SUCCESS)
2094
printf ("ERROR: Failed to create context!\n");
2095
groupDestroyCairoLayer (s, layer);
2099
groupClearCairoLayer (layer);
1546
ChangeTabAnimationDirection direction)
1548
CompWindow *w, *oldTopTab;
1549
GroupSelection *group;
1560
if (!group || group->tabbingState != NoTabbing)
1563
if (group->changeState == NoTabChange && group->topTab == topTab)
1566
if (group->changeState != NoTabChange && group->nextTopTab == topTab)
1569
oldTopTab = group->topTab ? group->topTab->window : NULL;
1571
if (group->changeState != NoTabChange)
1572
group->nextDirection = direction;
1573
else if (direction == RotateLeft)
1574
group->changeAnimationDirection = 1;
1575
else if (direction == RotateRight)
1576
group->changeAnimationDirection = -1;
1579
int distanceOld = 0, distanceNew = 0;
1580
GroupTabBarSlot *slot;
1583
for (slot = group->tabBar->slots; slot && (slot != group->topTab);
1584
slot = slot->next, distanceOld++);
1586
for (slot = group->tabBar->slots; slot && (slot != topTab);
1587
slot = slot->next, distanceNew++);
1589
if (distanceNew < distanceOld)
1590
group->changeAnimationDirection = 1; /*left */
1592
group->changeAnimationDirection = -1; /* right */
1594
/* check if the opposite direction is shorter */
1595
if (abs (distanceNew - distanceOld) > (group->tabBar->nSlots / 2))
1596
group->changeAnimationDirection *= -1;
1599
if (group->changeState != NoTabChange)
1601
if (group->prevTopTab == topTab)
1603
/* Reverse animation. */
1604
GroupTabBarSlot *tmp = group->topTab;
1605
group->topTab = group->prevTopTab;
1606
group->prevTopTab = tmp;
1608
group->changeAnimationDirection *= -1;
1609
group->changeAnimationTime =
1610
groupGetChangeAnimationTime (w->screen) * 500 -
1611
group->changeAnimationTime;
1612
group->changeState = (group->changeState == TabChangeOldOut) ?
1613
TabChangeNewIn : TabChangeOldOut;
1615
group->nextTopTab = NULL;
1618
group->nextTopTab = topTab;
1622
group->topTab = topTab;
1624
groupRenderWindowTitle (group);
1625
groupRenderTopTabHighlight (group);
1626
addWindowDamage (w);
1629
if (topTab != group->nextTopTab)
1631
groupSetWindowVisibility (w, TRUE);
1636
GROUP_SCREEN (w->screen);
1638
dx = WIN_CENTER_X (oldTopTab) - WIN_CENTER_X (w);
1639
dy = WIN_CENTER_Y (oldTopTab) - WIN_CENTER_Y (w);
1642
moveWindow (w, dx, dy, FALSE, TRUE);
1643
syncWindowPosition (w);
1647
if (HAS_PREV_TOP_WIN (group))
1649
/* we use only the half time here -
1650
the second half will be PaintFadeOut */
1651
group->changeAnimationTime =
1652
groupGetChangeAnimationTime (w->screen) * 500;
1653
groupTabChangeActivateEvent (w->screen, TRUE);
1654
group->changeState = TabChangeOldOut;
1658
/* No window to do animation with. */
1659
if (HAS_TOP_WIN (group))
1660
group->prevTopTab = group->topTab;
1662
group->prevTopTab = NULL;
2141
groupRecalcTabBarPos(GroupSelection *group, int middleX, int minX1, int maxX2)
1707
groupRecalcTabBarPos (GroupSelection *group,
2143
GroupTabBarSlot *slot;
2146
Bool isDraggedSlotGroup = FALSE;
2147
int space, barWidth;
2149
int tabsWidth = 0, tabsHeight = 0;
2153
if (!HAS_TOP_WIN (group) || !group->tabBar)
2156
GROUP_SCREEN (group->screen);
2158
bar = group->tabBar;
2159
topTab = TOP_TAB (group);
2160
space = groupGetThumbSpace (group->screen);
2162
/* calculate the space which the tabs need */
2163
for (slot = bar->slots; slot; slot = slot->next)
2165
if (slot == gs->draggedSlot && gs->dragged)
2167
isDraggedSlotGroup = TRUE;
2171
tabsWidth += (slot->region->extents.x2 - slot->region->extents.x1);
2172
if ((slot->region->extents.y2 - slot->region->extents.y1) > tabsHeight)
2173
tabsHeight = slot->region->extents.y2 - slot->region->extents.y1;
2176
/* just a little work-a-round for first call */
2177
thumbSize = groupGetThumbSize (group->screen);
2178
if (bar->nSlots && tabsWidth <= 0)
2181
tabsWidth = thumbSize * bar->nSlots;
2183
if (bar->nSlots && tabsHeight < thumbSize)
2185
/* we need to do the standard height too */
2186
tabsHeight = thumbSize;
2189
if (isDraggedSlotGroup)
2190
tabsWidth -= thumbSize;
2193
barWidth = space * (bar->nSlots + 1) + tabsWidth;
1712
GroupTabBarSlot *slot;
1715
Bool isDraggedSlotGroup = FALSE;
1716
int space, barWidth;
1718
int tabsWidth = 0, tabsHeight = 0;
1722
if (!HAS_TOP_WIN (group) || !group->tabBar)
1725
GROUP_SCREEN (group->screen);
1727
bar = group->tabBar;
1728
topTab = TOP_TAB (group);
1729
space = groupGetThumbSpace (group->screen);
1731
/* calculate the space which the tabs need */
1732
for (slot = bar->slots; slot; slot = slot->next)
1734
if (slot == gs->draggedSlot && gs->dragged)
1736
isDraggedSlotGroup = TRUE;
1740
tabsWidth += (slot->region->extents.x2 - slot->region->extents.x1);
1741
if ((slot->region->extents.y2 - slot->region->extents.y1) > tabsHeight)
1742
tabsHeight = slot->region->extents.y2 - slot->region->extents.y1;
1745
/* just a little work-a-round for first call
1746
FIXME: remove this! */
1747
thumbSize = groupGetThumbSize (group->screen);
1748
if (bar->nSlots && tabsWidth <= 0)
1751
tabsWidth = thumbSize * bar->nSlots;
1753
if (bar->nSlots && tabsHeight < thumbSize)
1755
/* we need to do the standard height too */
1756
tabsHeight = thumbSize;
2195
1759
if (isDraggedSlotGroup)
2197
/* 1 tab is missing, so we have 1 less border */
2201
if (maxX2 - minX1 < barWidth)
2202
box.x = (maxX2 + minX1) / 2 - barWidth / 2;
2203
else if (middleX - barWidth / 2 < minX1)
2205
else if (middleX + barWidth / 2 > maxX2)
2206
box.x = maxX2 - barWidth;
2208
box.x = middleX - barWidth / 2;
2210
box.y = WIN_Y (topTab);
2211
box.width = barWidth;
2212
box.height = space * 2 + tabsHeight;
2214
groupResizeTabBarRegion (group, &box, TRUE);
2216
/* recalc every slot region */
2218
for (slot = bar->slots; slot; slot = slot->next)
2220
if (slot == gs->draggedSlot && gs->dragged)
2223
groupRecalcSlotPos (slot, currentSlot);
2224
XOffsetRegion (slot->region,
2225
bar->region->extents.x1,
2226
bar->region->extents.y1);
2228
slot->springX = (slot->region->extents.x1 +
2229
slot->region->extents.x2) / 2;
2231
slot->msSinceLastMove = 0;
2236
bar->leftSpringX = box.x;
2237
bar->rightSpringX = box.x + box.width;
2239
bar->rightSpeed = 0;
2242
bar->rightMsSinceLastMove = 0;
2243
bar->leftMsSinceLastMove = 0;
1760
tabsWidth -= thumbSize;
1763
barWidth = space * (bar->nSlots + 1) + tabsWidth;
1765
if (isDraggedSlotGroup)
1767
/* 1 tab is missing, so we have 1 less border */
1771
if (maxX2 - minX1 < barWidth)
1772
box.x = (maxX2 + minX1) / 2 - barWidth / 2;
1773
else if (middleX - barWidth / 2 < minX1)
1775
else if (middleX + barWidth / 2 > maxX2)
1776
box.x = maxX2 - barWidth;
1778
box.x = middleX - barWidth / 2;
1780
box.y = WIN_Y (topTab);
1781
box.width = barWidth;
1782
box.height = space * 2 + tabsHeight;
1784
groupResizeTabBarRegion (group, &box, TRUE);
1786
/* recalc every slot region */
1788
for (slot = bar->slots; slot; slot = slot->next)
1790
if (slot == gs->draggedSlot && gs->dragged)
1793
groupRecalcSlotPos (slot, currentSlot);
1794
XOffsetRegion (slot->region,
1795
bar->region->extents.x1,
1796
bar->region->extents.y1);
1798
slot->springX = (slot->region->extents.x1 +
1799
slot->region->extents.x2) / 2;
1801
slot->msSinceLastMove = 0;
1806
bar->leftSpringX = box.x;
1807
bar->rightSpringX = box.x + box.width;
1809
bar->rightSpeed = 0;
1812
bar->rightMsSinceLastMove = 0;
1813
bar->leftMsSinceLastMove = 0;
2247
1817
groupDamageTabBarRegion (GroupSelection *group)
2251
reg.rects = ®.extents;
2254
/* we use 15 pixels as damage buffer here, as there is a 10 pixel wide
2255
border around the selected slot which also needs to be damaged
2256
properly - however the best way would be if slot->region was
2257
sized including the border */
1821
reg.rects = ®.extents;
1824
/* we use 15 pixels as damage buffer here, as there is a 10 pixel wide
1825
border around the selected slot which also needs to be damaged
1826
properly - however the best way would be if slot->region was
1827
sized including the border */
2259
1829
#define DAMAGE_BUFFER 20
2261
reg.extents = group->tabBar->region->extents;
1831
reg.extents = group->tabBar->region->extents;
2263
if (group->tabBar->slots)
2265
reg.extents.x1 = MIN (reg.extents.x1,
2266
group->tabBar->slots->region->extents.x1);
2267
reg.extents.y1 = MIN (reg.extents.y1,
2268
group->tabBar->slots->region->extents.y1);
2269
reg.extents.x2 = MAX (reg.extents.x2,
2270
group->tabBar->revSlots->region->extents.x2);
2271
reg.extents.y2 = MAX (reg.extents.y2,
2272
group->tabBar->revSlots->region->extents.y2);
1833
if (group->tabBar->slots)
1835
reg.extents.x1 = MIN (reg.extents.x1,
1836
group->tabBar->slots->region->extents.x1);
1837
reg.extents.y1 = MIN (reg.extents.y1,
1838
group->tabBar->slots->region->extents.y1);
1839
reg.extents.x2 = MAX (reg.extents.x2,
1840
group->tabBar->revSlots->region->extents.x2);
1841
reg.extents.y2 = MAX (reg.extents.y2,
1842
group->tabBar->revSlots->region->extents.y2);
2275
1845
reg.extents.x1 -= DAMAGE_BUFFER;
2276
1846
reg.extents.y1 -= DAMAGE_BUFFER;
2277
1847
reg.extents.x2 += DAMAGE_BUFFER;
2278
1848
reg.extents.y2 += DAMAGE_BUFFER;
2280
damageScreenRegion (group->screen, ®);
1850
damageScreenRegion (group->screen, ®);
2284
1854
groupMoveTabBarRegion (GroupSelection *group,
2289
groupDamageTabBarRegion (group);
2291
XOffsetRegion (group->tabBar->region, dx, dy);
2294
XMoveWindow (group->screen->display->display,
2295
group->inputPrevention,
2296
group->tabBar->leftSpringX,
2297
group->tabBar->region->extents.y1);
2299
groupDamageTabBarRegion (group);
1859
groupDamageTabBarRegion (group);
1861
XOffsetRegion (group->tabBar->region, dx, dy);
1864
XMoveWindow (group->screen->display->display,
1865
group->inputPrevention,
1866
group->tabBar->leftSpringX,
1867
group->tabBar->region->extents.y1);
1869
groupDamageTabBarRegion (group);
2303
1873
groupResizeTabBarRegion (GroupSelection *group,
2309
groupDamageTabBarRegion (group);
2311
oldWidth = group->tabBar->region->extents.x2 -
2312
group->tabBar->region->extents.x1;
2314
if (group->tabBar->bgLayer && oldWidth != box->width && syncIPW)
2316
group->tabBar->bgLayer =
2317
groupRebuildCairoLayer (group->screen,
2318
group->tabBar->bgLayer,
2320
groupGetThumbSpace (group->screen) +
2321
groupGetThumbSize (group->screen),
2323
groupRenderTabBarBackground (group);
2325
/* invalidate old width */
2326
group->tabBar->oldWidth = 0;
2329
EMPTY_REGION (group->tabBar->region);
2330
XUnionRectWithRegion (box, group->tabBar->region, group->tabBar->region);
2338
xwc.width = box->width;
2339
xwc.height = box->height;
2341
xwc.stack_mode = Above;
2342
xwc.sibling = HAS_TOP_WIN (group) ? TOP_TAB (group)->id : None;
2344
XConfigureWindow (group->screen->display->display,
2345
group->inputPrevention,
2346
CWSibling | CWStackMode | CWX | CWY |
2351
groupDamageTabBarRegion (group);
1879
groupDamageTabBarRegion (group);
1881
oldWidth = group->tabBar->region->extents.x2 -
1882
group->tabBar->region->extents.x1;
1884
if (group->tabBar->bgLayer && oldWidth != box->width && syncIPW)
1886
group->tabBar->bgLayer =
1887
groupRebuildCairoLayer (group->screen,
1888
group->tabBar->bgLayer,
1890
groupGetThumbSpace (group->screen) +
1891
groupGetThumbSize (group->screen),
1893
groupRenderTabBarBackground (group);
1895
/* invalidate old width */
1896
group->tabBar->oldWidth = 0;
1899
EMPTY_REGION (group->tabBar->region);
1900
XUnionRectWithRegion (box, group->tabBar->region, group->tabBar->region);
1908
xwc.width = box->width;
1909
xwc.height = box->height;
1911
xwc.stack_mode = Above;
1912
xwc.sibling = HAS_TOP_WIN (group) ? TOP_TAB (group)->id : None;
1914
XConfigureWindow (group->screen->display->display,
1915
group->inputPrevention,
1916
CWSibling | CWStackMode | CWX | CWY |
1921
groupDamageTabBarRegion (group);
2475
2045
groupUnhookTabBarSlot (GroupTabBar *bar,
2476
GroupTabBarSlot *slot,
2046
GroupTabBarSlot *slot,
2479
GroupTabBarSlot *prev = slot->prev;
2480
GroupTabBarSlot *next = slot->next;
2481
CompWindow *w = slot->window;
2493
bar->revSlots = prev;
2499
if (IS_TOP_TAB (w, gw->group) && !temporary)
2502
groupChangeTab (next, RotateRight);
2504
groupChangeTab (prev, RotateLeft);
2505
else if (gw->group->nWins == 1)
2506
gw->group->topTab = NULL;
2508
if (groupGetUntabOnClose (w->screen))
2509
groupUntabGroup (gw->group);
2512
if (IS_PREV_TOP_TAB (w, gw->group) && !temporary)
2513
gw->group->prevTopTab = NULL;
2515
if (slot == bar->hoveredSlot)
2516
bar->hoveredSlot = NULL;
2518
if (slot == bar->textSlot)
2520
bar->textSlot = NULL;
2524
if (bar->textLayer->state == PaintFadeIn ||
2525
bar->textLayer->state == PaintOn)
2527
bar->textLayer->animationTime =
2528
(groupGetFadeTextTime (w->screen) * 1000) -
2529
bar->textLayer->animationTime;
2530
bar->textLayer->state = PaintFadeOut;
2535
/* Moving bar->region->extents.x1 / x2 as minX1 / maxX2 will work,
2536
because the tab-bar got thiner now, so
2537
(bar->region->extents.x1 + bar->region->extents.x2) / 2
2538
Won't cause the new x1 / x2 to be outside the original region. */
2539
groupRecalcTabBarPos (gw->group,
2540
(bar->region->extents.x1 +
2541
bar->region->extents.x2) / 2,
2542
bar->region->extents.x1, bar->region->extents.x2);
2049
GroupTabBarSlot *tempSlot;
2050
GroupTabBarSlot *prev = slot->prev;
2051
GroupTabBarSlot *next = slot->next;
2052
CompWindow *w = slot->window;
2053
CompScreen *s = w->screen;
2054
GroupSelection *group;
2060
/* check if slot is not already unhooked */
2061
for (tempSlot = bar->slots; tempSlot; tempSlot = tempSlot->next)
2062
if (tempSlot == slot)
2076
bar->revSlots = prev;
2084
if (IS_PREV_TOP_TAB (w, group))
2085
group->prevTopTab = NULL;
2086
if (IS_TOP_TAB (w, group))
2088
group->topTab = NULL;
2091
groupChangeTab (next, RotateRight);
2093
groupChangeTab (prev, RotateLeft);
2095
if (groupGetUntabOnClose (s))
2096
groupUntabGroup (group);
2100
if (slot == bar->hoveredSlot)
2101
bar->hoveredSlot = NULL;
2103
if (slot == bar->textSlot)
2105
bar->textSlot = NULL;
2109
if (bar->textLayer->state == PaintFadeIn ||
2110
bar->textLayer->state == PaintOn)
2112
bar->textLayer->animationTime =
2113
(groupGetFadeTextTime (s) * 1000) -
2114
bar->textLayer->animationTime;
2115
bar->textLayer->state = PaintFadeOut;
2120
/* Moving bar->region->extents.x1 / x2 as minX1 / maxX2 will work,
2121
because the tab-bar got thiner now, so
2122
(bar->region->extents.x1 + bar->region->extents.x2) / 2
2123
Won't cause the new x1 / x2 to be outside the original region. */
2124
groupRecalcTabBarPos (group,
2125
(bar->region->extents.x1 +
2126
bar->region->extents.x2) / 2,
2127
bar->region->extents.x1,
2128
bar->region->extents.x2);
2550
2136
groupDeleteTabBarSlot (GroupTabBar *bar,
2551
GroupTabBarSlot *slot)
2137
GroupTabBarSlot *slot)
2553
CompWindow *w = slot->window;
2556
GROUP_SCREEN (w->screen);
2558
groupUnhookTabBarSlot (bar, slot, FALSE);
2561
XDestroyRegion (slot->region);
2563
if (slot == gs->draggedSlot)
2565
gs->draggedSlot = NULL;
2566
gs->dragged = FALSE;
2568
if (gs->grabState == ScreenGrabTabDrag)
2569
groupGrabScreen (w->screen, ScreenGrabNone);
2573
groupUpdateWindowProperty (w);
2139
CompWindow *w = slot->window;
2142
GROUP_SCREEN (w->screen);
2144
groupUnhookTabBarSlot (bar, slot, FALSE);
2147
XDestroyRegion (slot->region);
2149
if (slot == gs->draggedSlot)
2151
gs->draggedSlot = NULL;
2152
gs->dragged = FALSE;
2154
if (gs->grabState == ScreenGrabTabDrag)
2155
groupGrabScreen (w->screen, ScreenGrabNone);
2159
groupUpdateWindowProperty (w);
2578
2164
* groupCreateSlot
2581
void groupCreateSlot(GroupSelection *group, CompWindow *w)
2167
void groupCreateSlot (GroupSelection *group,
2583
GroupTabBarSlot *slot;
2590
slot = malloc (sizeof (GroupTabBarSlot));
2593
slot->region = XCreateRegion ();
2595
groupInsertTabBarSlot (group->tabBar, slot);
2597
groupUpdateWindowProperty (w);
2170
GroupTabBarSlot *slot;
2177
slot = malloc (sizeof (GroupTabBarSlot));
2183
slot->region = XCreateRegion ();
2185
groupInsertTabBarSlot (group->tabBar, slot);
2187
groupUpdateWindowProperty (w);
2600
#define SPRING_K groupGetDragSpringK(s)
2601
#define FRICTION groupGetDragFriction(s)
2602
#define SIZE groupGetThumbSize(s)
2603
#define BORDER groupGetBorderRadius(s)
2190
#define SPRING_K groupGetDragSpringK(s)
2191
#define FRICTION groupGetDragFriction(s)
2192
#define SIZE groupGetThumbSize(s)
2193
#define BORDER groupGetBorderRadius(s)
2604
2194
#define Y_START_MOVE groupGetDragYDistance(s)
2605
#define SPEED_LIMIT groupGetDragSpeedLimit(s)
2195
#define SPEED_LIMIT groupGetDragSpeedLimit(s)
2608
2198
* groupSpringForce
2628
2218
groupDraggedSlotForce (CompScreen *s,
2632
/* The dragged slot will make the slot move, to get
2633
DnD animations (slots will make room for the newly inserted slot).
2634
As the dragged slot is closer to the slot, it will put
2635
more force on the slot, causing it to make room for the dragged slot...
2636
But if the dragged slot gets too close to the slot, they are
2637
going to be reordered soon, so the force will get lower.
2639
If the dragged slot is in the other side of the slot,
2640
it will have to make force in the opposite direction.
2642
So we the needed funtion is an odd function that goes
2643
up at first, and down after that.
2644
Sinus is a function like that... :)
2646
The maximum is got when x = (x1 + x2) / 2,
2647
in this case: x = SIZE + BORDER.
2648
Because of that, for x = SIZE + BORDER,
2649
we get a force of SPRING_K * (SIZE + BORDER) / 2.
2650
That equals to the force we get from the the spring.
2651
This way, the slot won't move when its distance from
2652
the dragged slot is SIZE + BORDER (which is the default
2653
distance between slots).
2656
/* The maximum value */
2657
float a = SPRING_K * (SIZE + BORDER) / 2;
2658
/* This will make distanceX == 2 * (SIZE + BORDER) to get 0,
2659
and distanceX == (SIZE + BORDER) to get the maximum. */
2660
float b = PI / (2 * SIZE + 2 * BORDER);
2662
/* If there is some distance between the slots in the y axis,
2663
the slot should get less force... For this, we change max
2664
to a lower value, using a simple linear function. */
2666
if (distanceY < Y_START_MOVE)
2667
a *= 1.0f - (float)distanceY / Y_START_MOVE;
2671
if (abs (distanceX) < 2 * (SIZE + BORDER))
2672
return a * sin (b * distanceX);
2222
/* The dragged slot will make the slot move, to get
2223
DnD animations (slots will make room for the newly inserted slot).
2224
As the dragged slot is closer to the slot, it will put
2225
more force on the slot, causing it to make room for the dragged slot...
2226
But if the dragged slot gets too close to the slot, they are
2227
going to be reordered soon, so the force will get lower.
2229
If the dragged slot is in the other side of the slot,
2230
it will have to make force in the opposite direction.
2232
So we the needed funtion is an odd function that goes
2233
up at first, and down after that.
2234
Sinus is a function like that... :)
2236
The maximum is got when x = (x1 + x2) / 2,
2237
in this case: x = SIZE + BORDER.
2238
Because of that, for x = SIZE + BORDER,
2239
we get a force of SPRING_K * (SIZE + BORDER) / 2.
2240
That equals to the force we get from the the spring.
2241
This way, the slot won't move when its distance from
2242
the dragged slot is SIZE + BORDER (which is the default
2243
distance between slots).
2246
/* The maximum value */
2247
float a = SPRING_K * (SIZE + BORDER) / 2;
2248
/* This will make distanceX == 2 * (SIZE + BORDER) to get 0,
2249
and distanceX == (SIZE + BORDER) to get the maximum. */
2250
float b = PI / (2 * SIZE + 2 * BORDER);
2252
/* If there is some distance between the slots in the y axis,
2253
the slot should get less force... For this, we change max
2254
to a lower value, using a simple linear function. */
2256
if (distanceY < Y_START_MOVE)
2257
a *= 1.0f - (float)distanceY / Y_START_MOVE;
2261
if (abs (distanceX) < 2 * (SIZE + BORDER))
2262
return a * sin (b * distanceX);
2712
2302
groupApplyForces (CompScreen *s,
2714
GroupTabBarSlot *draggedSlot)
2304
GroupTabBarSlot *draggedSlot)
2716
GroupTabBarSlot *slot, *slot2;
2717
int centerX, centerY;
2718
int draggedCenterX, draggedCenterY;
2724
groupGetDrawOffsetForSlot (draggedSlot, &vx, &vy);
2726
draggedCenterX = ((draggedSlot->region->extents.x1 +
2727
draggedSlot->region->extents.x2) / 2) + vx;
2728
draggedCenterY = ((draggedSlot->region->extents.y1 +
2729
draggedSlot->region->extents.y2) / 2) + vy;
2737
bar->leftSpeed += groupSpringForce(s,
2738
bar->region->extents.x1,
2740
bar->rightSpeed += groupSpringForce(s,
2741
bar->region->extents.x2,
2746
int leftForce, rightForce;
2748
leftForce = groupDraggedSlotForce(s,
2749
bar->region->extents.x1 -
2750
SIZE / 2 - draggedCenterX,
2751
abs ((bar->region->extents.y1 +
2752
bar->region->extents.y2) / 2 -
2755
rightForce = groupDraggedSlotForce (s,
2756
bar->region->extents.x2 +
2757
SIZE / 2 - draggedCenterX,
2758
abs ((bar->region->extents.y1 +
2759
bar->region->extents.y2) / 2 -
2763
bar->leftSpeed += leftForce;
2765
bar->rightSpeed += rightForce;
2768
for (slot = bar->slots; slot; slot = slot->next)
2770
centerX = (slot->region->extents.x1 + slot->region->extents.x2) / 2;
2771
centerY = (slot->region->extents.y1 + slot->region->extents.y2) / 2;
2773
slot->speed += groupSpringForce (s, centerX, slot->springX);
2775
if (draggedSlot && draggedSlot != slot)
2777
int draggedSlotForce;
2779
groupDraggedSlotForce(s, centerX - draggedCenterX,
2780
abs (centerY - draggedCenterY));
2782
slot->speed += draggedSlotForce;
2785
if (draggedSlotForce < 0)
2788
bar->leftSpeed += draggedSlotForce;
2790
else if (draggedSlotForce > 0)
2793
bar->rightSpeed += draggedSlotForce;
2798
if (slot2 != draggedSlot)
2799
slot2->speed += draggedSlotForce;
2801
slot2 = (draggedSlotForce < 0) ? slot2->prev : slot2->next;
2806
for (slot = bar->slots; slot; slot = slot->next)
2808
groupApplyFriction (s, &slot->speed);
2809
groupApplySpeedLimit (s, &slot->speed);
2812
groupApplyFriction (s, &bar->leftSpeed);
2813
groupApplySpeedLimit (s, &bar->leftSpeed);
2815
groupApplyFriction (s, &bar->rightSpeed);
2816
groupApplySpeedLimit (s, &bar->rightSpeed);
2306
GroupTabBarSlot *slot, *slot2;
2307
int centerX, centerY;
2308
int draggedCenterX, draggedCenterY;
2314
groupGetDrawOffsetForSlot (draggedSlot, &vx, &vy);
2316
draggedCenterX = ((draggedSlot->region->extents.x1 +
2317
draggedSlot->region->extents.x2) / 2) + vx;
2318
draggedCenterY = ((draggedSlot->region->extents.y1 +
2319
draggedSlot->region->extents.y2) / 2) + vy;
2327
bar->leftSpeed += groupSpringForce(s,
2328
bar->region->extents.x1,
2330
bar->rightSpeed += groupSpringForce(s,
2331
bar->region->extents.x2,
2336
int leftForce, rightForce;
2338
leftForce = groupDraggedSlotForce(s,
2339
bar->region->extents.x1 -
2340
SIZE / 2 - draggedCenterX,
2341
abs ((bar->region->extents.y1 +
2342
bar->region->extents.y2) / 2 -
2345
rightForce = groupDraggedSlotForce (s,
2346
bar->region->extents.x2 +
2347
SIZE / 2 - draggedCenterX,
2348
abs ((bar->region->extents.y1 +
2349
bar->region->extents.y2) / 2 -
2353
bar->leftSpeed += leftForce;
2355
bar->rightSpeed += rightForce;
2358
for (slot = bar->slots; slot; slot = slot->next)
2360
centerX = (slot->region->extents.x1 + slot->region->extents.x2) / 2;
2361
centerY = (slot->region->extents.y1 + slot->region->extents.y2) / 2;
2363
slot->speed += groupSpringForce (s, centerX, slot->springX);
2365
if (draggedSlot && draggedSlot != slot)
2367
int draggedSlotForce;
2369
groupDraggedSlotForce(s, centerX - draggedCenterX,
2370
abs (centerY - draggedCenterY));
2372
slot->speed += draggedSlotForce;
2375
if (draggedSlotForce < 0)
2378
bar->leftSpeed += draggedSlotForce;
2380
else if (draggedSlotForce > 0)
2383
bar->rightSpeed += draggedSlotForce;
2388
if (slot2 != draggedSlot)
2389
slot2->speed += draggedSlotForce;
2391
slot2 = (draggedSlotForce < 0) ? slot2->prev : slot2->next;
2396
for (slot = bar->slots; slot; slot = slot->next)
2398
groupApplyFriction (s, &slot->speed);
2399
groupApplySpeedLimit (s, &slot->speed);
2402
groupApplyFriction (s, &bar->leftSpeed);
2403
groupApplySpeedLimit (s, &bar->leftSpeed);
2405
groupApplyFriction (s, &bar->rightSpeed);
2406
groupApplySpeedLimit (s, &bar->rightSpeed);
2824
2414
groupApplySpeeds (CompScreen *s,
2825
GroupSelection *group,
2826
int msSinceLastRepaint)
2415
GroupSelection *group,
2416
int msSinceLastRepaint)
2828
GroupTabBar *bar = group->tabBar;
2829
GroupTabBarSlot *slot;
2832
Bool updateTabBar = FALSE;
2834
box.x = bar->region->extents.x1;
2835
box.y = bar->region->extents.y1;
2836
box.width = bar->region->extents.x2 - bar->region->extents.x1;
2837
box.height = bar->region->extents.y2 - bar->region->extents.y1;
2839
bar->leftMsSinceLastMove += msSinceLastRepaint;
2840
bar->rightMsSinceLastMove += msSinceLastRepaint;
2843
move = bar->leftSpeed * bar->leftMsSinceLastMove / 1000;
2849
bar->leftMsSinceLastMove = 0;
2850
updateTabBar = TRUE;
2852
else if (bar->leftSpeed == 0 &&
2853
bar->region->extents.x1 != bar->leftSpringX &&
2854
(SPRING_K * abs (bar->region->extents.x1 - bar->leftSpringX) <
2857
/* Friction is preventing from the left border to get
2858
to its original position. */
2859
box.x += bar->leftSpringX - bar->region->extents.x1;
2860
box.width -= bar->leftSpringX - bar->region->extents.x1;
2862
bar->leftMsSinceLastMove = 0;
2863
updateTabBar = TRUE;
2865
else if (bar->leftSpeed == 0)
2866
bar->leftMsSinceLastMove = 0;
2869
move = bar->rightSpeed * bar->rightMsSinceLastMove / 1000;
2874
bar->rightMsSinceLastMove = 0;
2875
updateTabBar = TRUE;
2877
else if (bar->rightSpeed == 0 &&
2878
bar->region->extents.x2 != bar->rightSpringX &&
2879
(SPRING_K * abs (bar->region->extents.x2 - bar->rightSpringX) <
2882
/* Friction is preventing from the right border to get
2883
to its original position. */
2884
box.width += bar->leftSpringX - bar->region->extents.x1;
2886
bar->leftMsSinceLastMove = 0;
2887
updateTabBar = TRUE;
2889
else if (bar->rightSpeed == 0)
2890
bar->rightMsSinceLastMove = 0;
2893
groupResizeTabBarRegion (group, &box, FALSE);
2895
for (slot = bar->slots; slot; slot = slot->next)
2899
slot->msSinceLastMove += msSinceLastRepaint;
2900
move = slot->speed * slot->msSinceLastMove / 1000;
2901
slotCenter = (slot->region->extents.x1 +
2902
slot->region->extents.x2) / 2;
2906
XOffsetRegion (slot->region, move, 0);
2907
slot->msSinceLastMove = 0;
2909
else if (slot->speed == 0 &&
2910
slotCenter != slot->springX &&
2911
SPRING_K * abs (slotCenter - slot->springX) < FRICTION)
2913
/* Friction is preventing from the slot to get
2914
to its original position. */
2916
XOffsetRegion (slot->region, slot->springX - slotCenter, 0);
2917
slot->msSinceLastMove = 0;
2919
else if (slot->speed == 0)
2920
slot->msSinceLastMove = 0;
2418
GroupTabBar *bar = group->tabBar;
2419
GroupTabBarSlot *slot;
2422
Bool updateTabBar = FALSE;
2424
box.x = bar->region->extents.x1;
2425
box.y = bar->region->extents.y1;
2426
box.width = bar->region->extents.x2 - bar->region->extents.x1;
2427
box.height = bar->region->extents.y2 - bar->region->extents.y1;
2429
bar->leftMsSinceLastMove += msSinceLastRepaint;
2430
bar->rightMsSinceLastMove += msSinceLastRepaint;
2433
move = bar->leftSpeed * bar->leftMsSinceLastMove / 1000;
2439
bar->leftMsSinceLastMove = 0;
2440
updateTabBar = TRUE;
2442
else if (bar->leftSpeed == 0 &&
2443
bar->region->extents.x1 != bar->leftSpringX &&
2444
(SPRING_K * abs (bar->region->extents.x1 - bar->leftSpringX) <
2447
/* Friction is preventing from the left border to get
2448
to its original position. */
2449
box.x += bar->leftSpringX - bar->region->extents.x1;
2450
box.width -= bar->leftSpringX - bar->region->extents.x1;
2452
bar->leftMsSinceLastMove = 0;
2453
updateTabBar = TRUE;
2455
else if (bar->leftSpeed == 0)
2456
bar->leftMsSinceLastMove = 0;
2459
move = bar->rightSpeed * bar->rightMsSinceLastMove / 1000;
2464
bar->rightMsSinceLastMove = 0;
2465
updateTabBar = TRUE;
2467
else if (bar->rightSpeed == 0 &&
2468
bar->region->extents.x2 != bar->rightSpringX &&
2469
(SPRING_K * abs (bar->region->extents.x2 - bar->rightSpringX) <
2472
/* Friction is preventing from the right border to get
2473
to its original position. */
2474
box.width += bar->leftSpringX - bar->region->extents.x1;
2476
bar->leftMsSinceLastMove = 0;
2477
updateTabBar = TRUE;
2479
else if (bar->rightSpeed == 0)
2480
bar->rightMsSinceLastMove = 0;
2483
groupResizeTabBarRegion (group, &box, FALSE);
2485
for (slot = bar->slots; slot; slot = slot->next)
2489
slot->msSinceLastMove += msSinceLastRepaint;
2490
move = slot->speed * slot->msSinceLastMove / 1000;
2491
slotCenter = (slot->region->extents.x1 +
2492
slot->region->extents.x2) / 2;
2496
XOffsetRegion (slot->region, move, 0);
2497
slot->msSinceLastMove = 0;
2499
else if (slot->speed == 0 &&
2500
slotCenter != slot->springX &&
2501
SPRING_K * abs (slotCenter - slot->springX) < FRICTION)
2503
/* Friction is preventing from the slot to get
2504
to its original position. */
2506
XOffsetRegion (slot->region, slot->springX - slotCenter, 0);
2507
slot->msSinceLastMove = 0;
2509
else if (slot->speed == 0)
2510
slot->msSinceLastMove = 0;