~timo-jyrinki/ubuntu/trusty/maliit-framework/fix_qt52

« back to all changes in this revision

Viewing changes to src/mimremotewindow.cpp

  • Committer: Package Import Robot
  • Author(s): Ricardo Salveti de Araujo, Sergio Schvezov, Ricardo Salveti de Araujo
  • Date: 2013-07-23 19:47:04 UTC
  • mfrom: (1.1.2) (1.2.1 experimental)
  • Revision ID: package-import@ubuntu.com-20130723194704-1lsy1kmlda069cea
Tags: 0.99.0+git20130615+97e8335-0ubuntu1
[ Sergio Schvezov ]
* New build from HEAD 97e8335.
* Packaging import from lp:phablet-extras/maliit-framework.

[ Ricardo Salveti de Araujo ]
* debian/control: adding vcs and fixing dependencies
* General package cleanup

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* * This file is part of Maliit framework *
2
 
 *
3
 
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4
 
 * All rights reserved.
5
 
 *
6
 
 * Contact: maliit-discuss@lists.maliit.org
7
 
 *
8
 
 * This library is free software; you can redistribute it and/or
9
 
 * modify it under the terms of the GNU Lesser General Public
10
 
 * License version 2.1 as published by the Free Software Foundation
11
 
 * and appearing in the file LICENSE.LGPL included in the packaging
12
 
 * of this file.
13
 
 */
14
 
 
15
 
#include "mimremotewindow.h"
16
 
#include "mimserveroptions.h"
17
 
 
18
 
#include <QDebug>
19
 
#include <QX11Info>
20
 
 
21
 
#include "mimxapplication.h"
22
 
#include "mimxerrortrap.h"
23
 
 
24
 
#include <X11/X.h>
25
 
#include <X11/Xlib.h>
26
 
#include <X11/Xutil.h>
27
 
#include <X11/extensions/Xcomposite.h>
28
 
#include <X11/extensions/Xdamage.h>
29
 
 
30
 
#ifdef Q_WS_MAEMO_5
31
 
# include <X11/Xatom.h>
32
 
#endif
33
 
 
34
 
namespace {
35
 
 
36
 
Atom wmStateAtom()
37
 
{
38
 
#ifdef Q_WS_MAEMO_5
39
 
// MB doesn't update WM_STATE when window is iconified, so, as a
40
 
// workaround, we monitor _MB_CURRENT_APP_WINDOW. This points to wid
41
 
// when on FullScreen/Active
42
 
# define ICONIFIED_ATOM_NAME "_MB_CURRENT_APP_WINDOW"
43
 
#else
44
 
# define ICONIFIED_ATOM_NAME "WM_STATE"
45
 
#endif
46
 
    static const Atom stateAtom = XInternAtom(QX11Info::display(), ICONIFIED_ATOM_NAME, false);
47
 
 
48
 
    return stateAtom;
49
 
}
50
 
 
51
 
}
52
 
 
53
 
MImRemoteWindow::MImRemoteWindow(WId window,
54
 
                                 MImXServerLogic *serverLogic,
55
 
                                 const MImServerXOptions &options) :
56
 
    QObject(0),
57
 
    wid(window),
58
 
    xpixmap(0),
59
 
    damage(0),
60
 
    pixmap(),
61
 
    redirected(false),
62
 
    xOptions(options),
63
 
    mServerLogic(serverLogic)
64
 
{
65
 
}
66
 
 
67
 
MImRemoteWindow::~MImRemoteWindow()
68
 
{
69
 
    XSelectInput(QX11Info::display(), wid, 0);
70
 
    unredirect();
71
 
}
72
 
 
73
 
void MImRemoteWindow::setIMWidget(const QWidget *widget)
74
 
{
75
 
    XSetTransientForHint(QX11Info::display(),
76
 
                         widget->effectiveWinId(),
77
 
                         wid);
78
 
 
79
 
    // Using PropertyChangeMask is a work-around for NB#172722 (a WONTFIX):
80
 
    XSelectInput(QX11Info::display(),
81
 
                 wid,
82
 
                 StructureNotifyMask | PropertyChangeMask);
83
 
}
84
 
 
85
 
