diff --git a/events.cpp b/events.cpp index 949fb0d377..a2a488880f 100644 --- a/events.cpp +++ b/events.cpp @@ -21,9 +21,6 @@ License. See the file "COPYING" for the exact licensing terms. #include "tabbox.h" #include "group.h" #include "rules.h" -#include "unmanaged.h" -#include "scene.h" -#include "effects.h" #include #include @@ -221,8 +218,6 @@ bool Workspace::workspaceEvent( XEvent * e ) tab_box->handleMouseEvent( e ); return true; } - if( effects && effects->checkInputWindowEvent( e )) - return true; break; case KeyPress: { @@ -267,11 +262,6 @@ bool Workspace::workspaceEvent( XEvent * e ) if( c->windowEvent( e )) return true; } - else if( Unmanaged* c = findUnmanaged( HandleMatchPredicate( e->xany.window ))) - { - if( c->windowEvent( e )) - return true; - } else { Window special = findSpecialEventWindow( e ); @@ -329,8 +319,13 @@ bool Workspace::workspaceEvent( XEvent * e ) } return true; } + return ( e->xunmap.event != e->xunmap.window ); // hide wm typical event from Qt } + case MapNotify: + + return ( e->xmap.event != e->xmap.window ); // hide wm typical event from Qt + case ReparentNotify: { //do not confuse Qt with these events. After all, _we_ are the @@ -380,19 +375,6 @@ bool Workspace::workspaceEvent( XEvent * e ) } break; } - case MapNotify: - { - if( e->xmap.override_redirect ) - { - Unmanaged* c = findUnmanaged( HandleMatchPredicate( e->xmap.window )); - if( c == NULL ) - c = createUnmanaged( e->xmap.window ); - if( c ) - return c->windowEvent( e ); - } - return ( e->xmap.event != e->xmap.window ); // hide wm typical event from Qt - } - case EnterNotify: { if ( QWhatsThis::inWhatsThisMode() ) @@ -469,29 +451,7 @@ bool Workspace::workspaceEvent( XEvent * e ) if( electricBorder( e )) return true; break; - case MappingNotify: - XRefreshKeyboardMapping( &e->xmapping ); - tab_box->updateKeyMapping(); - break; - case Expose: - if( e->xexpose.window == rootWindow() && compositing()) // root window needs repainting - addDamage( e->xexpose.x, e->xexpose.y, e->xexpose.width, e->xexpose.height ); - break; default: - if( e->type == Extensions::randrNotifyEvent() && Extensions::randrAvailable() ) - { -#ifdef HAVE_XRANDR - XRRUpdateConfiguration( e ); -#endif - if( compositing() ) - { - // desktopResized() should take care of when the size or - // shape of the desktop has changed, but we also want to - // catch refresh rate changes - finishCompositing(); - QTimer::singleShot( 0, this, SLOT( setupCompositing() ) ); - } - } break; } return false; @@ -587,19 +547,6 @@ bool Client::windowEvent( XEvent* e ) if( demandAttentionKNotifyTimer != NULL ) demandAttentionKNotify(); } - if( dirty[ WinInfo::PROTOCOLS2 ] & NET::WM2Opacity ) - { - if( compositing()) - { - addDamageFull(); - scene->windowOpacityChanged( this ); - } - else - { // forward to the frame if there's possibly another compositing manager running - NETWinInfo i( display(), frameId(), rootWindow(), 0 ); - i.setOpacity( info->opacity()); - } - } } // TODO move all focus handling stuff to separate file? @@ -680,23 +627,15 @@ bool Client::windowEvent( XEvent* e ) workspace()->updateColormap(); } break; - case VisibilityNotify: - visibilityNotifyEvent( &e->xvisibility ); - break; default: if( e->xany.window == window()) + { + if( e->type == Shape::shapeEvent() ) { - if( e->type == Extensions::shapeNotifyEvent() ) - { - detectShape( window()); // workaround for #19644 - updateShape(); - } - } - if( e->xany.window == frameId()) - { - if( e->type == Extensions::damageNotifyEvent()) - damageNotifyEvent( reinterpret_cast< XDamageNotifyEvent* >( e )); + is_shape = Shape::hasShape( window()); // workaround for #19644 + updateShape(); } + } break; } return true; // eat all events @@ -1065,18 +1004,13 @@ void Client::ungrabButton( int modifier ) */ void Client::updateMouseGrab() { - if( workspace()->globalShortcutsDisabled()) - { - XUngrabButton( display(), AnyButton, AnyModifier, wrapperId()); - // keep grab for the simple click without modifiers if needed - if( !( !options->clickRaise || not_obscured )) - grabButton( None ); - return; - } if( isActive() && !workspace()->forcedGlobalMouseGrab()) // see Workspace::establishTabBoxGrab() { // remove the grab for no modifiers only if the window // is unobscured or if the user doesn't want click raise + // (it is unobscured if it the topmost in the unconstrained stacking order, i.e. it is + // the most recently raised window) + bool not_obscured = workspace()->topClientOnDesktop( workspace()->currentDesktop(), true, false ) == this; if( !options->clickRaise || not_obscured ) ungrabButton( None ); else @@ -1096,6 +1030,37 @@ void Client::updateMouseGrab() } } +int qtToX11Button( Qt::ButtonState button ) + { + if( button == Qt::LeftButton ) + return Button1; + else if( button == Qt::MidButton ) + return Button2; + else if( button == Qt::RightButton ) + return Button3; + return AnyButton; + } + +int qtToX11State( Qt::ButtonState buttons, Qt::KeyboardModifiers modifiers ) + { + int ret = 0; + if( buttons & Qt::LeftButton ) + ret |= Button1Mask; + if( buttons & Qt::MidButton ) + ret |= Button2Mask; + if( buttons & Qt::RightButton ) + ret |= Button3Mask; + if( modifiers & Qt::ShiftModifier ) + ret |= ShiftMask; + if( modifiers & Qt::ControlModifier ) + ret |= ControlMask; + if( modifiers & Qt::AltModifier ) + ret |= KKeyServer::modXAlt(); + if( modifiers & Qt::MetaModifier ) + ret |= KKeyServer::modXMeta(); + return ret; + } + // Qt propagates mouse events up the widget hierachy, which means events // for the decoration window cannot be (easily) intercepted as X11 events bool Client::eventFilter( QObject* o, QEvent* e ) @@ -1480,17 +1445,6 @@ void Client::focusOutEvent( XFocusOutEvent* e ) setActive( false ); } -void Client::visibilityNotifyEvent( XVisibilityEvent * e) - { - if( e->window != frameId()) - return; // care only about the whole frame - bool new_not_obscured = e->state == VisibilityUnobscured; - if( not_obscured == new_not_obscured ) - return; - not_obscured = new_not_obscured; - updateMouseGrab(); - } - // performs _NET_WM_MOVERESIZE void Client::NETMoveResize( int x_root, int y_root, NET::Direction direction ) { @@ -1552,7 +1506,7 @@ void Client::keyPressEvent( uint key_code ) bool is_alt = key_code & Qt::ALT; key_code = key_code & 0xffff; int delta = is_control?1:is_alt?32:8; - QPoint pos = cursorPos(); + QPoint pos = QCursor::pos(); switch ( key_code ) { case Qt::Key_Left: @@ -1585,72 +1539,6 @@ void Client::keyPressEvent( uint key_code ) QCursor::setPos( pos ); } -// **************************************** -// Unmanaged -// **************************************** - -bool Unmanaged::windowEvent( XEvent* e ) - { - unsigned long dirty[ 2 ]; - info->event( e, dirty, 2 ); // pass through the NET stuff - if( dirty[ NETWinInfo::PROTOCOLS2 ] & NET::WM2Opacity ) - { - scene->windowOpacityChanged( this ); - addDamageFull(); - } - switch (e->type) - { - case UnmapNotify: - unmapNotifyEvent( &e->xunmap ); - break; - case MapNotify: - mapNotifyEvent( &e->xmap ); - break; - case ConfigureNotify: - configureNotifyEvent( &e->xconfigure ); - break; - default: - { - if( e->type == Extensions::shapeNotifyEvent() ) - { - detectShape( handle()); - addDamageFull(); - if( compositing() ) - discardWindowPixmap(); - if( scene != NULL ) - scene->windowGeometryShapeChanged( this ); - } - if( e->type == Extensions::damageNotifyEvent()) - damageNotifyEvent( reinterpret_cast< XDamageNotifyEvent* >( e )); - break; - } - } - return false; // don't eat events, even our own unmanaged widgets are tracked - } - -void Unmanaged::mapNotifyEvent( XMapEvent* ) - { - } - -void Unmanaged::unmapNotifyEvent( XUnmapEvent* ) - { - release(); - } - -void Unmanaged::configureNotifyEvent( XConfigureEvent* e ) - { - if( effects ) - effects->checkInputWindowStacking(); // keep them on top - QRect newgeom( e->x, e->y, e->width, e->height ); - if( newgeom == geom ) - return; - geom = newgeom; - // TODO add damage only if the window is not obscured - workspace()->addDamage( geometry()); - // TODO maybe only damage changed area - addDamageFull(); - } - // **************************************** // Group // **************************************** diff --git a/tabbox.cpp b/tabbox.cpp index 355dafeb5f..dde4c31557 100644 --- a/tabbox.cpp +++ b/tabbox.cpp @@ -43,7 +43,7 @@ namespace KWinInternal extern QPixmap* kwin_get_menu_pix_hack(); TabBox::TabBox( Workspace *ws, const char *name ) - : Q3Frame( 0, name, Qt::WNoAutoErase ), client(0), wspace(ws) + : Q3Frame( 0, name, Qt::WNoAutoErase ), current_client( NULL ), wspace(ws) { setFrameStyle(QFrame::StyledPanel | QFrame::Plain); setLineWidth(2); @@ -53,14 +53,28 @@ TabBox::TabBox( Workspace *ws, const char *name ) no_tasks = i18n("*** No Windows ***"); m = DesktopMode; // init variables - updateKeyMapping(); reconfigure(); reset(); connect(&delayedShowTimer, SIGNAL(timeout()), this, SLOT(show())); + + XSetWindowAttributes attr; + attr.override_redirect = 1; + outline_left = XCreateWindow( display(), rootWindow(), 0, 0, 1, 1, 0, + CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr ); + outline_right = XCreateWindow( display(), rootWindow(), 0, 0, 1, 1, 0, + CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr ); + outline_top = XCreateWindow( display(), rootWindow(), 0, 0, 1, 1, 0, + CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr ); + outline_bottom = XCreateWindow( display(), rootWindow(), 0, 0, 1, 1, 0, + CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr ); } TabBox::~TabBox() { + XDestroyWindow( display(), outline_left ); + XDestroyWindow( display(), outline_right ); + XDestroyWindow( display(), outline_top ); + XDestroyWindow( display(), outline_bottom ); } @@ -111,7 +125,9 @@ void TabBox::createClientList(ClientList &list, int desktop /*-1 = all*/, Client else if( !list.contains( modal )) list += modal; else - ; // nothing + { + // nothing + } } } @@ -139,7 +155,7 @@ void TabBox::reset() { int w, h, cw = 0, wmax = 0; - QRect r = KGlobalSettings::desktopGeometry(cursorPos()); + QRect r = KGlobalSettings::desktopGeometry(QCursor::pos()); // calculate height of 1 line // fontheight + 1 pixel above + 1 pixel below, or 32x32 icon + 2 pixel above + below @@ -147,10 +163,10 @@ void TabBox::reset() if ( mode() == WindowsMode ) { - client = workspace()->activeClient(); + setCurrentClient( workspace()->activeClient()); // get all clients to show - createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), client, true); + createClientList(clients, options_traverse_all ? -1 : workspace()->currentDesktop(), current_client, true); // calculate maximum caption width cw = fontMetrics().width(no_tasks)+20; @@ -227,7 +243,8 @@ void TabBox::nextPrev( bool next) { if ( mode() == WindowsMode ) { - Client* firstClient = 0; + Client* firstClient = NULL; + Client* client = current_client; do { if ( next ) @@ -247,6 +264,7 @@ void TabBox::nextPrev( bool next) break; } } while ( client && !clients.contains( client )); + setCurrentClient( client ); } else if( mode() == DesktopMode ) { @@ -284,9 +302,18 @@ Client* TabBox::currentClient() { if ( mode() != WindowsMode ) return 0; - if (!workspace()->hasClient( client )) + if (!workspace()->hasClient( current_client )) return 0; - return client; + return current_client; + } + +void TabBox::setCurrentClient( Client* c ) + { + if( current_client != c ) + { + current_client = c; + updateOutline(); + } } /*! @@ -308,6 +335,11 @@ int TabBox::currentDesktop() */ void TabBox::showEvent( QShowEvent* ) { + updateOutline(); + XRaiseWindow( display(), outline_left ); + XRaiseWindow( display(), outline_right ); + XRaiseWindow( display(), outline_top ); + XRaiseWindow( display(), outline_bottom ); raise(); } @@ -317,6 +349,10 @@ void TabBox::showEvent( QShowEvent* ) */ void TabBox::hideEvent( QHideEvent* ) { + XUnmapWindow( display(), outline_left ); + XUnmapWindow( display(), outline_right ); + XUnmapWindow( display(), outline_top ); + XUnmapWindow( display(), outline_bottom ); } /*! @@ -355,7 +391,7 @@ void TabBox::drawContents( QPainter * ) if ( workspace()->hasClient( *it ) ) // safety { // draw highlight background - if ( (*it) == currentClient() ) + if ( (*it) == current_client ) p.fillRect(x, y, r.width(), lineHeight, palette().brush( QPalette::Highlight )); // draw icon @@ -389,10 +425,10 @@ void TabBox::drawContents( QPainter * ) else s += (*it)->caption(); - s = KStringHandler::cPixelSqueeze(s, fontMetrics(), r.width() - 5 - iconWidth - 8); + s = fontMetrics().elidedText(s, Qt::ElideMiddle, r.width() - 5 - iconWidth - 8); // draw text - if ( (*it) == currentClient() ) + if ( (*it) == current_client ) p.setPen(palette().color( QPalette::HighlightedText )); else if( (*it)->isMinimized()) { @@ -510,6 +546,91 @@ void TabBox::drawContents( QPainter * ) localPainter.drawImage( QPoint( r.x(), r.y() ), pix.toImage() ); } +void TabBox::updateOutline() + { + Client* c = currentClient(); + if( c == NULL || this->isHidden() || !c->isShown( true ) || !c->isOnCurrentDesktop()) + { + XUnmapWindow( display(), outline_left ); + XUnmapWindow( display(), outline_right ); + XUnmapWindow( display(), outline_top ); + XUnmapWindow( display(), outline_bottom ); + return; + } + // left/right parts are between top/bottom, they don't reach as far as the corners + XMoveResizeWindow( display(), outline_left, c->x(), c->y() + 5, 5, c->height() - 10 ); + XMoveResizeWindow( display(), outline_right, c->x() + c->width() - 5, c->y() + 5, 5, c->height() - 10 ); + XMoveResizeWindow( display(), outline_top, c->x(), c->y(), c->width(), 5 ); + XMoveResizeWindow( display(), outline_bottom, c->x(), c->y() + c->height() - 5, c->width(), 5 ); + { + QPixmap pix( 5, c->height() - 10 ); + QPainter p( &pix ); + p.setPen( Qt::white ); + p.drawLine( 0, 0, 0, pix.height() - 1 ); + p.drawLine( 4, 0, 4, pix.height() - 1 ); + p.setPen( Qt::gray ); + p.drawLine( 1, 0, 1, pix.height() - 1 ); + p.drawLine( 3, 0, 3, pix.height() - 1 ); + p.setPen( Qt::black ); + p.drawLine( 2, 0, 2, pix.height() - 1 ); + p.end(); + XSetWindowBackgroundPixmap( display(), outline_left, pix.handle()); + XSetWindowBackgroundPixmap( display(), outline_right, pix.handle()); + } + { + QPixmap pix( c->width(), 5 ); + QPainter p( &pix ); + p.setPen( Qt::white ); + p.drawLine( 0, 0, pix.width() - 1 - 0, 0 ); + p.drawLine( 4, 4, pix.width() - 1 - 4, 4 ); + p.drawLine( 0, 0, 0, 4 ); + p.drawLine( pix.width() - 1 - 0, 0, pix.width() - 1 - 0, 4 ); + p.setPen( Qt::gray ); + p.drawLine( 1, 1, pix.width() - 1 - 1, 1 ); + p.drawLine( 3, 3, pix.width() - 1 - 3, 3 ); + p.drawLine( 1, 1, 1, 4 ); + p.drawLine( 3, 3, 3, 4 ); + p.drawLine( pix.width() - 1 - 1, 1, pix.width() - 1 - 1, 4 ); + p.drawLine( pix.width() - 1 - 3, 3, pix.width() - 1 - 3, 4 ); + p.setPen( Qt::black ); + p.drawLine( 2, 2, pix.width() - 1 - 2, 2 ); + p.drawLine( 2, 2, 2, 4 ); + p.drawLine( pix.width() - 1 - 2, 2, pix.width() - 1 - 2, 4 ); + p.end(); + XSetWindowBackgroundPixmap( display(), outline_top, pix.handle()); + } + { + QPixmap pix( c->width(), 5 ); + QPainter p( &pix ); + p.setPen( Qt::white ); + p.drawLine( 4, 0, pix.width() - 1 - 4, 0 ); + p.drawLine( 0, 4, pix.width() - 1 - 0, 4 ); + p.drawLine( 0, 4, 0, 0 ); + p.drawLine( pix.width() - 1 - 0, 4, pix.width() - 1 - 0, 0 ); + p.setPen( Qt::gray ); + p.drawLine( 3, 1, pix.width() - 1 - 3, 1 ); + p.drawLine( 1, 3, pix.width() - 1 - 1, 3 ); + p.drawLine( 3, 1, 3, 0 ); + p.drawLine( 1, 3, 1, 0 ); + p.drawLine( pix.width() - 1 - 3, 1, pix.width() - 1 - 3, 0 ); + p.drawLine( pix.width() - 1 - 1, 3, pix.width() - 1 - 1, 0 ); + p.setPen( Qt::black ); + p.drawLine( 2, 2, pix.width() - 1 - 2, 2 ); + p.drawLine( 2, 0, 2, 2 ); + p.drawLine( pix.width() - 1 - 2, 0, pix.width() - 1 - 2 , 2 ); + p.end(); + XSetWindowBackgroundPixmap( display(), outline_bottom, pix.handle()); + } + XClearWindow( display(), outline_left ); + XClearWindow( display(), outline_right ); + XClearWindow( display(), outline_top ); + XClearWindow( display(), outline_bottom ); + XMapWindow( display(), outline_left ); + XMapWindow( display(), outline_right ); + XMapWindow( display(), outline_top ); + XMapWindow( display(), outline_bottom ); + } + void TabBox::hide() { delayedShowTimer.stop(); @@ -587,7 +708,7 @@ void TabBox::handleMouseEvent( XEvent* e ) { if( workspace()->hasClient( *it ) && (num == 0) ) // safety { - client = *it; + setCurrentClient( *it ); break; } num--; @@ -667,10 +788,6 @@ bool areKeySymXsDepressed( bool bAll, const uint keySyms[], int nKeySyms ) return bAll; } -static const int MAX_KEYSYMS = 4; -static uint alt_keysyms[ MAX_KEYSYMS ]; -static uint win_keysyms[ MAX_KEYSYMS ]; - static bool areModKeysDepressed( const QKeySequence& seq ) { uint rgKeySyms[10]; @@ -691,17 +808,18 @@ static bool areModKeysDepressed( const QKeySequence& seq ) } if( mod & Qt::ALT ) { - for( int i = 0; - i < MAX_KEYSYMS && alt_keysyms[ i ] != NoSymbol; - ++i ) - rgKeySyms[nKeySyms++] = alt_keysyms[ i ]; + rgKeySyms[nKeySyms++] = XK_Alt_L; + rgKeySyms[nKeySyms++] = XK_Alt_R; } if( mod & Qt::META ) { - for( int i = 0; - i < MAX_KEYSYMS && win_keysyms[ i ] != NoSymbol; - ++i ) - rgKeySyms[nKeySyms++] = win_keysyms[ i ]; + // It would take some code to determine whether the Win key + // is associated with Super or Meta, so check for both. + // See bug #140023 for details. + rgKeySyms[nKeySyms++] = XK_Super_L; + rgKeySyms[nKeySyms++] = XK_Super_R; + rgKeySyms[nKeySyms++] = XK_Meta_L; + rgKeySyms[nKeySyms++] = XK_Meta_R; } return areKeySymXsDepressed( false, rgKeySyms, nKeySyms ); @@ -715,44 +833,6 @@ static bool areModKeysDepressed( const KShortcut& cut ) return false; } -void TabBox::updateKeyMapping() - { - const int size = 6; - uint keysyms[ size ] = { XK_Alt_L, XK_Alt_R, XK_Super_L, XK_Super_R, XK_Meta_L, XK_Meta_R }; - XModifierKeymap* map = XGetModifierMapping( display() ); - int altpos = 0; - int winpos = 0; - int winmodpos = -1; - int winmod = KKeyServer::modXMeta(); - while( winmod > 0 ) // get position of the set bit in winmod - { - winmod >>= 1; - ++winmodpos; - } - for( int i = 0; - i < MAX_KEYSYMS; - ++i ) - alt_keysyms[ i ] = win_keysyms[ i ] = NoSymbol; - for( int i = 0; - i < size; - ++i ) - { - KeyCode keycode = XKeysymToKeycode( display(), keysyms[ i ] ); - for( int j = 0; - j < map->max_keypermod; - ++j ) - { - if( map->modifiermap[ 3 * map->max_keypermod + j ] == keycode ) // Alt - if( altpos < MAX_KEYSYMS ) - alt_keysyms[ altpos++ ] = keysyms[ i ]; - if( winmodpos >= 0 && map->modifiermap[ winmodpos * map->max_keypermod + j ] == keycode ) - if( winpos < MAX_KEYSYMS ) - win_keysyms[ winpos++ ] = keysyms[ i ]; - } - } - XFreeModifiermap( map ); - } - void Workspace::slotWalkThroughWindows() { if ( root != rootWindow() ) diff --git a/tabbox.h b/tabbox.h index 651067366b..36fe7fda94 100644 --- a/tabbox.h +++ b/tabbox.h @@ -53,7 +53,6 @@ class TabBox : public Q3Frame Workspace* workspace() const; void reconfigure(); - void updateKeyMapping(); protected: void showEvent( QShowEvent* );