1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qplatformdefs.h"
43 
44 #include "qwindowsystem_qws.h"
45 #include "qwsevent_qws.h"
46 #include "qwscommand_qws_p.h"
47 #include "qtransportauth_qws_p.h"
48 #include "qwsutils_qws.h"
49 #include "qwscursor_qws.h"
50 #include "qwsdisplay_qws.h"
51 #include "qmouse_qws.h"
52 #include "qcopchannel_qws.h"
53 #include "qwssocket_qws.h"
54 
55 #include "qapplication.h"
56 #include "private/qapplication_p.h"
57 #include "qsocketnotifier.h"
58 #include "qpolygon.h"
59 #include "qimage.h"
60 #include "qcursor.h"
61 #include <private/qpaintengine_raster_p.h>
62 #include "qscreen_qws.h"
63 #include "qwindowdefs.h"
64 #include "private/qlock_p.h"
65 #include "qwslock_p.h"
66 #include "qfile.h"
67 #include "qtimer.h"
68 #include "qpen.h"
69 #include "qdesktopwidget.h"
70 #include "qevent.h"
71 #include "qinputcontext.h"
72 #include "qpainter.h"
73 
74 #include <qdebug.h>
75 
76 #include "qkbddriverfactory_qws.h"
77 #include "qmousedriverfactory_qws.h"
78 
79 #include <qbuffer.h>
80 #include <qdir.h>
81 
82 #include <private/qwindowsurface_qws_p.h>
83 #include <private/qfontengine_qpf_p.h>
84 
85 #include "qwindowsystem_p.h"
86 
87 
88 #include <stdlib.h>
89 #include <stdio.h>
90 #include <errno.h>
91 
92 #ifndef QT_NO_QWS_MULTIPROCESS
93 #include <sys/param.h>
94 #include <sys/mount.h>
95 #endif
96 
97 #if !defined(QT_NO_SOUND) && !defined(Q_OS_DARWIN)
98 #ifdef QT_USE_OLD_QWS_SOUND
99 #include <sys/types.h>
100 #include <sys/stat.h>
101 #include <sys/ioctl.h>
102 #include <sys/soundcard.h>
103 #else
104 #include "qsoundqss_qws.h"
105 #endif
106 #endif
107 
108 //#define QWS_DEBUG_FONTCLEANUP
109 
110 QT_BEGIN_NAMESPACE
111 
112 QWSServer Q_GUI_EXPORT *qwsServer=0;
113 static QWSServerPrivate *qwsServerPrivate=0;
114 
115 #define MOUSE 0
116 #define KEY 1
117 //#define EVENT_BLOCK_DEBUG
118 
~QWSScreenSaver()119 QWSScreenSaver::~QWSScreenSaver()
120 {
121 }
122 
123 extern QByteArray qws_display_spec;
124 extern void qt_init_display(); //qapplication_qws.cpp
125 extern QString qws_qtePipeFilename();
126 
127 extern void qt_client_enqueue(const QWSEvent *); //qapplication_qws.cpp
128 extern QList<QWSCommand*> *qt_get_server_queue();
129 
130 Q_GLOBAL_STATIC_WITH_ARGS(QString, defaultMouse, (QLatin1String("Auto")))
131 Q_GLOBAL_STATIC_WITH_ARGS(QString, defaultKeyboard, (QLatin1String("TTY")))
132 static const int FontCleanupInterval = 60 * 1000;
133 
134 static int qws_keyModifiers = 0;
135 
136 static QWSWindow *keyboardGrabber;
137 static bool keyboardGrabbing;
138 
get_object_id(int count=1)139 static int get_object_id(int count = 1)
140 {
141     static int next=1000;
142     int n = next;
143     next += count;
144     return n;
145 }
146 #ifndef QT_NO_QWS_INPUTMETHODS
147 static QWSInputMethod *current_IM = 0;
148 
149 static QWSWindow *current_IM_composing_win = 0;
150 static int current_IM_winId = -1;
151 static bool force_reject_strokeIM = false;
152 #endif
153 
154 static void cleanupFontsDir();
155 
156 //#define QWS_REGION_DEBUG
157 
158 /*!
159     \class QWSScreenSaver
160     \ingroup qws
161 
162     \brief The QWSScreenSaver class is a base class for screensavers
163     in Qt for Embedded Linux.
164 
165     When running \l{Qt for Embedded Linux} applications, it is the server
166     application that installs and controls the screensaver.
167     \l{Qt for Embedded Linux} supports multilevel screen saving; i.e., it is possible to
168     specify several different levels of screen responsiveness. For
169     example, you can choose to first turn off the light before you
170     fully activate the screensaver.
171 
172     Note that there exists no default screensaver implementation.
173 
174     To create a custom screensaver, derive from this class and
175     reimplement the restore() and save() functions. These functions
176     are called whenever the screensaver is activated or deactivated,
177     respectively. Once an instance of your custom screensaver is
178     created, you can use the QWSServer::setScreenSaver() function to
179     install it.
180 
181     \sa QWSServer, QScreen, {Qt for Embedded Linux}
182 */
183 
184 /*!
185     \fn QWSScreenSaver::~QWSScreenSaver()
186 
187     Reimplement this function to destroy the screensaver.
188 */
189 
190 /*!
191     \fn QWSScreenSaver::restore()
192 
193     Implement this function to deactivate the screensaver, restoring
194     the previously saved screen.
195 
196     \sa save(), QWSServer::screenSaverActivate()
197 */
198 
199 /*!
200     \fn QWSScreenSaver::save(int level)
201 
202     Implement this function to activate the screensaver, saving the
203     current screen.
204 
205     \l{Qt for Embedded Linux} supports multilevel screen saving; i.e., it is
206     possible to specify several different levels of screen
207     responsiveness. For example, you can choose to first turn off the
208     light before you fully activate the screensaver. Use the
209     QWSServer::setScreenSaverIntervals() to specify the time intervals
210     between the different levels.
211 
212     This function should return true if the screensaver successfully
213     enters the given \a level; otherwise it should return false.
214 
215     \sa restore(), QWSServer::screenSaverActivate()
216 */
217 
218 class QWSWindowPrivate
219 {
220 public:
221     QWSWindowPrivate();
222 
223 #ifdef QT_QWS_CLIENTBLIT
224     QRegion directPaintRegion;
225 #endif
226     QRegion allocatedRegion;
227 #ifndef QT_NO_QWSEMBEDWIDGET
228     QList<QWSWindow*> embedded;
229     QWSWindow *embedder;
230 #endif
231     QWSWindow::State state;
232     Qt::WindowFlags windowFlags;
233     QRegion dirtyOnScreen;
234     bool painted;
235 };
236 
QWSWindowPrivate()237 QWSWindowPrivate::QWSWindowPrivate()
238     :
239 #ifndef QT_NO_QWSEMBEDWIDGET
240     embedder(0), state(QWSWindow::NoState),
241 #endif
242     painted(false)
243 {
244 }
245 
246 /*!
247     \class QWSWindow
248     \ingroup qws
249 
250     \brief The QWSWindow class encapsulates a top-level window in
251     Qt for Embedded Linux.
252 
253     When you run a \l{Qt for Embedded Linux} application, it either runs as a
254     server or connects to an existing server. As applications add and
255     remove windows, the server process maintains information about
256     each window. In \l{Qt for Embedded Linux}, top-level windows are
257     encapsulated as QWSWindow objects. Note that you should never
258     construct the QWSWindow class yourself; the current top-level
259     windows can be retrieved using the QWSServer::clientWindows()
260     function.
261 
262     With a window at hand, you can retrieve its caption, name, opacity
263     and ID using the caption(), name(), opacity() and winId()
264     functions, respectively. Use the client() function to retrieve a
265     pointer to the client that owns the window.
266 
267     Use the isVisible() function to find out if the window is
268     visible. You can find out if the window is completely obscured by
269     another window or by the bounds of the screen, using the
270     isFullyObscured() function. The isOpaque() function returns true
271     if the window has an alpha channel equal to 255. Finally, the
272     requestedRegion() function returns the region of the display the
273     window wants to draw on.
274 
275     \sa QWSServer, QWSClient, {Qt for Embedded Linux Architecture}
276 */
277 
278 /*!
279     \fn int QWSWindow::winId() const
280 
281     Returns the window's ID.
282 
283     \sa name(), caption()
284 */
285 
286 /*!
287     \fn const QString &QWSWindow::name() const
288 
289     Returns the window's name, which is taken from the \l {QWidget::}{objectName()}
290     at the time of \l {QWidget::}{show()}.
291 
292     \sa caption(), winId()
293 */
294 
295 /*!
296     \fn const QString &QWSWindow::caption() const
297 
298     Returns the window's caption.
299 
300     \sa name(), winId()
301 */
302 
303 /*!
304     \fn QWSClient* QWSWindow::client() const
305 
306     Returns a reference to the QWSClient object that owns this window.
307 
308     \sa requestedRegion()
309 */
310 
311 /*!
312     \fn QRegion QWSWindow::requestedRegion() const
313 
314     Returns the region that the window has requested to draw onto,
315     including any window decorations.
316 
317     \sa client()
318 */
319 
320 /*!
321     \fn bool QWSWindow::isVisible() const
322 
323     Returns true if the window is visible; otherwise returns false.
324 
325     \sa isFullyObscured()
326 */
327 
328 /*!
329     \fn bool QWSWindow::isOpaque() const
330 
331     Returns true if the window is opaque, i.e., if its alpha channel
332     equals 255; otherwise returns false.
333 
334     \sa opacity()
335 */
336 
337 /*!
338     \fn uint QWSWindow::opacity () const
339 
340     Returns the window's alpha channel value.
341 
342     \sa isOpaque()
343 */
344 
345 /*!
346     \fn bool QWSWindow::isPartiallyObscured() const
347     \internal
348 
349     Returns true if the window is partially obsured by another window
350     or by the bounds of the screen; otherwise returns false.
351 */
352 
353 /*!
354     \fn bool QWSWindow::isFullyObscured() const
355 
356     Returns true if the window is completely obsured by another window
357     or by the bounds of the screen; otherwise returns false.
358 
359     \sa isVisible()
360 */
361 
362 /*!
363     \fn QWSWindowSurface* QWSWindow::windowSurface() const
364     \internal
365 */
366 
QWSWindow(int i,QWSClient * client)367 QWSWindow::QWSWindow(int i, QWSClient* client)
368         : id(i), modified(false),
369           onTop(false), c(client), last_focus_time(0), _opacity(255),
370           opaque(true), d(new QWSWindowPrivate)
371 {
372     surface = 0;
373 }
374 
375 
376 /*!
377     \enum QWSWindow::State
378 
379     This enum describes the state of a window. Most of the
380     transitional states are set just before a call to
381     QScreen::exposeRegion() and reset immediately afterwards.
382 
383     \value NoState Initial state before the window is properly initialized.
384     \value Hidden The window is not visible.
385     \value Showing The window is being shown.
386     \value Visible The window is visible, and not in a transition.
387     \value Hiding The window is being hidden.
388     \value Raising The windoe is being raised.
389     \value Lowering The window is being raised.
390     \value Moving The window is being moved.
391     \value ChangingGeometry The window's geometry is being changed.
392     \value Destroyed  The window is destroyed.
393 
394     \sa state(), QScreen::exposeRegion()
395 */
396 
397 /*!
398   Returns the current state of the window.
399 
400   \since 4.3
401 */
state() const402 QWSWindow::State QWSWindow::state() const
403 {
404     return d->state;
405 }
406 
407 /*!
408   Returns the window flags of the window. This value is only available
409   after the first paint event.
410 
411   \since 4.3
412 */
windowFlags() const413 Qt::WindowFlags QWSWindow::windowFlags() const
414 {
415     return d->windowFlags;
416 }
417 
418 /*!
419   Returns the region that has been repainted since the previous
420   QScreen::exposeRegion(), and needs to be copied to the screen.
421   \since 4.3
422 */
dirtyOnScreen() const423 QRegion QWSWindow::dirtyOnScreen() const
424 {
425     return d->dirtyOnScreen;
426 }
427 
createSurface(const QString & key,const QByteArray & data)428 void QWSWindow::createSurface(const QString &key, const QByteArray &data)
429 {
430 #ifndef QT_NO_QWS_MULTIPROCESS
431     if (surface && !surface->isBuffered())
432         c->removeUnbufferedSurface();
433 #endif
434 
435     delete surface;
436     surface = qt_screen->createSurface(key);
437     surface->setPermanentState(data);
438 
439 #ifndef QT_NO_QWS_MULTIPROCESS
440     if (!surface->isBuffered())
441         c->addUnbufferedSurface();
442 #endif
443 }
444 
445 /*!
446     \internal
447     Raises the window above all other windows except "Stay on top" windows.
448 */
raise()449 void QWSWindow::raise()
450 {
451     qwsServerPrivate->raiseWindow(this);
452 #ifndef QT_NO_QWSEMBEDWIDGET
453     const int n = d->embedded.size();
454     for (int i = 0; i < n; ++i)
455         d->embedded.at(i)->raise();
456 #endif
457 }
458 
459 /*!
460     \internal
461     Lowers the window below other windows.
462 */
lower()463 void QWSWindow::lower()
464 {
465     qwsServerPrivate->lowerWindow(this);
466 #ifndef QT_NO_QWSEMBEDWIDGET
467     const int n = d->embedded.size();
468     for (int i = 0; i < n; ++i)
469         d->embedded.at(i)->lower();
470 #endif
471 }
472 
473 /*!
474     \internal
475     Shows the window.
476 */
show()477 void QWSWindow::show()
478 {
479     operation(QWSWindowOperationEvent::Show);
480 #ifndef QT_NO_QWSEMBEDWIDGET
481     const int n = d->embedded.size();
482     for (int i = 0; i < n; ++i)
483         d->embedded.at(i)->show();
484 #endif
485 }
486 
487 /*!
488     \internal
489     Hides the window.
490 */
hide()491 void QWSWindow::hide()
492 {
493     operation(QWSWindowOperationEvent::Hide);
494 #ifndef QT_NO_QWSEMBEDWIDGET
495     const int n = d->embedded.size();
496     for (int i = 0; i < n; ++i)
497         d->embedded.at(i)->hide();
498 #endif
499 }
500 
501 /*!
502     \internal
503     Make this the active window (i.e., sets the keyboard focus to this
504     window).
505 */
setActiveWindow()506 void QWSWindow::setActiveWindow()
507 {
508     qwsServerPrivate->setFocus(this, true);
509 #ifndef QT_NO_QWSEMBEDWIDGET
510     const int n = d->embedded.size();
511     for (int i = 0; i < n; ++i)
512         d->embedded.at(i)->setActiveWindow();
513 #endif
514 }
515 
setName(const QString & n)516 void QWSWindow::setName(const QString &n)
517 {
518     rgnName = n;
519 }
520 
521 /*!
522   \internal
523   Sets the window's caption to \a c.
524 */
setCaption(const QString & c)525 void QWSWindow::setCaption(const QString &c)
526 {
527     rgnCaption = c;
528 }
529 
530 
531 static int global_focus_time_counter=100;
532 
focus(bool get)533 void QWSWindow::focus(bool get)
534 {
535     if (get)
536         last_focus_time = global_focus_time_counter++;
537     if (c) {
538         QWSFocusEvent event;
539         event.simpleData.window = id;
540         event.simpleData.get_focus = get;
541         c->sendEvent(&event);
542     }
543 }
544 
operation(QWSWindowOperationEvent::Operation o)545 void QWSWindow::operation(QWSWindowOperationEvent::Operation o)
546 {
547     if (!c)
548         return;
549     QWSWindowOperationEvent event;
550     event.simpleData.window = id;
551     event.simpleData.op = o;
552     c->sendEvent(&event);
553 }
554 
555 /*!
556     \internal
557     Destructor.
558 */
~QWSWindow()559 QWSWindow::~QWSWindow()
560 {
561 #ifndef QT_NO_QWS_INPUTMETHODS
562     if (current_IM_composing_win == this)
563         current_IM_composing_win = 0;
564 #endif
565 #ifndef QT_NO_QWSEMBEDWIDGET
566     QWSWindow *embedder = d->embedder;
567     if (embedder) {
568         embedder->d->embedded.removeAll(this);
569         d->embedder = 0;
570     }
571     while (!d->embedded.isEmpty())
572         stopEmbed(d->embedded.first());
573 #endif
574 
575 #ifndef QT_NO_QWS_MULTIPROCESS
576     if (surface && !surface->isBuffered()) {
577         if (c && c->d_func()) // d_func() will be 0 if client is deleted
578             c->removeUnbufferedSurface();
579     }
580 #endif
581 
582     delete surface;
583     delete d;
584 }
585 
586 /*!
587     \internal
588 
589     Returns the region that the window is allowed to draw onto,
590     including any window decorations but excluding regions covered by
591     other windows.
592 
593     \sa paintedRegion(), requestedRegion()
594 */
allocatedRegion() const595 QRegion QWSWindow::allocatedRegion() const
596 {
597     return d->allocatedRegion;
598 }
599 
600 #ifdef QT_QWS_CLIENTBLIT
directPaintRegion() const601 QRegion QWSWindow::directPaintRegion() const
602 {
603     return d->directPaintRegion;
604 }
605 
setDirectPaintRegion(const QRegion & r)606 inline void QWSWindow::setDirectPaintRegion(const QRegion &r)
607 {
608     d->directPaintRegion = r;
609 }
610 #endif
611 
612 /*!
613     \internal
614 
615     Returns the region that the window is known to have drawn into.
616 
617     \sa allocatedRegion(), requestedRegion()
618 */
paintedRegion() const619 QRegion QWSWindow::paintedRegion() const
620 {
621     return (d->painted ? d->allocatedRegion : QRegion());
622 }
623 
setAllocatedRegion(const QRegion & region)624 inline void QWSWindow::setAllocatedRegion(const QRegion &region)
625 {
626     d->allocatedRegion = region;
627 }
628 
629 #ifndef QT_NO_QWSEMBEDWIDGET
startEmbed(QWSWindow * w)630 inline void QWSWindow::startEmbed(QWSWindow *w)
631 {
632     d->embedded.append(w);
633     w->d->embedder = this;
634 }
635 
stopEmbed(QWSWindow * w)636 inline void QWSWindow::stopEmbed(QWSWindow *w)
637 {
638     w->d->embedder = 0;
639     w->client()->sendEmbedEvent(w->winId(), QWSEmbedEvent::Region, QRegion());
640     d->embedded.removeAll(w);
641 }
642 #endif // QT_NO_QWSEMBEDWIDGET
643 
644 /*********************************************************************
645  *
646  * Class: QWSClient
647  *
648  *********************************************************************/
649 
650 class QWSClientPrivate : public QObjectPrivate
651 {
652     Q_DECLARE_PUBLIC(QWSClient)
653 
654 public:
655     QWSClientPrivate();
656     ~QWSClientPrivate();
657 
658     void setLockId(int id);
659     void unlockCommunication();
660 
661 private:
662 #ifndef QT_NO_QWS_MULTIPROCESS
663     QWSLock *clientLock;
664     bool shutdown;
665     int numUnbufferedSurfaces;
666 #endif
667     QSet<QByteArray> usedFonts;
668     friend class QWSServerPrivate;
669 };
670 
QWSClientPrivate()671 QWSClientPrivate::QWSClientPrivate()
672 {
673 #ifndef QT_NO_QWS_MULTIPROCESS
674     clientLock = 0;
675     shutdown = false;
676     numUnbufferedSurfaces = 0;
677 #endif
678 }
679 
~QWSClientPrivate()680 QWSClientPrivate::~QWSClientPrivate()
681 {
682 #ifndef QT_NO_QWS_MULTIPROCESS
683     delete clientLock;
684 #endif
685 }
686 
setLockId(int id)687 void QWSClientPrivate::setLockId(int id)
688 {
689 #ifdef QT_NO_QWS_MULTIPROCESS
690     Q_UNUSED(id);
691 #else
692     clientLock = new QWSLock(id);
693 #endif
694 }
695 
unlockCommunication()696 void QWSClientPrivate::unlockCommunication()
697 {
698 #ifndef QT_NO_QWS_MULTIPROCESS
699     if (clientLock)
700         clientLock->unlock(QWSLock::Communication);
701 #endif
702 }
703 
704 /*!
705     \class QWSClient
706     \ingroup qws
707 
708     \brief The QWSClient class encapsulates a client process in Qt for Embedded Linux.
709 
710     When you run a \l{Qt for Embedded Linux} application, it either runs as a
711     server or connects to an existing server. The server and client
712     processes have different responsibilities: The client process
713     performs all application specific operations. The server process
714     is responsible for managing the clients as well as taking care of
715     the pointer handling, character input, and screen output. In
716     addition, the server provides functionality to handle input
717     methods.
718 
719     As applications add and remove windows, the server process
720     maintains information about each window. In \l{Qt for Embedded Linux},
721     top-level windows are encapsulated as QWSWindow objects. A list of
722     the current windows can be retrieved using the
723     QWSServer::clientWindows() function, and each window can tell
724     which client that owns it through its QWSWindow::client()
725     function.
726 
727     A QWSClient object has an unique ID that can be retrieved using
728     its clientId() function. QWSClient also provides the identity()
729     function which typically returns the name of this client's running
730     application.
731 
732     \sa QWSServer, QWSWindow, {Qt for Embedded Linux Architecture}
733 */
734 
735 /*!
736    \internal
737 */
738 //always use frame buffer
QWSClient(QObject * parent,QWS_SOCK_BASE * sock,int id)739 QWSClient::QWSClient(QObject* parent, QWS_SOCK_BASE* sock, int id)
740     : QObject(*new QWSClientPrivate, parent), command(0), cid(id)
741 {
742 #ifdef QT_NO_QWS_MULTIPROCESS
743     Q_UNUSED(sock);
744     isClosed = false;
745 #else
746     csocket = 0;
747     if (!sock) {
748         socketDescriptor = -1;
749         isClosed = false;
750     } else {
751         csocket = static_cast<QWSSocket*>(sock); //###
752         isClosed = false;
753 
754         csocket->flush();
755         socketDescriptor = csocket->socketDescriptor();
756         connect(csocket, SIGNAL(readyRead()), this, SIGNAL(readyRead()));
757         connect(csocket, SIGNAL(disconnected()), this, SLOT(closeHandler()));
758         connect(csocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(errorHandler()));
759     }
760 #endif //QT_NO_QWS_MULTIPROCESS
761 }
762 
763 /*!
764    \internal
765 */
~QWSClient()766 QWSClient::~QWSClient()
767 {
768     qDeleteAll(cursors);
769     delete command;
770 #ifndef QT_NO_QWS_MULTIPROCESS
771     delete csocket;
772 #endif
773 }
774 
775 #ifndef QT_NO_QWS_MULTIPROCESS
removeUnbufferedSurface()776 void QWSClient::removeUnbufferedSurface()
777 {
778     Q_D(QWSClient);
779     --d->numUnbufferedSurfaces;
780 }
781 
addUnbufferedSurface()782 void QWSClient::addUnbufferedSurface()
783 {
784     Q_D(QWSClient);
785     ++d->numUnbufferedSurfaces;
786 }
787 #endif // QT_NO_QWS_MULTIPROCESS
788 
789 /*!
790    \internal
791 */
setIdentity(const QString & i)792 void QWSClient::setIdentity(const QString& i)
793 {
794     id = i;
795 }
796 
closeHandler()797 void QWSClient::closeHandler()
798 {
799     isClosed = true;
800     emit connectionClosed();
801 }
802 
errorHandler()803 void QWSClient::errorHandler()
804 {
805 #if defined(QWS_SOCKET_DEBUG)
806     qDebug("Client %p error %s", this, csocket ? csocket->errorString().toLatin1().constData() : "(no socket)");
807 #endif
808     isClosed = true;
809 //####Do we need to clean out the pipes?
810 
811     emit connectionClosed();
812 }
813 
814 /*!
815    \internal
816 */
socket() const817 int QWSClient::socket() const
818 {
819     return socketDescriptor;
820 }
821 
822 /*!
823    \internal
824 */
sendEvent(QWSEvent * event)825 void QWSClient::sendEvent(QWSEvent* event)
826 {
827 #ifndef QT_NO_QWS_MULTIPROCESS
828     if (csocket) {
829         // qDebug() << "QWSClient::sendEvent type " << event->type << " socket state " << csocket->state();
830         if ((QAbstractSocket::SocketState)(csocket->state()) == QAbstractSocket::ConnectedState) {
831             event->write(csocket);
832         }
833     }
834     else
835 #endif
836     {
837         qt_client_enqueue(event);
838     }
839 }
840 
841 /*!
842    \internal
843 */
sendRegionEvent(int winid,QRegion rgn,int type,int id)844 void QWSClient::sendRegionEvent(int winid, QRegion rgn, int type
845 #ifdef QT_QWS_CLIENTBLIT
846         , int id
847 #endif
848         )
849 {
850 #ifndef QT_NO_QWS_MULTIPROCESS
851     Q_D(QWSClient);
852     if (d->clientLock)
853         d->clientLock->lock(QWSLock::RegionEvent);
854 #endif
855 
856     QWSRegionEvent event;
857     event.setData(winid, rgn, type);
858 #ifdef QT_QWS_CLIENTBLIT
859     event.simpleData.id = id;
860 #endif
861 
862 //    qDebug() << "Sending Region event to" << winid << "rgn" << rgn << "type" << type;
863 
864     sendEvent(&event);
865 }
866 
867 extern int qt_servershmid;
868 
869 /*!
870    \internal
871 */
sendConnectedEvent(const char * display_spec)872 void QWSClient::sendConnectedEvent(const char *display_spec)
873 {
874     QWSConnectedEvent event;
875     event.simpleData.window = 0;
876     event.simpleData.len = strlen(display_spec) + 1;
877     event.simpleData.clientId = cid;
878     event.simpleData.servershmid = qt_servershmid;
879     char * tmp=(char *)display_spec;
880     event.setData(tmp, event.simpleData.len);
881     sendEvent(&event);
882 }
883 
884 /*!
885    \internal
886 */
sendMaxWindowRectEvent(const QRect & rect)887 void QWSClient::sendMaxWindowRectEvent(const QRect &rect)
888 {
889     QWSMaxWindowRectEvent event;
890     event.simpleData.window = 0;
891     event.simpleData.rect = rect;
892     sendEvent(&event);
893 }
894 
895 /*!
896    \internal
897 */
898 #ifndef QT_NO_QWS_PROPERTIES
sendPropertyNotifyEvent(int property,int state)899 void QWSClient::sendPropertyNotifyEvent(int property, int state)
900 {
901     QWSPropertyNotifyEvent event;
902     event.simpleData.window = 0; // not used yet
903     event.simpleData.property = property;
904     event.simpleData.state = state;
905     sendEvent(&event);
906 }
907 
908 /*!
909    \internal
910 */
sendPropertyReplyEvent(int property,int len,const char * data)911 void QWSClient::sendPropertyReplyEvent(int property, int len, const char *data)
912 {
913     QWSPropertyReplyEvent event;
914     event.simpleData.window = 0; // not used yet
915     event.simpleData.property = property;
916     event.simpleData.len = len;
917     event.setData(data, len);
918     sendEvent(&event);
919 }
920 #endif //QT_NO_QWS_PROPERTIES
921 
922 /*!
923    \internal
924 */
sendSelectionClearEvent(int windowid)925 void QWSClient::sendSelectionClearEvent(int windowid)
926 {
927     QWSSelectionClearEvent event;
928     event.simpleData.window = windowid;
929     sendEvent(&event);
930 }
931 
932 /*!
933    \internal
934 */
sendSelectionRequestEvent(QWSConvertSelectionCommand * cmd,int windowid)935 void QWSClient::sendSelectionRequestEvent(QWSConvertSelectionCommand *cmd, int windowid)
936 {
937     QWSSelectionRequestEvent event;
938     event.simpleData.window = windowid;
939     event.simpleData.requestor = cmd->simpleData.requestor;
940     event.simpleData.property = cmd->simpleData.selection;
941     event.simpleData.mimeTypes = cmd->simpleData.mimeTypes;
942     sendEvent(&event);
943 }
944 
945 #ifndef QT_NO_QWSEMBEDWIDGET
946 /*!
947    \internal
948 */
sendEmbedEvent(int windowid,QWSEmbedEvent::Type type,const QRegion & region)949 void QWSClient::sendEmbedEvent(int windowid, QWSEmbedEvent::Type type,
950                                const QRegion &region)
951 {
952     QWSEmbedEvent event;
953     event.setData(windowid, type, region);
954     sendEvent(&event);
955 }
956 #endif // QT_NO_QWSEMBEDWIDGET
957 
958 /*!
959    \fn void QWSClient::connectionClosed()
960    \internal
961 */
962 
963 /*!
964     \fn void QWSClient::readyRead();
965     \internal
966 */
967 
968 /*!
969    \fn int QWSClient::clientId () const
970 
971    Returns an integer uniquely identfying this client.
972 */
973 
974 /*!
975    \fn QString QWSClient::identity () const
976 
977    Returns the name of this client's running application.
978 */
979 /*********************************************************************
980  *
981  * Class: QWSServer
982  *
983  *********************************************************************/
984 
985 /*!
986     \class QWSServer
987     \brief The QWSServer class encapsulates a server process in Qt for Embedded Linux.
988 
989     \ingroup qws
990 
991     When you run a \l{Qt for Embedded Linux} application, it either runs as a
992     server or connects to an existing server. The server and client
993     processes have different responsibilities: The client process
994     performs all application specific operations. The server process
995     is responsible for managing the clients as well as taking care of
996     the pointer handling, character input, and screen output. In
997     addition, the server provides functionality to handle input
998     methods.
999 
1000     In \l{Qt for Embedded Linux}, all system generated events are passed to the
1001     server application which then propagates the event to the
1002     appropriate client. See the \l{Qt for Embedded Linux Architecture}
1003     documentation for details.
1004 
1005     Note that this class is instantiated by QApplication for
1006     \l{Qt for Embedded Linux} server processes; you should never construct this
1007     class yourself. Use the instance() function to retrieve a pointer
1008     to the server object.
1009 
1010     Note that the static functions of the QWSServer class can only be
1011     used in the server process.
1012 
1013     \tableofcontents
1014 
1015     \section1 Client Administration
1016 
1017     As applications add and remove windows, the server process
1018     maintains information about each window. In \l{Qt for Embedded Linux},
1019     top-level windows are encapsulated as QWSWindow objects. Each
1020     window can tell which client that owns it through its
1021     QWSWindow::client() function. Use the clientWindows() function to
1022     retrieve a list of the current top-level windows. Given a
1023     particular position on the display, the window containing it can
1024     be retrieved using the windowAt() function.
1025 
1026     QWSServer also provides the windowEvent() signal which is emitted
1027     whenever something happens to a top level window; the WindowEvent
1028     enum describes the various types of events that the signal
1029     recognizes. In addition, the server class provides the
1030     markedText() signal which is emitted whenever some text has been
1031     selected in any of the windows, passing the selection as
1032     parameter.
1033 
1034     The QCopChannel class and the QCOP communication protocol enable
1035     transfer of messages between clients. QWSServer provides the
1036     newChannel() and removedChannel() signals that is emitted whenever
1037     a new QCopChannel object is created or destroyed, respectively.
1038 
1039     See also: QWSWindow, QWSClient and QCopChannel.
1040 
1041 
1042     \section1 Mouse Handling
1043 
1044     The mouse driver (represented by an instance of the
1045     QWSMouseHandler class) is loaded by the server application when it
1046     starts running, using Qt's \l {How to Create Qt Plugins}{plugin
1047     system}. A mouse driver receives mouse events from the device and
1048     encapsulates each event with an instance of the QWSEvent class
1049     which it then passes to the server.
1050 
1051     The openMouse() function opens the mouse devices specified by the
1052     QWS_MOUSE_PROTO environment variable, and the setMouseHandler()
1053     functions sets the primary mouse driver. Alternatively, the static
1054     setDefaultMouse() function provides means of specifying the mouse
1055     driver to use if the QWS_MOUSE_PROTO variable is not defined (note
1056     that the default is otherwise platform dependent). The primary
1057     mouse driver can be retrieved using the static mouseHandler()
1058     function. Use the closeMouse() function to delete the mouse
1059     drivers.
1060 
1061     In addition, the QWSServer class can control the flow of mouse
1062     input using the suspendMouse() and resumeMouse() functions.
1063 
1064     See also: QWSMouseHandler and \l{Qt for Embedded Linux Pointer Handling}.
1065 
1066     \section1 Keyboard Handling
1067 
1068     The keyboard driver (represented by an instance of the
1069     QWSKeyboardHandler class) is loaded by the server application when
1070     it starts running, using Qt's \l {How to Create Qt Plugins}{plugin
1071     system}. A keyboard driver receives keyboard events from the
1072     device and encapsulates each event with an instance of the
1073     QWSEvent class which it then passes to the server.
1074 
1075     The openKeyboard() function opens the keyboard devices specified
1076     by the QWS_KEYBOARD environment variable, and the
1077     setKeyboardHandler() functions sets the primary keyboard
1078     driver. Alternatively, the static setDefaultKeyboard() function
1079     provides means of specifying the keyboard driver to use if the
1080     QWS_KEYBOARD variable is not defined (note again that the default
1081     is otherwise platform dependent). The primary keyboard driver can
1082     be retrieved using the static keyboardHandler() function. Use the
1083     closeKeyboard() function to delete the keyboard drivers.
1084 
1085     In addition, the QWSServer class can handle key events from both
1086     physical and virtual keyboards using the processKeyEvent() and
1087     sendKeyEvent() functions, respectively. Use the
1088     addKeyboardFilter() function to filter the key events from
1089     physical keyboard drivers, the most recently added filter can be
1090     removed and deleted using the removeKeyboardFilter() function.
1091 
1092     See also: QWSKeyboardHandler and \l{Qt for Embedded Linux Character Input}.
1093 
1094     \section1 Display Handling
1095 
1096     When a screen update is required, the server runs through all the
1097     top-level windows that intersect with the region that is about to
1098     be updated, and ensures that the associated clients have updated
1099     their memory buffer. Then the server uses the screen driver
1100     (represented by an instance of the QScreen class) to copy the
1101     content of the memory to the screen.
1102 
1103     In addition, the QWSServer class provides some means of managing
1104     the screen output: Use the refresh() function to refresh the
1105     entire display, or alternatively a specified region of it. The
1106     enablePainting() function can be used to disable (and enable)
1107     painting onto the screen. QWSServer also provide the
1108     setMaxWindowRect() function restricting the area of the screen
1109     which \l{Qt for Embedded Linux} applications will consider to be the
1110     maximum area to use for windows. To set the brush used as the
1111     background in the absence of obscuring windows, QWSServer provides
1112     the static setBackground() function. The corresponding
1113     backgroundBrush() function returns the currently set brush.
1114 
1115     QWSServer also controls the screen saver: Use the setScreenSaver()
1116     to install a custom screen saver derived from the QWSScreenSaver
1117     class. Once installed, the screensaver can be activated using the
1118     screenSaverActivate() function, and the screenSaverActive()
1119     function returns its current status. Use the
1120     setScreenSaverInterval() function to specify the timeout interval.
1121     \l{Qt for Embedded Linux} also supports multilevel screen saving, use the
1122     setScreenSaverIntervals() function to specify the various levels
1123     and their timeout intervals.
1124 
1125     Finally, the QWSServer class controls the cursor's appearance,
1126     i.e., use the setCursorVisible() function to hide or show the
1127     cursor, and the isCursorVisible() function to determine whether
1128     the cursor is visible on the display or not.
1129 
1130     See also: QScreen and \l{Qt for Embedded Linux Display Management}.
1131 
1132     \section1 Input Method Handling
1133 
1134     Whenever the server receives an event, it queries its stack of
1135     top-level windows to find the window containing the event's
1136     position (each window can identify the client application that
1137     created it). Then the server forwards the event to the appropriate
1138     client. If an input method is installed, it is used as a filter
1139     between the server and the client application.
1140 
1141     Derive from the QWSInputMethod class to create custom input
1142     methods, and use the server's setCurrentInputMethod() function to
1143     install it. Use the sendIMEvent() and sendIMQuery() functions to
1144     send input method events and queries.
1145 
1146     QWSServer provides the IMMouse enum describing the various mouse
1147     events recognized by the QWSInputMethod::mouseHandler()
1148     function. The latter function allows subclasses of QWSInputMethod
1149     to handle mouse events within the preedit text.
1150 
1151     \sa QWSInputMethod
1152 */
1153 
1154 /*!
1155     \enum QWSServer::IMState
1156     \obsolete
1157 
1158     This enum describes the various states of an input method.
1159 
1160     \value IMCompose Composing.
1161     \value IMStart Equivalent to IMCompose.
1162     \value IMEnd Finished composing.
1163 
1164     \sa QWSInputMethod::sendIMEvent()
1165 */
1166 
1167 /*!
1168     \enum QWSServer::IMMouse
1169 
1170     This enum describes the various types of mouse events recognized
1171     by the QWSInputMethod::mouseHandler() function.
1172 
1173     \value MousePress An event generated by pressing a mouse button.
1174     \value MouseRelease An event generated by relasing a mouse button.
1175     \value MouseMove An event generated by moving the mouse cursor.
1176     \value MouseOutside This value is only reserved, i.e., it is not used in
1177                                     current implementations.
1178 
1179     \sa QWSInputMethod, setCurrentInputMethod()
1180 */
1181 
1182 /*!
1183     \enum QWSServer::ServerFlags
1184     \internal
1185 
1186     This enum is used to pass various options to the window system
1187     server.
1188 
1189     \value DisableKeyboard Ignore all keyboard input.
1190     \value DisableMouse Ignore all mouse input.
1191 */
1192 
1193 /*!
1194     \enum QWSServer::WindowEvent
1195 
1196     This enum specifies the various events that can occur in a
1197     top-level window.
1198 
1199     \value Create A new window has been created (by the QWidget constructor).
1200     \value Destroy The window has been closed and deleted (by the QWidget destructor).
1201     \value Hide The window has been hidden using the QWidget::hide() function.
1202     \value Show The window has been shown using the QWidget::show() function or similar.
1203     \value Raise The window has been raised to the top of the desktop.
1204     \value Lower The window has been lowered.
1205     \value Geometry The window has changed size or position.
1206     \value Active The window has become the active window (i.e., it has keyboard focus).
1207     \value Name The window has been named.
1208 
1209     \sa windowEvent()
1210 */
1211 
1212 /*!
1213     \fn void QWSServer::markedText(const QString &selection)
1214 
1215     This signal is emitted whenever some text is selected in any of
1216     the running applications, passing the selected text in the \a
1217     selection parameter.
1218 
1219     \sa windowEvent()
1220 */
1221 
1222 /*!
1223     \fn const QList<QWSWindow*> &QWSServer::clientWindows()
1224 
1225     Returns the list of current top-level windows.
1226 
1227     Note that the collection of top-level windows changes as
1228     applications add and remove widgets so it should not be stored for
1229     future use. The windows are sorted in stacking order from top-most
1230     to bottom-most.
1231 
1232     Use the QWSWindow::client() function to retrieve the client
1233     application that owns a given window.
1234 
1235     \sa windowAt(), instance()
1236 */
1237 
1238 /*!
1239     \fn void QWSServer::newChannel(const QString& channel)
1240 
1241     This signal is emitted whenever a new QCopChannel object is
1242     created, passing the channel's name in the \a channel parameter.
1243 
1244     \sa removedChannel()
1245 */
1246 
1247 /*!
1248     \fn void QWSServer::removedChannel(const QString& channel)
1249 
1250     This signal is emitted immediately after the given the QCopChannel
1251     object specified by \a channel, is destroyed.
1252 
1253     Note that a channel is not destroyed until all its listeners have
1254     been unregistered.
1255 
1256     \sa newChannel()
1257 */
1258 
1259 /*!
1260     \fn QWSServer::QWSServer(int flags, QObject *parent)
1261     \internal
1262 
1263     Construct a QWSServer object with the given \a parent.  The \a
1264     flags are used for keyboard and mouse settings.
1265 
1266     \warning This class is instantiated by QApplication for
1267     \l{Qt for Embedded Linux} server processes. You should never construct
1268     this class yourself.
1269 
1270     \sa {Running Applications}
1271 */
1272 
1273 /*!
1274     \fn static QWSServer* QWSServer::instance()
1275     \since 4.2
1276 
1277     Returns a pointer to the server instance.
1278 
1279     Note that the pointer will be 0 if the application is not the
1280     server, i.e., if the QApplication::type() function doesn't return
1281     QApplication::GuiServer.
1282 
1283     \sa clientWindows(), windowAt()
1284 */
1285 
1286 struct QWSCommandStruct
1287 {
QWSCommandStructQWSCommandStruct1288     QWSCommandStruct(QWSCommand *c, QWSClient *cl) :command(c),client(cl){}
~QWSCommandStructQWSCommandStruct1289     ~QWSCommandStruct() { delete command; }
1290 
1291     QWSCommand *command;
1292     QWSClient *client;
1293 
1294 };
1295 
QWSServer(int flags,QObject * parent)1296 QWSServer::QWSServer(int flags, QObject *parent) :
1297     QObject(*new QWSServerPrivate, parent)
1298 {
1299     Q_D(QWSServer);
1300     QT_TRY {
1301         d->initServer(flags);
1302     } QT_CATCH(...) {
1303         qwsServer = 0;
1304         qwsServerPrivate = 0;
1305         QT_RETHROW;
1306     }
1307 }
1308 
1309 #ifdef QT3_SUPPORT
1310 /*!
1311     Use the two-argument overload and call the
1312     QObject::setObjectName() function instead.
1313 */
QWSServer(int flags,QObject * parent,const char * name)1314 QWSServer::QWSServer(int flags, QObject *parent, const char *name) :
1315     QObject(*new QWSServerPrivate, parent)
1316 {
1317     Q_D(QWSServer);
1318     setObjectName(QString::fromAscii(name));
1319     d->initServer(flags);
1320 }
1321 #endif
1322 
1323 
1324 #ifndef QT_NO_QWS_MULTIPROCESS
ignoreSignal(int)1325 static void ignoreSignal(int) {} // Used to eat SIGPIPE signals below
1326 #endif
1327 
screensaverblockevent(int index,int * screensaverinterval,bool isDown)1328 bool QWSServerPrivate::screensaverblockevent( int index, int *screensaverinterval, bool isDown )
1329 {
1330     static bool ignoreEvents[2] = { false, false };
1331     if ( isDown ) {
1332         if ( !ignoreEvents[index] ) {
1333             bool wake = false;
1334             if ( screensaverintervals ) {
1335                 if ( screensaverinterval != screensaverintervals ) {
1336                     wake = true;
1337                 }
1338             }
1339             if ( screensaverblockevents && wake ) {
1340 #ifdef EVENT_BLOCK_DEBUG
1341                 qDebug( "waking the screen" );
1342 #endif
1343                 ignoreEvents[index] = true;
1344             } else if ( !screensaverblockevents ) {
1345 #ifdef EVENT_BLOCK_DEBUG
1346                 qDebug( "the screen was already awake" );
1347 #endif
1348                 ignoreEvents[index] = false;
1349             }
1350         }
1351     } else {
1352         if ( ignoreEvents[index] ) {
1353 #ifdef EVENT_BLOCK_DEBUG
1354             qDebug( "mouseup?" );
1355 #endif
1356             ignoreEvents[index] = false;
1357             return true;
1358         }
1359     }
1360     return ignoreEvents[index];
1361 }
1362 
initServer(int flags)1363 void QWSServerPrivate::initServer(int flags)
1364 {
1365     Q_Q(QWSServer);
1366     Q_ASSERT(!qwsServer);
1367     qwsServer = q;
1368     qwsServerPrivate = this;
1369     disablePainting = false;
1370 #ifndef QT_NO_QWS_MULTIPROCESS
1371     ssocket = new QWSServerSocket(qws_qtePipeFilename(), q);
1372     QObject::connect(ssocket, SIGNAL(newConnection()), q, SLOT(_q_newConnection()));
1373 
1374     if ( !ssocket->isListening()) {
1375         perror("QWSServerPrivate::initServer: server socket not listening");
1376         qFatal("Failed to bind to %s", qws_qtePipeFilename().toLatin1().constData());
1377     }
1378 
1379     struct linger tmp;
1380     tmp.l_onoff=1;
1381     tmp.l_linger=0;
1382     setsockopt(ssocket->socketDescriptor(),SOL_SOCKET,SO_LINGER,(char *)&tmp,sizeof(tmp));
1383 
1384 
1385     signal(SIGPIPE, ignoreSignal); //we get it when we read
1386 #endif
1387     focusw = 0;
1388     mouseGrabber = 0;
1389     mouseGrabbing = false;
1390     inputMethodMouseGrabbed = false;
1391     keyboardGrabber = 0;
1392     keyboardGrabbing = false;
1393 #ifndef QT_NO_QWS_CURSOR
1394     haveviscurs = false;
1395     cursor = 0;
1396     nextCursor = 0;
1397 #endif
1398 
1399 #ifndef QT_NO_QWS_MULTIPROCESS
1400 
1401     if (!geteuid()) {
1402 #if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
1403         if(mount(0,"/var/shm", "shm", 0, 0)) {
1404             /* This just confuses people with 2.2 kernels
1405             if (errno != EBUSY)
1406                 qDebug("Failed mounting shm fs on /var/shm: %s",strerror(errno));
1407             */
1408         }
1409 #endif
1410     }
1411 #endif
1412 
1413     // no selection yet
1414     selectionOwner.windowid = -1;
1415     selectionOwner.time.set(-1, -1, -1, -1);
1416 
1417     cleanupFontsDir();
1418 
1419     // initialize the font database
1420     // from qfontdatabase_qws.cpp
1421     extern void qt_qws_init_fontdb();
1422     qt_qws_init_fontdb();
1423 
1424     openDisplay();
1425 
1426     screensavertimer = new QTimer(q);
1427     screensavertimer->setSingleShot(true);
1428     QObject::connect(screensavertimer, SIGNAL(timeout()), q, SLOT(_q_screenSaverTimeout()));
1429     _q_screenSaverWake();
1430 
1431     clientMap[-1] = new QWSClient(q, 0, 0);
1432 
1433     if (!bgBrush)
1434         bgBrush = new QBrush(QColor(0x20, 0xb0, 0x50));
1435 
1436     initializeCursor();
1437 
1438     // input devices
1439     if (!(flags&QWSServer::DisableMouse)) {
1440         q->openMouse();
1441     }
1442 #ifndef QT_NO_QWS_KEYBOARD
1443     if (!(flags&QWSServer::DisableKeyboard)) {
1444         q->openKeyboard();
1445     }
1446 #endif
1447 
1448 #if !defined(QT_NO_SOUND) && !defined(QT_EXTERNAL_SOUND_SERVER) && !defined(Q_OS_DARWIN)
1449     soundserver = new QWSSoundServer(q);
1450 #endif
1451 }
1452 
1453 /*!
1454     \internal
1455     Destructs this server.
1456 */
~QWSServer()1457 QWSServer::~QWSServer()
1458 {
1459     closeMouse();
1460 #ifndef QT_NO_QWS_KEYBOARD
1461     closeKeyboard();
1462 #endif
1463     d_func()->cleanupFonts(/*force =*/true);
1464 }
1465 
1466 /*!
1467   \internal
1468  */
timerEvent(QTimerEvent * e)1469 void QWSServer::timerEvent(QTimerEvent *e)
1470 {
1471     Q_D(QWSServer);
1472     if (e->timerId() == d->fontCleanupTimer.timerId()) {
1473         d->cleanupFonts();
1474         d->fontCleanupTimer.stop();
1475     } else {
1476         QObject::timerEvent(e);
1477     }
1478 }
1479 
clientWindows()1480 const QList<QWSWindow*> &QWSServer::clientWindows()
1481 {
1482     Q_D(QWSServer);
1483     return d->windows;
1484 }
1485 
1486 /*!
1487   \internal
1488 */
releaseMouse(QWSWindow * w)1489 void QWSServerPrivate::releaseMouse(QWSWindow* w)
1490 {
1491     if (w && mouseGrabber == w) {
1492         mouseGrabber = 0;
1493         mouseGrabbing = false;
1494 #ifndef QT_NO_QWS_CURSOR
1495         if (nextCursor) {
1496             // Not grabbing -> set the correct cursor
1497             setCursor(nextCursor);
1498             nextCursor = 0;
1499         }
1500 #endif
1501     }
1502 }
1503 
1504 /*!
1505   \internal
1506 */
releaseKeyboard(QWSWindow * w)1507 void QWSServerPrivate::releaseKeyboard(QWSWindow* w)
1508 {
1509     if (keyboardGrabber == w) {
1510         keyboardGrabber = 0;
1511         keyboardGrabbing = false;
1512     }
1513 }
1514 
handleWindowClose(QWSWindow * w)1515 void QWSServerPrivate::handleWindowClose(QWSWindow *w)
1516 {
1517     w->shuttingDown();
1518     if (focusw == w)
1519         setFocus(w,false);
1520     if (mouseGrabber == w)
1521         releaseMouse(w);
1522     if (keyboardGrabber == w)
1523         releaseKeyboard(w);
1524 }
1525 
1526 
1527 #ifndef QT_NO_QWS_MULTIPROCESS
1528 /*!
1529   \internal
1530 */
_q_newConnection()1531 void QWSServerPrivate::_q_newConnection()
1532 {
1533     Q_Q(QWSServer);
1534     while (QWS_SOCK_BASE *sock = ssocket->nextPendingConnection()) {
1535         int socket = sock->socketDescriptor();
1536         sock->setParent(0);
1537 
1538         QWSClient *client = new QWSClient(q,sock, get_object_id());
1539         clientMap[socket] = client;
1540 
1541 #ifndef QT_NO_SXE
1542 #ifdef QTRANSPORTAUTH_DEBUG
1543         qDebug( "Transport auth connected: unix stream socket %d", socket );
1544 #endif
1545         // get a handle to the per-process authentication service
1546         QTransportAuth *a = QTransportAuth::getInstance();
1547 
1548         // assert that this transport is trusted
1549         QTransportAuth::Data *d = a->connectTransport(
1550                 QTransportAuth::UnixStreamSock |
1551                 QTransportAuth::Trusted, socket );
1552 
1553         QAuthDevice *ad = a->recvBuf( d, sock );
1554         ad->setClient(client);
1555 
1556         QObject::connect(ad, SIGNAL(readyRead()),
1557                 q, SLOT(_q_doClient()));
1558 
1559         QObject::connect(client, SIGNAL(connectionClosed()),
1560                 q, SLOT(_q_clientClosed()));
1561 #else
1562         QObject::connect(client, SIGNAL(readyRead()),
1563                          q, SLOT(_q_doClient()));
1564         QObject::connect(client, SIGNAL(connectionClosed()),
1565                          q, SLOT(_q_clientClosed()));
1566 #endif // QT_NO_SXE
1567 
1568         client->sendConnectedEvent(qws_display_spec.constData());
1569 
1570         if (clientMap.contains(socket)) {
1571             QList<QScreen*> screens = qt_screen->subScreens();
1572             if (screens.isEmpty())
1573                 screens.append(qt_screen);
1574             for (int i = 0; i < screens.size(); ++i) {
1575                 const QApplicationPrivate *ap = QApplicationPrivate::instance();
1576                 QScreen *screen = screens.at(i);
1577                 const QRect rect = ap->maxWindowRect(screen);
1578                 if (!rect.isEmpty())
1579                     client->sendMaxWindowRectEvent(rect);
1580                 if (screen->isTransformed()) {
1581                     QWSScreenTransformationEvent event;
1582                     event.simpleData.screen = i;
1583                     event.simpleData.transformation = screen->transformOrientation();
1584                     client->sendEvent(&event);
1585                 }
1586             }
1587         }
1588 
1589         // pre-provide some object id's
1590         QWSCreateCommand cmd(30);
1591         invokeCreate(&cmd, client);
1592     }
1593 }
1594 /*!
1595   \internal
1596 */
_q_clientClosed()1597 void QWSServerPrivate::_q_clientClosed()
1598 {
1599     Q_Q(QWSServer);
1600     QWSClient* cl = (QWSClient*)q->sender();
1601 
1602     // Remove any queued commands for this client
1603     int i = 0;
1604     while (i < commandQueue.size()) {
1605         QWSCommandStruct *cs = commandQueue.at(i);
1606         if (cs->client == cl) {
1607             commandQueue.removeAt(i);
1608             delete cs;
1609         } else {
1610             ++i;
1611         }
1612     }
1613 
1614 #ifndef QT_NO_COP
1615     // Enfore unsubscription from all channels.
1616     QCopChannel::detach(cl);
1617 #endif
1618 
1619     // Shut down all windows for this client
1620     for (int i = 0; i < windows.size(); ++i) {
1621         QWSWindow* w = windows.at(i);
1622         if (w->forClient(cl))
1623             w->shuttingDown();
1624     }
1625 
1626     // Delete all windows for this client
1627     QRegion exposed;
1628     i = 0;
1629     while (i < windows.size()) {
1630         QWSWindow* w = windows.at(i);
1631         if (w->forClient(cl)) {
1632             windows.takeAt(i);
1633             w->c = 0; //so we don't send events to it anymore
1634             releaseMouse(w);
1635             releaseKeyboard(w);
1636             exposed += w->allocatedRegion();
1637 //                rgnMan->remove(w->allocationIndex());
1638             if (focusw == w)
1639                 setFocus(focusw,0);
1640             if (mouseGrabber == w)
1641                 releaseMouse(w);
1642             if (i < nReserved)
1643                 --nReserved;
1644 #ifndef QT_NO_QWS_PROPERTIES
1645             propertyManager.removeProperties(w->winId());
1646 #endif
1647             emit q->windowEvent(w, QWSServer::Destroy);
1648             w->d->state = QWSWindow::Destroyed; //???
1649             deletedWindows.append(w);
1650         } else {
1651             ++i;
1652         }
1653     }
1654     if (deletedWindows.count())
1655         QTimer::singleShot(0, q, SLOT(_q_deleteWindowsLater()));
1656 
1657     QWSClientPrivate *clientPrivate = cl->d_func();
1658     if (!clientPrivate->shutdown) {
1659 #if defined(QWS_DEBUG_FONTCLEANUP)
1660         qDebug() << "client" << cl->clientId() << "crashed";
1661 #endif
1662         // this would be the place to emit a signal to notify about the
1663         // crash of a client
1664         crashedClientIds.append(cl->clientId());
1665         fontCleanupTimer.start(10, q_func());
1666     }
1667     clientPrivate->shutdown = true;
1668 
1669     while (!clientPrivate->usedFonts.isEmpty()) {
1670         const QByteArray font = *clientPrivate->usedFonts.begin();
1671 #if defined(QWS_DEBUG_FONTCLEANUP)
1672         qDebug() << "dereferencing font" << font << "from disconnected client";
1673 #endif
1674         dereferenceFont(clientPrivate, font);
1675     }
1676     clientPrivate->usedFonts.clear();
1677 
1678     //qDebug("removing client %d with socket %d", cl->clientId(), cl->socket());
1679     clientMap.remove(cl->socket());
1680     if (cl == cursorClient)
1681         cursorClient = 0;
1682     if (qt_screen->clearCacheFunc)
1683         (qt_screen->clearCacheFunc)(qt_screen, cl->clientId());  // remove any remaining cache entries.
1684     cl->deleteLater();
1685 
1686     update_regions();
1687     exposeRegion(exposed);
1688 }
1689 
_q_deleteWindowsLater()1690 void QWSServerPrivate::_q_deleteWindowsLater()
1691 {
1692     qDeleteAll(deletedWindows);
1693     deletedWindows.clear();
1694 }
1695 
1696 #endif //QT_NO_QWS_MULTIPROCESS
1697 
referenceFont(QWSClientPrivate * client,const QByteArray & font)1698 void QWSServerPrivate::referenceFont(QWSClientPrivate *client, const QByteArray &font)
1699 {
1700     if (!client->usedFonts.contains(font)) {
1701         client->usedFonts.insert(font);
1702 
1703         ++fontReferenceCount[font];
1704 #if defined(QWS_DEBUG_FONTCLEANUP)
1705         qDebug() << "Client" << client->q_func()->clientId() << "added font" << font;
1706         qDebug() << "Refcount is" << fontReferenceCount[font];
1707 #endif
1708     }
1709 }
1710 
dereferenceFont(QWSClientPrivate * client,const QByteArray & font)1711 void QWSServerPrivate::dereferenceFont(QWSClientPrivate *client, const QByteArray &font)
1712 {
1713     if (client->usedFonts.contains(font)) {
1714         client->usedFonts.remove(font);
1715 
1716         Q_ASSERT(fontReferenceCount[font]);
1717         if (!--fontReferenceCount[font] && !fontCleanupTimer.isActive())
1718             fontCleanupTimer.start(FontCleanupInterval, q_func());
1719 
1720 #if defined(QWS_DEBUG_FONTCLEANUP)
1721         qDebug() << "Client" << client->q_func()->clientId() << "removed font" << font;
1722         qDebug() << "Refcount is" << fontReferenceCount[font];
1723 #endif
1724     }
1725 }
1726 
cleanupFontsDir()1727 static void cleanupFontsDir()
1728 {
1729     static bool dontDelete = !qgetenv("QWS_KEEP_FONTS").isEmpty();
1730     if (dontDelete)
1731         return;
1732 
1733     extern QString qws_fontCacheDir();
1734     QDir dir(qws_fontCacheDir(), QLatin1String("*.qsf"));
1735     for (uint i = 0; i < dir.count(); ++i) {
1736 #if defined(QWS_DEBUG_FONTCLEANUP)
1737         qDebug() << "removing stale font file" << dir[i];
1738 #endif
1739         dir.remove(dir[i]);
1740     }
1741 }
1742 
cleanupFonts(bool force)1743 void QWSServerPrivate::cleanupFonts(bool force)
1744 {
1745     static bool dontDelete = !qgetenv("QWS_KEEP_FONTS").isEmpty();
1746     if (dontDelete)
1747         return;
1748 
1749 #if defined(QWS_DEBUG_FONTCLEANUP)
1750     qDebug() << "cleanupFonts()";
1751 #endif
1752     if (!fontReferenceCount.isEmpty()) {
1753         QMap<QByteArray, int>::Iterator it = fontReferenceCount.begin();
1754         while (it != fontReferenceCount.end()) {
1755             if (it.value() && !force) {
1756                 ++it;
1757                 continue;
1758             }
1759 
1760             const QByteArray &fontName = it.key();
1761 #if defined(QWS_DEBUG_FONTCLEANUP)
1762             qDebug() << "removing unused font file" << fontName;
1763 #endif
1764             QT_TRY {
1765                 QFile::remove(QFile::decodeName(fontName));
1766                 sendFontRemovedEvent(fontName);
1767 
1768                 it = fontReferenceCount.erase(it);
1769             } QT_CATCH(...) {
1770                 // so we were not able to remove the font.
1771                 // don't be angry and just continue with the next ones.
1772                 ++it;
1773             }
1774         }
1775     }
1776 
1777     if (crashedClientIds.isEmpty())
1778         return;
1779 
1780     QList<QByteArray> removedFonts;
1781 #if !defined(QT_NO_QWS_QPF2) && !defined(QT_FONTS_ARE_RESOURCES)
1782     removedFonts = QFontEngineQPF::cleanUpAfterClientCrash(crashedClientIds);
1783 #endif
1784     crashedClientIds.clear();
1785 
1786     for (int i = 0; i < removedFonts.count(); ++i)
1787         sendFontRemovedEvent(removedFonts.at(i));
1788 }
1789 
sendFontRemovedEvent(const QByteArray & font)1790 void QWSServerPrivate::sendFontRemovedEvent(const QByteArray &font)
1791 {
1792     QWSFontEvent event;
1793     event.simpleData.type = QWSFontEvent::FontRemoved;
1794     event.setData(font.constData(), font.length(), false);
1795 
1796     QMap<int,QWSClient*>::const_iterator it = clientMap.constBegin();
1797     for (; it != clientMap.constEnd(); ++it)
1798         (*it)->sendEvent(&event);
1799 }
1800 
1801 /*!
1802    \internal
1803 */
readMoreCommand()1804 QWSCommand* QWSClient::readMoreCommand()
1805 {
1806 #ifndef QT_NO_QWS_MULTIPROCESS
1807     QIODevice *socket = 0;
1808 #endif
1809 #ifndef QT_NO_SXE
1810     if (socketDescriptor != -1)  // not server socket
1811         socket = QTransportAuth::getInstance()->passThroughByClient( this );
1812 #if QTRANSPORTAUTH_DEBUG
1813     if (socket) {
1814         char displaybuf[1024];
1815         qint64 bytes = socket->bytesAvailable();
1816         if ( bytes > 511 ) bytes = 511;
1817         hexstring( displaybuf, ((unsigned char *)(reinterpret_cast<QAuthDevice*>(socket)->buffer().constData())), bytes );
1818         qDebug( "readMoreCommand: %lli bytes - %s", socket->bytesAvailable(), displaybuf );
1819     }
1820 #endif
1821 #endif // QT_NO_SXE
1822 
1823 #ifndef QT_NO_QWS_MULTIPROCESS
1824     if (!socket)
1825         socket = csocket;   // server socket
1826     if (socket) {
1827         // read next command
1828         if (!command) {
1829             int command_type = qws_read_uint(socket);
1830 
1831             if (command_type >= 0)
1832                 command = QWSCommand::factory(command_type);
1833         }
1834         if (command) {
1835             if (command->read(socket)) {
1836                 // Finished reading a whole command.
1837                 QWSCommand* result = command;
1838                 command = 0;
1839                 return result;
1840             }
1841         }
1842 
1843         // Not finished reading a whole command.
1844         return 0;
1845     } else
1846 #endif // QT_NO_QWS_MULTIPROCESS
1847     {
1848         QList<QWSCommand*> *serverQueue = qt_get_server_queue();
1849         return serverQueue->isEmpty() ? 0 : serverQueue->takeFirst();
1850     }
1851 }
1852 
1853 
1854 /*!
1855   \internal
1856 */
processEventQueue()1857 void QWSServer::processEventQueue()
1858 {
1859     if (qwsServerPrivate)
1860         qwsServerPrivate->doClient(qwsServerPrivate->clientMap.value(-1));
1861 }
1862 
1863 
1864 #ifndef QT_NO_QWS_MULTIPROCESS
_q_doClient()1865 void QWSServerPrivate::_q_doClient()
1866 {
1867     Q_Q(QWSServer);
1868 
1869     QWSClient* client;
1870 #ifndef QT_NO_SXE
1871     QAuthDevice *ad = qobject_cast<QAuthDevice*>(q->sender());
1872     if (ad)
1873         client = (QWSClient*)ad->client();
1874     else
1875 #endif
1876         client = (QWSClient*)q->sender();
1877 
1878     if (doClientIsActive) {
1879         pendingDoClients.append(client);
1880         return;
1881     }
1882     doClientIsActive = true;
1883 
1884     doClient(client);
1885 
1886     while (!pendingDoClients.isEmpty()) {
1887         doClient(pendingDoClients.takeFirst());
1888     }
1889 
1890     doClientIsActive = false;
1891 }
1892 #endif // QT_NO_QWS_MULTIPROCESS
1893 
doClient(QWSClient * client)1894 void QWSServerPrivate::doClient(QWSClient *client)
1895 {
1896     QWSCommand* command=client->readMoreCommand();
1897 
1898     while (command) {
1899         QWSCommandStruct *cs = new QWSCommandStruct(command, client);
1900         commandQueue.append(cs);
1901         // Try for some more...
1902         command=client->readMoreCommand();
1903     }
1904 
1905     while (!commandQueue.isEmpty()) {
1906         QWSCommandStruct *cs = commandQueue.takeAt(0);
1907         switch (cs->command->type) {
1908         case QWSCommand::Identify:
1909             invokeIdentify((QWSIdentifyCommand*)cs->command, cs->client);
1910             break;
1911         case QWSCommand::Create:
1912             invokeCreate((QWSCreateCommand*)cs->command, cs->client);
1913             break;
1914 #ifndef QT_NO_QWS_MULTIPROCESS
1915         case QWSCommand::Shutdown:
1916             cs->client->d_func()->shutdown = true;
1917             break;
1918 #endif
1919         case QWSCommand::RegionName:
1920             invokeRegionName((QWSRegionNameCommand*)cs->command, cs->client);
1921             break;
1922         case QWSCommand::Region:
1923             invokeRegion((QWSRegionCommand*)cs->command, cs->client);
1924             cs->client->d_func()->unlockCommunication();
1925             break;
1926         case QWSCommand::RegionMove:
1927             invokeRegionMove((QWSRegionMoveCommand*)cs->command, cs->client);
1928             cs->client->d_func()->unlockCommunication();
1929             break;
1930         case QWSCommand::RegionDestroy:
1931             invokeRegionDestroy((QWSRegionDestroyCommand*)cs->command, cs->client);
1932             break;
1933 #ifndef QT_NO_QWS_PROPERTIES
1934         case QWSCommand::AddProperty:
1935             invokeAddProperty((QWSAddPropertyCommand*)cs->command);
1936             break;
1937         case QWSCommand::SetProperty:
1938             invokeSetProperty((QWSSetPropertyCommand*)cs->command);
1939             break;
1940         case QWSCommand::RemoveProperty:
1941             invokeRemoveProperty((QWSRemovePropertyCommand*)cs->command);
1942             break;
1943         case QWSCommand::GetProperty:
1944             invokeGetProperty((QWSGetPropertyCommand*)cs->command, cs->client);
1945             break;
1946 #endif
1947         case QWSCommand::SetSelectionOwner:
1948             invokeSetSelectionOwner((QWSSetSelectionOwnerCommand*)cs->command);
1949             break;
1950         case QWSCommand::RequestFocus:
1951             invokeSetFocus((QWSRequestFocusCommand*)cs->command, cs->client);
1952             break;
1953         case QWSCommand::ChangeAltitude:
1954             invokeSetAltitude((QWSChangeAltitudeCommand*)cs->command,
1955                                cs->client);
1956             cs->client->d_func()->unlockCommunication();
1957             break;
1958         case QWSCommand::SetOpacity:
1959             invokeSetOpacity((QWSSetOpacityCommand*)cs->command,
1960                                cs->client);
1961             break;
1962 
1963 #ifndef QT_NO_QWS_CURSOR
1964         case QWSCommand::DefineCursor:
1965             invokeDefineCursor((QWSDefineCursorCommand*)cs->command, cs->client);
1966             break;
1967         case QWSCommand::SelectCursor:
1968             invokeSelectCursor((QWSSelectCursorCommand*)cs->command, cs->client);
1969             break;
1970         case QWSCommand::PositionCursor:
1971             invokePositionCursor((QWSPositionCursorCommand*)cs->command, cs->client);
1972             break;
1973 #endif
1974         case QWSCommand::GrabMouse:
1975             invokeGrabMouse((QWSGrabMouseCommand*)cs->command, cs->client);
1976             break;
1977         case QWSCommand::GrabKeyboard:
1978             invokeGrabKeyboard((QWSGrabKeyboardCommand*)cs->command, cs->client);
1979             break;
1980 #if !defined(QT_NO_SOUND) && !defined(Q_OS_DARWIN)
1981         case QWSCommand::PlaySound:
1982             invokePlaySound((QWSPlaySoundCommand*)cs->command, cs->client);
1983             break;
1984 #endif
1985 #ifndef QT_NO_COP
1986         case QWSCommand::QCopRegisterChannel:
1987             invokeRegisterChannel((QWSQCopRegisterChannelCommand*)cs->command,
1988                                    cs->client);
1989             break;
1990         case QWSCommand::QCopSend:
1991             invokeQCopSend((QWSQCopSendCommand*)cs->command, cs->client);
1992             break;
1993 #endif
1994 #ifndef QT_NO_QWS_INPUTMETHODS
1995         case QWSCommand::IMUpdate:
1996             invokeIMUpdate((QWSIMUpdateCommand*)cs->command, cs->client);
1997             break;
1998         case QWSCommand::IMResponse:
1999             invokeIMResponse((QWSIMResponseCommand*)cs->command, cs->client);
2000             break;
2001         case QWSCommand::IMMouse:
2002             {
2003                 if (current_IM) {
2004                     QWSIMMouseCommand *cmd = (QWSIMMouseCommand *) cs->command;
2005                     current_IM->mouseHandler(cmd->simpleData.index,
2006                                               cmd->simpleData.state);
2007                 }
2008             }
2009             break;
2010 #endif
2011         case QWSCommand::Font:
2012             invokeFont((QWSFontCommand *)cs->command, cs->client);
2013             break;
2014         case QWSCommand::RepaintRegion:
2015             invokeRepaintRegion((QWSRepaintRegionCommand*)cs->command,
2016                                 cs->client);
2017             cs->client->d_func()->unlockCommunication();
2018             break;
2019 #ifndef QT_NO_QWSEMBEDWIDGET
2020         case QWSCommand::Embed:
2021             invokeEmbed(static_cast<QWSEmbedCommand*>(cs->command),
2022                         cs->client);
2023             break;
2024 #endif
2025         case QWSCommand::ScreenTransform:
2026             invokeScreenTransform(static_cast<QWSScreenTransformCommand*>(cs->command),
2027                                   cs->client);
2028             break;
2029         }
2030         delete cs;
2031     }
2032 }
2033 
2034 
showCursor()2035 void QWSServerPrivate::showCursor()
2036 {
2037 #ifndef QT_NO_QWS_CURSOR
2038     if (qt_screencursor)
2039         qt_screencursor->show();
2040 #endif
2041 }
2042 
hideCursor()2043 void QWSServerPrivate::hideCursor()
2044 {
2045 #ifndef QT_NO_QWS_CURSOR
2046     if (qt_screencursor)
2047         qt_screencursor->hide();
2048 #endif
2049 }
2050 
2051 /*!
2052     \fn void QWSServer::enablePainting(bool enable)
2053 
2054     Enables painting onto the screen if \a enable is true; otherwise
2055     painting is disabled.
2056 
2057     \sa {Qt for Embedded Linux Architecture#Drawing on Screen}{Qt for Embedded Linux
2058     Architecture}
2059 */
enablePainting(bool enable)2060 void QWSServer::enablePainting(bool enable)
2061 {
2062     Q_D(QWSServer);
2063 
2064     if (d->disablePainting == !enable)
2065         return;
2066 
2067     d->disablePainting = !enable;
2068 
2069     if (enable) {
2070         // Reset the server side allocated regions to ensure update_regions()
2071         // will send out region events.
2072         for (int i = 0; i < d->windows.size(); ++i) {
2073             QWSWindow *w = d->windows.at(i);
2074             w->setAllocatedRegion(QRegion());
2075 #ifdef QT_QWS_CLIENTBLIT
2076             w->setDirectPaintRegion(QRegion());
2077 #endif
2078         }
2079         d->update_regions();
2080         d->showCursor();
2081     } else {
2082         // Disable painting by clients by taking away their allocated region.
2083         // To ensure mouse events are still delivered to the correct windows,
2084         // the allocated regions are not modified on the server.
2085         for (int i = 0; i < d->windows.size(); ++i) {
2086             QWSWindow *w = d->windows.at(i);
2087             w->client()->sendRegionEvent(w->winId(), QRegion(),
2088                                          QWSRegionEvent::Allocation);
2089 #ifdef QT_QWS_CLIENTBLIT
2090             w->client()->sendRegionEvent(w->winId(), QRegion(),
2091                                          QWSRegionEvent::DirectPaint);
2092 #endif
2093         }
2094         d->hideCursor();
2095     }
2096 }
2097 
2098 /*!
2099     Refreshes the display by making the screen driver update the
2100     entire display.
2101 
2102     \sa QScreen::exposeRegion()
2103 */
refresh()2104 void QWSServer::refresh()
2105 {
2106     Q_D(QWSServer);
2107     d->exposeRegion(QScreen::instance()->region());
2108 //### send repaint to non-buffered windows
2109 }
2110 
2111 /*!
2112     \fn void QWSServer::refresh(QRegion & region)
2113     \overload
2114 
2115     Refreshes the given \a region of the display.
2116 */
refresh(QRegion & r)2117 void QWSServer::refresh(QRegion & r)
2118 {
2119     Q_D(QWSServer);
2120     d->exposeRegion(r);
2121 //### send repaint to non-buffered windows
2122 }
2123 
2124 /*!
2125     \fn void QWSServer::setMaxWindowRect(const QRect& rectangle)
2126 
2127     Sets the maximum area of the screen that \l{Qt for Embedded Linux}
2128     applications can use, to be the given \a rectangle.
2129 
2130     Note that this function can only be used in the server process.
2131 
2132     \sa QWidget::showMaximized()
2133 */
setMaxWindowRect(const QRect & rect)2134 void QWSServer::setMaxWindowRect(const QRect &rect)
2135 {
2136     QList<QScreen*> subScreens = qt_screen->subScreens();
2137     if (subScreens.isEmpty() && qt_screen != 0)
2138         subScreens.append(qt_screen);
2139 
2140     for (int i = 0; i < subScreens.size(); ++i) {
2141         const QScreen *screen = subScreens.at(i);
2142         const QRect r = (screen->region() & rect).boundingRect();
2143         if (r.isEmpty())
2144             continue;
2145 
2146         QApplicationPrivate *ap = QApplicationPrivate::instance();
2147         if (ap->maxWindowRect(screen) != r) {
2148             ap->setMaxWindowRect(screen, i, r);
2149             qwsServerPrivate->sendMaxWindowRectEvents(r);
2150         }
2151     }
2152 }
2153 
2154 /*!
2155   \internal
2156 */
sendMaxWindowRectEvents(const QRect & rect)2157 void QWSServerPrivate::sendMaxWindowRectEvents(const QRect &rect)
2158 {
2159     QMap<int,QWSClient*>::const_iterator it = clientMap.constBegin();
2160     for (; it != clientMap.constEnd(); ++it)
2161         (*it)->sendMaxWindowRectEvent(rect);
2162 }
2163 
2164 /*!
2165     \fn void QWSServer::setDefaultMouse(const char *mouseDriver)
2166 
2167     Sets the mouse driver that will be used if the QWS_MOUSE_PROTO
2168     environment variable is not defined, to be the given \a
2169     mouseDriver.
2170 
2171     Note that the default is platform-dependent. This function can
2172     only be used in the server process.
2173 
2174 
2175     \sa setMouseHandler(), {Qt for Embedded Linux Pointer Handling}
2176 */
setDefaultMouse(const char * m)2177 void QWSServer::setDefaultMouse(const char *m)
2178 {
2179     *defaultMouse() = QString::fromAscii(m);
2180 }
2181 
2182 /*!
2183     \fn void QWSServer::setDefaultKeyboard(const char *keyboardDriver)
2184 
2185     Sets the keyboard driver that will be used if the QWS_KEYBOARD
2186     environment variable is not defined, to be the given \a
2187     keyboardDriver.
2188 
2189     Note that the default is platform-dependent. This function can
2190     only be used in the server process.
2191 
2192     \sa setKeyboardHandler(), {Qt for Embedded Linux Character Input}
2193 */
setDefaultKeyboard(const char * k)2194 void QWSServer::setDefaultKeyboard(const char *k)
2195 {
2196     *defaultKeyboard() = QString::fromAscii(k);
2197 }
2198 
2199 #ifndef QT_NO_QWS_CURSOR
2200 static bool prevWin;
2201 #endif
2202 
2203 
2204 extern int *qt_last_x,*qt_last_y;
2205 
2206 
2207 /*!
2208   \internal
2209 
2210   Send a mouse event. \a pos is the screen position where the mouse
2211   event occurred and \a state is a mask indicating which buttons are
2212   pressed.
2213 
2214   \a pos is in device coordinates
2215 */
sendMouseEvent(const QPoint & pos,int state,int wheel)2216 void QWSServer::sendMouseEvent(const QPoint& pos, int state, int wheel)
2217 {
2218     bool block = qwsServerPrivate->screensaverblockevent(MOUSE, qwsServerPrivate->screensaverinterval, state);
2219 #ifdef EVENT_BLOCK_DEBUG
2220     qDebug() << "sendMouseEvent" << pos.x() << pos.y() << state << (block ? "block" : "pass");
2221 #endif
2222 
2223     if (state || wheel)
2224         qwsServerPrivate->_q_screenSaverWake();
2225 
2226     if ( block )
2227         return;
2228 
2229     QPoint tpos;
2230     // transformations
2231     if (qt_screen->isTransformed()) {
2232 	QSize s = QSize(qt_screen->deviceWidth(), qt_screen->deviceHeight());
2233 	tpos = qt_screen->mapFromDevice(pos, s);
2234     } else {
2235 	tpos = pos;
2236     }
2237 
2238     if (qt_last_x) {
2239          *qt_last_x = tpos.x();
2240          *qt_last_y = tpos.y();
2241     }
2242     QWSServer::mousePosition = tpos;
2243     qwsServerPrivate->mouseState = state;
2244 
2245 #ifndef QT_NO_QWS_INPUTMETHODS
2246     const int btnMask = Qt::LeftButton | Qt::RightButton | Qt::MidButton;
2247     int stroke_count; // number of strokes to keep shown.
2248     if (force_reject_strokeIM || !current_IM)
2249     {
2250 	stroke_count = 0;
2251     } else {
2252 	stroke_count = current_IM->filter(tpos, state, wheel);
2253     }
2254 
2255     if (stroke_count == 0) {
2256 	if (state&btnMask)
2257 	    force_reject_strokeIM = true;
2258         QWSServerPrivate::sendMouseEventUnfiltered(tpos, state, wheel);
2259     }
2260     // stop force reject after stroke ends.
2261     if (state&btnMask && force_reject_strokeIM)
2262 	force_reject_strokeIM = false;
2263     // on end of stroke, force_rejct
2264     // and once a stroke is rejected, do not try again till pen is lifted
2265 #else
2266     QWSServerPrivate::sendMouseEventUnfiltered(tpos, state, wheel);
2267 #endif // end QT_NO_QWS_FSIM
2268 }
2269 
sendMouseEventUnfiltered(const QPoint & pos,int state,int wheel)2270 void QWSServerPrivate::sendMouseEventUnfiltered(const QPoint &pos, int state, int wheel)
2271 {
2272     const int btnMask = Qt::LeftButton | Qt::RightButton | Qt::MidButton;
2273     QWSMouseEvent event;
2274 
2275     QWSWindow *win = qwsServer->windowAt(pos);
2276 
2277     QWSClient *serverClient = qwsServerPrivate->clientMap.value(-1);
2278     QWSClient *winClient = win ? win->client() : 0;
2279 
2280 
2281     bool imMouse = false;
2282 #ifndef QT_NO_QWS_INPUTMETHODS
2283     // check for input method window
2284     if (current_IM && current_IM_winId != -1) {
2285         QWSWindow *kbw = keyboardGrabber ? keyboardGrabber :
2286                          qwsServerPrivate->focusw;
2287 
2288         imMouse = kbw == win;
2289         if ( !imMouse ) {
2290             QWidget *target = winClient == serverClient ?
2291                               QApplication::widgetAt(pos) : 0;
2292             imMouse = target && (target->testAttribute(Qt::WA_InputMethodTransparent));
2293         }
2294     }
2295 #endif
2296 
2297     //If grabbing window disappears, grab is still active until
2298     //after mouse release.
2299     if ( qwsServerPrivate->mouseGrabber && (!imMouse || qwsServerPrivate->inputMethodMouseGrabbed)) {
2300         win = qwsServerPrivate->mouseGrabber;
2301         winClient = win ? win->client() : 0;
2302     }
2303     event.simpleData.window = win ? win->id : 0;
2304 
2305 #ifndef QT_NO_QWS_CURSOR
2306     if (qt_screencursor)
2307         qt_screencursor->move(pos.x(),pos.y());
2308 
2309     // Arrow cursor over desktop
2310     // prevWin remembers if the last event was over a window
2311     if (!win && prevWin) {
2312         if (!qwsServerPrivate->mouseGrabber)
2313             qwsServerPrivate->setCursor(QWSCursor::systemCursor(Qt::ArrowCursor));
2314         else
2315             qwsServerPrivate->nextCursor = QWSCursor::systemCursor(Qt::ArrowCursor);
2316         prevWin = false;
2317     }
2318     // reset prevWin
2319     if (win && !prevWin)
2320         prevWin = true;
2321 #endif
2322 
2323     if ((state&btnMask) && !qwsServerPrivate->mouseGrabbing) {
2324         qwsServerPrivate->mouseGrabber = win;
2325         if (imMouse)
2326             qwsServerPrivate->inputMethodMouseGrabbed = true;
2327     }
2328     if (!(state&btnMask))
2329         qwsServerPrivate->inputMethodMouseGrabbed = false;
2330 
2331     event.simpleData.x_root=pos.x();
2332     event.simpleData.y_root=pos.y();
2333     event.simpleData.state=state | qws_keyModifiers;
2334     event.simpleData.delta = wheel;
2335     event.simpleData.time=qwsServerPrivate->timer.elapsed();
2336 
2337     static int oldstate = 0;
2338 
2339 #ifndef QT_NO_QWS_INPUTMETHODS
2340     //tell the input method if we click on a different window that is not IM transparent
2341     bool isPress = state > oldstate;
2342     if (isPress && !imMouse && current_IM && current_IM_winId != -1)
2343         current_IM->mouseHandler(-1, QWSServer::MouseOutside);
2344 #endif
2345 
2346     if (serverClient)
2347        serverClient->sendEvent(&event);
2348     if (winClient && winClient != serverClient)
2349        winClient->sendEvent(&event);
2350 
2351     if ( !imMouse ) {
2352         // Make sure that if we leave a window, that window gets one last mouse
2353         // event so that it knows the mouse has left.
2354         QWSClient *oldClient = qwsServer->d_func()->cursorClient;
2355         if (oldClient && oldClient != winClient && oldClient != serverClient) {
2356             event.simpleData.state = oldstate | qws_keyModifiers;
2357             oldClient->sendEvent(&event);
2358         }
2359     }
2360 
2361     oldstate = state;
2362     if ( !imMouse )
2363         qwsServer->d_func()->cursorClient = winClient;
2364 
2365     if (!(state&btnMask) && !qwsServerPrivate->mouseGrabbing)
2366         qwsServerPrivate->releaseMouse(qwsServerPrivate->mouseGrabber);
2367 }
2368 
2369 /*!
2370     Returns the primary mouse driver.
2371 
2372     Note that this function can only be used in the server process.
2373 
2374     \sa setMouseHandler(), openMouse(), closeMouse()
2375 */
mouseHandler()2376 QWSMouseHandler *QWSServer::mouseHandler()
2377 {
2378     if (qwsServerPrivate->mousehandlers.empty())
2379         return 0;
2380     return qwsServerPrivate->mousehandlers.first();
2381 }
2382 
2383 /*!
2384     \since 4.5
2385 
2386     Returns list of all mouse handlers
2387 
2388     Note that this function can only be used in the server process.
2389 
2390     \sa mouseHandler(), setMouseHandler(), openMouse(), closeMouse()
2391 */
mouseHandlers()2392 const QList<QWSMouseHandler*>& QWSServer::mouseHandlers()
2393 {
2394     return qwsServerPrivate->mousehandlers;
2395 }
2396 
2397 
2398 // called by QWSMouseHandler constructor, not user code.
2399 /*!
2400     \fn void QWSServer::setMouseHandler(QWSMouseHandler* driver)
2401 
2402     Sets the primary mouse driver to be the given \a driver.
2403 
2404     \l{Qt for Embedded Linux} provides several ready-made mouse drivers, and
2405     custom drivers are typically added using Qt's plugin
2406     mechanism. See the \l{Qt for Embedded Linux Pointer Handling} documentation
2407     for details.
2408 
2409     Note that this function can only be used in the server process.
2410 
2411     \sa mouseHandler(), setDefaultMouse()
2412 */
setMouseHandler(QWSMouseHandler * mh)2413 void QWSServer::setMouseHandler(QWSMouseHandler* mh)
2414 {
2415     if (!mh)
2416         return;
2417     qwsServerPrivate->mousehandlers.removeAll(mh);
2418     qwsServerPrivate->mousehandlers.prepend(mh);
2419 }
2420 
2421 /*!
2422   \internal
2423   \obsolete
2424   Caller owns data in list, and must delete contents
2425 */
windowList()2426 QList<QWSInternalWindowInfo*> * QWSServer::windowList()
2427 {
2428     QList<QWSInternalWindowInfo*> * ret=new QList<QWSInternalWindowInfo*>;
2429     for (int i=0; i < qwsServerPrivate->windows.size(); ++i) {
2430         QWSWindow *window = qwsServerPrivate->windows.at(i);
2431         QWSInternalWindowInfo * qwi=new QWSInternalWindowInfo();
2432         qwi->winid=window->winId();
2433         qwi->clientid=window->client()->clientId();
2434         ret->append(qwi);
2435     }
2436     return ret;
2437 }
2438 
2439 #ifndef QT_NO_COP
2440 /*!
2441   \internal
2442 */
sendQCopEvent(QWSClient * c,const QString & ch,const QString & msg,const QByteArray & data,bool response)2443 void QWSServerPrivate::sendQCopEvent(QWSClient *c, const QString &ch,
2444                                const QString &msg, const QByteArray &data,
2445                                bool response)
2446 {
2447     Q_ASSERT(c);
2448 
2449     QWSQCopMessageEvent event;
2450     event.channel = ch.toLatin1();
2451     event.message = msg.toLatin1();
2452     event.data = data;
2453     event.simpleData.is_response = response;
2454     event.simpleData.lchannel = ch.length();
2455     event.simpleData.lmessage = msg.length();
2456     event.simpleData.ldata = data.size();
2457     int l = event.simpleData.lchannel + event.simpleData.lmessage +
2458             event.simpleData.ldata;
2459 
2460     // combine channel, message and data into one block of raw bytes
2461     char *tmp = new char [l];
2462     char *d = tmp;
2463     memcpy(d, event.channel.constData(), event.simpleData.lchannel);
2464     d += event.simpleData.lchannel;
2465     memcpy(d, event.message.constData(), event.simpleData.lmessage);
2466     d += event.simpleData.lmessage;
2467     memcpy(d, data.constData(), event.simpleData.ldata);
2468 
2469     event.setDataDirect(tmp, l);
2470 
2471     c->sendEvent(&event);
2472 }
2473 #endif
2474 
2475 /*!
2476     \fn QWSWindow *QWSServer::windowAt(const QPoint& position)
2477 
2478     Returns the window containing the given \a position.
2479 
2480     Note that if there is no window under the specified point this
2481     function returns 0.
2482 
2483     \sa clientWindows(), instance()
2484 */
windowAt(const QPoint & pos)2485 QWSWindow *QWSServer::windowAt(const QPoint& pos)
2486 {
2487     Q_D(QWSServer);
2488     for (int i=0; i<d->windows.size(); ++i) {
2489         QWSWindow* w = d->windows.at(i);
2490         if (w->allocatedRegion().contains(pos))
2491             return w;
2492     }
2493     return 0;
2494 }
2495 
2496 #ifndef QT_NO_QWS_KEYBOARD
keyUnicode(int keycode)2497 static inline int keyUnicode(int keycode)
2498 {
2499     int code = 0xffff;
2500 
2501     if (keycode >= Qt::Key_A && keycode <= Qt::Key_Z)
2502         code = keycode - Qt::Key_A + 'a';
2503     else if (keycode >= Qt::Key_0 && keycode <= Qt::Key_9)
2504         code = keycode - Qt::Key_0 + '0';
2505 
2506     return code;
2507 }
2508 #endif
2509 
2510 /*!
2511     Sends the given key event. The key is identified by its \a unicode
2512     value and the given \a keycode, \a modifiers, \a isPress and \a
2513     autoRepeat parameters.
2514 
2515     Use this function to send key events generated by "virtual
2516     keyboards" (note that the processKeyEvent() function is
2517     impelemented using this function).
2518 
2519     The \a keycode parameter is the Qt keycode value as defined by the
2520     Qt::Key enum. The \a modifiers is an OR combination of
2521     Qt::KeyboardModifier values, indicating whether \gui
2522     Shift/Alt/Ctrl keys are pressed. The \a isPress parameter is true
2523     if the event is a key press event and \a autoRepeat is true if the
2524     event is caused by an auto-repeat mechanism and not an actual key
2525     press.
2526 
2527     Note that this function can only be used in the server process.
2528 
2529     \sa processKeyEvent(), {Qt for Embedded Linux Character Input}
2530 */
sendKeyEvent(int unicode,int keycode,Qt::KeyboardModifiers modifiers,bool isPress,bool autoRepeat)2531 void QWSServer::sendKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
2532                              bool isPress, bool autoRepeat)
2533 {
2534     qws_keyModifiers = modifiers;
2535 
2536     if (isPress) {
2537         if (keycode != Qt::Key_F34 && keycode != Qt::Key_F35)
2538             qwsServerPrivate->_q_screenSaverWake();
2539     }
2540 
2541 #ifndef QT_NO_QWS_INPUTMETHODS
2542 
2543     if (!current_IM || !current_IM->filter(unicode, keycode, modifiers, isPress, autoRepeat))
2544         QWSServerPrivate::sendKeyEventUnfiltered(unicode, keycode, modifiers, isPress, autoRepeat);
2545 #else
2546     QWSServerPrivate::sendKeyEventUnfiltered(unicode, keycode, modifiers, isPress, autoRepeat);
2547 #endif
2548 }
2549 
sendKeyEventUnfiltered(int unicode,int keycode,Qt::KeyboardModifiers modifiers,bool isPress,bool autoRepeat)2550 void QWSServerPrivate::sendKeyEventUnfiltered(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
2551                                        bool isPress, bool autoRepeat)
2552 {
2553     QWSWindow *win = keyboardGrabber ? keyboardGrabber : qwsServerPrivate->focusw;
2554 
2555 #ifndef QT_NO_QWS_KEYBOARD
2556     if (unicode < 0)
2557         unicode = keyUnicode(keycode);
2558 #endif
2559 
2560     QWSKeyEvent event;
2561     event.simpleData.window = win ? win->winId() : 0;
2562     event.simpleData.unicode = unicode;
2563     event.simpleData.keycode = keycode;
2564     event.simpleData.modifiers = modifiers;
2565     event.simpleData.is_press = isPress;
2566     event.simpleData.is_auto_repeat = autoRepeat;
2567 
2568     QWSClient *serverClient = qwsServerPrivate->clientMap.value(-1);
2569     QWSClient *winClient = win ? win->client() : 0;
2570     if (serverClient)
2571         serverClient->sendEvent(&event);
2572     if (winClient && winClient != serverClient)
2573         winClient->sendEvent(&event);
2574 }
2575 
2576 /*!
2577     \internal
2578 */
beginDisplayReconfigure()2579 void QWSServer::beginDisplayReconfigure()
2580 {
2581     qwsServer->enablePainting(false);
2582 #ifndef QT_NO_QWS_CURSOR
2583     if (qt_screencursor)
2584         qt_screencursor->hide();
2585 #endif
2586     QWSDisplay::grab(true);
2587     qt_screen->disconnect();
2588 }
2589 
2590 /*!
2591     \internal
2592 */
endDisplayReconfigure()2593 void QWSServer::endDisplayReconfigure()
2594 {
2595     qt_screen->connect(QString());
2596     qwsServerPrivate->swidth = qt_screen->deviceWidth();
2597     qwsServerPrivate->sheight = qt_screen->deviceHeight();
2598 
2599     QWSDisplay::ungrab();
2600 #ifndef QT_NO_QWS_CURSOR
2601     if (qt_screencursor)
2602         qt_screencursor->show();
2603 #endif
2604     QApplicationPrivate *ap = QApplicationPrivate::instance();
2605     ap->setMaxWindowRect(qt_screen, 0,
2606                          QRect(0, 0, qt_screen->width(), qt_screen->height()));
2607     QSize olds = qApp->desktop()->size();
2608     qApp->desktop()->resize(qt_screen->width(), qt_screen->height());
2609     qApp->postEvent(qApp->desktop(), new QResizeEvent(qApp->desktop()->size(), olds));
2610     qwsServer->enablePainting(true);
2611     qwsServer->refresh();
2612     qDebug("Desktop size: %dx%d", qApp->desktop()->width(), qApp->desktop()->height());
2613 }
2614 
resetEngine()2615 void QWSServerPrivate::resetEngine()
2616 {
2617 #ifndef QT_NO_QWS_CURSOR
2618     if (!qt_screencursor)
2619         return;
2620     qt_screencursor->hide();
2621     qt_screencursor->show();
2622 #endif
2623 }
2624 
2625 
2626 #ifndef QT_NO_QWS_CURSOR
2627 /*!
2628     \fn void QWSServer::setCursorVisible(bool visible)
2629 
2630     Shows the cursor if \a visible is true: otherwise the cursor is
2631     hidden.
2632 
2633     Note that this function can only be used in the server process.
2634 
2635     \sa isCursorVisible()
2636 */
setCursorVisible(bool vis)2637 void QWSServer::setCursorVisible(bool vis)
2638 {
2639     if (qwsServerPrivate && qwsServerPrivate->haveviscurs != vis) {
2640         QWSCursor* c = qwsServerPrivate->cursor;
2641         qwsServerPrivate->setCursor(QWSCursor::systemCursor(Qt::BlankCursor));
2642         qwsServerPrivate->haveviscurs = vis;
2643         qwsServerPrivate->setCursor(c);
2644     }
2645 }
2646 
2647 /*!
2648     Returns true if the cursor is visible; otherwise returns false.
2649 
2650     Note that this function can only be used in the server process.
2651 
2652     \sa setCursorVisible()
2653 */
isCursorVisible()2654 bool QWSServer::isCursorVisible()
2655 {
2656     return qwsServerPrivate ? qwsServerPrivate->haveviscurs : true;
2657 }
2658 #endif
2659 
2660 #ifndef QT_NO_QWS_INPUTMETHODS
2661 
2662 
2663 /*!
2664     \fn void QWSServer::sendIMEvent(const QInputMethodEvent *event)
2665 
2666     Sends the given input method \a event.
2667 
2668     The \c QInputMethodEvent class is derived from QWSEvent, i.e., it
2669     is a QWSEvent object of the QWSEvent::IMEvent type.
2670 
2671     If there is a window actively composing the preedit string, the
2672     event is sent to that window. Otherwise, the event is sent to the
2673     window currently in focus.
2674 
2675     \sa sendIMQuery(), QWSInputMethod::sendEvent()
2676 */
sendIMEvent(const QInputMethodEvent * ime)2677 void QWSServer::sendIMEvent(const QInputMethodEvent *ime)
2678 {
2679     QWSIMEvent event;
2680 
2681     QWSWindow *win = keyboardGrabber ? keyboardGrabber :
2682                      qwsServerPrivate->focusw;
2683 
2684     //if currently composing then event must go to the composing window
2685 
2686     if (current_IM_composing_win)
2687         win = current_IM_composing_win;
2688 
2689     event.simpleData.window = win ? win->winId() : 0;
2690     event.simpleData.replaceFrom = ime->replacementStart();;
2691     event.simpleData.replaceLength = ime->replacementLength();
2692 
2693     QBuffer buffer;
2694     buffer.open(QIODevice::WriteOnly);
2695     QDataStream out(&buffer);
2696 
2697     out << ime->preeditString();
2698     out << ime->commitString();
2699 
2700     const QList<QInputMethodEvent::Attribute> &attributes = ime->attributes();
2701     for (int i = 0; i < attributes.count(); ++i) {
2702         const QInputMethodEvent::Attribute &a = attributes.at(i);
2703         out << a.type << a.start << a.length << a.value;
2704     }
2705     event.setData(buffer.data(), buffer.size());
2706     QWSClient *serverClient = qwsServerPrivate->clientMap.value(-1);
2707     if (serverClient)
2708         serverClient->sendEvent(&event);
2709     if (win && win->client() && win->client() != serverClient)
2710         win->client()->sendEvent(&event);
2711 
2712     current_IM_composing_win = ime->preeditString().isEmpty() ? 0 : win;
2713     current_IM_winId = win ? win->winId() : 0;
2714 }
2715 
2716 
2717 /*!
2718     Sends an input method query for the given \a property.
2719 
2720     To receive responses to input method queries, the virtual
2721     QWSInputMethod::queryResponse() function must be reimplemented in
2722     a QWSInputMethod subclass that is activated using the
2723     setCurrentInputMethod() function.
2724 
2725     \sa sendIMEvent(), setCurrentInputMethod()
2726 */
sendIMQuery(int property)2727 void QWSServer::sendIMQuery(int property)
2728 {
2729     QWSIMQueryEvent event;
2730 
2731     QWSWindow *win = keyboardGrabber ? keyboardGrabber :
2732                      qwsServerPrivate->focusw;
2733     if (current_IM_composing_win)
2734         win = current_IM_composing_win;
2735 
2736     event.simpleData.window = win ? win->winId() : 0;
2737     event.simpleData.property = property;
2738     if (win && win->client())
2739         win->client()->sendEvent(&event);
2740 }
2741 
2742 
2743 
2744 /*!
2745     \fn void QWSServer::setCurrentInputMethod(QWSInputMethod *method)
2746 
2747     Sets the current input method to be the given \a method.
2748 
2749     Note that this function can only be used in the server process.
2750 
2751     \sa sendIMQuery(), sendIMEvent()
2752 */
setCurrentInputMethod(QWSInputMethod * im)2753 void QWSServer::setCurrentInputMethod(QWSInputMethod *im)
2754 {
2755     if (current_IM)
2756         current_IM->reset(); //??? send an update event instead ?
2757     current_IM = im;
2758 }
2759 
2760 /*!
2761     \fn static void QWSServer::resetInputMethod()
2762 
2763     \internal
2764 */
2765 
2766 #endif //QT_NO_QWS_INPUTMETHODS
2767 
2768 #ifndef QT_NO_QWS_PROPERTIES
2769 /*!
2770   \internal
2771 */
sendPropertyNotifyEvent(int property,int state)2772 void QWSServer::sendPropertyNotifyEvent(int property, int state)
2773 {
2774     Q_D(QWSServer);
2775     QWSServerPrivate::ClientIterator it = d->clientMap.begin();
2776     while (it != d->clientMap.end()) {
2777         QWSClient *cl = *it;
2778         ++it;
2779         cl->sendPropertyNotifyEvent(property, state);
2780     }
2781 }
2782 #endif
2783 
invokeIdentify(const QWSIdentifyCommand * cmd,QWSClient * client)2784 void QWSServerPrivate::invokeIdentify(const QWSIdentifyCommand *cmd, QWSClient *client)
2785 {
2786     client->setIdentity(cmd->id);
2787 #ifndef QT_NO_QWS_MULTIPROCESS
2788     if (client->clientId() > 0)
2789         client->d_func()->setLockId(cmd->simpleData.idLock);
2790 #endif
2791 }
2792 
invokeCreate(QWSCreateCommand * cmd,QWSClient * client)2793 void QWSServerPrivate::invokeCreate(QWSCreateCommand *cmd, QWSClient *client)
2794 {
2795     QWSCreationEvent event;
2796     event.simpleData.objectid = get_object_id(cmd->count);
2797     event.simpleData.count = cmd->count;
2798     client->sendEvent(&event);
2799 }
2800 
invokeRegionName(const QWSRegionNameCommand * cmd,QWSClient * client)2801 void QWSServerPrivate::invokeRegionName(const QWSRegionNameCommand *cmd, QWSClient *client)
2802 {
2803     Q_Q(QWSServer);
2804     QWSWindow* changingw = findWindow(cmd->simpleData.windowid, client);
2805     if (changingw && (changingw->name() != cmd->name || changingw->caption() !=cmd->caption)) {
2806         changingw->setName(cmd->name);
2807         changingw->setCaption(cmd->caption);
2808         emit q->windowEvent(changingw, QWSServer::Name);
2809     }
2810 }
2811 
invokeRegion(QWSRegionCommand * cmd,QWSClient * client)2812 void QWSServerPrivate::invokeRegion(QWSRegionCommand *cmd, QWSClient *client)
2813 {
2814 #ifdef QWS_REGION_DEBUG
2815     qDebug("QWSServer::invokeRegion %d rects (%d)",
2816             cmd->simpleData.nrectangles, cmd->simpleData.windowid);
2817 #endif
2818 
2819     QWSWindow* changingw = findWindow(cmd->simpleData.windowid, 0);
2820     if (!changingw) {
2821         qWarning("Invalid window handle %08x",cmd->simpleData.windowid);
2822         return;
2823     }
2824     if (!changingw->forClient(client)) {
2825         qWarning("Disabled: clients changing other client's window region");
2826         return;
2827     }
2828 
2829     request_region(cmd->simpleData.windowid, cmd->surfaceKey, cmd->surfaceData,
2830                    cmd->region);
2831 }
2832 
invokeRegionMove(const QWSRegionMoveCommand * cmd,QWSClient * client)2833 void QWSServerPrivate::invokeRegionMove(const QWSRegionMoveCommand *cmd, QWSClient *client)
2834 {
2835     Q_Q(QWSServer);
2836     QWSWindow* changingw = findWindow(cmd->simpleData.windowid, 0);
2837     if (!changingw) {
2838         qWarning("invokeRegionMove: Invalid window handle %d",cmd->simpleData.windowid);
2839         return;
2840     }
2841     if (!changingw->forClient(client)) {
2842         qWarning("Disabled: clients changing other client's window region");
2843         return;
2844     }
2845 
2846 //    changingw->setNeedAck(true);
2847     moveWindowRegion(changingw, cmd->simpleData.dx, cmd->simpleData.dy);
2848     emit q->windowEvent(changingw, QWSServer::Geometry);
2849 }
2850 
invokeRegionDestroy(const QWSRegionDestroyCommand * cmd,QWSClient * client)2851 void QWSServerPrivate::invokeRegionDestroy(const QWSRegionDestroyCommand *cmd, QWSClient *client)
2852 {
2853     Q_Q(QWSServer);
2854     QWSWindow* changingw = findWindow(cmd->simpleData.windowid, 0);
2855     if (!changingw) {
2856         qWarning("invokeRegionDestroy: Invalid window handle %d",cmd->simpleData.windowid);
2857         return;
2858     }
2859     if (!changingw->forClient(client)) {
2860         qWarning("Disabled: clients changing other client's window region");
2861         return;
2862     }
2863 
2864     setWindowRegion(changingw, QRegion());
2865 //    rgnMan->remove(changingw->allocationIndex());
2866     for (int i = 0; i < windows.size(); ++i) {
2867         if (windows.at(i) == changingw) {
2868             windows.takeAt(i);
2869             if (i < nReserved)
2870                 --nReserved;
2871             break;
2872         }
2873     }
2874 
2875     handleWindowClose(changingw);
2876 #ifndef QT_NO_QWS_PROPERTIES
2877     propertyManager.removeProperties(changingw->winId());
2878 #endif
2879     emit q->windowEvent(changingw, QWSServer::Destroy);
2880     delete changingw;
2881 }
2882 
invokeSetFocus(const QWSRequestFocusCommand * cmd,QWSClient * client)2883 void QWSServerPrivate::invokeSetFocus(const QWSRequestFocusCommand *cmd, QWSClient *client)
2884 {
2885     int winId = cmd->simpleData.windowid;
2886     int gain = cmd->simpleData.flag;
2887 
2888     if (gain != 0 && gain != 1) {
2889         qWarning("Only 0(lose) and 1(gain) supported");
2890         return;
2891     }
2892 
2893     QWSWindow* changingw = findWindow(winId, 0);
2894     if (!changingw)
2895         return;
2896 
2897     if (!changingw->forClient(client)) {
2898        qWarning("Disabled: clients changing other client's focus");
2899         return;
2900     }
2901 
2902     setFocus(changingw, gain);
2903 }
2904 
setFocus(QWSWindow * changingw,bool gain)2905 void QWSServerPrivate::setFocus(QWSWindow* changingw, bool gain)
2906 {
2907     Q_Q(QWSServer);
2908 #ifndef QT_NO_QWS_INPUTMETHODS
2909     /*
2910       This is the logic:
2911       QWSWindow *loser = 0;
2912       if (gain && focusw != changingw)
2913          loser = focusw;
2914       else if (!gain && focusw == changingw)
2915          loser = focusw;
2916       But these five lines can be reduced to one:
2917     */
2918     if (current_IM) {
2919         QWSWindow *loser =  (!gain == (focusw==changingw)) ? focusw : 0;
2920         if (loser && loser->winId() == current_IM_winId)
2921             current_IM->updateHandler(QWSInputMethod::FocusOut);
2922     }
2923 #endif
2924     if (gain) {
2925         if (focusw != changingw) {
2926             if (focusw) focusw->focus(0);
2927             focusw = changingw;
2928             focusw->focus(1);
2929             emit q->windowEvent(focusw, QWSServer::Active);
2930         }
2931     } else if (focusw == changingw) {
2932         if (changingw->client())
2933             changingw->focus(0);
2934         focusw = 0;
2935         // pass focus to window which most recently got it...
2936         QWSWindow* bestw=0;
2937         for (int i=0; i<windows.size(); ++i) {
2938             QWSWindow* w = windows.at(i);
2939             if (w != changingw && !w->hidden() &&
2940                     (!bestw || bestw->focusPriority() < w->focusPriority()))
2941                 bestw = w;
2942         }
2943         if (!bestw && changingw->focusPriority()) { // accept focus back?
2944             bestw = changingw; // must be the only one
2945         }
2946         focusw = bestw;
2947         if (focusw) {
2948             focusw->focus(1);
2949             emit q->windowEvent(focusw, QWSServer::Active);
2950         }
2951     }
2952 }
2953 
2954 
2955 
invokeSetOpacity(const QWSSetOpacityCommand * cmd,QWSClient * client)2956 void QWSServerPrivate::invokeSetOpacity(const QWSSetOpacityCommand *cmd, QWSClient *client)
2957 {
2958     Q_UNUSED( client );
2959     int winId = cmd->simpleData.windowid;
2960     int opacity = cmd->simpleData.opacity;
2961 
2962     QWSWindow* changingw = findWindow(winId, 0);
2963 
2964     if (!changingw) {
2965         qWarning("invokeSetOpacity: Invalid window handle %d", winId);
2966         return;
2967     }
2968 
2969     int altitude = windows.indexOf(changingw);
2970     const bool wasOpaque = changingw->isOpaque();
2971     changingw->_opacity = opacity;
2972     if (wasOpaque != changingw->isOpaque())
2973         update_regions();
2974     exposeRegion(changingw->allocatedRegion(), altitude);
2975 }
2976 
invokeSetAltitude(const QWSChangeAltitudeCommand * cmd,QWSClient * client)2977 void QWSServerPrivate::invokeSetAltitude(const QWSChangeAltitudeCommand *cmd,
2978                                    QWSClient *client)
2979 {
2980     Q_UNUSED(client);
2981 
2982     int winId = cmd->simpleData.windowid;
2983     int alt = cmd->simpleData.altitude;
2984     bool fixed = cmd->simpleData.fixed;
2985 #if 0
2986     qDebug("QWSServer::invokeSetAltitude winId %d alt %d)", winId, alt);
2987 #endif
2988 
2989     if (alt < -1 || alt > 1) {
2990         qWarning("QWSServer::invokeSetAltitude Only lower, raise and stays-on-top supported");
2991         return;
2992     }
2993 
2994     QWSWindow* changingw = findWindow(winId, 0);
2995     if (!changingw) {
2996         qWarning("invokeSetAltitude: Invalid window handle %d", winId);
2997         return;
2998     }
2999 
3000     if (fixed && alt >= 1) {
3001         changingw->onTop = true;
3002     }
3003     if (alt == QWSChangeAltitudeCommand::Lower)
3004         changingw->lower();
3005     else
3006         changingw->raise();
3007 
3008 //      if (!changingw->forClient(client)) {
3009 //         refresh();
3010 //     }
3011 }
3012 
3013 #ifndef QT_NO_QWS_PROPERTIES
invokeAddProperty(QWSAddPropertyCommand * cmd)3014 void QWSServerPrivate::invokeAddProperty(QWSAddPropertyCommand *cmd)
3015 {
3016     propertyManager.addProperty(cmd->simpleData.windowid, cmd->simpleData.property);
3017 }
3018 
invokeSetProperty(QWSSetPropertyCommand * cmd)3019 void QWSServerPrivate::invokeSetProperty(QWSSetPropertyCommand *cmd)
3020 {
3021     Q_Q(QWSServer);
3022     if (propertyManager.setProperty(cmd->simpleData.windowid,
3023                                     cmd->simpleData.property,
3024                                     cmd->simpleData.mode,
3025                                     cmd->data,
3026                                     cmd->rawLen)) {
3027         q->sendPropertyNotifyEvent(cmd->simpleData.property,
3028                                  QWSPropertyNotifyEvent::PropertyNewValue);
3029 #ifndef QT_NO_QWS_INPUTMETHODS
3030         if (cmd->simpleData.property == QT_QWS_PROPERTY_MARKEDTEXT) {
3031             QString s((const QChar*)cmd->data, cmd->rawLen/2);
3032             emit q->markedText(s);
3033         }
3034 #endif
3035     }
3036 }
3037 
invokeRemoveProperty(QWSRemovePropertyCommand * cmd)3038 void QWSServerPrivate::invokeRemoveProperty(QWSRemovePropertyCommand *cmd)
3039 {
3040     Q_Q(QWSServer);
3041     if (propertyManager.removeProperty(cmd->simpleData.windowid,
3042                                        cmd->simpleData.property)) {
3043         q->sendPropertyNotifyEvent(cmd->simpleData.property,
3044                                  QWSPropertyNotifyEvent::PropertyDeleted);
3045     }
3046 }
3047 
3048 
get_property(int winId,int property,const char * & data,int & len)3049 bool QWSServerPrivate:: get_property(int winId, int property, const char *&data, int &len)
3050 {
3051     return propertyManager.getProperty(winId, property, data, len);
3052 }
3053 
3054 
invokeGetProperty(QWSGetPropertyCommand * cmd,QWSClient * client)3055 void QWSServerPrivate::invokeGetProperty(QWSGetPropertyCommand *cmd, QWSClient *client)
3056 {
3057     const char *data;
3058     int len;
3059 
3060     if (propertyManager.getProperty(cmd->simpleData.windowid,
3061                                     cmd->simpleData.property,
3062                                     data, len)) {
3063         client->sendPropertyReplyEvent(cmd->simpleData.property, len, data);
3064     } else {
3065         client->sendPropertyReplyEvent(cmd->simpleData.property, -1, 0);
3066     }
3067 }
3068 #endif //QT_NO_QWS_PROPERTIES
3069 
invokeSetSelectionOwner(QWSSetSelectionOwnerCommand * cmd)3070 void QWSServerPrivate::invokeSetSelectionOwner(QWSSetSelectionOwnerCommand *cmd)
3071 {
3072     qDebug("QWSServer::invokeSetSelectionOwner");
3073 
3074     SelectionOwner so;
3075     so.windowid = cmd->simpleData.windowid;
3076     so.time.set(cmd->simpleData.hour, cmd->simpleData.minute,
3077                  cmd->simpleData.sec, cmd->simpleData.ms);
3078 
3079     if (selectionOwner.windowid != -1) {
3080         QWSWindow *win = findWindow(selectionOwner.windowid, 0);
3081         if (win)
3082             win->client()->sendSelectionClearEvent(selectionOwner.windowid);
3083         else
3084             qDebug("couldn't find window %d", selectionOwner.windowid);
3085     }
3086 
3087     selectionOwner = so;
3088 }
3089 
invokeConvertSelection(QWSConvertSelectionCommand * cmd)3090 void QWSServerPrivate::invokeConvertSelection(QWSConvertSelectionCommand *cmd)
3091 {
3092     qDebug("QWSServer::invokeConvertSelection");
3093 
3094     if (selectionOwner.windowid != -1) {
3095         QWSWindow *win = findWindow(selectionOwner.windowid, 0);
3096         if (win)
3097             win->client()->sendSelectionRequestEvent(cmd, selectionOwner.windowid);
3098         else
3099             qDebug("couldn't find window %d", selectionOwner.windowid);
3100     }
3101 }
3102 
3103 #ifndef QT_NO_QWS_CURSOR
invokeDefineCursor(QWSDefineCursorCommand * cmd,QWSClient * client)3104 void QWSServerPrivate::invokeDefineCursor(QWSDefineCursorCommand *cmd, QWSClient *client)
3105 {
3106     if (cmd->simpleData.height > 64 || cmd->simpleData.width > 64) {
3107         qDebug("Cannot define cursor size > 64x64");
3108         return;
3109     }
3110 
3111     delete client->cursors.take(cmd->simpleData.id);
3112 
3113     int dataLen = cmd->simpleData.height * ((cmd->simpleData.width+7) / 8);
3114 
3115     if (dataLen > 0 && cmd->data) {
3116         QWSCursor *curs = new QWSCursor(cmd->data, cmd->data + dataLen,
3117                                         cmd->simpleData.width, cmd->simpleData.height,
3118                                         cmd->simpleData.hotX, cmd->simpleData.hotY);
3119         client->cursors.insert(cmd->simpleData.id, curs);
3120     }
3121 }
3122 
invokeSelectCursor(QWSSelectCursorCommand * cmd,QWSClient * client)3123 void QWSServerPrivate::invokeSelectCursor(QWSSelectCursorCommand *cmd, QWSClient *client)
3124 {
3125     int id = cmd->simpleData.id;
3126     QWSCursor *curs = 0;
3127     if (id <= Qt::LastCursor) {
3128         curs = QWSCursor::systemCursor(id);
3129     }
3130     else {
3131         QWSCursorMap cursMap = client->cursors;
3132         QWSCursorMap::Iterator it = cursMap.find(id);
3133         if (it != cursMap.end()) {
3134             curs = it.value();
3135         }
3136     }
3137     if (curs == 0) {
3138         curs = QWSCursor::systemCursor(Qt::ArrowCursor);
3139     }
3140 
3141     QWSWindow* win = findWindow(cmd->simpleData.windowid, 0);
3142     if (mouseGrabber) {
3143         // If the mouse is being grabbed, we don't want just anyone to
3144         // be able to change the cursor.  We do want the cursor to be set
3145         // correctly once mouse grabbing is stopped though.
3146         if (win != mouseGrabber)
3147             nextCursor = curs;
3148         else
3149             setCursor(curs);
3150     } else if (win && win->allocatedRegion().contains(QWSServer::mousePosition)) { //##################### cursor
3151         // A non-grabbing window can only set the cursor shape if the
3152         // cursor is within its allocated region.
3153         setCursor(curs);
3154     }
3155 }
3156 
invokePositionCursor(QWSPositionCursorCommand * cmd,QWSClient *)3157 void QWSServerPrivate::invokePositionCursor(QWSPositionCursorCommand *cmd, QWSClient *)
3158 {
3159     Q_Q(QWSServer);
3160     QPoint newPos(cmd->simpleData.newX, cmd->simpleData.newY);
3161     if (newPos != QWSServer::mousePosition)
3162         q->sendMouseEvent(newPos, qwsServer->d_func()->mouseState);
3163 }
3164 #endif
3165 
invokeGrabMouse(QWSGrabMouseCommand * cmd,QWSClient * client)3166 void QWSServerPrivate::invokeGrabMouse(QWSGrabMouseCommand *cmd, QWSClient *client)
3167 {
3168     QWSWindow* win = findWindow(cmd->simpleData.windowid, 0);
3169     if (!win)
3170         return;
3171 
3172     if (cmd->simpleData.grab) {
3173         if (!mouseGrabber || mouseGrabber->client() == client) {
3174             mouseGrabbing = true;
3175             mouseGrabber = win;
3176         }
3177     } else {
3178         releaseMouse(mouseGrabber);
3179     }
3180 }
3181 
invokeGrabKeyboard(QWSGrabKeyboardCommand * cmd,QWSClient * client)3182 void QWSServerPrivate::invokeGrabKeyboard(QWSGrabKeyboardCommand *cmd, QWSClient *client)
3183 {
3184     QWSWindow* win = findWindow(cmd->simpleData.windowid, 0);
3185     if (!win)
3186         return;
3187 
3188     if (cmd->simpleData.grab) {
3189         if (!keyboardGrabber || (keyboardGrabber->client() == client)) {
3190             keyboardGrabbing = true;
3191             keyboardGrabber = win;
3192         }
3193     } else {
3194         releaseKeyboard(keyboardGrabber);
3195     }
3196 }
3197 
3198 #if !defined(QT_NO_SOUND)
invokePlaySound(QWSPlaySoundCommand * cmd,QWSClient *)3199 void QWSServerPrivate::invokePlaySound(QWSPlaySoundCommand *cmd, QWSClient *)
3200 {
3201 #if !defined(QT_EXTERNAL_SOUND_SERVER) && !defined(Q_OS_DARWIN)
3202     soundserver->playFile( 1, cmd->filename );
3203 #else
3204     Q_UNUSED(cmd);
3205 #endif
3206 }
3207 #endif
3208 
3209 #ifndef QT_NO_COP
invokeRegisterChannel(QWSQCopRegisterChannelCommand * cmd,QWSClient * client)3210 void QWSServerPrivate::invokeRegisterChannel(QWSQCopRegisterChannelCommand *cmd,
3211                                        QWSClient *client)
3212 {
3213   // QCopChannel will force us to emit the newChannel signal if this channel
3214   // didn't already exist.
3215   QCopChannel::registerChannel(cmd->channel, client);
3216 }
3217 
invokeQCopSend(QWSQCopSendCommand * cmd,QWSClient * client)3218 void QWSServerPrivate::invokeQCopSend(QWSQCopSendCommand *cmd, QWSClient *client)
3219 {
3220     QCopChannel::answer(client, cmd->channel, cmd->message, cmd->data);
3221 }
3222 
3223 #endif
3224 
3225 #ifndef QT_NO_QWS_INPUTMETHODS
resetInputMethod()3226 void QWSServer::resetInputMethod()
3227 {
3228     if (current_IM && qwsServer) {
3229       current_IM->reset();
3230     }
3231 }
3232 
invokeIMResponse(const QWSIMResponseCommand * cmd,QWSClient *)3233 void QWSServerPrivate::invokeIMResponse(const QWSIMResponseCommand *cmd,
3234                                  QWSClient *)
3235 {
3236     if (current_IM)
3237         current_IM->queryResponse(cmd->simpleData.property, cmd->result);
3238 }
3239 
invokeIMUpdate(const QWSIMUpdateCommand * cmd,QWSClient *)3240 void QWSServerPrivate::invokeIMUpdate(const QWSIMUpdateCommand *cmd,
3241                                  QWSClient *)
3242 {
3243     if (cmd->simpleData.type == QWSInputMethod::FocusIn)
3244         current_IM_winId = cmd->simpleData.windowid;
3245 
3246     if (current_IM && (current_IM_winId == cmd->simpleData.windowid || cmd->simpleData.windowid == -1))
3247         current_IM->updateHandler(cmd->simpleData.type);
3248 }
3249 
3250 #endif
3251 
invokeFont(const QWSFontCommand * cmd,QWSClient * client)3252 void QWSServerPrivate::invokeFont(const QWSFontCommand *cmd, QWSClient *client)
3253 {
3254     QWSClientPrivate *priv = client->d_func();
3255     if (cmd->simpleData.type == QWSFontCommand::StartedUsingFont) {
3256         referenceFont(priv, cmd->fontName);
3257     } else if (cmd->simpleData.type == QWSFontCommand::StoppedUsingFont) {
3258         dereferenceFont(priv, cmd->fontName);
3259     }
3260 }
3261 
invokeRepaintRegion(QWSRepaintRegionCommand * cmd,QWSClient *)3262 void QWSServerPrivate::invokeRepaintRegion(QWSRepaintRegionCommand * cmd,
3263                                            QWSClient *)
3264 {
3265     QRegion r;
3266     r.setRects(cmd->rectangles,cmd->simpleData.nrectangles);
3267     repaint_region(cmd->simpleData.windowid, cmd->simpleData.windowFlags, cmd->simpleData.opaque, r);
3268 }
3269 
3270 #ifndef QT_NO_QWSEMBEDWIDGET
invokeEmbed(QWSEmbedCommand * cmd,QWSClient * client)3271 void QWSServerPrivate::invokeEmbed(QWSEmbedCommand *cmd, QWSClient *client)
3272 {
3273     // Should find these two windows in a single loop
3274     QWSWindow *embedder = findWindow(cmd->simpleData.embedder, client);
3275     QWSWindow *embedded = findWindow(cmd->simpleData.embedded);
3276 
3277     if (!embedder) {
3278         qWarning("QWSServer: Embed command from window %i failed: No such id.",
3279                  static_cast<int>(cmd->simpleData.embedder));
3280         return;
3281     }
3282 
3283     if (!embedded) {
3284         qWarning("QWSServer: Embed command on window %i failed: No such id.",
3285                  static_cast<int>(cmd->simpleData.embedded));
3286         return;
3287     }
3288 
3289     switch (cmd->simpleData.type) {
3290     case QWSEmbedEvent::StartEmbed:
3291         embedder->startEmbed(embedded);
3292         windows.removeAll(embedded);
3293         windows.insert(windows.indexOf(embedder), embedded);
3294         break;
3295     case QWSEmbedEvent::StopEmbed:
3296         embedder->stopEmbed(embedded);
3297         break;
3298     case QWSEmbedEvent::Region:
3299         break;
3300     }
3301 
3302     embedded->client()->sendEmbedEvent(embedded->winId(),
3303                                        cmd->simpleData.type, cmd->region);
3304     const QRegion oldAllocated = embedded->allocatedRegion();
3305     update_regions();
3306     exposeRegion(oldAllocated - embedded->allocatedRegion(),
3307                  windows.indexOf(embedded));
3308 }
3309 #endif // QT_NO_QWSEMBEDWIDGET
3310 
invokeScreenTransform(const QWSScreenTransformCommand * cmd,QWSClient * client)3311 void QWSServerPrivate::invokeScreenTransform(const QWSScreenTransformCommand *cmd,
3312                                              QWSClient *client)
3313 {
3314     Q_UNUSED(client);
3315 
3316     QWSScreenTransformationEvent event;
3317     event.simpleData.screen = cmd->simpleData.screen;
3318     event.simpleData.transformation = cmd->simpleData.transformation;
3319 
3320     QMap<int, QWSClient*>::const_iterator it = clientMap.constBegin();
3321     for (; it != clientMap.constEnd(); ++it)
3322         (*it)->sendEvent(&event);
3323 }
3324 
newWindow(int id,QWSClient * client)3325 QWSWindow* QWSServerPrivate::newWindow(int id, QWSClient* client)
3326 {
3327     Q_Q(QWSServer);
3328     // Make a new window, put it on top.
3329     QWSWindow* w = new QWSWindow(id,client);
3330 
3331     // insert after "stays on top" windows
3332     bool added = false;
3333     for (int i = nReserved; i < windows.size(); ++i) {
3334         QWSWindow *win = windows.at(i);
3335         if (!win->onTop) {
3336             windows.insert(i, w);
3337             added = true;
3338             break;
3339         }
3340     }
3341     if (!added)
3342         windows.append(w);
3343     emit q->windowEvent(w, QWSServer::Create);
3344     return w;
3345 }
3346 
findWindow(int windowid,QWSClient * client)3347 QWSWindow* QWSServerPrivate::findWindow(int windowid, QWSClient* client)
3348 {
3349     for (int i=0; i<windows.size(); ++i) {
3350         QWSWindow* w = windows.at(i);
3351         if (w->winId() == windowid)
3352             return w;
3353     }
3354     if (client)
3355         return newWindow(windowid,client);
3356     else
3357         return 0;
3358 }
3359 
raiseWindow(QWSWindow * changingw,int)3360 void QWSServerPrivate::raiseWindow(QWSWindow *changingw, int /*alt*/)
3361 {
3362     Q_Q(QWSServer);
3363     if (changingw == windows.first())
3364         return;
3365     QWSWindow::State oldstate = changingw->d->state;
3366     changingw->d->state = QWSWindow::Raising;
3367     // Expose regions previously overlapped by transparent windows
3368     const QRegion bound = changingw->allocatedRegion();
3369     QRegion expose;
3370     int windowPos = 0;
3371 
3372     //change position in list:
3373     for (int i = 0; i < windows.size(); ++i) {
3374         QWSWindow *w = windows.at(i);
3375         if (w == changingw) {
3376             windowPos = i;
3377             windows.takeAt(i);
3378             break;
3379         }
3380         if (!w->isOpaque())
3381             expose += (w->allocatedRegion() & bound);
3382     }
3383 
3384     bool onTop = changingw->onTop;
3385 
3386 #ifndef QT_NO_QWSEMBEDWIDGET
3387     // an embedded window is on top if the embedder is on top
3388     QWSWindow *embedder = changingw->d->embedder;
3389     while (!onTop && embedder) {
3390         onTop = embedder->onTop;
3391         embedder = embedder->d->embedder;
3392     }
3393 #endif
3394 
3395     int newPos = -1;
3396     if (onTop) {
3397         windows.insert(nReserved, changingw);
3398         newPos = nReserved;
3399     } else {
3400         // insert after "stays on top" windows
3401         bool in = false;
3402         for (int i = nReserved; i < windows.size(); ++i) {
3403             QWSWindow *w = windows.at(i);
3404             if (!w->onTop) {
3405                 windows.insert(i, changingw);
3406                 in = true;
3407                 newPos = i;
3408                 break;
3409             }
3410         }
3411         if (!in) {
3412             windows.append(changingw);
3413             newPos = windows.size()-1;
3414         }
3415     }
3416 
3417     if (windowPos != newPos) {
3418         update_regions();
3419         if (!expose.isEmpty())
3420             exposeRegion(expose, newPos);
3421     }
3422     changingw->d->state = oldstate;
3423     emit q->windowEvent(changingw, QWSServer::Raise);
3424 }
3425 
lowerWindow(QWSWindow * changingw,int)3426 void QWSServerPrivate::lowerWindow(QWSWindow *changingw, int /*alt*/)
3427 {
3428     Q_Q(QWSServer);
3429     if (changingw == windows.last())
3430         return;
3431     QWSWindow::State oldstate = changingw->d->state;
3432     changingw->d->state = QWSWindow::Lowering;
3433 
3434     int i = windows.indexOf(changingw);
3435     int newIdx = windows.size()-1;
3436     windows.move(i, newIdx);
3437 
3438     const QRegion bound = changingw->allocatedRegion();
3439 
3440     update_regions();
3441 
3442     // Expose regions previously overlapped by transparent window
3443     if (!changingw->isOpaque()) {
3444         QRegion expose;
3445         for (int j = i; j < windows.size() - 1; ++j)
3446             expose += (windows.at(j)->allocatedRegion() & bound);
3447         if (!expose.isEmpty())
3448             exposeRegion(expose, newIdx);
3449     }
3450 
3451     changingw->d->state = oldstate;
3452     emit q->windowEvent(changingw, QWSServer::Lower);
3453 }
3454 
update_regions()3455 void QWSServerPrivate::update_regions()
3456 {
3457     if (disablePainting)
3458         return;
3459 
3460     QRegion available = QRect(0, 0, qt_screen->width(), qt_screen->height());
3461     QRegion transparentRegion;
3462 
3463     // only really needed if there are unbuffered surfaces...
3464     const bool doLock = (clientMap.size() > 1);
3465     if (doLock)
3466         QWSDisplay::grab(true);
3467 
3468     for (int i = 0; i < windows.count(); ++i) {
3469         QWSWindow *w = windows.at(i);
3470         QRegion r = (w->requested_region & available);
3471 
3472 #ifndef QT_NO_QWSEMBEDWIDGET
3473         // Subtract regions needed for embedded windows
3474         const int n = w->d->embedded.size();
3475         for (int i = 0; i < n; ++i)
3476             r -= w->d->embedded.at(i)->allocatedRegion();
3477 
3478         // Limited to the embedder region
3479         if (w->d->embedder)
3480             r &= w->d->embedder->requested_region;
3481 #endif // QT_NO_QWSEMBEDWIDGET
3482 
3483         QWSWindowSurface *surface = w->windowSurface();
3484         const bool opaque = w->isOpaque()
3485                             && (w->d->painted || !surface || !surface->isBuffered());
3486 
3487         if (!opaque) {
3488             transparentRegion += r;
3489         } else {
3490             if (surface && (surface->isRegionReserved() || !surface->isBuffered()))
3491                 r -= transparentRegion;
3492             available -= r;
3493         }
3494 
3495         if (r != w->allocatedRegion()) {
3496             w->setAllocatedRegion(r);
3497             w->client()->sendRegionEvent(w->winId(), r,
3498                                          QWSRegionEvent::Allocation);
3499         }
3500 
3501 #ifdef QT_QWS_CLIENTBLIT
3502 #ifdef QT_NO_QWS_CURSOR
3503         // This optimization only really works when there isn't a crazy cursor
3504         // wizzing around.
3505         QRegion directPaint = (r - transparentRegion); // in gloal coords
3506         if(directPaint != w->directPaintRegion()) {
3507             w->setDirectPaintRegion(directPaint);
3508             static int id = 0;
3509             surface->setDirectRegion(directPaint, ++id);
3510             w->client()->sendRegionEvent(w->winId(), directPaint,
3511                                          QWSRegionEvent::DirectPaint, id);
3512         }
3513 #endif
3514 #endif
3515     }
3516 
3517     if (doLock)
3518         QWSDisplay::ungrab();
3519 }
3520 
moveWindowRegion(QWSWindow * changingw,int dx,int dy)3521 void QWSServerPrivate::moveWindowRegion(QWSWindow *changingw, int dx, int dy)
3522 {
3523     if (!changingw)
3524         return;
3525 
3526     QWSWindow::State oldState = changingw->d->state;
3527     changingw->d->state = QWSWindow::Moving;
3528     const QRegion oldRegion(changingw->allocatedRegion());
3529     changingw->requested_region.translate(dx, dy);
3530 
3531     // hw: Even if the allocated region doesn't change, the requested region
3532     // region has changed and we need to send region events.
3533     // Resetting the allocated region to force update_regions to send events.
3534     changingw->setAllocatedRegion(QRegion());
3535     update_regions();
3536     const QRegion newRegion(changingw->allocatedRegion());
3537 
3538     QWSWindowSurface *surface = changingw->windowSurface();
3539     QRegion expose;
3540     if (surface)
3541         expose = surface->move(QPoint(dx, dy), changingw->allocatedRegion());
3542     else
3543         expose = oldRegion + newRegion;
3544 
3545     if (!changingw->d->painted && !expose.isEmpty())
3546         expose = oldRegion - newRegion;
3547 
3548     int idx = windows.indexOf(changingw);
3549     exposeRegion(expose, idx);
3550     changingw->d->state = oldState;
3551 }
3552 
3553 /*!
3554     Changes the requested region of window \a changingw to \a r
3555     If \a changingw is 0, the server's reserved region is changed.
3556 */
setWindowRegion(QWSWindow * changingw,const QRegion & r)3557 void QWSServerPrivate::setWindowRegion(QWSWindow* changingw, const QRegion &r)
3558 {
3559     if (!changingw) {
3560         qWarning("Not implemented in this release");
3561         return;
3562     }
3563 
3564     if (changingw->requested_region == r)
3565         return;
3566 
3567     const QRegion oldRegion(changingw->allocatedRegion());
3568     changingw->requested_region = r;
3569     update_regions();
3570     const QRegion newRegion(changingw->allocatedRegion());
3571 
3572     int idx = windows.indexOf(changingw);
3573     exposeRegion(oldRegion - newRegion, idx);
3574 }
3575 
3576 
exposeRegion(const QRegion & r,int changing)3577 void QWSServerPrivate::exposeRegion(const QRegion &r, int changing)
3578 {
3579     if (disablePainting)
3580         return;
3581 
3582     if (r.isEmpty())
3583         return;
3584 
3585     static bool initial = true;
3586     if (initial) {
3587         changing = 0;
3588         initial = false;
3589         qt_screen->exposeRegion(qt_screen->region(), changing);
3590     } else {
3591         qt_screen->exposeRegion(r, changing);
3592     }
3593 }
3594 
3595 /*!
3596     Closes all pointer devices (specified by the QWS_MOUSE_PROTO
3597     environment variable) by deleting the associated mouse drivers.
3598 
3599     \sa openMouse(), mouseHandler()
3600 */
closeMouse()3601 void QWSServer::closeMouse()
3602 {
3603     Q_D(QWSServer);
3604     qDeleteAll(d->mousehandlers);
3605     d->mousehandlers.clear();
3606 }
3607 
3608 /*!
3609     Opens the mouse devices specified by the QWS_MOUSE_PROTO
3610     environment variable. Be advised that closeMouse() is called first
3611     to delete all the existing mouse handlers. This behaviour could be
3612     the cause of problems if you were not expecting it.
3613 
3614     \sa closeMouse(), mouseHandler()
3615 */
openMouse()3616 void QWSServer::openMouse()
3617 {
3618     Q_D(QWSServer);
3619     QString mice = QString::fromLatin1(qgetenv("QWS_MOUSE_PROTO"));
3620 #if defined(QT_QWS_CASSIOPEIA)
3621     if (mice.isEmpty())
3622         mice = QLatin1String("TPanel:/dev/tpanel");
3623 #endif
3624     if (mice.isEmpty())
3625         mice = *defaultMouse();
3626     closeMouse();
3627     bool needviscurs = true;
3628     if (mice != QLatin1String("None")) {
3629         const QStringList mouse = mice.split(QLatin1Char(' '));
3630         for (int i = mouse.size() - 1; i >= 0; --i) {
3631             QWSMouseHandler *handler = d->newMouseHandler(mouse.at(i));
3632             setMouseHandler(handler);
3633             /* XXX handle mouse cursor visibility sensibly
3634                if (!h->inherits("QCalibratedMouseHandler"))
3635                needviscurs = true;
3636             */
3637         }
3638     }
3639 #ifndef QT_NO_QWS_CURSOR
3640     setCursorVisible(needviscurs);
3641 #else
3642     Q_UNUSED(needviscurs)
3643 #endif
3644 }
3645 
3646 /*!
3647     Suspends pointer handling by deactivating all the mouse drivers
3648     registered by the QWS_MOUSE_PROTO environment variable.
3649 
3650 
3651     \sa resumeMouse(), QWSMouseHandler::suspend()
3652 */
suspendMouse()3653 void QWSServer::suspendMouse()
3654 {
3655     Q_D(QWSServer);
3656     for (int i=0; i < d->mousehandlers.size(); ++i)
3657         d->mousehandlers.at(i)->suspend();
3658 }
3659 
3660 /*!
3661     Resumes pointer handling by reactivating all the mouse drivers
3662     registered by the QWS_MOUSE_PROTO environment variable.
3663 
3664     \sa suspendMouse(), QWSMouseHandler::resume()
3665 */
resumeMouse()3666 void QWSServer::resumeMouse()
3667 {
3668     Q_D(QWSServer);
3669     for (int i=0; i < d->mousehandlers.size(); ++i)
3670         d->mousehandlers.at(i)->resume();
3671 }
3672 
3673 
3674 
newMouseHandler(const QString & spec)3675 QWSMouseHandler* QWSServerPrivate::newMouseHandler(const QString& spec)
3676 {
3677     int c = spec.indexOf(QLatin1Char(':'));
3678     QString mouseProto;
3679     QString mouseDev;
3680     if (c >= 0) {
3681         mouseProto = spec.left(c);
3682         mouseDev = spec.mid(c+1);
3683     } else {
3684         mouseProto = spec;
3685     }
3686 
3687     int screen = -1;
3688     const QList<QRegExp> regexps = QList<QRegExp>()
3689                                    << QRegExp(QLatin1String(":screen=(\\d+)\\b"))
3690                                    << QRegExp(QLatin1String("\\bscreen=(\\d+):"));
3691     for (int i = 0; i < regexps.size(); ++i) {
3692         QRegExp regexp = regexps.at(i);
3693         if (regexp.indexIn(mouseDev) == -1)
3694             continue;
3695         screen = regexp.cap(1).toInt();
3696         mouseDev.remove(regexp.pos(0), regexp.matchedLength());
3697         break;
3698     }
3699 
3700     QWSMouseHandler *handler = 0;
3701     handler = QMouseDriverFactory::create(mouseProto, mouseDev);
3702     if (screen != -1)
3703         handler->setScreen(qt_screen->subScreens().at(screen));
3704 
3705     return handler;
3706 }
3707 
3708 #ifndef QT_NO_QWS_KEYBOARD
3709 
3710 /*!
3711     Closes all the keyboard devices (specified by the QWS_KEYBOARD
3712     environment variable) by deleting the associated keyboard
3713     drivers.
3714 
3715     \sa openKeyboard(),  keyboardHandler()
3716 */
closeKeyboard()3717 void QWSServer::closeKeyboard()
3718 {
3719     Q_D(QWSServer);
3720     qDeleteAll(d->keyboardhandlers);
3721     d->keyboardhandlers.clear();
3722 }
3723 
3724 /*!
3725     Returns the primary keyboard driver.
3726 
3727     Note that this function can only be used in the server process.
3728 
3729     \sa setKeyboardHandler(), openKeyboard(), closeKeyboard()
3730 */
keyboardHandler()3731 QWSKeyboardHandler* QWSServer::keyboardHandler()
3732 {
3733     return qwsServerPrivate->keyboardhandlers.first();
3734 }
3735 
3736 /*!
3737     \fn void QWSServer::setKeyboardHandler(QWSKeyboardHandler* driver)
3738 
3739     Sets the primary keyboard driver to be the given \a driver.
3740 
3741     \l{Qt for Embedded Linux} provides several ready-made keyboard drivers, and
3742     custom drivers are typically added using Qt's plugin
3743     mechanism. See the \l{Qt for Embedded Linux Character Input} documentation
3744     for details.
3745 
3746     Note that this function can only be used in the server process.
3747 
3748     \sa keyboardHandler(), setDefaultKeyboard()
3749 */
setKeyboardHandler(QWSKeyboardHandler * kh)3750 void QWSServer::setKeyboardHandler(QWSKeyboardHandler* kh)
3751 {
3752     if (!kh)
3753         return;
3754     qwsServerPrivate->keyboardhandlers.removeAll(kh);
3755     qwsServerPrivate->keyboardhandlers.prepend(kh);
3756 }
3757 
3758 /*!
3759     Opens the keyboard devices specified by the QWS_KEYBOARD
3760     environment variable.
3761 
3762     \sa closeKeyboard(), keyboardHandler()
3763 */
openKeyboard()3764 void QWSServer::openKeyboard()
3765 {
3766     QString keyboards = QString::fromLatin1(qgetenv("QWS_KEYBOARD"));
3767 #if defined(QT_QWS_CASSIOPEIA)
3768     if (keyboards.isEmpty())
3769         keyboards = QLatin1String("Buttons");
3770 #endif
3771     if (keyboards.isEmpty())
3772         keyboards = *defaultKeyboard();
3773 
3774     closeKeyboard();
3775     if (keyboards == QLatin1String("None"))
3776         return;
3777 
3778     QString device;
3779     QString type;
3780     QStringList keyboard = keyboards.split(QLatin1Char(' '));
3781     for (int i = keyboard.size() - 1; i >= 0; --i) {
3782         const QString spec = keyboard.at(i);
3783         int colon=spec.indexOf(QLatin1Char(':'));
3784         if (colon>=0) {
3785             type = spec.left(colon);
3786             device = spec.mid(colon+1);
3787         } else {
3788             type = spec;
3789             device = QString();
3790         }
3791         QWSKeyboardHandler *handler = QKbdDriverFactory::create(type, device);
3792         setKeyboardHandler(handler);
3793     }
3794 }
3795 
3796 #endif //QT_NO_QWS_KEYBOARD
3797 
3798 QPoint QWSServer::mousePosition;
3799 QBrush *QWSServerPrivate::bgBrush = 0;
3800 
move_region(const QWSRegionMoveCommand * cmd)3801 void QWSServerPrivate::move_region(const QWSRegionMoveCommand *cmd)
3802 {
3803     QWSClient *serverClient = clientMap.value(-1);
3804     invokeRegionMove(cmd, serverClient);
3805 }
3806 
set_altitude(const QWSChangeAltitudeCommand * cmd)3807 void QWSServerPrivate::set_altitude(const QWSChangeAltitudeCommand *cmd)
3808 {
3809     QWSClient *serverClient = clientMap.value(-1);
3810     invokeSetAltitude(cmd, serverClient);
3811 }
3812 
set_opacity(const QWSSetOpacityCommand * cmd)3813 void QWSServerPrivate::set_opacity(const QWSSetOpacityCommand *cmd)
3814 {
3815     QWSClient *serverClient = clientMap.value(-1);
3816     invokeSetOpacity(cmd, serverClient);
3817 }
3818 
3819 
request_focus(const QWSRequestFocusCommand * cmd)3820 void QWSServerPrivate::request_focus(const QWSRequestFocusCommand *cmd)
3821 {
3822     invokeSetFocus(cmd, clientMap.value(-1));
3823 }
3824 
set_identity(const QWSIdentifyCommand * cmd)3825 void QWSServerPrivate::set_identity(const QWSIdentifyCommand *cmd)
3826 {
3827     invokeIdentify(cmd, clientMap.value(-1));
3828 }
3829 
repaint_region(int wid,int windowFlags,bool opaque,const QRegion & region)3830 void QWSServerPrivate::repaint_region(int wid, int windowFlags, bool opaque,
3831                                       const QRegion &region)
3832 {
3833     QWSWindow* changingw = findWindow(wid, 0);
3834     if (!changingw) {
3835         return;
3836     }
3837 
3838     const bool isOpaque = changingw->opaque;
3839     const bool wasPainted = changingw->d->painted;
3840     changingw->opaque = opaque;
3841     changingw->d->windowFlags = QFlag(windowFlags);
3842     changingw->d->dirtyOnScreen |= region;
3843     changingw->d->painted = true;
3844     if (isOpaque != opaque || !wasPainted)
3845         update_regions();
3846 
3847     int level = windows.indexOf(changingw);
3848     exposeRegion(region, level);
3849     changingw->d->dirtyOnScreen = QRegion();
3850 }
3851 
reserve_region(QWSWindow * win,const QRegion & region)3852 QRegion QWSServerPrivate::reserve_region(QWSWindow *win, const QRegion &region)
3853 {
3854     QRegion r = region;
3855 
3856     int oldPos = windows.indexOf(win);
3857     int newPos = oldPos < nReserved ? nReserved - 1 : nReserved;
3858     for (int i = 0; i < nReserved; ++i) {
3859         if (i != oldPos) {
3860             QWSWindow *w = windows.at(i);
3861             r -= w->requested_region;
3862         }
3863     }
3864     windows.move(oldPos, newPos);
3865     nReserved = newPos + 1;
3866 
3867     return r;
3868 }
3869 
request_region(int wid,const QString & surfaceKey,const QByteArray & surfaceData,const QRegion & region)3870 void QWSServerPrivate::request_region(int wid, const QString &surfaceKey,
3871                                       const QByteArray &surfaceData,
3872                                       const QRegion &region)
3873 {
3874     QWSWindow *changingw = findWindow(wid, 0);
3875     if (!changingw)
3876         return;
3877 
3878     Q_Q(QWSServer);
3879     QWSWindow::State windowState = QWSWindow::NoState;
3880 
3881     if (region.isEmpty()) {
3882         windowState = QWSWindow::Hiding;
3883         emit q->windowEvent(changingw, QWSServer::Hide);
3884     }
3885 
3886     const bool wasOpaque = changingw->opaque;
3887 
3888     QWSWindowSurface *surface = changingw->windowSurface();
3889     if (!surface) {
3890         changingw->createSurface(surfaceKey, surfaceData);
3891         surface = changingw->windowSurface();
3892     } else {
3893         surface->setPermanentState(surfaceData);
3894     }
3895 
3896     changingw->opaque = surface->isOpaque();
3897 
3898     QRegion r;
3899     if (surface->isRegionReserved())
3900         r = reserve_region(changingw, region);
3901     else
3902         r = region;
3903 
3904     if (!region.isEmpty())  {
3905         if (changingw->isVisible())
3906             windowState = QWSWindow::ChangingGeometry;
3907         else
3908             windowState = QWSWindow::Showing;
3909     }
3910     changingw->d->state = windowState;
3911 
3912     if (!r.isEmpty() && wasOpaque != changingw->opaque && surface->isBuffered())
3913         changingw->requested_region = QRegion(); // XXX: force update_regions
3914 
3915     const QRegion oldAllocated = changingw->allocatedRegion();
3916     setWindowRegion(changingw, r);
3917     if (oldAllocated == changingw->allocatedRegion()) {
3918         // Always send region event to the requesting window even if the
3919         // region didn't change. This is necessary as the client will reset
3920         // the clip region until an event is received.
3921         changingw->client()->sendRegionEvent(wid, changingw->allocatedRegion(),
3922                                              QWSRegionEvent::Allocation);
3923     }
3924 
3925     surface->QWindowSurface::setGeometry(r.boundingRect());
3926 
3927     if (windowState == QWSWindow::Showing)
3928         emit q->windowEvent(changingw, QWSServer::Show);
3929     else if (windowState == QWSWindow::ChangingGeometry)
3930         emit q->windowEvent(changingw, QWSServer::Geometry);
3931     if (windowState == QWSWindow::Hiding) {
3932         handleWindowClose(changingw);
3933         changingw->d->state = QWSWindow::Hidden;
3934         changingw->d->painted = false;
3935     } else {
3936         changingw->d->state = QWSWindow::Visible;
3937     }
3938 }
3939 
destroy_region(const QWSRegionDestroyCommand * cmd)3940 void QWSServerPrivate::destroy_region(const QWSRegionDestroyCommand *cmd)
3941 {
3942     invokeRegionDestroy(cmd, clientMap.value(-1));
3943 }
3944 
name_region(const QWSRegionNameCommand * cmd)3945 void QWSServerPrivate::name_region(const QWSRegionNameCommand *cmd)
3946 {
3947     invokeRegionName(cmd, clientMap.value(-1));
3948 }
3949 
3950 #ifndef QT_NO_QWS_INPUTMETHODS
im_response(const QWSIMResponseCommand * cmd)3951 void QWSServerPrivate::im_response(const QWSIMResponseCommand *cmd)
3952  {
3953      invokeIMResponse(cmd, clientMap.value(-1));
3954 }
3955 
im_update(const QWSIMUpdateCommand * cmd)3956 void QWSServerPrivate::im_update(const QWSIMUpdateCommand *cmd)
3957 {
3958     invokeIMUpdate(cmd, clientMap.value(-1));
3959 }
3960 
send_im_mouse(const QWSIMMouseCommand * cmd)3961 void QWSServerPrivate::send_im_mouse(const QWSIMMouseCommand *cmd)
3962 {
3963     if (current_IM)
3964         current_IM->mouseHandler(cmd->simpleData.index, cmd->simpleData.state);
3965 }
3966 #endif
3967 
openDisplay()3968 void QWSServerPrivate::openDisplay()
3969 {
3970     qt_init_display();
3971 
3972 //    rgnMan = qt_fbdpy->regionManager();
3973     swidth = qt_screen->deviceWidth();
3974     sheight = qt_screen->deviceHeight();
3975 }
3976 
closeDisplay()3977 void QWSServerPrivate::closeDisplay()
3978 {
3979     if (qt_screen)
3980         qt_screen->shutdownDevice();
3981 }
3982 
3983 /*!
3984     Returns the brush used as background in the absence of obscuring
3985     windows.
3986 
3987     \sa setBackground()
3988 */
backgroundBrush() const3989 const QBrush &QWSServer::backgroundBrush() const
3990 {
3991     return *QWSServerPrivate::bgBrush;
3992 }
3993 
3994 /*!
3995     Sets the brush used as background in the absence of obscuring
3996     windows, to be the given \a brush.
3997 
3998     Note that this function can only be used in the server process.
3999 
4000     \sa backgroundBrush()
4001 */
setBackground(const QBrush & brush)4002 void QWSServer::setBackground(const QBrush &brush)
4003 {
4004     if (!QWSServerPrivate::bgBrush)
4005         QWSServerPrivate::bgBrush = new QBrush(brush);
4006     else
4007         *QWSServerPrivate::bgBrush = brush;
4008     if (!qwsServer)
4009         return;
4010     qt_screen->exposeRegion(QRect(0,0,qt_screen->width(), qt_screen->height()), 0);
4011 }
4012 
4013 
4014 #ifdef QT3_SUPPORT
4015 /*!
4016     \fn void QWSServer::setDesktopBackground(const QImage &image)
4017 
4018     Sets the image used as background in the absence of obscuring
4019     windows, to be the given \a image.
4020 
4021     Use the setBackground() function instead.
4022 
4023     \oldcode
4024         QImage image;
4025         setDesktopBackground(image);
4026     \newcode
4027         QImage image;
4028         setBackground(QBrush(image));
4029     \endcode
4030 */
setDesktopBackground(const QImage & img)4031 void QWSServer::setDesktopBackground(const QImage &img)
4032 {
4033     if (img.isNull())
4034         setBackground(Qt::NoBrush);
4035     else
4036         setBackground(QBrush(QPixmap::fromImage(img)));
4037 }
4038 
4039 /*!
4040     \fn void QWSServer::setDesktopBackground(const QColor &color)
4041     \overload
4042 
4043     Sets the color used as background in the absence of obscuring
4044     windows, to be the given \a color.
4045 
4046     Use the setBackground() function instead.
4047 
4048     \oldcode
4049         QColor color;
4050         setDesktopBackground(color);
4051     \newcode
4052         QColor color;
4053         setBackground(QBrush(color));
4054     \endcode
4055 */
setDesktopBackground(const QColor & c)4056 void QWSServer::setDesktopBackground(const QColor &c)
4057 {
4058     setBackground(QBrush(c));
4059 }
4060 #endif //QT3_SUPPORT
4061 
4062 /*!
4063   \internal
4064  */
startup(int flags)4065 void QWSServer::startup(int flags)
4066 {
4067     if (qwsServer)
4068         return;
4069     unlink(qws_qtePipeFilename().toLatin1().constData());
4070     (void)new QWSServer(flags);
4071 }
4072 
4073 /*!
4074   \internal
4075 */
4076 
closedown()4077 void QWSServer::closedown()
4078 {
4079     QScopedPointer<QWSServer> server(qwsServer);
4080     qwsServer = 0;
4081     QT_TRY {
4082         unlink(qws_qtePipeFilename().toLatin1().constData());
4083     } QT_CATCH(const std::bad_alloc &) {
4084         // ### TODO - what to do when we run out of memory
4085         // when calling toLatin1?
4086     }
4087 }
4088 
emergency_cleanup()4089 void QWSServerPrivate::emergency_cleanup()
4090 {
4091 #ifndef QT_NO_QWS_KEYBOARD
4092     if (qwsServer)
4093         qwsServer->closeKeyboard();
4094 #endif
4095 }
4096 
4097 #ifndef QT_NO_QWS_KEYBOARD
4098 static QList<QWSServer::KeyboardFilter*> *keyFilters = 0;
4099 
4100 /*!
4101     Processes the given key event. The key is identified by its \a
4102     unicode value and the given \a keycode, \a modifiers, \a isPress
4103     and \a autoRepeat parameters.
4104 
4105     The \a keycode parameter is the Qt keycode value as defined by the
4106     Qt::Key enum. The \a modifiers is an OR combination of
4107     Qt::KeyboardModifier values, indicating whether \gui
4108     Shift/Alt/Ctrl keys are pressed. The \a isPress parameter is true
4109     if the event is a key press event and \a autoRepeat is true if the
4110     event is caused by an auto-repeat mechanism and not an actual key
4111     press.
4112 
4113     This function is typically called internally by keyboard drivers.
4114     Note that this function can only be used in the server process.
4115 
4116     \sa sendKeyEvent(), {Qt for Embedded Linux Character Input}
4117 */
processKeyEvent(int unicode,int keycode,Qt::KeyboardModifiers modifiers,bool isPress,bool autoRepeat)4118 void QWSServer::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
4119                                 bool isPress, bool autoRepeat)
4120 {
4121     bool block;
4122     // Don't block the POWER or LIGHT keys
4123     if ( keycode == Qt::Key_F34 || keycode == Qt::Key_F35 )
4124         block = false;
4125     else
4126         block = qwsServerPrivate->screensaverblockevent(KEY, qwsServerPrivate->screensaverinterval, isPress);
4127 
4128 #ifdef EVENT_BLOCK_DEBUG
4129     qDebug() << "processKeyEvent" << unicode << keycode << modifiers << isPress << autoRepeat << (block ? "block" : "pass");
4130 #endif
4131 
4132     // If we press a key and it's going to be blocked, wake up the screen
4133     if (block) {
4134         if (isPress)
4135             qwsServerPrivate->_q_screenSaverWake();
4136         return;
4137     }
4138 
4139     if (keyFilters) {
4140         for (int i = 0; i < keyFilters->size(); ++i) {
4141             QWSServer::KeyboardFilter *keyFilter = keyFilters->at(i);
4142             if (keyFilter->filter(unicode, keycode, modifiers, isPress, autoRepeat))
4143                 return;
4144         }
4145     }
4146     sendKeyEvent(unicode, keycode, modifiers, isPress, autoRepeat);
4147 }
4148 
4149 /*!
4150     \fn void QWSServer::addKeyboardFilter(KeyboardFilter *filter)
4151 
4152     Activates the given keyboard \a filter all key events generated by
4153     physical keyboard drivers (i.e., events sent using the
4154     processKeyEvent() function).
4155 
4156     Note that the filter is not invoked for keys generated by \e
4157     virtual keyboard drivers (i.e., events sent using the
4158     sendKeyEvent() function).
4159 
4160     Note that this function can only be used in the server process.
4161 
4162     \sa removeKeyboardFilter()
4163 */
addKeyboardFilter(KeyboardFilter * f)4164 void QWSServer::addKeyboardFilter(KeyboardFilter *f)
4165 {
4166      if (!keyFilters)
4167         keyFilters = new QList<QWSServer::KeyboardFilter*>;
4168      if (f) {
4169         keyFilters->prepend(f);
4170      }
4171 }
4172 
4173 /*
4174 //#######
4175  We should probably obsolete the whole keyboard filter thing since
4176  it's not useful for input methods anyway
4177 
4178  We could do removeKeyboardFilter(KeyboardFilter *f), but
4179  the "remove and delete the filter" concept does not match "user
4180  remembers the pointer".
4181 */
4182 
4183 /*!
4184     Removes and deletes the most recently added filter.
4185 
4186     Note that the programmer is responsible for removing each added
4187     keyboard filter.
4188 
4189     Note that this function can only be used in the server process.
4190 
4191     \sa addKeyboardFilter()
4192 */
removeKeyboardFilter()4193 void QWSServer::removeKeyboardFilter()
4194 {
4195      if (!keyFilters || keyFilters->isEmpty())
4196          return;
4197      delete keyFilters->takeAt(0);
4198 }
4199 #endif // QT_NO_QWS_KEYBOARD
4200 
4201 /*!
4202     \fn void QWSServer::setScreenSaverIntervals(int* intervals)
4203 
4204     Specifies the time \a intervals (in milliseconds) between the
4205     different levels of screen responsiveness.
4206 
4207     \l{Qt for Embedded Linux} supports multilevel screen saving, i.e., it is
4208     possible to specify several different levels of screen
4209     responsiveness by implementing the QWSScreenSaver::save()
4210     function. For example, you can choose to first turn off the light
4211     before you fully activate the screensaver. See the QWSScreenSaver
4212     documentation for details.
4213 
4214     Note that an interval of 0 milliseconds will turn off the
4215     screensaver, and that the \a intervals array must be 0-terminated.
4216     This function can only be used in the server process.
4217 
4218     \sa setScreenSaverInterval(), setScreenSaverBlockLevel()
4219 */
setScreenSaverIntervals(int * ms)4220 void QWSServer::setScreenSaverIntervals(int* ms)
4221 {
4222     if (!qwsServerPrivate)
4223         return;
4224 
4225     delete [] qwsServerPrivate->screensaverintervals;
4226     if (ms) {
4227         int* t=ms;
4228         int n=0;
4229         while (*t++) n++;
4230         if (n) {
4231             n++; // the 0
4232             qwsServerPrivate->screensaverintervals = new int[n];
4233             memcpy(qwsServerPrivate->screensaverintervals, ms, n*sizeof(int));
4234         } else {
4235             qwsServerPrivate->screensaverintervals = 0;
4236         }
4237     } else {
4238         qwsServerPrivate->screensaverintervals = 0;
4239     }
4240     qwsServerPrivate->screensaverinterval = 0;
4241 
4242     qwsServerPrivate->screensavertimer->stop();
4243     qt_screen->blank(false);
4244     qwsServerPrivate->_q_screenSaverWake();
4245 }
4246 
4247 /*!
4248     \fn void QWSServer::setScreenSaverInterval(int milliseconds)
4249 
4250     Sets the timeout interval for the screensaver to the specified \a
4251     milliseconds. To turn off the screensaver, set the timout interval
4252     to 0.
4253 
4254     Note that this function can only be used in the server process.
4255 
4256     \sa setScreenSaverIntervals(), setScreenSaverBlockLevel()
4257 */
setScreenSaverInterval(int ms)4258 void QWSServer::setScreenSaverInterval(int ms)
4259 {
4260     int v[2];
4261     v[0] = ms;
4262     v[1] = 0;
4263     setScreenSaverIntervals(v);
4264 }
4265 
4266 /*!
4267   Block the key or mouse event that wakes the system from level \a eventBlockLevel or higher.
4268   To completely disable event blocking (the default behavior), set \a eventBlockLevel to -1.
4269 
4270   The algorithm blocks the "down", "up" as well as any "repeat" events for the same key
4271   but will not block other key events after the initial "down" event. For mouse events, the
4272   algorithm blocks all mouse events until an event with no buttons pressed is received.
4273 
4274   There are 2 keys that are never blocked, Qt::Key_F34 (POWER) and Qt::Key_F35 (LIGHT).
4275 
4276   Example usage:
4277 
4278   \snippet doc/src/snippets/code/src_gui_embedded_qwindowsystem_qws.cpp 0
4279 
4280     Note that this function can only be used in the server process.
4281 
4282   \sa setScreenSaverIntervals(), setScreenSaverInterval()
4283 */
setScreenSaverBlockLevel(int eventBlockLevel)4284 void QWSServer::setScreenSaverBlockLevel(int eventBlockLevel)
4285 {
4286     if (!qwsServerPrivate)
4287         return;
4288     qwsServerPrivate->screensavereventblocklevel = eventBlockLevel;
4289 #ifdef EVENT_BLOCK_DEBUG
4290     qDebug() << "QWSServer::setScreenSaverBlockLevel() " << eventBlockLevel;
4291 #endif
4292 }
4293 
4294 extern bool qt_disable_lowpriority_timers; //in qeventloop_unix.cpp
4295 
_q_screenSaverWake()4296 void QWSServerPrivate::_q_screenSaverWake()
4297 {
4298     if (screensaverintervals) {
4299         if (screensaverinterval != screensaverintervals) {
4300             if (saver) saver->restore();
4301             screensaverinterval = screensaverintervals;
4302             screensaverblockevents = false;
4303         } else {
4304             if (!screensavertimer->isActive()) {
4305                 qt_screen->blank(false);
4306                 if (saver) saver->restore();
4307             }
4308         }
4309         screensavertimer->start(*screensaverinterval);
4310         screensavertime.start();
4311     }
4312     qt_disable_lowpriority_timers=false;
4313 }
4314 
_q_screenSaverSleep()4315 void QWSServerPrivate::_q_screenSaverSleep()
4316 {
4317     qt_screen->blank(true);
4318 #if !defined(QT_QWS_IPAQ) && !defined(QT_QWS_EBX)
4319     screensavertimer->stop();
4320 #else
4321     if (screensaverinterval) {
4322         screensavertimer->start(*screensaverinterval);
4323         screensavertime.start();
4324     } else {
4325         screensavertimer->stop();
4326     }
4327 #endif
4328     qt_disable_lowpriority_timers=true;
4329 }
4330 
4331 /*!
4332     \fn void QWSServer::setScreenSaver(QWSScreenSaver* screenSaver)
4333 
4334     Installs the given \a screenSaver, deleting the current screen
4335     saver.
4336 
4337     Note that this function can only be used in the server process.
4338 
4339     \sa screenSaverActivate(), setScreenSaverInterval(), setScreenSaverIntervals(), setScreenSaverBlockLevel()
4340 */
setScreenSaver(QWSScreenSaver * ss)4341 void QWSServer::setScreenSaver(QWSScreenSaver* ss)
4342 {
4343     QWSServerPrivate *qd = qwsServer->d_func();
4344     delete qd->saver;
4345     qd->saver = ss;
4346 }
4347 
screenSave(int level)4348 void QWSServerPrivate::screenSave(int level)
4349 {
4350     if (saver) {
4351         // saver->save() may call QCoreApplication::processEvents,
4352         // block event before calling saver->save().
4353         bool oldScreensaverblockevents = screensaverblockevents;
4354         if (*screensaverinterval >= 1000) {
4355             screensaverblockevents = (screensavereventblocklevel >= 0 && screensavereventblocklevel <= level);
4356 #ifdef EVENT_BLOCK_DEBUG
4357             if (screensaverblockevents)
4358                 qDebug("ready to block events");
4359 #endif
4360         }
4361         int *oldScreensaverinterval = screensaverinterval;
4362         if (saver->save(level)) {
4363             // only update screensaverinterval if it hasn't already changed
4364             if (oldScreensaverinterval == screensaverinterval) {
4365                 if (screensaverinterval && screensaverinterval[1]) {
4366                     screensavertimer->start(*++screensaverinterval);
4367                     screensavertime.start();
4368                 } else {
4369                     screensaverinterval = 0;
4370                 }
4371             }
4372         } else {
4373             // restore previous state
4374             screensaverblockevents = oldScreensaverblockevents;
4375 
4376             // for some reason, the saver don't want us to change to the
4377             // next level, so we'll stay at this level for another interval
4378             if (screensaverinterval && *screensaverinterval) {
4379                 screensavertimer->start(*screensaverinterval);
4380                 screensavertime.start();
4381             }
4382         }
4383     } else {
4384         screensaverinterval = 0;//screensaverintervals;
4385         screensaverblockevents = false;
4386         _q_screenSaverSleep();
4387     }
4388 }
4389 
_q_screenSaverTimeout()4390 void QWSServerPrivate::_q_screenSaverTimeout()
4391 {
4392     if (screensaverinterval) {
4393         if (screensavertime.elapsed() > *screensaverinterval*2) {
4394             // bogus (eg. unsuspend, system time changed)
4395             _q_screenSaverWake(); // try again
4396             return;
4397         }
4398         screenSave(screensaverinterval - screensaverintervals);
4399     }
4400 }
4401 
4402 /*!
4403     Returns true if the screen saver is active; otherwise returns
4404     false.
4405 
4406     Note that this function can only be used in the server process.
4407 
4408     \sa screenSaverActivate()
4409 */
screenSaverActive()4410 bool QWSServer::screenSaverActive()
4411 {
4412     return qwsServerPrivate->screensaverinterval
4413         && !qwsServerPrivate->screensavertimer->isActive();
4414 }
4415 
4416 /*!
4417     \internal
4418 */
updateWindowRegions() const4419 void QWSServer::updateWindowRegions() const
4420 {
4421     qwsServerPrivate->update_regions();
4422 }
4423 
4424 /*!
4425     Activates the screen saver if \a activate is true; otherwise it is
4426     deactivated.
4427 
4428     Note that this function can only be used in the server process.
4429 
4430     \sa screenSaverActive(), setScreenSaver()
4431 */
screenSaverActivate(bool activate)4432 void QWSServer::screenSaverActivate(bool activate)
4433 {
4434     if (activate)
4435         qwsServerPrivate->_q_screenSaverSleep();
4436     else
4437         qwsServerPrivate->_q_screenSaverWake();
4438 }
4439 
disconnectClient(QWSClient * c)4440 void QWSServerPrivate::disconnectClient(QWSClient *c)
4441 {
4442     QTimer::singleShot(0, c, SLOT(closeHandler()));
4443 }
4444 
updateClientCursorPos()4445 void QWSServerPrivate::updateClientCursorPos()
4446 {
4447     Q_Q(QWSServer);
4448     QWSWindow *win = qwsServerPrivate->mouseGrabber ? qwsServerPrivate->mouseGrabber : qwsServer->windowAt(QWSServer::mousePosition);
4449     QWSClient *winClient = win ? win->client() : 0;
4450     if (winClient && winClient != cursorClient)
4451         q->sendMouseEvent(QWSServer::mousePosition, mouseState);
4452 }
4453 
4454 #ifndef QT_NO_QWS_INPUTMETHODS
4455 
4456 /*!
4457     \class QWSInputMethod
4458     \preliminary
4459     \ingroup qws
4460 
4461     \brief The QWSInputMethod class provides international input methods
4462     in Qt for Embedded Linux.
4463 
4464     Note that this class is only available in \l{Qt for Embedded Linux}.
4465 
4466     A \l{Qt for Embedded Linux} application requires a server application to be
4467     running, or to be the server application itself. All system
4468     generated events, including keyboard and mouse events, are passed
4469     to the server application which then propagates the event to the
4470     appropriate client.
4471 
4472     An input method consists of a filter and optionally a graphical
4473     interface, and is used to filter input events between the server
4474     and the client application.
4475 
4476     \tableofcontents
4477 
4478     \section1 Creating Custom Input Methods
4479 
4480     To implement a custom input method, derive from the QWSInputMethod
4481     class, and use the server's \l
4482     {QWSServer::}{setCurrentInputMethod()} function to install it.
4483 
4484     When subclassing QWSInputMethod, you can reimplement the filter()
4485     functions to handle input from both physical and virtual keyboards
4486     as well as mouse devices. Note that the default implementations do
4487     nothing. Use the setInputResolution() function to control the
4488     number of bits shifted when filtering mouse input, i.e., when
4489     going from pointer resolution to screen resolution (the current
4490     resolution can be retrieved using the inputResolutionShift()
4491     function).
4492 
4493     Reimplement the reset() function to restore the state of the input
4494     method. Note that the default implementation calls the sendEvent()
4495     function with empty preedit and commit strings if the input method
4496     is in compose mode (i.e., if the input method is actively
4497     composing a preedit string).
4498 
4499     To receive replies to an input method query (sent using the
4500     sendQuery() function), you must reimplement the queryResponse()
4501     function, while the mouseHandler() function must be reimplemented
4502     if you want to handle mouse events within the preedit
4503     text. Reimplement the updateHandler() function to handle update
4504     events including resets and focus changes. The UpdateType enum
4505     describes the various types of update events recognized by the
4506     input method.
4507 
4508     \section1 Using Input Methods
4509 
4510     In addition to the filter(), reset(), queryResponse(),
4511     mouseHandler() and updateHandler() function mentioned in the
4512     previous section, the QWSInputMethod provides several other
4513     functions helping the window system to manage the installed input
4514     methods.
4515 
4516     The sendEvent() function sends the given event to the focus
4517     widget, while the sendPreeditString() function sends the given
4518     preedit text (encapsulated by an event). QWSInputMethod also
4519     provides the sendCommitString() convenience function which sends
4520     an event encapsulating the given commit string to the current
4521     focus widget, and the sendMouseEvent() function which sends the
4522     given mouse event.
4523 
4524     Finally, the QWSInputMethod class provides the sendQuery()
4525     function for sending input method queries. This function
4526     encapsulates the event with a QWSEvent instance of the \l
4527     {QWSEvent::}{IMQuery} type.
4528 
4529     \sa QWSServer, {Qt for Embedded Linux Architecture}
4530 */
4531 
4532 /*!
4533     Constructs a new input method.
4534 
4535     Use the QWSServer::setCurrentInputMethod() function to install it.
4536 */
4537 
QWSInputMethod()4538 QWSInputMethod::QWSInputMethod()
4539 {
4540 
4541 }
4542 
4543 /*!
4544     Destroys this input method, uninstalling it if it is installed.
4545 */
~QWSInputMethod()4546 QWSInputMethod::~QWSInputMethod()
4547 {
4548     if (current_IM == this)
4549         current_IM = 0;
4550 }
4551 
4552 /*!
4553     Filters the key input identified by the given \a unicode, \a
4554     keycode, \a modifiers, \a isPress and \a autoRepeat parameters.
4555 
4556     Note that the default implementation does nothing; reimplement
4557     this function to handle input from both physical and virtual
4558     devices.
4559 
4560     The \a keycode is a Qt::Key value, and the \a modifiers is an OR
4561     combination of Qt::KeyboardModifiers. The \a isPress parameter is
4562     telling whether the input is a key press or key release, and the
4563     \a autoRepeat parameter determines whether the input is
4564     autorepeated ( i.e., in which case the
4565     QWSKeyboardHandler::beginAutoRepeat() function has been called).
4566 
4567     To block the event from further processing, return true when
4568     reimplementing this function; the default implementation returns
4569     false.
4570 
4571     \sa setInputResolution(), inputResolutionShift()
4572 */
filter(int unicode,int keycode,int modifiers,bool isPress,bool autoRepeat)4573 bool QWSInputMethod::filter(int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat)
4574 {
4575     Q_UNUSED(unicode);
4576     Q_UNUSED(keycode);
4577     Q_UNUSED(modifiers);
4578     Q_UNUSED(isPress);
4579     Q_UNUSED(autoRepeat);
4580     return false;
4581 }
4582 
4583 /*!
4584     \overload
4585 
4586     Filters the mouse input identified by the given \a position, \a
4587     state, and \a wheel parameters.
4588 */
filter(const QPoint & position,int state,int wheel)4589 bool QWSInputMethod::filter(const QPoint &position, int state, int wheel)
4590 {
4591     Q_UNUSED(position);
4592     Q_UNUSED(state);
4593     Q_UNUSED(wheel);
4594     return false;
4595 }
4596 
4597 /*!
4598     Resets the state of the input method.
4599 
4600     If the input method is in compose mode, i.e., the input method is
4601     actively composing a preedit string, the default implementation
4602     calls sendEvent() with empty preedit and commit strings; otherwise
4603     it does nothing. Reimplement this function to alter this behavior.
4604 
4605     \sa sendEvent()
4606 */
reset()4607 void QWSInputMethod::reset()
4608 {
4609     if (current_IM_composing_win) {
4610         QInputMethodEvent ime;
4611         sendEvent(&ime);
4612     }
4613 }
4614 
4615 /*!
4616     \enum QWSInputMethod::UpdateType
4617 
4618     This enum describes the various types of update events recognized
4619     by the input method.
4620 
4621     \value Update    The input widget is updated in some way; use sendQuery() with
4622                             Qt::ImMicroFocus as an argument for more information.
4623     \value FocusIn   A new input widget receives focus.
4624     \value FocusOut  The input widget loses focus.
4625     \value Reset       The input method should be reset.
4626     \value Destroyed The input widget is destroyed.
4627 
4628     \sa updateHandler()
4629 */
4630 
4631 /*!
4632     Handles update events including resets and focus changes. The
4633     update events are specified by the given \a type which is one of
4634     the UpdateType enum values.
4635 
4636     Note that reimplementations of this function must call the base
4637     implementation for all cases that it does not handle itself.
4638 
4639     \sa UpdateType
4640 */
updateHandler(int type)4641 void QWSInputMethod::updateHandler(int type)
4642 {
4643     switch (type) {
4644     case FocusOut:
4645     case Reset:
4646         reset();
4647         break;
4648 
4649     default:
4650         break;
4651     }
4652 }
4653 
4654 
4655 /*!
4656     Receive replies to an input method query.
4657 
4658     Note that the default implementation does nothing; reimplement
4659     this function to receive such replies.
4660 
4661     Internally, an input method query is passed encapsulated by an \l
4662     {QWSEvent::IMQuery}{IMQuery} event generated by the sendQuery()
4663     function. The queried property and the result is passed in the \a
4664     property and \a result parameters.
4665 
4666     \sa sendQuery(), QWSServer::sendIMQuery()
4667 */
queryResponse(int property,const QVariant & result)4668 void QWSInputMethod::queryResponse(int property, const QVariant &result)
4669 {
4670     Q_UNUSED(property);
4671     Q_UNUSED(result);
4672 }
4673 
4674 
4675 
4676 /*!
4677     \fn void QWSInputMethod::mouseHandler(int offset, int state)
4678 
4679     Handles mouse events within the preedit text.
4680 
4681     Note that the default implementation resets the input method on
4682     all mouse presses; reimplement this function to alter this
4683     behavior.
4684 
4685     The \a offset parameter specifies the position of the mouse event
4686     within the string, and \a state specifies the type of the mouse
4687     event as described by the QWSServer::IMMouse enum. If \a state is
4688     less than 0, the mouse event is inside the associated widget, but
4689     outside the preedit text. When clicking in a different widget, the
4690     \a state is QWSServer::MouseOutside.
4691 
4692     \sa sendPreeditString(), reset()
4693 */
mouseHandler(int,int state)4694 void QWSInputMethod::mouseHandler(int, int state)
4695 {
4696     if (state == QWSServer::MousePress || state == QWSServer::MouseOutside)
4697         reset();
4698 }
4699 
4700 
4701 /*!
4702     Sends an event encapsulating the given \a preeditString, to the
4703     focus widget.
4704 
4705     The specified \a selectionLength is the number of characters to be
4706     marked as selected (starting at the given \a cursorPosition). If
4707     \a selectionLength is negative, the text \e before \a
4708     cursorPosition is marked.
4709 
4710     The preedit string is marked with QInputContext::PreeditFormat,
4711     and the selected part is marked with
4712     QInputContext::SelectionFormat.
4713 
4714     Sending an input method event with a non-empty preedit string will
4715     cause the input method to enter compose mode.  Sending an input
4716     method event with an empty preedit string will cause the input
4717     method to leave compose mode, i.e., the input method will no longer
4718     be actively composing the preedit string.
4719 
4720     Internally, the event is represented by a QWSEvent object of the
4721     \l {QWSEvent::IMEvent}{IMEvent} type.
4722 
4723     \sa sendEvent(), sendCommitString()
4724 */
4725 
sendPreeditString(const QString & preeditString,int cursorPosition,int selectionLength)4726 void QWSInputMethod::sendPreeditString(const QString &preeditString, int cursorPosition, int selectionLength)
4727 {
4728     QList<QInputMethodEvent::Attribute> attributes;
4729 
4730     int selPos = cursorPosition;
4731     if (selectionLength == 0) {
4732         selPos = 0;
4733     } else if (selectionLength < 0) {
4734         selPos += selectionLength;
4735         selectionLength = -selectionLength;
4736     }
4737     if (selPos > 0)
4738         attributes += QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, selPos,
4739                                                    QVariant(int(QInputContext::PreeditFormat)));
4740 
4741     if (selectionLength)
4742         attributes += QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, selPos, selectionLength,
4743                                                    QVariant(int(QInputContext::SelectionFormat)));
4744 
4745     if (selPos + selectionLength < preeditString.length())
4746         attributes += QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
4747                                                    selPos + selectionLength,
4748                                                    preeditString.length() - selPos - selectionLength,
4749                                                    QVariant(int(QInputContext::PreeditFormat)));
4750 
4751     attributes += QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursorPosition,  0, QVariant());
4752 
4753     QInputMethodEvent ime(preeditString, attributes);
4754     qwsServer->sendIMEvent(&ime);
4755 }
4756 
4757 /*!
4758     \fn void QWSInputMethod::sendCommitString(const QString &commitString, int replaceFromPosition, int replaceLength)
4759 
4760     Sends an event encapsulating the given \a commitString, to the
4761     focus widget.
4762 
4763     Note that this will cause the input method to leave compose mode,
4764     i.e., the input method will no longer be actively composing the
4765     preedit string.
4766 
4767     If the specified \a replaceLength is greater than 0, the commit
4768     string will replace the given number of characters of the
4769     receiving widget's previous text, starting at the given \a
4770     replaceFromPosition relative to the start of the current preedit
4771     string.
4772 
4773     Internally, the event is represented by a QWSEvent object of the
4774     \l {QWSEvent::IMEvent}{IMEvent} type.
4775 
4776     \sa sendEvent(), sendPreeditString()
4777 */
sendCommitString(const QString & commitString,int replaceFrom,int replaceLength)4778 void QWSInputMethod::sendCommitString(const QString &commitString, int replaceFrom, int replaceLength)
4779 {
4780     QInputMethodEvent ime;
4781     ime.setCommitString(commitString, replaceFrom, replaceLength);
4782     qwsServer->sendIMEvent(&ime);
4783 }
4784 
4785 /*!
4786     \fn QWSInputMethod::sendIMEvent(QWSServer::IMState state, const QString &text, int cursorPosition, int selectionLength)
4787     \obsolete
4788 
4789     Sends a QInputMethodEvent object to the focus widget.
4790 
4791     If the specified \a state is QWSServer::IMCompose, \a text is a
4792     preedit string, \a cursorPosition is the cursor's position within
4793     the preedit string, and \a selectionLength is the number of
4794     characters (starting at \a cursorPosition) that should be marked
4795     as selected by the input widget receiving the event. If the
4796     specified \a state is QWSServer::IMEnd, \a text is a commit
4797     string.
4798 
4799     Use sendEvent(), sendPreeditString() or sendCommitString() instead.
4800 */
4801 
4802 /*!
4803     \fn QWSInputMethod::sendEvent(const QInputMethodEvent *event)
4804 
4805     Sends the given \a event to the focus widget.
4806 
4807     The \c QInputMethodEvent class is derived from QWSEvent, i.e., the
4808     given \a event is a QWSEvent object of the \l
4809     {QWSEvent::IMEvent}{IMEvent} type.
4810 
4811     \sa sendPreeditString(), sendCommitString(), reset()
4812 */
4813 
4814 
4815 /*!
4816     \fn void QWSInputMethod::sendQuery(int property)
4817 
4818     Sends an input method query (internally encapsulated by a QWSEvent
4819     of the \l {QWSEvent::IMQuery}{IMQuery} type) for the specified \a
4820     property.
4821 
4822     To receive responses to input method queries, the virtual
4823     queryResponse() function must be reimplemented.
4824 
4825     \sa queryResponse(), QWSServer::sendIMQuery()
4826 */
4827 
4828 /*!
4829     Sets and returns the number of bits shifted to go from pointer
4830     resolution to screen resolution when filtering mouse input.
4831 
4832     If \a isHigh is true and the device has a pointer device
4833     resolution twice or more of the screen resolution, the positions
4834     passed to the filter() function will be presented at the higher
4835     resolution; otherwise the resolution will be equal to that of the
4836     screen resolution.
4837 
4838     \sa inputResolutionShift(), filter()
4839 */
setInputResolution(bool isHigh)4840 uint QWSInputMethod::setInputResolution(bool isHigh)
4841 {
4842     mIResolution = isHigh;
4843     return inputResolutionShift();
4844 }
4845 
4846 /*!
4847     Returns the number of bits shifted to go from pointer resolution
4848     to screen resolution when filtering mouse input.
4849 
4850     \sa setInputResolution(), filter()
4851 */
inputResolutionShift() const4852 uint QWSInputMethod::inputResolutionShift() const
4853 {
4854     return 0; // default for devices with single resolution.
4855 }
4856 
4857 /*!
4858     \fn void QWSInputMethod::sendMouseEvent( const QPoint &position, int state, int wheel )
4859 
4860     Sends a mouse event specified by the given \a position, \a state
4861     and \a wheel parameters.
4862 
4863     The given \a position will be transformed if the screen
4864     coordinates do not match the pointer device coordinates.
4865 
4866     Note that the event will be not be tested by the active input
4867     method, but calling the QWSServer::sendMouseEvent() function will
4868     make the current input method filter the event.
4869 
4870     \sa mouseHandler(), sendEvent()
4871 */
sendMouseEvent(const QPoint & pos,int state,int wheel)4872 void QWSInputMethod::sendMouseEvent( const QPoint &pos, int state, int wheel )
4873 {
4874         if (qt_last_x) {
4875          *qt_last_x = pos.x();
4876          *qt_last_y = pos.y();
4877     }
4878     QWSServer::mousePosition = pos;
4879     qwsServerPrivate->mouseState = state;
4880     QWSServerPrivate::sendMouseEventUnfiltered(pos, state, wheel);
4881 }
4882 #endif // QT_NO_QWS_INPUTMETHODS
4883 
4884 /*!
4885     \fn  QWSWindow::QWSWindow(int i, QWSClient * client)
4886     \internal
4887 
4888     Constructs a new top-level window, associated with the client \a
4889     client and giving it the id \a i.
4890 */
4891 
4892 /*!
4893     \fn QWSServer::windowEvent(QWSWindow * window, QWSServer::WindowEvent eventType)
4894 
4895     This signal is emitted whenever something happens to a top-level
4896     window (e.g., it's created or destroyed), passing a pointer to the
4897     window and the event's type in the \a window and \a eventType
4898     parameters, respectively.
4899 
4900     \sa markedText()
4901 */
4902 
4903 /*!
4904     \class QWSServer::KeyboardFilter
4905     \ingroup qws
4906 
4907     \brief The KeyboardFilter class is a base class for global
4908     keyboard event filters in Qt for Embedded Linux.
4909 
4910     Note that this class is only available in \l{Qt for Embedded Linux}.
4911 
4912     In \l{Qt for Embedded Linux}, all system generated events, including
4913     keyboard events, are passed to the server application which then
4914     propagates the event to the appropriate client. The KeyboardFilter
4915     class is used to implement a global, low-level filter on the
4916     server side. The server applies the filter to all keyboard events
4917     before passing them on to the clients:
4918 
4919     \image qwsserver_keyboardfilter.png
4920 
4921     This feature can, for example, be used to filter things like APM
4922     (advanced power management) suspended from a button without having
4923     to filter for it in all applications.
4924 
4925     To add a new keyboard filter you must first create the filter by
4926     deriving from this class, reimplementing the pure virtual filter()
4927     function. Then you can install the filter on the server using
4928     QWSServer's \l {QWSServer::}{addKeyboardFilter()}
4929     function. QWSServer also provides a \l
4930     {QWSServer::}{removeKeyboardFilter()} function.
4931 
4932     \sa {Qt for Embedded Linux Architecture}, QWSServer, QWSInputMethod
4933 */
4934 
4935 /*!
4936     \fn QWSServer::KeyboardFilter::~KeyboardFilter()
4937 
4938     Destroys the keyboard filter.
4939 */
4940 
4941 /*!
4942     \fn bool QWSServer::KeyboardFilter::filter(int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat)
4943 
4944     Implement this function to return true if a given key event should
4945     be stopped from being processed any further; otherwise it should
4946     return false.
4947 
4948     A key event can be identified by the given \a unicode value and
4949     the \a keycode, \a modifiers, \a isPress and \a autoRepeat
4950     parameters.
4951 
4952     The \a keycode parameter is the Qt keycode value as defined by the
4953     Qt::Key enum. The \a modifiers is an OR combination of
4954     Qt::KeyboardModifier values, indicating whether \gui
4955     Shift/Alt/Ctrl keys are pressed. The \a isPress parameter is true
4956     if the event is a key press event and \a autoRepeat is true if the
4957     event is caused by an auto-repeat mechanism and not an actual key
4958     press.
4959 */
4960 
4961 QT_END_NAMESPACE
4962 
4963 #include "moc_qwindowsystem_qws.cpp"
4964