--nextPart1316034.UoX46vosE0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8Bit Kevin Puetz wrote: > The attached patch provides at least the beginnings of real Xinerama > support for kicker placement. It allows the user to drag&drop the panel > along any edge of any monitor, saves/restores panel placement correctly, > and prevents panels from spanning across multiple screens. > > Just posting a rough-cut for comments (espescially any suggestions on how > to do a kcontrol UI for placing the panel). I haven't got any great ideas > here... maybe just a combobox to pick the screen number, but that seems > cryptic (and the useability team just did such a nice job with that > dialog). Showing multiple pickers (for each monitor) is another > possibility, but also not a great one since there could be a heck of a lot > of them. > > also, which Kicker classes have to stay BC? I hope not PanelContainer > (it's header is not shipped, so I went ahead and assumed not). > > Known bugs: > Category 1: panels along the edges of physical screens, but logically in > the middle > Kwin seems to mess up window placement with these around (it won't let you > drag windows past them). > Autohiding - autohidden panels in this position are basically impossible > to open, since the electric borders aren't there to trigger it. Since they > look stupid anyway (they slide oddly from one screen to the other, where > they show but are dead) I need to disable autohide for these positions. > > Switching - it doesn't correctly force taskbars assigned to screens > greated than the available number back onto an existing one. So > reconfiguration is bad until I fix that. > > It should work on non-Xinerama systems as well, though I haven't tested > that yet :-) > > If anybody with an unusual Xinerama setup would like to take a look, be my > guest. Any bug reports I haven't listed above are also welcome. Ok, second cut, all the above bugs are corrected except the lack of kcontrol configuration. If nobody has any great suggestions, I'm just going to add a combobox to pick the screen number a panel is on, because I think trying to represent all the possible locations for Xinerama placement is just too messy. Better to just drag&drop if you want to see what you're getting. I need to check this on non-Xinerama, and then I'm going to commit if I don't hear any objections. --nextPart1316034.UoX46vosE0 Content-Type: text/x-diff; name="kicker-xinerama.diff" Content-Transfer-Encoding: 8Bit Content-Disposition: attachment; filename="kicker-xinerama.diff" ? .snprj ? kicker.proj ? core/.container_panel.cpp.swp ? core/.container_panel.h.swp Index: core/container_panel.cpp =================================================================== RCS file: /home/kde/kdebase/kicker/core/container_panel.cpp,v retrieving revision 1.57 diff -u -p -r1.57 container_panel.cpp --- core/container_panel.cpp 2002/06/02 23:55:10 1.57 +++ core/container_panel.cpp 2002/06/06 22:23:42 @@ -78,11 +78,11 @@ PanelSettings::PanelSettings() _size = Normal; _customSize = 58; - // For now, we barely support xinerama. Let's just stick to the U-L head and that's it. + // Basic Xinerama support - position itself on the U-L head, along the bottom if (QApplication::desktop()->isVirtualDesktop()) { - int screen = QApplication::desktop()->screenNumber(QPoint(0,0)); - _sizePercentage = 100*QApplication::desktop()->screenGeometry(screen).width() / - QApplication::desktop()->width(); + _xineramaScreen = QApplication::desktop()->screenNumber(QPoint(0,0)); + } else { + _xineramaScreen = -1; } } @@ -92,6 +92,7 @@ void PanelSettings::readConfig( KConfig c->readNumEntry( "Position", _position)); _alignment = static_cast( c->readNumEntry( "Alignment", _alignment)); + _xineramaScreen = c->readNumEntry( "XineramaScreen", _xineramaScreen); _HBwidth = c->readNumEntry( "HideButtonSize", _HBwidth); _showLeftHB = c->readBoolEntry( "ShowLeftHideButton", _showLeftHB); _showRightHB = c->readBoolEntry( "ShowRightHideButton", _showRightHB); @@ -130,6 +131,7 @@ void PanelSettings::readConfig( KConfig void PanelSettings::writeConfig( KConfig *c ) { c->writeEntry( "Position", static_cast(_position)); c->writeEntry( "Alignment", static_cast(_alignment)); + c->writeEntry( "XineramaScreen", _xineramaScreen); c->writeEntry( "HideButtonSize", _HBwidth); c->writeEntry( "ShowLeftHideButton", _showLeftHB); c->writeEntry( "ShowRightHideButton", _showRightHB); @@ -171,8 +173,8 @@ PanelContainer::PanelContainer(QWidget * setLineWidth( 0 ); setMargin(0); - connect( UnhideTrigger::the(), SIGNAL(triggerUnhide(UnhideTrigger::Trigger)), - SLOT(unhideTriggered(UnhideTrigger::Trigger)) ); + connect( UnhideTrigger::the(), SIGNAL(triggerUnhide(UnhideTrigger::Trigger,int)), + SLOT(unhideTriggered(UnhideTrigger::Trigger,int)) ); _popupWidgetFilter = new PopupWidgetFilter( this ); connect( _popupWidgetFilter, SIGNAL(popupWidgetHiding()), SLOT(maybeStartAutoHideTimer()) ); @@ -252,9 +254,9 @@ void PanelContainer::writeConfig( KConfi _settings.writeConfig( config ); } -void PanelContainer::arrange( Position p, Alignment a ) +void PanelContainer::arrange( Position p, Alignment a, int XineramaScreen ) { - if ( p == _settings._position && a == _settings._alignment ) + if ( p == _settings._position && a == _settings._alignment && XineramaScreen == _settings._xineramaScreen) return; if ( p != _settings._position ) { @@ -267,6 +269,11 @@ void PanelContainer::arrange( Position p emit alignmentChange( a ); } + if( XineramaScreen != _settings._xineramaScreen ) { + _settings._xineramaScreen = XineramaScreen; + emit xineramaScreenChange( XineramaScreen ); + } + updateLayout(); writeConfig(); } @@ -334,7 +341,7 @@ void PanelContainer::hideRight() void PanelContainer::resetLayout() { - QRect g = initialGeometry( position(), alignment(), autoHidden(), userHidden() ); + QRect g = initialGeometry( position(), alignment(), xineramaScreen(), autoHidden(), userHidden() ); setGeometry( g ); @@ -448,7 +455,7 @@ void PanelContainer::blockUserInput( boo // are printed! WTF?! This happens if you drag an applet handle outside // the panel and wait for the timeout. I am completely mystified // by this. -void PanelContainer::unhideTriggered( UnhideTrigger::Trigger tr ) +void PanelContainer::unhideTriggered( UnhideTrigger::Trigger tr, int XineramaScreen ) { if( _settings._hideMode == PanelSettings::Manual ) return; @@ -468,6 +475,9 @@ void PanelContainer::unhideTriggered( Un if( !_autoHidden ) return; + if(XineramaScreen != _settings._xineramaScreen) + return; + int x = QCursor::pos().x(); int y = QCursor::pos().y(); int t = geometry().top(); @@ -648,9 +658,9 @@ bool PanelContainer::eventFilter( QObjec return false; } -QSize PanelContainer::initialSize( Position p ) +QSize PanelContainer::initialSize( Position p, int XineramaScreen ) { - QRect a = workArea(); + QRect a = workArea(XineramaScreen); // kdDebug(1210) << " Work Area: (" << a.topLeft().x() << ", " << a.topLeft().y() << ") to (" // << a.bottomRight().x() << ", " << a.bottomRight().y() << ")" << endl; @@ -678,9 +688,9 @@ QSize PanelContainer::initialSize( Posit return QSize( width, height ); } -QPoint PanelContainer::initialLocation( Position p, Alignment a, QSize s, bool autohidden, UserHidden userHidden ) +QPoint PanelContainer::initialLocation( Position p, Alignment a, int XineramaScreen, QSize s, bool autohidden, UserHidden userHidden ) { - QRect area = workArea(); + QRect area = workArea(XineramaScreen); int left; int top; @@ -784,16 +794,15 @@ QPoint PanelContainer::initialLocation( break; } } - return QPoint( left, top ); } -QRect PanelContainer::initialGeometry( Position p, Alignment a, bool autoHidden, UserHidden userHidden ) +QRect PanelContainer::initialGeometry( Position p, Alignment a, int XineramaScreen, bool autoHidden, UserHidden userHidden ) { // kdDebug(1210) << " Computing geometry for " << name() << endl; - QSize size = initialSize( p ); - QPoint point = initialLocation( p, a, size, autoHidden, userHidden ); + QSize size = initialSize( p, XineramaScreen ); + QPoint point = initialLocation( p, a, XineramaScreen, size, autoHidden, userHidden ); // kdDebug(1210) << " Size: " << size.width() << " x " << size.height() << endl; // kdDebug(1210) << " Pos: (" << point.x() << ", " << point.y() << ")" << endl; @@ -811,7 +820,7 @@ void PanelContainer::updateLayout() void PanelContainer::strutChanged() { // kdDebug(1210) << "PanelContainer::strutChanged()" << endl; - if ( initialGeometry( position(), alignment(), autoHidden(), userHidden() ) != geometry() ) { + if ( initialGeometry( position(), alignment(), xineramaScreen(), autoHidden(), userHidden() ) != geometry() ) { updateLayout(); } } @@ -825,18 +834,30 @@ void PanelContainer::updateWindowManager QRect r(QApplication::desktop()->geometry()); - QRect geom = initialGeometry( position(), alignment() ); + QRect geom = initialGeometry( position(), alignment(), xineramaScreen() ); if( userHidden() || _settings._hideMode != PanelSettings::Manual ) w = h = 0; // only call KWin::setStrut when the strut is really changed + + //FIXME do not set the strut if we are not actually along the edge of the virtual screen, since + //NETWM has no way to represent the resulting non-rectangular client areas that result in + //an Xinerama environment. Remove these checks once NetWM is smarter NETStrut strut; switch (position()) { - case ::Top: strut.top = geom.y() + h; break; - case ::Bottom: strut.bottom = (r.bottom() - geom.y() - height()) + h + 1; break; - case ::Right: strut.right = (r.right() - geom.x() - width()) + w + 1; break; - case ::Left: strut.left = geom.x() + w; break; + case ::Top: if(geom.top() == r.top()) + strut.top = geom.y() + h; + break; + case ::Bottom: if(geom.bottom() == r.bottom()) + strut.bottom = (r.bottom() - geom.bottom()) + h + 1; + break; + case ::Right: if(geom.right() == r.right()) + strut.right = (r.right() - geom.right()) + w + 1; + break; + case ::Left: if(geom.left() == r.left()) + strut.left = geom.x() + w; + break; } if ( strut.left != _strut.left || @@ -847,12 +868,7 @@ void PanelContainer::updateWindowManager _strut = strut; // kdDebug(1210) << "Panel sets new strut: " << position() << endl; // kdDebug(1210) << strut.top << " " << strut.bottom << " " << strut.right << " " << strut.left << endl; - switch (position()) { - case ::Top: KWin::setStrut( winId(), 0, 0, strut.top, 0 ); break; - case ::Bottom: KWin::setStrut( winId(), 0, 0, 0, strut.bottom); break; - case ::Right: KWin::setStrut( winId(), 0, strut.right, 0, 0 ); break; - case ::Left: KWin::setStrut( winId(), strut.left, 0, 0, 0 ); break; - } + KWin::setStrut( winId(), strut.left, strut.right, strut.top, strut.bottom ); } } @@ -893,14 +909,28 @@ void PanelContainer::animatedHide(bool l if( _userHidden != Unhidden ) newState = Unhidden; else if( left ) - newState = LeftTop; + newState = LeftTop; else newState = RightBottom; QPoint oldpos = pos(); - QPoint newpos = initialGeometry( position(), alignment(), false, newState ).topLeft(); + QRect newextent = initialGeometry( position(), alignment(), xineramaScreen(), false, newState ); + QPoint newpos(newextent.topLeft()); if( newState != Unhidden ) { + /* bail out if we are unable to hide */ + for(int s=0; s < QApplication::desktop()->numScreens(); s++) { + /* don't let it intersect with any screen in the hidden position + * that it doesn't intesect in the shown position. Should prevent + * panels from hiding by sliding onto other screens, while still + * letting them show reveal buttons onscreen */ + if(QApplication::desktop()->screenGeometry(s).intersects(newextent) + && !QApplication::desktop()->screenGeometry(s).intersects(geometry())) { + blockUserInput( false ); + return; + } + } + _userHidden = newState; // So we don't cover the mac-style menubar @@ -970,6 +1000,28 @@ void PanelContainer::autoHide(bool hide) // kdDebug(1210) << "entering autohide for real" << endl; + blockUserInput(true); + + QPoint oldpos = pos(); + QRect newextent = initialGeometry( position(), alignment(), xineramaScreen(), hide, Unhidden ); + QPoint newpos = newextent.topLeft(); + + if ( hide ) { + /* bail out if we are unable to hide */ + + for(int s=0; s < QApplication::desktop()->numScreens(); s++) { + /* don't let it intersect with any screen in the hidden position + * that it doesn't intesect in the shown position. Should prevent + * panels from hiding by sliding onto other screens, while still + * letting them show reveal buttons onscreen */ + if(QApplication::desktop()->screenGeometry(s).intersects(newextent) + && !QApplication::desktop()->screenGeometry(s).intersects(geometry())) { + blockUserInput( false ); + return; + } + } + + } _in_autohide = true; PanelButtonBase::setZoomEnabled(false); @@ -977,11 +1029,6 @@ void PanelContainer::autoHide(bool hide) _autoHidden = hide; UnhideTrigger::the()->setEnabled( _autoHidden ); - blockUserInput(true); - - QPoint oldpos = pos(); - QPoint newpos = initialGeometry( position(), alignment(), hide, Unhidden ).topLeft(); - if( hide ) { // So we don't cover other panels lower(); @@ -1048,18 +1095,19 @@ void PanelContainer::moveMe() Position positions[] = { ::Left, ::Right, ::Top, ::Bottom }; Alignment alignments[] = { ::LeftTop, ::Center, ::RightBottom }; - for( int i = 0; i < 4; i++ ) { - for( int j = 0; j < 3; j++ ) { - rects.append( initialGeometry( positions[i], alignments[j] ) ); + for(int s = 0; s < QApplication::desktop()->numScreens(); s++) { + for( int i = 0; i < 4; i++ ) { + for( int j = 0; j < 3; j++ ) { + rects.append( initialGeometry( positions[i], alignments[j], s ) ); + } } } int rect = UserRectSel::select(rects, position()); - Position p = (Position)(rect / 3); + int XineramaScreen = rect / 12; + Position p = (Position)((rect / 3) % 4); Alignment a = (Alignment)(rect % 3); - setPosition( p ); - setAlignment( a ); - updateLayout(); + arrange(p, a, XineramaScreen); _is_lmb_down = false; @@ -1070,7 +1118,7 @@ void PanelContainer::moveMe() maybeStartAutoHideTimer(); } -QRect PanelContainer::workArea() +QRect PanelContainer::workArea(int XineramaScreen) { QValueList list; @@ -1087,7 +1135,10 @@ QRect PanelContainer::workArea() list.append((*it)->winId()); } - return kWinModule->workArea(list); + if(XineramaScreen < 0 || XineramaScreen >= QApplication::desktop()->numScreens()) + /* force invalid screen locations onto the primary screen */ + XineramaScreen = 0 + return kWinModule->workArea(list).intersect(QApplication::desktop()->screenGeometry(XineramaScreen)); } PopupWidgetFilter::PopupWidgetFilter( QObject *parent ) Index: core/container_panel.h =================================================================== RCS file: /home/kde/kdebase/kicker/core/container_panel.h,v retrieving revision 1.26 diff -u -p -r1.26 container_panel.h --- core/container_panel.h 2002/06/02 23:55:10 1.26 +++ core/container_panel.h 2002/06/06 22:23:42 @@ -51,6 +51,7 @@ public: // Configuration settings Position _position; Alignment _alignment; + int _xineramaScreen; int _HBwidth; bool _showLeftHB; bool _showRightHB; @@ -76,17 +77,20 @@ public: virtual ~PanelContainer(); Position position() const { return _settings._position; } - void setPosition(Position p) { arrange( p, alignment() ); } + void setPosition(Position p) { arrange( p, alignment(), xineramaScreen() ); } + int xineramaScreen() const { return _settings._xineramaScreen; } + void setXineramaScreen(int screen) { arrange(position(),alignment(), screen); } + virtual void setSize(Size size, int customSize = 0); Size size() const; int customSize() const; Alignment alignment() const { return _settings._alignment; } - void setAlignment(Alignment a) { arrange( position(), a ); } + void setAlignment(Alignment a) { arrange( position(), a, xineramaScreen() ); } enum UserHidden{ Unhidden, LeftTop, RightBottom }; - QRect initialGeometry( Position p, Alignment a, bool autoHidden = false, UserHidden userHidden = Unhidden ); + QRect initialGeometry( Position p, Alignment a, int XineramaScreen, bool autoHidden = false, UserHidden userHidden = Unhidden ); virtual QSize sizeHint( Position p, QSize maxSize ); bool eventFilter( QObject *, QEvent * ); @@ -101,10 +105,11 @@ public: signals: void positionChange( Position pos ); void alignmentChange( Alignment a ); + void xineramaScreenChange ( int XineramaScreen ); void sizeChange( int size, int customSize ); protected: - void arrange( Position p, Alignment a ); + void arrange( Position p, Alignment a, int XineramaScreen ); void setMainWidget( QWidget* widget ); virtual PanelSettings defaultSettings(); bool autoHidden() const { return _autoHidden; }; @@ -112,7 +117,7 @@ protected: Orientation orientation() const; virtual void resetLayout(); virtual bool vetoAutoHide() { return false; } - QRect workArea(); + QRect workArea(int XineramaScreen); static KWinModule* kWinModule; @@ -123,7 +128,7 @@ protected slots: void enableZoomedIcons(); private slots: - void unhideTriggered( UnhideTrigger::Trigger t ); + void unhideTriggered( UnhideTrigger::Trigger t, int XineramaScreen ); void autoHideTimeout(); void hideLeft(); void hideRight(); @@ -137,8 +142,8 @@ private slots: void stopAutoHideTimer(); private: - QSize initialSize( Position p ); - QPoint initialLocation( Position p, Alignment a, QSize s, + QSize initialSize( Position p, int XineramaScreen ); + QPoint initialLocation( Position p, Alignment a, int XineramaScreen, QSize s, bool autohidden = false, UserHidden userHidden = Unhidden ); PanelSettings _settings; Index: core/containerarea.cpp =================================================================== RCS file: /home/kde/kdebase/kicker/core/containerarea.cpp,v retrieving revision 1.122 diff -u -p -r1.122 containerarea.cpp --- core/containerarea.cpp 2002/05/26 22:47:06 1.122 +++ core/containerarea.cpp 2002/06/06 22:23:43 @@ -114,7 +114,7 @@ void ContainerArea::defaultContainerConf containers.append( new KMenuButtonContainer( viewport() ) ); containers.append( new DesktopButtonContainer( viewport() ) ); - QRect r = panel->initialGeometry( panel->position(), panel->alignment() ); + QRect r = panel->initialGeometry( panel->position(), panel->alignment(), panel->xineramaScreen() ); int dsize; if (orientation() == Horizontal) Index: core/unhidetrigger.cpp =================================================================== RCS file: /home/kde/kdebase/kicker/core/unhidetrigger.cpp,v retrieving revision 1.1 diff -u -p -r1.1 unhidetrigger.cpp --- core/unhidetrigger.cpp 2002/02/27 13:31:49 1.1 +++ core/unhidetrigger.cpp 2002/06/06 22:23:43 @@ -36,6 +36,7 @@ UnhideTrigger* UnhideTrigger::the() UnhideTrigger::UnhideTrigger() : _lastTrigger( None ) + , _lastXineramaScreen( -1 ) , enabledCount( 0 ) { _timer = new QTimer( this ); @@ -64,37 +65,42 @@ bool UnhideTrigger::isEnabled() const void UnhideTrigger::pollMouse() { QPoint pos = QCursor::pos(); - QRect r = QApplication::desktop()->geometry(); - if( pos.x() == 0 ) { - if( pos.y() == 0 ) { - emitTrigger( TopLeft ); + for(int s = 0; s < QApplication::desktop()->numScreens(); s++) + { + QRect r = QApplication::desktop()->screenGeometry(s); + if( pos.x() == r.left() ) { + if( pos.y() == r.top() ) { + emitTrigger( TopLeft, s ); + } else if( pos.y() == r.bottom() ) { + emitTrigger( BottomLeft, s ); + } else { + emitTrigger( Left, s ); + } + } else if( pos.x() == r.right() ) { + if( pos.y() == r.top() ) { + emitTrigger( TopRight, s ); + } else if( pos.y() == r.bottom() ) { + emitTrigger( BottomRight ,s ); + } else { + emitTrigger( Right, s ); + } + } else if( pos.y() == r.top() ) { + emitTrigger( Top, s ); } else if( pos.y() == r.bottom() ) { - emitTrigger( BottomLeft ); + emitTrigger( Bottom, s ); } else { - emitTrigger( Left ); + _lastTrigger = None; + _lastXineramaScreen = -1; } - } else if( pos.x() == r.right() ) { - if( pos.y() == 0 ) { - emitTrigger( TopRight ); - } else if( pos.y() == r.bottom() ) { - emitTrigger( BottomRight ); - } else { - emitTrigger( Right ); - } - } else if( pos.y() == 0 ) { - emitTrigger( Top ); - } else if( pos.y() == r.bottom() ) { - emitTrigger( Bottom ); - } else { - _lastTrigger = None; } } -void UnhideTrigger::emitTrigger( Trigger t ) +void UnhideTrigger::emitTrigger( Trigger t, int XineramaScreen ) { - if( _lastTrigger == t ) + if( _lastTrigger == t && _lastXineramaScreen == XineramaScreen) return; _lastTrigger = t; - emit triggerUnhide( t ); + _lastXineramaScreen = XineramaScreen; + emit triggerUnhide( t, XineramaScreen ); } Index: core/unhidetrigger.h =================================================================== RCS file: /home/kde/kdebase/kicker/core/unhidetrigger.h,v retrieving revision 1.1 diff -u -p -r1.1 unhidetrigger.h --- core/unhidetrigger.h 2002/02/27 13:31:49 1.1 +++ core/unhidetrigger.h 2002/06/06 22:23:43 @@ -42,13 +42,14 @@ public: bool isEnabled() const; signals: - void triggerUnhide( UnhideTrigger::Trigger t ); + void triggerUnhide( UnhideTrigger::Trigger t, int XineramaScreen ); private slots: void pollMouse(); private: UnhideTrigger(); - void emitTrigger( Trigger t ); + void emitTrigger( Trigger t , int XineramaScreen); Trigger _lastTrigger; + int _lastXineramaScreen; QTimer *_timer; int enabledCount; }; Index: core/userrectsel.cpp =================================================================== RCS file: /home/kde/kdebase/kicker/core/userrectsel.cpp,v retrieving revision 1.2 diff -u -p -r1.2 userrectsel.cpp --- core/userrectsel.cpp 2002/03/16 06:11:32 1.2 +++ core/userrectsel.cpp 2002/06/06 22:23:43 @@ -66,8 +66,6 @@ void UserRectSel::mouseMoveEvent( QMouse QRect r( rectangles[i] ); int ndiff = (r.center().x() - e->globalPos().x() ) * (r.center().x() - e->globalPos().x() ) + (r.center().y() - e->globalPos().y() ) * (r.center().y() - e->globalPos().y() ); - if ( r.contains( e->globalPos() ) ) - ndiff = 0; if ( diff < 0 || ndiff < diff ) { diff = ndiff; nearest = i; --nextPart1316034.UoX46vosE0--