diff --git a/client.cpp b/client.cpp index acd1f4b51..118959ec2 100644 --- a/client.cpp +++ b/client.cpp @@ -1,1503 +1,1858 @@ /***************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ #include "client.h" #include #include #include -#include +#include #include #include #include #include #include #include #include "bridge.h" #include "group.h" #include "workspace.h" #include "atoms.h" #include "notifications.h" #include "rules.h" -#include "scene.h" -#include "effects.h" -#include "deleted.h" #include #include // put all externs before the namespace statement to allow the linker // to resolve them properly namespace KWinInternal { /* Creating a client: - only by calling Workspace::createClient() - it creates a new client and calls manage() for it Destroying a client: - destroyClient() - only when the window itself has been destroyed - releaseWindow() - the window is kept, only the client itself is destroyed */ /*! \class Client client.h \brief The Client class encapsulates a window decoration frame. */ /*! This ctor is "dumb" - it only initializes data. All the real initialization is done in manage(). */ Client::Client( Workspace *ws ) - : Toplevel( ws ), + : QObject( NULL ), client( None ), wrapper( None ), + frame( None ), decoration( NULL ), + wspace( ws ), bridge( new Bridge( this )), move_faked_activity( false ), move_resize_grab_window( None ), transient_for( NULL ), transient_for_id( None ), original_transient_for_id( None ), in_group( NULL ), window_group( None ), in_layer( UnknownLayer ), ping_timer( NULL ), process_killer( NULL ), user_time( CurrentTime ), // not known yet allowed_actions( 0 ), - block_geometry_updates( 0 ), + postpone_geometry_updates( 0 ), pending_geometry_update( false ), shade_geometry_change( false ), border_left( 0 ), border_right( 0 ), border_top( 0 ), border_bottom( 0 ), sm_stacking_order( -1 ), demandAttentionKNotifyTimer( NULL ) // SELI do all as initialization { autoRaiseTimer = 0; shadeHoverTimer = 0; // set the initial mapping state mapping_state = WithdrawnState; desk = 0; // no desktop yet mode = PositionCenter; buttonDown = false; moveResizeMode = false; info = NULL; shade_mode = ShadeNone; active = false; deleting = false; keep_above = false; keep_below = false; + is_shape = false; motif_noborder = false; motif_may_move = true; motif_may_resize = true; motif_may_close = true; fullscreen_mode = FullScreenNone; skip_taskbar = false; original_skip_taskbar = false; minimized = false; hidden = false; modal = false; noborder = false; user_noborder = false; - not_obscured = false; urgency = false; ignore_focus_stealing = false; demands_attention = false; check_active_modal = false; Pdeletewindow = 0; Ptakefocus = 0; Ptakeactivity = 0; Pcontexthelp = 0; Pping = 0; input = false; skip_pager = false; max_mode = MaximizeRestore; maxmode_restore = MaximizeRestore; cmap = None; - geom = QRect( 0, 0, 100, 100 ); // so that decorations don't start with size being (0,0) + frame_geometry = QRect( 0, 0, 100, 100 ); // so that decorations don't start with size being (0,0) client_size = QSize( 100, 100 ); // SELI initialize xsizehints?? } /*! "Dumb" destructor. */ Client::~Client() { assert(!moveResizeMode); assert( client == None ); - assert( wrapper == None ); -// assert( frameId() == None ); + assert( frame == None && wrapper == None ); assert( decoration == NULL ); - assert( block_geometry_updates == 0 ); + assert( postpone_geometry_updates == 0 ); assert( !check_active_modal ); + delete info; delete bridge; } // use destroyClient() or releaseWindow(), Client instances cannot be deleted directly void Client::deleteClient( Client* c, allowed_t ) { delete c; } /*! Releases the window. The client has done its job and the window is still existing. */ void Client::releaseWindow( bool on_shutdown ) { assert( !deleting ); deleting = true; - Deleted* del = Deleted::create( this ); - if( effects ) - { - effects->windowClosed( effectWindow()); - scene->windowClosed( this, del ); - } - finishCompositing(); workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules StackingUpdatesBlocker blocker( workspace()); if (moveResizeMode) leaveMoveResize(); finishWindowRules(); - ++block_geometry_updates; - if( isOnCurrentDesktop() && isShown( true )) - addWorkspaceRepaint( geometry()); + ++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(); 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) if( !on_shutdown ) workspace()->clientHidden( this ); XUnmapWindow( display(), frameId()); // destroying decoration would cause ugly visual effect destroyDecoration(); cleanGrouping(); if( !on_shutdown ) { workspace()->removeClient( this, Allowed ); // only when the window is being unmapped, not when closing down KWin // (NETWM sections 5.5,5.7) info->setDesktop( 0 ); desk = 0; info->setState( 0, info->state()); // reset all state flags } XDeleteProperty( display(), client, atoms->kde_net_wm_user_creation_time); XDeleteProperty( display(), client, atoms->net_frame_extents ); XDeleteProperty( display(), client, atoms->kde_net_wm_frame_strut ); XReparentWindow( display(), client, workspace()->rootWin(), x(), y()); XRemoveFromSaveSet( display(), client ); XSelectInput( display(), client, NoEventMask ); if( on_shutdown ) { // map the window, so it can be found after another WM is started XMapWindow( display(), client ); // TODO preserve minimized, shaded etc. state? } else { // Make sure it's not mapped if the app unmapped it (#65279). The app // may do map+unmap before we initially map the window by calling rawShow() from manage(). XUnmapWindow( display(), client ); } client = None; XDestroyWindow( display(), wrapper ); wrapper = None; - XDestroyWindow( display(), frameId()); -// frame = None; - --block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry - disownDataPassedToDeleted(); - del->unrefWindow(); + XDestroyWindow( display(), frame ); + frame = None; + --postpone_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry + checkNonExistentClients(); deleteClient( this, Allowed ); + ungrabXServer(); } // like releaseWindow(), but this one is called when the window has been already destroyed // (e.g. the application closed it) void Client::destroyClient() { assert( !deleting ); deleting = true; - Deleted* del = Deleted::create( this ); - if( effects ) - { - effects->windowClosed( effectWindow()); - scene->windowClosed( this, del ); - } - finishCompositing(); workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules StackingUpdatesBlocker blocker( workspace()); if (moveResizeMode) leaveMoveResize(); finishWindowRules(); - ++block_geometry_updates; - if( isOnCurrentDesktop() && isShown( true )) - addWorkspaceRepaint( geometry()); + ++postpone_geometry_updates; setModal( false ); hidden = true; // so that it's not considered visible anymore workspace()->clientHidden( this ); destroyDecoration(); cleanGrouping(); workspace()->removeClient( this, Allowed ); client = None; // invalidate XDestroyWindow( display(), wrapper ); wrapper = None; - XDestroyWindow( display(), frameId()); -// frame = None; - --block_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry - disownDataPassedToDeleted(); - del->unrefWindow(); + XDestroyWindow( display(), frame ); + frame = None; + --postpone_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry + checkNonExistentClients(); deleteClient( this, Allowed ); } void Client::updateDecoration( bool check_workspace_pos, bool force ) { if( !force && (( decoration == NULL && noBorder()) || ( decoration != NULL && !noBorder()))) return; bool do_show = false; - QRect oldgeom = geometry(); - blockGeometryUpdates( true ); + postponeGeometryUpdates( true ); if( force ) destroyDecoration(); if( !noBorder()) { + setMask( QRegion()); // reset shape mask decoration = workspace()->createDecoration( bridge ); // TODO check decoration's minimum size? decoration->init(); decoration->widget()->installEventFilter( this ); XReparentWindow( display(), decoration->widget()->winId(), frameId(), 0, 0 ); decoration->widget()->lower(); decoration->borders( border_left, border_right, border_top, border_bottom ); int save_workarea_diff_x = workarea_diff_x; int save_workarea_diff_y = workarea_diff_y; move( calculateGravitation( false )); plainResize( sizeForClientSize( clientSize()), ForceGeometrySet ); workarea_diff_x = save_workarea_diff_x; workarea_diff_y = save_workarea_diff_y; do_show = true; - if( compositing() ) - discardWindowPixmap(); - if( scene != NULL ) - scene->windowGeometryShapeChanged( this ); - if( effects != NULL ) - effects->windowGeometryShapeChanged( effectWindow(), oldgeom ); } else destroyDecoration(); if( check_workspace_pos ) checkWorkspacePosition(); - blockGeometryUpdates( false ); + postponeGeometryUpdates( false ); if( do_show ) decoration->widget()->show(); updateFrameExtents(); } void Client::destroyDecoration() { - QRect oldgeom = geometry(); if( decoration != NULL ) { delete decoration; decoration = NULL; QPoint grav = calculateGravitation( true ); border_left = border_right = border_top = border_bottom = 0; setMask( QRegion()); // reset shape mask int save_workarea_diff_x = workarea_diff_x; int save_workarea_diff_y = workarea_diff_y; plainResize( sizeForClientSize( clientSize()), ForceGeometrySet ); move( grav ); workarea_diff_x = save_workarea_diff_x; workarea_diff_y = save_workarea_diff_y; - if( compositing() ) - discardWindowPixmap(); - if( scene != NULL && !deleting ) - scene->windowGeometryShapeChanged( this ); - if( effects != NULL && !deleting ) - effects->windowGeometryShapeChanged( effectWindow(), oldgeom ); } } void Client::checkBorderSizes() { if( decoration == NULL ) return; int new_left, new_right, new_top, new_bottom; decoration->borders( new_left, new_right, new_top, new_bottom ); if( new_left == border_left && new_right == border_right && new_top == border_top && new_bottom == border_bottom ) return; - GeometryUpdatesBlocker blocker( this ); + GeometryUpdatesPostponer blocker( this ); move( calculateGravitation( true )); border_left = new_left; border_right = new_right; border_top = new_top; border_bottom = new_bottom; if (border_left != new_left || border_right != new_right || border_top != new_top || border_bottom != new_bottom) move( calculateGravitation( false )); plainResize( sizeForClientSize( clientSize()), ForceGeometrySet ); checkWorkspacePosition(); } void Client::detectNoBorder() { - if( shape()) + if( Shape::hasShape( window())) { noborder = true; return; } switch( windowType()) { case NET::Desktop : case NET::Dock : case NET::TopMenu : case NET::Splash : noborder = true; break; case NET::Unknown : case NET::Normal : case NET::Toolbar : case NET::Menu : case NET::Dialog : case NET::Utility : noborder = false; break; default: assert( false ); } // NET::Override is some strange beast without clear definition, usually // just meaning "noborder", so let's treat it only as such flag, and ignore it as // a window type otherwise (SUPPORTED_WINDOW_TYPES_MASK doesn't include it) if( info->windowType( SUPPORTED_WINDOW_TYPES_MASK | NET::OverrideMask ) == NET::Override ) noborder = true; } void Client::updateFrameExtents() { NETStrut strut; strut.left = border_left; strut.right = border_right; strut.top = border_top; strut.bottom = border_bottom; info->setFrameExtents( strut ); } // Resizes the decoration, and makes sure the decoration widget gets resize event // even if the size hasn't changed. This is needed to make sure the decoration // re-layouts (e.g. when options()->moveResizeMaximizedWindows() changes, // the decoration may turn on/off some borders, but the actual size // of the decoration stays the same). void Client::resizeDecoration( const QSize& s ) { if( decoration == NULL ) return; QSize oldsize = decoration->widget()->size(); decoration->resize( s ); if( oldsize == s ) { QResizeEvent e( s, oldsize ); QApplication::sendEvent( decoration->widget(), &e ); } } bool Client::noBorder() const { return noborder || isFullScreen() || user_noborder || motif_noborder; } bool Client::userCanSetNoBorder() const { return !noborder && !isFullScreen() && !isShade(); } bool Client::isUserNoBorder() const { return user_noborder; } void Client::setUserNoBorder( bool set ) { if( !userCanSetNoBorder()) return; set = rules()->checkNoBorder( set ); if( user_noborder == set ) return; user_noborder = set; updateDecoration( true, false ); updateWindowRules(); } 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( compositing()) - addDamageFull(); - if( scene != NULL ) - scene->windowGeometryShapeChanged( this ); - if( effects != NULL ) - effects->windowGeometryShapeChanged( effectWindow(), geometry()); // 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 ) { _mask = reg; if( reg.isEmpty()) XShapeCombineMask( display(), frameId(), ShapeBounding, 0, 0, None, ShapeSet ); else if( mode == X::Unsorted ) XShapeCombineRegion( display(), frameId(), ShapeBounding, 0, 0, reg.handle(), ShapeSet ); else { QVector< QRect > rects = reg.rects(); XRectangle* xrects = new XRectangle[ rects.count() ]; for( int i = 0; i < rects.count(); ++i ) { xrects[ i ].x = rects[ i ].x(); xrects[ i ].y = rects[ i ].y(); xrects[ i ].width = rects[ i ].width(); xrects[ i ].height = rects[ i ].height(); } XShapeCombineRectangles( display(), frameId(), ShapeBounding, 0, 0, xrects, rects.count(), ShapeSet, mode ); delete[] xrects; } - if( compositing()) - addDamageFull(); - if( scene != NULL ) - scene->windowGeometryShapeChanged( this ); - if( effects != NULL ) - effects->windowGeometryShapeChanged( effectWindow(), geometry()); + updateShape(); } QRegion Client::mask() const { if( _mask.isEmpty()) return QRegion( 0, 0, width(), height()); return _mask; } void Client::hideClient( bool hide ) { if( hidden == hide ) return; hidden = hide; updateVisibility(); } /* Returns whether the window is minimizable or not */ bool Client::isMinimizable() const { if( isSpecialWindow()) return false; if( isTransient()) { // #66868 - let other xmms windows be minimized when the mainwindow is minimized bool shown_mainwindow = false; ClientList mainclients = mainClients(); for( ClientList::ConstIterator it = mainclients.begin(); it != mainclients.end(); ++it ) { if( (*it)->isShown( true )) shown_mainwindow = true; } if( !shown_mainwindow ) return true; } // this is here because kicker's taskbar doesn't provide separate entries // for windows with an explicitly given parent // TODO perhaps this should be redone if( transientFor() != NULL ) return false; if( !wantsTabFocus()) // SELI - NET::Utility? why wantsTabFocus() - skiptaskbar? ? return false; return true; } /*! Minimizes this client plus its transients */ void Client::minimize( bool avoid_animation ) { if ( !isMinimizable() || isMinimized()) return; Notify::raise( Notify::Minimize ); + // SELI mainClients().isEmpty() ??? - and in unminimize() too + if ( mainClients().isEmpty() && isOnCurrentDesktop() && isShown( true ) && !avoid_animation ) + animateMinimizeOrUnminimize( true ); // was visible or shaded + minimized = true; updateVisibility(); updateAllowedActions(); workspace()->updateMinimizedOfTransients( this ); updateWindowRules(); workspace()->updateFocusChains( this, Workspace::FocusChainMakeLast ); - if( effects && !avoid_animation ) // TODO shouldn't it tell effects at least about the change? - effects->windowMinimized( effectWindow()); } void Client::unminimize( bool avoid_animation ) { if( !isMinimized()) return; Notify::raise( Notify::UnMinimize ); minimized = false; + if( isOnCurrentDesktop() && isShown( true )) + { + if( mainClients().isEmpty() && !avoid_animation ) + animateMinimizeOrUnminimize( false ); + } updateVisibility(); updateAllowedActions(); workspace()->updateMinimizedOfTransients( this ); updateWindowRules(); - if( effects && !avoid_animation ) - effects->windowUnminimized( effectWindow()); } -QRect Client::iconGeometry() const +extern bool blockAnimation; + +void Client::animateMinimizeOrUnminimize( bool minimize ) { +#ifdef __GNUC__ + #warning implement kwin animation +#endif + if ( 1 || blockAnimation ) + return; + if ( !options->animateMinimize ) + return; + + if( decoration != NULL && decoration->animateMinimize( minimize )) + return; // decoration did it + + // the function is a bit tricky since it will ensure that an + // animation action needs always the same time regardless of the + // performance of the machine or the X-Server. + + float lf,rf,tf,bf,step; + + int speed = options->animateMinimizeSpeed; + if ( speed > 10 ) + speed = 10; + if ( speed < 0 ) + speed = 0; + + step = 40. * (11 - speed ); + NETRect r = info->iconGeometry(); - QRect geom( r.pos.x, r.pos.y, r.size.width, r.size.height ); - if( geom.isValid() ) - return geom; - else - { - // Check all mainwindows of this window (recursively) - foreach( Client* mainwin, mainClients() ) + QRect icongeom( r.pos.x, r.pos.y, r.size.width, r.size.height ); + if ( !icongeom.isValid() ) + return; + + QPixmap pm = animationPixmap( minimize ? width() : icongeom.width() ); + + QRect before, after; + if ( minimize ) + { + before = QRect( x(), y(), width(), pm.height() ); + after = QRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() ); + } + else + { + before = QRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() ); + after = QRect( x(), y(), width(), pm.height() ); + } + + lf = (after.left() - before.left())/step; + rf = (after.right() - before.right())/step; + tf = (after.top() - before.top())/step; + bf = (after.bottom() - before.bottom())/step; + + grabXServer(); + + QRect area = before; + QRect area2; + QPixmap pm2; + + QTime t; + t.start(); + float diff; + + QPainter p ( workspace()->desktopWidget() ); + bool need_to_clear = false; + QPixmap pm3; + do + { + if (area2 != area) { - geom = mainwin->iconGeometry(); - if( geom.isValid() ) - return geom; + pm = animationPixmap( area.width() ); + pm2 = QPixmap::grabWindow( rootWindow(), area.x(), area.y(), area.width(), area.height() ); + p.drawPixmap( area.x(), area.y(), pm ); + if ( need_to_clear ) + { + p.drawPixmap( area2.x(), area2.y(), pm3 ); + need_to_clear = false; + } + area2 = area; } - // No mainwindow (or their parents) with icon geometry was found - return QRect(); - } + XFlush(display()); + XSync( display(), false ); + diff = t.elapsed(); + if (diff > step) + diff = step; + area.setLeft(before.left() + int(diff*lf)); + area.setRight(before.right() + int(diff*rf)); + area.setTop(before.top() + int(diff*tf)); + area.setBottom(before.bottom() + int(diff*bf)); + if (area2 != area ) + { + if ( area2.intersects( area ) ) + p.drawPixmap( area2.x(), area2.y(), pm2 ); + else + { // no overlap, we can clear later to avoid flicker + pm3 = pm2; + need_to_clear = true; + } + } + } while ( t.elapsed() < step); + if (area2 == area || need_to_clear ) + p.drawPixmap( area2.x(), area2.y(), pm2 ); + + p.end(); + ungrabXServer(); } + +/*! + The pixmap shown during (un)minimalization animation + */ +QPixmap Client::animationPixmap( int w ) + { + QFont font = options->font(isActive()); + QFontMetrics fm( font ); + QPixmap pm( w, fm.lineSpacing() ); + pm.fill( options->color(Options::ColorTitleBar, isActive() || isMinimized() ) ); + QPainter p( &pm ); + p.setPen(options->color(Options::ColorFont, isActive() || isMinimized() )); + p.setFont(options->font(isActive())); + p.drawText( pm.rect(), Qt::AlignLeft|Qt::AlignVCenter|Qt::TextSingleLine, caption() ); + return pm; + } + + bool Client::isShadeable() const { return !isSpecialWindow() && !noBorder(); } void Client::setShade( ShadeMode mode ) { if( !isShadeable()) return; mode = rules()->checkShade( mode ); if( shade_mode == mode ) return; bool was_shade = isShade(); ShadeMode was_shade_mode = shade_mode; shade_mode = mode; if( was_shade == isShade()) { if( decoration != NULL ) // decoration may want to update after e.g. hover-shade changes decoration->shadeChange(); return; // no real change in shaded state } if( shade_mode == ShadeNormal ) { if ( isShown( true ) && isOnCurrentDesktop()) Notify::raise( Notify::ShadeUp ); } else if( shade_mode == ShadeNone ) { if( isShown( true ) && isOnCurrentDesktop()) Notify::raise( Notify::ShadeDown ); } assert( decoration != NULL ); // noborder windows can't be shaded - GeometryUpdatesBlocker blocker( this ); + GeometryUpdatesPostponer blocker( this ); // decorations may turn off some borders when shaded decoration->borders( border_left, border_right, border_top, border_bottom ); + int as = options->animateShade? 10 : 1; // TODO all this unmapping, resizing etc. feels too much duplicated from elsewhere if ( isShade()) { // shade_mode == ShadeNormal - addWorkspaceRepaint( geometry()); + // we're about to shade, texx xcompmgr to prepare + long _shade = 1; + XChangeProperty(display(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &_shade, 1L); // shade + int h = height(); shade_geometry_change = true; QSize s( sizeForClientSize( QSize( clientSize()))); s.setHeight( border_top + border_bottom ); XSelectInput( display(), wrapper, ClientWinMask ); // avoid getting UnmapNotify XUnmapWindow( display(), wrapper ); XUnmapWindow( display(), client ); XSelectInput( display(), wrapper, ClientWinMask | SubstructureNotifyMask ); + //as we hid the unmap event, xcompmgr didn't recognize the client wid has vanished, so we'll extra inform it + //done xcompmgr workaround +// FRAME repaint( false ); +// bool wasStaticContents = testWFlags( WStaticContents ); +// setWFlags( WStaticContents ); + int step = qMax( 4, QABS( h - s.height() ) / as )+1; + do + { + h -= step; + XResizeWindow( display(), frameId(), s.width(), h ); + resizeDecoration( QSize( s.width(), h )); + QApplication::syncX(); + } while ( h > s.height() + step ); +// if ( !wasStaticContents ) +// clearWFlags( WStaticContents ); plainResize( s ); shade_geometry_change = false; if( isActive()) { if( was_shade_mode == ShadeHover ) workspace()->activateNextClient( this ); else workspace()->focusToNull(); } + // tell xcompmgr shade's done + _shade = 2; + XChangeProperty(display(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &_shade, 1L); } else { + int h = height(); shade_geometry_change = true; QSize s( sizeForClientSize( clientSize())); +// FRAME bool wasStaticContents = testWFlags( WStaticContents ); +// setWFlags( WStaticContents ); + int step = qMax( 4, QABS( h - s.height() ) / as )+1; + do + { + h += step; + XResizeWindow( display(), frameId(), s.width(), h ); + resizeDecoration( QSize( s.width(), h )); + // assume a border + // we do not have time to wait for X to send us paint events +// FRAME repaint( 0, h - step-5, width(), step+5, true); + QApplication::syncX(); + } while ( h < s.height() - step ); +// if ( !wasStaticContents ) +// clearWFlags( WStaticContents ); shade_geometry_change = false; plainResize( s ); if( shade_mode == ShadeHover || shade_mode == ShadeActivated ) setActive( true ); XMapWindow( display(), wrapperId()); XMapWindow( display(), window()); + XDeleteProperty (display(), client, atoms->net_wm_window_shade); if ( isActive() ) workspace()->requestFocus( this ); } checkMaximizeGeometry(); info->setState( isShade() ? NET::Shaded : 0, NET::Shaded ); info->setState( isShown( false ) ? 0 : NET::Hidden, NET::Hidden ); - discardWindowPixmap(); updateVisibility(); updateAllowedActions(); workspace()->updateMinimizedOfTransients( this ); decoration->shadeChange(); updateWindowRules(); } void Client::shadeHover() { setShade( ShadeHover ); cancelShadeHover(); } void Client::cancelShadeHover() { delete shadeHoverTimer; shadeHoverTimer = 0; } void Client::toggleShade() { // if the mode is ShadeHover or ShadeActive, cancel shade too setShade( shade_mode == ShadeNone ? ShadeNormal : ShadeNone ); } void Client::updateVisibility() { if( deleting ) return; bool show = true; if( hidden ) { setMappingState( IconicState ); info->setState( NET::Hidden, NET::Hidden ); setSkipTaskbar( true, false ); // also hide from taskbar rawHide(); show = false; } else { setSkipTaskbar( original_skip_taskbar, false ); } if( minimized ) { setMappingState( IconicState ); info->setState( NET::Hidden, NET::Hidden ); rawHide(); show = false; } if( show ) info->setState( 0, NET::Hidden ); if( !isOnCurrentDesktop()) { setMappingState( IconicState ); rawHide(); show = false; } if( show ) { bool belongs_to_desktop = false; for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); ++it ) if( (*it)->isDesktop()) { belongs_to_desktop = true; break; } if( !belongs_to_desktop && workspace()->showingDesktop()) workspace()->resetShowingDesktop( true ); if( isShade()) setMappingState( IconicState ); else setMappingState( NormalState ); rawShow(); } } /*! Sets the client window's mapping state. Possible values are WithdrawnState, IconicState, NormalState. */ void Client::setMappingState(int s) { assert( client != None ); assert( !deleting || s == WithdrawnState ); if( mapping_state == s ) return; bool was_unmanaged = ( mapping_state == WithdrawnState ); mapping_state = s; if( mapping_state == WithdrawnState ) { XDeleteProperty( display(), window(), atoms->wm_state ); return; } assert( s == NormalState || s == IconicState ); unsigned long data[2]; data[0] = (unsigned long) s; data[1] = (unsigned long) None; XChangeProperty(display(), window(), atoms->wm_state, atoms->wm_state, 32, PropModeReplace, (unsigned char *)data, 2); - if( was_unmanaged ) // manage() did block_geometry_updates = 1, now it's ok to finally set the geometry - blockGeometryUpdates( false ); + if( was_unmanaged ) // manage() did postpone_geometry_updates = 1, now it's ok to finally set the geometry + postponeGeometryUpdates( false ); } /*! Reimplemented to map the managed window in the window wrapper. Proper mapping state should be set before showing the client. */ void Client::rawShow() { if( decoration != NULL ) decoration->widget()->show(); // not really necessary, but let it know the state - XMapWindow( display(), frameId()); + XMapWindow( display(), frame ); if( !isShade()) { XMapWindow( display(), wrapper ); XMapWindow( display(), client ); } - // XComposite invalidates backing pixmaps on unmap (minimize, different - // virtual desktop, etc.). We kept the last known good pixmap around - // for use in effects, but now we want to have access to the new pixmap - if( compositing() ) - discardWindowPixmap(); } /*! Reimplemented to unmap the managed window in the window wrapper. Also informs the workspace. Proper mapping state should be set before hiding the client. */ void Client::rawHide() { - addWorkspaceRepaint( 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, // which won't be missed, so this shouldn't be a problem. The chance the real UnmapNotify // 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(), frameId()); + XUnmapWindow( display(), frame ); XUnmapWindow( display(), wrapper ); XUnmapWindow( display(), client ); XSelectInput( display(), wrapper, ClientWinMask | SubstructureNotifyMask ); if( decoration != NULL ) decoration->widget()->hide(); // not really necessary, but let it know the state workspace()->clientHidden( this ); } void Client::sendClientMessage(Window w, Atom a, Atom protocol, long data1, long data2, long data3) { XEvent ev; long mask; memset(&ev, 0, sizeof(ev)); ev.xclient.type = ClientMessage; ev.xclient.window = w; ev.xclient.message_type = a; ev.xclient.format = 32; ev.xclient.data.l[0] = protocol; ev.xclient.data.l[1] = xTime(); ev.xclient.data.l[2] = data1; ev.xclient.data.l[3] = data2; ev.xclient.data.l[4] = data3; mask = 0L; if (w == rootWindow()) mask = SubstructureRedirectMask; /* magic! */ XSendEvent(display(), w, False, mask, &ev); } /* Returns whether the window may be closed (have a close button) */ bool Client::isCloseable() const { return rules()->checkCloseable( motif_may_close && !isSpecialWindow()); } /*! Closes the window by either sending a delete_window message or using XKill. */ void Client::closeWindow() { if( !isCloseable()) return; // Update user time, because the window may create a confirming dialog. updateUserTime(); if ( Pdeletewindow ) { Notify::raise( Notify::Close ); sendClientMessage( window(), atoms->wm_protocols, atoms->wm_delete_window); pingWindow(); } else { // client will not react on wm_delete_window. We have not choice // but destroy his connection to the XServer. killWindow(); } } /*! Kills the window via XKill */ void Client::killWindow() { kDebug( 1212 ) << "Client::killWindow():" << caption() << endl; // not sure if we need an Notify::Kill or not.. until then, use // Notify::Close Notify::raise( Notify::Close ); if( isDialog()) Notify::raise( Notify::TransDelete ); if( isNormalWindow()) Notify::raise( Notify::Delete ); killProcess( false ); // always kill this client at the server XKillClient(display(), window() ); destroyClient(); } // send a ping to the window using _NET_WM_PING if possible // if it doesn't respond within a reasonable time, it will be // killed void Client::pingWindow() { if( !Pping ) return; // can't ping :( if( options->killPingTimeout == 0 ) return; // turned off if( ping_timer != NULL ) return; // pinging already ping_timer = new QTimer( this ); connect( ping_timer, SIGNAL( timeout()), SLOT( pingTimeout())); ping_timer->setSingleShot( true ); ping_timer->start( options->killPingTimeout ); ping_timestamp = xTime(); workspace()->sendPingToWindow( window(), ping_timestamp ); } void Client::gotPing( Time timestamp ) { if( timestamp != ping_timestamp ) return; delete ping_timer; ping_timer = NULL; if( process_killer != NULL ) { process_killer->kill(); delete process_killer; process_killer = NULL; } } void Client::pingTimeout() { kDebug( 1212 ) << "Ping timeout:" << caption() << endl; delete ping_timer; ping_timer = NULL; killProcess( true, ping_timestamp ); } void Client::killProcess( bool ask, Time timestamp ) { if( process_killer != NULL ) return; Q_ASSERT( !ask || timestamp != CurrentTime ); QByteArray machine = wmClientMachine( true ); pid_t pid = info->pid(); if( pid <= 0 || machine.isEmpty()) // needed properties missing return; kDebug( 1212 ) << "Kill process:" << pid << "(" << machine << ")" << endl; if( !ask ) { if( machine != "localhost" ) { - KProcess proc; + K3Process proc; proc << "xon" << machine << "kill" << QString::number( pid ); - proc.start( KProcess::DontCare ); + proc.start( K3Process::DontCare ); } else ::kill( pid, SIGTERM ); } else { // SELI TODO handle the window created by handler specially (on top,urgent?) - process_killer = new KProcess( this ); + process_killer = new K3Process( this ); *process_killer << KStandardDirs::findExe( "kwin_killer_helper" ) << "--pid" << QByteArray().setNum( pid ) << "--hostname" << machine << "--windowname" << caption().toUtf8() << "--applicationname" << resourceClass() << "--wid" << QString::number( window() ) << "--timestamp" << QString::number( timestamp ); - connect( process_killer, SIGNAL( processExited( KProcess* )), + connect( process_killer, SIGNAL( processExited( K3Process* )), SLOT( processKillerExited())); - if( !process_killer->start( KProcess::NotifyOnExit )) + if( !process_killer->start( K3Process::NotifyOnExit )) { delete process_killer; process_killer = NULL; return; } } } void Client::processKillerExited() { kDebug( 1212 ) << "Killer exited" << endl; delete process_killer; process_killer = NULL; } void Client::setSkipTaskbar( bool b, bool from_outside ) { int was_wants_tab_focus = wantsTabFocus(); if( from_outside ) { b = rules()->checkSkipTaskbar( b ); original_skip_taskbar = b; } if ( b == skipTaskbar() ) return; skip_taskbar = b; info->setState( b?NET::SkipTaskbar:0, NET::SkipTaskbar ); updateWindowRules(); if( was_wants_tab_focus != wantsTabFocus()) workspace()->updateFocusChains( this, isActive() ? Workspace::FocusChainMakeFirst : Workspace::FocusChainUpdate ); } void Client::setSkipPager( bool b ) { b = rules()->checkSkipPager( b ); if ( b == skipPager() ) return; skip_pager = b; info->setState( b?NET::SkipPager:0, NET::SkipPager ); updateWindowRules(); } void Client::setModal( bool m ) { // Qt-3.2 can have even modal normal windows :( if( modal == m ) return; modal = m; if( !modal ) return; // changing modality for a mapped window is weird (?) // _NET_WM_STATE_MODAL should possibly rather be _NET_WM_WINDOW_TYPE_MODAL_DIALOG } void Client::setDesktop( int desktop ) { if( desktop != NET::OnAllDesktops ) // do range check desktop = qMax( 1, qMin( workspace()->numberOfDesktops(), desktop )); desktop = rules()->checkDesktop( desktop ); if( desk == desktop ) return; int was_desk = desk; desk = desktop; info->setDesktop( desktop ); if(( was_desk == NET::OnAllDesktops ) != ( desktop == NET::OnAllDesktops )) { // onAllDesktops changed if ( isShown( true )) Notify::raise( isOnAllDesktops() ? Notify::OnAllDesktops : Notify::NotOnAllDesktops ); workspace()->updateOnAllDesktopsOfTransients( this ); } if( decoration != NULL ) decoration->desktopChange(); workspace()->updateFocusChains( this, Workspace::FocusChainMakeFirst ); updateVisibility(); updateWindowRules(); } -/*! - Returns the virtual desktop within the workspace() the client window - is located in, 0 if it isn't located on any special desktop (not mapped yet), - or NET::OnAllDesktops. Do not use desktop() directly, use - isOnDesktop() instead. - */ -int Client::desktop() const - { - return desk; - } - void Client::setOnAllDesktops( bool b ) { if(( b && isOnAllDesktops()) || ( !b && !isOnAllDesktops())) return; if( b ) setDesktop( NET::OnAllDesktops ); else setDesktop( workspace()->currentDesktop()); } +bool Client::isOnCurrentDesktop() const + { + return isOnDesktop( workspace()->currentDesktop()); + } + // performs activation and/or raising of the window void Client::takeActivity( int flags, bool handled, allowed_t ) { if( !handled || !Ptakeactivity ) { if( flags & ActivityFocus ) takeFocus( Allowed ); if( flags & ActivityRaise ) workspace()->raiseClient( this ); return; } #ifndef NDEBUG static Time previous_activity_timestamp; static Client* previous_client; if( previous_activity_timestamp == xTime() && previous_client != this ) { kDebug( 1212 ) << "Repeated use of the same X timestamp for activity" << endl; kDebug( 1212 ) << kBacktrace() << endl; } previous_activity_timestamp = xTime(); previous_client = this; #endif workspace()->sendTakeActivity( this, xTime(), flags ); } // performs the actual focusing of the window using XSetInputFocus and WM_TAKE_FOCUS void Client::takeFocus( allowed_t ) { #ifndef NDEBUG static Time previous_focus_timestamp; static Client* previous_client; if( previous_focus_timestamp == xTime() && previous_client != this ) { kDebug( 1212 ) << "Repeated use of the same X timestamp for focus" << endl; kDebug( 1212 ) << kBacktrace() << endl; } previous_focus_timestamp = xTime(); previous_client = this; #endif if ( rules()->checkAcceptFocus( input )) { XSetInputFocus( display(), window(), RevertToPointerRoot, xTime() ); } if ( Ptakefocus ) sendClientMessage(window(), atoms->wm_protocols, atoms->wm_take_focus); workspace()->setShouldGetFocus( this ); } /*! Returns whether the window provides context help or not. If it does, you should show a help menu item or a help button like '?' and call contextHelp() if this is invoked. \sa contextHelp() */ bool Client::providesContextHelp() const { return Pcontexthelp; } /*! Invokes context help on the window. Only works if the window actually provides context help. \sa providesContextHelp() */ void Client::showContextHelp() { if ( Pcontexthelp ) { sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_context_help); QWhatsThis::enterWhatsThisMode(); // SELI? } } /*! Fetches the window's caption (WM_NAME property). It will be stored in the client's caption(). */ void Client::fetchName() { setCaption( readName()); } QString Client::readName() const { if ( info->name() && info->name()[ 0 ] != '\0' ) return QString::fromUtf8( info->name() ); else return KWin::readNameProperty( window(), XA_WM_NAME ); } -KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate, Client, const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption()); +KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate, const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption()); void Client::setCaption( const QString& _s, bool force ) { QString s = _s; if ( s != cap_normal || force ) { bool reset_name = force; for( int i = 0; i < s.length(); ++i ) if( !s[ i ].isPrint()) s[ i ] = QChar( ' ' ); cap_normal = s; bool was_suffix = ( !cap_suffix.isEmpty()); QString machine_suffix; if( wmClientMachine( false ) != "localhost" && !isLocalMachine( wmClientMachine( false ))) machine_suffix = " <@" + wmClientMachine( true ) + '>'; QString shortcut_suffix = !shortcut().isEmpty() ? ( " {" + shortcut().toString() + '}' ) : QString(); cap_suffix = machine_suffix + shortcut_suffix; if ( ( !isSpecialWindow() || isToolbar()) && workspace()->findClient( FetchNameInternalPredicate( this ))) { int i = 2; do { cap_suffix = machine_suffix + " <" + QString::number(i) + '>' + shortcut_suffix; i++; } while ( workspace()->findClient( FetchNameInternalPredicate( this ))); info->setVisibleName( caption().toUtf8() ); reset_name = false; } if(( was_suffix && cap_suffix.isEmpty() || reset_name )) // if it was new window, it may have old value still set, if the window is reused { info->setVisibleName( "" ); // remove info->setVisibleIconName( "" ); // remove } else if( !cap_suffix.isEmpty() && !cap_iconic.isEmpty()) // keep the same suffix in iconic name if it's set info->setVisibleIconName( ( cap_iconic + cap_suffix ).toUtf8() ); if( isManaged() && decoration != NULL ) decoration->captionChange(); } } void Client::updateCaption() { setCaption( cap_normal, true ); } void Client::fetchIconicName() { QString s; if ( info->iconName() && info->iconName()[ 0 ] != '\0' ) s = QString::fromUtf8( info->iconName() ); else s = KWin::readNameProperty( window(), XA_WM_ICON_NAME ); if ( s != cap_iconic ) { bool was_set = !cap_iconic.isEmpty(); cap_iconic = s; if( !cap_suffix.isEmpty()) { if( !cap_iconic.isEmpty()) // keep the same suffix in iconic name if it's set info->setVisibleIconName( ( s + cap_suffix ).toUtf8() ); else if( was_set ) info->setVisibleIconName( "" ); //remove } } } /*!\reimp */ QString Client::caption( bool full ) const { return full ? cap_normal + cap_suffix : cap_normal; } void Client::getWMHints() { XWMHints *hints = XGetWMHints(display(), window() ); input = true; window_group = None; urgency = false; if ( hints ) { if( hints->flags & InputHint ) input = hints->input; if( hints->flags & WindowGroupHint ) window_group = hints->window_group; urgency = ( hints->flags & UrgencyHint ) ? true : false; // true/false needed, it's uint bitfield XFree( (char*)hints ); } checkGroup(); updateUrgency(); updateAllowedActions(); // group affects isMinimizable() } void Client::getMotifHints() { bool mnoborder, mresize, mmove, mminimize, mmaximize, mclose; Motif::readFlags( client, mnoborder, mresize, mmove, mminimize, mmaximize, mclose ); motif_noborder = mnoborder; if( !hasNETSupport()) // NETWM apps should set type and size constraints { motif_may_resize = mresize; // this should be set using minsize==maxsize, but oh well motif_may_move = mmove; } else motif_may_resize = motif_may_move = true; // mminimize; - ignore, bogus - e.g. shading or sending to another desktop is "minimizing" too // mmaximize; - ignore, bogus - maximizing is basically just resizing motif_may_close = mclose; // motif apps like to crash when they set this hint and WM closes them anyway if( isManaged()) updateDecoration( true ); // check if noborder state has changed } void Client::readIcons( Window win, QPixmap* icon, QPixmap* miniicon ) { // get the icons, allow scaling if( icon != NULL ) *icon = KWin::icon( win, 32, 32, true, KWin::NETWM | KWin::WMHints ); if( miniicon != NULL ) if( icon == NULL || !icon->isNull()) *miniicon = KWin::icon( win, 16, 16, true, KWin::NETWM | KWin::WMHints ); else *miniicon = QPixmap(); } void Client::getIcons() { // first read icons from the window itself readIcons( window(), &icon_pix, &miniicon_pix ); if( icon_pix.isNull()) { // then try window group icon_pix = group()->icon(); miniicon_pix = group()->miniIcon(); } if( icon_pix.isNull() && isTransient()) { // then mainclients ClientList mainclients = mainClients(); for( ClientList::ConstIterator it = mainclients.begin(); it != mainclients.end() && icon_pix.isNull(); ++it ) { icon_pix = (*it)->icon(); miniicon_pix = (*it)->miniIcon(); } } if( icon_pix.isNull()) { // and if nothing else, load icon from classhint or xapp icon icon_pix = KWin::icon( window(), 32, 32, true, KWin::ClassHint | KWin::XApp ); miniicon_pix = KWin::icon( window(), 16, 16, true, KWin::ClassHint | KWin::XApp ); } if( isManaged() && decoration != NULL ) decoration->iconChange(); } void Client::getWindowProtocols() { Atom *p; int i,n; Pdeletewindow = 0; Ptakefocus = 0; Ptakeactivity = 0; Pcontexthelp = 0; Pping = 0; if (XGetWMProtocols(display(), window(), &p, &n)) { for (i = 0; i < n; i++) if (p[i] == atoms->wm_delete_window) Pdeletewindow = 1; else if (p[i] == atoms->wm_take_focus) Ptakefocus = 1; else if (p[i] == atoms->net_wm_take_activity) Ptakeactivity = 1; else if (p[i] == atoms->net_wm_context_help) Pcontexthelp = 1; else if (p[i] == atoms->net_wm_ping) Pping = 1; if (n>0) XFree(p); } } +static int nullErrorHandler(Display *, XErrorEvent *) + { + return 0; + } + +/*! + Returns WM_WINDOW_ROLE property for a given window. + */ +QByteArray Client::staticWindowRole(WId w) + { + return getStringProperty(w, atoms->wm_window_role).toLower(); + } + +/*! + Returns SM_CLIENT_ID property for a given window. + */ +QByteArray Client::staticSessionId(WId w) + { + return getStringProperty(w, atoms->sm_client_id); + } + +/*! + Returns WM_COMMAND property for a given window. + */ +QByteArray Client::staticWmCommand(WId w) + { + return getStringProperty(w, XA_WM_COMMAND, ' '); + } + +/*! + Returns WM_CLIENT_LEADER property for a given window. + */ +Window Client::staticWmClientLeader(WId w) + { + Atom type; + int format, status; + unsigned long nitems = 0; + unsigned long extra = 0; + unsigned char *data = 0; + Window result = w; + XErrorHandler oldHandler = XSetErrorHandler(nullErrorHandler); + status = XGetWindowProperty( display(), w, atoms->wm_client_leader, 0, 10000, + false, XA_WINDOW, &type, &format, + &nitems, &extra, &data ); + XSetErrorHandler(oldHandler); + if (status == Success ) + { + if (data && nitems > 0) + result = *((Window*) data); + XFree(data); + } + return result; + } + + +void Client::getWmClientLeader() + { + wmClientLeaderWin = staticWmClientLeader(window()); + } + +/*! + Returns sessionId for this client, + taken either from its window or from the leader window. + */ +QByteArray Client::sessionId() + { + QByteArray result = staticSessionId(window()); + if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window()) + result = staticSessionId(wmClientLeaderWin); + return result; + } + +/*! + Returns command property for this client, + taken either from its window or from the leader window. + */ +QByteArray Client::wmCommand() + { + QByteArray result = staticWmCommand(window()); + if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window()) + result = staticWmCommand(wmClientLeaderWin); + return result; + } + +void Client::getWmClientMachine() + { + client_machine = getStringProperty(window(), XA_WM_CLIENT_MACHINE); + if( client_machine.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window()) + client_machine = getStringProperty(wmClientLeaderWin, XA_WM_CLIENT_MACHINE); + if( client_machine.isEmpty()) + client_machine = "localhost"; + } + +/*! + Returns client machine for this client, + taken either from its window or from the leader window. +*/ +QByteArray Client::wmClientMachine( bool use_localhost ) const + { + QByteArray result = client_machine; + if( use_localhost ) + { // special name for the local machine (localhost) + if( result != "localhost" && isLocalMachine( result )) + result = "localhost"; + } + return result; + } + +/*! + Returns client leader window for this client. + Returns the client window itself if no leader window is defined. +*/ +Window Client::wmClientLeader() const + { + if (wmClientLeaderWin) + return wmClientLeaderWin; + return window(); + } + bool Client::wantsTabFocus() const { return ( isNormalWindow() || isDialog()) && wantsInput(); } 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 ); + if( direct ) + return wt; + NET::WindowType wt2 = rules()->checkType( wt ); + if( wt != wt2 ) + { + wt = wt2; + info->setWindowType( wt ); // force hint change + } + // hacks here + if( wt == NET::Menu ) + { + // ugly hack to support the times when NET::Menu meant NET::TopMenu + // if it's as wide as the screen, not very high and has its upper-left + // corner a bit above the screen's upper-left cornet, it's a topmenu + if( x() == 0 && y() < 0 && y() > -10 && height() < 100 + && abs( width() - workspace()->clientArea( FullArea, this ).width()) < 10 ) + wt = NET::TopMenu; + } + // TODO change this to rule + const char* const oo_prefix = "openoffice.org"; // QByteArray has no startsWith() + // oo_prefix is lowercase, because resourceClass() is forced to be lowercase + if( qstrncmp( resourceClass(), oo_prefix, strlen( oo_prefix )) == 0 && wt == NET::Dialog ) + wt = NET::Normal; // see bug #66065 + if( wt == NET::Unknown ) // this is more or less suggested in NETWM spec + wt = isTransient() ? NET::Dialog : NET::Normal; + return wt; + } + /*! Sets an appropriate cursor shape for the logical mouse position \a m */ void Client::setCursor( Position m ) { if( !isResizable() || isShade()) { m = PositionCenter; } switch ( m ) { case PositionTopLeft: case PositionBottomRight: setCursor( Qt::SizeFDiagCursor ); break; case PositionBottomLeft: case PositionTopRight: setCursor( Qt::SizeBDiagCursor ); break; case PositionTop: case PositionBottom: setCursor( Qt::SizeVerCursor ); break; case PositionLeft: case PositionRight: setCursor( Qt::SizeHorCursor ); break; default: if( buttonDown && isMovable()) setCursor( Qt::SizeAllCursor ); else setCursor( Qt::ArrowCursor ); break; } } // TODO mit nejake checkCursor(), ktere se zavola v manage() a pri vecech, kdy by se kurzor mohl zmenit? void Client::setCursor( const QCursor& c ) { if( c.handle() == cursor.handle()) return; cursor = c; if( decoration != NULL ) decoration->widget()->setCursor( cursor ); XDefineCursor( display(), frameId(), cursor.handle()); } Client::Position Client::mousePosition( const QPoint& p ) const { if( decoration != NULL ) return decoration->mousePosition( p ); return PositionCenter; } void Client::updateAllowedActions( bool force ) { if( !isManaged() && !force ) return; unsigned long old_allowed_actions = allowed_actions; allowed_actions = 0; if( isMovable()) allowed_actions |= NET::ActionMove; if( isResizable()) allowed_actions |= NET::ActionResize; if( isMinimizable()) allowed_actions |= NET::ActionMinimize; if( isShadeable()) allowed_actions |= NET::ActionShade; // sticky state not supported if( isMaximizable()) allowed_actions |= NET::ActionMax; if( userCanSetFullScreen()) allowed_actions |= NET::ActionFullScreen; allowed_actions |= NET::ActionChangeDesktop; // always (pagers shouldn't show Docks etc.) if( isCloseable()) allowed_actions |= NET::ActionClose; if( old_allowed_actions == allowed_actions ) return; // TODO this could be delayed and compressed - it's only for pagers etc. anyway info->setAllowedActions( allowed_actions ); // TODO this should also tell the decoration, so that it can update the buttons } void Client::autoRaise() { workspace()->raiseClient( this ); cancelAutoRaise(); } void Client::cancelAutoRaise() { delete autoRaiseTimer; autoRaiseTimer = 0; } -void Client::debug( kdbgstream& stream ) const +#ifndef NDEBUG +kdbgstream& operator<<( kdbgstream& stream, const Client* cl ) + { + if( cl == NULL ) + return stream << "\'NULL_CLIENT\'"; + return stream << "\'ID:" << cl->window() << ";WMCLASS:" << cl->resourceClass() << ":" << cl->resourceName() << ";Caption:" << cl->caption() << "\'"; + } +kdbgstream& operator<<( kdbgstream& stream, const ClientList& list ) + { + 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; + } +kdbgstream& operator<<( kdbgstream& stream, const ConstClientList& list ) { - stream << "\'ID:" << window() << ";WMCLASS:" << resourceClass() << ":" << resourceName() << ";Caption:" << caption() << "\'"; + 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; } +#endif QPixmap * kwin_get_menu_pix_hack() { static QPixmap p; if ( p.isNull() ) p = SmallIcon( "bx2" ); return &p; } } // namespace #include "client.moc" diff --git a/client.h b/client.h index a22ff6b4e..0bf54729d 100644 --- a/client.h +++ b/client.h @@ -1,916 +1,916 @@ /***************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ #ifndef KWIN_CLIENT_H #define KWIN_CLIENT_H #include #include #include #include #include #include #include #include #include #include #include "utils.h" #include "options.h" #include "workspace.h" #include "kdecoration.h" #include "rules.h" class QTimer; -class KProcess; +class K3Process; class KStartupInfoData; namespace KWinInternal { class Workspace; class Client; class WinInfo; class SessionInfo; class Bridge; class Client : public QObject, public KDecorationDefines { Q_OBJECT public: Client( Workspace *ws ); Window window() const; Window frameId() const; Window wrapperId() const; Window decorationId() const; Workspace* workspace() const; const Client* transientFor() const; Client* transientFor(); bool isTransient() const; bool groupTransient() const; bool wasOriginallyGroupTransient() const; ClientList mainClients() const; // call once before loop , is not indirect bool hasTransient( const Client* c, bool indirect ) const; const ClientList& transients() const; // is not indirect void checkTransient( Window w ); Client* findModal(); const Group* group() const; Group* group(); void checkGroup( Group* gr = NULL, bool force = false ); void changeClientLeaderGroup( Group* gr ); // prefer isXXX() instead NET::WindowType windowType( bool direct = false, int supported_types = SUPPORTED_WINDOW_TYPES_MASK ) const; const WindowRules* rules() const; void removeRule( Rules* r ); void setupWindowRules( bool ignore_temporary ); void applyWindowRules(); void updateWindowRules(); QRect geometry() const; QSize size() const; QSize minSize() const; QSize maxSize() const; QPoint pos() const; QRect rect() const; int x() const; int y() const; int width() const; int height() const; QPoint clientPos() const; // inside of geometry() QSize clientSize() const; bool windowEvent( XEvent* e ); virtual bool eventFilter( QObject* o, QEvent* e ); bool manage( Window w, bool isMapped ); void releaseWindow( bool on_shutdown = false ); enum Sizemode // how to resize the window in order to obey constains (mainly aspect ratios) { SizemodeAny, SizemodeFixedW, // try not to affect width SizemodeFixedH, // try not to affect height SizemodeMax // try not to make it larger in either direction }; QSize adjustedSize( const QSize&, Sizemode mode = SizemodeAny ) const; QSize adjustedSize() const; QPixmap icon() const; QPixmap miniIcon() const; bool isActive() const; void setActive( bool ); int desktop() const; void setDesktop( int ); bool isOnDesktop( int d ) const; bool isOnCurrentDesktop() const; bool isOnAllDesktops() const; void setOnAllDesktops( bool set ); // !isMinimized() && not hidden, i.e. normally visible on some virtual desktop bool isShown( bool shaded_is_shown ) const; bool isShade() const; // true only for ShadeNormal ShadeMode shadeMode() const; // prefer isShade() void setShade( ShadeMode mode ); bool isShadeable() const; bool isMinimized() const; bool isMaximizable() const; QRect geometryRestore() const; MaximizeMode maximizeModeRestore() const; MaximizeMode maximizeMode() const; bool isMinimizable() const; void setMaximize( bool vertically, bool horizontally ); void setFullScreen( bool set, bool user ); bool isFullScreen() const; bool isFullScreenable( bool fullscreen_hack = false ) const; bool userCanSetFullScreen() const; QRect geometryFSRestore() const { return geom_fs_restore; } // only for session saving int fullScreenMode() const { return fullscreen_mode; } // only for session saving bool isUserNoBorder() const; void setUserNoBorder( bool set ); bool userCanSetNoBorder() const; bool noBorder() const; bool skipTaskbar( bool from_outside = false ) const; void setSkipTaskbar( bool set, bool from_outside ); bool skipPager() const; void setSkipPager( bool ); bool keepAbove() const; void setKeepAbove( bool ); bool keepBelow() const; void setKeepBelow( bool ); Layer layer() const; Layer belongsToLayer() const; void invalidateLayer(); int sessionStackingOrder() const; void setModal( bool modal ); bool isModal() const; // auxiliary functions, depend on the windowType bool wantsTabFocus() const; bool wantsInput() const; bool hasNETSupport() const; bool isMovable() const; bool isDesktop() const; bool isDock() const; bool isToolbar() const; bool isTopMenu() const; bool isMenu() const; bool isNormalWindow() const; // normal as in 'NET::Normal or NET::Unknown non-transient' bool isDialog() const; bool isSplash() const; bool isUtility() const; // returns true for "special" windows and false for windows which are "normal" // (normal=window which has a border, can be moved by the user, can be closed, etc.) // true for Desktop, Dock, Splash, Override and TopMenu (and Toolbar??? - for now) // false for Normal, Dialog, Utility and Menu (and Toolbar??? - not yet) TODO bool isSpecialWindow() const; bool isResizable() const; bool isCloseable() const; // may be closed by the user (may have a close button) void takeActivity( int flags, bool handled, allowed_t ); // takes ActivityFlags as arg (in utils.h) void takeFocus( allowed_t ); void demandAttention( bool set = true ); void setMask( const QRegion& r, int mode = X::Unsorted ); QRegion mask() const; void updateDecoration( bool check_workspace_pos, bool force = false ); void checkBorderSizes(); // shape extensions bool shape() const; void updateShape(); void setGeometry( int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet ); void setGeometry( const QRect& r, ForceGeometry_t force = NormalGeometrySet ); void move( int x, int y, ForceGeometry_t force = NormalGeometrySet ); void move( const QPoint & p, ForceGeometry_t force = NormalGeometrySet ); // plainResize() simply resizes void plainResize( int w, int h, ForceGeometry_t force = NormalGeometrySet ); void plainResize( const QSize& s, ForceGeometry_t force = NormalGeometrySet ); // resizeWithChecks() resizes according to gravity, and checks workarea position void resizeWithChecks( int w, int h, ForceGeometry_t force = NormalGeometrySet ); void resizeWithChecks( const QSize& s, ForceGeometry_t force = NormalGeometrySet ); void keepInArea( QRect area, bool partial = false ); void growHorizontal(); void shrinkHorizontal(); void growVertical(); void shrinkVertical(); bool providesContextHelp() const; KShortcut shortcut() const; void setShortcut( const QString& cut ); bool performMouseCommand( Options::MouseCommand, QPoint globalPos, bool handled = false ); QByteArray windowRole() const; QByteArray sessionId(); QByteArray resourceName() const; QByteArray resourceClass() const; QByteArray wmCommand(); QByteArray wmClientMachine( bool use_localhost ) const; Window wmClientLeader() const; pid_t pid() const; QRect adjustedClientArea( const QRect& desktop, const QRect& area ) const; Colormap colormap() const; // updates visibility depending on being shaded, virtual desktop, etc. void updateVisibility(); // hides a client - basically like minimize, but without effects, it's simply hidden void hideClient( bool hide ); QString caption( bool full = true ) const; void updateCaption(); void keyPressEvent( uint key_code ); // FRAME ?? void updateMouseGrab(); Window moveResizeGrabWindow() const; const QPoint calculateGravitation( bool invert, int gravity = 0 ) const; // FRAME public? void NETMoveResize( int x_root, int y_root, NET::Direction direction ); void NETMoveResizeWindow( int flags, int x, int y, int width, int height ); void restackWindow( Window above, int detail, NET::RequestSource source, Time timestamp, bool send_event = false ); void gotPing( Time timestamp ); static QByteArray staticWindowRole(WId); static QByteArray staticSessionId(WId); static QByteArray staticWmCommand(WId); static QByteArray staticWmClientMachine(WId); static Window staticWmClientLeader(WId); void checkWorkspacePosition(); void updateUserTime( Time time = CurrentTime ); Time userTime() const; bool hasUserTimeSupport() const; bool ignoreFocusStealing() const; // does 'delete c;' static void deleteClient( Client* c, allowed_t ); static bool resourceMatch( const Client* c1, const Client* c2 ); static bool belongToSameApplication( const Client* c1, const Client* c2, bool active_hack = false ); static void readIcons( Window win, QPixmap* icon, QPixmap* miniicon ); void minimize( bool avoid_animation = false ); void unminimize( bool avoid_animation = false ); void closeWindow(); void killWindow(); void maximize( MaximizeMode ); void toggleShade(); void showContextHelp(); void cancelShadeHover(); void cancelAutoRaise(); void destroyClient(); void checkActiveModal(); bool hasStrut() const; private slots: void autoRaise(); void shadeHover(); void shortcutActivated(); private: friend class Bridge; // FRAME virtual void processMousePressEvent( QMouseEvent* e ); private: // TODO cleanup the order of things in the .h file // use Workspace::createClient() virtual ~Client(); // use destroyClient() or releaseWindow() Position mousePosition( const QPoint& ) const; void setCursor( Position m ); void setCursor( const QCursor& c ); void animateMinimizeOrUnminimize( bool minimize ); QPixmap animationPixmap( int w ); // transparent stuff void drawbound( const QRect& geom ); void clearbound(); void doDrawbound( const QRect& geom, bool clear ); // handlers for X11 events bool mapRequestEvent( XMapRequestEvent* e ); void unmapNotifyEvent( XUnmapEvent*e ); void destroyNotifyEvent( XDestroyWindowEvent*e ); void configureRequestEvent( XConfigureRequestEvent* e ); void propertyNotifyEvent( XPropertyEvent* e ); void clientMessageEvent( XClientMessageEvent* e ); void enterNotifyEvent( XCrossingEvent* e ); void leaveNotifyEvent( XCrossingEvent* e ); void focusInEvent( XFocusInEvent* e ); void focusOutEvent( XFocusOutEvent* e ); bool buttonPressEvent( Window w, int button, int state, int x, int y, int x_root, int y_root ); bool buttonReleaseEvent( Window w, int button, int state, int x, int y, int x_root, int y_root ); bool motionNotifyEvent( Window w, int state, int x, int y, int x_root, int y_root ); void processDecorationButtonPress( int button, int state, int x, int y, int x_root, int y_root ); private slots: void pingTimeout(); void processKillerExited(); void demandAttentionKNotify(); private: // ICCCM 4.1.3.1, 4.1.4 , NETWM 2.5.1 void setMappingState( int s ); int mappingState() const; bool isIconicState() const; bool isNormalState() const; bool isManaged() const; // returns false if this client is not yet managed void updateAllowedActions( bool force = false ); QSize sizeForClientSize( const QSize&, Sizemode mode = SizemodeAny, bool noframe = false ) const; void changeMaximize( bool horizontal, bool vertical, bool adjust ); void checkMaximizeGeometry(); int checkFullScreenHack( const QRect& geom ) const; // 0 - none, 1 - one xinerama screen, 2 - full area void updateFullScreenHack( const QRect& geom ); void getWmNormalHints(); void getMotifHints(); void getIcons(); void getWmClientLeader(); void getWmClientMachine(); void fetchName(); void fetchIconicName(); QString readName() const; void setCaption( const QString& s, bool force = false ); bool hasTransientInternal( const Client* c, bool indirect, ConstClientList& set ) const; void finishWindowRules(); void setShortcutInternal( const KShortcut& cut ); void updateWorkareaDiffs(); void checkDirection( int new_diff, int old_diff, QRect& rect, const QRect& area ); static int computeWorkareaDiff( int left, int right, int a_left, int a_right ); void configureRequest( int value_mask, int rx, int ry, int rw, int rh, int gravity, bool from_tool ); NETExtendedStrut strut() const; int checkShadeGeometry( int w, int h ); void postponeGeometryUpdates( bool postpone ); bool startMoveResize(); void finishMoveResize( bool cancel ); void leaveMoveResize(); void checkUnrestrictedMoveResize(); void handleMoveResize( int x, int y, int x_root, int y_root ); void positionGeometryTip(); void grabButton( int mod ); void ungrabButton( int mod ); void resetMaximize(); void resizeDecoration( const QSize& s ); void pingWindow(); void killProcess( bool ask, Time timestamp = CurrentTime ); void updateUrgency(); static void sendClientMessage( Window w, Atom a, Atom protocol, long data1 = 0, long data2 = 0, long data3 = 0 ); void embedClient( Window w, const XWindowAttributes &attr ); void detectNoBorder(); void destroyDecoration(); void updateFrameExtents(); void rawShow(); // just shows it void rawHide(); // just hides it Time readUserTimeMapTimestamp( const KStartupInfoId* asn_id, const KStartupInfoData* asn_data, bool session ) const; Time readUserCreationTime() const; static bool sameAppWindowRoleMatch( const Client* c1, const Client* c2, bool active_hack ); void startupIdChanged(); Window client; Window wrapper; Window frame; KDecoration* decoration; Workspace* wspace; Bridge* bridge; int desk; bool buttonDown; bool moveResizeMode; bool move_faked_activity; Window move_resize_grab_window; bool unrestrictedMoveResize; bool isMove() const { return moveResizeMode && mode == PositionCenter; } bool isResize() const { return moveResizeMode && mode != PositionCenter; } Position mode; QPoint moveOffset; QPoint invertedMoveOffset; QRect moveResizeGeom; QRect initialMoveResizeGeom; XSizeHints xSizeHint; void sendSyntheticConfigureNotify(); int mapping_state; void readTransient(); Window verifyTransientFor( Window transient_for, bool set ); void addTransient( Client* cl ); void removeTransient( Client* cl ); void removeFromMainClients(); void cleanGrouping(); void checkGroupTransients(); void setTransient( Window new_transient_for_id ); Client* transient_for; Window transient_for_id; Window original_transient_for_id; ClientList transients_list; // SELI make this ordered in stacking order? ShadeMode shade_mode; uint active :1; uint deleting : 1; // true when doing cleanup and destroying the client uint keep_above : 1; // NET::KeepAbove (was stays_on_top) uint is_shape :1; uint skip_taskbar :1; uint original_skip_taskbar :1; // unaffected by KWin uint Pdeletewindow :1; // does the window understand the DeleteWindow protocol? uint Ptakefocus :1;// does the window understand the TakeFocus protocol? uint Ptakeactivity : 1; // does it support _NET_WM_TAKE_ACTIVITY uint Pcontexthelp : 1; // does the window understand the ContextHelp protocol? uint Pping : 1; // does it support _NET_WM_PING? uint input :1; // does the window want input in its wm_hints uint skip_pager : 1; uint motif_noborder : 1; uint motif_may_resize : 1; uint motif_may_move :1; uint motif_may_close : 1; uint keep_below : 1; // NET::KeepBelow uint minimized : 1; uint hidden : 1; // forcibly hidden by calling hide() uint modal : 1; // NET::Modal uint noborder : 1; uint user_noborder : 1; uint urgency : 1; // XWMHints, UrgencyHint uint ignore_focus_stealing : 1; // don't apply focus stealing prevention to this client uint demands_attention : 1; WindowRules client_rules; void getWMHints(); void readIcons(); void getWindowProtocols(); QPixmap icon_pix; QPixmap miniicon_pix; QCursor cursor; // FullScreenHack - non-NETWM fullscreen (noborder,size of desktop) // DON'T reorder - saved to config files !!! enum FullScreenMode { FullScreenNone, FullScreenNormal, FullScreenHack }; FullScreenMode fullscreen_mode; MaximizeMode max_mode; QRect geom_restore; QRect geom_fs_restore; MaximizeMode maxmode_restore; int workarea_diff_x, workarea_diff_y; WinInfo* info; QTimer* autoRaiseTimer; QTimer* shadeHoverTimer; Colormap cmap; QByteArray resource_name; QByteArray resource_class; QByteArray client_machine; QString cap_normal, cap_iconic, cap_suffix; WId wmClientLeaderWin; QByteArray window_role; Group* in_group; Window window_group; Layer in_layer; QTimer* ping_timer; - KProcess* process_killer; + K3Process* process_killer; Time ping_timestamp; Time user_time; unsigned long allowed_actions; QRect frame_geometry; QSize client_size; int postpone_geometry_updates; // >0 - new geometry is remembered, but not actually set bool pending_geometry_update; bool shade_geometry_change; int border_left, border_right, border_top, border_bottom; QRegion _mask; static bool check_active_modal; // see Client::checkActiveModal() KShortcut _shortcut; int sm_stacking_order; friend struct FetchNameInternalPredicate; friend struct CheckIgnoreFocusStealingProcedure; friend struct ResetupRulesProcedure; friend class GeometryUpdatesPostponer; void show() { assert( false ); } // SELI remove after Client is no longer QWidget void hide() { assert( false ); } QTimer* demandAttentionKNotifyTimer; friend bool performTransiencyCheck(); }; // helper for Client::postponeGeometryUpdates() being called in pairs (true/false) class GeometryUpdatesPostponer { public: GeometryUpdatesPostponer( Client* c ) : cl( c ) { cl->postponeGeometryUpdates( true ); } ~GeometryUpdatesPostponer() { cl->postponeGeometryUpdates( false ); } private: Client* cl; }; // NET WM Protocol handler class class WinInfo : public NETWinInfo { private: typedef KWinInternal::Client Client; // because of NET::Client public: WinInfo( Client* c, Display * display, Window window, Window rwin, const unsigned long pr[], int pr_size ); virtual void changeDesktop(int desktop); virtual void changeState( unsigned long state, unsigned long mask ); private: Client * m_client; }; inline Window Client::window() const { return client; } inline Window Client::frameId() const { return frame; } inline Window Client::wrapperId() const { return wrapper; } inline Window Client::decorationId() const { return decoration != NULL ? decoration->widget()->winId() : None; } inline Workspace* Client::workspace() const { return wspace; } inline const Client* Client::transientFor() const { return transient_for; } inline Client* Client::transientFor() { return transient_for; } inline bool Client::groupTransient() const { return transient_for_id == workspace()->rootWin(); } // needed because verifyTransientFor() may set transient_for_id to root window, // if the original value has a problem (window doesn't exist, etc.) inline bool Client::wasOriginallyGroupTransient() const { return original_transient_for_id == workspace()->rootWin(); } inline bool Client::isTransient() const { return transient_for_id != None; } inline const ClientList& Client::transients() const { return transients_list; } inline const Group* Client::group() const { return in_group; } inline Group* Client::group() { return in_group; } inline int Client::mappingState() const { return mapping_state; } inline QByteArray Client::resourceName() const { return resource_name; // it is always lowercase } inline QByteArray Client::resourceClass() const { return resource_class; // it is always lowercase } inline bool Client::isMinimized() const { return minimized; } inline bool Client::isActive() const { return active; } /*! Returns the virtual desktop within the workspace() the client window is located in, 0 if it isn't located on any special desktop (not mapped yet), or NET::OnAllDesktops. Do not use desktop() directly, use isOnDesktop() instead. */ inline int Client::desktop() const { return desk; } inline bool Client::isOnAllDesktops() const { return desk == NET::OnAllDesktops; } /*! Returns whether the client is on the virtual desktop \a d. This is always true for onAllDesktops clients. */ inline bool Client::isOnDesktop( int d ) const { return desk == d || /*desk == 0 ||*/ isOnAllDesktops(); } inline bool Client::isShown( bool shaded_is_shown ) const { return !isMinimized() && ( !isShade() || shaded_is_shown ) && !hidden; } inline bool Client::isShade() const { return shade_mode == ShadeNormal; } inline ShadeMode Client::shadeMode() const { return shade_mode; } inline QPixmap Client::icon() const { return icon_pix; } inline QPixmap Client::miniIcon() const { return miniicon_pix; } inline QRect Client::geometryRestore() const { return geom_restore; } inline Client::MaximizeMode Client::maximizeModeRestore() const { return maxmode_restore; } inline Client::MaximizeMode Client::maximizeMode() const { return max_mode; } inline bool Client::skipTaskbar( bool from_outside ) const { return from_outside ? original_skip_taskbar : skip_taskbar; } inline bool Client::skipPager() const { return skip_pager; } inline bool Client::keepAbove() const { return keep_above; } inline bool Client::keepBelow() const { return keep_below; } inline bool Client::shape() const { return is_shape; } inline bool Client::isFullScreen() const { return fullscreen_mode != FullScreenNone; } inline bool Client::isModal() const { return modal; } inline bool Client::hasNETSupport() const { return info->hasNETSupport(); } inline Colormap Client::colormap() const { return cmap; } inline pid_t Client::pid() const { return info->pid(); } inline void Client::invalidateLayer() { in_layer = UnknownLayer; } inline int Client::sessionStackingOrder() const { return sm_stacking_order; } inline bool Client::isIconicState() const { return mapping_state == IconicState; } inline bool Client::isNormalState() const { return mapping_state == NormalState; } inline bool Client::isManaged() const { return mapping_state != WithdrawnState; } inline QByteArray Client::windowRole() const { return window_role; } inline QRect Client::geometry() const { return frame_geometry; } inline QSize Client::size() const { return frame_geometry.size(); } inline QPoint Client::pos() const { return frame_geometry.topLeft(); } inline int Client::x() const { return frame_geometry.x(); } inline int Client::y() const { return frame_geometry.y(); } inline int Client::width() const { return frame_geometry.width(); } inline int Client::height() const { return frame_geometry.height(); } inline QRect Client::rect() const { return QRect( 0, 0, width(), height()); } inline QPoint Client::clientPos() const { return QPoint( border_left, border_top ); } inline QSize Client::clientSize() const { return client_size; } inline void Client::setGeometry( const QRect& r, ForceGeometry_t force ) { setGeometry( r.x(), r.y(), r.width(), r.height(), force ); } inline void Client::move( const QPoint & p, ForceGeometry_t force ) { move( p.x(), p.y(), force ); } inline void Client::plainResize( const QSize& s, ForceGeometry_t force ) { plainResize( s.width(), s.height(), force ); } inline void Client::resizeWithChecks( const QSize& s, ForceGeometry_t force ) { resizeWithChecks( s.width(), s.height(), force ); } inline bool Client::hasUserTimeSupport() const { return info->userTime() != -1U; } inline bool Client::ignoreFocusStealing() const { return ignore_focus_stealing; } inline const WindowRules* Client::rules() const { return &client_rules; } KWIN_PROCEDURE( CheckIgnoreFocusStealingProcedure, cl->ignore_focus_stealing = options->checkIgnoreFocusStealing( cl )); inline Window Client::moveResizeGrabWindow() const { return move_resize_grab_window; } inline KShortcut Client::shortcut() const { return _shortcut; } inline void Client::removeRule( Rules* rule ) { client_rules.remove( rule ); } #ifdef NDEBUG inline kndbgstream& operator<<( kndbgstream& stream, const Client* ) { return stream; } inline kndbgstream& operator<<( kndbgstream& stream, const ClientList& ) { return stream; } inline kndbgstream& operator<<( kndbgstream& stream, const ConstClientList& ) { return stream; } #else kdbgstream& operator<<( kdbgstream& stream, const Client* ); kdbgstream& operator<<( kdbgstream& stream, const ClientList& ); kdbgstream& operator<<( kdbgstream& stream, const ConstClientList& ); #endif KWIN_COMPARE_PREDICATE( WindowMatchPredicate, Window, cl->window() == value ); KWIN_COMPARE_PREDICATE( FrameIdMatchPredicate, Window, cl->frameId() == value ); KWIN_COMPARE_PREDICATE( WrapperIdMatchPredicate, Window, cl->wrapperId() == value ); } // namespace #endif diff --git a/kcmkwin/kwinoptions/windows.cpp b/kcmkwin/kwinoptions/windows.cpp index 9fc099a9a..c4c937db2 100644 --- a/kcmkwin/kwinoptions/windows.cpp +++ b/kcmkwin/kwinoptions/windows.cpp @@ -1,1650 +1,1663 @@ /* * windows.cpp * * Copyright (c) 1997 Patrick Dowler dowler@morgul.fsh.uvic.ca * Copyright (c) 2001 Waldo Bastian bastian@kde.org * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * */ #include #include #include #include #include #include #include #include #include //Added by qt3to4: #include #include #include #include #include +#include #include #include #include #include #include #include #include -#include +#include #include #include #include #include #include #include "windows.h" - // kwin config keywords #define KWIN_FOCUS "FocusPolicy" #define KWIN_PLACEMENT "Placement" #define KWIN_MOVE "MoveMode" #define KWIN_MINIMIZE_ANIM "AnimateMinimize" #define KWIN_MINIMIZE_ANIM_SPEED "AnimateMinimizeSpeed" #define KWIN_RESIZE_OPAQUE "ResizeMode" #define KWIN_GEOMETRY "GeometryTip" #define KWIN_AUTORAISE_INTERVAL "AutoRaiseInterval" #define KWIN_AUTORAISE "AutoRaise" #define KWIN_DELAYFOCUS_INTERVAL "DelayFocusInterval" #define KWIN_DELAYFOCUS "DelayFocus" #define KWIN_CLICKRAISE "ClickRaise" #define KWIN_ANIMSHADE "AnimateShade" #define KWIN_MOVE_RESIZE_MAXIMIZED "MoveResizeMaximizedWindows" #define KWIN_ALTTABMODE "AltTabStyle" #define KWIN_TRAVERSE_ALL "TraverseAll" #define KWIN_SHOW_POPUP "ShowPopup" #define KWIN_ROLL_OVER_DESKTOPS "RollOverDesktops" #define KWIN_SHADEHOVER "ShadeHover" #define KWIN_SHADEHOVER_INTERVAL "ShadeHoverInterval" #define KWIN_FOCUS_STEALING "FocusStealingPreventionLevel" #define KWIN_HIDE_UTILITY "HideUtilityWindowsForInactive" // kwm config keywords #define KWM_ELECTRIC_BORDER "ElectricBorders" #define KWM_ELECTRIC_BORDER_DELAY "ElectricBorderDelay" //CT 15mar 98 - magics #define KWM_BRDR_SNAP_ZONE "BorderSnapZone" #define KWM_BRDR_SNAP_ZONE_DEFAULT 10 #define KWM_WNDW_SNAP_ZONE "WindowSnapZone" #define KWM_WNDW_SNAP_ZONE_DEFAULT 10 #define MAX_BRDR_SNAP 100 #define MAX_WNDW_SNAP 100 #define MAX_EDGE_RES 1000 KFocusConfig::~KFocusConfig () { if (standAlone) delete config; } // removed the LCD display over the slider - this is not good GUI design :) RNolden 051701 KFocusConfig::KFocusConfig (bool _standAlone, KConfig *_config, const KComponentData &inst, QWidget * parent) : KCModule(inst, parent), config(_config), standAlone(_standAlone) { QString wtstr; QBoxLayout *lay = new QVBoxLayout(this); lay->setMargin(0); lay->setSpacing(KDialog::spacingHint()); //iTLabel = new QLabel(i18n(" Allowed overlap:\n" // "(% of desktop space)"), // plcBox); //iTLabel->setAlignment(AlignTop|AlignHCenter); //pLay->addWidget(iTLabel,1,1); //interactiveTrigger = new QSpinBox(0, 500, 1, plcBox); //pLay->addWidget(interactiveTrigger,1,2); //pLay->addRowSpacing(2,KDialog::spacingHint()); //lay->addWidget(plcBox); // focus policy fcsBox = new Q3ButtonGroup(i18n("Focus"),this); fcsBox->setColumnLayout( 0, Qt::Horizontal ); QBoxLayout *fLay = new QVBoxLayout(); fLay->setSpacing(KDialog::spacingHint()); fcsBox->layout()->addItem( fLay ); QBoxLayout *cLay = new QHBoxLayout(); fLay->addLayout( cLay ); QLabel *fLabel = new QLabel(i18n("&Policy:"), fcsBox); cLay->addWidget(fLabel, 0); focusCombo = new QComboBox(fcsBox); focusCombo->setEditable( false ); focusCombo->addItem(i18n("Click to Focus"), CLICK_TO_FOCUS); focusCombo->addItem(i18n("Focus Follows Mouse"), FOCUS_FOLLOWS_MOUSE); focusCombo->addItem(i18n("Focus Under Mouse"), FOCUS_UNDER_MOUSE); focusCombo->addItem(i18n("Focus Strictly Under Mouse"), FOCUS_STRICTLY_UNDER_MOUSE); cLay->addWidget(focusCombo,1 ,Qt::AlignLeft); fLabel->setBuddy(focusCombo); // FIXME, when more policies have been added to KWin wtstr = i18n("The focus policy is used to determine the active window, i.e." " the window you can work in.
    " "
  • Click to focus: A window becomes active when you click into it." " This is the behavior you might know from other operating systems.
  • " "
  • Focus follows mouse: Moving the mouse pointer actively on to a" " normal window activates it. New windows will receive the focus," " without you having to point the mouse at them explicitly." " Very practical if you are using the mouse a lot.
  • " "
  • Focus under mouse: The window that happens to be under the" " mouse pointer is active. If the mouse points nowhere, the last window" " that was under the mouse has focus." " New windows will not automatically receive the focus.
  • " "
  • Focus strictly under mouse: Only the window under the mouse pointer is" " active. If the mouse points nowhere, nothing has focus." "
