31
34
#include <X11/Xlib.h>
32
35
#include <X11/Xatom.h>
36
#include <libwnck/libwnck.h>
39
#define GOBJECT_CALLBACK0(callbackName, slot) \
41
callbackName(GObject* src, void* dummy1, QObject* dst) \
43
QMetaObject::invokeMethod(dst, slot); \
46
GOBJECT_CALLBACK0(activeWorkspaceChangedCB, "onActiveWorkspaceChanged");
48
37
Unity2DDeclarativeView::Unity2DDeclarativeView(QWidget *parent) :
49
QDeclarativeView(parent),
38
QGraphicsView(parent),
50
39
m_screenInfo(NULL),
51
40
m_useOpenGL(false),
52
41
m_transparentBackground(false),
53
m_last_focused_window(None)
46
setOptimizationFlags(QGraphicsView::DontSavePainterState);
47
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
48
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
49
setFrameStyle(NoFrame);
51
setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
52
scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
53
viewport()->setFocusPolicy(Qt::NoFocus);
54
setFocusPolicy(Qt::StrongFocus);
56
scene()->setStickyFocus(true);
55
58
if (!QFileInfo(UNITY_2D_SCHEMA_FILE).exists()) {
56
59
m_useOpenGL = false;
58
61
m_useOpenGL = unity2dConfiguration().property("useOpengl").toBool();
61
WnckScreen* screen = wnck_screen_get_default();
62
g_signal_connect(G_OBJECT(screen), "active_workspace_changed", G_CALLBACK(activeWorkspaceChangedCB), this);
71
QDeclarativeEngine* Unity2DDeclarativeView::engine()
73
static QDeclarativeEngine* engine = new QDeclarativeEngine();
77
QDeclarativeContext* Unity2DDeclarativeView::rootContext() const
79
return engine()->rootContext();
82
QDeclarativeItem* Unity2DDeclarativeView::rootObject() const
87
void Unity2DDeclarativeView::forceActivateWindow()
89
forceActivateWindow(effectiveWinId(), this);
92
void Unity2DDeclarativeView::setSource(const QUrl &source, const QMap<const char*, QVariant> &rootObjectProperties)
94
QDeclarativeComponent* component = new QDeclarativeComponent(engine(), source, this);
95
QObject *instance = component->beginCreate(rootContext());
96
if (component->isError()) {
97
qDebug() << component->errors();
99
QMap<const char*, QVariant>::const_iterator it = rootObjectProperties.begin();
100
QMap<const char*, QVariant>::const_iterator itEnd = rootObjectProperties.end();
101
for ( ; it != itEnd; ++it) {
102
instance->setProperty(it.key(), it.value());
104
component->completeCreate();
105
m_rootItem = qobject_cast<QDeclarativeItem *>(instance);
106
connect(m_rootItem, SIGNAL(widthChanged()), SLOT(resizeToRootObject()));
107
connect(m_rootItem, SIGNAL(heightChanged()), SLOT(resizeToRootObject()));
108
resizeToRootObject();
109
m_scene.addItem(m_rootItem);
113
void Unity2DDeclarativeView::resizeToRootObject()
115
QSize size(m_rootItem->width(), m_rootItem->height());
117
setSceneRect(QRectF(0, 0, size.width(), size.height()));
118
Q_EMIT sceneResized(size);
71
121
bool Unity2DDeclarativeView::useOpenGL() const
73
123
return m_useOpenGL;
105
160
QPoint Unity2DDeclarativeView::globalPosition() const
107
return mapToGlobal(QPoint(0,0));
162
// FIXME This used to be mapToGlobal(QPoint(0,0)) that is the correct
163
// thing for all kind of widgets, but seems to fail sometimes if we
164
// call it just after a moveEvent, which is bad
165
// Since all our Unity2DDeclarativeView are toplevel windows we
166
// are workarounding it by just returning pos()
110
170
void Unity2DDeclarativeView::setupViewport()
165
225
void Unity2DDeclarativeView::showEvent(QShowEvent* event)
167
QDeclarativeView::showEvent(event);
227
QGraphicsView::showEvent(event);
168
228
Q_EMIT visibleChanged(true);
171
231
void Unity2DDeclarativeView::hideEvent(QHideEvent* event)
173
QDeclarativeView::hideEvent(event);
233
QGraphicsView::hideEvent(event);
174
234
Q_EMIT visibleChanged(false);
177
/* Obtaining & Discarding Keyboard Focus for Window on Demand
179
* In the X world, activating a window means to give it the input (keyboard)
180
* focus. When a new window opens, X usually makes it active immediately.
181
* Clicking on a window makes it active too.
183
* Qt does not have the capability to explicitly ask the window manager to
184
* make an existing window active - setFocus() only forwards input focus to
185
* whatever QWidget you specify.
187
* De-Activating a window is not possible with X (and hence with Qt). So
188
* we work-around this by remembering which application is active prior to
189
* stealing focus, and then Re-Activating it when we're finished. This is
190
* not guaranteed to succeed, as previous window may have closed.
192
* The following methods deal with these tasks. Note that when the window
193
* has been activated (deactivated), Qt will realise it has obtained (lost)
194
* focus and act appropriately.
197
/* Ask Window Manager to activate this window and hence get keyboard focus */
198
void Unity2DDeclarativeView::forceActivateWindow()
200
// Save reference to window with current keyboard focus
201
if( m_last_focused_window == None ){
205
// Show this window by giving it keyboard focus
206
forceActivateThisWindow(this->effectiveWinId());
209
/* Ask Window Manager to deactivate this window - not guaranteed to succeed. */
210
void Unity2DDeclarativeView::forceDeactivateWindow()
212
if( m_last_focused_window == None ){
213
UQ_WARNING << "No previously focused window found, use mouse to select window.";
217
// What if previously focused window closed while we we had focus? Check if window
218
// exists by seeing if it has attributes.
220
XWindowAttributes attributes;
221
status = XGetWindowAttributes(QX11Info::display(), m_last_focused_window, &attributes);
222
if ( status == BadWindow ){
223
UQ_WARNING << "Previously focused window has gone, use mouse to select window.";
227
// Show this window by giving it keyboard focus
228
forceActivateThisWindow(m_last_focused_window);
230
m_last_focused_window = None;
233
void Unity2DDeclarativeView::forceActivateThisWindow(WId window)
237
void Unity2DDeclarativeView::keyPressEvent(QKeyEvent* event)
239
QApplication::sendEvent(scene(), event);
242
void Unity2DDeclarativeView::keyReleaseEvent(QKeyEvent* event)
244
QApplication::sendEvent(scene(), event);
247
void Unity2DDeclarativeView::forceActivateWindow(WId window, QWidget *w)
235
249
/* Workaround focus stealing prevention implemented by some window
236
250
managers such as Compiz. This is the exact same code you will find in
264
278
/* Use Qt's setFocus mechanism as a safety guard in case the above failed */
268
/* Save WId of window with keyboard focus to m_last_focused_window */
269
void Unity2DDeclarativeView::saveActiveWindow()
271
Display* display = QX11Info::display();
273
int current_focus_state;
275
XGetInputFocus(display, &active_window, ¤t_focus_state);
276
if( active_window != this->effectiveWinId()){
277
m_last_focused_window = active_window;
281
void Unity2DDeclarativeView::onActiveWorkspaceChanged()
283
m_last_focused_window = None;
284
Q_EMIT activeWorkspaceChanged();