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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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 ®ion)
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