" "Note that 'Focus under mouse' and 'Focus strictly under mouse' prevent certain" " features such as the Alt+Tab walk through windows dialog in the KDE mode" " from working properly." ); focusCombo->setWhatsThis( wtstr); fLabel->setWhatsThis( wtstr); connect(focusCombo, SIGNAL(activated(int)), this, SLOT(setAutoRaiseEnabled()) ); // autoraise delay autoRaiseOn = new QCheckBox(i18n("Auto &raise"), fcsBox); fLay->addWidget(autoRaiseOn); connect(autoRaiseOn,SIGNAL(toggled(bool)), this, SLOT(autoRaiseOnTog(bool))); autoRaise = new KIntNumInput(500, fcsBox); autoRaise->setLabel(i18n("Dela&y:"), Qt::AlignVCenter|Qt::AlignLeft); autoRaise->setRange(0, 3000, 100, true); autoRaise->setSteps(100,100); autoRaise->setSuffix(i18n(" msec")); fLay->addWidget(autoRaise); connect(focusCombo, SIGNAL(activated(int)), this, SLOT(setDelayFocusEnabled()) ); delayFocusOn = new QCheckBox(i18n("Delay focus"), fcsBox); fLay->addWidget(delayFocusOn); connect(delayFocusOn,SIGNAL(toggled(bool)), this, SLOT(delayFocusOnTog(bool))); delayFocus = new KIntNumInput(500, fcsBox); delayFocus->setLabel(i18n("Dela&y:"), Qt::AlignVCenter|Qt::AlignLeft); delayFocus->setRange(0, 3000, 100, true); delayFocus->setSteps(100,100); delayFocus->setSuffix(i18n(" msec")); fLay->addWidget(delayFocus); clickRaiseOn = new QCheckBox(i18n("C&lick raise active window"), fcsBox); connect(clickRaiseOn,SIGNAL(toggled(bool)), this, SLOT(clickRaiseOnTog(bool))); fLay->addWidget(clickRaiseOn); // fLay->addColSpacing(0,qMax(autoRaiseOn->sizeHint().width(), // clickRaiseOn->sizeHint().width()) + 15); autoRaiseOn->setWhatsThis( i18n("When this option is enabled, a window in the background will automatically" " come to the front when the mouse pointer has been over it for some time.") ); wtstr = i18n("This is the delay after which the window that the mouse pointer is over will automatically" " come to the front."); autoRaise->setWhatsThis( wtstr ); clickRaiseOn->setWhatsThis( i18n("When this option is enabled, the active window will be brought to the" " front when you click somewhere into the window contents. To change" " it for inactive windows, you need to change the settings" " in the Actions tab.") ); delayFocusOn->setWhatsThis( i18n("When this option is enabled, there will be a delay after which the" " window the mouse pointer is over will become active (receive focus).") ); delayFocus->setWhatsThis( i18n("This is the delay after which the window the mouse pointer is over" " will automatically receive focus.") ); lay->addWidget(fcsBox); kbdBox = new Q3ButtonGroup(i18n("Navigation"), this); kbdBox->setColumnLayout( 0, Qt::Horizontal ); QVBoxLayout *kLay = new QVBoxLayout(); kLay->setSpacing(KDialog::spacingHint()); kbdBox->layout()->addItem( kLay ); altTabPopup = new QCheckBox( i18n("Show window list while switching windows"), kbdBox ); kLay->addWidget( altTabPopup ); wtstr = i18n("Hold down the Alt key and press the Tab key repeatedly to walk" " through the windows on the current desktop (the Alt+Tab" " combination can be reconfigured).\n\n" "If this checkbox is checked" " a popup widget is shown, displaying the icons of all windows to" " walk through and the title of the currently selected one.\n\n" "Otherwise, the focus is passed to a new window each time Tab" " is pressed, with no popup widget. In addition, the previously" " activated window will be sent to the back in this mode."); altTabPopup->setWhatsThis( wtstr ); connect(focusCombo, SIGNAL(activated(int)), this, SLOT(updateAltTabMode())); traverseAll = new QCheckBox( i18n( "&Traverse windows on all desktops" ), kbdBox ); kLay->addWidget( traverseAll ); wtstr = i18n( "Leave this option disabled if you want to limit walking through" " windows to the current desktop." ); traverseAll->setWhatsThis( wtstr ); rollOverDesktops = new QCheckBox( i18n("Desktop navi&gation wraps around"), kbdBox ); kLay->addWidget(rollOverDesktops); wtstr = i18n( "Enable this option if you want keyboard or active desktop border navigation beyond" " the edge of a desktop to take you to the opposite edge of the new desktop." ); rollOverDesktops->setWhatsThis( wtstr ); showPopupinfo = new QCheckBox( i18n("Popup desktop name on desktop &switch"), kbdBox ); kLay->addWidget(showPopupinfo); wtstr = i18n( "Enable this option if you wish to see the current desktop" " name popup whenever the current desktop is changed." ); showPopupinfo->setWhatsThis( wtstr ); lay->addWidget(kbdBox); lay->addStretch(); // Any changes goes to slotChanged() connect(focusCombo, SIGNAL(activated(int)), SLOT(changed())); connect(fcsBox, SIGNAL(clicked(int)), SLOT(changed())); connect(autoRaise, SIGNAL(valueChanged(int)), SLOT(changed())); connect(delayFocus, SIGNAL(valueChanged(int)), SLOT(changed())); connect(altTabPopup, SIGNAL(clicked()), SLOT(changed())); connect(traverseAll, SIGNAL(clicked()), SLOT(changed())); connect(rollOverDesktops, SIGNAL(clicked()), SLOT(changed())); connect(showPopupinfo, SIGNAL(clicked()), SLOT(changed())); load(); } int KFocusConfig::getFocus() { return focusCombo->currentIndex(); } void KFocusConfig::setFocus(int foc) { focusCombo->setCurrentIndex(foc); // this will disable/hide the auto raise delay widget if focus==click setAutoRaiseEnabled(); updateAltTabMode(); } void KFocusConfig::updateAltTabMode() { // not KDE-style Alt+Tab with unreasonable focus policies altTabPopup->setEnabled( focusCombo->currentIndex() == 0 || focusCombo->currentIndex() == 1 ); } void KFocusConfig::setAutoRaiseInterval(int tb) { autoRaise->setValue(tb); } void KFocusConfig::setDelayFocusInterval(int tb) { delayFocus->setValue(tb); } int KFocusConfig::getAutoRaiseInterval() { return autoRaise->value(); } int KFocusConfig::getDelayFocusInterval() { return delayFocus->value(); } void KFocusConfig::setAutoRaise(bool on) { autoRaiseOn->setChecked(on); } void KFocusConfig::setDelayFocus(bool on) { delayFocusOn->setChecked(on); } void KFocusConfig::setClickRaise(bool on) { clickRaiseOn->setChecked(on); } void KFocusConfig::setAutoRaiseEnabled() { // the auto raise related widgets are: autoRaise if ( focusCombo->currentIndex() != CLICK_TO_FOCUS ) { autoRaiseOn->setEnabled(true); autoRaiseOnTog(autoRaiseOn->isChecked()); } else { autoRaiseOn->setEnabled(false); autoRaiseOnTog(false); } } void KFocusConfig::setDelayFocusEnabled() { // the delayed focus related widgets are: delayFocus if ( focusCombo->currentIndex() != CLICK_TO_FOCUS ) { delayFocusOn->setEnabled(true); delayFocusOnTog(delayFocusOn->isChecked()); } else { delayFocusOn->setEnabled(false); delayFocusOnTog(false); } } void KFocusConfig::autoRaiseOnTog(bool a) { autoRaise->setEnabled(a); clickRaiseOn->setEnabled( !a ); } void KFocusConfig::delayFocusOnTog(bool a) { delayFocus->setEnabled(a); } void KFocusConfig::clickRaiseOnTog(bool ) { } void KFocusConfig::setAltTabMode(bool a) { altTabPopup->setChecked(a); } void KFocusConfig::setTraverseAll(bool a) { traverseAll->setChecked(a); } void KFocusConfig::setRollOverDesktops(bool a) { rollOverDesktops->setChecked(a); } void KFocusConfig::setShowPopupinfo(bool a) { showPopupinfo->setChecked(a); } void KFocusConfig::load( void ) { QString key; KConfigGroup cg(config, "Windows"); key = cg.readEntry(KWIN_FOCUS); if( key == "ClickToFocus") setFocus(CLICK_TO_FOCUS); else if( key == "FocusFollowsMouse") setFocus(FOCUS_FOLLOWS_MOUSE); else if(key == "FocusUnderMouse") setFocus(FOCUS_UNDER_MOUSE); else if(key == "FocusStrictlyUnderMouse") setFocus(FOCUS_STRICTLY_UNDER_MOUSE); int k = cg.readEntry(KWIN_AUTORAISE_INTERVAL,750); setAutoRaiseInterval(k); k = cg.readEntry(KWIN_DELAYFOCUS_INTERVAL,750); setDelayFocusInterval(k); key = cg.readEntry(KWIN_AUTORAISE); setAutoRaise(key == "on"); key = cg.readEntry(KWIN_DELAYFOCUS); setDelayFocus(key == "on"); key = cg.readEntry(KWIN_CLICKRAISE); setClickRaise(key != "off"); setAutoRaiseEnabled(); // this will disable/hide the auto raise delay widget if focus==click setDelayFocusEnabled(); key = cg.readEntry(KWIN_ALTTABMODE, "KDE"); setAltTabMode(key == "KDE"); setRollOverDesktops( cg.readEntry(KWIN_ROLL_OVER_DESKTOPS, true)); setShowPopupinfo( config->group("PopupInfo").readEntry(KWIN_SHOW_POPUP, false)); setTraverseAll( config->group("TabBox").readEntry(KWIN_TRAVERSE_ALL, false)); config->setGroup("Desktops"); emit KCModule::changed(false); } void KFocusConfig::save( void ) { int v; KConfigGroup cg(config, "Windows"); v = getFocus(); if (v == CLICK_TO_FOCUS) cg.writeEntry(KWIN_FOCUS,"ClickToFocus"); else if (v == FOCUS_UNDER_MOUSE) cg.writeEntry(KWIN_FOCUS,"FocusUnderMouse"); else if (v == FOCUS_STRICTLY_UNDER_MOUSE) cg.writeEntry(KWIN_FOCUS,"FocusStrictlyUnderMouse"); else cg.writeEntry(KWIN_FOCUS,"FocusFollowsMouse"); v = getAutoRaiseInterval(); if (v <0) v = 0; cg.writeEntry(KWIN_AUTORAISE_INTERVAL,v); v = getDelayFocusInterval(); if (v <0) v = 0; cg.writeEntry(KWIN_DELAYFOCUS_INTERVAL,v); if (autoRaiseOn->isChecked()) cg.writeEntry(KWIN_AUTORAISE, "on"); else cg.writeEntry(KWIN_AUTORAISE, "off"); if (delayFocusOn->isChecked()) cg.writeEntry(KWIN_DELAYFOCUS, "on"); else cg.writeEntry(KWIN_DELAYFOCUS, "off"); if (clickRaiseOn->isChecked()) cg.writeEntry(KWIN_CLICKRAISE, "on"); else cg.writeEntry(KWIN_CLICKRAISE, "off"); if (altTabPopup->isChecked()) cg.writeEntry(KWIN_ALTTABMODE, "KDE"); else cg.writeEntry(KWIN_ALTTABMODE, "CDE"); cg.writeEntry( KWIN_ROLL_OVER_DESKTOPS, rollOverDesktops->isChecked()); config->group("PopupInfo").writeEntry( KWIN_SHOW_POPUP, showPopupinfo->isChecked()); config->group("TabBox").writeEntry( KWIN_TRAVERSE_ALL , traverseAll->isChecked()); config->setGroup("Desktops"); if (standAlone) { config->sync(); - QDBusInterface kwin( "org.kde.kwin", "/KWin", "org.kde.KWin" ); - kwin.call( "reconfigure" ); + // Send signal to all kwin instances + QDBusMessage message = + QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig"); + QDBusConnection::sessionBus().send(message); } emit KCModule::changed(false); } void KFocusConfig::defaults() { setAutoRaiseInterval(0); setDelayFocusInterval(0); setFocus(CLICK_TO_FOCUS); setAutoRaise(false); setDelayFocus(false); setClickRaise(true); setAltTabMode(true); setTraverseAll( false ); setRollOverDesktops(true); setShowPopupinfo(false); emit KCModule::changed(true); } KAdvancedConfig::~KAdvancedConfig () { if (standAlone) delete config; } KAdvancedConfig::KAdvancedConfig (bool _standAlone, KConfig *_config, const KComponentData &inst, QWidget *parent) : KCModule(inst, parent), config(_config), standAlone(_standAlone) { QString wtstr; QBoxLayout *lay = new QVBoxLayout (this); lay->setMargin(0); lay->setSpacing(KDialog::spacingHint()); //iTLabel = new QLabel(i18n(" Allowed overlap:\n" // "(% of desktop space)"), // plcBox); //iTLabel->setAlignment(AlignTop|AlignHCenter); //pLay->addWidget(iTLabel,1,1); //interactiveTrigger = new QSpinBox(0, 500, 1, plcBox); //pLay->addWidget(interactiveTrigger,1,2); //pLay->addRowSpacing(2,KDialog::spacingHint()); //lay->addWidget(plcBox); shBox = new Q3VButtonGroup(i18n("Shading"), this); animateShade = new QCheckBox(i18n("Anima&te"), shBox); animateShade->setWhatsThis( i18n("Animate the action of reducing the window to its titlebar (shading)" " as well as the expansion of a shaded window") ); shadeHoverOn = new QCheckBox(i18n("&Enable hover"), shBox); connect(shadeHoverOn, SIGNAL(toggled(bool)), this, SLOT(shadeHoverChanged(bool))); shadeHover = new KIntNumInput(500, shBox); shadeHover->setLabel(i18n("Dela&y:"), Qt::AlignVCenter|Qt::AlignLeft); shadeHover->setRange(0, 3000, 100, true); shadeHover->setSteps(100, 100); shadeHover->setSuffix(i18n(" msec")); shadeHoverOn->setWhatsThis( i18n("If Shade Hover is enabled, a shaded window will un-shade automatically " "when the mouse pointer has been over the title bar for some time.")); wtstr = i18n("Sets the time in milliseconds before the window unshades " "when the mouse pointer goes over the shaded window."); shadeHover->setWhatsThis( wtstr); lay->addWidget(shBox); // Any changes goes to slotChanged() connect(animateShade, SIGNAL(toggled(bool)), SLOT(changed())); connect(shadeHoverOn, SIGNAL(toggled(bool)), SLOT(changed())); connect(shadeHover, SIGNAL(valueChanged(int)), SLOT(changed())); electricBox = new Q3VButtonGroup(i18n("Active Desktop Borders"), this); electricBox->layout()->setMargin(15); electricBox->setWhatsThis( i18n("If this option is enabled, moving the mouse to a screen border" " will change your desktop. This is e.g. useful if you want to drag windows from one desktop" " to the other.") ); active_disable = new QRadioButton(i18n("D&isabled"), electricBox); active_move = new QRadioButton(i18n("Only &when moving windows"), electricBox); active_always = new QRadioButton(i18n("A&lways enabled"), electricBox); delays = new KIntNumInput(10, electricBox); delays->setRange(0, MAX_EDGE_RES, 50, true); delays->setSuffix(i18n(" msec")); delays->setLabel(i18n("Desktop &switch delay:")); delays->setWhatsThis( i18n("Here you can set a delay for switching desktops using the active" " borders feature. Desktops will be switched after the mouse has been pushed against a screen border" " for the specified number of milliseconds.") ); connect( electricBox, SIGNAL(clicked(int)), this, SLOT(setEBorders())); // Any changes goes to slotChanged() connect(electricBox, SIGNAL(clicked(int)), SLOT(changed())); connect(delays, SIGNAL(valueChanged(int)), SLOT(changed())); lay->addWidget(electricBox); QHBoxLayout* focusStealingLayout = new QHBoxLayout(); focusStealingLayout->setSpacing(KDialog::spacingHint()); lay->addLayout( focusStealingLayout ); QLabel* focusStealingLabel = new QLabel( i18n( "Focus stealing prevention level:" ), this ); focusStealing = new QComboBox( this ); focusStealing->addItem( i18nc( "Focus Stealing Prevention Level", "None" )); focusStealing->addItem( i18nc( "Focus Stealing Prevention Level", "Low" )); focusStealing->addItem( i18nc( "Focus Stealing Prevention Level", "Normal" )); focusStealing->addItem( i18nc( "Focus Stealing Prevention Level", "High" )); focusStealing->addItem( i18nc( "Focus Stealing Prevention Level", "Extreme" )); focusStealingLabel->setBuddy( focusStealing ); focusStealingLayout->addWidget( focusStealingLabel ); focusStealingLayout->addWidget( focusStealing, Qt::AlignLeft ); wtstr = i18n( "

This option specifies how much KWin will try to prevent unwanted focus stealing " "caused by unexpected activation of new windows. (Note: This feature does not " "work with the Focus Under Mouse or Focus Strictly Under Mouse focus policies.)" "

    " "
  • None: Prevention is turned off " "and new windows always become activated.
  • " "
  • Low: Prevention is enabled; when some window does not have support " "for the underlying mechanism and KWin cannot reliably decide whether to " "activate the window or not, it will be activated. This setting may have both " "worse and better results than normal level, depending on the applications.
  • " "
  • Normal: Prevention is enabled.
  • " "
  • High: New windows get activated only if no window is currently active " "or if they belong to the currently active application. This setting is probably " "not really usable when not using mouse focus policy.
  • " "
  • Extreme: All windows must be explicitly activated by the user.
  • " "

" "

Windows that are prevented from stealing focus are marked as demanding attention, " "which by default means their taskbar entry will be highlighted. This can be changed " "in the Notifications control module.

" ); focusStealing->setWhatsThis( wtstr ); focusStealingLabel->setWhatsThis( wtstr ); connect(focusStealing, SIGNAL(activated(int)), SLOT(changed())); hideUtilityWindowsForInactive = new QCheckBox( i18n( "Hide utility windows for inactive applications" ), this ); hideUtilityWindowsForInactive->setWhatsThis( i18n( "When turned on, utility windows (tool windows, torn-off menus,...) of inactive applications will be" " hidden and will be shown only when the application becomes active. Note that applications" " have to mark the windows with the proper window type for this feature to work." )); connect(hideUtilityWindowsForInactive, SIGNAL(toggled(bool)), SLOT(changed())); lay->addWidget( hideUtilityWindowsForInactive ); lay->addStretch(); load(); } void KAdvancedConfig::setShadeHover(bool on) { shadeHoverOn->setChecked(on); shadeHover->setEnabled(on); } void KAdvancedConfig::setShadeHoverInterval(int k) { shadeHover->setValue(k); } int KAdvancedConfig::getShadeHoverInterval() { return shadeHover->value(); } void KAdvancedConfig::shadeHoverChanged(bool a) { shadeHover->setEnabled(a); } void KAdvancedConfig::setAnimateShade(bool a) { animateShade->setChecked(a); } void KAdvancedConfig::setFocusStealing(int l) { l = qMax( 0, qMin( 4, l )); focusStealing->setCurrentIndex(l); } void KAdvancedConfig::setHideUtilityWindowsForInactive(bool s) { hideUtilityWindowsForInactive->setChecked( s ); } void KAdvancedConfig::load( void ) { KConfigGroup cg(config, "Windows"); setAnimateShade(cg.readEntry(KWIN_ANIMSHADE, true)); setShadeHover(cg.readEntry(KWIN_SHADEHOVER, false)); setShadeHoverInterval(cg.readEntry(KWIN_SHADEHOVER_INTERVAL, 250)); - setElectricBorders(cg.readEntry(KWM_ELECTRIC_BORDER, false)); + setElectricBorders(cg.readEntry(KWM_ELECTRIC_BORDER, 0)); setElectricBorderDelay(cg.readEntry(KWM_ELECTRIC_BORDER_DELAY, 150)); // setFocusStealing( cg.readEntry(KWIN_FOCUS_STEALING, 2 )); // TODO default to low for now setFocusStealing( cg.readEntry(KWIN_FOCUS_STEALING, 1 )); setHideUtilityWindowsForInactive( cg.readEntry( KWIN_HIDE_UTILITY, true)); emit KCModule::changed(false); } void KAdvancedConfig::save( void ) { int v; KConfigGroup cg(config, "Windows"); cg.writeEntry(KWIN_ANIMSHADE, animateShade->isChecked()); if (shadeHoverOn->isChecked()) cg.writeEntry(KWIN_SHADEHOVER, "on"); else cg.writeEntry(KWIN_SHADEHOVER, "off"); v = getShadeHoverInterval(); if (v<0) v = 0; cg.writeEntry(KWIN_SHADEHOVER_INTERVAL, v); cg.writeEntry(KWM_ELECTRIC_BORDER, getElectricBorders()); cg.writeEntry(KWM_ELECTRIC_BORDER_DELAY,getElectricBorderDelay()); cg.writeEntry(KWIN_FOCUS_STEALING, focusStealing->currentIndex()); cg.writeEntry(KWIN_HIDE_UTILITY, hideUtilityWindowsForInactive->isChecked()); if (standAlone) { config->sync(); - QDBusInterface kwin( "org.kde.kwin", "/KWin", "org.kde.KWin" ); - kwin.call( "reconfigure" ); + // Send signal to all kwin instances + QDBusMessage message = + QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig"); + QDBusConnection::sessionBus().send(message); + } emit KCModule::changed(false); } void KAdvancedConfig::defaults() { setAnimateShade(true); setShadeHover(false); setShadeHoverInterval(250); setElectricBorders(0); setElectricBorderDelay(150); // setFocusStealing(2); // TODO default to low for now setFocusStealing(1); setHideUtilityWindowsForInactive( true ); emit KCModule::changed(true); } void KAdvancedConfig::setEBorders() { delays->setEnabled(!active_disable->isChecked()); } int KAdvancedConfig::getElectricBorders() { if (active_move->isChecked()) return 1; if (active_always->isChecked()) return 2; return 0; } int KAdvancedConfig::getElectricBorderDelay() { return delays->value(); } void KAdvancedConfig::setElectricBorders(int i){ switch(i) { case 1: active_move->setChecked(true); break; case 2: active_always->setChecked(true); break; default: active_disable->setChecked(true); break; } setEBorders(); } void KAdvancedConfig::setElectricBorderDelay(int delay) { delays->setValue(delay); } KMovingConfig::~KMovingConfig () { if (standAlone) delete config; } KMovingConfig::KMovingConfig (bool _standAlone, KConfig *_config, const KComponentData &inst, QWidget *parent) : KCModule(inst, parent), config(_config), standAlone(_standAlone) { QString wtstr; QBoxLayout *lay = new QVBoxLayout (this); lay->setMargin(0); lay->setSpacing(KDialog::spacingHint()); windowsBox = new Q3ButtonGroup(i18n("Windows"), this); windowsBox->setColumnLayout( 0, Qt::Horizontal ); QBoxLayout *wLay = new QVBoxLayout (); wLay->setSpacing(KDialog::spacingHint()); windowsBox->layout()->addItem( wLay ); QBoxLayout *bLay = new QVBoxLayout; wLay->addLayout(bLay); opaque = new QCheckBox(i18n("Di&splay content in moving windows"), windowsBox); bLay->addWidget(opaque); opaque->setWhatsThis( i18n("Enable this option if you want a window's content to be fully shown" " while moving it, instead of just showing a window 'skeleton'. The result may not be satisfying" " on slow machines without graphic acceleration.") ); resizeOpaqueOn = new QCheckBox(i18n("Display content in &resizing windows"), windowsBox); bLay->addWidget(resizeOpaqueOn); resizeOpaqueOn->setWhatsThis( i18n("Enable this option if you want a window's content to be shown" " while resizing it, instead of just showing a window 'skeleton'. The result may not be satisfying" " on slow machines.") ); geometryTipOn = new QCheckBox(i18n("Display window &geometry when moving or resizing"), windowsBox); bLay->addWidget(geometryTipOn); geometryTipOn->setWhatsThis( i18n("Enable this option if you want a window's geometry to be displayed" " while it is being moved or resized. The window position relative" " to the top-left corner of the screen is displayed together with" " its size.")); QGridLayout *rLay = new QGridLayout(); bLay->addLayout(rLay); rLay->setColumnStretch(0,0); rLay->setColumnStretch(1,1); minimizeAnimOn = new QCheckBox(i18n("Animate minimi&ze and restore"), windowsBox); minimizeAnimOn->setWhatsThis( i18n("Enable this option if you want an animation shown when" " windows are minimized or restored." ) ); rLay->addWidget(minimizeAnimOn,0,0); minimizeAnimSlider = new QSlider(windowsBox); minimizeAnimSlider->setRange( 0, 10 ); minimizeAnimSlider->setSingleStep( 1 ); minimizeAnimSlider->setPageStep( 1 ); minimizeAnimSlider->setValue( 0 ); minimizeAnimSlider->setOrientation( Qt::Horizontal ); minimizeAnimSlider->setTickPosition(QSlider::TicksBelow); rLay->addWidget(minimizeAnimSlider,0,0,1,2); connect(minimizeAnimOn, SIGNAL(toggled(bool)), this, SLOT(setMinimizeAnim(bool))); connect(minimizeAnimSlider, SIGNAL(valueChanged(int)), this, SLOT(setMinimizeAnimSpeed(int))); minimizeAnimSlowLabel= new QLabel(i18n("Slow"),windowsBox); minimizeAnimSlowLabel->setAlignment(Qt::AlignTop|Qt::AlignLeft); rLay->addWidget(minimizeAnimSlowLabel,1,1); minimizeAnimFastLabel= new QLabel(i18n("Fast"),windowsBox); minimizeAnimFastLabel->setAlignment(Qt::AlignTop|Qt::AlignRight); rLay->addWidget(minimizeAnimFastLabel,1,2); wtstr = i18n("Here you can set the speed of the animation shown when windows are" " minimized and restored. "); minimizeAnimSlider->setWhatsThis( wtstr ); minimizeAnimSlowLabel->setWhatsThis( wtstr ); minimizeAnimFastLabel->setWhatsThis( wtstr ); moveResizeMaximized = new QCheckBox( i18n("Allow moving and resizing o&f maximized windows"), windowsBox); bLay->addWidget(moveResizeMaximized); moveResizeMaximized->setWhatsThis( i18n("When enabled, this feature activates the border of maximized windows" " and allows you to move or resize them," " just like for normal windows")); QBoxLayout *vLay = new QHBoxLayout(); bLay->addLayout( vLay ); QLabel *plcLabel = new QLabel(i18n("&Placement:"),windowsBox); placementCombo = new QComboBox(windowsBox); placementCombo->setEditable( false ); placementCombo->addItem(i18n("Smart"), SMART_PLACEMENT); placementCombo->addItem(i18n("Maximizing"), MAXIMIZING_PLACEMENT); placementCombo->addItem(i18n("Cascade"), CASCADE_PLACEMENT); placementCombo->addItem(i18n("Random"), RANDOM_PLACEMENT); placementCombo->addItem(i18n("Centered"), CENTERED_PLACEMENT); placementCombo->addItem(i18n("Zero-Cornered"), ZEROCORNERED_PLACEMENT); // CT: disabling is needed as long as functionality misses in kwin //placementCombo->addItem(i18n("Interactive"), INTERACTIVE_PLACEMENT); //placementCombo->addItem(i18n("Manual"), MANUAL_PLACEMENT); placementCombo->setCurrentIndex(SMART_PLACEMENT); // FIXME, when more policies have been added to KWin wtstr = i18n("The placement policy determines where a new window" " will appear on the desktop." "
    " "
  • Smart will try to achieve a minimum overlap of windows
  • " "
  • Maximizing will try to maximize every window to fill the whole screen." " It might be useful to selectively affect placement of some windows using" " the window-specific settings.
  • " "
  • Cascade will cascade the windows
  • " "
  • Random will use a random position
  • " "
  • Centered will place the window centered
  • " "
  • Zero-Cornered will place the window in the top-left corner
  • " "
") ; plcLabel->setWhatsThis( wtstr); placementCombo->setWhatsThis( wtstr); plcLabel->setBuddy(placementCombo); vLay->addWidget(plcLabel, 0); vLay->addWidget(placementCombo, 1, Qt::AlignLeft); bLay->addSpacing(10); lay->addWidget(windowsBox); //iTLabel = new QLabel(i18n(" Allowed overlap:\n" // "(% of desktop space)"), // plcBox); //iTLabel->setAlignment(AlignTop|AlignHCenter); //pLay->addWidget(iTLabel,1,1); //interactiveTrigger = new QSpinBox(0, 500, 1, plcBox); //pLay->addWidget(interactiveTrigger,1,2); //pLay->addRowSpacing(2,KDialog::spacingHint()); //lay->addWidget(plcBox); //CT 15mar98 - add EdgeResistance, BorderAttractor, WindowsAttractor config MagicBox = new Q3VButtonGroup(i18n("Snap Zones"), this); MagicBox->layout()->setMargin(15); BrdrSnap = new KIntNumInput(10, MagicBox); BrdrSnap->setSpecialValueText( i18n("none") ); BrdrSnap->setRange( 0, MAX_BRDR_SNAP); BrdrSnap->setLabel(i18n("&Border snap zone:")); BrdrSnap->setSteps(1,10); BrdrSnap->setWhatsThis( i18n("Here you can set the snap zone for screen borders, i.e." " the 'strength' of the magnetic field which will make windows snap to the border when" " moved near it.") ); WndwSnap = new KIntNumInput(10, MagicBox); WndwSnap->setSpecialValueText( i18n("none") ); WndwSnap->setRange( 0, MAX_WNDW_SNAP); WndwSnap->setLabel(i18n("&Window snap zone:")); BrdrSnap->setSteps(1,10); WndwSnap->setWhatsThis( i18n("Here you can set the snap zone for windows, i.e." " the 'strength' of the magnetic field which will make windows snap to each other when" " they're moved near another window.") ); OverlapSnap=new QCheckBox(i18n("Snap windows onl&y when overlapping"),MagicBox); OverlapSnap->setWhatsThis( i18n("Here you can set that windows will be only" " snapped if you try to overlap them, i.e. they will not be snapped if the windows" " comes only near another window or border.") ); lay->addWidget(MagicBox); lay->addStretch(); load(); // Any changes goes to slotChanged() connect( opaque, SIGNAL(clicked()), SLOT(changed())); connect( resizeOpaqueOn, SIGNAL(clicked()), SLOT(changed())); connect( geometryTipOn, SIGNAL(clicked()), SLOT(changed())); connect( minimizeAnimOn, SIGNAL(clicked() ), SLOT(changed())); connect( minimizeAnimSlider, SIGNAL(valueChanged(int)), SLOT(changed())); connect( moveResizeMaximized, SIGNAL(toggled(bool)), SLOT(changed())); connect( placementCombo, SIGNAL(activated(int)), SLOT(changed())); connect( BrdrSnap, SIGNAL(valueChanged(int)), SLOT(changed())); connect( BrdrSnap, SIGNAL(valueChanged(int)), SLOT(slotBrdrSnapChanged(int))); connect( WndwSnap, SIGNAL(valueChanged(int)), SLOT(changed())); connect( WndwSnap, SIGNAL(valueChanged(int)), SLOT(slotWndwSnapChanged(int))); connect( OverlapSnap, SIGNAL(clicked()), SLOT(changed())); // To get suffix to BrdrSnap and WndwSnap inputs with default values. slotBrdrSnapChanged(BrdrSnap->value()); slotWndwSnapChanged(WndwSnap->value()); } int KMovingConfig::getMove() { return (opaque->isChecked())? OPAQUE : TRANSPARENT; } void KMovingConfig::setMove(int trans) { opaque->setChecked(trans == OPAQUE); } void KMovingConfig::setGeometryTip(bool showGeometryTip) { geometryTipOn->setChecked(showGeometryTip); } bool KMovingConfig::getGeometryTip() { return geometryTipOn->isChecked(); } // placement policy --- CT 31jan98 --- int KMovingConfig::getPlacement() { return placementCombo->currentIndex(); } void KMovingConfig::setPlacement(int plac) { placementCombo->setCurrentIndex(plac); } bool KMovingConfig::getMinimizeAnim() { return minimizeAnimOn->isChecked(); } int KMovingConfig::getMinimizeAnimSpeed() { return minimizeAnimSlider->value(); } void KMovingConfig::setMinimizeAnim(bool anim) { minimizeAnimOn->setChecked( anim ); minimizeAnimSlider->setEnabled( anim ); minimizeAnimSlowLabel->setEnabled( anim ); minimizeAnimFastLabel->setEnabled( anim ); } void KMovingConfig::setMinimizeAnimSpeed(int speed) { minimizeAnimSlider->setValue(speed); } int KMovingConfig::getResizeOpaque() { return (resizeOpaqueOn->isChecked())? RESIZE_OPAQUE : RESIZE_TRANSPARENT; } void KMovingConfig::setResizeOpaque(int opaque) { resizeOpaqueOn->setChecked(opaque == RESIZE_OPAQUE); } void KMovingConfig::setMoveResizeMaximized(bool a) { moveResizeMaximized->setChecked(a); } void KMovingConfig::slotBrdrSnapChanged(int value) { BrdrSnap->setSuffix(i18np(" pixel", " pixels", value)); } void KMovingConfig::slotWndwSnapChanged(int value) { WndwSnap->setSuffix(i18np(" pixel", " pixels", value)); } void KMovingConfig::load( void ) { QString key; KConfigGroup cg(config, "Windows"); key = cg.readEntry(KWIN_MOVE, "Opaque"); if( key == "Transparent") setMove(TRANSPARENT); else if( key == "Opaque") setMove(OPAQUE); //CT 17Jun1998 - variable animation speed from 0 (none!!) to 10 (max) bool anim = cg.readEntry(KWIN_MINIMIZE_ANIM, true); int animSpeed = cg.readEntry(KWIN_MINIMIZE_ANIM_SPEED, 5); if( animSpeed < 1 ) animSpeed = 0; if( animSpeed > 10 ) animSpeed = 10; setMinimizeAnim( anim ); setMinimizeAnimSpeed( animSpeed ); // DF: please keep the default consistent with kwin (options.cpp line 145) key = cg.readEntry(KWIN_RESIZE_OPAQUE, "Opaque"); if( key == "Opaque") setResizeOpaque(RESIZE_OPAQUE); else if ( key == "Transparent") setResizeOpaque(RESIZE_TRANSPARENT); //KS 10Jan2003 - Geometry Tip during window move/resize bool showGeomTip = cg.readEntry(KWIN_GEOMETRY, false); setGeometryTip( showGeomTip ); // placement policy --- CT 19jan98 --- key = cg.readEntry(KWIN_PLACEMENT); //CT 13mar98 interactive placement // if( key.left(11) == "interactive") { // setPlacement(INTERACTIVE_PLACEMENT); // int comma_pos = key.find(','); // if (comma_pos < 0) // interactiveTrigger->setValue(0); // else // interactiveTrigger->setValue (key.right(key.length() // - comma_pos).toUInt(0)); // iTLabel->setEnabled(true); // interactiveTrigger->show(); // } // else { // interactiveTrigger->setValue(0); // iTLabel->setEnabled(false); // interactiveTrigger->hide(); if( key == "Random") setPlacement(RANDOM_PLACEMENT); else if( key == "Cascade") setPlacement(CASCADE_PLACEMENT); //CT 31jan98 //CT 31mar98 manual placement else if( key == "manual") setPlacement(MANUAL_PLACEMENT); else if( key == "Centered") setPlacement(CENTERED_PLACEMENT); else if( key == "ZeroCornered") setPlacement(ZEROCORNERED_PLACEMENT); else if( key == "Maximizing") setPlacement(MAXIMIZING_PLACEMENT); else setPlacement(SMART_PLACEMENT); // } setMoveResizeMaximized(cg.readEntry(KWIN_MOVE_RESIZE_MAXIMIZED, false)); int v; v = cg.readEntry(KWM_BRDR_SNAP_ZONE, KWM_BRDR_SNAP_ZONE_DEFAULT); if (v > MAX_BRDR_SNAP) setBorderSnapZone(MAX_BRDR_SNAP); else if (v < 0) setBorderSnapZone (0); else setBorderSnapZone(v); v = cg.readEntry(KWM_WNDW_SNAP_ZONE, KWM_WNDW_SNAP_ZONE_DEFAULT); if (v > MAX_WNDW_SNAP) setWindowSnapZone(MAX_WNDW_SNAP); else if (v < 0) setWindowSnapZone (0); else setWindowSnapZone(v); OverlapSnap->setChecked(cg.readEntry("SnapOnlyWhenOverlapping", false)); emit KCModule::changed(false); } void KMovingConfig::save( void ) { int v; KConfigGroup cg(config, "Windows"); v = getMove(); if (v == TRANSPARENT) cg.writeEntry(KWIN_MOVE,"Transparent"); else cg.writeEntry(KWIN_MOVE,"Opaque"); cg.writeEntry(KWIN_GEOMETRY, getGeometryTip()); // placement policy --- CT 31jan98 --- v =getPlacement(); if (v == RANDOM_PLACEMENT) cg.writeEntry(KWIN_PLACEMENT, "Random"); else if (v == CASCADE_PLACEMENT) cg.writeEntry(KWIN_PLACEMENT, "Cascade"); else if (v == CENTERED_PLACEMENT) cg.writeEntry(KWIN_PLACEMENT, "Centered"); else if (v == ZEROCORNERED_PLACEMENT) cg.writeEntry(KWIN_PLACEMENT, "ZeroCornered"); else if (v == MAXIMIZING_PLACEMENT) cg.writeEntry(KWIN_PLACEMENT, "Maximizing"); //CT 13mar98 manual and interactive placement // else if (v == MANUAL_PLACEMENT) // cg.writeEntry(KWIN_PLACEMENT, "Manual"); // else if (v == INTERACTIVE_PLACEMENT) { // QString tmpstr = QString("Interactive,%1").arg(interactiveTrigger->value()); // cg.writeEntry(KWIN_PLACEMENT, tmpstr); // } else cg.writeEntry(KWIN_PLACEMENT, "Smart"); cg.writeEntry(KWIN_MINIMIZE_ANIM, getMinimizeAnim()); cg.writeEntry(KWIN_MINIMIZE_ANIM_SPEED, getMinimizeAnimSpeed()); v = getResizeOpaque(); if (v == RESIZE_OPAQUE) cg.writeEntry(KWIN_RESIZE_OPAQUE, "Opaque"); else cg.writeEntry(KWIN_RESIZE_OPAQUE, "Transparent"); cg.writeEntry(KWIN_MOVE_RESIZE_MAXIMIZED, moveResizeMaximized->isChecked()); cg.writeEntry(KWM_BRDR_SNAP_ZONE,getBorderSnapZone()); cg.writeEntry(KWM_WNDW_SNAP_ZONE,getWindowSnapZone()); cg.writeEntry("SnapOnlyWhenOverlapping",OverlapSnap->isChecked()); if (standAlone) { config->sync(); - QDBusInterface kwin( "org.kde.kwin", "/KWin", "org.kde.KWin" ); - kwin.call( "reconfigure" ); + // Send signal to all kwin instances + QDBusMessage message = + QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig"); + QDBusConnection::sessionBus().send(message); } emit KCModule::changed(false); } void KMovingConfig::defaults() { setMove(OPAQUE); setResizeOpaque(RESIZE_TRANSPARENT); setGeometryTip(false); setPlacement(SMART_PLACEMENT); setMoveResizeMaximized(false); //copied from kcontrol/konq/kwindesktop, aleXXX setWindowSnapZone(KWM_WNDW_SNAP_ZONE_DEFAULT); setBorderSnapZone(KWM_BRDR_SNAP_ZONE_DEFAULT); OverlapSnap->setChecked(false); setMinimizeAnim( true ); setMinimizeAnimSpeed( 5 ); emit KCModule::changed(true); } int KMovingConfig::getBorderSnapZone() { return BrdrSnap->value(); } void KMovingConfig::setBorderSnapZone(int pxls) { BrdrSnap->setValue(pxls); } int KMovingConfig::getWindowSnapZone() { return WndwSnap->value(); } void KMovingConfig::setWindowSnapZone(int pxls) { WndwSnap->setValue(pxls); } KTranslucencyConfig::~KTranslucencyConfig () { if (standAlone) delete config; if (kompmgr) kompmgr->detach(); } KTranslucencyConfig::KTranslucencyConfig (bool _standAlone, KConfig *_config, const KComponentData &inst, QWidget *parent) : KCModule(inst, parent), config(_config), standAlone(_standAlone) { kompmgr = 0L; resetKompmgr_ = false; QVBoxLayout *lay = new QVBoxLayout (this); kompmgrAvailable_ = kompmgrAvailable(); if (!kompmgrAvailable_){ QLabel *label = new QLabel(i18n("It seems that alpha channel support is not available.

" "Please make sure you have " "Xorg ≥ 6.8," " and have installed the kompmgr that came with kwin.
" "Also, make sure you have the following entries in your XConfig (e.g. /etc/X11/xorg.conf):

" "Section \"Extensions\"
" "Option \"Composite\" \"Enable\"
" "EndSection


" "And if your GPU provides hardware-accelerated Xrender support (mainly nVidia cards):

" "Option \"RenderAccel\" \"true\"
" "In Section \"Device\"
"), this); + label->setOpenExternalLinks(true); + label->setTextInteractionFlags(Qt::LinksAccessibleByMouse); lay->addWidget(label); } else { QTabWidget *tabW = new QTabWidget(this); QWidget *tGroup = new QWidget(tabW); QVBoxLayout *vLay = new QVBoxLayout (tGroup); vLay->setMargin(KDialog::marginHint()); vLay->setSpacing(KDialog::spacingHint()); vLay->addSpacing(11); // to get the proper gb top offset onlyDecoTranslucent = new QCheckBox(i18n("Apply translucency only to decoration"),tGroup); vLay->addWidget(onlyDecoTranslucent); vLay->addSpacing(11); QGridLayout *gLay = new QGridLayout(); gLay->setSpacing(KDialog::spacingHint()); gLay->setColumnStretch(1,1); vLay->addLayout( gLay ); activeWindowTransparency = new QCheckBox(i18n("Active windows:"),tGroup); gLay->addWidget(activeWindowTransparency,0,0); activeWindowOpacity = new KIntNumInput(100, tGroup); activeWindowOpacity->setRange(0,100); activeWindowOpacity->setSuffix("%"); gLay->addWidget(activeWindowOpacity,0,1); inactiveWindowTransparency = new QCheckBox(i18n("Inactive windows:"),tGroup); gLay->addWidget(inactiveWindowTransparency,1,0); inactiveWindowOpacity = new KIntNumInput(100, tGroup); inactiveWindowOpacity->setRange(0,100); inactiveWindowOpacity->setSuffix("%"); gLay->addWidget(inactiveWindowOpacity,1,1); movingWindowTransparency = new QCheckBox(i18n("Moving windows:"),tGroup); gLay->addWidget(movingWindowTransparency,2,0); movingWindowOpacity = new KIntNumInput(100, tGroup); movingWindowOpacity->setRange(0,100); movingWindowOpacity->setSuffix("%"); gLay->addWidget(movingWindowOpacity,2,1); dockWindowTransparency = new QCheckBox(i18n("Dock windows:"),tGroup); gLay->addWidget(dockWindowTransparency,3,0); dockWindowOpacity = new KIntNumInput(100, tGroup); dockWindowOpacity->setRange(0,100); dockWindowOpacity->setSuffix("%"); gLay->addWidget(dockWindowOpacity,3,1); vLay->addSpacing(11); keepAboveAsActive = new QCheckBox(i18n("Treat 'keep above' windows as active ones"),tGroup); vLay->addWidget(keepAboveAsActive); disableARGB = new QCheckBox(i18n("Disable ARGB windows (ignores window alpha maps, fixes gtk1 apps)"),tGroup); vLay->addWidget(disableARGB); vLay->addStretch(); tabW->addTab(tGroup, i18n("Opacity")); QWidget *sGroup = new QWidget(tabW); // sGroup->setCheckable(true); QVBoxLayout *vLay2 = new QVBoxLayout (sGroup); vLay2->setMargin(11); vLay2->setSpacing(6); vLay2->addSpacing(11); // to get the proper gb top offset useShadows = new QCheckBox(i18n("Use shadows"),sGroup); vLay2->addWidget(useShadows); vLay2->addSpacing(11); QGridLayout *gLay2 = new QGridLayout(); gLay2->setColumnStretch(1,1); vLay2->addLayout( gLay2 ); QLabel *label1 = new QLabel(i18n("Active window size:"),sGroup); gLay2->addWidget(label1,0,0); activeWindowShadowSize = new KIntNumInput(12,sGroup); activeWindowShadowSize->setRange(0,32); // activeWindowShadowSize->setSuffix("px"); gLay2->addWidget(activeWindowShadowSize,0,1); QLabel *label2 = new QLabel(i18n("Inactive window size:"),sGroup); gLay2->addWidget(label2,1,0); inactiveWindowShadowSize = new KIntNumInput(6,sGroup); inactiveWindowShadowSize->setRange(0,32); // inactiveWindowShadowSize->setSuffix("px"); gLay2->addWidget(inactiveWindowShadowSize,1,1); QLabel *label3 = new QLabel(i18n("Dock window size:"),sGroup); gLay2->addWidget(label3,2,0); dockWindowShadowSize = new KIntNumInput(6,sGroup); dockWindowShadowSize->setRange(0,32); // dockWindowShadowSize->setSuffix("px"); gLay2->addWidget(dockWindowShadowSize,2,1); QLabel *label4 = new QLabel(i18n("Vertical offset:"),sGroup); gLay2->addWidget(label4,3,0); shadowTopOffset = new KIntNumInput(80,sGroup); shadowTopOffset->setSuffix("%"); shadowTopOffset->setRange(-200,200); gLay2->addWidget(shadowTopOffset,3,1); QLabel *label5 = new QLabel(i18n("Horizontal offset:"),sGroup); gLay2->addWidget(label5,4,0); shadowLeftOffset = new KIntNumInput(0,sGroup); shadowLeftOffset->setSuffix("%"); shadowLeftOffset->setRange(-200,200); gLay2->addWidget(shadowLeftOffset,4,1); QLabel *label6 = new QLabel(i18n("Shadow color:"),sGroup); gLay2->addWidget(label6,5,0); shadowColor = new KColorButton(Qt::black,sGroup); gLay2->addWidget(shadowColor,5,1); gLay2->setColumnStretch(1,1); vLay2->addSpacing(11); removeShadowsOnMove = new QCheckBox(i18n("Remove shadows on move"),sGroup); vLay2->addWidget(removeShadowsOnMove); removeShadowsOnResize = new QCheckBox(i18n("Remove shadows on resize"),sGroup); vLay2->addWidget(removeShadowsOnResize); vLay2->addStretch(); tabW->addTab(sGroup, i18n("Shadows")); QWidget *eGroup = new QWidget(this); QVBoxLayout *vLay3 = new QVBoxLayout (eGroup); vLay3->setMargin( 11 ); vLay3->setSpacing( 6 ); fadeInWindows = new QCheckBox(i18n("Fade-in windows (including popups)"),eGroup); fadeOnOpacityChange = new QCheckBox(i18n("Fade between opacity changes"),eGroup); fadeInSpeed = new KIntNumInput(100, eGroup); fadeInSpeed->setRange(1,100); fadeInSpeed->setLabel("Fade-in speed:"); fadeOutSpeed = new KIntNumInput(100, eGroup); fadeOutSpeed->setRange(1,100); fadeOutSpeed->setLabel("Fade-out speed:"); vLay3->addWidget(fadeInWindows); vLay3->addWidget(fadeOnOpacityChange); vLay3->addWidget(fadeInSpeed); vLay3->addWidget(fadeOutSpeed); vLay3->addStretch(); tabW->addTab(eGroup, i18n("Effects")); useTranslucency = new QCheckBox(i18n("Use translucency/shadows"),this); lay->addWidget(useTranslucency); lay->addWidget(tabW); connect(useTranslucency, SIGNAL(toggled(bool)), tabW, SLOT(setEnabled(bool))); connect(activeWindowTransparency, SIGNAL(toggled(bool)), activeWindowOpacity, SLOT(setEnabled(bool))); connect(inactiveWindowTransparency, SIGNAL(toggled(bool)), inactiveWindowOpacity, SLOT(setEnabled(bool))); connect(movingWindowTransparency, SIGNAL(toggled(bool)), movingWindowOpacity, SLOT(setEnabled(bool))); connect(dockWindowTransparency, SIGNAL(toggled(bool)), dockWindowOpacity, SLOT(setEnabled(bool))); connect(useTranslucency, SIGNAL(toggled(bool)), SLOT(changed())); connect(onlyDecoTranslucent, SIGNAL(toggled(bool)), SLOT(changed())); connect(activeWindowTransparency, SIGNAL(toggled(bool)), SLOT(changed())); connect(inactiveWindowTransparency, SIGNAL(toggled(bool)), SLOT(changed())); connect(movingWindowTransparency, SIGNAL(toggled(bool)), SLOT(changed())); connect(dockWindowTransparency, SIGNAL(toggled(bool)), SLOT(changed())); connect(keepAboveAsActive, SIGNAL(toggled(bool)), SLOT(changed())); connect(disableARGB, SIGNAL(toggled(bool)), SLOT(changed())); connect(useShadows, SIGNAL(toggled(bool)), SLOT(changed())); connect(removeShadowsOnResize, SIGNAL(toggled(bool)), SLOT(changed())); connect(removeShadowsOnMove, SIGNAL(toggled(bool)), SLOT(changed())); connect(activeWindowOpacity, SIGNAL(valueChanged(int)), SLOT(changed())); connect(inactiveWindowOpacity, SIGNAL(valueChanged(int)), SLOT(changed())); connect(movingWindowOpacity, SIGNAL(valueChanged(int)), SLOT(changed())); connect(dockWindowOpacity, SIGNAL(valueChanged(int)), SLOT(changed())); connect(dockWindowShadowSize, SIGNAL(valueChanged(int)), SLOT(changed())); connect(activeWindowShadowSize, SIGNAL(valueChanged(int)), SLOT(changed())); connect(inactiveWindowShadowSize, SIGNAL(valueChanged(int)), SLOT(changed())); connect(shadowTopOffset, SIGNAL(valueChanged(int)), SLOT(changed())); connect(shadowLeftOffset, SIGNAL(valueChanged(int)), SLOT(changed())); connect(shadowColor, SIGNAL(changed(const QColor&)), SLOT(changed())); connect(fadeInWindows, SIGNAL(toggled(bool)), SLOT(changed())); connect(fadeOnOpacityChange, SIGNAL(toggled(bool)), SLOT(changed())); connect(fadeInSpeed, SIGNAL(valueChanged(int)), SLOT(changed())); connect(fadeOutSpeed, SIGNAL(valueChanged(int)), SLOT(changed())); connect(useShadows, SIGNAL(toggled(bool)), dockWindowShadowSize, SLOT(setEnabled(bool))); connect(useShadows, SIGNAL(toggled(bool)), activeWindowShadowSize, SLOT(setEnabled(bool))); connect(useShadows, SIGNAL(toggled(bool)), inactiveWindowShadowSize, SLOT(setEnabled(bool))); connect(useShadows, SIGNAL(toggled(bool)), shadowTopOffset, SLOT(setEnabled(bool))); connect(useShadows, SIGNAL(toggled(bool)), shadowLeftOffset, SLOT(setEnabled(bool))); connect(useShadows, SIGNAL(toggled(bool)), shadowColor, SLOT(setEnabled(bool))); load(); tabW->setEnabled(useTranslucency->isChecked()); connect(useTranslucency, SIGNAL(toggled(bool)), this, SLOT(showWarning(bool))); // handle kompmgr restarts if necessary connect(useTranslucency, SIGNAL(toggled(bool)), SLOT(resetKompmgr())); connect(disableARGB, SIGNAL(toggled(bool)), SLOT(resetKompmgr())); connect(useShadows, SIGNAL(toggled(bool)), SLOT(resetKompmgr())); connect(inactiveWindowShadowSize, SIGNAL(valueChanged(int)), SLOT(resetKompmgr())); connect(shadowTopOffset, SIGNAL(valueChanged(int)), SLOT(resetKompmgr())); connect(shadowLeftOffset, SIGNAL(valueChanged(int)), SLOT(resetKompmgr())); connect(shadowColor, SIGNAL(changed(const QColor&)), SLOT(resetKompmgr())); connect(fadeInWindows, SIGNAL(toggled(bool)), SLOT(resetKompmgr())); connect(fadeOnOpacityChange, SIGNAL(toggled(bool)), SLOT(resetKompmgr())); connect(fadeInSpeed, SIGNAL(valueChanged(int)), SLOT(resetKompmgr())); connect(fadeOutSpeed, SIGNAL(valueChanged(int)), SLOT(resetKompmgr())); } } void KTranslucencyConfig::resetKompmgr() { resetKompmgr_ = true; } void KTranslucencyConfig::load( void ) { if (!kompmgrAvailable_) return; + useTranslucency->setChecked(config->group("Notification Messages").readEntry("UseTranslucency", false)); KConfigGroup translucencyConfig(config, "Translucency"); - useTranslucency->setChecked(translucencyConfig.readEntry("UseTranslucency", false)); activeWindowTransparency->setChecked(translucencyConfig.readEntry("TranslucentActiveWindows", false)); inactiveWindowTransparency->setChecked(translucencyConfig.readEntry("TranslucentInactiveWindows", true)); movingWindowTransparency->setChecked(translucencyConfig.readEntry("TranslucentMovingWindows", false)); removeShadowsOnMove->setChecked(translucencyConfig.readEntry("RemoveShadowsOnMove", false)); removeShadowsOnResize->setChecked(translucencyConfig.readEntry("RemoveShadowsOnResize", false)); dockWindowTransparency->setChecked(translucencyConfig.readEntry("TranslucentDocks", true)); keepAboveAsActive->setChecked(translucencyConfig.readEntry("TreatKeepAboveAsActive", true)); onlyDecoTranslucent->setChecked(translucencyConfig.readEntry("OnlyDecoTranslucent", false)); activeWindowOpacity->setValue(translucencyConfig.readEntry("ActiveWindowOpacity",100)); inactiveWindowOpacity->setValue(translucencyConfig.readEntry("InactiveWindowOpacity",75)); movingWindowOpacity->setValue(translucencyConfig.readEntry("MovingWindowOpacity",25)); dockWindowOpacity->setValue(translucencyConfig.readEntry("DockOpacity",80)); int ass, iss, dss; dss = translucencyConfig.readEntry("DockShadowSize", 33); ass = translucencyConfig.readEntry("ActiveWindowShadowSize", 133); iss = translucencyConfig.readEntry("InactiveWindowShadowSize", 67); activeWindowOpacity->setEnabled(activeWindowTransparency->isChecked()); inactiveWindowOpacity->setEnabled(inactiveWindowTransparency->isChecked()); movingWindowOpacity->setEnabled(movingWindowTransparency->isChecked()); dockWindowOpacity->setEnabled(dockWindowTransparency->isChecked()); KConfig *pConf = new KConfig(QDir::homePath() + "/.xcompmgrrc"); KConfigGroup conf_(pConf, "xcompmgr"); disableARGB->setChecked(conf_.readEntry("DisableARGB", false)); useShadows->setChecked(conf_.readEntry("Compmode","CompClientShadows").compare("CompClientShadows") == 0); shadowTopOffset->setValue(-1*(conf_.readEntry("ShadowOffsetY",-80))); shadowLeftOffset->setValue(-1*(conf_.readEntry("ShadowOffsetX",0))); int ss = conf_.readEntry("ShadowRadius",6); dockWindowShadowSize->setValue((int)(dss*ss/100.0)); activeWindowShadowSize->setValue((int)(ass*ss/100.0)); inactiveWindowShadowSize->setValue((int)(iss*ss/100.0)); QString hex = conf_.readEntry("ShadowColor","#000000"); uint r, g, b; r = g = b = 256; if (sscanf(hex.toLatin1(), "0x%02x%02x%02x", &r, &g, &b)!=3 || r > 255 || g > 255 || b > 255) shadowColor->setColor(Qt::black); else shadowColor->setColor(QColor(r,g,b)); fadeInWindows->setChecked(conf_.readEntry("FadeWindows", true)); fadeOnOpacityChange->setChecked(conf_.readEntry("FadeTrans", false)); fadeInSpeed->setValue((int)(conf_.readEntry("FadeInStep",0.020)*1000.0)); fadeOutSpeed->setValue((int)(conf_.readEntry("FadeOutStep",0.070)*1000.0)); delete pConf; emit KCModule::changed(false); } void KTranslucencyConfig::save( void ) { if (!kompmgrAvailable_) return; + config->group("Notification Messages").writeEntry("UseTranslucency",useTranslucency->isChecked()); + KConfigGroup translucencyConfig(config, "Translucency"); - translucencyConfig.writeEntry("UseTranslucency",useTranslucency->isChecked()); translucencyConfig.writeEntry("TranslucentActiveWindows",activeWindowTransparency->isChecked()); translucencyConfig.writeEntry("TranslucentInactiveWindows",inactiveWindowTransparency->isChecked()); translucencyConfig.writeEntry("TranslucentMovingWindows",movingWindowTransparency->isChecked()); translucencyConfig.writeEntry("TranslucentDocks",dockWindowTransparency->isChecked()); translucencyConfig.writeEntry("TreatKeepAboveAsActive",keepAboveAsActive->isChecked()); translucencyConfig.writeEntry("ActiveWindowOpacity",activeWindowOpacity->value()); translucencyConfig.writeEntry("InactiveWindowOpacity",inactiveWindowOpacity->value()); translucencyConfig.writeEntry("MovingWindowOpacity",movingWindowOpacity->value()); translucencyConfig.writeEntry("DockOpacity",dockWindowOpacity->value()); // for simplification: // xcompmgr supports a general shadow radius and additionally lets external apps set a multiplicator for each window // (speed reasons, so the shadow matrix hasn't to be recreated for every window) // we set inactive windows to 100%, the radius to the inactive window value and adjust the multiplicators for docks and active windows // this way the user can set the three values without caring about the radius/multiplicator stuff // additionally we find a value between big and small values to have a more smooth appereance translucencyConfig.writeEntry("DockShadowSize",(int)(200.0 * dockWindowShadowSize->value() / (activeWindowShadowSize->value() + inactiveWindowShadowSize->value()))); translucencyConfig.writeEntry("ActiveWindowShadowSize",(int)(200.0 * activeWindowShadowSize->value() / (activeWindowShadowSize->value() + inactiveWindowShadowSize->value()))); translucencyConfig.writeEntry("InctiveWindowShadowSize",(int)(200.0 * inactiveWindowShadowSize->value() / (activeWindowShadowSize->value() + inactiveWindowShadowSize->value()))); translucencyConfig.writeEntry("RemoveShadowsOnMove",removeShadowsOnMove->isChecked()); translucencyConfig.writeEntry("RemoveShadowsOnResize",removeShadowsOnResize->isChecked()); translucencyConfig.writeEntry("OnlyDecoTranslucent", onlyDecoTranslucent->isChecked()); translucencyConfig.writeEntry("ResetKompmgr",resetKompmgr_); KConfig *pConf = new KConfig(QDir::homePath() + "/.xcompmgrrc"); KConfigGroup conf_(pConf, "xcompmgr"); conf_.writeEntry("Compmode",useShadows->isChecked()?"CompClientShadows":""); conf_.writeEntry("DisableARGB",disableARGB->isChecked()); conf_.writeEntry("ShadowOffsetY",-1*shadowTopOffset->value()); conf_.writeEntry("ShadowOffsetX",-1*shadowLeftOffset->value()); int r, g, b; shadowColor->color().getRgb( &r, &g, &b ); QString hex; hex.sprintf("0x%02X%02X%02X", r,g,b); conf_.writeEntry("ShadowColor",hex); conf_.writeEntry("ShadowRadius",(activeWindowShadowSize->value() + inactiveWindowShadowSize->value()) / 2); conf_.writeEntry("FadeWindows",fadeInWindows->isChecked()); conf_.writeEntry("FadeTrans",fadeOnOpacityChange->isChecked()); conf_.writeEntry("FadeInStep",fadeInSpeed->value()/1000.0); conf_.writeEntry("FadeOutStep",fadeOutSpeed->value()/1000.0); delete pConf; if (standAlone) { config->sync(); - QDBusInterface kwin( "org.kde.kwin", "/KWin", "org.kde.KWin" ); - kwin.call( "reconfigure" ); + // Send signal to all kwin instances + QDBusMessage message = + QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig"); + QDBusConnection::sessionBus().send(message); + } emit KCModule::changed(false); } void KTranslucencyConfig::defaults() { if (!kompmgrAvailable_) return; useTranslucency->setChecked(false); onlyDecoTranslucent->setChecked(false); activeWindowTransparency->setChecked(false); inactiveWindowTransparency->setChecked(true); movingWindowTransparency->setChecked(false); dockWindowTransparency->setChecked(true); keepAboveAsActive->setChecked(true); disableARGB->setChecked(false); activeWindowOpacity->setValue(100); inactiveWindowOpacity->setValue(75); movingWindowOpacity->setValue(25); dockWindowOpacity->setValue(80); dockWindowShadowSize->setValue(6); activeWindowShadowSize->setValue(12); inactiveWindowShadowSize->setValue(6); shadowTopOffset->setValue(80); shadowLeftOffset->setValue(0); activeWindowOpacity->setEnabled(false); inactiveWindowOpacity->setEnabled(true); movingWindowOpacity->setEnabled(false); dockWindowOpacity->setEnabled(true); useShadows->setChecked(true); removeShadowsOnMove->setChecked(false); removeShadowsOnResize->setChecked(false); shadowColor->setColor(Qt::black); fadeInWindows->setChecked(true); fadeOnOpacityChange->setChecked(false); fadeInSpeed->setValue(70); fadeOutSpeed->setValue(20); emit KCModule::changed(true); } bool KTranslucencyConfig::kompmgrAvailable() { bool ret; - KProcess proc; + K3Process proc; proc << "kompmgr" << "-v"; - ret = proc.start(KProcess::DontCare, KProcess::AllOutput); + ret = proc.start(K3Process::DontCare, K3Process::AllOutput); proc.detach(); return ret; } void KTranslucencyConfig::showWarning(bool alphaActivated) { if (alphaActivated) KMessageBox::information(this, i18n("Translucency support is new and may cause problems
including crashes (sometimes the translucency engine, seldom even X).
"), i18n("Warning")); } #include "windows.moc" diff --git a/kcmkwin/kwinoptions/windows.h b/kcmkwin/kwinoptions/windows.h index b83dc39fc..910906269 100644 --- a/kcmkwin/kwinoptions/windows.h +++ b/kcmkwin/kwinoptions/windows.h @@ -1,289 +1,289 @@ /* * windows.h * * Copyright (c) 1997 Patrick Dowler dowler@morgul.fsh.uvic.ca * Copyright (c) 2001 Waldo Bastian bastian@kde.org * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KWINDOWCONFIG_H__ #define __KWINDOWCONFIG_H__ #include #include #include class QRadioButton; class QCheckBox; class QPushButton; class QComboBox; class QGroupBox; class QLabel; class QSlider; class Q3ButtonGroup; class QSpinBox; class Q3VButtonGroup; class KColorButton; class KIntNumInput; #define TRANSPARENT 0 #define OPAQUE 1 #define CLICK_TO_FOCUS 0 #define FOCUS_FOLLOW_MOUSE 1 #define TITLEBAR_PLAIN 0 #define TITLEBAR_SHADED 1 #define RESIZE_TRANSPARENT 0 #define RESIZE_OPAQUE 1 #define SMART_PLACEMENT 0 #define MAXIMIZING_PLACEMENT 1 #define CASCADE_PLACEMENT 2 #define RANDOM_PLACEMENT 3 #define CENTERED_PLACEMENT 4 #define ZEROCORNERED_PLACEMENT 5 #define INTERACTIVE_PLACEMENT 6 #define MANUAL_PLACEMENT 7 #define CLICK_TO_FOCUS 0 #define FOCUS_FOLLOWS_MOUSE 1 #define FOCUS_UNDER_MOUSE 2 #define FOCUS_STRICTLY_UNDER_MOUSE 3 class QSpinBox; class KFocusConfig : public KCModule { Q_OBJECT public: KFocusConfig( bool _standAlone, KConfig *_config, const KComponentData &inst, QWidget *parent ); ~KFocusConfig(); void load(); void save(); void defaults(); private slots: void setDelayFocusEnabled(); void setAutoRaiseEnabled(); void autoRaiseOnTog(bool);//CT 23Oct1998 void delayFocusOnTog(bool); void clickRaiseOnTog(bool); void updateAltTabMode(); void changed() { emit KCModule::changed(true); } private: int getFocus( void ); int getAutoRaiseInterval( void ); int getDelayFocusInterval( void ); void setFocus(int); void setAutoRaiseInterval(int); void setAutoRaise(bool); void setDelayFocusInterval(int); void setDelayFocus(bool); void setClickRaise(bool); void setAltTabMode(bool); void setTraverseAll(bool); void setRollOverDesktops(bool); void setShowPopupinfo(bool); Q3ButtonGroup *fcsBox; QComboBox *focusCombo; QCheckBox *autoRaiseOn; QCheckBox *delayFocusOn; QCheckBox *clickRaiseOn; KIntNumInput *autoRaise; KIntNumInput *delayFocus; Q3ButtonGroup *kbdBox; QCheckBox *altTabPopup; QCheckBox *traverseAll; QCheckBox *rollOverDesktops; QCheckBox *showPopupinfo; KConfig *config; bool standAlone; }; class KMovingConfig : public KCModule { Q_OBJECT public: KMovingConfig( bool _standAlone, KConfig *config, const KComponentData &inst, QWidget *parent ); ~KMovingConfig(); void load(); void save(); void defaults(); private slots: void setMinimizeAnim( bool ); void setMinimizeAnimSpeed( int ); void changed() { emit KCModule::changed(true); } void slotBrdrSnapChanged( int ); void slotWndwSnapChanged( int ); private: int getMove( void ); bool getMinimizeAnim( void ); int getMinimizeAnimSpeed( void ); int getResizeOpaque ( void ); bool getGeometryTip( void ); //KS int getPlacement( void ); //CT void setMove(int); void setResizeOpaque(int); void setGeometryTip(bool); //KS void setPlacement(int); //CT void setMoveResizeMaximized(bool); Q3ButtonGroup *windowsBox; QCheckBox *opaque; QCheckBox *resizeOpaqueOn; QCheckBox *geometryTipOn; QCheckBox* minimizeAnimOn; QSlider *minimizeAnimSlider; QLabel *minimizeAnimSlowLabel, *minimizeAnimFastLabel; QCheckBox *moveResizeMaximized; QComboBox *placementCombo; KConfig *config; bool standAlone; int getBorderSnapZone(); void setBorderSnapZone( int ); int getWindowSnapZone(); void setWindowSnapZone( int ); Q3VButtonGroup *MagicBox; KIntNumInput *BrdrSnap, *WndwSnap; QCheckBox *OverlapSnap; }; class KAdvancedConfig : public KCModule { Q_OBJECT public: KAdvancedConfig( bool _standAlone, KConfig *config, const KComponentData &inst, QWidget *parent ); ~KAdvancedConfig(); void load(); void save(); void defaults(); private slots: void shadeHoverChanged(bool); //copied from kcontrol/konq/kwindesktop, aleXXX void setEBorders(); void changed() { emit KCModule::changed(true); } private: int getShadeHoverInterval (void ); void setAnimateShade(bool); void setShadeHover(bool); void setShadeHoverInterval(int); QCheckBox *animateShade; Q3ButtonGroup *shBox; QCheckBox *shadeHoverOn; KIntNumInput *shadeHover; KConfig *config; bool standAlone; int getElectricBorders( void ); int getElectricBorderDelay(); void setElectricBorders( int ); void setElectricBorderDelay( int ); Q3VButtonGroup *electricBox; QRadioButton *active_disable; QRadioButton *active_move; QRadioButton *active_always; KIntNumInput *delays; void setFocusStealing( int ); void setHideUtilityWindowsForInactive( bool ); QComboBox* focusStealing; QCheckBox* hideUtilityWindowsForInactive; }; -class KProcess; +class K3Process; class KTranslucencyConfig : public KCModule { Q_OBJECT public: KTranslucencyConfig( bool _standAlone, KConfig *config, const KComponentData &inst, QWidget *parent); ~KTranslucencyConfig(); void load(); void save(); void defaults(); private: QCheckBox *useTranslucency; QCheckBox *activeWindowTransparency; QCheckBox *inactiveWindowTransparency; QCheckBox *movingWindowTransparency; QCheckBox *dockWindowTransparency; QCheckBox *keepAboveAsActive; QCheckBox *disableARGB; QCheckBox *fadeInWindows; QCheckBox *fadeOnOpacityChange; QCheckBox *useShadows; QCheckBox *removeShadowsOnResize; QCheckBox *removeShadowsOnMove; QGroupBox *sGroup; QCheckBox *onlyDecoTranslucent; // QPushButton *xcompmgrButton; KIntNumInput *activeWindowOpacity; KIntNumInput *inactiveWindowOpacity; KIntNumInput *movingWindowOpacity; KIntNumInput *dockWindowOpacity; KIntNumInput *dockWindowShadowSize; KIntNumInput *activeWindowShadowSize; KIntNumInput *inactiveWindowShadowSize; KIntNumInput *shadowTopOffset; KIntNumInput *shadowLeftOffset; KIntNumInput *fadeInSpeed; KIntNumInput *fadeOutSpeed; KColorButton *shadowColor; KConfig *config; bool standAlone; bool alphaActivated; bool resetKompmgr_; bool kompmgrAvailable(); bool kompmgrAvailable_; - KProcess *kompmgr; + K3Process *kompmgr; private slots: void resetKompmgr(); void showWarning(bool alphaActivated); }; #endif diff --git a/killer/killer.cpp b/killer/killer.cpp index 66182192c..4396006a7 100644 --- a/killer/killer.cpp +++ b/killer/killer.cpp @@ -1,89 +1,89 @@ /**************************************************************************** Copyright (C) 2003 Lubos Lunak Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include #include #include -#include +#include #include #include #include #include #include static const KCmdLineOptions options[] = { // no need for I18N_NOOP(), this is not supposed to be used directly { "pid ", "PID of the application to terminate.", 0 }, { "hostname ", "Hostname on which the application is running.", 0 }, { "windowname ", "Caption of the window to be terminated.", 0 }, { "applicationname ", "Name of the application to be terminated.", 0 }, { "wid ", "ID of resource belonging to the application.", 0 }, { "timestamp