~tiagosh/unity-2d/fix-dash-cursor

« back to all changes in this revision

Viewing changes to launcher/app/launcherview.cpp

  • Committer: Tarmac
  • Author(s): Albert Astals, Ugo Riboni, Michał Sawicz, Florian Boucault, LDS
  • Date: 2012-02-10 17:32:14 UTC
  • mfrom: (771.3.235 unity-2d-shell_trunk)
  • Revision ID: tarmac-20120210173214-eekg5uiqdb7gjza6
Merge launcher and dash into a common new QML scene: the shell.
 - Created a shell folder that holds both launcher and dash QML code, the C++ code for the single binary and a common folder with shared QML files
 - The shell occupies the whole screen but is shaped for input where it is transparent in order not to interfere with the rest of the windows
 - The shell binary, unity-2d-shell, has a -rootqml option that lets the user specify the QML file to load
 - Implement visibility behaviours in QML instead of C++
 - Do not use D-Bus anymore to communicate between the launcher and the dash
 - Remove the homebutton panel plugin
 - Make the strut setting reusable outside of Unity2dPanel
 - Make LauncherDropItem a FocusScope
 - Implement gesture handling in QML instead of C++

Known issues:
 - In non composited mode there is a 1px wide rectangle on the edge of the screen where the launcher is hidden. This is acceptable for the moment since XFixes barriers to show the launcher are in the plan and will get rid of this problem
 - HomeShortcuts.qml has a transparent Rectangle to fix alignment in RTL mode that causes QML warnings. This is acceptable since the Home lens is going away. Fixes: . Approved by .

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2010 Canonical, Ltd.
3
 
 *
4
 
 * Authors:
5
 
 *  Olivier Tilloy <olivier.tilloy@canonical.com>
6
 
 *
7
 
 * This program is free software; you can redistribute it and/or modify
8
 
 * it under the terms of the GNU General Public License as published by
9
 
 * the Free Software Foundation; version 3.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#include "launcherview.h"
21
 
 
22
 
#include <config.h>
23
 
#include <keyboardmodifiersmonitor.h>
24
 
#include <hotkey.h>
25
 
#include <hotkeymonitor.h>
26
 
#include <keymonitor.h>
27
 
#include <screeninfo.h>
28
 
#include <debug_p.h>
29
 
 
30
 
#include <QApplication>
31
 
#include <QDesktopWidget>
32
 
#include <QX11Info>
33
 
#include <QDebug>
34
 
#include <QGraphicsObject>
35
 
 
36
 
#include <QtDeclarative/qdeclarative.h>
37
 
#include <QDeclarativeEngine>
38
 
#include <QDeclarativeContext>
39
 
#include <QDeclarativeImageProvider>
40
 
#include <QtDBus/QDBusInterface>
41
 
#include <QtDBus/QDBusPendingCall>
42
 
#include <QtDBus/QDBusReply>
43
 
#include <QtDBus/QDBusConnectionInterface>
44
 
 
45
 
#include <X11/Xlib.h>
46
 
#include <X11/Xatom.h>
47
 
 
48
 
static const int KEY_HOLD_THRESHOLD = 250;
49
 
 
50
 
static const char* DASH_DBUS_SERVICE = "com.canonical.Unity2d.Dash";
51
 
static const char* DASH_DBUS_PATH = "/Dash";
52
 
static const char* DASH_DBUS_INTERFACE = "com.canonical.Unity2d.Dash";
53
 
static const char* SPREAD_DBUS_SERVICE = "com.canonical.Unity2d.Spread";
54
 
static const char* SPREAD_DBUS_PATH = "/Spread";
55
 
static const char* SPREAD_DBUS_INTERFACE = "com.canonical.Unity2d.Spread";
56
 
 
57
 
static const char* DASH_DBUS_PROPERTY_ACTIVE = "active";
58
 
static const char* DASH_DBUS_METHOD_ACTIVATE_HOME = "activateHome";
59
 
static const char* SPREAD_DBUS_METHOD_IS_SHOWN = "IsShown";
60
 
static const char* COMMANDS_LENS_ID = "commands.lens";
61
 
 
62
 
LauncherView::LauncherView(QWidget* parent) :
63
 
    Unity2DDeclarativeView(parent),
64
 
    m_superKeyPressed(false), m_superKeyHeld(false)
65
 
