diff options
Diffstat (limited to 'kicker/kicker/core/container_extension.cpp')
-rw-r--r-- | kicker/kicker/core/container_extension.cpp | 2067 |
1 files changed, 2067 insertions, 0 deletions
diff --git a/kicker/kicker/core/container_extension.cpp b/kicker/kicker/core/container_extension.cpp new file mode 100644 index 000000000..694513109 --- /dev/null +++ b/kicker/kicker/core/container_extension.cpp @@ -0,0 +1,2067 @@ +/***************************************************************** + +Copyright (c) 2004-2005 Aaron J. Seigo <aseigo@kde.org> +Copyright (c) 2000-2001 the kicker authors. See file AUTHORS. + +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 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 <stdlib.h> +#include <math.h> + +#include <qcursor.h> +#include <qfile.h> +#include <qlayout.h> +#include <qmovie.h> +#include <qpainter.h> +#include <qtimer.h> +#include <qtooltip.h> +#include <qvbox.h> +#include <qxembed.h> +#include <qcolor.h> + +#include <dcopclient.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kdesktopfile.h> +#include <kglobal.h> +#include <kicker.h> +#include <kstandarddirs.h> +#include <kwin.h> +#include <klocale.h> +#include <kglobalsettings.h> +#include <kapplication.h> +#include <netwm.h> +#include <fixx11h.h> +#include <kwinmodule.h> + +#include "container_base.h" +#include "extensionmanager.h" +#include "extensionop_mnu.h" +#include "hidebutton.h" +#include "kicker.h" +#include "kickerSettings.h" +#include "kickertip.h" +#include "pluginmanager.h" +#include "userrectsel.h" + +#include "container_extension.h" + +/* 1 is the initial speed, hide_show_animation is the top speed. */ +#define PANEL_SPEED(x, c) (int)((1.0-2.0*fabs((x)-(c)/2.0)/c)*m_settings.hideAnimationSpeed()+1.0) + +ExtensionContainer::ExtensionContainer(const AppletInfo& info, + const QString& extensionId, + QWidget *parent) + : QFrame(parent, ("ExtensionContainer#" + extensionId).latin1(), WStyle_Customize | WStyle_NoBorder), + m_settings(KSharedConfig::openConfig(info.configFile())), + m_hideMode(ManualHide), + m_unhideTriggeredAt(UnhideTrigger::None), + _autoHidden(false), + _userHidden(Unhidden), + _block_user_input(false), + _is_lmb_down(false), + _in_autohide(false), + _id(extensionId), + _opMnu(0), + _info(info), + _ltHB(0), + _rbHB(0), + m_extension(0), + m_maintainFocus(0), + m_panelOrder(ExtensionManager::the()->nextPanelOrder()) +{ + // now actually try to load the extension + m_extension = PluginManager::the()->loadExtension(info, this); + init(); +} + +ExtensionContainer::ExtensionContainer(KPanelExtension* extension, + const AppletInfo& info, + const QString& extensionId, + QWidget *parent) + : QFrame(parent, ("ExtensionContainer#" + extensionId).latin1(), WStyle_Customize | WStyle_NoBorder), + m_settings(KSharedConfig::openConfig(info.configFile())), + _autoHidden(false), + _userHidden(Unhidden), + _block_user_input(false), + _is_lmb_down(false), + _in_autohide(false), + _id(extensionId), + _opMnu(0), + _info(info), + _ltHB(0), + _rbHB(0), + m_extension(extension), + m_maintainFocus(0), + m_panelOrder(ExtensionManager::the()->nextPanelOrder()) +{ + m_extension->reparent(this, QPoint(0, 0)); + init(); +} + +void ExtensionContainer::init() +{ + // panels live in the dock + KWin::setType(winId(), NET::Dock); + KWin::setState(winId(), NET::Sticky); + KWin::setOnAllDesktops(winId(), true); + + connect(Kicker::the()->kwinModule(), SIGNAL(strutChanged()), this, SLOT(strutChanged())); + connect(Kicker::the()->kwinModule(), SIGNAL(currentDesktopChanged(int)), + this, SLOT( currentDesktopChanged(int))); + + setBackgroundOrigin(AncestorOrigin); + setFrameStyle(NoFrame); + setLineWidth(0); + setMargin(0); + + connect(UnhideTrigger::the(), SIGNAL(triggerUnhide(UnhideTrigger::Trigger,int)), + this, SLOT(unhideTriggered(UnhideTrigger::Trigger,int))); + + _popupWidgetFilter = new PopupWidgetFilter( this ); + connect(_popupWidgetFilter, SIGNAL(popupWidgetHiding()), SLOT(maybeStartAutoHideTimer())); + + // layout + _layout = new QGridLayout(this, 3, 3, 0, 0); + _layout->setResizeMode(QLayout::FreeResize); + _layout->setRowStretch(1,10); + _layout->setColStretch(1,10); + + // instantiate the autohide timer + _autohideTimer = new QTimer(this, "_autohideTimer"); + connect(_autohideTimer, SIGNAL(timeout()), SLOT(autoHideTimeout())); + + // instantiate the updateLayout event compressor timer + _updateLayoutTimer = new QTimer(this, "_updateLayoutTimer"); + connect(_updateLayoutTimer, SIGNAL(timeout()), SLOT(actuallyUpdateLayout())); + + installEventFilter(this); // for mouse event handling + + connect(Kicker::the(), SIGNAL(kdisplayPaletteChanged()), this, SLOT(updateHighlightColor())); + updateHighlightColor(); + + // if we were hidden when kicker quit, let's start out hidden as well! + KConfig *config = KGlobal::config(); + config->setGroup(extensionId()); + int tmp = config->readNumEntry("UserHidden", Unhidden); + if (tmp > Unhidden && tmp <= RightBottom) + { + _userHidden = static_cast<UserHidden>(tmp); + } + + if (m_extension) + { + // if we have an extension, we need to grab the extension-specific + // defaults for position, size and custom size and override the + // defaults in the settings object since the extension may differ + // from the "normal" panels. for example, the universal sidebar's + // preferred position is the left, not the bottom/top + KConfigSkeleton::ItemInt* item = dynamic_cast<KConfigSkeleton::ItemInt*>(m_settings.findItem("Position")); + if (item) + { + KPanelExtension::Position p = m_extension->preferedPosition(); + item->setDefaultValue(p); + item->readConfig(m_settings.config()); + } + + item = dynamic_cast<KConfigSkeleton::ItemInt*>(m_settings.findItem("Size")); + if (item) + { + item->setDefaultValue(m_extension->sizeSetting()); + } + + item = dynamic_cast<KConfigSkeleton::ItemInt*>(m_settings.findItem("CustomSize")); + if (item) + { + item->setDefaultValue(m_extension->customSize()); + } + + connect(m_extension, SIGNAL(updateLayout()), SLOT(updateLayout())); + connect(m_extension, SIGNAL(maintainFocus(bool)), + SLOT(maintainFocus(bool))); + + _layout->addWidget(m_extension, 1, 1); + } + + if (!m_settings.iExist()) + { + m_settings.setIExist(true); + m_settings.writeConfig(); + } +} + +ExtensionContainer::~ExtensionContainer() +{ +} + +QSize ExtensionContainer::sizeHint(KPanelExtension::Position p, const QSize &maxSize) const +{ + int width = 0; + int height = 0; + if (p == KPanelExtension::Top || p == KPanelExtension::Bottom) + { + if (needsBorder()) + { + height += 1; // border + } + + if (m_settings.showLeftHideButton()) + { + width += m_settings.hideButtonSize(); + } + + if (m_settings.showRightHideButton()) + { + width += m_settings.hideButtonSize(); + } + + // don't forget we might have a border! + width += _layout->colSpacing(0) + _layout->colSpacing(2); + } + else + { + if (needsBorder()) + { + width += 1; // border + } + + if (m_settings.showLeftHideButton()) + { + height += m_settings.hideButtonSize(); + } + + if (m_settings.showRightHideButton()) + { + height += m_settings.hideButtonSize(); + } + + // don't forget we might have a border! + height += _layout->rowSpacing(0) + _layout->rowSpacing(2); + } + + QSize size(width, height); + size = size.boundedTo(maxSize); + + if (m_extension) + { + size = m_extension->sizeHint(p, maxSize - size) + size; + } + + return size.boundedTo(maxSize); +} + +static bool isnetwm12_below() +{ + NETRootInfo info( qt_xdisplay(), NET::Supported ); + return info.supportedProperties()[ NETRootInfo::STATES ] & NET::KeepBelow; +} + +void ExtensionContainer::readConfig() +{ +// kdDebug(1210) << "ExtensionContainer::readConfig()" << endl; + m_settings.readConfig(); + + if (m_settings.autoHidePanel()) + { + m_hideMode = AutomaticHide; + } + else if (m_settings.backgroundHide()) + { + m_hideMode = BackgroundHide; + } + else + { + m_hideMode = ManualHide; + } + + positionChange(position()); + alignmentChange(alignment()); + setSize(static_cast<KPanelExtension::Size>(m_settings.size()), + m_settings.customSize()); + + if (m_hideMode != AutomaticHide) + { + autoHide(false); + } + + static bool netwm12 = isnetwm12_below(); + if (netwm12) // new netwm1.2 compliant way + { + if (m_hideMode == BackgroundHide) + { + KWin::setState( winId(), NET::KeepBelow ); + UnhideTrigger::the()->setEnabled( true ); + } + else + { + KWin::clearState( winId(), NET::KeepBelow ); + } + } + else if (m_hideMode == BackgroundHide) + { + // old way + KWin::clearState( winId(), NET::StaysOnTop ); + UnhideTrigger::the()->setEnabled( true ); + } + else + { + // the other old way + KWin::setState( winId(), NET::StaysOnTop ); + } + + actuallyUpdateLayout(); + maybeStartAutoHideTimer(); +} + +void ExtensionContainer::writeConfig() +{ +// kdDebug(1210) << "ExtensionContainer::writeConfig()" << endl; + KConfig *config = KGlobal::config(); + config->setGroup(extensionId()); + + config->writePathEntry("ConfigFile", _info.configFile()); + config->writePathEntry("DesktopFile", _info.desktopFile()); + config->writeEntry("UserHidden", userHidden()); + + m_settings.writeConfig(); +} + +void ExtensionContainer::showPanelMenu( const QPoint& globalPos ) +{ + if (!kapp->authorizeKAction("kicker_rmb")) + { + return; + } + + if (m_extension && m_extension->customMenu()) + { + // use the extenion's own custom menu + Kicker::the()->setInsertionPoint(globalPos); + m_extension->customMenu()->exec(globalPos); + Kicker::the()->setInsertionPoint(QPoint()); + return; + } + + if (!_opMnu) + { + KDesktopFile f(KGlobal::dirs()->findResource("extensions", _info.desktopFile())); + _opMnu = new PanelExtensionOpMenu(f.readName(), + m_extension ? m_extension->actions() : 0, + this); + } + + QPopupMenu *menu = KickerLib::reduceMenu(_opMnu); + + Kicker::the()->setInsertionPoint(globalPos); + + switch (menu->exec(globalPos)) + { + case PanelExtensionOpMenu::Remove: + emit removeme(this); + break; + case PanelExtensionOpMenu::About: + about(); + break; + case PanelExtensionOpMenu::Help: + help(); + break; + case PanelExtensionOpMenu::Preferences: + preferences(); + break; + case PanelExtensionOpMenu::ReportBug: + reportBug(); + break; + default: + break; + } + Kicker::the()->setInsertionPoint(QPoint()); +} + +void ExtensionContainer::about() +{ + if (!m_extension) + { + return; + } + + m_extension->action(KPanelExtension::About); +} + +void ExtensionContainer::help() +{ + if (!m_extension) + { + return; + } + + m_extension->action(KPanelExtension::Help); +} + +void ExtensionContainer::preferences() +{ + if (!m_extension) + { + return; + } + + m_extension->action(KPanelExtension::Preferences); +} + +void ExtensionContainer::reportBug() +{ + if (!m_extension) + { + return; + } + + m_extension->action(KPanelExtension::ReportBug); +} + +void ExtensionContainer::removeSessionConfigFile() +{ + if (_info.configFile().isEmpty() || _info.isUniqueApplet()) + { + return; + } + + if (QFile::exists(locate("config", _info.configFile()))) + { + QFile::remove(locate("config", _info.configFile())); + } +} + +void ExtensionContainer::moveMe() +{ + int screen = xineramaScreen(); + if (screen < 0) + { + screen = kapp->desktop()->screenNumber(this); + } + + if (screen < 0) + { + // we aren't on any screen? um. ok. + return; + } + + stopAutoHideTimer(); + + QApplication::syncX(); + UserRectSel::RectList rects; + + KPanelExtension::Position positions[] = { KPanelExtension::Left, + KPanelExtension::Right, + KPanelExtension::Top, + KPanelExtension::Bottom }; + KPanelExtension::Alignment alignments[] = { KPanelExtension::LeftTop, + KPanelExtension::Center, + KPanelExtension::RightBottom }; + + for (int s = 0; s < QApplication::desktop()->numScreens(); s++) + { + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 3; j++) + { + // FIXME: + // asking for initial geometry here passes bogus heightForWidth + // and widthForHeight requests to applets and buttons. if they + // need to make layout adjustments or need to calculate based + // on other parameters this can lead to Bad Things(tm) + // + // we need to find a way to do this that doesn't result in + // sizeHint's getting called on the extension =/ + // + // or else we need to change the semantics for applets so that + // they don't get their "you're changing position" signals through + // heightForWidth/widthForHeight + rects.append(UserRectSel::PanelStrut(initialGeometry(positions[i], + alignments[j], s), + s, positions[i], alignments[j])); + } + } + } + + UserRectSel::PanelStrut newStrut = UserRectSel::select(rects, rect().center(), m_highlightColor); + arrange(newStrut.m_pos, newStrut.m_alignment, newStrut.m_screen); + + _is_lmb_down = false; + + // sometimes the HB's are not reset correctly + if (_ltHB) + { + _ltHB->setDown(false); + } + + if (_rbHB) + { + _rbHB->setDown(false); + } + + maybeStartAutoHideTimer(); +} + +void ExtensionContainer::updateLayout() +{ + /* + m_extension == 0 can happen for example if the constructor of a panel + extension calls adjustSize(), resulting in a sendPostedEvents on the parent (us) and + therefore this call. Happens with ksim for example. One can argue about ksim here, but + kicker shouldn't crash in any case. + */ + if (!m_extension || _updateLayoutTimer->isActive()) + { + return; + } + + // don't update our layout more than once every half a second... + if (_in_autohide) + { + // ... unless we are autohiding + _updateLayoutTimer->start(0,true); + } + else + { + _updateLayoutTimer->start(500,true); + } +} + +void ExtensionContainer::actuallyUpdateLayout() +{ +// kdDebug(1210) << "PanelContainer::updateLayout()" << endl; + resetLayout(); + updateWindowManager(); +} + +void ExtensionContainer::enableMouseOverEffects() +{ + KickerTip::enableTipping(true); + QPoint globalPos = QCursor::pos(); + QPoint localPos = mapFromGlobal(globalPos); + QWidget* child = childAt(localPos); + + if (child) + { + QMouseEvent* e = new QMouseEvent(QEvent::Enter, localPos, globalPos, 0, 0); + qApp->sendEvent(child, e); + } +} + +bool ExtensionContainer::shouldUnhideForTrigger(UnhideTrigger::Trigger t) const +{ + int loc = m_settings.unhideLocation(); + + if (loc == t) + { + return true; + } + + if (loc == UnhideTrigger::Bottom) + { + return t == UnhideTrigger::BottomLeft || + t == UnhideTrigger::BottomRight; + } + else if (loc == UnhideTrigger::Top) + { + return t == UnhideTrigger::TopLeft || + t == UnhideTrigger::TopRight; + } + else if (loc == UnhideTrigger::Left) + { + return t == UnhideTrigger::TopLeft || + t == UnhideTrigger::BottomLeft; + } + else if (loc == UnhideTrigger::Right) + { + return t == UnhideTrigger::TopRight || + t == UnhideTrigger::BottomRight; + } + + return false; +} + +void ExtensionContainer::unhideTriggered(UnhideTrigger::Trigger tr, int XineramaScreen) +{ + if (m_hideMode == ManualHide) + { + return; + } + else if (tr == UnhideTrigger::None) + { + if (m_settings.unhideLocation() != UnhideTrigger::None && _autoHidden) + { + UnhideTrigger::the()->setEnabled(false); + } + + m_unhideTriggeredAt = UnhideTrigger::None; + return; + } + + if (xineramaScreen() != XineramaAllScreens && + XineramaScreen != xineramaScreen()) + { + if (m_settings.unhideLocation() != UnhideTrigger::None) + { + m_unhideTriggeredAt = tr; + } + return; + } + + // here we handle the case where the user has defined WHERE + // the pannel can be popped up from. + if (m_settings.unhideLocation() != UnhideTrigger::None) + { + if (_autoHidden) + { + UnhideTrigger::the()->setEnabled(true); + } + + m_unhideTriggeredAt = tr; + if (shouldUnhideForTrigger(tr)) + { + UnhideTrigger::the()->triggerAccepted(tr, XineramaScreen); + + if (m_hideMode == BackgroundHide) + { + KWin::raiseWindow(winId()); + } + else if (_autoHidden) + { + autoHide(false); + maybeStartAutoHideTimer(); + } + } + + return; + } + + m_unhideTriggeredAt = UnhideTrigger::None; + + // Otherwise hide mode is automatic. The code below is slightly + // complex so as to keep the same behavior as it has always had: + // only unhide when the cursor position is within the widget geometry. + // We can't just do geometry().contains(QCursor::pos()) because + // now we hide the panel completely off screen. + + int x = QCursor::pos().x(); + int y = QCursor::pos().y(); + int t = geometry().top(); + int b = geometry().bottom(); + int r = geometry().right(); + int l = geometry().left(); + if (((tr == UnhideTrigger::Top || + tr == UnhideTrigger::TopLeft || + tr == UnhideTrigger::TopRight) && + position() == KPanelExtension::Top && x >= l && x <= r) || + ((tr == UnhideTrigger::Left || + tr == UnhideTrigger::TopLeft || + tr == UnhideTrigger::BottomLeft) && + position() == KPanelExtension::Left && y >= t && y <= b) || + ((tr == UnhideTrigger::Bottom || + tr == UnhideTrigger::BottomLeft || + tr == UnhideTrigger::BottomRight) && + position() == KPanelExtension::Bottom && x >= l && x <= r ) || + ((tr == UnhideTrigger::Right || + tr == UnhideTrigger::TopRight || + tr == UnhideTrigger::BottomRight) && + position() == KPanelExtension::Right && y >= t && y <= b )) + { + UnhideTrigger::the()->triggerAccepted(tr, XineramaScreen); + + if (_autoHidden) + { + autoHide(false); + maybeStartAutoHideTimer(); + } + else if (m_hideMode == BackgroundHide) + { + KWin::raiseWindow(winId()); + } + } +} + +void ExtensionContainer::autoHideTimeout() +{ +// kdDebug(1210) << "PanelContainer::autoHideTimeout() " << name() << endl; + // Hack: If there is a popup open, don't autohide until it closes. + QWidget* popup = QApplication::activePopupWidget(); + if (popup) + { + + // kdDebug(1210) << "popup detected" << endl; + + // Remove it first in case it was already installed. + // Does nothing if it wasn't installed. + popup->removeEventFilter( _popupWidgetFilter ); + + // We will get a signal from the filter after the + // popup is hidden. At that point, maybeStartAutoHideTimer() + // will get called again. + popup->installEventFilter( _popupWidgetFilter ); + + // Stop the timer. + stopAutoHideTimer(); + return; + } + + if (m_hideMode != AutomaticHide || + _autoHidden || + _userHidden || + m_maintainFocus > 0) + { + return; + } + + QRect r = geometry(); + QPoint p = QCursor::pos(); + if (!r.contains(p) && + (m_settings.unhideLocation() == UnhideTrigger::None || + !shouldUnhideForTrigger(m_unhideTriggeredAt))) + { + stopAutoHideTimer(); + autoHide(true); + UnhideTrigger::the()->resetTriggerThrottle(); + } +} + +void ExtensionContainer::hideLeft() +{ + animatedHide(true); +} + +void ExtensionContainer::hideRight() +{ + animatedHide(false); +} + +void ExtensionContainer::autoHide(bool hide) +{ +// kdDebug(1210) << "PanelContainer::autoHide( " << hide << " )" << endl; + + if (_in_autohide || hide == _autoHidden) + { + return; + } + + // 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 */ + QRect desktopGeom = QApplication::desktop()->screenGeometry(s); + if (desktopGeom.intersects(newextent) && + !desktopGeom.intersects(geometry())) + { + blockUserInput( false ); + return; + } + } + } + + _in_autohide = true; + _autoHidden = hide; + UnhideTrigger::the()->setEnabled(_autoHidden); + KickerTip::enableTipping(false); + + if (hide) + { + // So we don't cover other panels + lower(); + } + else + { + // So we aren't covered by other panels + raise(); + } + + if (m_settings.hideAnimation()) + { + if (position() == KPanelExtension::Left || position() == KPanelExtension::Right) + { + for (int i = 0; i < abs(newpos.x() - oldpos.x()); + i += PANEL_SPEED(i,abs(newpos.x() - oldpos.x()))) + { + if (newpos.x() > oldpos.x()) + { + move(oldpos.x() + i, newpos.y()); + } + else + { + move(oldpos.x() - i, newpos.y()); + } + + qApp->syncX(); + qApp->processEvents(); + } + } + else + { + for (int i = 0; i < abs(newpos.y() - oldpos.y()); + i += PANEL_SPEED(i,abs(newpos.y() - oldpos.y()))) + { + if (newpos.y() > oldpos.y()) + { + move(newpos.x(), oldpos.y() + i); + } + else + { + move(newpos.x(), oldpos.y() - i); + } + + qApp->syncX(); + qApp->processEvents(); + } + } + } + + blockUserInput(false); + + updateLayout(); + + // Sometimes tooltips don't get hidden + QToolTip::hide(); + + _in_autohide = false; + + QTimer::singleShot(100, this, SLOT(enableMouseOverEffects())); +} + +void ExtensionContainer::animatedHide(bool left) +{ +// kdDebug(1210) << "PanelContainer::animatedHide()" << endl; + KickerTip::enableTipping(false); + blockUserInput(true); + + UserHidden newState; + if (_userHidden != Unhidden) + { + newState = Unhidden; + } + else if (left) + { + newState = LeftTop; + } + else + { + newState = RightBottom; + } + + QPoint oldpos = pos(); + 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); + QTimer::singleShot(100, this, SLOT(enableMouseOverEffects())); + return; + } + } + + _userHidden = newState; + + // So we don't cover the mac-style menubar + lower(); + } + + if (m_settings.hideAnimation()) + { + if (position() == KPanelExtension::Left || position() == KPanelExtension::Right) + { + for (int i = 0; i < abs(newpos.y() - oldpos.y()); + i += PANEL_SPEED(i, abs(newpos.y() - oldpos.y()))) + { + if (newpos.y() > oldpos.y()) + { + move(newpos.x(), oldpos.y() + i); + } + else + { + move(newpos.x(), oldpos.y() - i); + } + qApp->syncX(); + qApp->processEvents(); + } + } + else + { + for (int i = 0; i < abs(newpos.x() - oldpos.x()); + i += PANEL_SPEED(i, abs(newpos.x() - oldpos.x()))) + { + if (newpos.x() > oldpos.x()) + { + move(oldpos.x() + i, newpos.y()); + } + else + { + move(oldpos.x() - i, newpos.y()); + } + qApp->syncX(); + qApp->processEvents(); + } + } + } + + blockUserInput( false ); + + _userHidden = newState; + + actuallyUpdateLayout(); + qApp->syncX(); + qApp->processEvents(); + + // save our hidden status so that when kicker starts up again + // we'll come back in the same state + KConfig *config = KGlobal::config(); + config->setGroup(extensionId()); + config->writeEntry("UserHidden", userHidden()); + + QTimer::singleShot(100, this, SLOT(enableMouseOverEffects())); +} + +bool ExtensionContainer::reserveStrut() const +{ + return !m_extension || m_extension->reserveStrut(); +} + +KPanelExtension::Alignment ExtensionContainer::alignment() const +{ + // KConfigXT really needs to get support for vars that are enums that + // are defined in other classes + return static_cast<KPanelExtension::Alignment>(m_settings.alignment()); +} + +void ExtensionContainer::updateWindowManager() +{ + NETExtendedStrut strut; + + if (reserveStrut()) + { + // kdDebug(1210) << "PanelContainer::updateWindowManager()" << endl; + // Set the relevant properties on the window. + int w = 0; + int h = 0; + + QRect geom = initialGeometry(position(), alignment(), xineramaScreen()); + QRect virtRect(QApplication::desktop()->geometry()); + QRect screenRect(QApplication::desktop()->screenGeometry(xineramaScreen())); + + if (m_hideMode == ManualHide && !userHidden()) + { + w = width(); + h = height(); + } + + switch (position()) + { + case KPanelExtension::Top: + strut.top_width = geom.y() + h; + strut.top_start = x(); + strut.top_end = x() + width() - 1; + break; + + case KPanelExtension::Bottom: + // also claim the non-visible part at the bottom + strut.bottom_width = (virtRect.bottom() - geom.bottom()) + h; + strut.bottom_start = x(); + strut.bottom_end = x() + width() - 1; + break; + + case KPanelExtension::Right: + strut.right_width = (virtRect.right() - geom.right()) + w; + strut.right_start = y(); + strut.right_end = y() + height() - 1; + break; + + case KPanelExtension::Left: + strut.left_width = geom.x() + w; + strut.left_start = y(); + strut.left_end = y() + height() - 1; + break; + + case KPanelExtension::Floating: + // should never be reached, anyways + break; + } + } + + if (strut.left_width != _strut.left_width || + strut.left_start != _strut.left_start || + strut.left_end != _strut.left_end || + strut.right_width != _strut.right_width || + strut.right_start != _strut.right_start || + strut.right_end != _strut.right_end || + strut.top_width != _strut.top_width || + strut.top_start != _strut.top_start || + strut.top_end != _strut.top_end || + strut.bottom_width != _strut.bottom_width || + strut.bottom_start != _strut.bottom_start || + strut.bottom_end != _strut.bottom_end) + { + /*kdDebug(1210) << " === Panel sets new strut for pos " << position() << " ===" << endl; + + kdDebug(1210) << "strut for " << winId() << ": " << endl << + "\tleft : " << strut.left_width << " " << strut.left_start << " " << strut.left_end << endl << + "\tright : " << strut.right_width << " " << strut.right_start << " " << strut.right_end << endl << + "\ttop : " << strut.top_width << " " << strut.top_start << " " << strut.top_end << endl << + "\tbottom: " << strut.bottom_width << " " << strut.bottom_start << " " << strut.bottom_end << endl; */ + _strut = strut; + + KWin::setExtendedStrut(winId(), + strut.left_width, strut.left_start, strut.left_end, + strut.right_width, strut.right_start, strut.right_end, + strut.top_width, strut.top_start, strut.top_end, + strut.bottom_width, strut.bottom_start, strut.bottom_end); + KWin::setStrut(winId(), strut.left_width, strut.right_width, strut.top_width, strut.bottom_width); + } + /*else + { + kdDebug(1210) << "Panel strut did NOT change!" << endl; + }*/ +} + +void ExtensionContainer::currentDesktopChanged(int) +{ + // kdDebug(1210) << "PanelContainer::currentDesktopChanged" << endl; + if (m_settings.autoHideSwitch()) + { + if (m_hideMode == AutomaticHide) + { + autoHide(false); + } + else if (m_hideMode == BackgroundHide) + { + KWin::raiseWindow(winId()); + } + } + + // For some reason we don't always get leave events when the user + // changes desktops and moves the cursor out of the panel at the + // same time. Maybe always calling this will help. + maybeStartAutoHideTimer(); +} + +void ExtensionContainer::strutChanged() +{ + //kdDebug(1210) << "PanelContainer::strutChanged()" << endl; + QRect ig = currentGeometry(); + + if (ig != geometry()) + { + setGeometry(ig); + updateLayout(); + } +} + +void ExtensionContainer::blockUserInput( bool block ) +{ + if (block == _block_user_input) + { + return; + } + + // If we don't want any user input to be possible we should catch mouse + // events and such. Therefore we install an eventfilter and let the + // eventfilter discard those events. + if ( block ) + { + qApp->installEventFilter( this ); + } + else + { + qApp->removeEventFilter( this ); + } + + _block_user_input = block; +} + +void ExtensionContainer::maybeStartAutoHideTimer() +{ + if (m_hideMode != ManualHide && + !_autoHidden && + !_userHidden) + { + // kdDebug(1210) << "starting auto hide timer for " << name() << endl; + if (m_settings.autoHideDelay() == 0) + { + _autohideTimer->start(250); + } + else + { + _autohideTimer->start(m_settings.autoHideDelay() * 1000); + } + } +} + +void ExtensionContainer::stopAutoHideTimer() +{ + if (_autohideTimer->isActive()) + { + //kdDebug(1210) << "stopping auto hide timer for " << name() << endl; + _autohideTimer->stop(); + } +} + +void ExtensionContainer::maintainFocus(bool maintain) +{ + if (maintain) + { + ++m_maintainFocus; + + if (_autoHidden) + { + autoHide(false); + } + else if (_userHidden == LeftTop) + { + animatedHide(true); + } + else if (_userHidden == RightBottom) + { + animatedHide(false); + } + } + else if (m_maintainFocus > 0) + { + --m_maintainFocus; + } +} + +int ExtensionContainer::arrangeHideButtons() +{ + bool layoutEnabled = _layout->isEnabled(); + + if (layoutEnabled) + { + _layout->setEnabled(false); + } + + if (orientation() == Vertical) + { + int maxWidth = width(); + + if (needsBorder()) + { + --maxWidth; + } + + if (_ltHB) + { + _ltHB->setMaximumWidth(maxWidth); + _ltHB->setMaximumHeight(14); + _layout->remove(_ltHB); + _layout->addWidget(_ltHB, 0, 1, Qt::AlignBottom | Qt::AlignLeft); + } + + if (_rbHB) + { + _rbHB->setMaximumWidth(maxWidth); + _rbHB->setMaximumHeight(14); + _layout->remove(_rbHB); + _layout->addWidget(_rbHB, 2, 1); + } + } + else + { + int maxHeight = height(); + + if (needsBorder()) + { + --maxHeight; + } + + int vertAlignment = (position() == KPanelExtension::Top) ? Qt::AlignTop : 0; + int leftAlignment = Qt::AlignRight; + + if (_ltHB) + { + _ltHB->setMaximumHeight(maxHeight); + _ltHB->setMaximumWidth(14); + _layout->remove(_ltHB); + if (kapp->reverseLayout()) + { + _layout->addWidget(_ltHB, 1, 2, vertAlignment); + } + else + { + _layout->addWidget(_ltHB, 1, 0, leftAlignment | vertAlignment); + } + } + + if (_rbHB) + { + _rbHB->setMaximumHeight(maxHeight); + _rbHB->setMaximumWidth(14); + _layout->remove(_rbHB); + if (kapp->reverseLayout()) + { + _layout->addWidget(_rbHB, 1, 0, leftAlignment | vertAlignment); + } + else + { + _layout->addWidget(_rbHB, 1, 2, vertAlignment); + } + } + } + + int layoutOffset = setupBorderSpace(); + if (layoutEnabled) + { + _layout->setEnabled(true); + } + + return layoutOffset; +} + +int ExtensionContainer::setupBorderSpace() +{ + _layout->setRowSpacing(0, 0); + _layout->setRowSpacing(2, 0); + _layout->setColSpacing(0, 0); + _layout->setColSpacing(2, 0); + + if (!needsBorder()) + { + return 0; + } + + int layoutOffset = 0; + QRect r = QApplication::desktop()->screenGeometry(xineramaScreen()); + QRect h = geometry(); + + if (orientation() == Vertical) + { + if (h.top() > 0) + { + int topHeight = (_ltHB && _ltHB->isVisibleTo(this)) ? _ltHB->height() + 1 : 1; + _layout->setRowSpacing(0, topHeight); + ++layoutOffset; + } + + if (h.bottom() < r.bottom()) + { + int bottomHeight = (_rbHB && _rbHB->isVisibleTo(this)) ? _rbHB->height() + 1 : 1; + _layout->setRowSpacing(1, bottomHeight); + ++layoutOffset; + } + } + else + { + if (h.left() > 0) + { + int leftWidth = (_ltHB && _ltHB->isVisibleTo(this)) ? _ltHB->width() + 1 : 1; + _layout->setColSpacing(0, leftWidth); + ++layoutOffset; + } + + if (h.right() < r.right()) + { + int rightWidth = (_rbHB && _rbHB->isVisibleTo(this)) ? _rbHB->width() + 1 : 1; + _layout->setColSpacing(1, rightWidth); + ++layoutOffset; + } + } + + switch (position()) + { + case KPanelExtension::Left: + _layout->setColSpacing(2, 1); + break; + + case KPanelExtension::Right: + _layout->setColSpacing(0, 1); + break; + + case KPanelExtension::Top: + _layout->setRowSpacing(2, 1); + break; + + case KPanelExtension::Bottom: + default: + _layout->setRowSpacing(0, 1); + break; + } + + return layoutOffset; +} + +void ExtensionContainer::positionChange(KPanelExtension::Position p) +{ + arrangeHideButtons(); + + if (m_extension) + { + m_extension->setPosition(p); + } + + update(); +} + +void ExtensionContainer::updateHighlightColor() +{ + KConfig *config = KGlobal::config(); + config->setGroup("WM"); + QColor color = QApplication::palette().active().highlight(); + m_highlightColor = config->readColorEntry("activeBackground", &color); + update(); +} + +void ExtensionContainer::paintEvent(QPaintEvent *e) +{ + QFrame::paintEvent(e); + + if (needsBorder()) + { + // draw border + QPainter p(this); + if (KickerSettings::useBackgroundTheme() && KickerSettings::colorizeBackground()) + p.setPen(m_highlightColor); + else + p.setPen(palette().color(QPalette::Active, QColorGroup::Mid)); + p.drawRect(0, 0, width(), height()); + } +} + +void ExtensionContainer::leaveEvent(QEvent*) +{ + maybeStartAutoHideTimer(); +} + +void ExtensionContainer::alignmentChange(KPanelExtension::Alignment a) +{ + if (!m_extension) + { + return; + } + + m_extension->setAlignment(a); +} + +void ExtensionContainer::setSize(KPanelExtension::Size size, int custom) +{ + if (!m_extension) + { + return; + } + + m_settings.setSize(size); + m_settings.setCustomSize(custom); + m_extension->setSize(size, custom); +} + +KPanelExtension::Size ExtensionContainer::size() const +{ + // KConfigXT really needs to get support for vars that are enums that + // are defined in other classes + return static_cast<KPanelExtension::Size>(m_settings.size()); +} + +ExtensionContainer::HideMode ExtensionContainer::hideMode() const +{ + return m_hideMode; +} + +void ExtensionContainer::unhideIfHidden(int showForAtLeastHowManyMS) +{ + if (_autoHidden) + { + autoHide(false); + QTimer::singleShot(showForAtLeastHowManyMS, + this, SLOT(maybeStartAutoHideTimer())); + return; + } + + if (_userHidden == LeftTop) + { + animatedHide(true); + } + else if (_userHidden == RightBottom) + { + animatedHide(false); + } +} + +void ExtensionContainer::setHideButtons(bool showLeft, bool showRight) +{ + if (m_settings.showLeftHideButton() == showLeft && + m_settings.showRightHideButton() == showRight) + { + return; + } + + m_settings.setShowLeftHideButton(showLeft); + m_settings.setShowRightHideButton(showRight); + resetLayout(); +} + +bool ExtensionContainer::event(QEvent* e) +{ + // Update the layout when we receive a LayoutHint. This way we can adjust + // to changes of the layout of the main widget. + if (e->type() == QEvent::LayoutHint) + { + updateLayout(); + } + + return QFrame::event(e); +} + +void ExtensionContainer::closeEvent(QCloseEvent* e) +{ + // Prevent being closed via Alt-F4 + e->ignore(); +} + +void ExtensionContainer::arrange(KPanelExtension::Position p, + KPanelExtension::Alignment a, + int XineramaScreen) +{ + if (p == m_settings.position() && + a == m_settings.alignment() && + XineramaScreen == xineramaScreen()) + { + return; + } + + bool positionChanged = p != m_settings.position(); + if (positionChanged) + { + m_settings.setPosition(p); + } + else if (!needsBorder()) + { + // this ensures that the layout gets rejigged + // even if position doesn't change + _layout->setRowSpacing(0, 0); + _layout->setRowSpacing(2, 0); + _layout->setColSpacing(0, 0); + _layout->setColSpacing(2, 0); + } + + if (a != m_settings.alignment()) + { + m_settings.setAlignment(a); + setAlignment(a); + } + + if (XineramaScreen != xineramaScreen()) + { + m_settings.setXineramaScreen(XineramaScreen); + xineramaScreenChange(XineramaScreen); + } + + actuallyUpdateLayout(); + + if (positionChanged) + { + positionChange(p); + } + writeConfig(); +} + +KPanelExtension::Orientation ExtensionContainer::orientation() const +{ + if (position() == KPanelExtension::Top || position() == KPanelExtension::Bottom) + { + return Horizontal; + } + else + { + return Vertical; + } +} + +KPanelExtension::Position ExtensionContainer::position() const +{ + // KConfigXT really needs to get support for vars that are enums that + // are defined in other classes + return static_cast<KPanelExtension::Position>(m_settings.position()); +} + +void ExtensionContainer::resetLayout() +{ + QRect g = initialGeometry(position(), alignment(), xineramaScreen(), + autoHidden(), userHidden()); + + // Disable the layout while we rearrange the panel. + // Necessary because the children may be + // relayouted with the wrong size. + + _layout->setEnabled(false); + + if (geometry() != g) + { + setGeometry(g); + ExtensionManager::the()->extensionSizeChanged(this); + } + + // layout + bool haveToArrangeButtons = false; + bool showLeftHideButton = m_settings.showLeftHideButton() || userHidden() == RightBottom; + bool showRightHideButton = m_settings.showRightHideButton() || userHidden() == LeftTop; + + // left/top hide button + if (showLeftHideButton) + { + if (!_ltHB) + { + _ltHB = new HideButton(this); + _ltHB->installEventFilter(this); + _ltHB->setEnabled(true); + connect(_ltHB, SIGNAL(clicked()), this, SLOT(hideLeft())); + haveToArrangeButtons = true; + } + + if (orientation() == Horizontal) + { + _ltHB->setArrowType(Qt::LeftArrow); + _ltHB->setFixedSize(m_settings.hideButtonSize(), height()); + } + else + { + _ltHB->setArrowType(Qt::UpArrow); + _ltHB->setFixedSize(width(), m_settings.hideButtonSize()); + } + + _ltHB->show(); + } + else if (_ltHB) + { + _ltHB->hide(); + } + + // right/bottom hide button + if (showRightHideButton) + { + if (!_rbHB) + { + // right/bottom hide button + _rbHB = new HideButton(this); + _rbHB->installEventFilter(this); + _rbHB->setEnabled(true); + connect(_rbHB, SIGNAL(clicked()), this, SLOT(hideRight())); + haveToArrangeButtons = true; + } + + if ( orientation() == Horizontal) + { + _rbHB->setArrowType(Qt::RightArrow); + _rbHB->setFixedSize(m_settings.hideButtonSize(), height()); + } + else + { + _rbHB->setArrowType(Qt::DownArrow); + _rbHB->setFixedSize(width(), m_settings.hideButtonSize()); + } + + _rbHB->show(); + } + else if (_rbHB) + { + _rbHB->hide(); + } + + if (_ltHB) + { + QToolTip::remove(_ltHB); + if (userHidden()) + { + QToolTip::add(_ltHB, i18n("Show panel")); + } + else + { + QToolTip::add(_ltHB, i18n("Hide panel")); + } + } + + if (_rbHB) + { + QToolTip::remove( _rbHB ); + if (userHidden()) + { + QToolTip::add(_rbHB, i18n("Show panel")); + } + else + { + QToolTip::add(_rbHB, i18n("Hide panel")); + } + } + + updateGeometry(); + int endBorderWidth = haveToArrangeButtons ? arrangeHideButtons() : setupBorderSpace(); + + if (orientation() == Horizontal) + { + if (m_extension) + { + int maxWidth = width() - endBorderWidth; + + if (showLeftHideButton) + { + maxWidth -= _ltHB->width(); + } + + if (showRightHideButton) + { + maxWidth -= _rbHB->width(); + } + + m_extension->setMaximumWidth(maxWidth); + + if (needsBorder()) + { + m_extension->setFixedHeight(height() - 1); + } + else + { + m_extension->setFixedHeight(height()); + } + } + } + else if (m_extension) + { + int maxHeight = height() - endBorderWidth; + + if (showLeftHideButton) + { + maxHeight -= _ltHB->height(); + } + + if (showRightHideButton) + { + maxHeight -= _rbHB->height(); + } + + m_extension->setMaximumHeight(maxHeight); + + if (needsBorder()) + { + m_extension->setFixedWidth(width() - 1); + } + else + { + m_extension->setFixedWidth(width()); + } + } + + _layout->setEnabled(true); +} + +bool ExtensionContainer::needsBorder() const +{ + return !KickerSettings::transparent(); + //&& !KickerSettings::useBackgroundTheme(); +} + +QSize ExtensionContainer::initialSize(KPanelExtension::Position p, QRect workArea) const +{ + /*kdDebug(1210) << "initialSize() Work Area: (" << workArea.topLeft().x() << + ", " << workArea.topLeft().y() << ") to (" << workArea.bottomRight().x() << + ", " << workArea.bottomRight().y() << ")" << endl;*/ + + QSize hint = sizeHint(p, workArea.size()).boundedTo(workArea.size()); + int width = 0; + int height = 0; + + if (p == KPanelExtension::Left || p == KPanelExtension::Right) + { + width = hint.width(); + height = (workArea.height() * m_settings.sizePercentage()) / 100; + + if (m_settings.expandSize()) + { + height = QMAX(height, hint.height()); + } + } + else + { + width = (workArea.width() * m_settings.sizePercentage()) / 100; + height = hint.height(); + + if (m_settings.expandSize()) + { + width = QMAX( width, hint.width() ); + } + } + + return QSize(width, height); +} + +QPoint ExtensionContainer::initialLocation(KPanelExtension::Position p, + KPanelExtension::Alignment a, + int XineramaScreen, + const QSize &s, + QRect workArea, + bool autohidden, + UserHidden userHidden) const +{ + QRect wholeScreen; + if (XineramaScreen == XineramaAllScreens) + { + wholeScreen = QApplication::desktop()->geometry(); + } + else + { + wholeScreen = QApplication::desktop()->screenGeometry(XineramaScreen); + } + + /*kdDebug(1210) << "initialLocation() Work Area: (" << + workArea.topLeft().x() << ", " << + area.topLeft().y() << ") to (" << + workArea.bottomRight().x() << ", " << + workArea.bottomRight().y() << ")" << endl;*/ + + int left; + int top; + + // If the panel is horizontal + if (p == KPanelExtension::Top || p == KPanelExtension::Bottom) + { + // Get the X coordinate + switch (a) + { + case KPanelExtension::LeftTop: + left = workArea.left(); + break; + + case KPanelExtension::Center: + { + left = wholeScreen.left() + ( wholeScreen.width() - s.width() ) / 2; + int right = left + s.width(); + if (right > workArea.right()) + { + left = left - (right - workArea.right()); + } + + if (left < workArea.left()) + { + left = workArea.left(); + } + + break; + } + + case KPanelExtension::RightBottom: + left = workArea.right() - s.width() + 1; + break; + + default: + left = workArea.left(); + break; + } + + // Get the Y coordinate + if (p == KPanelExtension::Top) + { + top = workArea.top(); + } + else + { + top = workArea.bottom() - s.height() + 1; + } + } + else // vertical panel + { + // Get the Y coordinate + switch (a) + { + case KPanelExtension::LeftTop: + top = workArea.top(); + break; + + case KPanelExtension::Center: + { + top = wholeScreen.top() + ( wholeScreen.height() - s.height() ) / 2; + int bottom = top + s.height(); + if (bottom > workArea.bottom()) + { + top = top - (bottom - workArea.bottom()); + } + + if (top < workArea.top()) + { + top = workArea.top(); + } + break; + } + + case KPanelExtension::RightBottom: + top = workArea.bottom() - s.height() + 1; + break; + + default: + top = workArea.top(); + } + + // Get the X coordinate + if (p == KPanelExtension::Left) + { + left = workArea.left(); + } + else + { + left = workArea.right() - s.width() + 1; + } + } + + // Correct for auto hide + if (autohidden) + { + switch (position()) + { + case KPanelExtension::Left: + left -= s.width(); + break; + + case KPanelExtension::Right: + left += s.width(); + break; + + case KPanelExtension::Top: + top -= s.height(); + break; + + case KPanelExtension::Bottom: + default: + top += s.height(); + break; + } + // Correct for user hide + } + else if (userHidden == LeftTop) + { + if (position() == KPanelExtension::Left || position() == KPanelExtension::Right) + { + top = workArea.top() - s.height() + m_settings.hideButtonSize(); + } + else + { + left = workArea.left() - s.width() + m_settings.hideButtonSize(); + } + } + else if (userHidden == RightBottom) + { + if (position() == KPanelExtension::Left || position() == KPanelExtension::Right) + { + top = workArea.bottom() - m_settings.hideButtonSize() + 1; + } + else + { + left = workArea.right() - m_settings.hideButtonSize() + 1; + } + } + + return QPoint( left, top ); +} + +int ExtensionContainer::xineramaScreen() const +{ + // sanitize at runtime only, since many Xinerama users + // turn it on and off and don't want kicker to lose their configs + + /* -2 means all screens, -1 primary screens, the rest are valid screen numbers */ + if (XineramaAllScreens <= m_settings.xineramaScreen() && + m_settings.xineramaScreen() < QApplication::desktop()->numScreens()) + { + return m_settings.xineramaScreen(); + } + else + { + /* force invalid screen locations onto the primary screen */ + return QApplication::desktop()->primaryScreen(); + } +} + +void ExtensionContainer::setXineramaScreen(int screen) +{ + if (m_settings.isImmutable("XineramaScreen")) + { + return; + } + + arrange(position(),alignment(), screen); +} + +QRect ExtensionContainer::currentGeometry() const +{ + return initialGeometry(position(), alignment(), xineramaScreen(), + autoHidden(), userHidden()); +} + +QRect ExtensionContainer::initialGeometry(KPanelExtension::Position p, + KPanelExtension::Alignment a, + int XineramaScreen, + bool autoHidden, + UserHidden userHidden) const +{ + //RESEARCH: is there someway to cache the results of the repeated calls to this method? + + /*kdDebug(1210) << "initialGeometry() Computing geometry for " << name() << + " on screen " << XineramaScreen << endl;*/ + QRect workArea = ExtensionManager::the()->workArea(XineramaScreen, this); + QSize size = initialSize(p, workArea); + QPoint point = initialLocation(p, a, XineramaScreen, + size, workArea, + autoHidden, userHidden); + + //kdDebug(1210) << "Size: " << size.width() << " x " << size.height() << endl; + //kdDebug(1210) << "Pos: (" << point.x() << ", " << point.y() << ")" << endl; + + return QRect(point, size); +} + +bool ExtensionContainer::eventFilter( QObject*, QEvent * e) +{ + if (autoHidden()) + { + switch ( e->type() ) + { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::KeyPress: + case QEvent::KeyRelease: + return true; // ignore; + default: + break; + } + } + + QEvent::Type eventType = e->type(); + if (_block_user_input) + { + return (eventType == QEvent::MouseButtonPress || + eventType == QEvent::MouseButtonRelease || + eventType == QEvent::MouseButtonDblClick || + eventType == QEvent::MouseMove || + eventType == QEvent::KeyPress || + eventType == QEvent::KeyRelease || + eventType == QEvent::Enter || + eventType == QEvent::Leave); + } + + switch (eventType) + { + case QEvent::MouseButtonPress: + { + QMouseEvent* me = static_cast<QMouseEvent*>(e); + if ( me->button() == LeftButton ) + { + _last_lmb_press = me->globalPos(); + _is_lmb_down = true; + } + else if (me->button() == RightButton) + { + showPanelMenu(me->globalPos()); + return true; // don't crash! + } + } + break; + + case QEvent::MouseButtonRelease: + { + QMouseEvent* me = static_cast<QMouseEvent*>(e); + if ( me->button() == LeftButton ) + { + _is_lmb_down = false; + } + } + break; + + case QEvent::MouseMove: + { + QMouseEvent* me = (QMouseEvent*) e; + if (_is_lmb_down && + ((me->state() & LeftButton) == LeftButton) && + !Kicker::the()->isImmutable() && + !m_settings.config()->isImmutable() && + !ExtensionManager::the()->isMenuBar(this)) + { + QPoint p(me->globalPos() - _last_lmb_press); + int x_threshold = width(); + int y_threshold = height(); + + if (x_threshold > y_threshold) + { + x_threshold = x_threshold / 3; + y_threshold *= 2; + } + else + { + y_threshold = y_threshold / 3; + x_threshold *= 2; + } + + if ((abs(p.x()) > x_threshold) || + (abs(p.y()) > y_threshold)) + { + moveMe(); + return true; + } + } + } + break; + + default: + break; + } + + return false; +} + +PopupWidgetFilter::PopupWidgetFilter( QObject *parent ) + : QObject( parent, "PopupWidgetFilter" ) +{ +} + +bool PopupWidgetFilter::eventFilter( QObject*, QEvent* e ) +{ + if (e->type() == QEvent::Hide) + { + emit popupWidgetHiding(); + } + return false; +} + +#include "container_extension.moc" + |