~sil2100/unity-2d/precise-security

« back to all changes in this revision

Viewing changes to launcher/app/visibilitycontroller.cpp

  • Committer: Florian Boucault
  • Date: 2012-02-06 19:38:07 UTC
  • mto: This revision was merged to the branch mainline in revision 897.
  • Revision ID: florian@boucault.net-20120206193807-7u5ezdcl5m58bcvw
Support running installed inside a directory that is a symlink.

isRunningInstalled() is made more reliable by resolving all symlinks contained
in the installation path.
Header inclusions were shuffled around to respect the best practice to include
from the more local to the more global headers and to solve a compilation error
as a result.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of unity-2d
 
3
 *
 
4
 * Copyright 2011 Canonical Ltd.
 
5
 *
 
6
 * Authors:
 
7
 * - Aurélien Gâteau <aurelien.gateau@canonical.com>
 
8
 *
 
9
 * This program is free software; you can redistribute it and/or modify
 
10
 * it under the terms of the GNU General Public License as published by
 
11
 * the Free Software Foundation; version 3.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License
 
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
// Self
 
22
#include "visibilitycontroller.h"
 
23
 
 
24
// Local
 
25
#include <autohidebehavior.h>
 
26
#include <forcevisiblebehavior.h>
 
27
#include <intellihidebehavior.h>
 
28
 
 
29
// unity-2d
 
30
#include <debug_p.h>
 
31
#include <unity2dpanel.h>
 
32
#include <config.h>
 
33
 
 
34
// Qt
 
35
#include <QDBusConnection>
 
36
#include <QDBusServiceWatcher>
 
37
 
 
38
VisibilityController::VisibilityController(Unity2dPanel* panel)
 
39
: QObject(panel)
 
40
, m_panel(panel)
 
41
, m_dbusWatcher(new QDBusServiceWatcher(this))
 
42
{
 
43
    m_dbusWatcher->setConnection(QDBusConnection::sessionBus());
 
44
    m_dbusWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
 
45
 
 
46
    connect(&launcher2dConfiguration(), SIGNAL(hideModeChanged(int)), SLOT(update()));
 
47
    connect(m_panel, SIGNAL(manualSlidingChanged(bool)), SLOT(update()));
 
48
    connect(m_dbusWatcher, SIGNAL(serviceUnregistered(const QString&)), SLOT(slotServiceUnregistered(const QString&)));
 
49
    update();
 
50
}
 
51
 
 
52
VisibilityController::~VisibilityController()
 
53
{
 
54
}
 
55
 
 
56
void VisibilityController::update(UpdateReason reason)
 
57
{
 
58
    if (!m_forceVisibleCountHash.isEmpty()) {
 
59
        return;
 
60
    }
 
61
    AutoHideMode mode = AutoHideMode(launcher2dConfiguration().property("hideMode").toInt());
 
62
 
 
63
    setBehavior(0);
 
64
 
 
65
    /* Do not use any hiding controller if the panel is being slid manually */
 
66
    if (!m_panel->manualSliding()) {
 
67
        switch (mode) {
 
68
        case ManualHide:
 
69
            m_panel->setUseStrut(true);
 
70
            m_panel->slideIn();
 
71
            break;
 
72
        case AutoHide:
 
73
            m_panel->setUseStrut(false);
 
74
            setBehavior(new AutoHideBehavior(m_panel));
 
75
            break;
 
76
        case IntelliHide:
 
77
            m_panel->setUseStrut(false);
 
78
            setBehavior(new IntelliHideBehavior(m_panel));
 
79
            if (reason == UpdateFromForceVisibilityEnded && !m_panel->geometry().contains(QCursor::pos())) {
 
80
                // The first thing IntelliHideBehavior does is checking if there is
 
81
                // a window behind the panel, and if there is one, hide the panel immediately
 
82
                // This is correct for some cases, but in the case we come from an update because the
 
83
                // panel is not forced visible anymore and the mouse is not in the panel,
 
84
                // i.e. the launcher was visible and the user clicked in an action of the tile menu,
 
85
                // we should still give the user the wait 1 second before hiding behaviour.
 
86
                // To achieve this we tell the behaviour controller to show the panel
 
87
                // and simulate a mouse leave on the panel to start the hiding timer
 
88
                QMetaObject::invokeMethod(m_behavior.data(), "showPanel");
 
89
                QEvent e(QEvent::Leave);
 
90
                QCoreApplication::sendEvent(m_panel, &e);
 
91
            }
 
92
            break;
 
93
        }
 
94
    }
 
95
}
 
96
 
 
97
void VisibilityController::beginForceVisible(const QString& service)
 
98
{
 
99
    bool wasEmpty = m_forceVisibleCountHash.isEmpty();
 
100
    if (m_forceVisibleCountHash.contains(service)) {
 
101
        ++m_forceVisibleCountHash[service];
 
102
    } else {
 
103
        m_forceVisibleCountHash[service] = 1;
 
104
        if (!service.isEmpty()) {
 
105
            m_dbusWatcher->addWatchedService(service);
 
106
        }
 
107
    }
 
108
    if (wasEmpty) {
 
109
        setBehavior(new ForceVisibleBehavior(m_panel));
 
110
    }
 
111
}
 
112
 
 
113
void VisibilityController::endForceVisible(const QString& service)
 
114
{
 
115
    if (m_forceVisibleCountHash.contains(service)) {
 
116
        if (m_forceVisibleCountHash[service] == 1) {
 
117
            m_forceVisibleCountHash.remove(service);
 
118
            m_dbusWatcher->removeWatchedService(service);
 
119
        } else {
 
120
            --m_forceVisibleCountHash[service];
 
121
        }
 
122
    } else {
 
123
        UQ_WARNING << "Application" << service << "called endForceVisible() more than beginForceVisible().";
 
124
    }
 
125
    if (m_forceVisibleCountHash.isEmpty()) {
 
126
        update(UpdateFromForceVisibilityEnded);
 
127
    }
 
128
}
 
129
 
 
130
void VisibilityController::setBehavior(AbstractVisibilityBehavior* behavior)
 
131
{
 
132
    // This method could be replaced by code calling reset() directly but
 
133
    // having only one point where the behavior is changed makes it easy to log
 
134
    // behavior changes using something like: UQ_VAR(behavior);
 
135
    m_behavior.reset(behavior);
 
136
    if (behavior != NULL) {
 
137
        connect(behavior, SIGNAL(visibleChanged(bool)), SLOT(updatePanelVisibility(bool)));
 
138
        updatePanelVisibility(behavior->visible());
 
139
    }
 
140
}
 
141
 
 
142
void VisibilityController::updatePanelVisibility(bool visible)
 
143
{
 
144
    if (visible) {
 
145
        m_panel->slideIn();
 
146
    } else {
 
147
        m_panel->slideOut();
 
148
    }
 
149
}
 
150
 
 
151
void VisibilityController::slotServiceUnregistered(const QString& service)
 
152
{
 
153
    if (!m_forceVisibleCountHash.contains(service)) {
 
154
        return;
 
155
    }
 
156
 
 
157
    UQ_WARNING << "Application" << service << "quit without calling endForceVisible().";
 
158
    m_forceVisibleCountHash.remove(service);
 
159
    m_dbusWatcher->removeWatchedService(service);
 
160
    if (m_forceVisibleCountHash.isEmpty()) {
 
161
        update(UpdateFromForceVisibilityEnded);
 
162
    }
 
163
}