{
66
 
    setTransparentBackground(QX11Info::isCompositingManagerRunning());
67
 
 
68
 
    m_superKeyHoldTimer.setSingleShot(true);
69
 
    m_superKeyHoldTimer.setInterval(KEY_HOLD_THRESHOLD);
70
 
    connect(&m_superKeyHoldTimer, SIGNAL(timeout()), SLOT(updateSuperKeyHoldState()));
71
 
    connect(this, SIGNAL(superKeyTapped()), SLOT(toggleDash()));
72
 
 
73
 
    m_screenInfo = new ScreenInfo(ScreenInfo::TopLeft, this);
74
 
 
75
 
    connect(&launcher2dConfiguration(), SIGNAL(superKeyEnableChanged(bool)), SLOT(updateSuperKeyMonitoring()));
76
 
    updateSuperKeyMonitoring();
77
 
 
78
 
    /* Alt+F1 toggle the keyboard focus between laucher and other(previous) application. */
79
 
    Hotkey* altF1 = HotkeyMonitor::instance().getHotkeyFor(Qt::Key_F1, Qt::AltModifier);
80
 
    connect(altF1, SIGNAL(pressed()), SLOT(onAltF1Pressed()));
81
 
 
82
 
    /* Alt+F2 shows the dash with the commands lens activated. */
83
 
    Hotkey* altF2 = HotkeyMonitor::instance().getHotkeyFor(Qt::Key_F2, Qt::AltModifier);
84
 
    connect(altF2, SIGNAL(pressed()), SLOT(showCommandsLens()));
85
 
 
86
 
    /* Super+S before 'Spread'ing, close all the contextual menus/tooltips in the launcher. */
87
 
    Hotkey* superS = HotkeyMonitor::instance().getHotkeyFor(Qt::Key_S, Qt::MetaModifier);
88
 
    connect(superS, SIGNAL(pressed()), SLOT(onSuperSPressed()));
89
 
 
90
 
    /* Super+{n} for 0 ≤ n ≤ 9 activates the item with index (n + 9) % 10. */
91
 
    for (Qt::Key key = Qt::Key_0; key <= Qt::Key_9; key = (Qt::Key) (key + 1)) {
92
 
        Hotkey* hotkey = HotkeyMonitor::instance().getHotkeyFor(key, Qt::MetaModifier);
93
 
        connect(hotkey, SIGNAL(pressed()), SLOT(forwardNumericHotkey()));
94
 
        hotkey = HotkeyMonitor::instance().getHotkeyFor(key, Qt::MetaModifier | Qt::ShiftModifier);
95
 
        connect(hotkey, SIGNAL(pressed()), SLOT(forwardNumericHotkey()));
96
 
    }
97
 
}
98
 
 
99
 
LauncherView::~LauncherView()
100
 
{
101
 
}
102
 
 
103
 
void
104
 
LauncherView::focusInEvent(QFocusEvent* event)
105
 
{
106
 
    QDeclarativeView::focusInEvent(event);
107
 
    Q_EMIT focusChanged(true);
108
 
}
109
 
 
110
 
void
111
 
LauncherView::focusOutEvent(QFocusEvent* event)
112
 
{
113
 
    QDeclarativeView::focusOutEvent(event);
114
 
    Q_EMIT focusChanged(false);
115
 
}
116
 
 
117
 
void
118
 
LauncherView::updateSuperKeyMonitoring()
119
 
