X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fuisupport%2Fgraphicalui.cpp;h=d1e106d10722c335c9363b749d9b7caf2440e7c3;hp=8e5fe9432df1c0bdceff37522abb98f36461494e;hb=09ced75541a8702726ed5d66ebc628db2bd50423;hpb=4476cfb22f36ad9ba96e4978c3bcce1c2f6b5a04 diff --git a/src/uisupport/graphicalui.cpp b/src/uisupport/graphicalui.cpp index 8e5fe943..d1e106d1 100644 --- a/src/uisupport/graphicalui.cpp +++ b/src/uisupport/graphicalui.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2010 by the Quassel Project * + * Copyright (C) 2005-2015 by the Quassel Project * * devel@quassel-irc.org * * * * This contains code from KStatusNotifierItem, part of the KDE libs * @@ -18,18 +18,20 @@ * 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., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "graphicalui.h" #include "actioncollection.h" +#include "uisettings.h" #include "contextmenuactionprovider.h" +#include "toolbaractionprovider.h" #ifdef Q_WS_X11 # include #endif -#ifdef HAVE_KDE +#ifdef HAVE_KDE4 # include # include #endif @@ -42,169 +44,234 @@ ToolBarActionProvider *GraphicalUi::_toolBarActionProvider = 0; UiStyle *GraphicalUi::_uiStyle = 0; bool GraphicalUi::_onAllDesktops = false; -GraphicalUi::GraphicalUi(QObject *parent) : AbstractUi(parent) { - Q_ASSERT(!_instance); - _instance = this; +GraphicalUi::GraphicalUi(QObject *parent) : AbstractUi(parent) +{ + Q_ASSERT(!_instance); + _instance = this; -#ifdef Q_WS_WIN - _dwTickCount = 0; +#ifdef Q_OS_WIN + _dwTickCount = 0; #endif } -void GraphicalUi::init() { -#ifdef Q_WS_WIN - mainWidget()->installEventFilter(this); + +void GraphicalUi::init() +{ +#ifdef Q_OS_WIN + mainWidget()->installEventFilter(this); #endif } -ActionCollection *GraphicalUi::actionCollection(const QString &category) { - if(_actionCollections.contains(category)) - return _actionCollections.value(category); - ActionCollection *coll = new ActionCollection(_mainWidget); - if(_mainWidget) - coll->addAssociatedWidget(_mainWidget); - _actionCollections.insert(category, coll); - return coll; -} -void GraphicalUi::setMainWidget(QWidget *widget) { - _mainWidget = widget; +ActionCollection *GraphicalUi::actionCollection(const QString &category, const QString &translatedCategory) +{ + if (_actionCollections.contains(category)) + return _actionCollections.value(category); + ActionCollection *coll = new ActionCollection(_mainWidget); + + if (!translatedCategory.isEmpty()) + coll->setProperty("Category", translatedCategory); + else + coll->setProperty("Category", category); + + if (_mainWidget) + coll->addAssociatedWidget(_mainWidget); + _actionCollections.insert(category, coll); + return coll; } -void GraphicalUi::setContextMenuActionProvider(ContextMenuActionProvider *provider) { - _contextMenuActionProvider = provider; + +QHash GraphicalUi::actionCollections() +{ + return _actionCollections; } -void GraphicalUi::setToolBarActionProvider(ToolBarActionProvider *provider) { - _toolBarActionProvider = provider; + +void GraphicalUi::loadShortcuts() +{ + foreach(ActionCollection *coll, actionCollections()) + coll->readSettings(); } -void GraphicalUi::setUiStyle(UiStyle *style) { - _uiStyle = style; + +void GraphicalUi::saveShortcuts() +{ + ShortcutSettings s; + s.clear(); + foreach(ActionCollection *coll, actionCollections()) + coll->writeSettings(); } -bool GraphicalUi::eventFilter(QObject *obj, QEvent *event) { -#ifdef Q_WS_WIN - if(obj == mainWidget() && event->type() == QEvent::ActivationChange) { - _dwTickCount = GetTickCount(); - } -#endif - return AbstractUi::eventFilter(obj, event); + +void GraphicalUi::setMainWidget(QWidget *widget) +{ + _mainWidget = widget; } -// Code taken from KStatusNotifierItem for handling minimize/restore -bool GraphicalUi::checkMainWidgetVisibility(bool perform) { -#ifdef Q_WS_WIN - // the problem is that we lose focus when the systray icon is activated - // and we don't know the former active window - // therefore we watch for activation event and use our stopwatch :) - if(GetTickCount() - _dwTickCount < 300) { - // we were active in the last 300ms -> hide it - if(perform) - minimizeRestore(false); - return false; - } else { - if(perform) - minimizeRestore(true); - return true; - } - -#elif defined(HAVE_KDE) && defined(Q_WS_X11) - KWindowInfo info1 = KWindowSystem::windowInfo(mainWidget()->winId(), NET::XAWMState | NET::WMState | NET::WMDesktop); - // mapped = visible (but possibly obscured) - bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized(); - - // - not mapped -> show, raise, focus - // - mapped - // - obscured -> raise, focus - // - not obscured -> hide - //info1.mappingState() != NET::Visible -> window on another desktop? - if(!mapped) { - if(perform) - minimizeRestore(true); - return true; +void GraphicalUi::setContextMenuActionProvider(ContextMenuActionProvider *provider) +{ + _contextMenuActionProvider = provider; +} - } else { - QListIterator< WId > it (KWindowSystem::stackingOrder()); - it.toBack(); - while(it.hasPrevious()) { - WId id = it.previous(); - if(id == mainWidget()->winId()) - break; - KWindowInfo info2 = KWindowSystem::windowInfo(id, NET::WMDesktop | NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType); +void GraphicalUi::setToolBarActionProvider(ToolBarActionProvider *provider) +{ + _toolBarActionProvider = provider; +} - if(info2.mappingState() != NET::Visible) - continue; // not visible on current desktop -> ignore - if(!info2.geometry().intersects(mainWidget()->geometry())) - continue; // not obscuring the window -> ignore +void GraphicalUi::setUiStyle(UiStyle *style) +{ + _uiStyle = style; +} - if(!info1.hasState(NET::KeepAbove) && info2.hasState(NET::KeepAbove)) - continue; // obscured by window kept above -> ignore - NET::WindowType type = info2.windowType(NET::NormalMask | NET::DesktopMask - | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask - | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask); +void GraphicalUi::disconnectedFromCore() +{ + _contextMenuActionProvider->disconnectedFromCore(); + _toolBarActionProvider->disconnectedFromCore(); + AbstractUi::disconnectedFromCore(); +} - if(type == NET::Dock || type == NET::TopMenu) - continue; // obscured by dock or topmenu -> ignore - if(perform) { - KWindowSystem::raiseWindow(mainWidget()->winId()); - KWindowSystem::activateWindow(mainWidget()->winId()); - } - return true; +bool GraphicalUi::eventFilter(QObject *obj, QEvent *event) +{ +#ifdef Q_OS_WIN + if (obj == mainWidget() && event->type() == QEvent::ActivationChange) { + _dwTickCount = GetTickCount(); } +#endif + return AbstractUi::eventFilter(obj, event); +} + - //not on current desktop? - if(!info1.isOnCurrentDesktop()) { - if(perform) - KWindowSystem::activateWindow(mainWidget()->winId()); - return true; +// NOTE: Window activation stuff seems to work just fine in Plasma 5 without requiring X11 hacks. +// TODO: Evaluate cleaning all this up once we can get rid of Qt4/KDE4 + +// Code taken from KStatusNotifierItem for handling minimize/restore + +bool GraphicalUi::checkMainWidgetVisibility(bool perform) +{ +#ifdef Q_OS_WIN + // the problem is that we lose focus when the systray icon is activated + // and we don't know the former active window + // therefore we watch for activation event and use our stopwatch :) + if (GetTickCount() - _dwTickCount < 300) { + // we were active in the last 300ms -> hide it + if (perform) + minimizeRestore(false); + return false; + } + else { + if (perform) + minimizeRestore(true); + return true; } - if(perform) - minimizeRestore(false); // hide - return false; - } +#elif defined(HAVE_KDE4) && defined(Q_WS_X11) + KWindowInfo info1 = KWindowSystem::windowInfo(mainWidget()->winId(), NET::XAWMState | NET::WMState | NET::WMDesktop); + // mapped = visible (but possibly obscured) + bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized(); + + // - not mapped -> show, raise, focus + // - mapped + // - obscured -> raise, focus + // - not obscured -> hide + //info1.mappingState() != NET::Visible -> window on another desktop? + if (!mapped) { + if (perform) + minimizeRestore(true); + return true; + } + else { + QListIterator it(KWindowSystem::stackingOrder()); + it.toBack(); + while (it.hasPrevious()) { + WId id = it.previous(); + if (id == mainWidget()->winId()) + break; + + KWindowInfo info2 = KWindowSystem::windowInfo(id, NET::WMDesktop | NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType); + + if (info2.mappingState() != NET::Visible) + continue; // not visible on current desktop -> ignore + + if (!info2.geometry().intersects(mainWidget()->geometry())) + continue; // not obscuring the window -> ignore + + if (!info1.hasState(NET::KeepAbove) && info2.hasState(NET::KeepAbove)) + continue; // obscured by window kept above -> ignore + + NET::WindowType type = info2.windowType(NET::NormalMask | NET::DesktopMask + | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask + | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask); + + if (type == NET::Dock || type == NET::TopMenu) + continue; // obscured by dock or topmenu -> ignore + + if (perform) { + KWindowSystem::raiseWindow(mainWidget()->winId()); + KWindowSystem::activateWindow(mainWidget()->winId()); + } + return true; + } + + //not on current desktop? + if (!info1.isOnCurrentDesktop()) { + if (perform) + KWindowSystem::activateWindow(mainWidget()->winId()); + return true; + } + + if (perform) + minimizeRestore(false); // hide + return false; + } #else - if(!mainWidget()->isVisible() || mainWidget()->isMinimized()) { - if(perform) - minimizeRestore(true); - return true; - } else { - if(perform) - minimizeRestore(false); - return false; - } + if (!mainWidget()->isVisible() || mainWidget()->isMinimized() || !mainWidget()->isActiveWindow()) { + if (perform) + minimizeRestore(true); + return true; + } + else { + if (perform) + minimizeRestore(false); + return false; + } #endif - return true; + return true; } -bool GraphicalUi::isMainWidgetVisible() { - return !instance()->checkMainWidgetVisibility(false); + +bool GraphicalUi::isMainWidgetVisible() +{ + return !instance()->checkMainWidgetVisibility(false); } -void GraphicalUi::minimizeRestore(bool show) { - if(show) - activateMainWidget(); - else - hideMainWidget(); + +void GraphicalUi::minimizeRestore(bool show) +{ + if (show) + activateMainWidget(); + else + hideMainWidget(); } -void GraphicalUi::activateMainWidget() { -#ifdef HAVE_KDE + +void GraphicalUi::activateMainWidget() +{ +#ifdef HAVE_KDE4 # ifdef Q_WS_X11 KWindowInfo info = KWindowSystem::windowInfo(mainWidget()->winId(), NET::WMDesktop | NET::WMFrameExtents); - if(_onAllDesktops) { - KWindowSystem::setOnAllDesktops(mainWidget()->winId(), true); - } else { - KWindowSystem::setCurrentDesktop(info.desktop()); + if (_onAllDesktops) { + KWindowSystem::setOnAllDesktops(mainWidget()->winId(), true); + } + else { + KWindowSystem::setCurrentDesktop(info.desktop()); } mainWidget()->move(info.frameGeometry().topLeft()); // avoid placement policies @@ -218,38 +285,41 @@ void GraphicalUi::activateMainWidget() { KWindowSystem::forceActiveWindow(mainWidget()->winId()); # endif -#else /* HAVE_KDE */ +#else /* HAVE_KDE4 */ #ifdef Q_WS_X11 - // Bypass focus stealing prevention - QX11Info::setAppUserTime(QX11Info::appTime()); + // Bypass focus stealing prevention + QX11Info::setAppUserTime(QX11Info::appTime()); #endif - if(mainWidget()->windowState() & Qt::WindowMinimized) { - // restore - mainWidget()->setWindowState((mainWidget()->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); - } + if (mainWidget()->windowState() & Qt::WindowMinimized) { + // restore + mainWidget()->setWindowState((mainWidget()->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); + } - // this does not actually work on all platforms... and causes more evil than good - // mainWidget()->move(mainWidget()->frameGeometry().topLeft()); // avoid placement policies - mainWidget()->show(); - mainWidget()->raise(); - mainWidget()->activateWindow(); + // this does not actually work on all platforms... and causes more evil than good + // mainWidget()->move(mainWidget()->frameGeometry().topLeft()); // avoid placement policies + mainWidget()->show(); + mainWidget()->raise(); + mainWidget()->activateWindow(); -#endif /* HAVE_KDE */ +#endif /* HAVE_KDE4 */ } -void GraphicalUi::hideMainWidget() { -#if defined(HAVE_KDE) && defined(Q_WS_X11) - KWindowInfo info = KWindowSystem::windowInfo(mainWidget()->winId(), NET::WMDesktop | NET::WMFrameExtents); - _onAllDesktops = info.onAllDesktops(); +void GraphicalUi::hideMainWidget() +{ +#if defined(HAVE_KDE4) && defined(Q_WS_X11) + KWindowInfo info = KWindowSystem::windowInfo(mainWidget()->winId(), NET::WMDesktop | NET::WMFrameExtents); + _onAllDesktops = info.onAllDesktops(); #endif - if(instance()->isHidingMainWidgetAllowed()) - mainWidget()->hide(); + if (instance()->isHidingMainWidgetAllowed()) + mainWidget()->hide(); } -void GraphicalUi::toggleMainWidget() { - instance()->checkMainWidgetVisibility(true); + +void GraphicalUi::toggleMainWidget() +{ + instance()->checkMainWidgetVisibility(true); }