/******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2008, 2009 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "flipswitch.h" #include #include #include #include #include #include #include #include namespace KWin { KWIN_EFFECT( flipswitch, FlipSwitchEffect ) KWIN_EFFECT_SUPPORTED( flipswitch, FlipSwitchEffect::supported() ) FlipSwitchEffect::FlipSwitchEffect() : m_currentAnimationShape( TimeLine::EaseInOutCurve ) , m_active( false ) , m_start( false ) , m_stop( false ) , m_animation( false ) , m_hasKeyboardGrab( false ) , m_captionFrame( EffectFrame::Styled ) { reconfigure( ReconfigureAll ); // Caption frame m_captionFont.setBold( true ); m_captionFont.setPointSize( m_captionFont.pointSize() * 2 ); m_captionFrame.setFont( m_captionFont ); KActionCollection* actionCollection = new KActionCollection( this ); KAction* a = ( KAction* )actionCollection->addAction( "FlipSwitchCurrent" ); a->setText( i18n( "Toggle Flip Switch (Current desktop)" )); a->setGlobalShortcut( KShortcut(), KAction::ActiveShortcut ); m_shortcutCurrent = a->globalShortcut(); connect( a, SIGNAL( triggered(bool) ), this, SLOT( toggleActiveCurrent() )); connect( a, SIGNAL( globalShortcutChanged(QKeySequence) ), this, SLOT( globalShortcutChangedCurrent(QKeySequence))); KAction* b = ( KAction* )actionCollection->addAction( "FlipSwitchAll" ); b->setText( i18n( "Toggle Flip Switch (All desktops)" )); b->setGlobalShortcut( KShortcut(), KAction::ActiveShortcut ); m_shortcutAll = b->globalShortcut(); connect( b, SIGNAL( triggered(bool) ), this, SLOT( toggleActiveAllDesktops() )); connect( b, SIGNAL( globalShortcutChanged(QKeySequence) ), this, SLOT( globalShortcutChangedAll(QKeySequence))); } FlipSwitchEffect::~FlipSwitchEffect() { foreach( ElectricBorder border, m_borderActivate ) { effects->unreserveElectricBorder( border ); } foreach( ElectricBorder border, m_borderActivateAll ) { effects->unreserveElectricBorder( border ); } } bool FlipSwitchEffect::supported() { return effects->compositingType() == OpenGLCompositing; } void FlipSwitchEffect::reconfigure( ReconfigureFlags ) { KConfigGroup conf = effects->effectConfig( "FlipSwitch" ); foreach( ElectricBorder border, m_borderActivate ) { effects->unreserveElectricBorder( border ); } foreach( ElectricBorder border, m_borderActivateAll ) { effects->unreserveElectricBorder( border ); } m_borderActivate.clear(); m_borderActivateAll.clear(); QList borderList = QList(); borderList.append( int( ElectricNone ) ); borderList = conf.readEntry( "BorderActivate", borderList ); foreach( int i, borderList ) { m_borderActivate.append( ElectricBorder( i ) ); effects->reserveElectricBorder( ElectricBorder( i ) ); } borderList.clear(); borderList.append( int( ElectricNone ) ); borderList = conf.readEntry( "BorderActivateAll", borderList ); foreach( int i, borderList ) { m_borderActivateAll.append( ElectricBorder( i ) ); effects->reserveElectricBorder( ElectricBorder( i ) ); } m_tabbox = conf.readEntry( "TabBox", false ); float duration = animationTime( conf, "Duration", 200 ); m_timeLine.setDuration( duration ); m_startStopTimeLine.setDuration( duration ); m_angle = conf.readEntry( "Angle", 30 ); m_xPosition = float( conf.readEntry( "XPosition", 33 ))/100.0f; m_yPosition = float( conf.readEntry( "YPosition", 100 ))/100.0f; m_windowTitle = conf.readEntry( "WindowTitle", true ); } void FlipSwitchEffect::prePaintScreen( ScreenPrePaintData& data, int time ) { if( m_active ) { data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; if( m_start ) m_startStopTimeLine.addTime( time ); if( m_stop && m_scheduledDirections.isEmpty() ) m_startStopTimeLine.removeTime( time ); if( m_animation ) m_timeLine.addTime( time ); } effects->prePaintScreen( data, time ); } void FlipSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) { effects->paintScreen( mask, region, data ); if( m_active ) { EffectWindowList tempList; if( m_mode == TabboxMode ) tempList = effects->currentTabBoxWindowList(); else { // we have to setup the list // using stacking order directly is not possible // as not each window in stacking order is shown // TODO: store list instead of calculating in each frame? foreach( EffectWindow* w, effects->stackingOrder() ) { if( m_windows.contains( w ) ) tempList.append( w ); } } m_flipOrderedWindows.clear(); int index = tempList.indexOf( m_selectedWindow ); int tabIndex = index; if( m_mode == TabboxMode ) { foreach( SwitchingDirection direction, m_scheduledDirections ) { if( direction == DirectionBackward ) index++; else index--; if( index < 0 ) index = tempList.count() + index; if( index >= tempList.count() ) index = index % tempList.count(); } tabIndex = index; EffectWindow* w = NULL; if( !m_scheduledDirections.isEmpty() && m_scheduledDirections.head() == DirectionBackward ) { index--; if( index < 0 ) index = tempList.count() + index; w = tempList.at( index ); } for( int i=index-1; i>=0; i-- ) m_flipOrderedWindows.append(tempList.at( i )); for( int i=effects->currentTabBoxWindowList().count()-1; i>=index; i-- ) m_flipOrderedWindows.append(tempList.at( i )); if( w ) { m_flipOrderedWindows.removeAll( w ); m_flipOrderedWindows.append( w ); } } else { foreach( SwitchingDirection direction, m_scheduledDirections ) { if( direction == DirectionForward ) index++; else index--; if( index < 0 ) index = tempList.count() -1; if( index >= tempList.count() ) index = 0; } tabIndex = index; EffectWindow* w = NULL; if( !m_scheduledDirections.isEmpty() && m_scheduledDirections.head() == DirectionBackward ) { index++; if( index >= tempList.count() ) index = 0; } // sort from stacking order for( int i=index+1; inumScreens() > 1 ) { // unfortunatelly we have to change the projection matrix in dual screen mode QRect fullRect = effects->clientArea( FullArea, effects->activeScreen(), effects->currentDesktop() ); glMatrixMode( GL_PROJECTION ); glPushMatrix(); glLoadIdentity(); float fovy = 60.0f; float aspect = 1.0f; float zNear = 0.1f; float zFar = 100.0f; float ymax = zNear * tan( fovy * M_PI / 360.0f ); float ymin = -ymax; float xmin = ymin * aspect; float xmax = ymax * aspect; float xTranslate = 0.0; float yTranslate = 0.0; float xminFactor = 1.0; float xmaxFactor = 1.0; float yminFactor = 1.0; float ymaxFactor = 1.0; if( m_screenArea.x() == 0 && m_screenArea.width() != fullRect.width() ) { // horizontal layout: left screen xminFactor = (float)m_screenArea.width()/(float)fullRect.width(); xmaxFactor = ((float)fullRect.width()-(float)m_screenArea.width()*0.5f)/((float)fullRect.width()*0.5f); xTranslate = (float)fullRect.width()*0.5f-(float)m_screenArea.width()*0.5f; } if( m_screenArea.x() != 0 && m_screenArea.width() != fullRect.width() ) { // horizontal layout: right screen xminFactor = ((float)fullRect.width()-(float)m_screenArea.width()*0.5f)/((float)fullRect.width()*0.5f); xmaxFactor = (float)m_screenArea.width()/(float)fullRect.width(); xTranslate = (float)fullRect.width()*0.5f-(float)m_screenArea.width()*0.5f; } if( m_screenArea.y() == 0 && m_screenArea.height() != fullRect.height() ) { // vertical layout: top screen yminFactor = ((float)fullRect.height()-(float)m_screenArea.height()*0.5f)/((float)fullRect.height()*0.5f); ymaxFactor = (float)m_screenArea.height()/(float)fullRect.height(); yTranslate = (float)fullRect.height()*0.5f-(float)m_screenArea.height()*0.5f; } if( m_screenArea.y() != 0 && m_screenArea.height() != fullRect.height() ) { // vertical layout: bottom screen yminFactor = (float)m_screenArea.height()/(float)fullRect.height(); ymaxFactor = ((float)fullRect.height()-(float)m_screenArea.height()*0.5f)/((float)fullRect.height()*0.5f); yTranslate = (float)fullRect.height()*0.5f-(float)m_screenArea.height()*0.5f; } glFrustum( xmin*xminFactor, xmax*xmaxFactor, ymin*yminFactor, ymax*ymaxFactor, zNear, zFar ); glMatrixMode( GL_MODELVIEW ); glPushMatrix(); glTranslatef( xTranslate, yTranslate, 0.0 ); } int winMask = PAINT_WINDOW_TRANSFORMED | PAINT_WINDOW_TRANSLUCENT; RotationData rot; rot.axis = RotationData::YAxis; rot.angle = m_angle * m_startStopTimeLine.value(); // fade in/out one window at the end of the stack during animation if( m_animation && !m_scheduledDirections.isEmpty() ) { EffectWindow* w = m_flipOrderedWindows.last(); if( m_windows.contains( w ) ) { WindowPaintData data( w ); data.opacity = m_windows[ w ]->opacity; data.brightness = m_windows[ w ]->brightness; data.saturation = m_windows[ w ]->saturation; int distance = tempList.count() - 1; float zDistance = 500.0f; data.xTranslate -= (w->x() - m_screenArea.x() + data.xTranslate) * m_startStopTimeLine.value(); data.xTranslate += m_screenArea.width()*m_xPosition * m_startStopTimeLine.value(); data.yTranslate += (m_screenArea.y() + m_screenArea.height()*m_yPosition - ( w->y() + w->height() + data.yTranslate )) * m_startStopTimeLine.value(); data.xTranslate -= (m_screenArea.width()*0.25f) * distance * m_startStopTimeLine.value(); data.yTranslate -= (m_screenArea.height()*0.10f) * distance * m_startStopTimeLine.value(); data.zTranslate -= (zDistance * distance) * m_startStopTimeLine.value(); if( m_scheduledDirections.head() == DirectionForward ) data.opacity *= 0.8 * m_timeLine.value(); else data.opacity *= 0.8 * (1.0 - m_timeLine.value() ); if( effects->numScreens() > 1) { adjustWindowMultiScreen( w, data ); } data.rotation = &rot; effects->drawWindow( w, winMask, infiniteRegion(), data ); } } foreach( EffectWindow* w, m_flipOrderedWindows ) { if( !m_windows.contains( w ) ) continue; WindowPaintData data( w ); data.opacity = m_windows[ w ]->opacity; data.brightness = m_windows[ w ]->brightness; data.saturation = m_windows[ w ]->saturation; int windowIndex = tempList.indexOf( w ); int distance; if( m_mode == TabboxMode ) { if( windowIndex < tabIndex ) distance = tempList.count() - (tabIndex - windowIndex); else if( windowIndex > tabIndex) distance = windowIndex - tabIndex; else distance = 0; } else { distance = m_flipOrderedWindows.count() - m_flipOrderedWindows.indexOf( w ) - 1; if( !m_scheduledDirections.isEmpty() && m_scheduledDirections.head() == DirectionBackward ) { distance--; } } if( !m_scheduledDirections.isEmpty() && m_scheduledDirections.head() == DirectionBackward ) { if( w == m_flipOrderedWindows.last() ) { distance = -1; data.opacity *= m_timeLine.value(); } } float zDistance = 500.0f; data.xTranslate -= (w->x() - m_screenArea.x() + data.xTranslate) * m_startStopTimeLine.value(); data.xTranslate += m_screenArea.width()*m_xPosition * m_startStopTimeLine.value(); data.yTranslate += (m_screenArea.y() + m_screenArea.height()*m_yPosition - ( w->y() + w->height() + data.yTranslate )) * m_startStopTimeLine.value(); data.xTranslate -= (m_screenArea.width()*0.25f) * distance * m_startStopTimeLine.value(); data.yTranslate -= (m_screenArea.height()*0.10f) * distance * m_startStopTimeLine.value(); data.zTranslate -= (zDistance * distance) * m_startStopTimeLine.value(); if( m_animation && !m_scheduledDirections.isEmpty() ) { if( m_scheduledDirections.head() == DirectionForward ) { data.xTranslate += (m_screenArea.width()*0.25f) * m_timeLine.value(); data.yTranslate += (m_screenArea.height()*0.10f) * m_timeLine.value(); data.zTranslate += zDistance * m_timeLine.value(); if( distance == 0 ) data.opacity *= (1.0 - m_timeLine.value() ); } else { data.xTranslate -= (m_screenArea.width()*0.25f) * m_timeLine.value(); data.yTranslate -= (m_screenArea.height()*0.10f) * m_timeLine.value(); data.zTranslate -= zDistance * m_timeLine.value(); } } data.opacity *= (0.8 + 0.2 * (1.0 - m_startStopTimeLine.value())); if( effects->numScreens() > 1) { adjustWindowMultiScreen( w, data ); } data.rotation = &rot; effects->drawWindow( w, winMask, infiniteRegion(), data ); } if( effects->numScreens() > 1 ) { glPopMatrix(); // revert change of projection matrix glMatrixMode( GL_PROJECTION ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); } if( m_windowTitle ) { // Render the caption frame double opacity = 1.0; opacity = m_startStopTimeLine.value(); QPixmap iconPixmap = m_selectedWindow->icon(); if( m_start || m_stop ) { int alpha = 255.0f * m_startStopTimeLine.value(); QPixmap transparency = iconPixmap.copy( iconPixmap.rect() ); transparency.fill( QColor( 255, 255, 255, alpha )); iconPixmap.setAlphaChannel( transparency.alphaChannel() ); } m_captionFrame.setText( m_selectedWindow->caption() ); m_captionFrame.setIcon( iconPixmap ); m_captionFrame.render( region, opacity ); } } } void FlipSwitchEffect::postPaintScreen() { if( m_active ) { if( m_start && m_startStopTimeLine.value() == 1.0f ) { m_start = false; if( !m_scheduledDirections.isEmpty() ) { m_animation = true; m_timeLine.setProgress( 0.0f ); if( m_scheduledDirections.count() == 1 ) { m_currentAnimationShape = TimeLine::EaseOutCurve; m_timeLine.setCurveShape( m_currentAnimationShape ); } else { m_currentAnimationShape = TimeLine::LinearCurve; m_timeLine.setCurveShape( m_currentAnimationShape ); } } effects->addRepaintFull(); } if( m_stop && m_startStopTimeLine.value() == 0.0f ) { m_stop = false; m_active = false; m_captionFrame.free(); effects->setActiveFullScreenEffect( 0 ); effects->addRepaintFull(); qDeleteAll( m_windows ); m_windows.clear(); } if( m_animation && m_timeLine.value() == 1.0f ) { m_timeLine.setProgress( 0.0f ); m_scheduledDirections.dequeue(); if( m_scheduledDirections.isEmpty() ) { m_animation = false; effects->addRepaintFull(); } else { if( m_scheduledDirections.count() == 1 ) { if( m_stop ) m_currentAnimationShape = TimeLine::LinearCurve; else m_currentAnimationShape = TimeLine::EaseOutCurve; } else { m_currentAnimationShape = TimeLine::LinearCurve; } m_timeLine.setCurveShape( m_currentAnimationShape ); } } if( m_start || m_stop || m_animation ) effects->addRepaintFull(); } effects->postPaintScreen(); } void FlipSwitchEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) { if( m_active ) { if( m_windows.contains( w ) ) { data.setTransformed(); data.setTranslucent(); if( !w->isOnCurrentDesktop() ) w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); if( w->isMinimized() ) w->enablePainting( EffectWindow::PAINT_DISABLED_BY_MINIMIZE ); } else { if( ( m_start || m_stop ) && !w->isDesktop() && w->isOnCurrentDesktop() ) data.setTranslucent(); else if( !w->isDesktop() ) w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); } } effects->prePaintWindow( w, data, time ); } void FlipSwitchEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) { if( m_active ) { if( w->isDesktop() ) { // desktop is painted in normal way effects->paintWindow( w, mask, region, data ); return; } if( ( m_start || m_stop ) && !m_windows.contains( w ) ) { // fade out all windows not in window list data.opacity *= ( 1.0 - m_startStopTimeLine.value() ); effects->paintWindow( w, mask, region, data ); return; } m_windows[ w ]->opacity = data.opacity; m_windows[ w ]->brightness = data.brightness; m_windows[ w ]->saturation = data.saturation; // it's not nice but it removes flickering return; } else { effects->paintWindow( w, mask, region, data ); } } //************************************************************* // Tabbox handling //************************************************************* void FlipSwitchEffect::tabBoxAdded( int mode ) { if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this ) return; // only for windows mode if( m_tabbox && (!m_active || (m_active && m_stop)) && mode == TabBoxWindowsMode && !effects->currentTabBoxWindowList().isEmpty() ) { setActive( true, TabboxMode ); if( m_active ) effects->refTabBox(); } } void FlipSwitchEffect::tabBoxClosed() { if( m_active ) { setActive( false, TabboxMode ); effects->unrefTabBox(); } } void FlipSwitchEffect::tabBoxUpdated() { if( m_active && !m_stop ) { if( !effects->currentTabBoxWindowList().isEmpty() ) { // determine the switch direction if( m_selectedWindow != effects->currentTabBoxWindow() ) { if( m_selectedWindow != NULL ) { int old_index = effects->currentTabBoxWindowList().indexOf( m_selectedWindow ); int new_index = effects->currentTabBoxWindowList().indexOf( effects->currentTabBoxWindow() ); SwitchingDirection new_direction; int distance = new_index - old_index; if( distance > 0 ) new_direction = DirectionForward; if( distance < 0 ) new_direction = DirectionBackward; if( effects->currentTabBoxWindowList().count() == 2 ) { new_direction = DirectionForward; distance = 1; } if( distance != 0 ) { distance = abs( distance ); int tempDistance = effects->currentTabBoxWindowList().count() - distance; if( tempDistance < abs( distance ) ) { distance = tempDistance; if( new_direction == DirectionForward ) new_direction = DirectionBackward; else new_direction = DirectionForward; } scheduleAnimation( new_direction, distance ); } } m_selectedWindow = effects->currentTabBoxWindow(); } } effects->addRepaintFull(); } } //************************************************************* // Window adding/removing handling //************************************************************* void FlipSwitchEffect::windowAdded( EffectWindow* w ) { if( m_active && isSelectableWindow( w ) ) { m_windows[ w ] = new ItemInfo(); } } void FlipSwitchEffect::windowClosed( EffectWindow* w ) { if( m_active && m_windows.contains( w ) ) { m_windows.remove( w ); } } //************************************************************* // Activation //************************************************************* void FlipSwitchEffect::setActive( bool activate, FlipSwitchMode mode ) { if( activate ) { // effect already active, do some sanity checks if( m_active ) { if( m_stop ) { if( mode != m_mode ) { // only the same mode may reactivate the effect return; } } else { // active, but not scheduled for closing -> abort return; } } m_mode = mode; foreach( EffectWindow* w, effects->stackingOrder() ) { if( isSelectableWindow( w ) && !m_windows.contains( w ) ) m_windows[ w ] = new ItemInfo(); } if( m_windows.isEmpty() ) return; effects->setActiveFullScreenEffect( this ); m_active = true; m_start = true; m_startStopTimeLine.setCurveShape( TimeLine::EaseInOutCurve ); m_activeScreen = effects->activeScreen(); m_screenArea = effects->clientArea( ScreenArea, m_activeScreen, effects->currentDesktop() ); if( m_stop ) { // effect is still closing from last usage m_stop = false; } else { // things to do only when there is no closing animation m_scheduledDirections.clear(); } switch( m_mode ) { case TabboxMode: m_selectedWindow = effects->currentTabBoxWindow(); break; case CurrentDesktopMode: m_selectedWindow = effects->activeWindow(); m_input = effects->createFullScreenInputWindow( this, Qt::BlankCursor ); m_hasKeyboardGrab = effects->grabKeyboard( this ); break; case AllDesktopsMode: m_selectedWindow = effects->activeWindow(); m_input = effects->createFullScreenInputWindow( this, Qt::BlankCursor ); m_hasKeyboardGrab = effects->grabKeyboard( this ); break; } // Setup caption frame geometry QRect frameRect = QRect( m_screenArea.width() * 0.25f + m_screenArea.x(), m_screenArea.height() * 0.1f + m_screenArea.y() - QFontMetrics( m_captionFont ).height(), m_screenArea.width() * 0.5f, QFontMetrics( m_captionFont ).height() ); m_captionFrame.setGeometry( frameRect ); m_captionFrame.setIconSize( QSize( frameRect.height(), frameRect.height() )); effects->addRepaintFull(); } else { // only deactivate if mode is current mode if( mode != m_mode ) return; if( m_start && m_scheduledDirections.isEmpty() ) { m_start = false; } m_stop = true; if( m_animation ) { m_startStopTimeLine.setCurveShape( TimeLine::EaseOutCurve ); if( m_scheduledDirections.count() == 1 ) { if( m_currentAnimationShape == TimeLine::EaseInOutCurve ) m_currentAnimationShape = TimeLine::EaseInCurve; else if( m_currentAnimationShape == TimeLine::EaseOutCurve ) m_currentAnimationShape = TimeLine::LinearCurve; m_timeLine.setCurveShape( m_currentAnimationShape ); } } else m_startStopTimeLine.setCurveShape( TimeLine::EaseInOutCurve ); if( mode != TabboxMode ) effects->destroyInputWindow( m_input ); if( m_hasKeyboardGrab ) { effects->ungrabKeyboard(); m_hasKeyboardGrab = false; } effects->addRepaintFull(); } } void FlipSwitchEffect::toggleActiveAllDesktops() { if( m_active ) { if( m_stop ) { // reactivate if stopping setActive( true, AllDesktopsMode ); } else { // deactivate if not stopping setActive( false, AllDesktopsMode ); } } else { setActive( true, AllDesktopsMode ); } } void FlipSwitchEffect::toggleActiveCurrent() { if( m_active ) { if( m_stop ) { // reactivate if stopping setActive( true, CurrentDesktopMode ); } else { // deactivate if not stopping setActive( false, CurrentDesktopMode ); } } else { setActive( true, CurrentDesktopMode ); } } bool FlipSwitchEffect::borderActivated(ElectricBorder border) { if( !m_borderActivate.contains( border ) && !m_borderActivateAll.contains( border ) ) return false; if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this ) return true; if( m_borderActivate.contains( border ) ) toggleActiveCurrent(); else toggleActiveAllDesktops(); return true; } //************************************************************* // Helper function //************************************************************* bool FlipSwitchEffect::isSelectableWindow( EffectWindow* w ) const { if( w->isSpecialWindow() || w->isUtility() ) return false; if( w->isDeleted() ) return false; if( !w->acceptsFocus() ) return false; switch( m_mode ) { case TabboxMode: return effects->currentTabBoxWindowList().contains( w ); case CurrentDesktopMode: return w->isOnCurrentDesktop(); case AllDesktopsMode: //nothing special break; } return true; } void FlipSwitchEffect::scheduleAnimation( const SwitchingDirection& direction, int distance ) { if( m_start ) { // start is still active so change the shape to have a nice transition m_startStopTimeLine.setCurveShape( TimeLine::EaseInCurve ); } if( !m_animation && !m_start ) { m_animation = true; m_scheduledDirections.enqueue( direction ); distance--; // reset shape just to make sure m_currentAnimationShape = TimeLine::EaseInOutCurve; m_timeLine.setCurveShape( m_currentAnimationShape ); } for( int i=0; i 1 && m_scheduledDirections.last() != direction ) m_scheduledDirections.pop_back(); else m_scheduledDirections.enqueue( direction ); if( m_scheduledDirections.count() == m_windows.count() + 1 ) { SwitchingDirection temp = m_scheduledDirections.dequeue(); m_scheduledDirections.clear(); m_scheduledDirections.enqueue( temp ); } } if( m_scheduledDirections.count() > 1 ) { TimeLine::CurveShape newShape = TimeLine::EaseInOutCurve; switch( m_currentAnimationShape ) { case TimeLine::EaseInOutCurve: newShape = TimeLine::EaseInCurve; break; case TimeLine::EaseOutCurve: newShape = TimeLine::LinearCurve; break; default: newShape = m_currentAnimationShape; } if( newShape != m_currentAnimationShape ) { m_currentAnimationShape = newShape; m_timeLine.setCurveShape( m_currentAnimationShape ); } } } void FlipSwitchEffect::adjustWindowMultiScreen( const KWin::EffectWindow* w, WindowPaintData& data ) { if( effects->numScreens() <= 1 ) return; QRect clientRect = effects->clientArea( FullScreenArea, w->screen(), effects->currentDesktop() ); QRect rect = effects->clientArea( ScreenArea, m_activeScreen, effects->currentDesktop() ); QRect fullRect = effects->clientArea( FullArea, m_activeScreen, effects->currentDesktop() ); if( w->screen() == m_activeScreen ) { if( clientRect.width() != fullRect.width() && clientRect.x() != fullRect.x() ) { data.xTranslate -= clientRect.x(); } if( clientRect.height() != fullRect.height() && clientRect.y() != fullRect.y() ) { data.yTranslate -= clientRect.y(); } } else { if( clientRect.width() != fullRect.width() && clientRect.x() < rect.x()) { data.xTranslate -= clientRect.width(); } if( clientRect.height() != fullRect.height() && clientRect.y() < m_screenArea.y() ) { data.yTranslate -= clientRect.height(); } } } //************************************************************* // Keyboard handling //************************************************************* void FlipSwitchEffect::globalShortcutChangedAll( QKeySequence shortcut ) { m_shortcutAll = KShortcut( shortcut ); } void FlipSwitchEffect::globalShortcutChangedCurrent(QKeySequence shortcut) { m_shortcutCurrent = KShortcut( shortcut ); } void FlipSwitchEffect::grabbedKeyboardEvent(QKeyEvent* e) { if( e->type() == QEvent::KeyPress ) { // check for global shortcuts // HACK: keyboard grab disables the global shortcuts so we have to check for global shortcut (bug 156155) if( m_mode == CurrentDesktopMode && m_shortcutCurrent.contains( e->key() + e->modifiers() ) ) { toggleActiveCurrent(); return; } if( m_mode == AllDesktopsMode && m_shortcutAll.contains( e->key() + e->modifiers() ) ) { toggleActiveAllDesktops(); return; } switch( e->key() ) { case Qt::Key_Escape: setActive( false, m_mode ); return; case Qt::Key_Tab: { // find next window if( m_windows.isEmpty() ) return; // sanity check bool found = false; for( int i=effects->stackingOrder().indexOf( m_selectedWindow)-1; i>=0; i-- ) { if( isSelectableWindow( effects->stackingOrder().at( i )) ) { m_selectedWindow = effects->stackingOrder().at( i ); found = true; break; } } if( !found ) { for( int i=effects->stackingOrder().count()-1; i>effects->stackingOrder().indexOf( m_selectedWindow); i-- ) { if( isSelectableWindow( effects->stackingOrder().at( i )) ) { m_selectedWindow = effects->stackingOrder().at( i ); found = true; break; } } } if( found ) { scheduleAnimation( DirectionForward ); } break; } case Qt::Key_Backtab: { // find previous window if( m_windows.isEmpty() ) return; // sanity check bool found = false; for( int i=effects->stackingOrder().indexOf( m_selectedWindow)+1; istackingOrder().count(); i++ ) { if( isSelectableWindow( effects->stackingOrder().at( i )) ) { m_selectedWindow = effects->stackingOrder().at( i ); found = true; break; } } if( !found ) { for( int i=0; istackingOrder().indexOf( m_selectedWindow); i++ ) { if( isSelectableWindow( effects->stackingOrder().at( i )) ) { m_selectedWindow = effects->stackingOrder().at( i ); found = true; break; } } } if( found ) { scheduleAnimation( DirectionBackward ); } break; } case Qt::Key_Return: case Qt::Key_Enter: case Qt::Key_Space: if( m_selectedWindow ) effects->activateWindow( m_selectedWindow ); setActive( false, m_mode ); break; default: break; } effects->addRepaintFull(); } } //************************************************************* // Item Info //************************************************************* FlipSwitchEffect::ItemInfo::ItemInfo() : deleted(false) , opacity( 0.0 ) , brightness( 0.0 ) , saturation( 0.0 ) { } FlipSwitchEffect::ItemInfo::~ItemInfo() { } } // namespace #include "flipswitch.moc"