2025-02-09 23:08:39 +01:00
/ * *
2025-02-09 23:10:52 +01:00
* V - Shell ( Vertical Workspaces )
2025-02-09 23:08:39 +01:00
* workspacesView . js
2025-02-09 23:10:52 +01:00
*
2025-02-09 23:08:39 +01:00
* @ author GdH < G - dH @ github . com >
* @ copyright 2022 - 2023
* @ license GPL - 3.0
*
* /
'use strict' ;
const { GObject , Clutter , Meta , St } = imports . gi ;
const Main = imports . ui . main ;
const Util = imports . misc . util ;
const WorkspacesView = imports . ui . workspacesView ;
2025-02-09 23:10:52 +01:00
// first reference to constant defined using const in other module returns undefined, the SecondaryMonitorDisplay const will remain empty and unused
const SecondaryMonitorDisplay = WorkspacesView . SecondaryMonitorDisplay ;
2025-02-09 23:08:39 +01:00
const ControlsState = imports . ui . overviewControls . ControlsState ;
const FitMode = imports . ui . workspacesView . FitMode ;
const SIDE _CONTROLS _ANIMATION _TIME = imports . ui . overview . ANIMATION _TIME ;
const Me = imports . misc . extensionUtils . getCurrentExtension ( ) ;
2025-02-09 23:10:52 +01:00
const SEARCH _WINDOWS _PREFIX = Me . imports . lib . windowSearchProvider . prefix ;
const SEARCH _RECENT _FILES _PREFIX = Me . imports . lib . recentFilesSearchProvider . prefix ;
2025-02-09 23:08:39 +01:00
2025-02-09 23:10:52 +01:00
const _Util = Me . imports . lib . util ;
2025-02-09 23:08:39 +01:00
let _overrides ;
let opt ;
function update ( reset = false ) {
2025-02-09 23:10:52 +01:00
opt = Me . imports . lib . settings . opt ;
opt . DESKTOP _CUBE _ENABLED = Main . extensionManager . _enabledExtensions . includes ( 'desktop-cube@schneegans.github.com' ) ;
const cubeSupported = opt . DESKTOP _CUBE _ENABLED && ! opt . ORIENTATION && ! opt . OVERVIEW _MODE ;
// if desktop cube extension is enabled while V-Shell is loaded, removeAll() would override its code
if ( _overrides && ! cubeSupported ) {
2025-02-09 23:08:39 +01:00
_overrides . removeAll ( ) ;
global . workspace _manager . override _workspace _layout ( Meta . DisplayCorner . TOPLEFT , false , 1 , - 1 ) ;
}
if ( reset ) {
_overrides = null ;
opt = null ;
return ;
}
_overrides = new _Util . Overrides ( ) ;
2025-02-09 23:10:52 +01:00
if ( ! cubeSupported )
_overrides . addOverride ( 'WorkspacesView' , WorkspacesView . WorkspacesView . prototype , WorkspacesViewCommon ) ;
2025-02-09 23:08:39 +01:00
_overrides . addOverride ( 'WorkspacesDisplay' , WorkspacesView . WorkspacesDisplay . prototype , WorkspacesDisplay ) ;
2025-02-09 23:10:52 +01:00
_overrides . addOverride ( 'ExtraWorkspaceView' , WorkspacesView . ExtraWorkspaceView . prototype , ExtraWorkspaceView ) ;
2025-02-09 23:08:39 +01:00
if ( opt . ORIENTATION ) {
// switch internal workspace orientation in GS
global . workspace _manager . override _workspace _layout ( Meta . DisplayCorner . TOPLEFT , false , - 1 , 1 ) ;
_overrides . addOverride ( 'SecondaryMonitorDisplay' , WorkspacesView . SecondaryMonitorDisplay . prototype , SecondaryMonitorDisplayVertical ) ;
} else {
_overrides . addOverride ( 'SecondaryMonitorDisplay' , WorkspacesView . SecondaryMonitorDisplay . prototype , SecondaryMonitorDisplayHorizontal ) ;
}
}
2025-02-09 23:10:52 +01:00
const WorkspacesViewCommon = {
_getFirstFitSingleWorkspaceBox ( box , spacing , vertical ) {
2025-02-09 23:08:39 +01:00
let [ width , height ] = box . get _size ( ) ;
const [ workspace ] = this . _workspaces ;
const rtl = this . text _direction === Clutter . TextDirection . RTL ;
const adj = this . _scrollAdjustment ;
const currentWorkspace = vertical || ! rtl
? adj . value : adj . upper - adj . value - 1 ;
// Single fit mode implies centered too
let [ x1 , y1 ] = box . get _origin ( ) ;
2025-02-09 23:10:52 +01:00
const [ , workspaceWidth ] = workspace ? workspace . get _preferred _width ( Math . floor ( height ) ) : [ 0 , width ] ;
const [ , workspaceHeight ] = workspace ? workspace . get _preferred _height ( workspaceWidth ) : [ 0 , height ] ;
2025-02-09 23:08:39 +01:00
if ( vertical ) {
x1 += ( width - workspaceWidth ) / 2 ;
y1 -= currentWorkspace * ( workspaceHeight + spacing ) ;
} else {
x1 += ( width - workspaceWidth ) / 2 ;
x1 -= currentWorkspace * ( workspaceWidth + spacing ) ;
}
2025-02-09 23:10:52 +01:00
const fitSingleBox = new Clutter . ActorBox ( { x1 , y1 } ) ;
2025-02-09 23:08:39 +01:00
fitSingleBox . set _size ( workspaceWidth , workspaceHeight ) ;
return fitSingleBox ;
} ,
// set spacing between ws previews
2025-02-09 23:10:52 +01:00
_getSpacing ( box , fitMode , vertical ) {
2025-02-09 23:08:39 +01:00
const [ width , height ] = box . get _size ( ) ;
const [ workspace ] = this . _workspaces ;
2025-02-09 23:10:52 +01:00
if ( ! workspace )
return 0 ;
2025-02-09 23:08:39 +01:00
let availableSpace ;
let workspaceSize ;
if ( vertical ) {
[ , workspaceSize ] = workspace . get _preferred _height ( width ) ;
availableSpace = height ;
} else {
[ , workspaceSize ] = workspace . get _preferred _width ( height ) ;
availableSpace = width ;
}
const spacing = ( availableSpace - workspaceSize * 0.4 ) * ( 1 - fitMode ) ;
const { scaleFactor } = St . ThemeContext . get _for _stage ( global . stage ) ;
return Math . clamp ( spacing ,
opt . WORKSPACE _MIN _SPACING * scaleFactor ,
opt . WORKSPACE _MAX _SPACING * scaleFactor ) ;
} ,
// this function has duplicate in OverviewControls so we use one function for both to avoid issues with syncing them
2025-02-09 23:10:52 +01:00
_getFitModeForState ( state ) {
2025-02-09 23:08:39 +01:00
return _getFitModeForState ( state ) ;
} ,
// normal view 0, spread windows 1
2025-02-09 23:10:52 +01:00
_getWorkspaceModeForOverviewState ( state ) {
2025-02-09 23:08:39 +01:00
switch ( state ) {
case ControlsState . HIDDEN :
return 0 ;
case ControlsState . WINDOW _PICKER :
return opt . WORKSPACE _MODE ;
case ControlsState . APP _GRID :
2025-02-09 23:10:52 +01:00
return ( this . _monitorIndex !== global . display . get _primary _monitor ( ) || ! opt . WS _ANIMATION ) && ! opt . OVERVIEW _MODE ? 1 : 0 ;
2025-02-09 23:08:39 +01:00
}
return 0 ;
} ,
2025-02-09 23:10:52 +01:00
_updateVisibility ( ) {
// replaced in _updateWorkspacesState
/ * l e t w o r k s p a c e M a n a g e r = g l o b a l . w o r k s p a c e _ m a n a g e r ;
2025-02-09 23:08:39 +01:00
let active = workspaceManager . get _active _workspace _index ( ) ;
const fitMode = this . _fitModeAdjustment . value ;
const singleFitMode = fitMode === FitMode . SINGLE ;
for ( let w = 0 ; w < this . _workspaces . length ; w ++ ) {
let workspace = this . _workspaces [ w ] ;
2025-02-09 23:10:52 +01:00
if ( this . _animating || this . _gestureActive || ! singleFitMode )
workspace . show ( ) ;
else
2025-02-09 23:08:39 +01:00
workspace . visible = Math . abs ( w - active ) <= opt . NUMBER _OF _VISIBLE _NEIGHBORS ;
2025-02-09 23:10:52 +01:00
} * /
2025-02-09 23:08:39 +01:00
} ,
// disable scaling and hide inactive workspaces
2025-02-09 23:10:52 +01:00
_updateWorkspacesState ( ) {
2025-02-09 23:08:39 +01:00
const adj = this . _scrollAdjustment ;
const fitMode = this . _fitModeAdjustment . value ;
let { initialState , finalState , progress , currentState } =
this . _overviewAdjustment . getStateTransitionParams ( ) ;
const workspaceMode = ( 1 - fitMode ) * Util . lerp (
this . _getWorkspaceModeForOverviewState ( initialState ) ,
this . _getWorkspaceModeForOverviewState ( finalState ) ,
progress ) ;
2025-02-09 23:10:52 +01:00
const primaryMonitor = Main . layoutManager . primaryMonitor . index ;
2025-02-09 23:08:39 +01:00
// define the transition values here to save time in each ws
let scaleX , scaleY ;
2025-02-09 23:10:52 +01:00
if ( opt . ORIENTATION ) { // vertical 1 / horizontal 0
2025-02-09 23:08:39 +01:00
scaleX = 1 ;
scaleY = 0.1 ;
} else {
scaleX = 0.1 ;
scaleY = 1 ;
}
2025-02-09 23:10:52 +01:00
const wsScrollProgress = adj . value % 1 ;
2025-02-09 23:08:39 +01:00
const secondaryMonitor = this . _monitorIndex !== global . display . get _primary _monitor ( ) ;
2025-02-09 23:10:52 +01:00
const blockSecondaryAppGrid = opt . OVERVIEW _MODE && currentState > 1 ;
2025-02-09 23:08:39 +01:00
// Hide inactive workspaces
this . _workspaces . forEach ( ( w , index ) => {
if ( ! ( blockSecondaryAppGrid && secondaryMonitor ) )
w . stateAdjustment . value = workspaceMode ;
const distanceToCurrentWorkspace = Math . abs ( adj . value - index ) ;
const scaleProgress = 1 - Math . clamp ( distanceToCurrentWorkspace , 0 , 1 ) ;
// if we disable workspaces that we can't or don't need to see, transition animations will be noticeably smoother
// only the current ws needs to be visible during overview transition animations
// and only current and adjacent ws when switching ws
2025-02-09 23:10:52 +01:00
w . visible = ( this . _animating && wsScrollProgress && distanceToCurrentWorkspace <= ( opt . NUMBER _OF _VISIBLE _NEIGHBORS + 1 ) ) || scaleProgress === 1 ||
( opt . WORKSPACE _MAX _SPACING > 340 && distanceToCurrentWorkspace <= opt . NUMBER _OF _VISIBLE _NEIGHBORS && currentState === ControlsState . WINDOW _PICKER ) ||
( this . _monitorIndex !== primaryMonitor && distanceToCurrentWorkspace <= opt . NUMBER _OF _VISIBLE _NEIGHBORS ) || ( ! opt . WS _ANIMATION && distanceToCurrentWorkspace < opt . NUMBER _OF _VISIBLE _NEIGHBORS ) ||
( opt . WORKSPACE _MAX _SPACING < 340 && distanceToCurrentWorkspace <= opt . NUMBER _OF _VISIBLE _NEIGHBORS && currentState <= ControlsState . WINDOW _PICKER &&
( ( initialState < ControlsState . APP _GRID && finalState < ControlsState . APP _GRID ) )
) ;
// after transition from APP_GRID to WINDOW_PICKER state,
// adjacent workspaces are hidden and we need them to show up
// make them visible during animation can impact smoothness of the animation
// so we show them after the animation finished, scaling animation will make impression that they move in from outside the monitor
if ( ! w . visible && distanceToCurrentWorkspace === 1 && initialState === ControlsState . APP _GRID && currentState === ControlsState . WINDOW _PICKER ) {
w . scale _x = scaleX ;
w . scale _y = scaleY ;
w . visible = true ;
w . ease ( {
duration : 100 ,
scale _x : 1 ,
scale _y : 1 ,
mode : Clutter . AnimationMode . EASE _OUT _QUAD ,
} ) ;
} else if ( ! w . visible && distanceToCurrentWorkspace <= opt . NUMBER _OF _VISIBLE _NEIGHBORS && currentState === ControlsState . WINDOW _PICKER ) {
w . set ( {
scale _x : 1 ,
scale _y : 1 ,
} ) ;
2025-02-09 23:08:39 +01:00
}
// force ws preview bg corner radiuses where GS doesn't do it
2025-02-09 23:10:52 +01:00
if ( opt . SHOW _WS _PREVIEW _BG && opt . OVERVIEW _MODE === 1 && distanceToCurrentWorkspace < 2 )
2025-02-09 23:08:39 +01:00
w . _background . _updateBorderRadius ( Math . min ( 1 , w . _overviewAdjustment . value ) ) ;
2025-02-09 23:10:52 +01:00
2025-02-09 23:08:39 +01:00
// hide workspace background
2025-02-09 23:10:52 +01:00
if ( ! opt . SHOW _WS _PREVIEW _BG && w . _background . opacity )
2025-02-09 23:08:39 +01:00
w . _background . opacity = 0 ;
} ) ;
2025-02-09 23:10:52 +01:00
} ,
} ;
2025-02-09 23:08:39 +01:00
// SecondaryMonitorDisplay Vertical
2025-02-09 23:10:52 +01:00
const SecondaryMonitorDisplayVertical = {
_getThumbnailParamsForState ( state ) {
2025-02-09 23:08:39 +01:00
2025-02-09 23:10:52 +01:00
let opacity , scale , translationX ;
2025-02-09 23:08:39 +01:00
switch ( state ) {
case ControlsState . HIDDEN :
opacity = 255 ;
scale = 1 ;
2025-02-09 23:10:52 +01:00
translationX = 0 ;
if ( ! Main . layoutManager . _startingUp && ( ! opt . SHOW _WS _PREVIEW _BG || opt . OVERVIEW _MODE2 ) )
translationX = this . _thumbnails . width * ( opt . SEC _WS _TMB _LEFT ? - 1 : 1 ) ;
2025-02-09 23:08:39 +01:00
break ;
case ControlsState . WINDOW _PICKER :
case ControlsState . APP _GRID :
opacity = 255 ;
scale = 1 ;
2025-02-09 23:10:52 +01:00
translationX = 0 ;
2025-02-09 23:08:39 +01:00
break ;
default :
opacity = 255 ;
scale = 1 ;
2025-02-09 23:10:52 +01:00
translationX = 0 ;
2025-02-09 23:08:39 +01:00
break ;
}
2025-02-09 23:10:52 +01:00
return { opacity , scale , translationX } ;
2025-02-09 23:08:39 +01:00
} ,
2025-02-09 23:10:52 +01:00
_getThumbnailsWidth ( box , spacing ) {
if ( opt . SEC _WS _TMB _HIDDEN )
2025-02-09 23:08:39 +01:00
return 0 ;
const [ width , height ] = box . get _size ( ) ;
const { expandFraction } = this . _thumbnails ;
const [ , thumbnailsWidth ] = this . _thumbnails . get _preferred _custom _width ( height - 2 * spacing ) ;
2025-02-09 23:10:52 +01:00
let scaledWidth ;
if ( opt . SEC _WS _PREVIEW _SHIFT && ! opt . PANEL _DISABLED )
scaledWidth = ( ( height - Main . panel . height ) * opt . SEC _MAX _THUMBNAIL _SCALE ) * ( width / height ) ;
else
scaledWidth = width * opt . SEC _MAX _THUMBNAIL _SCALE ;
2025-02-09 23:08:39 +01:00
return Math . min (
thumbnailsWidth * expandFraction ,
2025-02-09 23:10:52 +01:00
Math . round ( scaledWidth ) ) ;
2025-02-09 23:08:39 +01:00
} ,
2025-02-09 23:10:52 +01:00
_getWorkspacesBoxForState ( state , box , padding , thumbnailsWidth , spacing ) {
// const { ControlsState } = OverviewControls;
2025-02-09 23:08:39 +01:00
const workspaceBox = box . copy ( ) ;
const [ width , height ] = workspaceBox . get _size ( ) ;
2025-02-09 23:10:52 +01:00
let wWidth , wHeight , wsbX , wsbY , offset , yShift ;
2025-02-09 23:08:39 +01:00
switch ( state ) {
case ControlsState . HIDDEN :
break ;
case ControlsState . WINDOW _PICKER :
case ControlsState . APP _GRID :
2025-02-09 23:10:52 +01:00
if ( opt . OVERVIEW _MODE2 && ! opt . WORKSPACE _MODE )
2025-02-09 23:08:39 +01:00
break ;
2025-02-09 23:10:52 +01:00
yShift = 0 ;
if ( opt . SEC _WS _PREVIEW _SHIFT && ! opt . PANEL _DISABLED ) {
if ( opt . PANEL _POSITION _TOP )
yShift = Main . panel . height ;
else
yShift = - Main . panel . height ;
2025-02-09 23:08:39 +01:00
}
2025-02-09 23:10:52 +01:00
wWidth = width - thumbnailsWidth - 5 * spacing ;
wHeight = Math . min ( wWidth / ( width / height ) - Math . abs ( yShift ) , height - 4 * spacing ) ;
wWidth = Math . round ( wWidth * opt . SEC _WS _PREVIEW _SCALE ) ;
wHeight = Math . round ( wHeight * opt . SEC _WS _PREVIEW _SCALE ) ;
2025-02-09 23:08:39 +01:00
2025-02-09 23:10:52 +01:00
offset = Math . round ( width - thumbnailsWidth - wWidth ) / 2 ;
if ( opt . SEC _WS _TMB _LEFT )
2025-02-09 23:08:39 +01:00
wsbX = thumbnailsWidth + offset ;
2025-02-09 23:10:52 +01:00
else
2025-02-09 23:08:39 +01:00
wsbX = offset ;
2025-02-09 23:10:52 +01:00
wsbY = Math . round ( ( height - wHeight - Math . abs ( yShift ) ) / 2 + yShift ) ;
2025-02-09 23:08:39 +01:00
workspaceBox . set _origin ( wsbX , wsbY ) ;
workspaceBox . set _size ( wWidth , wHeight ) ;
break ;
}
return workspaceBox ;
} ,
2025-02-09 23:10:52 +01:00
vfunc _allocate ( box ) {
2025-02-09 23:08:39 +01:00
this . set _allocation ( box ) ;
const themeNode = this . get _theme _node ( ) ;
const contentBox = themeNode . get _content _box ( box ) ;
const [ width , height ] = contentBox . get _size ( ) ;
const { expandFraction } = this . _thumbnails ;
const spacing = themeNode . get _length ( 'spacing' ) * expandFraction ;
const padding = Math . round ( 0.1 * height ) ;
let thumbnailsWidth = this . _getThumbnailsWidth ( contentBox , spacing ) ;
let [ , thumbnailsHeight ] = this . _thumbnails . get _preferred _custom _height ( thumbnailsWidth ) ;
thumbnailsHeight = Math . min ( thumbnailsHeight , height - 2 * spacing ) ;
2025-02-09 23:10:52 +01:00
this . _thumbnails . visible = ! opt . SEC _WS _TMB _HIDDEN ;
2025-02-09 23:08:39 +01:00
if ( this . _thumbnails . visible ) {
let wsTmbX ;
if ( opt . SEC _WS _TMB _LEFT ) { // left
wsTmbX = Math . round ( spacing / 4 ) ;
this . _thumbnails . _positionLeft = true ;
} else {
wsTmbX = Math . round ( width - spacing / 4 - thumbnailsWidth ) ;
this . _thumbnails . _positionLeft = false ;
}
const childBox = new Clutter . ActorBox ( ) ;
const availSpace = height - thumbnailsHeight - 2 * spacing ;
let wsTmbY = availSpace / 2 ;
wsTmbY -= opt . SEC _WS _TMB _POSITION _ADJUSTMENT * wsTmbY - spacing ;
childBox . set _origin ( Math . round ( wsTmbX ) , Math . round ( wsTmbY ) ) ;
childBox . set _size ( thumbnailsWidth , thumbnailsHeight ) ;
this . _thumbnails . allocate ( childBox ) ;
}
const {
currentState , initialState , finalState , transitioning , progress ,
} = this . _overviewAdjustment . getStateTransitionParams ( ) ;
let workspacesBox ;
const workspaceParams = [ contentBox , padding , thumbnailsWidth , spacing ] ;
if ( ! transitioning ) {
workspacesBox =
this . _getWorkspacesBoxForState ( currentState , ... workspaceParams ) ;
} else {
const initialBox =
this . _getWorkspacesBoxForState ( initialState , ... workspaceParams ) ;
const finalBox =
this . _getWorkspacesBoxForState ( finalState , ... workspaceParams ) ;
workspacesBox = initialBox . interpolate ( finalBox , progress ) ;
}
this . _workspacesView . allocate ( workspacesBox ) ;
} ,
2025-02-09 23:10:52 +01:00
_updateThumbnailVisibility ( ) {
if ( opt . OVERVIEW _MODE2 )
2025-02-09 23:08:39 +01:00
this . set _child _above _sibling ( this . _thumbnails , null ) ;
2025-02-09 23:10:52 +01:00
const visible = ! opt . SEC _WS _TMB _HIDDEN ;
2025-02-09 23:08:39 +01:00
if ( this . _thumbnails . visible === visible )
return ;
this . _thumbnails . show ( ) ;
this . _updateThumbnailParams ( ) ;
this . _thumbnails . ease _property ( 'expand-fraction' , visible ? 1 : 0 , {
duration : SIDE _CONTROLS _ANIMATION _TIME ,
mode : Clutter . AnimationMode . EASE _OUT _QUAD ,
onComplete : ( ) => {
this . _thumbnails . visible = visible ;
this . _thumbnails . _indicator . visible = visible ;
} ,
} ) ;
} ,
2025-02-09 23:10:52 +01:00
_updateThumbnailParams ( ) {
if ( opt . SEC _WS _TMB _HIDDEN )
return ;
2025-02-09 23:08:39 +01:00
// workaround for upstream bug - secondary thumbnails boxes don't catch 'showing' signal on the shell startup and don't populate the box with thumbnails
// the tmbBox contents is also destroyed when overview state adjustment gets above 1 when swiping gesture from window picker to app grid
2025-02-09 23:10:52 +01:00
if ( ! this . _thumbnails . _thumbnails . length )
2025-02-09 23:08:39 +01:00
this . _thumbnails . _createThumbnails ( ) ;
const { initialState , finalState , progress } =
this . _overviewAdjustment . getStateTransitionParams ( ) ;
const initialParams = this . _getThumbnailParamsForState ( initialState ) ;
const finalParams = this . _getThumbnailParamsForState ( finalState ) ;
2025-02-09 23:10:52 +01:00
/ * c o n s t o p a c i t y =
2025-02-09 23:08:39 +01:00
Util . lerp ( initialParams . opacity , finalParams . opacity , progress ) ;
const scale =
Util . lerp ( initialParams . scale , finalParams . scale , progress ) ; * /
// OVERVIEW_MODE 2 should animate dash and wsTmbBox only if WORKSPACE_MODE === 0 (windows not spread)
const animateOverviewMode2 = opt . OVERVIEW _MODE2 && ! ( finalState === 1 && opt . WORKSPACE _MODE ) ;
2025-02-09 23:10:52 +01:00
const translationX = ! Main . layoutManager . _startingUp && ( ( ! opt . SHOW _WS _PREVIEW _BG && ! opt . OVERVIEW _MODE2 ) || animateOverviewMode2 )
? Util . lerp ( initialParams . translationX , finalParams . translationX , progress )
2025-02-09 23:08:39 +01:00
: 0 ;
this . _thumbnails . set ( {
opacity : 255 ,
2025-02-09 23:10:52 +01:00
// scale_x: scale,
// scale_y: scale,
translation _x : translationX ,
2025-02-09 23:08:39 +01:00
} ) ;
} ,
2025-02-09 23:10:52 +01:00
_updateWorkspacesView ( ) {
2025-02-09 23:08:39 +01:00
if ( this . _workspacesView )
this . _workspacesView . destroy ( ) ;
if ( this . _settings . get _boolean ( 'workspaces-only-on-primary' ) ) {
2025-02-09 23:10:52 +01:00
opt . SEC _WS _TMB _HIDDEN = true ;
2025-02-09 23:08:39 +01:00
this . _workspacesView = new WorkspacesView . ExtraWorkspaceView (
this . _monitorIndex ,
this . _overviewAdjustment ) ;
} else {
2025-02-09 23:10:52 +01:00
opt . SEC _WS _TMB _HIDDEN = ! opt . SHOW _SEC _WS _TMB ;
2025-02-09 23:08:39 +01:00
this . _workspacesView = new WorkspacesView . WorkspacesView (
this . _monitorIndex ,
this . _controls ,
this . _scrollAdjustment ,
// Secondary monitors don't need FitMode.ALL since there is workspace switcher always visible
2025-02-09 23:10:52 +01:00
// this._fitModeAdjustment,
2025-02-09 23:08:39 +01:00
new St . Adjustment ( {
actor : this ,
2025-02-09 23:10:52 +01:00
value : 0 , // FitMode.SINGLE,
lower : 0 , // FitMode.SINGLE,
upper : 0 , // FitMode.SINGLE,
2025-02-09 23:08:39 +01:00
} ) ,
2025-02-09 23:10:52 +01:00
// secondaryOverviewAdjustment);
2025-02-09 23:08:39 +01:00
this . _overviewAdjustment ) ;
}
this . add _child ( this . _workspacesView ) ;
this . _thumbnails . opacity = 0 ;
2025-02-09 23:10:52 +01:00
} ,
} ;
2025-02-09 23:08:39 +01:00
// SecondaryMonitorDisplay Horizontal
2025-02-09 23:10:52 +01:00
const SecondaryMonitorDisplayHorizontal = {
_getThumbnailParamsForState ( state ) {
// const { ControlsState } = OverviewControls;
2025-02-09 23:08:39 +01:00
2025-02-09 23:10:52 +01:00
let opacity , scale , translationY ;
2025-02-09 23:08:39 +01:00
switch ( state ) {
case ControlsState . HIDDEN :
opacity = 255 ;
scale = 1 ;
2025-02-09 23:10:52 +01:00
translationY = 0 ;
if ( ! Main . layoutManager . _startingUp && ( ! opt . SHOW _WS _PREVIEW _BG || opt . OVERVIEW _MODE2 ) )
translationY = this . _thumbnails . height * ( opt . SEC _WS _TMB _TOP ? - 1 : 1 ) ;
2025-02-09 23:08:39 +01:00
break ;
case ControlsState . WINDOW _PICKER :
case ControlsState . APP _GRID :
opacity = 255 ;
scale = 1 ;
2025-02-09 23:10:52 +01:00
translationY = 0 ;
2025-02-09 23:08:39 +01:00
break ;
default :
opacity = 255 ;
scale = 1 ;
2025-02-09 23:10:52 +01:00
translationY = 0 ;
2025-02-09 23:08:39 +01:00
break ;
}
2025-02-09 23:10:52 +01:00
return { opacity , scale , translationY } ;
2025-02-09 23:08:39 +01:00
} ,
2025-02-09 23:10:52 +01:00
_getWorkspacesBoxForState ( state , box , padding , thumbnailsHeight , spacing ) {
// const { ControlsState } = OverviewControls;
2025-02-09 23:08:39 +01:00
const workspaceBox = box . copy ( ) ;
const [ width , height ] = workspaceBox . get _size ( ) ;
2025-02-09 23:10:52 +01:00
let wWidth , wHeight , wsbX , wsbY , offset , yShift ;
2025-02-09 23:08:39 +01:00
switch ( state ) {
case ControlsState . HIDDEN :
break ;
case ControlsState . WINDOW _PICKER :
case ControlsState . APP _GRID :
2025-02-09 23:10:52 +01:00
if ( opt . OVERVIEW _MODE2 && ! opt . WORKSPACE _MODE )
2025-02-09 23:08:39 +01:00
break ;
2025-02-09 23:10:52 +01:00
yShift = 0 ;
if ( opt . SEC _WS _PREVIEW _SHIFT && ! opt . PANEL _DISABLED ) {
if ( opt . PANEL _POSITION _TOP )
yShift = Main . panel . height ;
else
yShift = - Main . panel . height ;
2025-02-09 23:08:39 +01:00
}
2025-02-09 23:10:52 +01:00
wHeight = height - Math . abs ( yShift ) - ( thumbnailsHeight ? thumbnailsHeight + 4 * spacing : padding ) ;
wWidth = Math . min ( wHeight * ( width / height ) , width - 5 * spacing ) ;
wWidth = Math . round ( wWidth * opt . SEC _WS _PREVIEW _SCALE ) ;
wHeight = Math . round ( wHeight * opt . SEC _WS _PREVIEW _SCALE ) ;
2025-02-09 23:08:39 +01:00
2025-02-09 23:10:52 +01:00
offset = Math . round ( ( height - thumbnailsHeight - wHeight - Math . abs ( yShift ) ) / 2 ) ;
if ( opt . SEC _WS _TMB _TOP )
2025-02-09 23:08:39 +01:00
wsbY = thumbnailsHeight + offset ;
2025-02-09 23:10:52 +01:00
else
2025-02-09 23:08:39 +01:00
wsbY = offset ;
2025-02-09 23:10:52 +01:00
wsbY += yShift ;
wsbX = Math . round ( ( width - wWidth ) / 2 ) ;
2025-02-09 23:08:39 +01:00
workspaceBox . set _origin ( wsbX , wsbY ) ;
workspaceBox . set _size ( wWidth , wHeight ) ;
break ;
}
return workspaceBox ;
} ,
2025-02-09 23:10:52 +01:00
_getThumbnailsHeight ( box ) {
if ( opt . SEC _WS _TMB _HIDDEN )
2025-02-09 23:08:39 +01:00
return 0 ;
const [ width , height ] = box . get _size ( ) ;
const { expandFraction } = this . _thumbnails ;
const [ thumbnailsHeight ] = this . _thumbnails . get _preferred _height ( width ) ;
return Math . min (
thumbnailsHeight * expandFraction ,
2025-02-09 23:10:52 +01:00
height * opt . SEC _MAX _THUMBNAIL _SCALE ) ;
2025-02-09 23:08:39 +01:00
} ,
2025-02-09 23:10:52 +01:00
vfunc _allocate ( box ) {
2025-02-09 23:08:39 +01:00
this . set _allocation ( box ) ;
const themeNode = this . get _theme _node ( ) ;
const contentBox = themeNode . get _content _box ( box ) ;
const [ width , height ] = contentBox . get _size ( ) ;
const { expandFraction } = this . _thumbnails ;
const spacing = themeNode . get _length ( 'spacing' ) * expandFraction ;
const padding = Math . round ( 0.1 * height ) ;
let thumbnailsHeight = this . _getThumbnailsHeight ( contentBox ) ;
let [ , thumbnailsWidth ] = this . _thumbnails . get _preferred _custom _width ( thumbnailsHeight ) ;
thumbnailsWidth = Math . min ( thumbnailsWidth , width - 2 * spacing ) ;
2025-02-09 23:10:52 +01:00
this . _thumbnails . visible = ! opt . SEC _WS _TMB _HIDDEN ;
2025-02-09 23:08:39 +01:00
if ( this . _thumbnails . visible ) {
let wsTmbY ;
2025-02-09 23:10:52 +01:00
if ( opt . SEC _WS _TMB _TOP )
2025-02-09 23:08:39 +01:00
wsTmbY = Math . round ( spacing / 4 ) ;
2025-02-09 23:10:52 +01:00
else
2025-02-09 23:08:39 +01:00
wsTmbY = Math . round ( height - spacing / 4 - thumbnailsHeight ) ;
2025-02-09 23:10:52 +01:00
2025-02-09 23:08:39 +01:00
const childBox = new Clutter . ActorBox ( ) ;
const availSpace = width - thumbnailsWidth - 2 * spacing ;
let wsTmbX = availSpace / 2 ;
wsTmbX -= opt . SEC _WS _TMB _POSITION _ADJUSTMENT * wsTmbX - spacing ;
childBox . set _origin ( Math . round ( wsTmbX ) , Math . round ( wsTmbY ) ) ;
childBox . set _size ( thumbnailsWidth , thumbnailsHeight ) ;
this . _thumbnails . allocate ( childBox ) ;
}
const {
currentState , initialState , finalState , transitioning , progress ,
} = this . _overviewAdjustment . getStateTransitionParams ( ) ;
let workspacesBox ;
const workspaceParams = [ contentBox , padding , thumbnailsHeight , spacing ] ;
if ( ! transitioning ) {
workspacesBox =
this . _getWorkspacesBoxForState ( currentState , ... workspaceParams ) ;
} else {
const initialBox =
this . _getWorkspacesBoxForState ( initialState , ... workspaceParams ) ;
const finalBox =
this . _getWorkspacesBoxForState ( finalState , ... workspaceParams ) ;
workspacesBox = initialBox . interpolate ( finalBox , progress ) ;
}
this . _workspacesView . allocate ( workspacesBox ) ;
} ,
_updateThumbnailVisibility : SecondaryMonitorDisplayVertical . _updateThumbnailVisibility ,
2025-02-09 23:10:52 +01:00
_updateThumbnailParams ( ) {
if ( opt . SEC _WS _TMB _HIDDEN )
return ;
2025-02-09 23:08:39 +01:00
// workaround for upstream bug - secondary thumbnails boxes don't catch 'showing' signal on the shell startup and don't populate the box with thumbnails
// the tmbBox contents is also destroyed when overview state adjustment gets above 1 when swiping gesture from window picker to app grid
2025-02-09 23:10:52 +01:00
if ( ! this . _thumbnails . _thumbnails . length )
2025-02-09 23:08:39 +01:00
this . _thumbnails . _createThumbnails ( ) ;
const { initialState , finalState , progress } =
this . _overviewAdjustment . getStateTransitionParams ( ) ;
const initialParams = this . _getThumbnailParamsForState ( initialState ) ;
const finalParams = this . _getThumbnailParamsForState ( finalState ) ;
2025-02-09 23:10:52 +01:00
/ * c o n s t o p a c i t y =
2025-02-09 23:08:39 +01:00
Util . lerp ( initialParams . opacity , finalParams . opacity , progress ) ;
const scale =
Util . lerp ( initialParams . scale , finalParams . scale , progress ) ; * /
// OVERVIEW_MODE 2 should animate dash and wsTmbBox only if WORKSPACE_MODE === 0 (windows not spread)
const animateOverviewMode2 = opt . OVERVIEW _MODE2 && ! ( finalState === 1 && opt . WORKSPACE _MODE ) ;
2025-02-09 23:10:52 +01:00
const translationY = ! Main . layoutManager . _startingUp && ( ( ! opt . SHOW _WS _PREVIEW _BG && ! opt . OVERVIEW _MODE2 ) || animateOverviewMode2 )
? Util . lerp ( initialParams . translationY , finalParams . translationY , progress )
2025-02-09 23:08:39 +01:00
: 0 ;
this . _thumbnails . set ( {
opacity : 255 ,
2025-02-09 23:10:52 +01:00
// scale_x: scale,
// scale_y: scale,
translation _y : translationY ,
2025-02-09 23:08:39 +01:00
} ) ;
} ,
2025-02-09 23:10:52 +01:00
_updateWorkspacesView ( ) {
2025-02-09 23:08:39 +01:00
if ( this . _workspacesView )
this . _workspacesView . destroy ( ) ;
if ( this . _settings . get _boolean ( 'workspaces-only-on-primary' ) ) {
2025-02-09 23:10:52 +01:00
opt . SEC _WS _TMB _HIDDEN = true ;
2025-02-09 23:08:39 +01:00
this . _workspacesView = new WorkspacesView . ExtraWorkspaceView (
this . _monitorIndex ,
this . _overviewAdjustment ) ;
} else {
2025-02-09 23:10:52 +01:00
opt . SEC _WS _TMB _HIDDEN = ! opt . SHOW _SEC _WS _TMB ;
2025-02-09 23:08:39 +01:00
this . _workspacesView = new WorkspacesView . WorkspacesView (
this . _monitorIndex ,
this . _controls ,
this . _scrollAdjustment ,
// Secondary monitors don't need FitMode.ALL since there is workspace switcher always visible
2025-02-09 23:10:52 +01:00
// this._fitModeAdjustment,
2025-02-09 23:08:39 +01:00
new St . Adjustment ( {
actor : this ,
2025-02-09 23:10:52 +01:00
value : 0 , // FitMode.SINGLE,
lower : 0 , // FitMode.SINGLE,
upper : 0 , // FitMode.SINGLE,
2025-02-09 23:08:39 +01:00
} ) ,
2025-02-09 23:10:52 +01:00
// secondaryOverviewAdjustment);
2025-02-09 23:08:39 +01:00
this . _overviewAdjustment ) ;
}
this . add _child ( this . _workspacesView ) ;
this . _thumbnails . opacity = 0 ;
2025-02-09 23:10:52 +01:00
} ,
} ;
const ExtraWorkspaceView = {
_updateWorkspaceMode ( ) {
const overviewState = this . _overviewAdjustment . value ;
2025-02-09 23:08:39 +01:00
2025-02-09 23:10:52 +01:00
const progress = Math . clamp ( overviewState ,
ControlsState . HIDDEN ,
opt . OVERVIEW _MODE && ! opt . WORKSPACE _MODE ? ControlsState . HIDDEN : ControlsState . WINDOW _PICKER ) ;
this . _workspace . stateAdjustment . value = progress ;
// force ws preview bg corner radiuses where GS doesn't do it
if ( opt . SHOW _WS _PREVIEW _BG && opt . OVERVIEW _MODE === 1 )
this . _workspace . _background . _updateBorderRadius ( Math . min ( 1 , this . _workspace . _overviewAdjustment . value ) ) ;
// hide workspace background
if ( ! opt . SHOW _WS _PREVIEW _BG && this . _workspace . _background . opacity )
this . _workspace . _background . opacity = 0 ;
} ,
} ;
const WorkspacesDisplay = {
_updateWorkspacesViews ( ) {
2025-02-09 23:08:39 +01:00
for ( let i = 0 ; i < this . _workspacesViews . length ; i ++ )
this . _workspacesViews [ i ] . destroy ( ) ;
this . _primaryIndex = Main . layoutManager . primaryIndex ;
this . _workspacesViews = [ ] ;
let monitors = Main . layoutManager . monitors ;
for ( let i = 0 ; i < monitors . length ; i ++ ) {
let view ;
if ( i === this . _primaryIndex ) {
view = new WorkspacesView . WorkspacesView ( i ,
this . _controls ,
this . _scrollAdjustment ,
this . _fitModeAdjustment ,
this . _overviewAdjustment ) ;
view . visible = this . _primaryVisible ;
this . bind _property ( 'opacity' , view , 'opacity' , GObject . BindingFlags . SYNC _CREATE ) ;
this . add _child ( view ) ;
} else {
view = new WorkspacesView . SecondaryMonitorDisplay ( i ,
this . _controls ,
this . _scrollAdjustment ,
// Secondary monitors don't need FitMode.ALL since there is workspace switcher always visible
2025-02-09 23:10:52 +01:00
// this._fitModeAdjustment,
2025-02-09 23:08:39 +01:00
new St . Adjustment ( {
actor : this ,
2025-02-09 23:10:52 +01:00
value : 0 , // FitMode.SINGLE,
lower : 0 , // FitMode.SINGLE,
upper : 0 , // FitMode.SINGLE,
2025-02-09 23:08:39 +01:00
} ) ,
this . _overviewAdjustment ) ;
Main . layoutManager . overviewGroup . add _actor ( view ) ;
}
this . _workspacesViews . push ( view ) ;
}
} ,
2025-02-09 23:10:52 +01:00
_onScrollEvent ( actor , event ) {
2025-02-09 23:08:39 +01:00
if ( this . _swipeTracker . canHandleScrollEvent ( event ) )
return Clutter . EVENT _PROPAGATE ;
if ( ! this . mapped )
return Clutter . EVENT _PROPAGATE ;
if ( this . _workspacesOnlyOnPrimary &&
2025-02-09 23:10:52 +01:00
this . _getMonitorIndexForEvent ( event ) !== this . _primaryIndex )
2025-02-09 23:08:39 +01:00
return Clutter . EVENT _PROPAGATE ;
2025-02-09 23:10:52 +01:00
if ( opt . PANEL _MODE === 1 ) {
const panelBox = Main . layoutManager . panelBox ;
const [ , y ] = global . get _pointer ( ) ;
if ( y > panelBox . allocation . y1 && y < panelBox . allocation . y2 )
return Clutter . EVENT _STOP ;
}
2025-02-09 23:08:39 +01:00
2025-02-09 23:10:52 +01:00
if ( _Util . isShiftPressed ( ) ) {
let direction = _Util . getScrollDirection ( event ) ;
if ( direction === null || ( Date . now ( ) - this . _lastScrollTime ) < 150 )
return Clutter . EVENT _STOP ;
this . _lastScrollTime = Date . now ( ) ;
2025-02-09 23:08:39 +01:00
2025-02-09 23:10:52 +01:00
if ( direction === Clutter . ScrollDirection . UP )
2025-02-09 23:08:39 +01:00
direction = - 1 ;
2025-02-09 23:10:52 +01:00
else if ( direction === Clutter . ScrollDirection . DOWN )
2025-02-09 23:08:39 +01:00
direction = 1 ;
2025-02-09 23:10:52 +01:00
else
2025-02-09 23:08:39 +01:00
direction = 0 ;
2025-02-09 23:10:52 +01:00
2025-02-09 23:08:39 +01:00
if ( direction ) {
2025-02-09 23:10:52 +01:00
_Util . reorderWorkspace ( direction ) ;
2025-02-09 23:08:39 +01:00
// make all workspaces on primary monitor visible for case the new position is hidden
2025-02-09 23:10:52 +01:00
Main . overview . _overview . _controls . _workspacesDisplay . _workspacesViews [ 0 ] . _workspaces . forEach ( w => {
w . visible = true ;
} ) ;
2025-02-09 23:08:39 +01:00
return Clutter . EVENT _STOP ;
}
}
return Main . wm . handleWorkspaceScroll ( event ) ;
} ,
2025-02-09 23:10:52 +01:00
_onKeyPressEvent ( actor , event ) {
2025-02-09 23:08:39 +01:00
const symbol = event . get _key _symbol ( ) ;
2025-02-09 23:10:52 +01:00
/ * c o n s t { C o n t r o l s S t a t e } = O v e r v i e w C o n t r o l s ;
2025-02-09 23:08:39 +01:00
if ( this . _overviewAdjustment . value !== ControlsState . WINDOW _PICKER && symbol !== Clutter . KEY _space )
return Clutter . EVENT _PROPAGATE ; * /
2025-02-09 23:10:52 +01:00
/ * i f ( ! t h i s . r e a c t i v e )
return Clutter . EVENT _PROPAGATE ; * /
2025-02-09 23:08:39 +01:00
const { workspaceManager } = global ;
const vertical = workspaceManager . layout _rows === - 1 ;
const rtl = this . get _text _direction ( ) === Clutter . TextDirection . RTL ;
2025-02-09 23:10:52 +01:00
const state = this . _overviewAdjustment . value ;
2025-02-09 23:08:39 +01:00
let which ;
switch ( symbol ) {
2025-02-09 23:10:52 +01:00
case Clutter . KEY _Return :
case Clutter . KEY _KP _Enter :
if ( _Util . isCtrlPressed ( ) ) {
Main . ctrlAltTabManager . _items . forEach ( i => {
if ( i . sortGroup === 1 && i . name === 'Dash' )
Main . ctrlAltTabManager . focusGroup ( i ) ;
} ) ;
}
return Clutter . EVENT _STOP ;
2025-02-09 23:08:39 +01:00
case Clutter . KEY _Page _Up :
if ( vertical )
which = Meta . MotionDirection . UP ;
else if ( rtl )
which = Meta . MotionDirection . RIGHT ;
else
which = Meta . MotionDirection . LEFT ;
break ;
case Clutter . KEY _Page _Down :
if ( vertical )
which = Meta . MotionDirection . DOWN ;
else if ( rtl )
which = Meta . MotionDirection . LEFT ;
else
which = Meta . MotionDirection . RIGHT ;
break ;
case Clutter . KEY _Home :
which = 0 ;
break ;
case Clutter . KEY _End :
which = workspaceManager . n _workspaces - 1 ;
break ;
case Clutter . KEY _space :
2025-02-09 23:10:52 +01:00
if ( _Util . isCtrlPressed ( ) && _Util . isShiftPressed ( ) ) {
2025-02-09 23:08:39 +01:00
_Util . openPreferences ( ) ;
2025-02-09 23:10:52 +01:00
} else if ( _Util . isAltPressed ( ) ) {
Main . ctrlAltTabManager . _items . forEach ( i => {
if ( i . sortGroup === 1 && i . name === 'Dash' )
Main . ctrlAltTabManager . focusGroup ( i ) ;
} ) ;
} else if ( opt . RECENT _FILES _SEARCH _PROVIDER _ENABLED && _Util . isCtrlPressed ( ) ) {
2025-02-09 23:08:39 +01:00
_Util . activateSearchProvider ( SEARCH _RECENT _FILES _PREFIX ) ;
2025-02-09 23:10:52 +01:00
} else if ( opt . WINDOW _SEARCH _PROVIDER _ENABLED ) {
2025-02-09 23:08:39 +01:00
_Util . activateSearchProvider ( SEARCH _WINDOWS _PREFIX ) ;
}
2025-02-09 23:10:52 +01:00
2025-02-09 23:08:39 +01:00
return Clutter . EVENT _STOP ;
case Clutter . KEY _Down :
case Clutter . KEY _Left :
case Clutter . KEY _Right :
case Clutter . KEY _Up :
2025-02-09 23:10:52 +01:00
case Clutter . KEY _Tab :
2025-02-09 23:08:39 +01:00
if ( Main . overview . _overview . _controls . _searchController . searchActive ) {
Main . overview . searchEntry . grab _key _focus ( ) ;
2025-02-09 23:10:52 +01:00
} else if ( opt . OVERVIEW _MODE2 && ! opt . WORKSPACE _MODE && state === 1 ) {
// expose windows by "clicking" on ws thumbnail
// in this case overview stateAdjustment will be used for transition
Main . overview . _overview . controls . _thumbnailsBox . _activateThumbnailAtPoint ( 0 , 0 , global . get _current _time ( ) , true ) ;
Main . ctrlAltTabManager . _items . forEach ( i => {
if ( i . sortGroup === 1 && i . name === 'Windows' )
Main . ctrlAltTabManager . focusGroup ( i ) ;
} ) ;
} else if ( opt . OVERVIEW _MODE && ! opt . WORKSPACE _MODE && state === 1 ) {
// expose windows for OVERVIEW_MODE 1
const adjustment = this . _workspacesViews [ 0 ] . _workspaces [ global . workspace _manager . get _active _workspace ( ) . index ( ) ] . _background . _stateAdjustment ;
opt . WORKSPACE _MODE = 1 ;
_Util . exposeWindows ( adjustment , true ) ;
} else {
if ( state === 2 )
return Clutter . EVENT _PROPAGATE ;
Main . ctrlAltTabManager . _items . forEach ( i => {
if ( i . sortGroup === 1 && i . name === 'Windows' )
Main . ctrlAltTabManager . focusGroup ( i ) ;
} ) ;
2025-02-09 23:08:39 +01:00
}
2025-02-09 23:10:52 +01:00
2025-02-09 23:08:39 +01:00
return Clutter . EVENT _STOP ;
default :
return Clutter . EVENT _PROPAGATE ;
}
2025-02-09 23:10:52 +01:00
if ( state === 2 )
return Clutter . EVENT _PROPAGATE ;
2025-02-09 23:08:39 +01:00
let ws ;
if ( which < 0 )
// Negative workspace numbers are directions
ws = workspaceManager . get _active _workspace ( ) . get _neighbor ( which ) ;
else
// Otherwise it is a workspace index
ws = workspaceManager . get _workspace _by _index ( which ) ;
2025-02-09 23:10:52 +01:00
if ( _Util . isShiftPressed ( ) ) {
2025-02-09 23:08:39 +01:00
let direction ;
if ( which === Meta . MotionDirection . UP || which === Meta . MotionDirection . LEFT )
direction = - 1 ;
else if ( which === Meta . MotionDirection . DOWN || which === Meta . MotionDirection . RIGHT )
direction = 1 ;
if ( direction )
2025-02-09 23:10:52 +01:00
_Util . reorderWorkspace ( direction ) ;
2025-02-09 23:08:39 +01:00
// make all workspaces on primary monitor visible for case the new position is hidden
2025-02-09 23:10:52 +01:00
Main . overview . _overview . _controls . _workspacesDisplay . _workspacesViews [ 0 ] . _workspaces . forEach ( w => {
w . visible = true ;
} ) ;
return Clutter . EVENT _STOP ;
2025-02-09 23:08:39 +01:00
}
if ( ws )
Main . wm . actionMoveWorkspace ( ws ) ;
return Clutter . EVENT _STOP ;
} ,
2025-02-09 23:10:52 +01:00
} ;
2025-02-09 23:08:39 +01:00
// same copy of this function should be available in OverviewControls and WorkspacesView
function _getFitModeForState ( state ) {
switch ( state ) {
case ControlsState . HIDDEN :
case ControlsState . WINDOW _PICKER :
return FitMode . SINGLE ;
case ControlsState . APP _GRID :
if ( opt . WS _ANIMATION && opt . SHOW _WS _TMB )
return FitMode . ALL ;
else
return FitMode . SINGLE ;
default :
return FitMode . SINGLE ;
}
}