{
120
 
    KeyboardModifiersMonitor *modifiersMonitor = KeyboardModifiersMonitor::instance();
121
 
    KeyMonitor *keyMonitor = KeyMonitor::instance();
122
 
    HotkeyMonitor& hotkeyMonitor = HotkeyMonitor::instance();
123
 
 
124
 
    QVariant value = launcher2dConfiguration().property("superKeyEnable");
125
 
    if (!value.isValid() || value.toBool() == true) {
126
 
        hotkeyMonitor.enableModifiers(Qt::MetaModifier);
127
 
        QObject::connect(modifiersMonitor,
128
 
                         SIGNAL(keyboardModifiersChanged(Qt::KeyboardModifiers)),
129
 
                         this, SLOT(setHotkeysForModifiers(Qt::KeyboardModifiers)));
130
 
        /* Ignore Super presses if another key was pressed simultaneously
131
 
           (i.e. a shortcut). https://bugs.launchpad.net/unity-2d/+bug/801073 */
132
 
        QObject::connect(keyMonitor,
133
 
                         SIGNAL(keyPressed()),
134
 
                         this, SLOT(ignoreSuperPress()));
135
 
        setHotkeysForModifiers(modifiersMonitor->keyboardModifiers());
136
 
    } else {
137
 
        hotkeyMonitor.disableModifiers(Qt::MetaModifier);
138
 
        QObject::disconnect(modifiersMonitor,
139
 
                            SIGNAL(keyboardModifiersChanged(Qt::KeyboardModifiers)),
140
 
                            this, SLOT(setHotkeysForModifiers(Qt::KeyboardModifiers)));
141
 
        QObject::disconnect(keyMonitor,
142
 
                            SIGNAL(keyPressed()),
143
 
                            this, SLOT(ignoreSuperPress()));
144
 
        m_superKeyHoldTimer.stop();
145
 
        m_superKeyPressed = false;
146
 
        if (m_superKeyHeld) {
147
 
            m_superKeyHeld = false;
148
 
            Q_EMIT superKeyHeldChanged(false);
149
 
        }
150
 
    }
151
 
}
152
 
 
153
 
void
154
 
LauncherView::setHotkeysForModifiers(Qt::KeyboardModifiers modifiers)
155
 
{
156
 
    /* This is the new new state of the Super key (AKA Meta key), while
157
 
       m_superKeyPressed is the previous state of the key at the last modifiers change. */
158
 
    bool superKeyPressed = modifiers.testFlag(Qt::MetaModifier);
159
 
 
160
 
    if (m_superKeyPressed != superKeyPressed) {
161
 
        m_superKeyPressed = superKeyPressed;
162
 
        if (superKeyPressed) {
163
 
            m_superPressIgnored = false;
164
 
            /* If the key is pressed, start up a timer to monitor if it's being held short
165
 
               enough to qualify as just a "tap" or as a proper hold */
166
 
            m_superKeyHoldTimer.start();
167
 
        } else {
168
 
            m_superKeyHoldTimer.stop();
169
 
 
170
 
            /* If the key is released, and was not being held, it means that the user just
171
 
               performed a "tap". Unless we're told to ignore that tap, that is. */
172
 
            if (!m_superKeyHeld && !m_superPressIgnored) {
173
 
                Q_EMIT superKeyTapped();
174
 
            }
175
 
            /* Otherwise the user just terminated a hold. */
176
 
            else if(m_superKeyHeld){
177
 
                m_superKeyHeld = false;
178
 
                Q_EMIT superKeyHeldChanged(m_superKeyHeld);
179
 
            }
180
 
        }
181
 
    }
182
 
}
183
 
 
184
 
void
185
 
LauncherView::updateSuperKeyHoldState()
186
 
{
187
 
    /* If the key was released in the meantime, just do nothing, otherwise
188
 
       consider the key being held, unless we're told to ignore it. */
189
 
    if (m_superKeyPressed && !m_superPressIgnored) {
190
 
        m_superKeyHeld = true;
191
 
        Q_EMIT superKeyHeldChanged(m_superKeyHeld);
192
 
    }
193
 
}
194
 
 
195
 
void
196
 
LauncherView::ignoreSuperPress()
197
 
{
198
 
    /* There was a key pressed, ignore current super tap/hold */
199
 
    m_superPressIgnored = true;
200
 
}
201
 
 
202
 
void
203
 
LauncherView::forwardNumericHotkey()
204
 
{
205
 
    Hotkey* hotkey = qobject_cast<Hotkey*>(sender());
206
 
    if (hotkey != NULL) {
207
 
        /* Shortcuts from 1 to 9 should activate the items with index
208
 
           from 1 to 9 (index 0 being the so-called "BFB" or Dash launcher).
209
 
           Shortcut for 0 should activate item with index 10.
210
 
           In other words, the indexes are activated in the same order as
211
 
           the keys appear on a standard keyboard. */
212
 
        Qt::Key key = hotkey->key();
213
 
        if (key >= Qt::Key_1 && key <= Qt::Key_9) {
214
 
            int index = key - Qt::Key_0;
215
 
            if (hotkey->modifiers() & Qt::ShiftModifier) {
216
 
                Q_EMIT newInstanceShortcutPressed(index);
217
 
            } else {
218
 
                Q_EMIT activateShortcutPressed(index);
219
 
            }
220
 
        } else if (key == Qt::Key_0) {
221
 
            if (hotkey->modifiers() & Qt::ShiftModifier) {
222
 
                Q_EMIT newInstanceShortcutPressed(10);
223
 
            } else {
224
 
                Q_EMIT activateShortcutPressed(10);
225
 
            }
226
 
        }
227
 
    }
228
 
}
229
 
 
230
 
