diff --git a/client.cpp b/client.cpp index 34f4cb55a4..d3127ece78 100644 --- a/client.cpp +++ b/client.cpp @@ -28,6 +28,7 @@ License. See the file "COPYING" for the exact licensing terms. #include "atoms.h" #include "notifications.h" #include "rules.h" +#include "scene.h" #include #include @@ -63,12 +64,10 @@ namespace KWinInternal is done in manage(). */ Client::Client( Workspace *ws ) - : QObject( NULL ), + : Toplevel( ws ), client( None ), wrapper( None ), - frame( None ), decoration( NULL ), - wspace( ws ), bridge( new Bridge( this )), move_faked_activity( false ), move_resize_grab_window( None ), @@ -82,7 +81,7 @@ Client::Client( Workspace *ws ) process_killer( NULL ), user_time( CurrentTime ), // not known yet allowed_actions( 0 ), - postpone_geometry_updates( 0 ), + block_geometry_updates( 0 ), pending_geometry_update( false ), shade_geometry_change( false ), border_left( 0 ), @@ -111,7 +110,6 @@ Client::Client( Workspace *ws ) deleting = false; keep_above = false; keep_below = false; - is_shape = false; motif_noborder = false; motif_may_move = true; motif_may_resize = true; @@ -124,6 +122,7 @@ Client::Client( Workspace *ws ) modal = false; noborder = false; user_noborder = false; + not_obscured = false; urgency = false; ignore_focus_stealing = false; demands_attention = false; @@ -142,7 +141,7 @@ Client::Client( Workspace *ws ) cmap = None; - frame_geometry = QRect( 0, 0, 100, 100 ); // so that decorations don't start with size being (0,0) + geom = QRect( 0, 0, 100, 100 ); // so that decorations don't start with size being (0,0) client_size = QSize( 100, 100 ); // SELI initialize xsizehints?? @@ -155,9 +154,10 @@ Client::~Client() { assert(!moveResizeMode); assert( client == None ); - assert( frame == None && wrapper == None ); + assert( wrapper == None ); +// assert( frameId() == None ); assert( decoration == NULL ); - assert( postpone_geometry_updates == 0 ); + assert( block_geometry_updates == 0 ); assert( !check_active_modal ); delete info; delete bridge; @@ -176,15 +176,15 @@ void Client::releaseWindow( bool on_shutdown ) { assert( !deleting ); deleting = true; + finishCompositing(); workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules StackingUpdatesBlocker blocker( workspace()); if (moveResizeMode) leaveMoveResize(); finishWindowRules(); - ++postpone_geometry_updates; - // grab X during the release to make removing of properties, setting to withdrawn state - // and repareting to root an atomic operation (http://lists.kde.org/?l=kde-devel&m=116448102901184&w=2) - grabXServer(); + ++block_geometry_updates; + if( isNormalState()) // is mapped? + workspace()->addDamage( geometry()); setMappingState( WithdrawnState ); setModal( false ); // otherwise its mainwindow wouldn't get focus hidden = true; // so that it's not considered visible anymore (can't use hideClient(), it would set flags) @@ -222,11 +222,10 @@ void Client::releaseWindow( bool on_shutdown ) client = None; XDestroyWindow( display(), wrapper ); wrapper = None; - XDestroyWindow( display(), frame ); - frame = None; - --postpone_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry + XDestroyWindow( display(), frameId()); +// frame = None; + --block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry deleteClient( this, Allowed ); - ungrabXServer(); } // like releaseWindow(), but this one is called when the window has been already destroyed @@ -235,12 +234,15 @@ void Client::destroyClient() { assert( !deleting ); deleting = true; + finishCompositing(); workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules StackingUpdatesBlocker blocker( workspace()); if (moveResizeMode) leaveMoveResize(); finishWindowRules(); - ++postpone_geometry_updates; + ++block_geometry_updates; + if( isNormalState()) // is mapped? + workspace()->addDamage( geometry()); setModal( false ); hidden = true; // so that it's not considered visible anymore workspace()->clientHidden( this ); @@ -250,9 +252,9 @@ void Client::destroyClient() client = None; // invalidate XDestroyWindow( display(), wrapper ); wrapper = None; - XDestroyWindow( display(), frame ); - frame = None; - --postpone_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry + XDestroyWindow( display(), frameId()); +// frame = None; + --block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry deleteClient( this, Allowed ); } @@ -262,12 +264,11 @@ void Client::updateDecoration( bool check_workspace_pos, bool force ) || ( decoration != NULL && !noBorder()))) return; bool do_show = false; - postponeGeometryUpdates( true ); + blockGeometryUpdates( true ); if( force ) destroyDecoration(); if( !noBorder()) { - setMask( QRegion()); // reset shape mask decoration = workspace()->createDecoration( bridge ); // TODO check decoration's minimum size? decoration->init(); @@ -282,15 +283,18 @@ void Client::updateDecoration( bool check_workspace_pos, bool force ) workarea_diff_x = save_workarea_diff_x; workarea_diff_y = save_workarea_diff_y; do_show = true; + if( scene != NULL ) + scene->windowGeometryShapeChanged( this ); } else destroyDecoration(); if( check_workspace_pos ) checkWorkspacePosition(); - postponeGeometryUpdates( false ); + blockGeometryUpdates( false ); if( do_show ) decoration->widget()->show(); updateFrameExtents(); + addDamageFull(); } void Client::destroyDecoration() @@ -308,6 +312,9 @@ void Client::destroyDecoration() move( grav ); workarea_diff_x = save_workarea_diff_x; workarea_diff_y = save_workarea_diff_y; + if( scene != NULL ) + scene->windowGeometryShapeChanged( this ); + addDamageFull(); } } @@ -320,7 +327,7 @@ void Client::checkBorderSizes() if( new_left == border_left && new_right == border_right && new_top == border_top && new_bottom == border_bottom ) return; - GeometryUpdatesPostponer blocker( this ); + GeometryUpdatesBlocker blocker( this ); move( calculateGravitation( true )); border_left = new_left; border_right = new_right; @@ -337,7 +344,7 @@ void Client::checkBorderSizes() void Client::detectNoBorder() { - if( Shape::hasShape( window())) + if( shape()) { noborder = true; return; @@ -425,47 +432,22 @@ void Client::setUserNoBorder( bool set ) void Client::updateShape() { + if ( shape() ) + XShapeCombineShape(display(), frameId(), ShapeBounding, + clientPos().x(), clientPos().y(), + window(), ShapeBounding, ShapeSet); + else + XShapeCombineMask( display(), frameId(), ShapeBounding, 0, 0, + None, ShapeSet); + if( scene != NULL ) + scene->windowGeometryShapeChanged( this ); + addDamageFull(); // workaround for #19644 - shaped windows shouldn't have decoration if( shape() && !noBorder()) { noborder = true; updateDecoration( true ); } - if( shape()) - { - XShapeCombineShape(display(), frameId(), ShapeBounding, - clientPos().x(), clientPos().y(), - window(), ShapeBounding, ShapeSet); - } - // !shape() mask setting is done in setMask() when the decoration - // calls it or when the decoration is created/destroyed - - if( Shape::version() >= 0x11 ) // 1.1, has input shape support - { // There appears to be no way to find out if a window has input - // shape set or not, so always propagate the input shape - // (it's the same like the bounding shape by default). - // Also, build the shape using a helper window, not directly - // in the frame window, because the sequence set-shape-to-frame, - // remove-shape-of-client, add-input-shape-of-client has the problem - // that after the second step there's a hole in the input shape - // until the real shape of the client is added and that can make - // the window lose focus (which is a problem with mouse focus policies) - static Window helper_window = None; - if( helper_window == None ) - helper_window = XCreateSimpleWindow( display(), rootWindow(), - 0, 0, 1, 1, 0, 0, 0 ); - XResizeWindow( display(), helper_window, width(), height()); - XShapeCombineShape( display(), helper_window, ShapeInput, 0, 0, - frameId(), ShapeBounding, ShapeSet ); - XShapeCombineShape( display(), helper_window, ShapeInput, - clientPos().x(), clientPos().y(), - window(), ShapeBounding, ShapeSubtract ); - XShapeCombineShape( display(), helper_window, ShapeInput, - clientPos().x(), clientPos().y(), - window(), ShapeInput, ShapeUnion ); - XShapeCombineShape( display(), frameId(), ShapeInput, 0, 0, - helper_window, ShapeInput, ShapeSet ); - } } void Client::setMask( const QRegion& reg, int mode ) @@ -494,7 +476,9 @@ void Client::setMask( const QRegion& reg, int mode ) xrects, rects.count(), ShapeSet, mode ); delete[] xrects; } - updateShape(); + if( scene != NULL ) + scene->windowGeometryShapeChanged( this ); + addDamageFull(); } QRegion Client::mask() const @@ -743,7 +727,7 @@ void Client::setShade( ShadeMode mode ) } assert( decoration != NULL ); // noborder windows can't be shaded - GeometryUpdatesPostponer blocker( this ); + GeometryUpdatesBlocker blocker( this ); // decorations may turn off some borders when shaded decoration->borders( border_left, border_right, border_top, border_bottom ); @@ -790,9 +774,13 @@ void Client::setShade( ShadeMode mode ) // tell xcompmgr shade's done _shade = 2; XChangeProperty(display(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &_shade, 1L); + if( isNormalState()) // is mapped? + workspace()->addDamage( geometry()); } else { + if( isNormalState()) // is mapped? + workspace()->addDamage( geometry()); int h = height(); shade_geometry_change = true; QSize s( sizeForClientSize( clientSize())); @@ -927,8 +915,8 @@ void Client::setMappingState(int s) XChangeProperty(display(), window(), atoms->wm_state, atoms->wm_state, 32, PropModeReplace, (unsigned char *)data, 2); - if( was_unmanaged ) // manage() did postpone_geometry_updates = 1, now it's ok to finally set the geometry - postponeGeometryUpdates( false ); + if( was_unmanaged ) // manage() did block_geometry_updates = 1, now it's ok to finally set the geometry + blockGeometryUpdates( false ); } /*! @@ -939,7 +927,7 @@ void Client::rawShow() { if( decoration != NULL ) decoration->widget()->show(); // not really necessary, but let it know the state - XMapWindow( display(), frame ); + XMapWindow( display(), frameId()); if( !isShade()) { XMapWindow( display(), wrapper ); @@ -954,6 +942,7 @@ void Client::rawShow() */ void Client::rawHide() { + workspace()->addDamage( geometry()); // Here it may look like a race condition, as some other client might try to unmap // the window between these two XSelectInput() calls. However, they're supposed to // use XWithdrawWindow(), which also sends a synthetic event to the root window, @@ -961,7 +950,7 @@ void Client::rawHide() // will be missed is also very minimal, so I don't think it's needed to grab the server // here. XSelectInput( display(), wrapper, ClientWinMask ); // avoid getting UnmapNotify - XUnmapWindow( display(), frame ); + XUnmapWindow( display(), frameId()); XUnmapWindow( display(), wrapper ); XUnmapWindow( display(), client ); XSelectInput( display(), wrapper, ClientWinMask | SubstructureNotifyMask ); @@ -1306,7 +1295,7 @@ QString Client::readName() const return KWin::readNameProperty( window(), XA_WM_NAME ); } -KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate, const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption()); +KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate, Client, const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption()); void Client::setCaption( const QString& _s, bool force ) { @@ -1623,58 +1612,6 @@ bool Client::wantsInput() const return rules()->checkAcceptFocus( input || Ptakefocus ); } -bool Client::isDesktop() const - { - return windowType() == NET::Desktop; - } - -bool Client::isDock() const - { - return windowType() == NET::Dock; - } - -bool Client::isTopMenu() const - { - return windowType() == NET::TopMenu; - } - - -bool Client::isMenu() const - { - return windowType() == NET::Menu && !isTopMenu(); // because of backwards comp. - } - -bool Client::isToolbar() const - { - return windowType() == NET::Toolbar; - } - -bool Client::isSplash() const - { - return windowType() == NET::Splash; - } - -bool Client::isUtility() const - { - return windowType() == NET::Utility; - } - -bool Client::isDialog() const - { - return windowType() == NET::Dialog; - } - -bool Client::isNormalWindow() const - { - return windowType() == NET::Normal; - } - -bool Client::isSpecialWindow() const - { - return isDesktop() || isDock() || isSplash() || isTopMenu() - || isToolbar(); // TODO - } - NET::WindowType Client::windowType( bool direct, int supported_types ) const { NET::WindowType wt = info->windowType( supported_types ); @@ -1706,6 +1643,12 @@ NET::WindowType Client::windowType( bool direct, int supported_types ) const return wt; } +bool Client::isSpecialWindow() const + { + return isDesktop() || isDock() || isSplash() || isTopMenu() + || isToolbar(); // TODO + } + /*! Sets an appropriate cursor shape for the logical mouse position \a m @@ -1802,46 +1745,24 @@ void Client::cancelAutoRaise() autoRaiseTimer = 0; } -#ifndef NDEBUG -kdbgstream& operator<<( kdbgstream& stream, const Client* cl ) +double Client::opacity() const { - if( cl == NULL ) - return stream << "\'NULL_CLIENT\'"; - return stream << "\'ID:" << cl->window() << ";WMCLASS:" << cl->resourceClass() << ":" << cl->resourceName() << ";Caption:" << cl->caption() << "\'"; + if( info->opacity() == 0xffffffff ) + return 1.0; + return info->opacity() * 1.0 / 0xffffffff; } -kdbgstream& operator<<( kdbgstream& stream, const ClientList& list ) + +void Client::setOpacity( double opacity ) { - stream << "LIST:("; - bool first = true; - for( ClientList::ConstIterator it = list.begin(); - it != list.end(); - ++it ) - { - if( !first ) - stream << ":"; - first = false; - stream << *it; - } - stream << ")"; - return stream; + opacity = qBound( 0.0, opacity, 1.0 ); + info->setOpacity( static_cast< unsigned long >( opacity * 0xffffffff )); + // we'll react on PropertyNotify } -kdbgstream& operator<<( kdbgstream& stream, const ConstClientList& list ) + +void Client::debug( kdbgstream& stream ) const { - stream << "LIST:("; - bool first = true; - for( ConstClientList::ConstIterator it = list.begin(); - it != list.end(); - ++it ) - { - if( !first ) - stream << ":"; - first = false; - stream << *it; - } - stream << ")"; - return stream; + stream << "\'ID:" << window() << ";WMCLASS:" << resourceClass() << ":" << resourceName() << ";Caption:" << caption() << "\'"; } -#endif QPixmap * kwin_get_menu_pix_hack() { diff --git a/tabbox.cpp b/tabbox.cpp index 385943614a..4bbe5febd5 100644 --- a/tabbox.cpp +++ b/tabbox.cpp @@ -43,7 +43,7 @@ namespace KWinInternal extern QPixmap* kwin_get_menu_pix_hack(); TabBox::TabBox( Workspace *ws, const char *name ) - : Q3Frame( 0, name, Qt::WNoAutoErase ), current_client( NULL ), wspace(ws) + : Q3Frame( 0, name, Qt::WNoAutoErase ), client(0), wspace(ws) { setFrameStyle(QFrame::StyledPanel | QFrame::Plain); setLineWidth(2); @@ -57,25 +57,10 @@ TabBox::TabBox( Workspace *ws, const char *name ) reconfigure(); reset(); connect(&delayedShowTimer, SIGNAL(timeout()), this, SLOT(show())); - - XSetWindowAttributes attr; - attr.override_redirect = 1; - outline_left = XCreateWindow( display(), rootWindow(), 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr ); - outline_right = XCreateWindow( display(), rootWindow(), 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr ); - outline_top = XCreateWindow( display(), rootWindow(), 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr ); - outline_bottom = XCreateWindow( display(), rootWindow(), 0, 0, 1, 1, 0, - CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr ); } TabBox::~TabBox() { - XDestroyWindow( display(), outline_left ); - XDestroyWindow( display(), outline_right ); - XDestroyWindow( display(), outline_top ); - XDestroyWindow( display(), outline_bottom ); } @@ -126,9 +111,7 @@ void TabBox::createClientList(ClientList &list, int desktop /*-1 = all*/, Client else if( !list.contains( modal )) list += modal; else - { - // nothing - } + ; // nothing } } @@ -164,10 +147,10 @@ void TabBox::reset() if ( mode() == WindowsMode ) { - setCurrentClient( workspace()->activeClient()); + client = workspace()->activeClient(); // get all clients to show - createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), current_client, true); + createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), client, true); // calculate maximum caption width cw = fontMetrics().width(no_tasks)+20; @@ -244,8 +227,7 @@ void TabBox::nextPrev( bool next) { if ( mode() == WindowsMode ) { - Client* firstClient = NULL; - Client* client = current_client; + Client* firstClient = 0; do { if ( next ) @@ -265,7 +247,6 @@ void TabBox::nextPrev( bool next) break; } } while ( client && !clients.contains( client )); - setCurrentClient( client ); } else if( mode() == DesktopMode ) { @@ -303,18 +284,9 @@ Client* TabBox::currentClient() { if ( mode() != WindowsMode ) return 0; - if (!workspace()->hasClient( current_client )) + if (!workspace()->hasClient( client )) return 0; - return current_client; - } - -void TabBox::setCurrentClient( Client* c ) - { - if( current_client != c ) - { - current_client = c; - updateOutline(); - } + return client; } /*! @@ -336,11 +308,6 @@ int TabBox::currentDesktop() */ void TabBox::showEvent( QShowEvent* ) { - updateOutline(); - XRaiseWindow( display(), outline_left ); - XRaiseWindow( display(), outline_right ); - XRaiseWindow( display(), outline_top ); - XRaiseWindow( display(), outline_bottom ); raise(); } @@ -350,10 +317,6 @@ void TabBox::showEvent( QShowEvent* ) */ void TabBox::hideEvent( QHideEvent* ) { - XUnmapWindow( display(), outline_left ); - XUnmapWindow( display(), outline_right ); - XUnmapWindow( display(), outline_top ); - XUnmapWindow( display(), outline_bottom ); } /*! @@ -392,7 +355,7 @@ void TabBox::drawContents( QPainter * ) if ( workspace()->hasClient( *it ) ) // safety { // draw highlight background - if ( (*it) == current_client ) + if ( (*it) == currentClient() ) p.fillRect(x, y, r.width(), lineHeight, palette().brush( QPalette::Highlight )); // draw icon @@ -426,10 +389,10 @@ void TabBox::drawContents( QPainter * ) else s += (*it)->caption(); - s = fontMetrics().elidedText(s, Qt::ElideMiddle, r.width() - 5 - iconWidth - 8); + s = KStringHandler::cPixelSqueeze(s, fontMetrics(), r.width() - 5 - iconWidth - 8); // draw text - if ( (*it) == current_client ) + if ( (*it) == currentClient() ) p.setPen(palette().color( QPalette::HighlightedText )); else if( (*it)->isMinimized()) { @@ -547,91 +510,6 @@ void TabBox::drawContents( QPainter * ) localPainter.drawImage( QPoint( r.x(), r.y() ), pix.toImage() ); } -void TabBox::updateOutline() - { - Client* c = currentClient(); - if( c == NULL || this->isHidden() || !c->isShown( true ) || !c->isOnCurrentDesktop()) - { - XUnmapWindow( display(), outline_left ); - XUnmapWindow( display(), outline_right ); - XUnmapWindow( display(), outline_top ); - XUnmapWindow( display(), outline_bottom ); - return; - } - // left/right parts are between top/bottom, they don't reach as far as the corners - XMoveResizeWindow( display(), outline_left, c->x(), c->y() + 5, 5, c->height() - 10 ); - XMoveResizeWindow( display(), outline_right, c->x() + c->width() - 5, c->y() + 5, 5, c->height() - 10 ); - XMoveResizeWindow( display(), outline_top, c->x(), c->y(), c->width(), 5 ); - XMoveResizeWindow( display(), outline_bottom, c->x(), c->y() + c->height() - 5, c->width(), 5 ); - { - QPixmap pix( 5, c->height() - 10 ); - QPainter p( &pix ); - p.setPen( Qt::white ); - p.drawLine( 0, 0, 0, pix.height() - 1 ); - p.drawLine( 4, 0, 4, pix.height() - 1 ); - p.setPen( Qt::gray ); - p.drawLine( 1, 0, 1, pix.height() - 1 ); - p.drawLine( 3, 0, 3, pix.height() - 1 ); - p.setPen( Qt::black ); - p.drawLine( 2, 0, 2, pix.height() - 1 ); - p.end(); - XSetWindowBackgroundPixmap( display(), outline_left, pix.handle()); - XSetWindowBackgroundPixmap( display(), outline_right, pix.handle()); - } - { - QPixmap pix( c->width(), 5 ); - QPainter p( &pix ); - p.setPen( Qt::white ); - p.drawLine( 0, 0, pix.width() - 1 - 0, 0 ); - p.drawLine( 4, 4, pix.width() - 1 - 4, 4 ); - p.drawLine( 0, 0, 0, 4 ); - p.drawLine( pix.width() - 1 - 0, 0, pix.width() - 1 - 0, 4 ); - p.setPen( Qt::gray ); - p.drawLine( 1, 1, pix.width() - 1 - 1, 1 ); - p.drawLine( 3, 3, pix.width() - 1 - 3, 3 ); - p.drawLine( 1, 1, 1, 4 ); - p.drawLine( 3, 3, 3, 4 ); - p.drawLine( pix.width() - 1 - 1, 1, pix.width() - 1 - 1, 4 ); - p.drawLine( pix.width() - 1 - 3, 3, pix.width() - 1 - 3, 4 ); - p.setPen( Qt::black ); - p.drawLine( 2, 2, pix.width() - 1 - 2, 2 ); - p.drawLine( 2, 2, 2, 4 ); - p.drawLine( pix.width() - 1 - 2, 2, pix.width() - 1 - 2, 4 ); - p.end(); - XSetWindowBackgroundPixmap( display(), outline_top, pix.handle()); - } - { - QPixmap pix( c->width(), 5 ); - QPainter p( &pix ); - p.setPen( Qt::white ); - p.drawLine( 4, 0, pix.width() - 1 - 4, 0 ); - p.drawLine( 0, 4, pix.width() - 1 - 0, 4 ); - p.drawLine( 0, 4, 0, 0 ); - p.drawLine( pix.width() - 1 - 0, 4, pix.width() - 1 - 0, 0 ); - p.setPen( Qt::gray ); - p.drawLine( 3, 1, pix.width() - 1 - 3, 1 ); - p.drawLine( 1, 3, pix.width() - 1 - 1, 3 ); - p.drawLine( 3, 1, 3, 0 ); - p.drawLine( 1, 3, 1, 0 ); - p.drawLine( pix.width() - 1 - 3, 1, pix.width() - 1 - 3, 0 ); - p.drawLine( pix.width() - 1 - 1, 3, pix.width() - 1 - 1, 0 ); - p.setPen( Qt::black ); - p.drawLine( 2, 2, pix.width() - 1 - 2, 2 ); - p.drawLine( 2, 0, 2, 2 ); - p.drawLine( pix.width() - 1 - 2, 0, pix.width() - 1 - 2 , 2 ); - p.end(); - XSetWindowBackgroundPixmap( display(), outline_bottom, pix.handle()); - } - XClearWindow( display(), outline_left ); - XClearWindow( display(), outline_right ); - XClearWindow( display(), outline_top ); - XClearWindow( display(), outline_bottom ); - XMapWindow( display(), outline_left ); - XMapWindow( display(), outline_right ); - XMapWindow( display(), outline_top ); - XMapWindow( display(), outline_bottom ); - } - void TabBox::hide() { delayedShowTimer.stop(); @@ -709,7 +587,7 @@ void TabBox::handleMouseEvent( XEvent* e ) { if( workspace()->hasClient( *it ) && (num == 0) ) // safety { - setCurrentClient( *it ); + client = *it; break; } num--; diff --git a/useractions.cpp b/useractions.cpp index e351e47a58..e9793278ec 100644 --- a/useractions.cpp +++ b/useractions.cpp @@ -101,22 +101,18 @@ QMenu* Workspace::clientPopup() desk_popup_index = popup->actions().count(); if (options->useTranslucency){ - QMenu *trans_popup = new QMenu( popup ); - QVBoxLayout *transLayout = new QVBoxLayout(trans_popup); - trans_popup->setLayout( transLayout ); - transButton = new QPushButton(trans_popup); - transButton->setObjectName("transButton"); - transButton->setToolTip( i18n("Reset opacity to default value")); - transSlider = new QSlider(trans_popup); - transSlider->setObjectName( "transSlider" ); - transSlider->setRange( 0, 100 ); - transSlider->setValue( 100 ); - transSlider->setOrientation( Qt::Vertical ); - transSlider->setToolTip( i18n("Slide this to set the window's opacity")); - connect(transButton, SIGNAL(clicked()), SLOT(resetClientOpacity())); - connect(transButton, SIGNAL(clicked()), trans_popup, SLOT(hide())); - connect(transSlider, SIGNAL(valueChanged(int)), SLOT(setTransButtonText(int))); - connect(transSlider, SIGNAL(valueChanged(int)), this, SLOT(setPopupClientOpacity(int))); + trans_popup = new QMenu( popup ); + trans_popup->setFont(KGlobalSettings::menuFont()); + connect( trans_popup, SIGNAL( triggered(QAction*) ), this, SLOT( setPopupClientOpacity(QAction*))); + const int levels[] = { 100, 90, 75, 50, 25, 10 }; + for( unsigned int i = 0; + i < sizeof( levels ) / sizeof( levels[ 0 ] ); + ++i ) + { + action = trans_popup->addAction( QString::number( levels[ i ] ) + "%" ); + action->setCheckable( true ); + action->setData( levels[ i ] ); + } action = popup->addMenu( trans_popup ); action->setText( i18n("&Opacity") ); } @@ -163,31 +159,14 @@ QMenu* Workspace::clientPopup() return popup; } -//sets the transparency of the client to given value(given by slider) -void Workspace::setPopupClientOpacity(int value) +void Workspace::setPopupClientOpacity( QAction* action ) { - // TODO + if( active_popup_client == NULL ) + return; + int level = action->data().toInt(); + active_popup_client->setOpacity( level / 100.0 ); } -void Workspace::setTransButtonText(int value) - { - value = 100 - value; - if(value < 0) - transButton->setText("000 %"); - else if (value >= 100 ) - transButton->setText("100 %"); - else if(value < 10) - transButton->setText("00"+QString::number(value)+" %"); - else if(value < 100) - transButton->setText('0'+QString::number(value)+" %"); - } - -void Workspace::resetClientOpacity() - { - // TODO - } - - /*! The client popup menu will become visible soon. @@ -222,6 +201,16 @@ void Workspace::clientPopupAboutToShow() mNoBorderOpAction->setChecked( active_popup_client->noBorder() ); mMinimizeOpAction->setEnabled( active_popup_client->isMinimizable() ); mCloseOpAction->setEnabled( active_popup_client->isCloseable() ); + if (options->useTranslucency) + { + foreach( QAction* action, trans_popup->actions()) + { + if( action->data().toInt() == qRound( active_popup_client->opacity() * 100 )) + action->setChecked( true ); + else + action->setChecked( false ); + } + } } @@ -640,10 +629,10 @@ bool Client::performMouseCommand( Options::MouseCommand command, QPoint globalPo workspace()->windowToNextDesktop( this ); break; case Options::MouseOpacityMore: - // TODO + setOpacity( qMin( opacity() + 0.1, 1.0 )); break; case Options::MouseOpacityLess: - // TODO + setOpacity( qMax( opacity() - 0.1, 0.0 )); break; case Options::MouseNothing: replay = true; diff --git a/utils.cpp b/utils.cpp index 6d68e62e81..34e3a028ff 100644 --- a/utils.cpp +++ b/utils.cpp @@ -30,6 +30,7 @@ License. See the file "COPYING" for the exact licensing terms. #include #include #include + #include #include "atoms.h" @@ -42,19 +43,68 @@ namespace KWinInternal #ifndef KCMRULES -// used to store the return values of -// XShapeQueryExtension. -// Necessary since shaped window are an extension to X -int Shape::kwin_shape_version = 0; -int Shape::kwin_shape_event = 0; +bool Extensions::has_shape = false; +int Extensions::shape_event_base = 0; +bool Extensions::has_randr = false; +int Extensions::randr_event_base = 0; +bool Extensions::has_damage = false; +int Extensions::damage_event_base = 0; +bool Extensions::has_composite = false; +bool Extensions::has_composite_overlay = false; +bool Extensions::has_fixes = false; -// does the window w need a shape combine mask around it? -bool Shape::hasShape( WId w) +void Extensions::init() + { + int dummy; + has_shape = XShapeQueryExtension( display(), &shape_event_base, &dummy); +#ifdef HAVE_XRANDR + has_randr = XRRQueryExtension( display(), &randr_event_base, &dummy ); + if( has_randr ) + { + int major, minor; + XRRQueryVersion( display(), &major, &minor ); + has_randr = ( major > 1 || ( major == 1 && minor >= 1 ) ); + } +#else + has_randr = false; +#endif +#ifdef HAVE_XDAMAGE + has_damage = XDamageQueryExtension( display(), &damage_event_base, &dummy ); +#else + has_damage = false; +#endif +#ifdef HAVE_XCOMPOSITE + has_composite = XCompositeQueryExtension( display(), &dummy, &dummy ); + if( has_composite ) + { + int major, minor; + XCompositeQueryVersion( display(), &major, &minor ); + has_composite = ( major > 0 || minor >= 2 ); + has_composite_overlay = ( major > 0 || minor >= 3 ); + } +#else + has_composite = false; + has_composite_overlay = false; +#endif +#ifdef HAVE_XFIXES + has_fixes = XFixesQueryExtension( display(), &dummy, &dummy ); +#else + has_fixes = false; +#endif + } + +int Extensions::shapeNotifyEvent() + { + return shape_event_base + ShapeNotify; + } + +// does the window w need a shape combine mask around it? +bool Extensions::hasShape( Window w ) { int xws, yws, xbs, ybs; unsigned int wws, hws, wbs, hbs; int boundingShaped = 0, clipShaped = 0; - if (!available()) + if( !Extensions::shapeAvailable()) return false; XShapeQueryExtents(display(), w, &boundingShaped, &xws, &yws, &wws, &hws, @@ -62,21 +112,22 @@ bool Shape::hasShape( WId w) return boundingShaped != 0; } -int Shape::shapeEvent() +int Extensions::randrNotifyEvent() { - return kwin_shape_event; +#ifdef HAVE_XRANDR + return randr_event_base + RRScreenChangeNotify; +#else + return 0; +#endif } -void Shape::init() +int Extensions::damageNotifyEvent() { - kwin_shape_version = 0; - int dummy; - if( !XShapeQueryExtension( display(), &kwin_shape_event, &dummy )) - return; - int major, minor; - if( !XShapeQueryVersion( display(), &major, &minor )) - return; - kwin_shape_version = major * 0x10 + minor; +#ifdef HAVE_XDAMAGE + return damage_event_base + XDamageNotify; +#else + return 0; +#endif } void Motif::readFlags( WId w, bool& noborder, bool& resize, bool& move, @@ -300,7 +351,6 @@ bool grabbedXServer() { return server_grab_count > 0; } - #endif bool isLocalMachine( const QByteArray& host ) @@ -364,8 +414,6 @@ void ShortcutDialog::accept() KShortcutDialog::accept(); } #endif - - } // namespace #ifndef KCMRULES diff --git a/workspace.cpp b/workspace.cpp index d867ec6e08..9363e92d7c 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -573,7 +573,7 @@ void Workspace::removeClient( Client* c, allowed_t ) if( client_keys_client == c ) setupWindowShortcutDone( false ); - if( !c->shortcut().isNull()) + if( !c->shortcut().isEmpty()) c->setShortcut( QString() ); // remove from client_keys if( c->isDialog()) @@ -2403,7 +2403,7 @@ void Workspace::helperDialog( const QString& message, const Client* c ) { KAction* action = keys->action( "Window Operations Menu" ); QString shortcut = QString( "%1 (%2)" ).arg( action->text() ) - .arg( action->globalShortcut().seq( 0 ).toString()); + .arg( action->globalShortcut().primary().toString()); args << "--msgbox" << i18n( "You have selected to show a window without its border.\n" "Without the border, you will not be able to enable the border " @@ -2416,7 +2416,7 @@ void Workspace::helperDialog( const QString& message, const Client* c ) { KAction* action = keys->action( "Window Operations Menu" ); QString shortcut = QString( "%1 (%2)" ).arg( action->text() ) - .arg( action->globalShortcut().seq( 0 ).toString()); + .arg( action->globalShortcut().primary().toString()); args << "--msgbox" << i18n( "You have selected to show a window in fullscreen mode.\n" "If the application itself does not have an option to turn the fullscreen "