23
26
#include "actioncollection.h"
24
27
#include "contextmenuactionprovider.h"
33
# include <KWindowInfo>
34
# include <KWindowSystem>
37
GraphicalUi *GraphicalUi::_instance = 0;
26
38
QWidget *GraphicalUi::_mainWidget = 0;
27
39
QHash<QString, ActionCollection *> GraphicalUi::_actionCollections;
28
40
ContextMenuActionProvider *GraphicalUi::_contextMenuActionProvider = 0;
29
41
ToolBarActionProvider *GraphicalUi::_toolBarActionProvider = 0;
30
42
UiStyle *GraphicalUi::_uiStyle = 0;
32
GraphicalUi::GraphicalUi(QObject *parent) : AbstractUi(parent)
43
bool GraphicalUi::_onAllDesktops = false;
45
GraphicalUi::GraphicalUi(QObject *parent) : AbstractUi(parent) {
54
void GraphicalUi::init() {
56
mainWidget()->installEventFilter(this);
37
60
ActionCollection *GraphicalUi::actionCollection(const QString &category) {
59
82
void GraphicalUi::setUiStyle(UiStyle *style) {
86
bool GraphicalUi::eventFilter(QObject *obj, QEvent *event) {
88
if(obj == mainWidget() && event->type() == QEvent::ActivationChange) {
89
_dwTickCount = GetTickCount();
92
return AbstractUi::eventFilter(obj, event);
95
// Code taken from KStatusNotifierItem for handling minimize/restore
97
bool GraphicalUi::checkMainWidgetVisibility(bool perform) {
99
// the problem is that we lose focus when the systray icon is activated
100
// and we don't know the former active window
101
// therefore we watch for activation event and use our stopwatch :)
102
if(GetTickCount() - _dwTickCount < 300) {
103
// we were active in the last 300ms -> hide it
105
minimizeRestore(false);
109
minimizeRestore(true);
113
#elif defined(HAVE_KDE) && defined(Q_WS_X11)
114
KWindowInfo info1 = KWindowSystem::windowInfo(mainWidget()->winId(), NET::XAWMState | NET::WMState | NET::WMDesktop);
115
// mapped = visible (but possibly obscured)
116
bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized();
118
// - not mapped -> show, raise, focus
120
// - obscured -> raise, focus
121
// - not obscured -> hide
122
//info1.mappingState() != NET::Visible -> window on another desktop?
125
minimizeRestore(true);
129
QListIterator< WId > it (KWindowSystem::stackingOrder());
131
while(it.hasPrevious()) {
132
WId id = it.previous();
133
if(id == mainWidget()->winId())
136
KWindowInfo info2 = KWindowSystem::windowInfo(id, NET::WMDesktop | NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType);
138
if(info2.mappingState() != NET::Visible)
139
continue; // not visible on current desktop -> ignore
141
if(!info2.geometry().intersects(mainWidget()->geometry()))
142
continue; // not obscuring the window -> ignore
144
if(!info1.hasState(NET::KeepAbove) && info2.hasState(NET::KeepAbove))
145
continue; // obscured by window kept above -> ignore
147
NET::WindowType type = info2.windowType(NET::NormalMask | NET::DesktopMask
148
| NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
149
| NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask);
151
if(type == NET::Dock || type == NET::TopMenu)
152
continue; // obscured by dock or topmenu -> ignore
155
KWindowSystem::raiseWindow(mainWidget()->winId());
156
KWindowSystem::activateWindow(mainWidget()->winId());
161
//not on current desktop?
162
if(!info1.isOnCurrentDesktop()) {
164
KWindowSystem::activateWindow(mainWidget()->winId());
169
minimizeRestore(false); // hide
174
if(!mainWidget()->isVisible() || mainWidget()->isMinimized()) {
176
minimizeRestore(true);
180
minimizeRestore(false);
189
bool GraphicalUi::isMainWidgetVisible() {
190
return !instance()->checkMainWidgetVisibility(false);
193
void GraphicalUi::minimizeRestore(bool show) {
195
activateMainWidget();
200
void GraphicalUi::activateMainWidget() {
203
KWindowInfo info = KWindowSystem::windowInfo(mainWidget()->winId(), NET::WMDesktop | NET::WMFrameExtents);
205
KWindowSystem::setOnAllDesktops(mainWidget()->winId(), true);
207
KWindowSystem::setCurrentDesktop(info.desktop());
210
mainWidget()->move(info.frameGeometry().topLeft()); // avoid placement policies
211
mainWidget()->show();
212
mainWidget()->raise();
213
KWindowSystem::raiseWindow(mainWidget()->winId());
214
KWindowSystem::activateWindow(mainWidget()->winId());
216
mainWidget()->show();
217
KWindowSystem::raiseWindow(mainWidget()->winId());
218
KWindowSystem::forceActiveWindow(mainWidget()->winId());
224
// Bypass focus stealing prevention
225
QX11Info::setAppUserTime(QX11Info::appTime());
228
if(mainWidget()->windowState() & Qt::WindowMinimized) {
230
mainWidget()->setWindowState((mainWidget()->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
233
// this does not actually work on all platforms... and causes more evil than good
234
// mainWidget()->move(mainWidget()->frameGeometry().topLeft()); // avoid placement policies
235
mainWidget()->show();
236
mainWidget()->raise();
237
mainWidget()->activateWindow();
239
#endif /* HAVE_KDE */
242
void GraphicalUi::hideMainWidget() {
244
#if defined(HAVE_KDE) && defined(Q_WS_X11)
245
KWindowInfo info = KWindowSystem::windowInfo(mainWidget()->winId(), NET::WMDesktop | NET::WMFrameExtents);
246
_onAllDesktops = info.onAllDesktops();
249
if(instance()->isHidingMainWidgetAllowed())
250
mainWidget()->hide();
253
void GraphicalUi::toggleMainWidget() {
254
instance()->checkMainWidgetVisibility(true);