void
231
 
LauncherView::toggleDash()
232
 
{
233
 
    QDBusInterface dashInterface(DASH_DBUS_SERVICE, DASH_DBUS_PATH, DASH_DBUS_INTERFACE);
234
 
 
235
 
    QVariant dashActiveResult = dashInterface.property(DASH_DBUS_PROPERTY_ACTIVE);
236
 
    if (!dashActiveResult.isValid()) {
237
 
        UQ_WARNING << "Can't read the DBUS Dash property" << DASH_DBUS_PROPERTY_ACTIVE
238
 
                   << "on" << DASH_DBUS_SERVICE << DASH_DBUS_PATH << DASH_DBUS_INTERFACE;
239
 
        return;
240
 
    }
241
 
 
242
 
    bool dashActive = dashActiveResult.toBool();
243
 
    if (dashActive) {
244
 
        if (!dashInterface.setProperty(DASH_DBUS_PROPERTY_ACTIVE, false)) {
245
 
            UQ_WARNING << "Can't set the DBUS Dash property" << DASH_DBUS_PROPERTY_ACTIVE
246
 
                       << "on" << DASH_DBUS_SERVICE << DASH_DBUS_PATH << DASH_DBUS_INTERFACE;
247
 
        }
248
 
    } else {
249
 
        /* Check if the spread is active before activating the dash.
250
 
           We need to do this since the spread can't prevent the launcher from
251
 
           monitoring the super key and therefore getting to this point if
252
 
           it's tapped. */
253
 
 
254
 
        /* Check if the spread is present on DBUS first, as we don't want to have DBUS
255
 
           activate it if it's not running yet */
256
 
        QDBusConnectionInterface* sessionBusIFace = QDBusConnection::sessionBus().interface();
257
 
        QDBusReply<bool> reply = sessionBusIFace->isServiceRegistered(SPREAD_DBUS_SERVICE);
258
 
        if (reply.isValid() && reply.value() == true) {
259
 
            QDBusInterface spreadInterface(SPREAD_DBUS_SERVICE, SPREAD_DBUS_PATH,
260
 
                                           SPREAD_DBUS_INTERFACE);
261
 
 
262
 
            QDBusReply<bool> spreadActiveResult = spreadInterface.call(SPREAD_DBUS_METHOD_IS_SHOWN);
263
 
            if (spreadActiveResult.isValid() && spreadActiveResult.value() == true) {
264
 
                return;
265
 
            }
266
 
        }
267
 
 
268
 
        dashInterface.asyncCall(DASH_DBUS_METHOD_ACTIVATE_HOME);
269
 
    }
270
 
}
271
 
 
272
 
void
273
 
LauncherView::showCommandsLens()
274
 
{
275
 
    QDBusInterface dashInterface(DASH_DBUS_SERVICE, DASH_DBUS_PATH, DASH_DBUS_INTERFACE);
276
 
    dashInterface.asyncCall("activateLens", COMMANDS_LENS_ID);
277
 
}
278
 
 
279
 
/* BUGFIX:881458 */
280
 
void
281
 
LauncherView::onSuperSPressed()
282
 
{
283
 
    QGraphicsObject* launcher = rootObject();
284
 
    QMetaObject::invokeMethod(launcher, "hideMenu", Qt::AutoConnection);
285
 
}
286
 
 
287
 
void
288
 
LauncherView::onAltF1Pressed()
289
 
{
290
 
    QGraphicsObject* launcher = rootObject();
291
 
 
292
 
    if (hasFocus()) {
293
 
        QMetaObject::invokeMethod(launcher, "hideMenu", Qt::AutoConnection);
294
 
        forceDeactivateWindow();
295
 
    } else {
296
 
        forceActivateWindow();
297
 
        QMetaObject::invokeMethod(launcher, "focusBFB", Qt::AutoConnection);
298
 
    }
299
 
}