Remove MeegoGraphicsSystem support
[maliit:maliit-framework.git] / src / mimxserverlogic.cpp
1 /* * This file is part of meego-im-framework *
2  *
3  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4  * All rights reserved.
5  * Contact: Nokia Corporation (directui@nokia.com)
6  *
7  * If you have questions regarding the use of this file, please contact
8  * Nokia at directui@nokia.com.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License version 2.1 as published by the Free Software Foundation
13  * and appearing in the file LICENSE.LGPL included in the packaging
14  * of this file.
15  */
16
17 #include "mimxserverlogic.h"
18
19 #include "mpassthruwindow.h"
20 #include "mimremotewindow.h"
21 #include "mimxextension.h"
22 #include "mimrotationanimation.h"
23
24 #include "mimxapplication.h"
25 #include "mimpluginsproxywidget.h"
26 #include "mimrotationanimation.h"
27 #include "mimserveroptions.h"
28
29 #include <QDebug>
30
31 #include <X11/Xlib.h>
32
33 namespace
34 {
35     class ConfigureForCompositing {
36
37     public:
38         ConfigureForCompositing(const MImServerXOptions &newOptions)
39             : options(newOptions)
40         {
41         }
42
43         bool operator()(QWidget *w)
44         {
45             if (not w) {
46                 return false;
47             }
48
49             w->setAttribute(Qt::WA_OpaquePaintEvent);
50             w->setAttribute(Qt::WA_NoSystemBackground);
51             w->setAutoFillBackground(false);
52             // Be aware that one cannot verify whether the background role *is*
53             // QPalette::NoRole - see QTBUG-17924.
54             w->setBackgroundRole(QPalette::NoRole);
55
56             if (!options.selfComposited) {
57                 // Careful: This flag can trigger a call to
58                 // qt_x11_recreateNativeWidgetsRecursive
59                 // - which will crash when it tries to get the effective WId
60                 // (as none of widgets have been mapped yet).
61                 w->setAttribute(Qt::WA_TranslucentBackground);
62             }
63
64             return true;
65         }
66
67     private:
68         const MImServerXOptions &options;
69
70     };
71
72
73 }
74
75 MImXServerLogic::MImXServerLogic(const MImServerXOptions &options, QObject *parent) :
76     MImAbstractServerLogic(parent),
77     xOptions(options),
78     mBackgroundSuppressed(false),
79     mCompositeExtension(),
80     mDamageExtension(),
81     mPassThruWindow(),
82     mRemoteWindow()
83 {
84     mPassThruWindow.reset(new MPassThruWindow(this, xOptions));
85     mPluginsProxyWidget.reset(new MImPluginsProxyWidget(mPassThruWindow.data()));
86     mRotationAnimation = new MImRotationAnimation(pluginsProxyWidget(), passThruWindow(),
87                                                   this, xOptions);
88
89     configureWidgetsForCompositing();
90 }
91
92 MImXServerLogic::~MImXServerLogic()
93 {
94 }
95
96 void MImXServerLogic::finalize()
97 {
98     // Cannot destroy QWidgets or QPixmaps during MIMApplication destruction.
99     // Hence the finalize handler that runs before the d'tor.
100     mPluginsProxyWidget.reset();
101     mPassThruWindow.reset();
102     mRemoteWindow.reset();
103 }
104
105 bool MImXServerLogic::selfCompositionSupported()
106 {
107     return mCompositeExtension.supported(0, 2) && mDamageExtension.supported();
108 }
109
110 void MImXServerLogic::x11EventFilter(XEvent *ev)
111 {
112     handleTransientEvents(ev);
113     handleRemoteWindowEvents(ev);
114     handlePassThruMapEvent(ev);
115 }
116
117 void MImXServerLogic::handleTransientEvents(XEvent *ev)
118 {
119     if (not mRemoteWindow.data()) {
120         return;
121     }
122
123     if (mRemoteWindow->wasIconified(ev) || mRemoteWindow->wasUnmapped(ev)) {
124         qDebug() << "MImX11ServerLogic" << __PRETTY_FUNCTION__
125                  << "Remote window was destroyed or iconified - hiding.";
126
127         Q_EMIT remoteWindowChanged(0);
128         Q_EMIT applicationWindowGone();
129         mRemoteWindow.reset();
130     }
131 }
132
133 void MImXServerLogic::handleRemoteWindowEvents(XEvent *event)
134 {
135     if (not mRemoteWindow.data()) {
136         return;
137     }
138
139     mRemoteWindow->handleEvent(event);
140 }
141
142 void MImXServerLogic::handlePassThruMapEvent(XEvent *ev)
143 {
144     if (ev->type != MapNotify)
145         return;
146
147     if (ev->xmap.window != mPassThruWindow->effectiveWinId())
148         return;
149
150     if (not mRemoteWindow.data()) {
151         qWarning() << __PRETTY_FUNCTION__
152                    << "No remote window found, but passthru window was mapped.";
153         return;
154     }
155
156     mRemoteWindow->resetPixmap();
157 }
158
159 void MImXServerLogic::applicationFocusChanged(WId newRemoteWinId)
160 {
161     if (0 == newRemoteWinId) {
162         return;
163     }
164
165     if (mRemoteWindow.data() && mRemoteWindow->id() == newRemoteWinId) {
166         return;
167     }
168
169     const bool wasRedirected(mRemoteWindow.data() && mRemoteWindow->isRedirected());
170
171     mRemoteWindow.reset(new MImRemoteWindow(newRemoteWinId, this, xOptions));
172     mRemoteWindow->setIMWidget(mPassThruWindow->window());
173
174     connect(mRemoteWindow.data(), SIGNAL(contentUpdated(QRegion)),
175             this,                SLOT(updatePassThruWindow(QRegion)));
176
177     if (wasRedirected) {
178         mRemoteWindow->redirect();
179     }
180
181     Q_EMIT remoteWindowChanged(mRemoteWindow.data());
182 }
183
184 void MImXServerLogic::setSuppressBackground(bool suppress)
185 {
186     mBackgroundSuppressed = suppress;
187 }
188
189 QWidget *MImXServerLogic::passThruWindow() const
190 {
191     return mPassThruWindow.data();
192 }
193
194 QWidget* MImXServerLogic::pluginsProxyWidget() const
195 {
196     return mPluginsProxyWidget.data();
197 }
198
199 const QPixmap &MImXServerLogic::remoteWindowPixmap()
200 {
201     if (not mRemoteWindow.data()
202             || mBackgroundSuppressed
203             || not xOptions.selfComposited) {
204         static const QPixmap empty;
205         return empty;
206     }
207
208     return mRemoteWindow->windowPixmap();
209 }
210
211 void MImXServerLogic::updatePassThruWindow(const QRegion &region)
212 {
213     if (region.isEmpty() || remoteWindowPixmap().isNull()) {
214         qDebug() << "Skipping update request for passthru window.";
215         return;
216     }
217
218     mPassThruWindow->updateFromRemoteWindow(region);
219 }
220
221 void MImXServerLogic::pluginLoaded()
222 {
223     configureWidgetsForCompositing();
224 }
225
226 void MImXServerLogic::configureWidgetsForCompositing()
227 {
228     ConfigureForCompositing visitor(xOptions);
229     visitWidgetHierarchy(visitor, mPassThruWindow.data());
230 }
231
232 void MImXServerLogic::appOrientationAboutToChange(int toAngle) {
233     mRotationAnimation->appOrientationAboutToChange(toAngle);
234 }
235
236 void MImXServerLogic::appOrientationChangeFinished(int toAngle) {
237     mRotationAnimation->appOrientationChangeFinished(toAngle);
238 }
239
240 MImRemoteWindow *MImXServerLogic::remoteWindow() const
241 {
242     return mRemoteWindow.data();
243 }
244
245 void MImXServerLogic::inputPassthrough(const QRegion &region)
246 {
247     mPassThruWindow->inputPassthrough(region);
248 }
249
250 const MImXCompositeExtension& MImXServerLogic::compositeExtension()
251 {
252     return mCompositeExtension;
253 }
254
255 const MImXDamageExtension& MImXServerLogic::damageExtension()
256 {
257     return mDamageExtension;
258 }