~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to plasma/desktop/shell/desktopview.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *   Copyright 2007 Aaron Seigo <aseigo@kde.org>
 
3
 *   Copyright 2007 Matt Broadstone <mbroadst@gmail.com>
 
4
 *   Copyright (c) 2009 Chani Armitage <chani@kde.org>
 
5
 *
 
6
 *   This program is free software; you can redistribute it and/or modify
 
7
 *   it under the terms of the GNU Library General Public License version 2 as
 
8
 *   published by the Free Software Foundation
 
9
 *
 
10
 *   This program is distributed in the hope that it will be useful,
 
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *   GNU General Public License for more details
 
14
 *
 
15
 *   You should have received a copy of the GNU Library General Public
 
16
 *   License along with this program; if not, write to the
 
17
 *   Free Software Foundation, Inc.,
 
18
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
19
 */
 
20
 
 
21
#include "desktopview.h"
 
22
 
 
23
#include <QFile>
 
24
#include <QWheelEvent>
 
25
#include <QCoreApplication>
 
26
 
 
27
#include <KAuthorized>
 
28
#include <KMenu>
 
29
#include <KRun>
 
30
#include <KToggleAction>
 
31
#include <KWindowSystem>
 
32
#include <NETRootInfo>
 
33
 
 
34
#include <Plasma/Applet>
 
35
#include <Plasma/Corona>
 
36
#include <Plasma/Containment>
 
37
#include <Plasma/Svg>
 
38
#include <Plasma/Wallpaper>
 
39
#include <Plasma/Theme>
 
40
 
 
41
#include <kephal/screens.h>
 
42
 
 
43
#include "dashboardview.h"
 
44
#include "desktopcorona.h"
 
45
#include "kactivitycontroller.h"
 
46
#include "plasmaapp.h"
 
47
#include "plasma-shell-desktop.h"
 
48
 
 
49
#ifdef Q_WS_WIN
 
50
#include "windows.h"
 
51
#include "windef.h"
 
52
#include "wingdi.h"
 
53
#include "winuser.h"
 
54
#endif
 
55
 
 
56
DesktopView::DesktopView(Plasma::Containment *containment, int id, QWidget *parent)
 
57
    : Plasma::View(containment, id, parent),
 
58
      m_dashboard(0),
 
59
      m_dashboardFollowsDesktop(true),
 
60
      m_init(false)
 
