2
* This file is part of unity-2d
4
* Copyright 2011 Canonical Ltd.
7
* - Aurélien Gâteau <aurelien.gateau@canonical.com>
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.
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.
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/>.
22
#include "visibilitycontroller.h"
25
#include <autohidebehavior.h>
26
#include <forcevisiblebehavior.h>
27
#include <intellihidebehavior.h>
31
#include <unity2dpanel.h>
35
#include <QDBusConnection>
36
#include <QDBusServiceWatcher>
38
VisibilityController::VisibilityController(Unity2dPanel* panel)
41
, m_dbusWatcher(new QDBusServiceWatcher(this))
43
m_dbusWatcher->setConnection(QDBusConnection::sessionBus());
44
m_dbusWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
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&)));
52
VisibilityController::~VisibilityController()
56
void VisibilityController::update(UpdateReason reason)
58
if (!m_forceVisibleCountHash.isEmpty()) {
61
AutoHideMode mode = AutoHideMode(launcher2dConfiguration().property("hideMode").toInt());
65
/* Do not use any hiding controller if the panel is being slid manually */
66
if (!m_panel->manualSliding()) {
69
m_panel->setUseStrut(true);
73
m_panel->setUseStrut(false);
74
setBehavior(new AutoHideBehavior(m_panel));
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);
97
void VisibilityController::beginForceVisible(const QString& service)
99
bool wasEmpty = m_forceVisibleCountHash.isEmpty();
100
if (m_forceVisibleCountHash.contains(service)) {
101
++m_forceVisibleCountHash[service];
103
m_forceVisibleCountHash[service] = 1;
104
if (!service.isEmpty()) {
105
m_dbusWatcher->addWatchedService(service);
109
setBehavior(new ForceVisibleBehavior(m_panel));
113
void VisibilityController::endForceVisible(const QString& service)
115
if (m_forceVisibleCountHash.contains(service)) {
116
if (m_forceVisibleCountHash[service] == 1) {
117
m_forceVisibleCountHash.remove(service);
118
m_dbusWatcher->removeWatchedService(service);
120
--m_forceVisibleCountHash[service];
123
UQ_WARNING << "Application" << service << "called endForceVisible() more than beginForceVisible().";
125
if (m_forceVisibleCountHash.isEmpty()) {
126
update(UpdateFromForceVisibilityEnded);
130
void VisibilityController::setBehavior(AbstractVisibilityBehavior* behavior)
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());
142
void VisibilityController::updatePanelVisibility(bool visible)
151
void VisibilityController::slotServiceUnregistered(const QString& service)
153
if (!m_forceVisibleCountHash.contains(service)) {
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);