bool MImRemoteWindow::wasIconified(XEvent *ev) const
86
 
{
87
 
    if (PropertyNotify != ev->type) {
88
 
        return false;
89
 
    }
90
 
 
91
 
    if (ev->xproperty.atom == wmStateAtom()) {
92
 
        return isIconified();
93
 
    }
94
 
 
95
 
    return false;
96
 
}
97
 
 
98
 
bool MImRemoteWindow::isIconified() const
99
 
{
100
 
    Atom type;
101
 
    int format;
102
 
    unsigned long length;
103
 
    unsigned long after;
104
 
    unsigned long *state;
105
 
    uchar *data = 0;
106
 
 
107
 
#ifdef Q_WS_MAEMO_5
108
 
# define REAL_ATOM XA_WINDOW
109
 
# define IS_ICONIFIED(_X) _X != wid
110
 
#else
111
 
# define REAL_ATOM AnyPropertyType
112
 
# define IS_ICONIFIED(_X) _X == IconicState
113
 
#endif
114
 
 
115
 
    int queryResult = XGetWindowProperty(QX11Info::display(), wid, wmStateAtom(), 0, 2,
116
 
                                         false, REAL_ATOM, &type, &format, &length,
117
 
                                         &after, &data);
118
 
    state = reinterpret_cast<unsigned long *>(data);
119
 
 
120
 
    bool result = (queryResult == Success && data && format == 32 && IS_ICONIFIED(*state));
121
 
 
122
 
    if (data) {
123
 
        XFree(data);
124
 
    }
125
 
 
126
 
    return result;
127
 
}
128
 
 
129
 
 
130
 
bool MImRemoteWindow::wasUnmapped(XEvent *ev) const
131
 
{
132
 
    return (ev->type == UnmapNotify &&
133
 
            ev->xunmap.event == wid);
134
 
}
135
 
 
136
 
void MImRemoteWindow::setupDamage()
137
 
{
138
 
    destroyDamage();
139
 
 
140
 
    damage = XDamageCreate(QX11Info::display(), wid, XDamageReportNonEmpty);
141
 
}
142
 
 
143
 
void MImRemoteWindow::destroyDamage()
144
 
{
145
 
    if (damage == 0)
146
 
        return;
147
 
 
148
 
    XDamageDestroy(QX11Info::display(), damage);
149
 
    damage = 0;
150
 
}
151
 
 
152
 
void MImRemoteWindow::redirect()
153
 
{
154
 
    if (redirected)
155
 
        return;
156
 
 
157
 
    if (xOptions.manualRedirection) {
158
 
        MImXErrorTrap xerror(mServerLogic->compositeExtension(), X_CompositeRedirectWindow);
159
 
        XCompositeRedirectWindow(QX11Info::display(),
160
 
                                 wid,
161
 
                                 CompositeRedirectManual);
162
 
        if (xerror.untrap() == BadAccess)
163
 
            qDebug() << "Window " << wid << " was already redirected";
164
 
    }
165
 
 
166
 
    redirected = true;
167
 
 
168
 
    setupPixmap();
169
 
    setupDamage();
170
 
 
171
 
    Q_EMIT contentUpdated(QRegion(QRect(QPoint(), pixmap.size())));
172
 
}
173
 
 
174
 
void MImRemoteWindow::unredirect()
175
 
{
176
 
    if (!redirected)
177
 
        return;
178
 
 
179
 
    redirected = false;
180
 
 
181
 
    destroyDamage();
182
 
    destroyPixmap();
183
 
 
184
 
    if (xOptions.manualRedirection) {
185
 
        MImXErrorTrap xerror(mServerLogic->compositeExtension(), X_CompositeUnredirectWindow);
186
 
        XCompositeUnredirectWindow(QX11Info::display(),
187
 
                                   wid,
188
 
                                   CompositeRedirectManual);
189
 
        if (xerror.untrap() == BadAccess)
190
 
            qDebug() << "Window " << wid << " was not redirected";
191
 
    }
192
 
}
193
 
 
194
 