61
{
 
62
    setAttribute(Qt::WA_TranslucentBackground, false);
 
63
    //setCacheMode(QGraphicsView::CacheNone);
 
64
 
 
65
    /*FIXME: Work around for a (maybe) Qt bug:
 
66
     * QApplication::focusWidget() can't track focus change in QGraphicsProxyWidget
 
67
     *   wrapped normal widget (eg. QLineEdit), if the QGraphicsView has called 
 
68
     *   setFocusPolicy(Qt::NoFocus)
 
69
     * I've created a bug report to Qt Software.
 
70
     * There is also a simple reproduce program in case you're interested in this bug:
 
71
     *   ftp://fearee:public@public.sjtu.edu.cn/reproduce.tar.gz
 
72
     */
 
73
 
 
74
    //setFocusPolicy(Qt::NoFocus);
 
75
#ifdef Q_WS_WIN
 
76
    setWindowFlags(Qt::FramelessWindowHint);
 
77
    SetWindowPos(winId(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 
78
    HWND hwndDesktop = ::FindWindowW(L"Progman", NULL);
 
79
    SetParent(winId(), hwndDesktop);
 
80
#else
 
81
    setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
 
82
#endif
 
83
 
 
84
    checkDesktopAffiliation();
 
85
 
 
86
    KWindowSystem::setType(winId(), NET::Desktop);
 
87
    lower();
 
88
 
 
89
    /*
 
90
    const int w = 25;
 
91
    QPixmap tile(w * 2, w * 2);
 
92
    tile.fill(palette().base().color());
 
93
    QPainter pt(&tile);
 
94
    QColor color = palette().mid().color();
 
95
    color.setAlphaF(.6);
 
96
    pt.fillRect(0, 0, w, w, color);
 
97
    pt.fillRect(w, w, w, w, color);
 
98
    pt.end();
 
99
    QBrush b(tile);
 
100
    setBackgroundBrush(tile);
 
101
    */
 
102
 
 
103
    KConfigGroup cg = config();
 
104
    const uint dashboardContainmentId = cg.readEntry("DashboardContainment", uint(0));
 
105
    m_dashboardFollowsDesktop = dashboardContainmentId == 0;
 
106
 
 
107
    // since Plasma::View has a delayed init we need to
 
108
    // put a delay also for this call in order to be sure
 
109
    // to have correct information set (e.g. screen())
 
110
    if (containment) {
 
111
        QRect geom = PlasmaApp::self()->corona()->screenGeometry(containment->screen());
 
112
        setGeometry(geom);
 
113
    }
 
114
 
 
115
    Kephal::Screens *screens = Kephal::Screens::self();
 
116
    connect(screens, SIGNAL(screenResized(Kephal::Screen *, QSize, QSize)),
 
117
            this, SLOT(screenResized(Kephal::Screen *)));
 
118
    connect(screens, SIGNAL(screenMoved(Kephal::Screen *, QPoint, QPoint)),
 
119
            this, SLOT(screenMoved(Kephal::Screen *)));
 
120
}
 
121
 
 
122
DesktopView::~DesktopView()
 
123
{
 
124
    delete m_dashboard;
 
125
}
 
126
 
 
127
void DesktopView::checkDesktopAffiliation()
 
128
{
 
129
    if (AppSettings::perVirtualDesktopViews()) {
 
130
        m_desktop = containment() ? containment()->desktop() + 1 : -1;
 
131
        kDebug() << "setting to desktop" << m_desktop;
 
132
        KWindowSystem::setOnDesktop(winId(), m_desktop);
 
133
    } else {
 
134
        m_desktop = -1;
 
135
        KWindowSystem::setOnAllDesktops(winId(), true);
 
136
    }
 
137
}
 
138
 
 
139
void DesktopView::toggleDashboard()
 
140
{
 
141
    kDebug() << "toggling dashboard for screen" << screen() << "and destop" << desktop() <<
 
142
        (m_dashboard ? (m_dashboard->isVisible() ? "visible" : "hidden") : "non-existent");
 
143
    prepDashboard();
 
144
    if (m_dashboard) {
 
145
        m_dashboard->toggleVisibility();
 
146
        kDebug() << "toggling dashboard for screen" << screen() << "and destop" << desktop() << m_dashboard->isVisible();
 
147
    }
 
148
}
 
149
 
 
150
void DesktopView::showDashboard(bool show)
 
151
{
 
152
    if (!show && (!m_dashboard || !m_dashboard->isVisible())) {
 
153
        return;
 
154
    }
 
155
 
 
156
    prepDashboard();
 
157
    if (m_dashboard) {
 
158
        m_dashboard->showDashboard(show);
 
159
    }
 
160
}
 
161
 
 
162
void DesktopView::prepDashboard()
 
163
{
 
164
    if (!m_dashboard) {
 
165
        if (!containment()) {
 
166
            return;
 
167
        }
 
168
 
 
169
        KConfigGroup cg = config();
 
170
        Plasma::Containment *dc = dashboardContainment();
 
171
        m_dashboardFollowsDesktop = dc == 0;
 
172
        if (dc) {
 
173
            dc->resize(size());
 
174
            dc->enableAction("remove", false);
 
175
        } else {
 
176
            dc = containment();
 
177
        }
 
178
 
 
179
        m_dashboard = new DashboardView(dc, this);
 
180
        connect(m_dashboard, SIGNAL(dashboardClosed()), this, SIGNAL(dashboardClosed()));
 
181
        m_dashboard->addActions(actions());
 
182
    }
 
183
 
 
184
    //If a separate dashboard is used we must use the screen of this containment instead of the dashboard one
 
185
    if (!m_dashboardFollowsDesktop && containment()) {
 
186
        m_dashboard->setGeometry(PlasmaApp::self()->corona()->screenGeometry(containment()->screen()));
 
187
    }
 
188
}
 
189
 
 
190
Plasma::Containment *DesktopView::dashboardContainment() const
 
191
{
 
192
    KConfigGroup cg = config();
 
193
    Plasma::Containment *dc = 0;
 
194
    const uint containmentId = cg.readEntry("DashboardContainment", uint(0));
 
195
 
 
196
    if (containmentId > 0) {
 
197
        foreach (Plasma::Containment *c, PlasmaApp::self()->corona()->containments()) {
 
198
            if (c->id() == containmentId) {
 
199
                dc = c;
 
200
                break;
 
201
            }
 
202
        }
 
203
    }
 
204
 
 
205
    return dc;
 
206
}
 
207
 
 
208
void DesktopView::setDashboardContainment(Plasma::Containment *containment)
 
209
{
 
210
    if (containment) {
 
211
        config().writeEntry("DashboardContainment", containment->id());
 
212
        if (m_dashboard) {
 
213
            m_dashboard->setContainment(containment);
 
214
        }
 
215
    } else {
 
216
        Plasma::Containment *dc = 0;
 
217
        if (dashboardContainment()) {
 
218
            dc = dashboardContainment();
 
219
        }
 
220
 
 
221
        config().deleteEntry("DashboardContainment");
 
222
        if (m_dashboard) {
 
223
            m_dashboard->setContainment(View::containment());
 
224
        }
 
225
        //destroy this after changing the containment, makes sure the view won't receive the destroyed signal
 
226
        if (dc) {
 
227
            dc->destroy(false);
 
228
        }
 
229
    }
 
230
 
 
231
    m_dashboardFollowsDesktop = containment == 0;
 
232
}
 
233
 
 
234
void DesktopView::screenResized(Kephal::Screen *s)
 
235
{
 
236
    if (s->id() == screen()) {
 
237
        kDebug() << screen();
 
238
        adjustSize();
 
239
    }
 
240
}
 
241
 
 
242
void DesktopView::screenMoved(Kephal::Screen *s)
 
243
{
 
244
    if (s->id() == screen()) {
 
245
        kDebug() << screen();
 
246
        adjustSize();
 
247
    }
 
248
}
 
249
 
 
250
void DesktopView::adjustSize()
 
251
{
 
252
    // adapt to screen resolution changes
 
253
    QRect geom = PlasmaApp::self()->corona()->screenGeometry(screen());
 
254
    kDebug() << "screen" << screen() << "geom" << geom;
 
255
    setGeometry(geom);
 
256
    if (containment()) {
 
257
        containment()->resize(geom.size());
 
258
        kDebug() << "Containment's geom after resize" << containment()->geometry();
 
259
    }
 
260
 
 
261
    if (m_dashboard) {
 
262
        m_dashboard->setGeometry(geom);
 
263
    }
 
264
 
 
265
    kDebug() << "Done" << screen() << geometry();
 
266
}
 
267
 
 
268
bool DesktopView::isDashboardVisible() const
 
269
{
 
270
    return m_dashboard && m_dashboard->isVisible();
 
271
}
 
272
 
 
273
bool DesktopView::dashboardFollowsDesktop() const
 
274
{
 
275
    return m_dashboardFollowsDesktop;
 
276
}
 
277
 
 
278
void DesktopView::setContainment(Plasma::Containment *containment)
 
279
{
 
280
    Plasma::Containment *oldContainment = this->containment();
 
281
    if (m_init && containment == oldContainment) {
 
282
        //kDebug() << "initialized and containment is the same, aborting";
 
283
        return;
 
284
    }
 
285
 
 
286
    m_init = true;
 
287
 
 
288
    if (m_dashboard && m_dashboardFollowsDesktop) {
 
289
        m_dashboard->setContainment(containment);
 
290
    }
 
291
 
 
292
    KConfigGroup viewIds(KGlobal::config(), "ViewIds");
 
293
    if (oldContainment) {
 
294
        disconnect(oldContainment, SIGNAL(toolBoxVisibilityChanged(bool)), this, SLOT(toolBoxOpened(bool)));
 
295
        disconnect(oldContainment, SIGNAL(showAddWidgetsInterface(QPointF)), this, SLOT(showWidgetExplorer()));
 
296
        viewIds.deleteEntry(QString::number(oldContainment->id()));
 
297
    }
 
298
 
 
299
    if (containment) {
 
300
        connect(containment, SIGNAL(toolBoxVisibilityChanged(bool)), this, SLOT(toolBoxOpened(bool)));
 
301
        connect(containment, SIGNAL(showAddWidgetsInterface(QPointF)), this, SLOT(showWidgetExplorer()));
 
302
        viewIds.writeEntry(QString::number(containment->id()), id());
 
303
        if (containment->corona()) {
 
304
            containment->corona()->requestConfigSync();
 
305
        }
 
306
    }
 
307
 
 
308
    View::setContainment(containment);
 
309
}
 
310
 
 
311
void DesktopView::toolBoxOpened(bool open)
 
312
{
 
313
    if (isDashboardVisible()) {
 
314
        return;
 
315
    }
 
316
 
 
317
#ifndef Q_WS_WIN
 
318
    NETRootInfo info(QX11Info::display(), NET::Supported);
 
319
    if (!info.isSupported(NET::WM2ShowingDesktop)) {
 
320
        return;
 
321
    }
 
322
 
 
323
    if (open) {
 
324
        connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)),
 
325
                this, SLOT(showDesktopUntoggled(WId)));
 
326
    } else {
 
327
        disconnect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)),
 
