~ubuntu-branches/ubuntu/precise/unity-2d/precise-updates

« back to all changes in this revision

Viewing changes to panel/applets/common/indicatorsmanager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2011-08-25 18:16:57 UTC
  • mfrom: (1.1.19 upstream)
  • Revision ID: james.westby@ubuntu.com-20110825181657-opb29rqsxae3i98f
Tags: 4.2.0-0ubuntu1
* New upstream release:
  - [panel] application menus do not appear on first hover after dismissal
    (lp: #825262)
  - [dash] Lens icons badly scaled (lp: #825368)
  - [panel] indicators are shifted offscreen to the right (lp: #827673)
  - [panel] scrubbing from system indicators to menubar should be possible
    (lp: #706903)
  - [launcher] Closed applications don't get their launcher counts cleared
    (lp: #767367)
  - [dash] selected item should not be underlined but use the same 
    treatment as unity (lp: #817456)
  - [dash] categories should be collapsed by default (lp: #827214)
  - [dash] Ratings filter (lp: #831855)
  - [dash] Multirange filter (lp: #831856)
  - [dash] ToggleButton filter (lp: #831857)
  - [dash] Icon size must be bigger to match the mockups (lp: #831858)
  - [dash] "Refine search" right margin should be 15 pixels (lp: #832058)
  - [dash] "Refine search" should be "Filter results" (lp: #832060)
  - [dash] Font sizes should match new design (lp: #832114)
  - [panel] Glitch: application menu appearing when pressing the BFB 
    (lp: #825060)
  - [panel] Glitch: application menus are quickly opened after a drag gesture
    (lp: #825267)
  - [dash] File thumbnails aspect ratio is not respected (lp: #832204)
* debian/control: require current the current versions of nux and unity

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 "indicatorsmanager.h"
23
 
 
24
 
// Local
25
 
#include <debug_p.h>
26
 
#include <indicatorentrywidget.h>
27
 
 
28
 
// Qt
29
 
#include <QApplication>
30
 
#include <QTimer>
31
 
#include <QX11Info>
32
 
 
33
 
// X11
34
 
#include <X11/Xlib.h>
35
 
 
36
 
using namespace unity::indicator;
37
 
 
38
 
IndicatorsManager::IndicatorsManager(QObject* parent)
39
 
: QObject(parent)
40
 
, m_indicators(new DBusIndicators)
41
 
, m_geometrySyncTimer(new QTimer(this))
42
 
, m_mouseTrackerTimer(new QTimer(this))
43
 
{
44
 
    m_geometrySyncTimer->setInterval(0);
45
 
    m_geometrySyncTimer->setSingleShot(true);
46
 
    connect(m_geometrySyncTimer, SIGNAL(timeout()), SLOT(syncGeometries()));
47
 
 
48
 
    // m_mouseTrackerTimer is inspired from
49
 
    // plugins/unityshell/src/PanelView.cpp in OnEntryActivated()
50
 
    //
51
 
    // Rationale copied from Unity source code:
52
 
    // """
53
 
    // Track menus being scrubbed at 60Hz (about every 16 millisec)
54
 
    // It might sound ugly, but it's far nicer (and more responsive) than the
55
 
    // code it replaces which used to capture motion events in another process
56
 
    // (unity-panel-service) and send them to us over dbus.
57
 
    // NOTE: The reason why we have to use a timer instead of tracking motion
58
 
    // events is because the motion events will never be delivered to this
59
 
    // process. All the motion events will go to unity-panel-service while
60
 
    // scrubbing because the active panel menu has (needs) the pointer grab.
61
 
    // """
62
 
    m_mouseTrackerTimer->setInterval(16);
63
 
    m_mouseTrackerTimer->setSingleShot(false);
64
 
    connect(m_mouseTrackerTimer, SIGNAL(timeout()), SLOT(checkMousePosition()));
65
 
 
66
 
    m_indicators->on_entry_show_menu.connect(
67
 
        sigc::mem_fun(this, &IndicatorsManager::onEntryShowMenu)
68
 
        );
69
 
 
70
 
    m_indicators->on_entry_activate_request.connect(
71
 
        sigc::mem_fun(this, &IndicatorsManager::onEntryActivateRequest)
72
 
        );
73
 
 
74
 
    m_indicators->on_entry_activated.connect(
75
 
        sigc::mem_fun(this, &IndicatorsManager::onEntryActivated)
76
 
        );
77
 
 
78
 
    m_indicators->on_synced.connect(
79
 
        sigc::mem_fun(this, &IndicatorsManager::onSynced)
80
 
        );
81
 
}
82
 
 
83
 
unity::indicator::DBusIndicators::Ptr IndicatorsManager::indicators() const
84
 
{
85
 
    return m_indicators;
86
 
}
87
 
 
88
 
void IndicatorsManager::onEntryShowMenu(const std::string& /*entryId*/, int posX, int posY, int /*timestamp*/, int /*button*/)
89
 
{
90
 
    // Copied from plugins/unityshell/src/PanelView.cpp, in OnEntryShowMenu()
91
 
    // Without this code, menus cannot be shown from mousePressEvent() (but can
92
 
    // be shown from mouseReleaseEvent())
93
 
    /*
94
 
    Neil explanation:
95
 
    On button down, X automatically gives Qt a passive grab on the mouse this
96
 
    means that, if the panel service tries to grab the pointer to show the menu
97
 
    (gtk does this automatically), it fails and the menu can't show.
98
 
    We connect to the on_entry_show_menu signal, which is emitted before
99
 
    DBusIndicators does anything else, and just break the grab.
100
 
    */
101
 
    Display* display = QX11Info::display();
102
 
    XUngrabPointer(display, CurrentTime);
103
 
    XFlush(display);
104
 
 
105
 
    XButtonEvent event = {
106
 
        ButtonRelease,
107
 
        0,
108
 
        False,
109
 
        display,
110
 
        0,
111
 
        0,
112
 
        0,
113
 
        CurrentTime,
114
 
        posX, posY,
115
 
        posX, posY,
116
 
        0,
117
 
        Button1,
118
 
        True
119
 
    };
120
 
    qApp->x11ProcessEvent(reinterpret_cast<XEvent*>(&event));
121
 
}
122
 
 
123
 
void IndicatorsManager::checkMousePosition()
124
 
{
125
 
    // Called by m_mouseTrackerTimer to implement mouse scrubbing
126
 
    // (Assuming item A menu is opened, move mouse over item B => item B menu opens)
127
 
    QWidget* widget = QApplication::widgetAt(QCursor::pos());
128
 
    IndicatorEntryWidget* entryWidget = qobject_cast<IndicatorEntryWidget*>(widget);
129
 
    if (!entryWidget) {
130
 
        return;
131
 
    }
132
 
    entryWidget->showMenu(Qt::NoButton);
133
 
}
134
 
 
135
 
void IndicatorsManager::onEntryActivateRequest(const std::string& entryId)
136
 
{
137
 
    if (entryId.empty()) {
138
 
        return;
139
 
    }
140
 
    IndicatorEntryWidget* widget = 0;
141
 
    Q_FOREACH(widget, m_widgetList) {
142
 
        if (widget->entry()->id() == entryId) {
143
 
            break;
144
 
        }
145
 
    }
146
 
    if (!widget) {
147
 
        UQ_WARNING << "Could not find a widget for IndicatorEntry with id" << QString::fromStdString(entryId);
148
 
        return;
149
 
    }
150
 
    widget->showMenu(Qt::NoButton);
151
 
}
152
 
 
153
 
void IndicatorsManager::onEntryActivated(const std::string& entryId)
154
 
{
155
 
    if (entryId.empty()) {
156
 
        m_mouseTrackerTimer->stop();
157
 
    } else {
158
 
        m_mouseTrackerTimer->start();
159
 
    }
160
 
}
161
 
 
162
 
void IndicatorsManager::onSynced()
163
 
{
164
 
    QMetaObject::invokeMethod(m_geometrySyncTimer, "start", Qt::QueuedConnection);
165
 
}
166
 
 
167
 
void IndicatorsManager::addIndicatorEntryWidget(IndicatorEntryWidget* widget)
168
 
{
169
 
    m_widgetList.append(widget);
170
 
    widget->installEventFilter(this);
171
 
}
172
 
 
173
 
bool IndicatorsManager::eventFilter(QObject*, QEvent* event)
174
 
{
175
 
    switch (event->type()) {
176
 
    case QEvent::Show:
177
 
    case QEvent::Hide:
178
 
    case QEvent::Move:
179
 
    case QEvent::Resize:
180
 
        m_geometrySyncTimer->start();
181
 
        break;
182
 
    default:
183
 
        break;
184
 
    }
185
 
    return false;
186
 
}
187
 
 
188
 
void IndicatorsManager::syncGeometries()
189
 
{
190
 
    EntryLocationMap locations;
191
 
    Q_FOREACH(IndicatorEntryWidget* widget, m_widgetList) {
192
 
        if (!widget->isVisible()) {
193
 
            continue;
194
 
        }
195
 
        Entry::Ptr entry = widget->entry();
196
 
        if (entry->IsUnused()) {
197
 
            continue;
198
 
        }
199
 
        QPoint topLeft = widget->mapToGlobal(QPoint(0, 0));
200
 
        nux::Rect rect(topLeft.x(), topLeft.y(), widget->width(), widget->height());
201
 
        locations[widget->entry()->id()] = rect;
202
 
    }
203
 
    m_indicators->SyncGeometries("Panel", locations);
204
 
}
205
 
 
206
 
#include "indicatorsmanager.moc"