source: trunk/src/gui/embedded/qwindowsystem_qws.cpp@ 635

Last change on this file since 635 was 561, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 143.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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
110QT_BEGIN_NAMESPACE
111
112QWSServer Q_GUI_EXPORT *qwsServer=0;
113static QWSServerPrivate *qwsServerPrivate=0;
114
115#define MOUSE 0
116#define KEY 1
117//#define EVENT_BLOCK_DEBUG
118
119QWSScreenSaver::~QWSScreenSaver()
120{
121}
122
123extern QByteArray qws_display_spec;
124extern void qt_init_display(); //qapplication_qws.cpp
125extern QString qws_qtePipeFilename();
126
127extern void qt_client_enqueue(const QWSEvent *); //qapplication_qws.cpp
128extern QList<QWSCommand*> *qt_get_server_queue();
129
130Q_GLOBAL_STATIC_WITH_ARGS(QString, defaultMouse, (QLatin1String("Auto")))
131Q_GLOBAL_STATIC_WITH_ARGS(QString, defaultKeyboard, (QLatin1String("TTY")))
132static const int FontCleanupInterval = 60 * 1000;
133
134static int qws_keyModifiers = 0;
135
136static QWSWindow *keyboardGrabber;
137static bool keyboardGrabbing;
138
139static 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
147static QWSInputMethod *current_IM = 0;
148
149static QWSWindow *current_IM_composing_win = 0;
150static int current_IM_winId = -1;
151static bool force_reject_strokeIM = false;
152#endif
153
154static 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
218class QWSWindowPrivate
219{
220public:
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
237QWSWindowPrivate::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
367QWSWindow::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*/
402QWSWindow::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*/
413Qt::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*/
423QRegion QWSWindow::dirtyOnScreen() const
424{
425 return d->dirtyOnScreen;
426}
427
428void 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*/
449void 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*/
463void 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*/
477void 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*/
491void 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*/
506void 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
516void QWSWindow::setName(const QString &n)
517{
518 rgnName = n;
519}
520
521/*!
522 \internal
523 Sets the window's caption to \a c.
524*/
525void QWSWindow::setCaption(const QString &c)
526{
527 rgnCaption = c;
528}
529
530
531static int global_focus_time_counter=100;
532
533void 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
545void 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*/
559QWSWindow::~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*/
595QRegion QWSWindow::allocatedRegion() const
596{
597 return d->allocatedRegion;
598}
599
600#ifdef QT_QWS_CLIENTBLIT
601QRegion QWSWindow::directPaintRegion() const
602{
603 return d->directPaintRegion;
604}
605
606inline 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*/
619QRegion QWSWindow::paintedRegion() const
620{
621 return (d->painted ? d->allocatedRegion : QRegion());
622}
623
624inline void QWSWindow::setAllocatedRegion(const QRegion &region)
625{
626 d->allocatedRegion = region;
627}
628
629#ifndef QT_NO_QWSEMBEDWIDGET
630inline void QWSWindow::startEmbed(QWSWindow *w)
631{
632 d->embedded.append(w);
633 w->d->embedder = this;
634}
635
636inline 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
650class QWSClientPrivate : public QObjectPrivate
651{
652 Q_DECLARE_PUBLIC(QWSClient)
653
654public:
655 QWSClientPrivate();
656 ~QWSClientPrivate();
657
658 void setLockId(int id);
659 void unlockCommunication();
660
661private:
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
671QWSClientPrivate::QWSClientPrivate()
672{
673#ifndef QT_NO_QWS_MULTIPROCESS
674 clientLock = 0;
675 shutdown = false;
676 numUnbufferedSurfaces = 0;
677#endif
678}
679
680QWSClientPrivate::~QWSClientPrivate()
681{
682#ifndef QT_NO_QWS_MULTIPROCESS
683 delete clientLock;
684#endif
685}
686
687void 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
696void 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
739QWSClient::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*/
766QWSClient::~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
776void QWSClient::removeUnbufferedSurface()
777{
778 Q_D(QWSClient);
779 --d->numUnbufferedSurfaces;
780}
781
782void QWSClient::addUnbufferedSurface()
783{
784 Q_D(QWSClient);
785 ++d->numUnbufferedSurfaces;
786}
787#endif // QT_NO_QWS_MULTIPROCESS
788
789/*!
790 \internal
791*/
792void QWSClient::setIdentity(const QString& i)
793{
794 id = i;
795}
796
797void QWSClient::closeHandler()
798{
799 isClosed = true;
800 emit connectionClosed();
801}
802
803void 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*/
817int QWSClient::socket() const
818{
819 return socketDescriptor;
820}
821
822/*!
823 \internal
824*/
825void 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*/
844void 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
867extern int qt_servershmid;
868
869/*!
870 \internal
871*/
872void 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*/
887void 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
899void 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*/
911void 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*/
925void QWSClient::sendSelectionClearEvent(int windowid)
926{
927 QWSSelectionClearEvent event;
928 event.simpleData.window = windowid;
929 sendEvent(&event);
930}
931
932/*!
933 \internal
934*/
935void 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*/
949void QWSClient::sendEmbedEvent(int windowid, QWSEmbedEvent::Type type,
950 const QRegion &region)
951{
952 QWSEmbedEvent event;
953 event.setData(windowid, type, region);
954 sendEvent(&event);
955}
956#endif // QT_NO_QWSEMBEDWIDGET
957
958/*!
959 \fn void QWSClient::connectionClosed()
960 \internal
961*/
962
963/*!
964 \fn void QWSClient::readyRead();
965 \internal
966*/
967
968/*!
969 \fn int QWSClient::clientId () const
970
971 Returns an integer uniquely identfying this client.
972*/
973
974/*!
975 \fn QString QWSClient::identity () const
976
977 Returns the name of this client's running application.
978*/
979/*********************************************************************
980 *
981 * Class: QWSServer
982 *
983 *********************************************************************/
984
985/*!
986 \class QWSServer
987 \brief The QWSServer class encapsulates a server process in Qt for Embedded Linux.
988
989 \ingroup qws
990
991 When you run a \l{Qt for Embedded Linux} application, it either runs as a
992 server or connects to an existing server. The server and client
993 processes have different responsibilities: The client process
994 performs all application specific operations. The server process
995 is responsible for managing the clients as well as taking care of
996 the pointer handling, character input, and screen output. In
997 addition, the server provides functionality to handle input
998 methods.
999
1000 In \l{Qt for Embedded Linux}, all system generated events are passed to the
1001 server application which then propagates the event to the
1002 appropriate client. See the \l{Qt for Embedded Linux Architecture}
1003 documentation for details.
1004
1005 Note that this class is instantiated by QApplication for
1006 \l{Qt for Embedded Linux} server processes; you should never construct this
1007 class yourself. Use the instance() function to retrieve a pointer
1008 to the server object.
1009
1010 Note that the static functions of the QWSServer class can only be
1011 used in the server process.
1012
1013 \tableofcontents
1014
1015 \section1 Client Administration
1016
1017 As applications add and remove windows, the server process
1018 maintains information about each window. In \l{Qt for Embedded Linux},
1019 top-level windows are encapsulated as QWSWindow objects. Each
1020 window can tell which client that owns it through its
1021 QWSWindow::client() function. Use the clientWindows() function to
1022 retrieve a list of the current top-level windows. Given a
1023 particular position on the display, the window containing it can
1024 be retrieved using the windowAt() function.
1025
1026 QWSServer also provides the windowEvent() signal which is emitted
1027 whenever something happens to a top level window; the WindowEvent
1028 enum describes the various types of events that the signal
1029 recognizes. In addition, the server class provides the
1030 markedText() signal which is emitted whenever some text has been
1031 selected in any of the windows, passing the selection as
1032 parameter.
1033
1034 The QCopChannel class and the QCOP communication protocol enable
1035 transfer of messages between clients. QWSServer provides the
1036 newChannel() and removedChannel() signals that is emitted whenever
1037 a new QCopChannel object is created or destroyed, respectively.
1038
1039 See also: QWSWindow, QWSClient and QCopChannel.
1040
1041
1042 \section1 Mouse Handling
1043
1044 The mouse driver (represented by an instance of the
1045 QWSMouseHandler class) is loaded by the server application when it
1046 starts running, using Qt's \l {How to Create Qt Plugins}{plugin
1047 system}. A mouse driver receives mouse events from the device and
1048 encapsulates each event with an instance of the QWSEvent class
1049 which it then passes to the server.
1050
1051 The openMouse() function opens the mouse devices specified by the
1052 QWS_MOUSE_PROTO environment variable, and the setMouseHandler()
1053 functions sets the primary mouse driver. Alternatively, the static
1054 setDefaultMouse() function provides means of specifying the mouse
1055 driver to use if the QWS_MOUSE_PROTO variable is not defined (note
1056 that the default is otherwise platform dependent). The primary
1057 mouse driver can be retrieved using the static mouseHandler()
1058 function. Use the closeMouse() function to delete the mouse
1059 drivers.
1060
1061 In addition, the QWSServer class can control the flow of mouse
1062 input using the suspendMouse() and resumeMouse() functions.
1063
1064 See also: QWSMouseHandler and \l{Qt for Embedded Linux Pointer Handling}.
1065
1066 \section1 Keyboard Handling
1067
1068 The keyboard driver (represented by an instance of the
1069 QWSKeyboardHandler class) is loaded by the server application when
1070 it starts running, using Qt's \l {How to Create Qt Plugins}{plugin
1071 system}. A keyboard driver receives keyboard events from the
1072 device and encapsulates each event with an instance of the
1073 QWSEvent class which it then passes to the server.
1074
1075 The openKeyboard() function opens the keyboard devices specified
1076 by the QWS_KEYBOARD environment variable, and the
1077 setKeyboardHandler() functions sets the primary keyboard
1078 driver. Alternatively, the static setDefaultKeyboard() function
1079 provides means of specifying the keyboard driver to use if the
1080 QWS_KEYBOARD variable is not defined (note again that the default
1081 is otherwise platform dependent). The primary keyboard driver can
1082 be retrieved using the static keyboardHandler() function. Use the
1083 closeKeyboard() function to delete the keyboard drivers.
1084
1085 In addition, the QWSServer class can handle key events from both
1086 physical and virtual keyboards using the processKeyEvent() and
1087 sendKeyEvent() functions, respectively. Use the
1088 addKeyboardFilter() function to filter the key events from
1089 physical keyboard drivers, the most recently added filter can be
1090 removed and deleted using the removeKeyboardFilter() function.
1091
1092 See also: QWSKeyboardHandler and \l{Qt for Embedded Linux Character Input}.
1093
1094 \section1 Display Handling
1095
1096 When a screen update is required, the server runs through all the
1097 top-level windows that intersect with the region that is about to
1098 be updated, and ensures that the associated clients have updated
1099 their memory buffer. Then the server uses the screen driver
1100 (represented by an instance of the QScreen class) to copy the
1101 content of the memory to the screen.
1102
1103 In addition, the QWSServer class provides some means of managing
1104 the screen output: Use the refresh() function to refresh the
1105 entire display, or alternatively a specified region of it. The
1106 enablePainting() function can be used to disable (and enable)
1107 painting onto the screen. QWSServer also provide the
1108 setMaxWindowRect() function restricting the area of the screen
1109 which \l{Qt for Embedded Linux} applications will consider to be the
1110 maximum area to use for windows. To set the brush used as the
1111 background in the absence of obscuring windows, QWSServer provides
1112 the static setBackground() function. The corresponding
1113 backgroundBrush() function returns the currently set brush.
1114
1115 QWSServer also controls the screen saver: Use the setScreenSaver()
1116 to install a custom screen saver derived from the QWSScreenSaver
1117 class. Once installed, the screensaver can be activated using the
1118 screenSaverActivate() function, and the screenSaverActive()
1119 function returns its current status. Use the
1120 setScreenSaverInterval() function to specify the timeout interval.
1121 \l{Qt for Embedded Linux} also supports multilevel screen saving, use the
1122 setScreenSaverIntervals() function to specify the various levels
1123 and their timeout intervals.
1124
1125 Finally, the QWSServer class controls the cursor's appearance,
1126 i.e., use the setCursorVisible() function to hide or show the
1127 cursor, and the isCursorVisible() function to determine whether
1128 the cursor is visible on the display or not.
1129
1130 See also: QScreen and \l{Qt for Embedded Linux Display Management}.
1131
1132 \section1 Input Method Handling
1133
1134 Whenever the server receives an event, it queries its stack of
1135 top-level windows to find the window containing the event's
1136 position (each window can identify the client application that
1137 created it). Then the server forwards the event to the appropriate
1138 client. If an input method is installed, it is used as a filter
1139 between the server and the client application.
1140
1141 Derive from the QWSInputMethod class to create custom input
1142 methods, and use the server's setCurrentInputMethod() function to
1143 install it. Use the sendIMEvent() and sendIMQuery() functions to
1144 send input method events and queries.
1145
1146 QWSServer provides the IMMouse enum describing the various mouse
1147 events recognized by the QWSInputMethod::mouseHandler()
1148 function. The latter function allows subclasses of QWSInputMethod
1149 to handle mouse events within the preedit text.
1150
1151 \sa QWSInputMethod
1152*/
1153
1154/*!
1155 \enum QWSServer::IMState
1156 \obsolete
1157
1158 This enum describes the various states of an input method.
1159
1160 \value IMCompose Composing.
1161 \value IMStart Equivalent to IMCompose.
1162 \value IMEnd Finished composing.
1163
1164 \sa QWSInputMethod::sendIMEvent()
1165*/
1166
1167/*!
1168 \enum QWSServer::IMMouse
1169
1170 This enum describes the various types of mouse events recognized
1171 by the QWSInputMethod::mouseHandler() function.
1172
1173 \value MousePress An event generated by pressing a mouse button.
1174 \value MouseRelease An event generated by relasing a mouse button.
1175 \value MouseMove An event generated by moving the mouse cursor.
1176 \value MouseOutside This value is only reserved, i.e., it is not used in
1177 current implementations.
1178
1179 \sa QWSInputMethod, setCurrentInputMethod()
1180*/
1181
1182/*!
1183 \enum QWSServer::ServerFlags
1184 \internal
1185
1186 This enum is used to pass various options to the window system
1187 server.
1188
1189 \value DisableKeyboard Ignore all keyboard input.
1190 \value DisableMouse Ignore all mouse input.
1191*/
1192
1193/*!
1194 \enum QWSServer::WindowEvent
1195
1196 This enum specifies the various events that can occur in a
1197 top-level window.
1198
1199 \value Create A new window has been created (by the QWidget constructor).
1200 \value Destroy The window has been closed and deleted (by the QWidget destructor).
1201 \value Hide The window has been hidden using the QWidget::hide() function.
1202 \value Show The window has been shown using the QWidget::show() function or similar.
1203 \value Raise The window has been raised to the top of the desktop.
1204 \value Lower The window has been lowered.
1205 \value Geometry The window has changed size or position.
1206 \value Active The window has become the active window (i.e., it has keyboard focus).
1207 \value Name The window has been named.
1208
1209 \sa windowEvent()
1210*/
1211
1212/*!
1213 \fn void QWSServer::markedText(const QString &selection)
1214
1215 This signal is emitted whenever some text is selected in any of
1216 the running applications, passing the selected text in the \a
1217 selection parameter.
1218
1219 \sa windowEvent()
1220*/
1221
1222/*!
1223 \fn const QList<QWSWindow*> &QWSServer::clientWindows()
1224
1225 Returns the list of current top-level windows.
1226
1227 Note that the collection of top-level windows changes as
1228 applications add and remove widgets so it should not be stored for
1229 future use. The windows are sorted in stacking order from top-most
1230 to bottom-most.
1231
1232 Use the QWSWindow::client() function to retrieve the client
1233 application that owns a given window.
1234
1235 \sa windowAt(), instance()
1236*/
1237
1238/*!
1239 \fn void QWSServer::newChannel(const QString& channel)
1240
1241 This signal is emitted whenever a new QCopChannel object is
1242 created, passing the channel's name in the \a channel parameter.
1243
1244 \sa removedChannel()
1245*/
1246
1247/*!
1248 \fn void QWSServer::removedChannel(const QString& channel)
1249
1250 This signal is emitted immediately after the given the QCopChannel
1251 object specified by \a channel, is destroyed.
1252
1253 Note that a channel is not destroyed until all its listeners have
1254 been unregistered.
1255
1256 \sa newChannel()
1257*/
1258
1259/*!
1260 \fn QWSServer::QWSServer(int flags, QObject *parent)
1261 \internal
1262
1263 Construct a QWSServer object with the given \a parent. The \a
1264 flags are used for keyboard and mouse settings.
1265
1266 \warning This class is instantiated by QApplication for
1267 \l{Qt for Embedded Linux} server processes. You should never construct
1268 this class yourself.
1269
1270 \sa {Running Applications}
1271*/
1272
1273/*!
1274 \fn static QWSServer* QWSServer::instance()
1275 \since 4.2
1276
1277 Returns a pointer to the server instance.
1278
1279 Note that the pointer will be 0 if the application is not the
1280 server, i.e., if the QApplication::type() function doesn't return
1281 QApplication::GuiServer.
1282
1283 \sa clientWindows(), windowAt()
1284*/
1285
1286struct QWSCommandStruct
1287{
1288 QWSCommandStruct(QWSCommand *c, QWSClient *cl) :command(c),client(cl){}
1289 ~QWSCommandStruct() { delete command; }
1290
1291 QWSCommand *command;
1292 QWSClient *client;
1293
1294};
1295
1296QWSServer::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*/
1314QWSServer::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
1325static void ignoreSignal(int) {} // Used to eat SIGPIPE signals below
1326#endif
1327
1328bool 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
1363void 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*/
1457QWSServer::~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 */
1469void 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
1480const QList<QWSWindow*> &QWSServer::clientWindows()
1481{
1482 Q_D(QWSServer);
1483 return d->windows;
1484}
1485
1486/*!
1487 \internal
1488*/
1489void 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*/
1507void QWSServerPrivate::releaseKeyboard(QWSWindow* w)
1508{
1509 if (keyboardGrabber == w) {
1510 keyboardGrabber = 0;
1511 keyboardGrabbing = false;
1512 }
1513}
1514
1515void 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*/
1531void 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*/
1597void 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
1690void QWSServerPrivate::_q_deleteWindowsLater()
1691{
1692 qDeleteAll(deletedWindows);
1693 deletedWindows.clear();
1694}
1695
1696#endif //QT_NO_QWS_MULTIPROCESS
1697
1698void 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
1711void 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
1727static 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
1743void 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
1790void 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*/
1804QWSCommand* 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*/
1857void QWSServer::processEventQueue()
1858{
1859 if (qwsServerPrivate)
1860 qwsServerPrivate->doClient(qwsServerPrivate->clientMap.value(-1));
1861}
1862
1863
1864#ifndef QT_NO_QWS_MULTIPROCESS
1865void 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
1894void 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
2035void QWSServerPrivate::showCursor()
2036{
2037#ifndef QT_NO_QWS_CURSOR
2038 if (qt_screencursor)
2039 qt_screencursor->show();
2040#endif
2041}
2042
2043void 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*/
2060void 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*/
2104void 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*/
2117void 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*/
2134void 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*/
2157void 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*/
2177void 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*/
2194void QWSServer::setDefaultKeyboard(const char *k)
2195{
2196 *defaultKeyboard() = QString::fromAscii(k);
2197}
2198
2199#ifndef QT_NO_QWS_CURSOR
2200static bool prevWin;
2201#endif
2202
2203
2204extern 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*/
2216void 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
2270void 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*/
2376QWSMouseHandler *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*/
2392const 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*/
2413void 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*/
2426QList<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*/
2443void 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*/
2485QWSWindow *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
2497static 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*/
2531void 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
2550void QWSServerPrivate::sendKeyEventUnfiltered(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
2551 bool isPress, bool autoRepeat)
2552{
2553
2554 QWSKeyEvent event;
2555 QWSWindow *win = keyboardGrabber ? keyboardGrabber :
2556 qwsServerPrivate->focusw;
2557
2558 event.simpleData.window = win ? win->winId() : 0;
2559
2560 event.simpleData.unicode =
2561#ifndef QT_NO_QWS_KEYBOARD
2562 unicode < 0 ? keyUnicode(keycode) :
2563#endif
2564 unicode;
2565 event.simpleData.keycode = keycode;
2566 event.simpleData.modifiers = modifiers;
2567 event.simpleData.is_press = isPress;
2568 event.simpleData.is_auto_repeat = autoRepeat;
2569
2570 QWSClient *serverClient = qwsServerPrivate->clientMap.value(-1);
2571 QWSClient *winClient = win ? win->client() : 0;
2572 if (serverClient)
2573 serverClient->sendEvent(&event);
2574 if (winClient && winClient != serverClient)
2575 winClient->sendEvent(&event);
2576}
2577
2578/*!
2579 \internal
2580*/
2581void QWSServer::beginDisplayReconfigure()
2582{
2583 qwsServer->enablePainting(false);
2584#ifndef QT_NO_QWS_CURSOR
2585 if (qt_screencursor)
2586 qt_screencursor->hide();
2587#endif
2588 QWSDisplay::grab(true);
2589 qt_screen->disconnect();
2590}
2591
2592/*!
2593 \internal
2594*/
2595void QWSServer::endDisplayReconfigure()
2596{
2597 qt_screen->connect(QString());
2598 qwsServerPrivate->swidth = qt_screen->deviceWidth();
2599 qwsServerPrivate->sheight = qt_screen->deviceHeight();
2600
2601 QWSDisplay::ungrab();
2602#ifndef QT_NO_QWS_CURSOR
2603 if (qt_screencursor)
2604 qt_screencursor->show();
2605#endif
2606 QApplicationPrivate *ap = QApplicationPrivate::instance();
2607 ap->setMaxWindowRect(qt_screen, 0,
2608 QRect(0, 0, qt_screen->width(), qt_screen->height()));
2609 QSize olds = qApp->desktop()->size();
2610 qApp->desktop()->resize(qt_screen->width(), qt_screen->height());
2611 qApp->postEvent(qApp->desktop(), new QResizeEvent(qApp->desktop()->size(), olds));
2612 qwsServer->enablePainting(true);
2613 qwsServer->refresh();
2614 qDebug("Desktop size: %dx%d", qApp->desktop()->width(), qApp->desktop()->height());
2615}
2616
2617void QWSServerPrivate::resetEngine()
2618{
2619#ifndef QT_NO_QWS_CURSOR
2620 if (!qt_screencursor)
2621 return;
2622 qt_screencursor->hide();
2623 qt_screencursor->show();
2624#endif
2625}
2626
2627
2628#ifndef QT_NO_QWS_CURSOR
2629/*!
2630 \fn void QWSServer::setCursorVisible(bool visible)
2631
2632 Shows the cursor if \a visible is true: otherwise the cursor is
2633 hidden.
2634
2635 Note that this function can only be used in the server process.
2636
2637 \sa isCursorVisible()
2638*/
2639void QWSServer::setCursorVisible(bool vis)
2640{
2641 if (qwsServerPrivate && qwsServerPrivate->haveviscurs != vis) {
2642 QWSCursor* c = qwsServerPrivate->cursor;
2643 qwsServerPrivate->setCursor(QWSCursor::systemCursor(Qt::BlankCursor));
2644 qwsServerPrivate->haveviscurs = vis;
2645 qwsServerPrivate->setCursor(c);
2646 }
2647}
2648
2649/*!
2650 Returns true if the cursor is visible; otherwise returns false.
2651
2652 Note that this function can only be used in the server process.
2653
2654 \sa setCursorVisible()
2655*/
2656bool QWSServer::isCursorVisible()
2657{
2658 return qwsServerPrivate ? qwsServerPrivate->haveviscurs : true;
2659}
2660#endif
2661
2662#ifndef QT_NO_QWS_INPUTMETHODS
2663
2664
2665/*!
2666 \fn void QWSServer::sendIMEvent(const QInputMethodEvent *event)
2667
2668 Sends the given input method \a event.
2669
2670 The \c QInputMethodEvent class is derived from QWSEvent, i.e., it
2671 is a QWSEvent object of the QWSEvent::IMEvent type.
2672
2673 If there is a window actively composing the preedit string, the
2674 event is sent to that window. Otherwise, the event is sent to the
2675 window currently in focus.
2676
2677 \sa sendIMQuery(), QWSInputMethod::sendEvent()
2678*/
2679void QWSServer::sendIMEvent(const QInputMethodEvent *ime)
2680{
2681 QWSIMEvent event;
2682
2683 QWSWindow *win = keyboardGrabber ? keyboardGrabber :
2684 qwsServerPrivate->focusw;
2685
2686 //if currently composing then event must go to the composing window
2687
2688 if (current_IM_composing_win)
2689 win = current_IM_composing_win;
2690
2691 event.simpleData.window = win ? win->winId() : 0;
2692 event.simpleData.replaceFrom = ime->replacementStart();;
2693 event.simpleData.replaceLength = ime->replacementLength();
2694
2695 QBuffer buffer;
2696 buffer.open(QIODevice::WriteOnly);
2697 QDataStream out(&buffer);
2698
2699 out << ime->preeditString();
2700 out << ime->commitString();
2701
2702 const QList<QInputMethodEvent::Attribute> &attributes = ime->attributes();
2703 for (int i = 0; i < attributes.count(); ++i) {
2704 const QInputMethodEvent::Attribute &a = attributes.at(i);
2705 out << a.type << a.start << a.length << a.value;
2706 }
2707 event.setData(buffer.data(), buffer.size());
2708 QWSClient *serverClient = qwsServerPrivate->clientMap.value(-1);
2709 if (serverClient)
2710 serverClient->sendEvent(&event);
2711 if (win && win->client() && win->client() != serverClient)
2712 win->client()->sendEvent(&event);
2713
2714 current_IM_composing_win = ime->preeditString().isEmpty() ? 0 : win;
2715 current_IM_winId = win ? win->winId() : 0;
2716}
2717
2718
2719/*!
2720 Sends an input method query for the given \a property.
2721
2722 To receive responses to input method queries, the virtual
2723 QWSInputMethod::queryResponse() function must be reimplemented in
2724 a QWSInputMethod subclass that is activated using the
2725 setCurrentInputMethod() function.
2726
2727 \sa sendIMEvent(), setCurrentInputMethod()
2728*/
2729void QWSServer::sendIMQuery(int property)
2730{
2731 QWSIMQueryEvent event;
2732
2733 QWSWindow *win = keyboardGrabber ? keyboardGrabber :
2734 qwsServerPrivate->focusw;
2735 if (current_IM_composing_win)
2736 win = current_IM_composing_win;
2737
2738 event.simpleData.window = win ? win->winId() : 0;
2739 event.simpleData.property = property;
2740 if (win && win->client())
2741 win->client()->sendEvent(&event);
2742}
2743
2744
2745
2746/*!
2747 \fn void QWSServer::setCurrentInputMethod(QWSInputMethod *method)
2748
2749 Sets the current input method to be the given \a method.
2750
2751 Note that this function can only be used in the server process.
2752
2753 \sa sendIMQuery(), sendIMEvent()
2754*/
2755void QWSServer::setCurrentInputMethod(QWSInputMethod *im)
2756{
2757 if (current_IM)
2758 current_IM->reset(); //??? send an update event instead ?
2759 current_IM = im;
2760}
2761
2762/*!
2763 \fn static void QWSServer::resetInputMethod()
2764
2765 \internal
2766*/
2767
2768#endif //QT_NO_QWS_INPUTMETHODS
2769
2770#ifndef QT_NO_QWS_PROPERTIES
2771/*!
2772 \internal
2773*/
2774void QWSServer::sendPropertyNotifyEvent(int property, int state)
2775{
2776 Q_D(QWSServer);
2777 QWSServerPrivate::ClientIterator it = d->clientMap.begin();
2778 while (it != d->clientMap.end()) {
2779 QWSClient *cl = *it;
2780 ++it;
2781 cl->sendPropertyNotifyEvent(property, state);
2782 }
2783}
2784#endif
2785
2786void QWSServerPrivate::invokeIdentify(const QWSIdentifyCommand *cmd, QWSClient *client)
2787{
2788 client->setIdentity(cmd->id);
2789#ifndef QT_NO_QWS_MULTIPROCESS
2790 if (client->clientId() > 0)
2791 client->d_func()->setLockId(cmd->simpleData.idLock);
2792#endif
2793}
2794
2795void QWSServerPrivate::invokeCreate(QWSCreateCommand *cmd, QWSClient *client)
2796{
2797 QWSCreationEvent event;
2798 event.simpleData.objectid = get_object_id(cmd->count);
2799 event.simpleData.count = cmd->count;
2800 client->sendEvent(&event);
2801}
2802
2803void QWSServerPrivate::invokeRegionName(const QWSRegionNameCommand *cmd, QWSClient *client)
2804{
2805 Q_Q(QWSServer);
2806 QWSWindow* changingw = findWindow(cmd->simpleData.windowid, client);
2807 if (changingw && (changingw->name() != cmd->name || changingw->caption() !=cmd->caption)) {
2808 changingw->setName(cmd->name);
2809 changingw->setCaption(cmd->caption);
2810 emit q->windowEvent(changingw, QWSServer::Name);
2811 }
2812}
2813
2814void QWSServerPrivate::invokeRegion(QWSRegionCommand *cmd, QWSClient *client)
2815{
2816#ifdef QWS_REGION_DEBUG
2817 qDebug("QWSServer::invokeRegion %d rects (%d)",
2818 cmd->simpleData.nrectangles, cmd->simpleData.windowid);
2819#endif
2820
2821 QWSWindow* changingw = findWindow(cmd->simpleData.windowid, 0);
2822 if (!changingw) {
2823 qWarning("Invalid window handle %08x",cmd->simpleData.windowid);
2824 return;
2825 }
2826 if (!changingw->forClient(client)) {
2827 qWarning("Disabled: clients changing other client's window region");
2828 return;
2829 }
2830
2831 request_region(cmd->simpleData.windowid, cmd->surfaceKey, cmd->surfaceData,
2832 cmd->region);
2833}
2834
2835void QWSServerPrivate::invokeRegionMove(const QWSRegionMoveCommand *cmd, QWSClient *client)
2836{
2837 Q_Q(QWSServer);
2838 QWSWindow* changingw = findWindow(cmd->simpleData.windowid, 0);
2839 if (!changingw) {
2840 qWarning("invokeRegionMove: Invalid window handle %d",cmd->simpleData.windowid);
2841 return;
2842 }
2843 if (!changingw->forClient(client)) {
2844 qWarning("Disabled: clients changing other client's window region");
2845 return;
2846 }
2847
2848// changingw->setNeedAck(true);
2849 moveWindowRegion(changingw, cmd->simpleData.dx, cmd->simpleData.dy);
2850 emit q->windowEvent(changingw, QWSServer::Geometry);
2851}
2852
2853void QWSServerPrivate::invokeRegionDestroy(const QWSRegionDestroyCommand *cmd, QWSClient *client)
2854{
2855 Q_Q(QWSServer);
2856 QWSWindow* changingw = findWindow(cmd->simpleData.windowid, 0);
2857 if (!changingw) {
2858 qWarning("invokeRegionDestroy: Invalid window handle %d",cmd->simpleData.windowid);
2859 return;
2860 }
2861 if (!changingw->forClient(client)) {
2862 qWarning("Disabled: clients changing other client's window region");
2863 return;
2864 }
2865
2866 setWindowRegion(changingw, QRegion());
2867// rgnMan->remove(changingw->allocationIndex());
2868 for (int i = 0; i < windows.size(); ++i) {
2869 if (windows.at(i) == changingw) {
2870 windows.takeAt(i);
2871 if (i < nReserved)
2872 --nReserved;
2873 break;
2874 }
2875 }
2876
2877 handleWindowClose(changingw);
2878#ifndef QT_NO_QWS_PROPERTIES
2879 propertyManager.removeProperties(changingw->winId());
2880#endif
2881 emit q->windowEvent(changingw, QWSServer::Destroy);
2882 delete changingw;
2883}
2884
2885void QWSServerPrivate::invokeSetFocus(const QWSRequestFocusCommand *cmd, QWSClient *client)
2886{
2887 int winId = cmd->simpleData.windowid;
2888 int gain = cmd->simpleData.flag;
2889
2890 if (gain != 0 && gain != 1) {
2891 qWarning("Only 0(lose) and 1(gain) supported");
2892 return;
2893 }
2894
2895 QWSWindow* changingw = findWindow(winId, 0);
2896 if (!changingw)
2897 return;
2898
2899 if (!changingw->forClient(client)) {
2900 qWarning("Disabled: clients changing other client's focus");
2901 return;
2902 }
2903
2904 setFocus(changingw, gain);
2905}
2906
2907void QWSServerPrivate::setFocus(QWSWindow* changingw, bool gain)
2908{
2909 Q_Q(QWSServer);
2910#ifndef QT_NO_QWS_INPUTMETHODS
2911 /*
2912 This is the logic:
2913 QWSWindow *loser = 0;
2914 if (gain && focusw != changingw)
2915 loser = focusw;
2916 else if (!gain && focusw == changingw)
2917 loser = focusw;
2918 But these five lines can be reduced to one:
2919 */
2920 if (current_IM) {
2921 QWSWindow *loser = (!gain == (focusw==changingw)) ? focusw : 0;
2922 if (loser && loser->winId() == current_IM_winId)
2923 current_IM->updateHandler(QWSInputMethod::FocusOut);
2924 }
2925#endif
2926 if (gain) {
2927 if (focusw != changingw) {
2928 if (focusw) focusw->focus(0);
2929 focusw = changingw;
2930 focusw->focus(1);
2931 emit q->windowEvent(focusw, QWSServer::Active);
2932 }
2933 } else if (focusw == changingw) {
2934 if (changingw->client())
2935 changingw->focus(0);
2936 focusw = 0;
2937 // pass focus to window which most recently got it...
2938 QWSWindow* bestw=0;
2939 for (int i=0; i<windows.size(); ++i) {
2940 QWSWindow* w = windows.at(i);
2941 if (w != changingw && !w->hidden() &&
2942 (!bestw || bestw->focusPriority() < w->focusPriority()))
2943 bestw = w;
2944 }
2945 if (!bestw && changingw->focusPriority()) { // accept focus back?
2946 bestw = changingw; // must be the only one
2947 }
2948 focusw = bestw;
2949 if (focusw) {
2950 focusw->focus(1);
2951 emit q->windowEvent(focusw, QWSServer::Active);
2952 }
2953 }
2954}
2955
2956
2957
2958void QWSServerPrivate::invokeSetOpacity(const QWSSetOpacityCommand *cmd, QWSClient *client)
2959{
2960 Q_UNUSED( client );
2961 int winId = cmd->simpleData.windowid;
2962 int opacity = cmd->simpleData.opacity;
2963
2964 QWSWindow* changingw = findWindow(winId, 0);
2965
2966 if (!changingw) {
2967 qWarning("invokeSetOpacity: Invalid window handle %d", winId);
2968 return;
2969 }
2970
2971 int altitude = windows.indexOf(changingw);
2972 const bool wasOpaque = changingw->isOpaque();
2973 changingw->_opacity = opacity;
2974 if (wasOpaque != changingw->isOpaque())
2975 update_regions();
2976 exposeRegion(changingw->allocatedRegion(), altitude);
2977}
2978
2979void QWSServerPrivate::invokeSetAltitude(const QWSChangeAltitudeCommand *cmd,
2980 QWSClient *client)
2981{
2982 Q_UNUSED(client);
2983
2984 int winId = cmd->simpleData.windowid;
2985 int alt = cmd->simpleData.altitude;
2986 bool fixed = cmd->simpleData.fixed;
2987#if 0
2988 qDebug("QWSServer::invokeSetAltitude winId %d alt %d)", winId, alt);
2989#endif
2990
2991 if (alt < -1 || alt > 1) {
2992 qWarning("QWSServer::invokeSetAltitude Only lower, raise and stays-on-top supported");
2993 return;
2994 }
2995
2996 QWSWindow* changingw = findWindow(winId, 0);
2997 if (!changingw) {
2998 qWarning("invokeSetAltitude: Invalid window handle %d", winId);
2999 return;
3000 }
3001
3002 if (fixed && alt >= 1) {
3003 changingw->onTop = true;
3004 }
3005 if (alt == QWSChangeAltitudeCommand::Lower)
3006 changingw->lower();
3007 else
3008 changingw->raise();
3009
3010// if (!changingw->forClient(client)) {
3011// refresh();
3012// }
3013}
3014
3015#ifndef QT_NO_QWS_PROPERTIES
3016void QWSServerPrivate::invokeAddProperty(QWSAddPropertyCommand *cmd)
3017{
3018 propertyManager.addProperty(cmd->simpleData.windowid, cmd->simpleData.property);
3019}
3020
3021void QWSServerPrivate::invokeSetProperty(QWSSetPropertyCommand *cmd)
3022{
3023 Q_Q(QWSServer);
3024 if (propertyManager.setProperty(cmd->simpleData.windowid,
3025 cmd->simpleData.property,
3026 cmd->simpleData.mode,
3027 cmd->data,
3028 cmd->rawLen)) {
3029 q->sendPropertyNotifyEvent(cmd->simpleData.property,
3030 QWSPropertyNotifyEvent::PropertyNewValue);
3031#ifndef QT_NO_QWS_INPUTMETHODS
3032 if (cmd->simpleData.property == QT_QWS_PROPERTY_MARKEDTEXT) {
3033 QString s((const QChar*)cmd->data, cmd->rawLen/2);
3034 emit q->markedText(s);
3035 }
3036#endif
3037 }
3038}
3039
3040void QWSServerPrivate::invokeRemoveProperty(QWSRemovePropertyCommand *cmd)
3041{
3042 Q_Q(QWSServer);
3043 if (propertyManager.removeProperty(cmd->simpleData.windowid,
3044 cmd->simpleData.property)) {
3045 q->sendPropertyNotifyEvent(cmd->simpleData.property,
3046 QWSPropertyNotifyEvent::PropertyDeleted);
3047 }
3048}
3049
3050
3051bool QWSServerPrivate:: get_property(int winId, int property, const char *&data, int &len)
3052{
3053 return propertyManager.getProperty(winId, property, data, len);
3054}
3055
3056
3057void QWSServerPrivate::invokeGetProperty(QWSGetPropertyCommand *cmd, QWSClient *client)
3058{
3059 const char *data;
3060 int len;
3061
3062 if (propertyManager.getProperty(cmd->simpleData.windowid,
3063 cmd->simpleData.property,
3064 data, len)) {
3065 client->sendPropertyReplyEvent(cmd->simpleData.property, len, data);
3066 } else {
3067 client->sendPropertyReplyEvent(cmd->simpleData.property, -1, 0);
3068 }
3069}
3070#endif //QT_NO_QWS_PROPERTIES
3071
3072void QWSServerPrivate::invokeSetSelectionOwner(QWSSetSelectionOwnerCommand *cmd)
3073{
3074 qDebug("QWSServer::invokeSetSelectionOwner");
3075
3076 SelectionOwner so;
3077 so.windowid = cmd->simpleData.windowid;
3078 so.time.set(cmd->simpleData.hour, cmd->simpleData.minute,
3079 cmd->simpleData.sec, cmd->simpleData.ms);
3080
3081 if (selectionOwner.windowid != -1) {
3082 QWSWindow *win = findWindow(selectionOwner.windowid, 0);
3083 if (win)
3084 win->client()->sendSelectionClearEvent(selectionOwner.windowid);
3085 else
3086 qDebug("couldn't find window %d", selectionOwner.windowid);
3087 }
3088
3089 selectionOwner = so;
3090}
3091
3092void QWSServerPrivate::invokeConvertSelection(QWSConvertSelectionCommand *cmd)
3093{
3094 qDebug("QWSServer::invokeConvertSelection");
3095
3096 if (selectionOwner.windowid != -1) {
3097 QWSWindow *win = findWindow(selectionOwner.windowid, 0);
3098 if (win)
3099 win->client()->sendSelectionRequestEvent(cmd, selectionOwner.windowid);
3100 else
3101 qDebug("couldn't find window %d", selectionOwner.windowid);
3102 }
3103}
3104
3105#ifndef QT_NO_QWS_CURSOR
3106void QWSServerPrivate::invokeDefineCursor(QWSDefineCursorCommand *cmd, QWSClient *client)
3107{
3108 if (cmd->simpleData.height > 64 || cmd->simpleData.width > 64) {
3109 qDebug("Cannot define cursor size > 64x64");
3110 return;
3111 }
3112
3113 delete client->cursors.take(cmd->simpleData.id);
3114
3115 int dataLen = cmd->simpleData.height * ((cmd->simpleData.width+7) / 8);
3116
3117 if (dataLen > 0 && cmd->data) {
3118 QWSCursor *curs = new QWSCursor(cmd->data, cmd->data + dataLen,
3119 cmd->simpleData.width, cmd->simpleData.height,
3120 cmd->simpleData.hotX, cmd->simpleData.hotY);
3121 client->cursors.insert(cmd->simpleData.id, curs);
3122 }
3123}
3124
3125void QWSServerPrivate::invokeSelectCursor(QWSSelectCursorCommand *cmd, QWSClient *client)
3126{
3127 int id = cmd->simpleData.id;
3128 QWSCursor *curs = 0;
3129 if (id <= Qt::LastCursor) {
3130 curs = QWSCursor::systemCursor(id);
3131 }
3132 else {
3133 QWSCursorMap cursMap = client->cursors;
3134 QWSCursorMap::Iterator it = cursMap.find(id);
3135 if (it != cursMap.end()) {
3136 curs = it.value();
3137 }
3138 }
3139 if (curs == 0) {
3140 curs = QWSCursor::systemCursor(Qt::ArrowCursor);
3141 }
3142
3143 QWSWindow* win = findWindow(cmd->simpleData.windowid, 0);
3144 if (mouseGrabber) {
3145 // If the mouse is being grabbed, we don't want just anyone to
3146 // be able to change the cursor. We do want the cursor to be set
3147 // correctly once mouse grabbing is stopped though.
3148 if (win != mouseGrabber)
3149 nextCursor = curs;
3150 else
3151 setCursor(curs);
3152 } else if (win && win->allocatedRegion().contains(QWSServer::mousePosition)) { //##################### cursor
3153 // A non-grabbing window can only set the cursor shape if the
3154 // cursor is within its allocated region.
3155 setCursor(curs);
3156 }
3157}
3158
3159void QWSServerPrivate::invokePositionCursor(QWSPositionCursorCommand *cmd, QWSClient *)
3160{
3161 Q_Q(QWSServer);
3162 QPoint newPos(cmd->simpleData.newX, cmd->simpleData.newY);
3163 if (newPos != QWSServer::mousePosition)
3164 q->sendMouseEvent(newPos, qwsServer->d_func()->mouseState);
3165}
3166#endif
3167
3168void QWSServerPrivate::invokeGrabMouse(QWSGrabMouseCommand *cmd, QWSClient *client)
3169{
3170 QWSWindow* win = findWindow(cmd->simpleData.windowid, 0);