328
                   this, SLOT(showDesktopUntoggled(WId)));
 
329
    }
 
330
 
 
331
    info.setShowingDesktop(open);
 
332
#endif
 
333
}
 
334
 
 
335
void DesktopView::showWidgetExplorer()
 
336
{
 
337
    if (isDashboardVisible()) {
 
338
        return;
 
339
    }
 
340
 
 
341
    Plasma::Containment *c = containment();
 
342
    if (c) {
 
343
        PlasmaApp::self()->showWidgetExplorer(screen(), c);
 
344
    }
 
345
}
 
346
 
 
347
void DesktopView::showDesktopUntoggled(WId id)
 
348
{
 
349
    if (isDashboardVisible()) {
 
350
        return;
 
351
    }
 
352
 
 
353
    Plasma::Containment *c = containment();
 
354
    if (c) {
 
355
        c->setToolBoxOpen(false);
 
356
    }
 
357
 
 
358
    KWindowSystem::activateWindow(id);
 
359
}
 
360
 
 
361
void DesktopView::screenOwnerChanged(int wasScreen, int isScreen, Plasma::Containment* newContainment)
 
362
{
 
363
    if (PlasmaApp::isPanelContainment(newContainment)) {
 
364
        // we don't care about panel containments changing screens on us
 
365
        return;
 
366
    }
 
367
 
 
368
    /*
 
369
    kDebug() << "was:" << wasScreen << "is:" << isScreen << "my screen:" << screen()
 
370
             << "containment:" << (QObject *)newContainment << newContainment->activity()
 
371
             << "current containment" << (QObject *)containment() 
 
372
             << "myself:" << (QObject *)this
 
373
             << "containment desktop:" << newContainment->desktop() << "my desktop:" << m_desktop;
 
374
    */
 
375
 
 
376
    if (containment() == newContainment &&
 
377
        wasScreen == screen() &&
 
378
        (isScreen != wasScreen || AppSettings::perVirtualDesktopViews())) {
 
379
        //kDebug() << "nulling out containment";
 
380
        setContainment(0);
 
381
    }
 
382
 
 
383
    if (isScreen > -1 && isScreen == screen() &&
 
384
        (!AppSettings::perVirtualDesktopViews() || newContainment->desktop() == m_desktop - 1) ) {
 
385
        //kDebug() << "setting new containment";
 
386
        setContainment(newContainment);
 
387
    }
 
388
}
 
389
 
 
390
#include "desktopview.moc"
 
391