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

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 143.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
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 qt-info@nokia.com.
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);
3171 if (!win)
3172 return;
3173
3174 if (cmd->simpleData.grab) {
3175 if (!mouseGrabber || mouseGrabber->client() == client) {
3176 mouseGrabbing = true;
3177 mouseGrabber = win;
3178 }
3179 } else {
3180 releaseMouse(mouseGrabber);
3181 }
3182}
3183
3184void QWSServerPrivate::invokeGrabKeyboard(QWSGrabKeyboardCommand *cmd, QWSClient *client)
3185{
3186 QWSWindow* win = findWindow(cmd->simpleData.windowid, 0);
3187 if (!win)
3188 return;
3189
3190 if (cmd->simpleData.grab) {
3191 if (!keyboardGrabber || (keyboardGrabber->client() == client)) {
3192 keyboardGrabbing = true;
3193 keyboardGrabber = win;
3194 }
3195 } else {
3196 releaseKeyboard(keyboardGrabber);
3197 }
3198}
3199
3200#if !defined(QT_NO_SOUND)
3201void QWSServerPrivate::invokePlaySound(QWSPlaySoundCommand *cmd, QWSClient *)
3202{
3203#if !defined(QT_EXTERNAL_SOUND_SERVER) && !defined(Q_OS_DARWIN)
3204 soundserver->playFile( 1, cmd->filename );
3205#else
3206 Q_UNUSED(cmd);
3207#endif
3208}
3209#endif
3210
3211#ifndef QT_NO_COP
3212void QWSServerPrivate::invokeRegisterChannel(QWSQCopRegisterChannelCommand *cmd,
3213 QWSClient *client)
3214{
3215 // QCopChannel will force us to emit the newChannel signal if this channel
3216 // didn't already exist.
3217 QCopChannel::registerChannel(cmd->channel, client);
3218}
3219
3220void QWSServerPrivate::invokeQCopSend(QWSQCopSendCommand *cmd, QWSClient *client)
3221{
3222 QCopChannel::answer(client, cmd->channel, cmd->message, cmd->data);
3223}
3224
3225#endif
3226
3227#ifndef QT_NO_QWS_INPUTMETHODS
3228void QWSServer::resetInputMethod()
3229{
3230 if (current_IM && qwsServer) {
3231 current_IM->reset();
3232 }
3233}
3234
3235void QWSServerPrivate::invokeIMResponse(const QWSIMResponseCommand *cmd,
3236 QWSClient *)
3237{
3238 if (current_IM)
3239 current_IM->queryResponse(cmd->simpleData.property, cmd->result);
3240}
3241
3242void QWSServerPrivate::invokeIMUpdate(const QWSIMUpdateCommand *cmd,
3243 QWSClient *)
3244{
3245 if (cmd->simpleData.type == QWSInputMethod::FocusIn)
3246 current_IM_winId = cmd->simpleData.windowid;
3247
3248 if (current_IM && (current_IM_winId == cmd->simpleData.windowid || cmd->simpleData.windowid == -1))
3249 current_IM->updateHandler(cmd->simpleData.type);
3250}
3251
3252#endif
3253
3254void QWSServerPrivate::invokeFont(const QWSFontCommand *cmd, QWSClient *client)
3255{
3256 QWSClientPrivate *priv = client->d_func();
3257 if (cmd->simpleData.type == QWSFontCommand::StartedUsingFont) {
3258 referenceFont(priv, cmd->fontName);
3259 } else if (cmd->simpleData.type == QWSFontCommand::StoppedUsingFont) {
3260 dereferenceFont(priv, cmd->fontName);
3261 }
3262}
3263
3264void QWSServerPrivate::invokeRepaintRegion(QWSRepaintRegionCommand * cmd,
3265 QWSClient *)
3266{
3267 QRegion r;
3268 r.setRects(cmd->rectangles,cmd->simpleData.nrectangles);
3269 repaint_region(cmd->simpleData.windowid, cmd->simpleData.windowFlags, cmd->simpleData.opaque, r);
3270}
3271
3272#ifndef QT_NO_QWSEMBEDWIDGET
3273void QWSServerPrivate::invokeEmbed(QWSEmbedCommand *cmd, QWSClient *client)
3274{
3275 // Should find these two windows in a single loop
3276 QWSWindow *embedder = findWindow(cmd->simpleData.embedder, client);
3277 QWSWindow *embedded = findWindow(cmd->simpleData.embedded);
3278
3279 if (!embedder) {
3280 qWarning("QWSServer: Embed command from window %i failed: No such id.",
3281 static_cast<int>(cmd->simpleData.embedder));
3282 return;
3283 }
3284
3285 if (!embedded) {
3286 qWarning("QWSServer: Embed command on window %i failed: No such id.",
3287 static_cast<int>(cmd->simpleData.embedded));
3288 return;
3289 }
3290
3291 switch (cmd->simpleData.type) {
3292 case QWSEmbedEvent::StartEmbed:
3293 embedder->startEmbed(embedded);
3294 windows.removeAll(embedded);
3295 windows.insert(windows.indexOf(embedder), embedded);
3296 break;
3297 case QWSEmbedEvent::StopEmbed:
3298 embedder->stopEmbed(embedded);
3299 break;
3300 case QWSEmbedEvent::Region:
3301 break;
3302 }
3303
3304 embedded->client()->sendEmbedEvent(embedded->winId(),
3305 cmd->simpleData.type, cmd->region);
3306 const QRegion oldAllocated = embedded->allocatedRegion();
3307 update_regions();
3308 exposeRegion(oldAllocated - embedded->allocatedRegion(),
3309 windows.indexOf(embedded));
3310}
3311#endif // QT_NO_QWSEMBEDWIDGET
3312
3313void QWSServerPrivate::invokeScreenTransform(const QWSScreenTransformCommand *cmd,
3314 QWSClient *client)
3315{
3316 Q_UNUSED(client);
3317
3318 QWSScreenTransformationEvent event;
3319 event.simpleData.screen = cmd->simpleData.screen;
3320 event.simpleData.transformation = cmd->simpleData.transformation;
3321
3322 QMap<int, QWSClient*>::const_iterator it = clientMap.constBegin();
3323 for (; it != clientMap.constEnd(); ++it)
3324 (*it)->sendEvent(&event);
3325}
3326
3327QWSWindow* QWSServerPrivate::newWindow(int id, QWSClient* client)
3328{
3329 Q_Q(QWSServer);
3330 // Make a new window, put it on top.
3331 QWSWindow* w = new QWSWindow(id,client);
3332
3333 // insert after "stays on top" windows
3334 bool added = false;
3335 for (int i = nReserved; i < windows.size(); ++i) {
3336 QWSWindow *win = windows.at(i);
3337 if (!win->onTop) {
3338 windows.insert(i, w);
3339 added = true;
3340 break;
3341 }
3342 }
3343 if (!added)
3344 windows.append(w);
3345 emit q->windowEvent(w, QWSServer::Create);
3346 return w;
3347}
3348
3349QWSWindow* QWSServerPrivate::findWindow(int windowid, QWSClient* client)
3350{
3351 for (int i=0; i<windows.size(); ++i) {
3352 QWSWindow* w = windows.at(i);
3353 if (w->winId() == windowid)
3354 return w;
3355 }
3356 if (client)
3357 return newWindow(windowid,client);
3358 else
3359 return 0;
3360}
3361
3362void QWSServerPrivate::raiseWindow(QWSWindow *changingw, int /*alt*/)
3363{
3364 Q_Q(QWSServer);
3365 if (changingw == windows.first())
3366 return;
3367 QWSWindow::State oldstate = changingw->d->state;
3368 changingw->d->state = QWSWindow::Raising;
3369 // Expose regions previously overlapped by transparent windows
3370 const QRegion bound = changingw->allocatedRegion();
3371 QRegion expose;
3372 int windowPos = 0;
3373
3374 //change position in list:
3375 for (int i = 0; i < windows.size(); ++i) {
3376 QWSWindow *w = windows.at(i);
3377 if (w == changingw) {
3378 windowPos = i;
3379 windows.takeAt(i);
3380 break;
3381 }
3382 if (!w->isOpaque())
3383 expose += (w->allocatedRegion() & bound);
3384 }
3385
3386 bool onTop = changingw->onTop;
3387
3388#ifndef QT_NO_QWSEMBEDWIDGET
3389 // an embedded window is on top if the embedder is on top
3390 QWSWindow *embedder = changingw->d->embedder;
3391 while (!onTop && embedder) {
3392 onTop = embedder->onTop;
3393 embedder = embedder->d->embedder;
3394 }
3395#endif
3396
3397 int newPos = -1;
3398 if (onTop) {
3399 windows.insert(nReserved, changingw);
3400 newPos = nReserved;
3401 } else {
3402 // insert after "stays on top" windows
3403 bool in = false;
3404 for (int i = nReserved; i < windows.size(); ++i) {
3405 QWSWindow *w = windows.at(i);
3406 if (!w->onTop) {
3407 windows.insert(i, changingw);
3408 in = true;
3409 newPos = i;
3410 break;
3411 }
3412 }
3413 if (!in) {
3414 windows.append(changingw);
3415 newPos = windows.size()-1;
3416 }
3417 }
3418
3419 if (windowPos != newPos) {
3420 update_regions();
3421 if (!expose.isEmpty())
3422 exposeRegion(expose, newPos);
3423 }
3424 changingw->d->state = oldstate;
3425 emit q->windowEvent(changingw, QWSServer::Raise);
3426}
3427
3428void QWSServerPrivate::lowerWindow(QWSWindow *changingw, int /*alt*/)
3429{
3430 Q_Q(QWSServer);
3431 if (changingw == windows.last())
3432 return;
3433 QWSWindow::State oldstate = changingw->d->state;
3434 changingw->d->state = QWSWindow::Lowering;
3435
3436 int i = windows.indexOf(changingw);
3437 int newIdx = windows.size()-1;
3438 windows.move(i, newIdx);
3439
3440 const QRegion bound = changingw->allocatedRegion();
3441
3442 update_regions();
3443
3444 // Expose regions previously overlapped by transparent window
3445 if (!changingw->isOpaque()) {
3446 QRegion expose;
3447 for (int j = i; j < windows.size() - 1; ++j)
3448 expose += (windows.at(j)->allocatedRegion() & bound);
3449 if (!expose.isEmpty())
3450 exposeRegion(expose, newIdx);
3451 }
3452
3453 changingw->d->state = oldstate;
3454 emit q->windowEvent(changingw, QWSServer::Lower);
3455}
3456
3457void QWSServerPrivate::update_regions()
3458{
3459 if (disablePainting)
3460 return;
3461
3462 QRegion available = QRect(0, 0, qt_screen->width(), qt_screen->height());
3463 QRegion transparentRegion;
3464
3465 // only really needed if there are unbuffered surfaces...
3466 const bool doLock = (clientMap.size() > 1);
3467 if (doLock)
3468 QWSDisplay::grab(true);
3469
3470 for (int i = 0; i < windows.count(); ++i) {
3471 QWSWindow *w = windows.at(i);
3472 QRegion r = (w->requested_region & available);
3473
3474#ifndef QT_NO_QWSEMBEDWIDGET
3475 // Subtract regions needed for embedded windows
3476 const int n = w->d->embedded.size();
3477 for (int i = 0; i < n; ++i)
3478 r -= w->d->embedded.at(i)->allocatedRegion();
3479
3480 // Limited to the embedder region
3481 if (w->d->embedder)
3482 r &= w->d->embedder->requested_region;
3483#endif // QT_NO_QWSEMBEDWIDGET
3484
3485 QWSWindowSurface *surface = w->windowSurface();
3486 const bool opaque = w->isOpaque()
3487 && (w->d->painted || !surface || !surface->isBuffered());
3488
3489 if (!opaque) {
3490 transparentRegion += r;
3491 } else {
3492 if (surface && (surface->isRegionReserved() || !surface->isBuffered()))
3493 r -= transparentRegion;
3494 available -= r;
3495 }
3496
3497 if (r != w->allocatedRegion()) {
3498 w->setAllocatedRegion(r);
3499 w->client()->sendRegionEvent(w->winId(), r,
3500 QWSRegionEvent::Allocation);
3501 }
3502
3503#ifdef QT_QWS_CLIENTBLIT
3504#ifdef QT_NO_QWS_CURSOR
3505 // This optimization only really works when there isn't a crazy cursor
3506 // wizzing around.
3507 QRegion directPaint = (r - transparentRegion); // in gloal coords
3508 if(directPaint != w->directPaintRegion()) {
3509 w->setDirectPaintRegion(directPaint);
3510 static int id = 0;
3511 surface->setDirectRegion(directPaint, ++id);
3512 w->client()->sendRegionEvent(w->winId(), directPaint,
3513 QWSRegionEvent::DirectPaint, id);
3514 }
3515#endif
3516#endif
3517 }
3518
3519 if (doLock)
3520 QWSDisplay::ungrab();
3521}
3522
3523void QWSServerPrivate::moveWindowRegion(QWSWindow *changingw, int dx, int dy)
3524{
3525 if (!changingw)
3526 return;
3527
3528 QWSWindow::State oldState = changingw->d->state;
3529 changingw->d->state = QWSWindow::Moving;
3530 const QRegion oldRegion(changingw->allocatedRegion());
3531 changingw->requested_region.translate(dx, dy);
3532
3533 // hw: Even if the allocated region doesn't change, the requested region
3534 // region has changed and we need to send region events.
3535 // Resetting the allocated region to force update_regions to send events.
3536 changingw->setAllocatedRegion(QRegion());
3537 update_regions();
3538 const QRegion newRegion(changingw->allocatedRegion());
3539
3540 QWSWindowSurface *surface = changingw->windowSurface();
3541 QRegion expose;
3542 if (surface)
3543 expose = surface->move(QPoint(dx, dy), changingw->allocatedRegion());
3544 else
3545 expose = oldRegion + newRegion;
3546
3547 if (!changingw->d->painted && !expose.isEmpty())
3548 expose = oldRegion - newRegion;
3549
3550 int idx = windows.indexOf(changingw);
3551 exposeRegion(expose, idx);
3552 changingw->d->state = oldState;
3553}
3554
3555/*!
3556 Changes the requested region of window \a changingw to \a r
3557 If \a changingw is 0, the server's reserved region is changed.
3558*/
3559void QWSServerPrivate::setWindowRegion(QWSWindow* changingw, const QRegion &r)
3560{
3561 if (!changingw) {
3562 qWarning("Not implemented in this release");
3563 return;
3564 }
3565
3566 if (changingw->requested_region == r)
3567 return;
3568
3569 const QRegion oldRegion(changingw->allocatedRegion());
3570 changingw->requested_region = r;
3571 update_regions();
3572 const QRegion newRegion(changingw->allocatedRegion());
3573
3574 int idx = windows.indexOf(changingw);
3575 exposeRegion(oldRegion - newRegion, idx);
3576}
3577
3578
3579void QWSServerPrivate::exposeRegion(const QRegion &r, int changing)
3580{
3581 if (disablePainting)
3582 return;
3583
3584 if (r.isEmpty())
3585 return;
3586
3587 static bool initial = true;
3588 if (initial) {
3589 changing = 0;
3590 initial = false;
3591 qt_screen->exposeRegion(qt_screen->region(), changing);
3592 } else {
3593 qt_screen->exposeRegion(r, changing);
3594 }
3595}
3596
3597/*!
3598 Closes all pointer devices (specified by the QWS_MOUSE_PROTO
3599 environment variable) by deleting the associated mouse drivers.
3600
3601 \sa openMouse(), mouseHandler()
3602*/
3603void QWSServer::closeMouse()
3604{
3605 Q_D(QWSServer);
3606 qDeleteAll(d->mousehandlers);
3607 d->mousehandlers.clear();
3608}
3609
3610/*!
3611 Opens the mouse devices specified by the QWS_MOUSE_PROTO
3612 environment variable. Be advised that closeMouse() is called first
3613 to delete all the existing mouse handlers. This behaviour could be
3614 the cause of problems if you were not expecting it.
3615
3616 \sa closeMouse(), mouseHandler()
3617*/
3618void QWSServer::openMouse()
3619{
3620 Q_D(QWSServer);
3621 QString mice = QString::fromLatin1(qgetenv("QWS_MOUSE_PROTO"));
3622#if defined(QT_QWS_CASSIOPEIA)
3623 if (mice.isEmpty())
3624 mice = QLatin1String("TPanel:/dev/tpanel");
3625#endif
3626 if (mice.isEmpty())
3627 mice = *defaultMouse();
3628 closeMouse();
3629 bool needviscurs = true;
3630 if (mice != QLatin1String("None")) {
3631 const QStringList mouse = mice.split(QLatin1Char(' '));
3632 for (int i = mouse.size() - 1; i >= 0; --i) {
3633 QWSMouseHandler *handler = d->newMouseHandler(mouse.at(i));
3634 setMouseHandler(handler);
3635 /* XXX handle mouse cursor visibility sensibly
3636 if (!h->inherits("QCalibratedMouseHandler"))
3637 needviscurs = true;
3638 */
3639 }
3640 }
3641#ifndef QT_NO_QWS_CURSOR
3642 setCursorVisible(needviscurs);
3643#else
3644 Q_UNUSED(needviscurs)
3645#endif
3646}
3647
3648/*!
3649 Suspends pointer handling by deactivating all the mouse drivers
3650 registered by the QWS_MOUSE_PROTO environment variable.
3651
3652
3653 \sa resumeMouse(), QWSMouseHandler::suspend()
3654*/
3655void QWSServer::suspendMouse()
3656{
3657 Q_D(QWSServer);
3658 for (int i=0; i < d->mousehandlers.size(); ++i)
3659 d->mousehandlers.at(i)->suspend();
3660}
3661
3662/*!
3663 Resumes pointer handling by reactivating all the mouse drivers
3664 registered by the QWS_MOUSE_PROTO environment variable.
3665
3666 \sa suspendMouse(), QWSMouseHandler::resume()
3667*/
3668void QWSServer::resumeMouse()
3669{
3670 Q_D(QWSServer);
3671 for (int i=0; i < d->mousehandlers.size(); ++i)
3672 d->mousehandlers.at(i)->resume();
3673}
3674
3675
3676
3677QWSMouseHandler* QWSServerPrivate::newMouseHandler(const QString& spec)
3678{
3679 int c = spec.indexOf(QLatin1Char(':'));
3680 QString mouseProto;
3681 QString mouseDev;
3682 if (c >= 0) {
3683 mouseProto = spec.left(c);
3684 mouseDev = spec.mid(c+1);
3685 } else {
3686 mouseProto = spec;
3687 }
3688
3689 int screen = -1;
3690 const QList<QRegExp> regexps = QList<QRegExp>()
3691 << QRegExp(QLatin1String(":screen=(\\d+)\\b"))
3692 << QRegExp(QLatin1String("\\bscreen=(\\d+):"));
3693 for (int i = 0; i < regexps.size(); ++i) {
3694 QRegExp regexp = regexps.at(i);
3695 if (regexp.indexIn(mouseDev) == -1)
3696 continue;
3697 screen = regexp.cap(1).toInt();
3698 mouseDev.remove(regexp.pos(0), regexp.matchedLength());
3699 break;
3700 }
3701
3702 QWSMouseHandler *handler = 0;
3703 handler = QMouseDriverFactory::create(mouseProto, mouseDev);
3704 if (screen != -1)
3705 handler->setScreen(qt_screen->subScreens().at(screen));
3706
3707 return handler;
3708}
3709
3710#ifndef QT_NO_QWS_KEYBOARD
3711
3712/*!
3713 Closes all the keyboard devices (specified by the QWS_KEYBOARD
3714 environment variable) by deleting the associated keyboard
3715 drivers.
3716
3717 \sa openKeyboard(), keyboardHandler()
3718*/
3719void QWSServer::closeKeyboard()
3720{
3721 Q_D(QWSServer);
3722 qDeleteAll(d->keyboardhandlers);
3723 d->keyboardhandlers.clear();
3724}
3725
3726/*!
3727 Returns the primary keyboard driver.
3728
3729 Note that this function can only be used in the server process.
3730
3731 \sa setKeyboardHandler(), openKeyboard(), closeKeyboard()
3732*/
3733QWSKeyboardHandler* QWSServer::keyboardHandler()
3734{
3735 return qwsServerPrivate->keyboardhandlers.first();
3736}
3737
3738/*!
3739 \fn void QWSServer::setKeyboardHandler(QWSKeyboardHandler* driver)
3740
3741 Sets the primary keyboard driver to be the given \a driver.
3742
3743 \l{Qt for Embedded Linux} provides several ready-made keyboard drivers, and
3744 custom drivers are typically added using Qt's plugin
3745 mechanism. See the \l{Qt for Embedded Linux Character Input} documentation
3746 for details.
3747
3748 Note that this function can only be used in the server process.
3749
3750 \sa keyboardHandler(), setDefaultKeyboard()
3751*/
3752void QWSServer::setKeyboardHandler(QWSKeyboardHandler* kh)
3753{
3754 if (!kh)
3755 return;
3756 qwsServerPrivate->keyboardhandlers.removeAll(kh);
3757 qwsServerPrivate->keyboardhandlers.prepend(kh);
3758}
3759
3760/*!
3761 Opens the keyboard devices specified by the QWS_KEYBOARD
3762 environment variable.
3763
3764 \sa closeKeyboard(), keyboardHandler()
3765*/
3766void QWSServer::openKeyboard()
3767{
3768 QString keyboards = QString::fromLatin1(qgetenv("QWS_KEYBOARD"));
3769#if defined(QT_QWS_CASSIOPEIA)
3770 if (keyboards.isEmpty())
3771 keyboards = QLatin1String("Buttons");
3772#endif
3773 if (keyboards.isEmpty())
3774 keyboards = *defaultKeyboard();
3775
3776 closeKeyboard();
3777 if (keyboards == QLatin1String("None"))
3778 return;
3779
3780 QString device;
3781 QString type;
3782 QStringList keyboard = keyboards.split(QLatin1Char(' '));
3783 for (int i = keyboard.size() - 1; i >= 0; --i) {
3784 const QString spec = keyboard.at(i);
3785 int colon=spec.indexOf(QLatin1Char(':'));
3786 if (colon>=0) {
3787 type = spec.left(colon);
3788 device = spec.mid(colon+1);
3789 } else {
3790 type = spec;
3791 device = QString();
3792 }
3793 QWSKeyboardHandler *handler = QKbdDriverFactory::create(type, device);
3794 setKeyboardHandler(handler);
3795 }
3796}
3797
3798#endif //QT_NO_QWS_KEYBOARD
3799
3800QPoint QWSServer::mousePosition;
3801QBrush *QWSServerPrivate::bgBrush = 0;
3802
3803void QWSServerPrivate::move_region(const QWSRegionMoveCommand *cmd)
3804{
3805 QWSClient *serverClient = clientMap.value(-1);
3806 invokeRegionMove(cmd, serverClient);
3807}
3808
3809void QWSServerPrivate::set_altitude(const QWSChangeAltitudeCommand *cmd)
3810{
3811 QWSClient *serverClient = clientMap.value(-1);
3812 invokeSetAltitude(cmd, serverClient);
3813}
3814
3815void QWSServerPrivate::set_opacity(const QWSSetOpacityCommand *cmd)
3816{
3817 QWSClient *serverClient = clientMap.value(-1);
3818 invokeSetOpacity(cmd, serverClient);
3819}
3820
3821
3822void QWSServerPrivate::request_focus(const QWSRequestFocusCommand *cmd)
3823{
3824 invokeSetFocus(cmd, clientMap.value(-1));
3825}
3826
3827void QWSServerPrivate::set_identity(const QWSIdentifyCommand *cmd)
3828{
3829 invokeIdentify(cmd, clientMap.value(-1));
3830}
3831
3832void QWSServerPrivate::repaint_region(int wid, int windowFlags, bool opaque,
3833 const QRegion &region)
3834{
3835 QWSWindow* changingw = findWindow(wid, 0);
3836 if (!changingw) {
3837 return;
3838 }
3839
3840 const bool isOpaque = changingw->opaque;
3841 const bool wasPainted = changingw->d->painted;
3842 changingw->opaque = opaque;
3843 changingw->d->windowFlags = QFlag(windowFlags);
3844 changingw->d->dirtyOnScreen |= region;
3845 changingw->d->painted = true;
3846 if (isOpaque != opaque || !wasPainted)
3847 update_regions();
3848
3849 int level = windows.indexOf(changingw);
3850 exposeRegion(region, level);
3851 changingw->d->dirtyOnScreen = QRegion();
3852}
3853
3854QRegion QWSServerPrivate::reserve_region(QWSWindow *win, const QRegion &region)
3855{
3856 QRegion r = region;
3857
3858 int oldPos = windows.indexOf(win);
3859 int newPos = oldPos < nReserved ? nReserved - 1 : nReserved;
3860 for (int i = 0; i < nReserved; ++i) {
3861 if (i != oldPos) {
3862 QWSWindow *w = windows.at(i);
3863 r -= w->requested_region;
3864 }
3865 }
3866 windows.move(oldPos, newPos);
3867 nReserved = newPos + 1;
3868
3869 return r;
3870}
3871
3872void QWSServerPrivate::request_region(int wid, const QString &surfaceKey,
3873 const QByteArray &surfaceData,
3874 const QRegion &region)
3875{
3876 QWSWindow *changingw = findWindow(wid, 0);
3877 if (!changingw)
3878 return;
3879
3880 Q_Q(QWSServer);
3881 QWSWindow::State windowState = QWSWindow::NoState;
3882
3883 if (region.isEmpty()) {
3884 windowState = QWSWindow::Hiding;
3885 emit q->windowEvent(changingw, QWSServer::Hide);
3886 }
3887
3888 const bool wasOpaque = changingw->opaque;
3889
3890 changingw->createSurface(surfaceKey, surfaceData);
3891 QWSWindowSurface *surface = changingw->windowSurface();
3892
3893 changingw->opaque = surface->isOpaque();
3894
3895 QRegion r;
3896 if (surface->isRegionReserved())
3897 r = reserve_region(changingw, region);
3898 else
3899 r = region;
3900
3901 if (!region.isEmpty()) {
3902 if (changingw->isVisible())
3903 windowState = QWSWindow::ChangingGeometry;
3904 else
3905 windowState = QWSWindow::Showing;
3906 }
3907 changingw->d->state = windowState;
3908
3909 if (!r.isEmpty() && wasOpaque != changingw->opaque && surface->isBuffered())
3910 changingw->requested_region = QRegion(); // XXX: force update_regions
3911
3912 const QRegion oldAllocated = changingw->allocatedRegion();
3913 setWindowRegion(changingw, r);
3914 if (oldAllocated == changingw->allocatedRegion()) {
3915 // Always send region event to the requesting window even if the
3916 // region didn't change. This is necessary as the client will reset
3917 // the clip region until an event is received.
3918 changingw->client()->sendRegionEvent(wid, changingw->allocatedRegion(),
3919 QWSRegionEvent::Allocation);
3920 }
3921
3922 surface->QWindowSurface::setGeometry(r.boundingRect());
3923
3924 if (windowState == QWSWindow::Showing)
3925 emit q->windowEvent(changingw, QWSServer::Show);
3926 else if (windowState == QWSWindow::ChangingGeometry)
3927 emit q->windowEvent(changingw, QWSServer::Geometry);
3928 if (windowState == QWSWindow::Hiding) {
3929 handleWindowClose(changingw);
3930 changingw->d->state = QWSWindow::Hidden;
3931 changingw->d->painted = false;
3932 } else {
3933 changingw->d->state = QWSWindow::Visible;
3934 }
3935}
3936
3937void QWSServerPrivate::destroy_region(const QWSRegionDestroyCommand *cmd)
3938{
3939 invokeRegionDestroy(cmd, clientMap.value(-1));
3940}
3941
3942void QWSServerPrivate::name_region(const QWSRegionNameCommand *cmd)
3943{
3944 invokeRegionName(cmd, clientMap.value(-1));
3945}
3946
3947#ifndef QT_NO_QWS_INPUTMETHODS
3948void QWSServerPrivate::im_response(const QWSIMResponseCommand *cmd)
3949 {
3950 invokeIMResponse(cmd, clientMap.value(-1));
3951}
3952
3953void QWSServerPrivate::im_update(const QWSIMUpdateCommand *cmd)
3954{
3955 invokeIMUpdate(cmd, clientMap.value(-1));
3956}
3957
3958void QWSServerPrivate::send_im_mouse(const QWSIMMouseCommand *cmd)
3959{
3960 if (current_IM)
3961 current_IM->mouseHandler(cmd->simpleData.index, cmd->simpleData.state);
3962}
3963#endif
3964
3965void QWSServerPrivate::openDisplay()
3966{
3967 qt_init_display();
3968
3969// rgnMan = qt_fbdpy->regionManager();
3970 swidth = qt_screen->deviceWidth();
3971 sheight = qt_screen->deviceHeight();
3972}
3973
3974void QWSServerPrivate::closeDisplay()
3975{
3976 if (qt_screen)
3977 qt_screen->shutdownDevice();
3978}
3979
3980/*!
3981 Returns the brush used as background in the absence of obscuring
3982 windows.
3983
3984 \sa setBackground()
3985*/
3986const QBrush &QWSServer::backgroundBrush() const
3987{
3988 return *QWSServerPrivate::bgBrush;
3989}
3990
3991/*!
3992 Sets the brush used as background in the absence of obscuring
3993 windows, to be the given \a brush.
3994
3995 Note that this function can only be used in the server process.
3996
3997 \sa backgroundBrush()
3998*/
3999void QWSServer::setBackground(const QBrush &brush)
4000{
4001 if (!QWSServerPrivate::bgBrush)
4002 QWSServerPrivate::bgBrush = new QBrush(brush);
4003 else
4004 *QWSServerPrivate::bgBrush = brush;
4005 if (!qwsServer)
4006 return;
4007 qt_screen->exposeRegion(QRect(0,0,qt_screen->width(), qt_screen->height()), 0);
4008}
4009
4010
4011#ifdef QT3_SUPPORT
4012/*!
4013 \fn void QWSServer::setDesktopBackground(const QImage &image)
4014
4015 Sets the image used as background in the absence of obscuring
4016 windows, to be the given \a image.
4017
4018 Use the setBackground() function instead.
4019
4020 \oldcode
4021 QImage image;
4022 setDesktopBackground(image);
4023 \newcode
4024 QImage image;
4025 setBackground(QBrush(image));
4026 \endcode
4027*/
4028void QWSServer::setDesktopBackground(const QImage &img)
4029{
4030 if (img.isNull())
4031 setBackground(Qt::NoBrush);
4032 else
4033 setBackground(QBrush(QPixmap::fromImage(img)));
4034}
4035
4036/*!
4037 \fn void QWSServer::setDesktopBackground(const QColor &color)
4038 \overload
4039
4040 Sets the color used as background in the absence of obscuring
4041 windows, to be the given \a color.
4042
4043 Use the setBackground() function instead.
4044
4045 \oldcode
4046 QColor color;
4047 setDesktopBackground(color);
4048 \newcode
4049 QColor color;
4050 setBackground(QBrush(color));
4051 \endcode
4052*/
4053void QWSServer::setDesktopBackground(const QColor &c)
4054{
4055 setBackground(QBrush(c));
4056}
4057#endif //QT3_SUPPORT
4058
4059/*!
4060 \internal
4061 */
4062void QWSServer::startup(int flags)
4063{
4064 if (qwsServer)
4065 return;
4066 unlink(qws_qtePipeFilename().toLatin1().constData());
4067 (void)new QWSServer(flags);
4068}
4069
4070/*!
4071 \internal
4072*/
4073
4074void QWSServer::closedown()
4075{
4076 QScopedPointer<QWSServer> server(qwsServer);
4077 qwsServer = 0;
4078 QT_TRY {
4079 unlink(qws_qtePipeFilename().toLatin1().constData());
4080 } QT_CATCH(const std::bad_alloc &) {
4081 // ### TODO - what to do when we run out of memory
4082 // when calling toLatin1?
4083 }
4084}
4085
4086void QWSServerPrivate::emergency_cleanup()
4087{
4088#ifndef QT_NO_QWS_KEYBOARD
4089 if (qwsServer)
4090 qwsServer->closeKeyboard();
4091#endif
4092}
4093
4094#ifndef QT_NO_QWS_KEYBOARD
4095static QList<QWSServer::KeyboardFilter*> *keyFilters = 0;
4096
4097/*!
4098 Processes the given key event. The key is identified by its \a
4099 unicode value and the given \a keycode, \a modifiers, \a isPress
4100 and \a autoRepeat parameters.
4101
4102 The \a keycode parameter is the Qt keycode value as defined by the
4103 Qt::Key enum. The \a modifiers is an OR combination of
4104 Qt::KeyboardModifier values, indicating whether \gui
4105 Shift/Alt/Ctrl keys are pressed. The \a isPress parameter is true
4106 if the event is a key press event and \a autoRepeat is true if the
4107 event is caused by an auto-repeat mechanism and not an actual key
4108 press.
4109
4110 This function is typically called internally by keyboard drivers.
4111 Note that this function can only be used in the server process.
4112
4113 \sa sendKeyEvent(), {Qt for Embedded Linux Character Input}
4114*/
4115void QWSServer::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
4116 bool isPress, bool autoRepeat)
4117{
4118 bool block;
4119 // Don't block the POWER or LIGHT keys
4120 if ( keycode == Qt::Key_F34 || keycode == Qt::Key_F35 )
4121 block = false;
4122 else
4123 block = qwsServerPrivate->screensaverblockevent(KEY, qwsServerPrivate->screensaverinterval, isPress);
4124
4125#ifdef EVENT_BLOCK_DEBUG
4126 qDebug() << "processKeyEvent" << unicode << keycode << modifiers << isPress << autoRepeat << (block ? "block" : "pass");
4127#endif
4128
4129 // If we press a key and it's going to be blocked, wake up the screen
4130 if ( block && isPress )
4131 qwsServerPrivate->_q_screenSaverWake();
4132
4133 if ( block )
4134 return;
4135
4136 if (keyFilters) {
4137 for (int i = 0; i < keyFilters->size(); ++i) {
4138 QWSServer::KeyboardFilter *keyFilter = keyFilters->at(i);
4139 if (keyFilter->filter(unicode, keycode, modifiers, isPress, autoRepeat))
4140 return;
4141 }
4142 }
4143 sendKeyEvent(unicode, keycode, modifiers, isPress, autoRepeat);
4144}
4145
4146/*!
4147 \fn void QWSServer::addKeyboardFilter(KeyboardFilter *filter)
4148
4149 Activates the given keyboard \a filter all key events generated by
4150 physical keyboard drivers (i.e., events sent using the
4151 processKeyEvent() function).
4152
4153 Note that the filter is not invoked for keys generated by \e
4154 virtual keyboard drivers (i.e., events sent using the
4155 sendKeyEvent() function).
4156
4157 Note that this function can only be used in the server process.
4158
4159 \sa removeKeyboardFilter()
4160*/
4161void QWSServer::addKeyboardFilter(KeyboardFilter *f)
4162{
4163 if (!keyFilters)
4164 keyFilters = new QList<QWSServer::KeyboardFilter*>;
4165 if (f) {
4166 keyFilters->prepend(f);
4167 }
4168}
4169
4170/*
4171//#######
4172 We should probably obsolete the whole keyboard filter thing since
4173 it's not useful for input methods anyway
4174
4175 We could do removeKeyboardFilter(KeyboardFilter *f), but
4176 the "remove and delete the filter" concept does not match "user
4177 remembers the pointer".
4178*/
4179
4180/*!
4181 Removes and deletes the most recently added filter.
4182
4183 Note that the programmer is responsible for removing each added
4184 keyboard filter.
4185
4186 Note that this function can only be used in the server process.
4187
4188 \sa addKeyboardFilter()
4189*/
4190void QWSServer::removeKeyboardFilter()
4191{
4192 if (!keyFilters || keyFilters->isEmpty())
4193 return;
4194 delete keyFilters->takeAt(0);
4195}
4196#endif // QT_NO_QWS_KEYBOARD
4197
4198/*!
4199 \fn void QWSServer::setScreenSaverIntervals(int* intervals)
4200
4201 Specifies the time \a intervals (in milliseconds) between the
4202 different levels of screen responsiveness.
4203
4204 \l{Qt for Embedded Linux} supports multilevel screen saving, i.e., it is
4205 possible to specify several different levels of screen
4206 responsiveness by implementing the QWSScreenSaver::save()
4207 function. For example, you can choose to first turn off the light
4208 before you fully activate the screensaver. See the QWSScreenSaver
4209 documentation for details.
4210
4211 Note that an interval of 0 milliseconds will turn off the
4212 screensaver, and that the \a intervals array must be 0-terminated.
4213 This function can only be used in the server process.
4214
4215 \sa setScreenSaverInterval(), setScreenSaverBlockLevel()
4216*/
4217void QWSServer::setScreenSaverIntervals(int* ms)
4218{
4219 if (!qwsServerPrivate)
4220 return;
4221
4222 delete [] qwsServerPrivate->screensaverintervals;
4223 if (ms) {
4224 int* t=ms;
4225 int n=0;
4226 while (*t++) n++;
4227 if (n) {
4228 n++; // the 0
4229 qwsServerPrivate->screensaverintervals = new int[n];
4230 memcpy(qwsServerPrivate->screensaverintervals, ms, n*sizeof(int));
4231 } else {
4232 qwsServerPrivate->screensaverintervals = 0;
4233 }
4234 } else {
4235 qwsServerPrivate->screensaverintervals = 0;
4236 }
4237 qwsServerPrivate->screensaverinterval = 0;
4238
4239 qwsServerPrivate->screensavertimer->stop();
4240 qt_screen->blank(false);
4241 qwsServerPrivate->_q_screenSaverWake();
4242}
4243
4244/*!
4245 \fn void QWSServer::setScreenSaverInterval(int milliseconds)
4246
4247 Sets the timeout interval for the screensaver to the specified \a
4248 milliseconds. To turn off the screensaver, set the timout interval
4249 to 0.
4250
4251 Note that this function can only be used in the server process.
4252
4253 \sa setScreenSaverIntervals(), setScreenSaverBlockLevel()
4254*/
4255void QWSServer::setScreenSaverInterval(int ms)
4256{
4257 int v[2];
4258 v[0] = ms;
4259 v[1] = 0;
4260 setScreenSaverIntervals(v);
4261}
4262
4263/*!
4264 Block the key or mouse event that wakes the system from level \a eventBlockLevel or higher.
4265 To completely disable event blocking (the default behavior), set \a eventBlockLevel to -1.
4266
4267 The algorithm blocks the "down", "up" as well as any "repeat" events for the same key
4268 but will not block other key events after the initial "down" event. For mouse events, the
4269 algorithm blocks all mouse events until an event with no buttons pressed is received.
4270
4271 There are 2 keys that are never blocked, Qt::Key_F34 (POWER) and Qt::Key_F35 (LIGHT).
4272
4273 Example usage:
4274
4275 \snippet doc/src/snippets/code/src_gui_embedded_qwindowsystem_qws.cpp 0
4276
4277 Note that this function can only be used in the server process.
4278
4279 \sa setScreenSaverIntervals(), setScreenSaverInterval()
4280*/
4281void QWSServer::setScreenSaverBlockLevel(int eventBlockLevel)
4282{
4283 if (!qwsServerPrivate)
4284 return;
4285 qwsServerPrivate->screensavereventblocklevel = eventBlockLevel;
4286#ifdef EVENT_BLOCK_DEBUG
4287 qDebug() << "QWSServer::setScreenSaverBlockLevel() " << eventBlockLevel;
4288#endif
4289}
4290
4291extern bool qt_disable_lowpriority_timers; //in qeventloop_unix.cpp
4292
4293void QWSServerPrivate::_q_screenSaverWake()
4294{
4295 if (screensaverintervals) {
4296 if (screensaverinterval != screensaverintervals) {
4297 if (saver) saver->restore();
4298 screensaverinterval = screensaverintervals;
4299 screensaverblockevents = false;
4300 } else {
4301 if (!screensavertimer->isActive()) {
4302 qt_screen->blank(false);
4303 if (saver) saver->restore();
4304 }
4305 }
4306 screensavertimer->start(*screensaverinterval);
4307 screensavertime.start();
4308 }
4309 qt_disable_lowpriority_timers=false;
4310}
4311
4312void QWSServerPrivate::_q_screenSaverSleep()
4313{
4314 qt_screen->blank(true);
4315#if !defined(QT_QWS_IPAQ) && !defined(QT_QWS_EBX)
4316 screensavertimer->stop();
4317#else
4318 if (screensaverinterval) {
4319 screensavertimer->start(*screensaverinterval);
4320 screensavertime.start();
4321 } else {
4322 screensavertimer->stop();
4323 }
4324#endif
4325 qt_disable_lowpriority_timers=true;
4326}
4327
4328/*!
4329 \fn void QWSServer::setScreenSaver(QWSScreenSaver* screenSaver)
4330
4331 Installs the given \a screenSaver, deleting the current screen
4332 saver.
4333
4334 Note that this function can only be used in the server process.
4335
4336 \sa screenSaverActivate(), setScreenSaverInterval(), setScreenSaverIntervals(), setScreenSaverBlockLevel()
4337*/
4338void QWSServer::setScreenSaver(QWSScreenSaver* ss)
4339{
4340 QWSServerPrivate *qd = qwsServer->d_func();
4341 delete qd->saver;
4342 qd->saver = ss;
4343}
4344
4345void QWSServerPrivate::screenSave(int level)
4346{
4347 if (saver) {
4348 // saver->save() may call QCoreApplication::processEvents,
4349 // block event before calling saver->save().
4350 bool oldScreensaverblockevents = screensaverblockevents;
4351 if (*screensaverinterval >= 1000) {
4352 screensaverblockevents = (screensavereventblocklevel >= 0 && screensavereventblocklevel <= level);
4353#ifdef EVENT_BLOCK_DEBUG
4354 if (screensaverblockevents)
4355 qDebug("ready to block events");
4356#endif
4357 }
4358 int *oldScreensaverinterval = screensaverinterval;
4359 if (saver->save(level)) {
4360 // only update screensaverinterval if it hasn't already changed
4361 if (oldScreensaverinterval == screensaverinterval) {
4362 if (screensaverinterval && screensaverinterval[1]) {
4363 screensavertimer->start(*++screensaverinterval);
4364 screensavertime.start();
4365 } else {
4366 screensaverinterval = 0;
4367 }
4368 }
4369 } else {
4370 // restore previous state
4371 screensaverblockevents = oldScreensaverblockevents;
4372
4373 // for some reason, the saver don't want us to change to the
4374 // next level, so we'll stay at this level for another interval
4375 if (screensaverinterval && *screensaverinterval) {
4376 screensavertimer->start(*screensaverinterval);
4377 screensavertime.start();
4378 }
4379 }
4380 } else {
4381 screensaverinterval = 0;//screensaverintervals;
4382 screensaverblockevents = false;
4383 _q_screenSaverSleep();
4384 }
4385}
4386
4387void QWSServerPrivate::_q_screenSaverTimeout()
4388{
4389 if (screensaverinterval) {
4390 if (screensavertime.elapsed() > *screensaverinterval*2) {
4391 // bogus (eg. unsuspend, system time changed)
4392 _q_screenSaverWake(); // try again
4393 return;
4394 }
4395 screenSave(screensaverinterval - screensaverintervals);
4396 }
4397}
4398
4399/*!
4400 Returns true if the screen saver is active; otherwise returns
4401 false.
4402
4403 Note that this function can only be used in the server process.
4404
4405 \sa screenSaverActivate()
4406*/
4407bool QWSServer::screenSaverActive()
4408{
4409 return qwsServerPrivate->screensaverinterval
4410 && !qwsServerPrivate->screensavertimer->isActive();
4411}
4412
4413/*!
4414 \internal
4415*/
4416void QWSServer::updateWindowRegions() const
4417{
4418 qwsServerPrivate->update_regions();
4419}
4420
4421/*!
4422 Activates the screen saver if \a activate is true; otherwise it is
4423 deactivated.
4424
4425 Note that this function can only be used in the server process.
4426
4427 \sa screenSaverActive(), setScreenSaver()
4428*/
4429void QWSServer::screenSaverActivate(bool activate)
4430{
4431 if (activate)
4432 qwsServerPrivate->_q_screenSaverSleep();
4433 else
4434 qwsServerPrivate->_q_screenSaverWake();
4435}
4436
4437void QWSServerPrivate::disconnectClient(QWSClient *c)
4438{
4439 QTimer::singleShot(0, c, SLOT(closeHandler()));
4440}
4441
4442void QWSServerPrivate::updateClientCursorPos()
4443{
4444 Q_Q(QWSServer);
4445 QWSWindow *win = qwsServerPrivate->mouseGrabber ? qwsServerPrivate->mouseGrabber : qwsServer->windowAt(QWSServer::mousePosition);
4446 QWSClient *winClient = win ? win->client() : 0;
4447 if (winClient && winClient != cursorClient)
4448 q->sendMouseEvent(QWSServer::mousePosition, mouseState);
4449}
4450
4451#ifndef QT_NO_QWS_INPUTMETHODS
4452
4453/*!
4454 \class QWSInputMethod
4455 \preliminary
4456 \ingroup qws
4457
4458 \brief The QWSInputMethod class provides international input methods
4459 in Qt for Embedded Linux.
4460
4461 Note that this class is only available in \l{Qt for Embedded Linux}.
4462
4463 A \l{Qt for Embedded Linux} application requires a server application to be
4464 running, or to be the server application itself. All system
4465 generated events, including keyboard and mouse events, are passed
4466 to the server application which then propagates the event to the
4467 appropriate client.
4468
4469 An input method consists of a filter and optionally a graphical
4470 interface, and is used to filter input events between the server
4471 and the client application.
4472
4473 \tableofcontents
4474
4475 \section1 Creating Custom Input Methods
4476
4477 To implement a custom input method, derive from the QWSInputMethod
4478 class, and use the server's \l
4479 {QWSServer::}{setCurrentInputMethod()} function to install it.
4480
4481 When subclassing QWSInputMethod, you can reimplement the filter()
4482 functions to handle input from both physical and virtual keyboards
4483 as well as mouse devices. Note that the default implementations do
4484 nothing. Use the setInputResolution() function to control the
4485 number of bits shifted when filtering mouse input, i.e., when
4486 going from pointer resolution to screen resolution (the current
4487 resolution can be retrieved using the inputResolutionShift()
4488 function).
4489
4490 Reimplement the reset() function to restore the state of the input
4491 method. Note that the default implementation calls the sendEvent()
4492 function with empty preedit and commit strings if the input method
4493 is in compose mode (i.e., if the input method is actively
4494 composing a preedit string).
4495
4496 To receive replies to an input method query (sent using the
4497 sendQuery() function), you must reimplement the queryResponse()
4498 function, while the mouseHandler() function must be reimplemented
4499 if you want to handle mouse events within the preedit
4500 text. Reimplement the updateHandler() function to handle update
4501 events including resets and focus changes. The UpdateType enum
4502 describes the various types of update events recognized by the
4503 input method.
4504
4505 \section1 Using Input Methods
4506
4507 In addition to the filter(), reset(), queryResponse(),
4508 mouseHandler() and updateHandler() function mentioned in the
4509 previous section, the QWSInputMethod provides several other
4510 functions helping the window system to manage the installed input
4511 methods.
4512
4513 The sendEvent() function sends the given event to the focus
4514 widget, while the sendPreeditString() function sends the given
4515 preedit text (encapsulated by an event). QWSInputMethod also
4516 provides the sendCommitString() convenience function which sends
4517 an event encapsulating the given commit string to the current
4518 focus widget, and the sendMouseEvent() function which sends the
4519 given mouse event.
4520
4521 Finally, the QWSInputMethod class provides the sendQuery()
4522 function for sending input method queries. This function
4523 encapsulates the event with a QWSEvent instance of the \l
4524 {QWSEvent::}{IMQuery} type.
4525
4526 \sa QWSServer, {Qt for Embedded Linux Architecture}
4527*/
4528
4529/*!
4530 Constructs a new input method.
4531
4532 Use the QWSServer::setCurrentInputMethod() function to install it.
4533*/
4534
4535QWSInputMethod::QWSInputMethod()
4536{
4537
4538}
4539
4540/*!
4541 Destroys this input method, uninstalling it if it is installed.
4542*/
4543QWSInputMethod::~QWSInputMethod()
4544{
4545 if (current_IM == this)
4546 current_IM = 0;
4547}
4548
4549/*!
4550 Filters the key input identified by the given \a unicode, \a
4551 keycode, \a modifiers, \a isPress and \a autoRepeat parameters.
4552
4553 Note that the default implementation does nothing; reimplement
4554 this function to handle input from both physical and virtual
4555 devices.
4556
4557 The \a keycode is a Qt::Key value, and the \a modifiers is an OR
4558 combination of Qt::KeyboardModifiers. The \a isPress parameter is
4559 telling whether the input is a key press or key release, and the
4560 \a autoRepeat parameter determines whether the input is
4561 autorepeated ( i.e., in which case the
4562 QWSKeyboardHandler::beginAutoRepeat() function has been called).
4563
4564 To block the event from further processing, return true when
4565 reimplementing this function; the default implementation returns
4566 false.
4567
4568 \sa setInputResolution(), inputResolutionShift()
4569*/
4570bool QWSInputMethod::filter(int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat)
4571{
4572 Q_UNUSED(unicode);
4573 Q_UNUSED(keycode);
4574 Q_UNUSED(modifiers);
4575 Q_UNUSED(isPress);
4576 Q_UNUSED(autoRepeat);
4577 return false;
4578}
4579
4580/*!
4581 \overload
4582
4583 Filters the mouse input identified by the given \a position, \a
4584 state, and \a wheel parameters.
4585*/
4586bool QWSInputMethod::filter(const QPoint &position, int state, int wheel)
4587{
4588 Q_UNUSED(position);
4589 Q_UNUSED(state);
4590 Q_UNUSED(wheel);
4591 return false;
4592}
4593
4594/*!
4595 Resets the state of the input method.
4596
4597 If the input method is in compose mode, i.e., the input method is
4598 actively composing a preedit string, the default implementation
4599 calls sendEvent() with empty preedit and commit strings; otherwise
4600 it does nothing. Reimplement this function to alter this behavior.
4601
4602 \sa sendEvent()
4603*/
4604void QWSInputMethod::reset()
4605{
4606 if (current_IM_composing_win) {
4607 QInputMethodEvent ime;
4608 sendEvent(&ime);
4609 }
4610}
4611
4612/*!
4613 \enum QWSInputMethod::UpdateType
4614
4615 This enum describes the various types of update events recognized
4616 by the input method.
4617
4618 \value Update The input widget is updated in some way; use sendQuery() with
4619 Qt::ImMicroFocus as an argument for more information.
4620 \value FocusIn A new input widget receives focus.
4621 \value FocusOut The input widget loses focus.
4622 \value Reset The input method should be reset.
4623 \value Destroyed The input widget is destroyed.
4624
4625 \sa updateHandler()
4626*/
4627
4628/*!
4629 Handles update events including resets and focus changes. The
4630 update events are specified by the given \a type which is one of
4631 the UpdateType enum values.
4632
4633 Note that reimplementations of this function must call the base
4634 implementation for all cases that it does not handle itself.
4635
4636 \sa UpdateType
4637*/
4638void QWSInputMethod::updateHandler(int type)
4639{
4640 switch (type) {
4641 case FocusOut:
4642 case Reset:
4643 reset();
4644 break;
4645
4646 default:
4647 break;
4648 }
4649}
4650
4651
4652/*!
4653 Receive replies to an input method query.
4654
4655 Note that the default implementation does nothing; reimplement
4656 this function to receive such replies.
4657
4658 Internally, an input method query is passed encapsulated by an \l
4659 {QWSEvent::IMQuery}{IMQuery} event generated by the sendQuery()
4660 function. The queried property and the result is passed in the \a
4661 property and \a result parameters.
4662
4663 \sa sendQuery(), QWSServer::sendIMQuery()
4664*/
4665void QWSInputMethod::queryResponse(int property, const QVariant &result)
4666{
4667 Q_UNUSED(property);
4668 Q_UNUSED(result);
4669}
4670
4671
4672
4673/*!
4674 \fn void QWSInputMethod::mouseHandler(int offset, int state)
4675
4676 Handles mouse events within the preedit text.
4677
4678 Note that the default implementation resets the input method on
4679 all mouse presses; reimplement this function to alter this
4680 behavior.
4681
4682 The \a offset parameter specifies the position of the mouse event
4683 within the string, and \a state specifies the type of the mouse
4684 event as described by the QWSServer::IMMouse enum. If \a state is
4685 less than 0, the mouse event is inside the associated widget, but
4686 outside the preedit text. When clicking in a different widget, the
4687 \a state is QWSServer::MouseOutside.
4688
4689 \sa sendPreeditString(), reset()
4690*/
4691void QWSInputMethod::mouseHandler(int, int state)
4692{
4693 if (state == QWSServer::MousePress || state == QWSServer::MouseOutside)
4694 reset();
4695}
4696
4697
4698/*!
4699 Sends an event encapsulating the given \a preeditString, to the
4700 focus widget.
4701
4702 The specified \a selectionLength is the number of characters to be
4703 marked as selected (starting at the given \a cursorPosition). If
4704 \a selectionLength is negative, the text \e before \a
4705 cursorPosition is marked.
4706
4707 The preedit string is marked with QInputContext::PreeditFormat,
4708 and the selected part is marked with
4709 QInputContext::SelectionFormat.
4710
4711 Sending an input method event with a non-empty preedit string will
4712 cause the input method to enter compose mode. Sending an input
4713 method event with an empty preedit string will cause the input
4714 method to leave compose mode, i.e., the input method will no longer
4715 be actively composing the preedit string.
4716
4717 Internally, the event is represented by a QWSEvent object of the
4718 \l {QWSEvent::IMEvent}{IMEvent} type.
4719
4720 \sa sendEvent(), sendCommitString()
4721*/
4722
4723void QWSInputMethod::sendPreeditString(const QString &preeditString, int cursorPosition, int selectionLength)
4724{
4725 QList<QInputMethodEvent::Attribute> attributes;
4726
4727 int selPos = cursorPosition;
4728 if (selectionLength == 0) {
4729 selPos = 0;
4730 } else if (selectionLength < 0) {
4731 selPos += selectionLength;
4732 selectionLength = -selectionLength;
4733 }
4734 if (selPos > 0)
4735 attributes += QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, selPos,
4736 QVariant(int(QInputContext::PreeditFormat)));
4737
4738 if (selectionLength)
4739 attributes += QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, selPos, selectionLength,
4740 QVariant(int(QInputContext::SelectionFormat)));
4741
4742 if (selPos + selectionLength < preeditString.length())
4743 attributes += QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
4744 selPos + selectionLength,
4745 preeditString.length() - selPos - selectionLength,
4746 QVariant(int(QInputContext::PreeditFormat)));
4747
4748 attributes += QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursorPosition, 0, QVariant());
4749
4750 QInputMethodEvent ime(preeditString, attributes);
4751 qwsServer->sendIMEvent(&ime);
4752}
4753
4754/*!
4755 \fn void QWSInputMethod::sendCommitString(const QString &commitString, int replaceFromPosition, int replaceLength)
4756
4757 Sends an event encapsulating the given \a commitString, to the
4758 focus widget.
4759
4760 Note that this will cause the input method to leave compose mode,
4761 i.e., the input method will no longer be actively composing the
4762 preedit string.
4763
4764 If the specified \a replaceLength is greater than 0, the commit
4765 string will replace the given number of characters of the
4766 receiving widget's previous text, starting at the given \a
4767 replaceFromPosition relative to the start of the current preedit
4768 string.
4769
4770 Internally, the event is represented by a QWSEvent object of the
4771 \l {QWSEvent::IMEvent}{IMEvent} type.
4772
4773 \sa sendEvent(), sendPreeditString()
4774*/
4775void QWSInputMethod::sendCommitString(const QString &commitString, int replaceFrom, int replaceLength)
4776{
4777 QInputMethodEvent ime;
4778 ime.setCommitString(commitString, replaceFrom, replaceLength);
4779 qwsServer->sendIMEvent(&ime);
4780}
4781
4782/*!
4783 \fn QWSInputMethod::sendIMEvent(QWSServer::IMState state, const QString &text, int cursorPosition, int selectionLength)
4784 \obsolete
4785
4786 Sends a QInputMethodEvent object to the focus widget.
4787
4788 If the specified \a state is QWSServer::IMCompose, \a text is a
4789 preedit string, \a cursorPosition is the cursor's position within
4790 the preedit string, and \a selectionLength is the number of
4791 characters (starting at \a cursorPosition) that should be marked
4792 as selected by the input widget receiving the event. If the
4793 specified \a state is QWSServer::IMEnd, \a text is a commit
4794 string.
4795
4796 Use sendEvent(), sendPreeditString() or sendCommitString() instead.
4797*/
4798
4799/*!
4800 \fn QWSInputMethod::sendEvent(const QInputMethodEvent *event)
4801
4802 Sends the given \a event to the focus widget.
4803
4804 The \c QInputMethodEvent class is derived from QWSEvent, i.e., the
4805 given \a event is a QWSEvent object of the \l
4806 {QWSEvent::IMEvent}{IMEvent} type.
4807
4808 \sa sendPreeditString(), sendCommitString(), reset()
4809*/
4810
4811
4812/*!
4813 \fn void QWSInputMethod::sendQuery(int property)
4814
4815 Sends an input method query (internally encapsulated by a QWSEvent
4816 of the \l {QWSEvent::IMQuery}{IMQuery} type) for the specified \a
4817 property.
4818
4819 To receive responses to input method queries, the virtual
4820 queryResponse() function must be reimplemented.
4821
4822 \sa queryResponse(), QWSServer::sendIMQuery()
4823*/
4824
4825/*!
4826 Sets and returns the number of bits shifted to go from pointer
4827 resolution to screen resolution when filtering mouse input.
4828
4829 If \a isHigh is true and the device has a pointer device
4830 resolution twice or more of the screen resolution, the positions
4831 passed to the filter() function will be presented at the higher
4832 resolution; otherwise the resolution will be equal to that of the
4833 screen resolution.
4834
4835 \sa inputResolutionShift(), filter()
4836*/
4837uint QWSInputMethod::setInputResolution(bool isHigh)
4838{
4839 mIResolution = isHigh;
4840 return inputResolutionShift();
4841}
4842
4843/*!
4844 Returns the number of bits shifted to go from pointer resolution
4845 to screen resolution when filtering mouse input.
4846
4847 \sa setInputResolution(), filter()
4848*/
4849uint QWSInputMethod::inputResolutionShift() const
4850{
4851 return 0; // default for devices with single resolution.
4852}
4853
4854/*!
4855 \fn void QWSInputMethod::sendMouseEvent( const QPoint &position, int state, int wheel )
4856
4857 Sends a mouse event specified by the given \a position, \a state
4858 and \a wheel parameters.
4859
4860 The given \a position will be transformed if the screen
4861 coordinates do not match the pointer device coordinates.
4862
4863 Note that the event will be not be tested by the active input
4864 method, but calling the QWSServer::sendMouseEvent() function will
4865 make the current input method filter the event.
4866
4867 \sa mouseHandler(), sendEvent()
4868*/
4869void QWSInputMethod::sendMouseEvent( const QPoint &pos, int state, int wheel )
4870{
4871 if (qt_last_x) {
4872 *qt_last_x = pos.x();
4873 *qt_last_y = pos.y();
4874 }
4875 QWSServer::mousePosition = pos;
4876 qwsServerPrivate->mouseState = state;
4877 QWSServerPrivate::sendMouseEventUnfiltered(pos, state, wheel);
4878}
4879#endif // QT_NO_QWS_INPUTMETHODS
4880
4881/*!
4882 \fn QWSWindow::QWSWindow(int i, QWSClient * client)
4883 \internal
4884
4885 Constructs a new top-level window, associated with the client \a
4886 client and giving it the id \a i.
4887*/
4888
4889/*!
4890 \fn QWSServer::windowEvent(QWSWindow * window, QWSServer::WindowEvent eventType)
4891
4892 This signal is emitted whenever something happens to a top-level
4893 window (e.g., it's created or destroyed), passing a pointer to the
4894 window and the event's type in the \a window and \a eventType
4895 parameters, respectively.
4896
4897 \sa markedText()
4898*/
4899
4900/*!
4901 \class QWSServer::KeyboardFilter
4902 \ingroup qws
4903
4904 \brief The KeyboardFilter class is a base class for global
4905 keyboard event filters in Qt for Embedded Linux.
4906
4907 Note that this class is only available in \l{Qt for Embedded Linux}.
4908
4909 In \l{Qt for Embedded Linux}, all system generated events, including
4910 keyboard events, are passed to the server application which then
4911 propagates the event to the appropriate client. The KeyboardFilter
4912 class is used to implement a global, low-level filter on the
4913 server side. The server applies the filter to all keyboard events
4914 before passing them on to the clients:
4915
4916 \image qwsserver_keyboardfilter.png
4917
4918 This feature can, for example, be used to filter things like APM
4919 (advanced power management) suspended from a button without having
4920 to filter for it in all applications.
4921
4922 To add a new keyboard filter you must first create the filter by
4923 deriving from this class, reimplementing the pure virtual filter()
4924 function. Then you can install the filter on the server using
4925 QWSServer's \l {QWSServer::}{addKeyboardFilter()}
4926 function. QWSServer also provides a \l
4927 {QWSServer::}{removeKeyboardFilter()} function.
4928
4929 \sa {Qt for Embedded Linux Architecture}, QWSServer, QWSInputMethod
4930*/
4931
4932/*!
4933 \fn QWSServer::KeyboardFilter::~KeyboardFilter()
4934
4935 Destroys the keyboard filter.
4936*/
4937
4938/*!
4939 \fn bool QWSServer::KeyboardFilter::filter(int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat)
4940
4941 Implement this function to return true if a given key event should
4942 be stopped from being processed any further; otherwise it should
4943 return false.
4944
4945 A key event can be identified by the given \a unicode value and
4946 the \a keycode, \a modifiers, \a isPress and \a autoRepeat
4947 parameters.
4948
4949 The \a keycode parameter is the Qt keycode value as defined by the
4950 Qt::Key enum. The \a modifiers is an OR combination of
4951 Qt::KeyboardModifier values, indicating whether \gui
4952 Shift/Alt/Ctrl keys are pressed. The \a isPress parameter is true
4953 if the event is a key press event and \a autoRepeat is true if the
4954 event is caused by an auto-repeat mechanism and not an actual key
4955 press.
4956*/
4957
4958QT_END_NAMESPACE
4959
4960#include "moc_qwindowsystem_qws.cpp"
Note: See TracBrowser for help on using the repository browser.