void MImRemoteWindow::handleEvent(XEvent *event)
195
 
{
196
 
    handleConfigureNotifyEvent(event);
197
 
    handleDamageEvent(event);
198
 
}
199
 
 
200
 
void MImRemoteWindow::handleConfigureNotifyEvent(XEvent *event)
201
 
{
202
 
    if (event->type != ConfigureNotify)
203
 
        return;
204
 
 
205
 
    XConfigureEvent *e = &event->xconfigure;
206
 
 
207
 
    if (e->window != wid)
208
 
        return;
209
 
 
210
 
    resetPixmap();
211
 
}
212
 
 
213
 
void MImRemoteWindow::resetPixmap()
214
 
{
215
 
    if (redirected)
216
 
        setupPixmap();
217
 
}
218
 
 
219
 
void MImRemoteWindow::update(const QRegion &region)
220
 
{
221
 
    Q_EMIT contentUpdated(region);
222
 
}
223
 
 
224
 
void MImRemoteWindow::handleDamageEvent(XEvent *event)
225
 
{
226
 
    if (event->type != mServerLogic->damageExtension().eventBase() + XDamageNotify)
227
 
        return;
228
 
 
229
 
    XDamageNotifyEvent *e = reinterpret_cast<XDamageNotifyEvent*>(event);
230
 
 
231
 
    if (damage != e->damage)
232
 
        return;
233
 
 
234
 
    XserverRegion parts = XFixesCreateRegion(QX11Info::display(), 0, 0);
235
 
    XDamageSubtract(QX11Info::display(), e->damage, None, parts);
236
 
 
237
 
    QRegion region;
238
 
 
239
 
    int nrects;
240
 
    XRectangle *rects = XFixesFetchRegion(QX11Info::display(), parts, &nrects);
241
 
    if (rects) {
242
 
        for (int i = 0; i < nrects; ++i) {
243
 
            region += QRect(rects[i].x, rects[i].y, rects[i].width, rects[i].height);
244
 
        }
245
 
    }
246
 
    free(rects);
247
 
 
248
 
    XFixesDestroyRegion(QX11Info::display(), parts);
249
 
 
250
 
    // setup remote pixmap when it failed before
251
 
    if (pixmap.isNull())
252
 
        setupPixmap();
253
 
 
254
 
    Q_EMIT contentUpdated(region);
255
 
}
256
 
 
257
 
void MImRemoteWindow::setupPixmap()
258
 
{
259
 
    destroyPixmap();
260
 
 
261
 
    MImXErrorTrap error(mServerLogic->compositeExtension(), X_CompositeNameWindowPixmap);
262
 
    xpixmap = XCompositeNameWindowPixmap(QX11Info::display(), wid);
263
 
    if (error.untrap() == BadMatch) {
264
 
        qDebug() << "Cannot get offscreen reference for Window " << wid;
265
 
        xpixmap = 0;
266
 
        return;
267
 
    }
268
 
 
269
 
    if (xpixmap != 0) {
270
 
        pixmap = QPixmap::fromX11Pixmap(xpixmap, QPixmap::ExplicitlyShared);
271
 
    }
272
 
}
273
 
 
274
 
void MImRemoteWindow::destroyPixmap()
275
 
{
276
 
    if (MImXApplication::instance())
277
 
        pixmap = QPixmap();
278
 
 
279
 
    if (xpixmap != 0) {
280
 
        XFreePixmap(QX11Info::display(), xpixmap);
281
 
        xpixmap = 0;
282
 
    }
283
 
}
284
 
 
285
 
const QPixmap &MImRemoteWindow::windowPixmap() const
286
 
{
287
 
    // setup remote pixmap when it failed before
288
 
    if (redirected && pixmap.isNull()) {
289
 
        const_cast<MImRemoteWindow*>(this)->setupPixmap();
290
 
    }
291
 
 
292
 
    return pixmap;
293
 
}