diff --git a/bridge.cpp b/bridge.cpp index c5b828ac3f..1ad86f2273 100644 --- a/bridge.cpp +++ b/bridge.cpp @@ -69,9 +69,7 @@ NET::WindowType Bridge::windowType( unsigned long supported_types ) const QIcon Bridge::icon() const { -#ifdef __GNUC__ #warning KDE4 drop me ? -#endif return QIcon( /*c->miniIcon(),*/ c->icon()); } @@ -128,7 +126,7 @@ void Bridge::titlebarDblClickOperation() void Bridge::titlebarMouseWheelOperation( int delta ) { - c->performMouseCommand( options->operationTitlebarMouseWheel( delta ), QCursor::pos()); + c->performMouseCommand( options->operationTitlebarMouseWheel( delta ), cursorPos()); } void Bridge::setShade( bool set ) diff --git a/effects/zoom.cpp b/effects/zoom.cpp index e958d47f8e..438117d09c 100644 --- a/effects/zoom.cpp +++ b/effects/zoom.cpp @@ -43,7 +43,7 @@ void ZoomEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) { data.xScale *= zoom; data.yScale *= zoom; - QPoint cursor = QCursor::pos(); // TODO this is one X roundtrip + QPoint cursor = cursorPos(); // set the position so that the cursor is in the same position in the scaled view data.xTranslate = - int( cursor.x() * ( zoom - 1 )); data.yTranslate = - int( cursor.y() * ( zoom - 1 )); diff --git a/events.cpp b/events.cpp index d29b0b4d62..fece719bc4 100644 --- a/events.cpp +++ b/events.cpp @@ -1552,7 +1552,7 @@ void Client::keyPressEvent( uint key_code ) bool is_alt = key_code & Qt::ALT; key_code = key_code & 0xffff; int delta = is_control?1:is_alt?32:8; - QPoint pos = QCursor::pos(); + QPoint pos = cursorPos(); switch ( key_code ) { case Qt::Key_Left: diff --git a/killwindow.cpp b/killwindow.cpp index 6ed5ca23b8..6dfab97f30 100644 --- a/killwindow.cpp +++ b/killwindow.cpp @@ -76,7 +76,7 @@ void KillWindow::start() mx /= 10; my /= 10; } - QCursor::setPos(QCursor::pos()+QPoint(mx, my)); + QCursor::setPos(cursorPos()+QPoint(mx, my)); } if (ev.type == ButtonRelease) diff --git a/manage.cpp b/manage.cpp index 7fbace11cb..5073479147 100644 --- a/manage.cpp +++ b/manage.cpp @@ -212,7 +212,7 @@ bool Client::manage( Window w, bool isMapped ) if( isMapped || session ) area = workspace()->clientArea( FullArea, geom.center(), desktop()); else if( options->xineramaPlacementEnabled ) - area = workspace()->clientArea( PlacementArea, QCursor::pos(), desktop()); + area = workspace()->clientArea( PlacementArea, cursorPos(), desktop()); else area = workspace()->clientArea( PlacementArea, geom.center(), desktop()); diff --git a/placement.cpp b/placement.cpp index a5a6ac7289..b9d141de4f 100644 --- a/placement.cpp +++ b/placement.cpp @@ -453,7 +453,7 @@ void Placement::placeUnderMouse(Client* c, QRect& area, Policy /*next*/ ) { area = checkArea( c, area ); QRect geom = c->geometry(); - geom.moveCenter( QCursor::pos()); + geom.moveCenter( cursorPos()); c->move( geom.topLeft()); c->keepInArea( area ); // make sure it's kept inside workarea } diff --git a/popupinfo.cpp b/popupinfo.cpp index ded206ddfe..11916f0889 100644 --- a/popupinfo.cpp +++ b/popupinfo.cpp @@ -66,7 +66,7 @@ PopupInfo::~PopupInfo() */ void PopupInfo::reset() { - QRect r = KGlobalSettings::desktopGeometry(QCursor::pos()); + QRect r = KGlobalSettings::desktopGeometry(cursorPos()); int w = fontMetrics().width( m_infoString ) + 30; diff --git a/tabbox.cpp b/tabbox.cpp index 3eae1d9d6f..355dafeb5f 100644 --- a/tabbox.cpp +++ b/tabbox.cpp @@ -139,7 +139,7 @@ void TabBox::reset() { int w, h, cw = 0, wmax = 0; - QRect r = KGlobalSettings::desktopGeometry(QCursor::pos()); + QRect r = KGlobalSettings::desktopGeometry(cursorPos()); // calculate height of 1 line // fontheight + 1 pixel above + 1 pixel below, or 32x32 icon + 2 pixel above + below diff --git a/useractions.cpp b/useractions.cpp index f29d72822a..85643e801b 100644 --- a/useractions.cpp +++ b/useractions.cpp @@ -442,16 +442,16 @@ void Workspace::performWindowOperation( Client* c, Options::WindowOperation op ) switch ( op ) { case Options::MoveOp: - c->performMouseCommand( Options::MouseMove, QCursor::pos() ); + c->performMouseCommand( Options::MouseMove, cursorPos() ); break; case Options::UnrestrictedMoveOp: - c->performMouseCommand( Options::MouseUnrestrictedMove, QCursor::pos() ); + c->performMouseCommand( Options::MouseUnrestrictedMove, cursorPos() ); break; case Options::ResizeOp: - c->performMouseCommand( Options::MouseResize, QCursor::pos() ); + c->performMouseCommand( Options::MouseResize, cursorPos() ); break; case Options::UnrestrictedResizeOp: - c->performMouseCommand( Options::MouseUnrestrictedResize, QCursor::pos() ); + c->performMouseCommand( Options::MouseUnrestrictedResize, cursorPos() ); break; case Options::CloseOp: c->closeWindow(); @@ -473,7 +473,7 @@ void Workspace::performWindowOperation( Client* c, Options::WindowOperation op ) c->minimize(); break; case Options::ShadeOp: - c->performMouseCommand( Options::MouseShade, QCursor::pos()); + c->performMouseCommand( Options::MouseShade, cursorPos()); break; case Options::OnAllDesktopsOp: c->setOnAllDesktops( !c->isOnAllDesktops() ); @@ -503,7 +503,7 @@ void Workspace::performWindowOperation( Client* c, Options::WindowOperation op ) break; } case Options::OperationsOp: - c->performMouseCommand( Options::MouseShade, QCursor::pos()); + c->performMouseCommand( Options::MouseShade, cursorPos()); break; case Options::WindowRulesOp: editWindowRules( c, false ); diff --git a/utils.cpp b/utils.cpp index 336aafdea7..f4b2625844 100644 --- a/utils.cpp +++ b/utils.cpp @@ -423,6 +423,22 @@ Qt::KeyboardModifiers x11ToQtKeyboardModifiers( int state ) return ret; } +// Optimized version of QCursor::pos() that tries to avoid X roundtrips +// by updating the value only when the X timestamp changes. +static QPoint last_cursor_pos; +static Time last_cursor_timestamp = CurrentTime; + +QPoint cursorPos() + { + if( last_cursor_timestamp == CurrentTime + || last_cursor_timestamp != QX11Info::appTime()) + { + last_cursor_timestamp = QX11Info::appTime(); + last_cursor_pos = QCursor::pos(); + } + return last_cursor_pos; + } + #endif bool isLocalMachine( const QByteArray& host ) diff --git a/utils.h b/utils.h index 20ed1a6909..88d9e745f4 100644 --- a/utils.h +++ b/utils.h @@ -274,6 +274,8 @@ int displayHeight() return XDisplayHeight( display(), DefaultScreen( display())); } +QPoint cursorPos(); + class Scene; extern Scene* scene; inline bool compositing() { return scene != NULL; } diff --git a/workspace.cpp b/workspace.cpp index c0ba4e18bd..3da096436e 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -42,6 +42,9 @@ License. See the file "COPYING" for the exact licensing terms. #include "group.h" #include "rules.h" #include "kwinadaptor.h" +#include "unmanaged.h" +#include "scene.h" +#include "effects.h" #include #include @@ -93,6 +96,7 @@ Workspace::Workspace( bool restore ) popupinfo (0), popup (0), advanced_popup (0), + trans_popup (0), desk_popup (0), desk_popup_index (0), keys (0), @@ -122,12 +126,17 @@ Workspace::Workspace( bool restore ) topmenu_space( NULL ), set_active_client_recursion( 0 ), block_stacking_updates( 0 ), - forced_global_mouse_grab( false ) + forced_global_mouse_grab( false ), + cm_selection( NULL ), + compositeRate( 0 ), + damage_region( None ), + overlay( None ), + transSlider( NULL ), + transButton( NULL ) { (void) new KWinAdaptor( this ); - QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerObject("/KWin", this); - dbus.connect(QString(), "/KWin", "org.kde.KWin", "reloadConfig", this, SLOT(slotReloadConfig())); + QDBusConnection::sessionBus().registerObject("/KWin", this); + _self = this; mgr = new PluginMgr; root = rootWindow(); @@ -168,10 +177,12 @@ Workspace::Workspace( bool restore ) ColormapChangeMask | SubstructureRedirectMask | SubstructureNotifyMask | - FocusChangeMask // for NotifyDetailNone + FocusChangeMask | // for NotifyDetailNone + ExposureMask ); - Shape::init(); + Extensions::init(); + setupCompositing(); // compatibility long data = 1; @@ -320,6 +331,7 @@ void Workspace::init() connect(&reconfigureTimer, SIGNAL(timeout()), this, SLOT(slotReconfigure())); connect( &updateToolWindowsTimer, SIGNAL( timeout()), this, SLOT( slotUpdateToolWindows())); + connect( &compositeTimer, SIGNAL( timeout()), SLOT( performCompositing())); connect(KGlobalSettings::self(), SIGNAL(appearanceChanged()), this, SLOT(slotReconfigure())); @@ -357,7 +369,11 @@ void Workspace::init() XWindowAttributes attr; XGetWindowAttributes(display(), wins[i], &attr); if (attr.override_redirect ) + { + if( attr.map_state != IsUnmapped && attr.c_class != InputOnly && compositing()) + createUnmanaged( wins[ i ] ); continue; + } if( topmenu_space && topmenu_space->winId() == wins[ i ] ) continue; if (attr.map_state != IsUnmapped) @@ -420,6 +436,7 @@ void Workspace::init() Workspace::~Workspace() { + finishCompositing(); blockStackingUpdates( true ); // TODO grabXServer(); // use stacking_order, so that kwin --replace keeps stacking order @@ -429,12 +446,12 @@ Workspace::~Workspace() { // only release the window (*it)->releaseWindow( true ); - // No removeClient() is called, it does more than just removing. - // However, remove from some lists to e.g. prevent performTransiencyCheck() - // from crashing. - clients.remove( *it ); - desktops.remove( *it ); + // no removeClient() is called ! } + for( UnmanagedList::ConstIterator it = unmanaged.begin(); + it != unmanaged.end(); + ++it ) + (*it)->release(); delete desktop_widget; delete tab_box; delete popupinfo; @@ -478,6 +495,28 @@ Client* Workspace::createClient( Window w, bool is_mapped ) return NULL; } addClient( c, Allowed ); + if( scene ) + scene->windowAdded( c ); + if( effects ) + effects->windowAdded( c ); + return c; + } + +Unmanaged* Workspace::createUnmanaged( Window w ) + { + if( w == overlay ) + return NULL; + Unmanaged* c = new Unmanaged( this ); + if( !c->track( w )) + { + Unmanaged::deleteUnmanaged( c, Allowed ); + return NULL; + } + addUnmanaged( c, Allowed ); + if( scene ) + scene->windowAdded( c ); + if( effects ) + effects->windowAdded( c ); return c; } @@ -518,7 +557,11 @@ void Workspace::addClient( Client* c, allowed_t ) updateStackingOrder( true ); // propagate new client if( c->isUtility() || c->isMenu() || c->isToolbar()) updateToolWindows( true ); - checkNonExistentClients(); + } + +void Workspace::addUnmanaged( Unmanaged* c, allowed_t ) + { + unmanaged.append( c ); } /* @@ -540,6 +583,10 @@ void Workspace::removeClient( Client* c, allowed_t ) Notify::raise( Notify::Delete ); Q_ASSERT( clients.contains( c ) || desktops.contains( c )); + if( scene ) + scene->windowDeleted( c ); + if( effects ) + effects->windowDeleted( c ); clients.removeAll( c ); desktops.removeAll( c ); unconstrained_stacking_order.removeAll( c ); @@ -575,6 +622,16 @@ void Workspace::removeClient( Client* c, allowed_t ) updateClientArea(); } +void Workspace::removeUnmanaged( Unmanaged* c, allowed_t ) + { + assert( unmanaged.contains( c )); + if( scene ) + scene->windowDeleted( c ); + if( effects ) + effects->windowDeleted( c ); + unmanaged.removeAll( c ); + } + void Workspace::updateFocusChains( Client* c, FocusChainChange change ) { if( !c->wantsTabFocus()) // doesn't want tab focus, remove @@ -600,13 +657,7 @@ void Workspace::updateFocusChains( Client* c, FocusChainChange change ) focus_chain[ i ].prepend( c ); } else if( !focus_chain[ i ].contains( c )) - { // add it after the active one - if( active_client != NULL && active_client != c - && !focus_chain[ i ].isEmpty() && focus_chain[ i ].last() == active_client ) - focus_chain[ i ].insert( focus_chain[ i ].size() - 1, c ); - else - focus_chain[ i ].append( c ); // otherwise add as the first one - } + focus_chain[ i ].prepend( c ); // otherwise add as the last one } } else //now only on desktop, remove it anywhere else @@ -626,13 +677,7 @@ void Workspace::updateFocusChains( Client* c, FocusChainChange change ) focus_chain[ i ].prepend( c ); } else if( !focus_chain[ i ].contains( c )) - { // add it after the active one - if( active_client != NULL && active_client != c - && !focus_chain[ i ].isEmpty() && focus_chain[ i ].last() == active_client ) - focus_chain[ i ].insert( focus_chain[ i ].size() - 1, c ); - else - focus_chain[ i ].append( c ); // otherwise add as the first one - } + focus_chain[ i ].prepend( c ); } else focus_chain[ i ].removeAll( c ); @@ -649,13 +694,7 @@ void Workspace::updateFocusChains( Client* c, FocusChainChange change ) global_focus_chain.prepend( c ); } else if( !global_focus_chain.contains( c )) - { // add it after the active one - if( active_client != NULL && active_client != c - && !global_focus_chain.isEmpty() && global_focus_chain.last() == active_client ) - global_focus_chain.insert( global_focus_chain.size() - 1, c ); - else - global_focus_chain.append( c ); // otherwise add as the first one - } + global_focus_chain.prepend( c ); } void Workspace::updateCurrentTopMenu() @@ -873,11 +912,6 @@ void Workspace::updateColormap() } } -void Workspace::slotReloadConfig() -{ - reconfigure(); -} - void Workspace::reconfigure() { reconfigureTimer.start( 200 ); @@ -894,7 +928,7 @@ void Workspace::slotSettingsChanged(int category) /*! Reread settings */ -KWIN_PROCEDURE( CheckBorderSizesProcedure, cl->checkBorderSizes() ); +KWIN_PROCEDURE( CheckBorderSizesProcedure, Client, cl->checkBorderSizes() ); void Workspace::slotReconfigure() { @@ -951,6 +985,11 @@ void Workspace::slotReconfigure() updateTopMenuGeometry(); updateCurrentTopMenu(); } + + if( options->useTranslucency ) + setupCompositing(); + else + finishCompositing(); loadWindowRules(); for( ClientList::Iterator it = clients.begin(); @@ -1240,18 +1279,11 @@ bool Workspace::setCurrentDesktop( int new_desktop ) if ( c ) requestFocus( c ); + else if( !desktops.isEmpty() ) + requestFocus( findDesktop( true, currentDesktop())); else focusToNull(); - if( !desktops.isEmpty() ) - { - Window w_tmp; - int i_tmp; - XGetInputFocus( display(), &w_tmp, &i_tmp ); - if( w_tmp == null_focus_window ) // CHECKME? - requestFocus( findDesktop( true, currentDesktop())); - } - updateCurrentTopMenu(); // Update focus chain: @@ -1652,7 +1684,7 @@ void Workspace::slotGrabWindow() QPixmap snapshot = QPixmap::grabWindow( active_client->frameId() ); //No XShape - no work. - if( Shape::available()) + if( Extensions::shapeAvailable()) { //As the first step, get the mask from XShape. int count, order; @@ -1853,7 +1885,7 @@ bool Workspace::keyPressMouseEmulation( XKeyEvent& ev ) bool is_alt = km & Mod1Mask; bool is_shift = km & ShiftMask; int delta = is_control?1:is_alt?32:8; - QPoint pos = QCursor::pos(); + QPoint pos = cursorPos(); switch ( kc ) { @@ -2005,7 +2037,8 @@ void Workspace::createBorderWindows() XSetWindowAttributes attributes; unsigned long valuemask; attributes.override_redirect = True; - attributes.event_mask = ( EnterWindowMask | LeaveWindowMask ); + attributes.event_mask = (EnterWindowMask | LeaveWindowMask | + VisibilityChangeMask); valuemask= (CWOverrideRedirect | CWEventMask | CWCursor ); attributes.cursor = XCreateFontCursor(display(), XC_sb_up_arrow);