1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qglobal.h"
43 #include "qlibrary.h"
44 #include "qcursor.h"
45 #include "qapplication.h"
46 #include "private/qapplication_p.h"
47 #include "qwidget.h"
48 #include "qbitarray.h"
49 #include "qpainter.h"
50 #include "qpixmapcache.h"
51 #include "qdatetime.h"
52 #include "qtextcodec.h"
53 #include "qdatastream.h"
54 #include "qbuffer.h"
55 #include "qsocketnotifier.h"
56 #include "qsessionmanager.h"
57 #include "qclipboard.h"
58 #include "qbitmap.h"
59 #include "qwssocket_qws.h"
60 #include "qtransportauth_qws.h"
61 #include "private/qtransportauth_qws_p.h"
62 #include "qwsevent_qws.h"
63 #include "private/qwscommand_qws_p.h"
64 #include "qwsproperty_qws.h"
65 #include "qscreen_qws.h"
66 #include "qscreenproxy_qws.h"
67 #include "qcopchannel_qws.h"
68 #include "private/qlock_p.h"
69 #include "private/qwslock_p.h"
70 //#include "qmemorymanager_qws.h"
71 #include "qwsmanager_qws.h"
72 //#include "qwsregionmanager_qws.h"
73 #include "qwindowsystem_qws.h"
74 #include "private/qwindowsystem_p.h"
75 #include "qdecorationfactory_qws.h"
76 
77 #include "qwsdisplay_qws.h"
78 #include "private/qwsdisplay_qws_p.h"
79 #include "private/qwsinputcontext_p.h"
80 #include "qfile.h"
81 #include "qhash.h"
82 #include "qdesktopwidget.h"
83 #include "qcolormap.h"
84 #include "private/qcursor_p.h"
85 #include "qsettings.h"
86 #include "qdebug.h"
87 #include "qeventdispatcher_qws_p.h"
88 #if !defined(QT_NO_GLIB)
89 #  include "qeventdispatcher_glib_qws_p.h"
90 #endif
91 
92 
93 #include "private/qwidget_p.h"
94 #include "private/qbackingstore_p.h"
95 #include "private/qwindowsurface_qws_p.h"
96 #include "private/qfont_p.h"
97 
98 #include <unistd.h>
99 #include <stdio.h>
100 #include <stdlib.h>
101 #include <string.h>
102 #include <locale.h>
103 #include <errno.h>
104 #include <fcntl.h>
105 #include <sys/stat.h>
106 #include <sys/types.h>
107 
108 #include <qvfbhdr.h>
109 
110 QT_BEGIN_NAMESPACE
111 
112 #ifndef QT_NO_DIRECTPAINTER
113 class QDirectPainter;
114 extern void qt_directpainter_region(QDirectPainter *dp, const QRegion &alloc, int type);
115 #ifndef QT_NO_QWSEMBEDWIDGET
116 extern void qt_directpainter_embedevent(QDirectPainter *dp,
117                                         const QWSEmbedEvent *e);
118 #endif
119 #endif // QT_NO_DIRECTPAINTER
120 
121 const int qwsSharedRamSize = 1 * 1024; // misc data, written by server, read by clients
122 
123 extern QApplication::Type qt_appType;
124 extern QDesktopWidget *qt_desktopWidget;
125 
126 //these used to be environment variables, they are initialized from
127 //environment variables in
128 
129 bool qws_savefonts = false;
130 bool qws_screen_is_interlaced=false; //### should be detected
131 bool qws_shared_memory = false;
132 bool qws_sw_cursor = true;
133 bool qws_accel = true;            // ### never set
134 QByteArray qws_display_spec(":0");
135 Q_GUI_EXPORT int qws_display_id = 0;
136 Q_GUI_EXPORT int qws_client_id = 0;
137 QWidget *qt_pressGrab = 0;
138 QWidget *qt_mouseGrb = 0;
139 int *qt_last_x = 0;
140 int *qt_last_y = 0;
141 
142 static int mouse_x_root = -1;
143 static int mouse_y_root = -1;
144 static int mouse_state = 0;
145 static int mouse_double_click_distance = 5;
146 
147 int qt_servershmid = -1;
148 
149 bool qws_overrideCursor = false;
150 #ifndef QT_NO_QWS_MANAGER
151 
152 extern Q_GUI_EXPORT QWSServer *qwsServer;
153 
154 static QDecoration *qws_decoration = 0;
155 #endif
156 
157 #if defined(QT_DEBUG)
158 /*
159 extern "C" void dumpmem(const char* m)
160 {
161     static int init=0;
162     static int prev=0;
163     FILE* f = fopen("/proc/meminfo","r");
164     //    char line[100];
165     int total=0,used=0,free=0,shared=0,buffers=0,cached=0;
166     fscanf(f,"%*[^M]Mem: %d %d %d %d %d %d",&total,&used,&free,&shared,&buffers,&cached);
167     used -= buffers + cached;
168     if (!init) {
169         init=used;
170     } else {
171         printf("%40s: %+8d = %8d\n",m,used-init-prev,used-init);
172         prev = used-init;
173     }
174     fclose(f);
175 }
176 */
177 #endif
178 
179 // Get the name of the directory where Qt for Embedded Linux temporary data should
180 // live.
qws_dataDir()181 QString qws_dataDir()
182 {
183     static QString result;
184     if (!result.isEmpty())
185         return result;
186     result = QT_VFB_DATADIR(qws_display_id);
187     QByteArray dataDir = result.toLocal8Bit();
188 
189 #if defined(Q_OS_INTEGRITY)
190     /* ensure filesystem is ready before starting requests */
191     WaitForFileSystemInitialization();
192 #endif
193 
194     if (QT_MKDIR(dataDir, 0700)) {
195         if (errno != EEXIST) {
196             qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData());
197         }
198     }
199 
200     QT_STATBUF buf;
201     if (QT_LSTAT(dataDir, &buf))
202         qFatal("stat failed for Qt for Embedded Linux data directory: %s", dataDir.constData());
203 
204     if (!S_ISDIR(buf.st_mode))
205         qFatal("%s is not a directory", dataDir.constData());
206 
207 #if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS) && !defined(Q_OS_QNX)
208     if (buf.st_uid != getuid())
209         qFatal("Qt for Embedded Linux data directory is not owned by user %d: %s", getuid(), dataDir.constData());
210 
211     if ((buf.st_mode & 0677) != 0600)
212         qFatal("Qt for Embedded Linux data directory has incorrect permissions: %s", dataDir.constData());
213 #endif
214 
215     result.append(QLatin1Char('/'));
216     return result;
217 }
218 
219 // Get the filename of the pipe Qt for Embedded Linux uses for server/client comms
qws_qtePipeFilename()220 Q_GUI_EXPORT QString qws_qtePipeFilename()
221 {
222     qws_dataDir();
223     return QTE_PIPE(qws_display_id);
224 }
225 
setMaxWindowRect(const QRect & rect)226 static void setMaxWindowRect(const QRect &rect)
227 {
228     const QList<QScreen*> subScreens = qt_screen->subScreens();
229     QScreen *screen = qt_screen;
230     int screenNo = 0;
231     for (int i = 0; i < subScreens.size(); ++i) {
232         if (subScreens.at(i)->region().contains(rect)) {
233             screen = subScreens.at(i);
234             screenNo = i;
235             break;
236         }
237     }
238 
239     QApplicationPrivate *ap = QApplicationPrivate::instance();
240     ap->setMaxWindowRect(screen, screenNo, rect);
241 }
242 
setMaxWindowRect(const QScreen * screen,int screenNo,const QRect & rect)243 void QApplicationPrivate::setMaxWindowRect(const QScreen *screen, int screenNo,
244                                            const QRect &rect)
245 {
246     if (maxWindowRects.value(screen) == rect)
247         return;
248 
249     maxWindowRects[screen] = rect;
250 
251     // Re-resize any maximized windows
252     QWidgetList l = QApplication::topLevelWidgets();
253     for (int i = 0; i < l.size(); ++i) {
254         QWidget *w = l.at(i);
255         QScreen *s = w->d_func()->getScreen();
256         if (s == screen) {
257             if (w->isMaximized())
258                 w->d_func()->setMaxWindowState_helper();
259             else if (w->isFullScreen())
260                 w->d_func()->setFullScreenSize_helper();
261         }
262     }
263 
264     if ( qt_desktopWidget ) // XXX workaround crash
265         emit QApplication::desktop()->workAreaResized(screenNo);
266 }
267 
268 #ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION
269 
270 typedef void (*TransformFunc)(QScreen *, int);
271 #ifndef QT_NO_QWS_TRANSFORMED
272 extern "C" void qws_setScreenTransformation(QScreen *, int);
273 #endif
getTransformationFunction()274 static TransformFunc getTransformationFunction()
275 {
276     static TransformFunc func = 0;
277 
278     if (!func) {
279 #ifdef QT_NO_QWS_TRANSFORMED
280 #  ifndef QT_NO_LIBRARY
281         // symbol is not built into the library, search for the plugin
282         const QStringList paths = QApplication::libraryPaths();
283         foreach (const QString &path, paths) {
284             const QString file = path + QLatin1String("/gfxdrivers/libqgfxtransformed");
285             func = (TransformFunc)QLibrary::resolve(file,
286                                                     "qws_setScreenTransformation");
287             if (func)
288                 break;
289         }
290 #  endif
291 #else
292         func = qws_setScreenTransformation;
293 #endif
294         if (!func)
295             func = (TransformFunc)-1;
296     }
297 
298     if (func == (TransformFunc)-1)
299         return 0;
300 
301     return func;
302 }
303 
setScreenTransformation(int screenNo,int transformation)304 static void setScreenTransformation(int screenNo, int transformation)
305 {
306     QScreen *screen = QScreen::instance();
307     const QList<QScreen*> subScreens = screen->subScreens();
308 
309     if (screenNo == -1)
310         screenNo = 0;
311 
312     if (screenNo == -1 && !subScreens.isEmpty())
313         screenNo = 0;
314 
315     if (subScreens.isEmpty() && screenNo == 0) {
316         // nothing
317     } else if (screenNo < 0 || screenNo >= subScreens.size()) {
318         qWarning("setScreenTransformation: invalid screen %i", screenNo);
319         return;
320     }
321 
322     if (screenNo < subScreens.size())
323         screen = subScreens.at(screenNo);
324 
325     QApplicationPrivate *ap = QApplicationPrivate::instance();
326     ap->setScreenTransformation(screen, screenNo, transformation);
327 }
328 
setScreenTransformation(QScreen * screen,int screenNo,int transformation)329 void QApplicationPrivate::setScreenTransformation(QScreen *screen,
330                                                   int screenNo,
331                                                   int transformation)
332 {
333     QScreen *transformed = screen;
334 
335     while (transformed->classId() == QScreen::ProxyClass)
336         transformed = static_cast<QProxyScreen*>(transformed)->screen();
337 
338     if (transformed->classId() != QScreen::TransformedClass)
339         return;
340 
341     TransformFunc setScreenTransformation = getTransformationFunction();
342     if (!setScreenTransformation)
343         return;
344 
345     setScreenTransformation(transformed, transformation);
346 
347     // need to re-configure() proxies bottom-up
348     if (screen->classId() == QScreen::ProxyClass) {
349         QList<QProxyScreen*> proxies;
350         QScreen *s = screen;
351 
352         do {
353             QProxyScreen *proxy = static_cast<QProxyScreen*>(s);
354             proxies.append(proxy);
355             s = proxy->screen();
356         } while (s->classId() == QScreen::ProxyClass);
357 
358         do {
359             QProxyScreen *proxy = proxies.takeLast();
360             proxy->setScreen(proxy->screen()); // triggers configure()
361         } while (!proxies.isEmpty());
362     }
363 
364     if (qt_desktopWidget) { // XXX workaround crash for early screen transform events
365         QDesktopWidget *desktop = QApplication::desktop();
366 
367         emit desktop->resized(screenNo);
368         if (maxWindowRect(screen).isEmpty()) // not explicitly set
369             emit desktop->workAreaResized(screenNo);
370     }
371 
372     QWSServer *server = QWSServer::instance();
373     if (server) {
374         server->updateWindowRegions();
375         QRegion r = screen->region();
376         server->refresh(r);
377     }
378 
379     // make sure maximized and fullscreen windows are updated
380     QWidgetList list = QApplication::topLevelWidgets();
381     for (int i = list.size() - 1; i >= 0; --i) {
382         QWidget *w = list.at(i);
383         if (w->isFullScreen())
384             w->d_func()->setFullScreenSize_helper();
385         else if (w->isMaximized())
386             w->d_func()->setMaxWindowState_helper();
387     }
388 }
389 
390 #endif // QT_NO_QWS_DYNAMICSCREENTRANSFORMATION
391 
392 /*****************************************************************************
393   Internal variables and functions
394  *****************************************************************************/
395 
396 
397 static QString appName;                          // application name
398 static const char *appFont = 0;                  // application font
399 static const char *appBGCol = 0;                 // application bg color
400 static const char *appFGCol = 0;                 // application fg color
401 static const char *appBTNCol = 0;                // application btn color
402 static const char *mwGeometry = 0;               // main widget geometry
403 static const char *mwTitle = 0;                  // main widget title
404 //static bool mwIconic = false;                  // main widget iconified
405 
406 static bool app_do_modal = false;                // modal mode
407 Q_GUI_EXPORT QWSDisplay *qt_fbdpy = 0;                        // QWS `display'
408 QLock *QWSDisplay::lock = 0;
409 
410 static int mouseButtonPressed = 0;               // last mouse button pressed
411 static int mouseButtonPressTime = 0;             // when was a button pressed
412 static short mouseXPos, mouseYPos;               // mouse position in act window
413 
414 extern QWidgetList *qt_modal_stack;              // stack of modal widgets
415 
416 static QWidget *popupButtonFocus = 0;
417 static QWidget *popupOfPopupButtonFocus = 0;
418 static bool popupCloseDownMode = false;
419 static bool popupGrabOk;
420 static QPointer<QWidget> *mouseInWidget = 0;
421 QPointer<QWidget> qt_last_mouse_receiver = 0;
422 
423 static bool sm_blockUserInput = false;           // session management
424 
425 QWidget *qt_button_down = 0;                     // widget got last button-down
426 WId qt_last_cursor = 0xffffffff;                 // Was -1, but WIds are unsigned
427 
428 class QWSMouseEvent;
429 class QWSKeyEvent;
430 
431 class QETWidget : public QWidget                 // event translator widget
432 {
433 public:
434     bool translateMouseEvent(const QWSMouseEvent *, int oldstate);
435     bool translateKeyEvent(const QWSKeyEvent *, bool grab);
436     bool translateRegionEvent(const QWSRegionEvent *);
437 #ifndef QT_NO_QWSEMBEDWIDGET
438     void translateEmbedEvent(const QWSEmbedEvent *event);
439 #endif
440     bool translateWheelEvent(const QWSMouseEvent *me);
441     void repaintDecoration(QRegion r, bool post);
442     void updateRegion();
443 
raiseOnClick()444     bool raiseOnClick()
445     {
446         // With limited windowmanagement/taskbar/etc., raising big windows
447         // (eg. spreadsheet) over the top of everything else (eg. calculator)
448         // is just annoying.
449         return !isMaximized() && !isFullScreen();
450     }
451 };
452 
createEventDispatcher()453 void QApplicationPrivate::createEventDispatcher()
454 {
455     Q_Q(QApplication);
456 #if !defined(QT_NO_GLIB)
457     if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported())
458         eventDispatcher = (q->type() != QApplication::Tty
459                            ? new QWSEventDispatcherGlib(q)
460                            : new QEventDispatcherGlib(q));
461     else
462 #endif
463     eventDispatcher = (q->type() != QApplication::Tty
464                        ? new QEventDispatcherQWS(q)
465                        : new QEventDispatcherUNIX(q));
466 }
467 
468 // Single-process stuff. This should maybe move into qwindowsystem_qws.cpp
469 
470 static bool qws_single_process;
471 static QList<QWSEvent*> incoming;
472 static QList<QWSCommand*> outgoing;
473 
qt_client_enqueue(const QWSEvent * event)474 void qt_client_enqueue(const QWSEvent *event)
475 {
476     QWSEvent *copy = QWSEvent::factory(event->type);
477     copy->copyFrom(event);
478     incoming.append(copy);
479 }
480 
qt_get_server_queue()481 QList<QWSCommand*> *qt_get_server_queue()
482 {
483     return &outgoing;
484 }
485 
qt_server_enqueue(const QWSCommand * command)486 void qt_server_enqueue(const QWSCommand *command)
487 {
488     QWSCommand *copy = QWSCommand::factory(command->type);
489     QT_TRY {
490         copy->copyFrom(command);
491         outgoing.append(copy);
492     } QT_CATCH(...) {
493         delete copy;
494         QT_RETHROW;
495     }
496 }
497 
Data(QObject * parent,bool singleProcess)498 QWSDisplay::Data::Data(QObject* parent, bool singleProcess)
499 {
500 #ifdef QT_NO_QWS_MULTIPROCESS
501     Q_UNUSED(parent);
502     Q_UNUSED(singleProcess);
503 #else
504     if (singleProcess)
505         csocket = 0;
506     else {
507         csocket = new QWSSocket(parent);
508         QObject::connect(csocket, SIGNAL(disconnected()),
509                          qApp, SLOT(quit()));
510     }
511     clientLock = 0;
512 #endif
513     init();
514 }
515 
~Data()516 QWSDisplay::Data::~Data()
517 {
518 //        delete rgnMan; rgnMan = 0;
519 //        delete memorymanager; memorymanager = 0;
520     qt_screen->disconnect();
521     delete qt_screen; qt_screen = 0;
522 #ifndef QT_NO_QWS_CURSOR
523     delete qt_screencursor; qt_screencursor = 0;
524 #endif
525 #ifndef QT_NO_QWS_MULTIPROCESS
526     shm.detach();
527     if (csocket) {
528         QWSCommand shutdownCmd(QWSCommand::Shutdown, 0, 0);
529         shutdownCmd.write(csocket);
530         csocket->flush(); // may be pending QCop message, eg.
531         delete csocket;
532     }
533     delete clientLock;
534     clientLock = 0;
535 #endif
536     delete connected_event;
537     delete mouse_event;
538     delete current_event;
539     qDeleteAll(queue);
540 #ifndef QT_NO_COP
541     delete qcop_response;
542 #endif
543 }
544 
545 #ifndef QT_NO_QWS_MULTIPROCESS
lockClient(QWSLock::LockType type,int timeout)546 bool QWSDisplay::Data::lockClient(QWSLock::LockType type, int timeout)
547 {
548     return !clientLock || clientLock->lock(type, timeout);
549 }
550 
unlockClient(QWSLock::LockType type)551 void QWSDisplay::Data::unlockClient(QWSLock::LockType type)
552 {
553     if (clientLock) clientLock->unlock(type);
554 }
555 
waitClient(QWSLock::LockType type,int timeout)556 bool QWSDisplay::Data::waitClient(QWSLock::LockType type, int timeout)
557 {
558     return !clientLock || clientLock->wait(type, timeout);
559 }
560 
getClientLock()561 QWSLock* QWSDisplay::Data::getClientLock()
562 {
563     return clientLock;
564 }
565 #endif // QT_NO_QWS_MULTIPROCESS
566 
flush()567 void QWSDisplay::Data::flush()
568 {
569 #ifndef QT_NO_QWS_MULTIPROCESS
570     if (csocket) {
571         csocket->waitForReadyRead(0);
572         csocket->flush();
573    }
574 #endif
575 }
576 
577 #if 0
578 void QWSDisplay::Data::debugQueue() {
579     for (int i = 0; i < queue.size(); ++i) {
580         QWSEvent *e = queue.at(i);
581         qDebug( "   ev %d type %d sl %d rl %d", i, e->type, e->simpleLen, e->rawLen);
582     }
583 }
584 #endif
585 
queueNotEmpty()586 bool QWSDisplay::Data::queueNotEmpty()
587 {
588     return mouse_event/*||region_event*/||queue.count() > 0;
589 }
dequeue()590 QWSEvent* QWSDisplay::Data::dequeue()
591 {
592     QWSEvent *r=0;
593     if (queue.count()) {
594         r = queue.first();
595         queue.removeFirst();
596         if (r->type == QWSEvent::Region)
597             region_events_count--;
598     } else if (mouse_event) {
599         r = mouse_event;
600         mouse_event = 0;
601 #ifdef QAPPLICATION_EXTRA_DEBUG
602         mouse_event_count = 0;
603 #endif
604     }
605     return r;
606 }
607 
peek()608 QWSEvent* QWSDisplay::Data::peek()
609 {
610     return queue.first();
611 }
612 
directServerConnection()613 bool QWSDisplay::Data::directServerConnection()
614 {
615 #ifndef QT_NO_QWS_MULTIPROCESS
616     return csocket == 0;
617 #else
618     return true;
619 #endif
620 }
621 
create(int n)622 void QWSDisplay::Data::create(int n)
623 {
624     QWSCreateCommand cmd(n);
625     sendCommand(cmd);
626 }
627 
flushCommands()628 void QWSDisplay::Data::flushCommands()
629 {
630 #ifndef QT_NO_QWS_MULTIPROCESS
631     if  (csocket)
632         csocket->flush();
633 #endif
634 }
635 
sendCommand(QWSCommand & cmd)636 void QWSDisplay::Data::sendCommand(QWSCommand & cmd)
637 {
638 #ifndef QT_NO_QWS_MULTIPROCESS
639     if  (csocket)
640         cmd.write(csocket);
641     else
642 #endif
643         qt_server_enqueue(&cmd);
644 }
645 
sendSynchronousCommand(QWSCommand & cmd)646 void QWSDisplay::Data::sendSynchronousCommand(QWSCommand & cmd)
647 {
648 #ifndef QT_NO_QWS_MULTIPROCESS
649     if  (csocket) {
650         lockClient(QWSLock::Communication);
651         cmd.write(csocket);
652         bool ok = true;
653         while (csocket->bytesToWrite() > 0) {
654             if (!csocket->waitForBytesWritten(-1)) {
655                 qCritical("QWSDisplay::Data::sendSynchronousCommand: %s",
656                           qPrintable(csocket->errorString()));
657                 ok = false;
658                 break;
659             }
660         }
661         if (ok)
662             waitClient(QWSLock::Communication);
663     } else
664 #endif
665         qt_server_enqueue(&cmd);
666 }
667 
takeId()668 int QWSDisplay::Data::takeId()
669 {
670     int unusedIdCount = unused_identifiers.count();
671     if (unusedIdCount <= 10)
672         create(15);
673     if (unusedIdCount == 0) {
674         create(1); // Make sure we have an incoming id to wait for, just in case we're recursive
675         waitForCreation();
676     }
677 
678     return unused_identifiers.takeFirst();
679 }
680 
setMouseFilter(void (* filter)(QWSMouseEvent *))681 void QWSDisplay::Data::setMouseFilter(void (*filter)(QWSMouseEvent*))
682 {
683     mouseFilter = filter;
684 }
685 
686 #ifndef QT_NO_QWS_MULTIPROCESS
687 
688 QWSLock* QWSDisplay::Data::clientLock = 0;
689 
qt_app_reinit(const QString & newAppName)690 void Q_GUI_EXPORT qt_app_reinit( const QString& newAppName )
691 {
692     qt_fbdpy->d->reinit( newAppName );
693 }
694 
695 #endif // QT_NO_QWS_MULTIPROCESS
696 
697 class QDesktopWidget;
698 
699 #ifndef QT_NO_QWS_MULTIPROCESS
reinit(const QString & newAppName)700 void QWSDisplay::Data::reinit( const QString& newAppName )
701 {
702     Q_ASSERT(csocket);
703 
704     delete connected_event;
705     connected_event = 0;
706     region_events_count = 0;
707 //    region_ack = 0;
708     delete mouse_event;
709     mouse_event = 0;
710 //    region_event = 0;
711     region_offset_window = 0;
712 #ifndef QT_NO_COP
713     delete qcop_response;
714     qcop_response = 0;
715 #endif
716     delete current_event;
717     current_event = 0;
718 #ifdef QAPPLICATION_EXTRA_DEBUG
719     mouse_event_count = 0;
720 #endif
721     mouseFilter = 0;
722 
723     qt_desktopWidget = 0;
724     delete QWSDisplay::Data::clientLock;
725     QWSDisplay::Data::clientLock = 0;
726 
727     QString pipe = qws_qtePipeFilename();
728 
729     // QWS client
730     // Cleanup all cached ids
731     unused_identifiers.clear();
732     delete csocket;
733 
734     appName = newAppName;
735     qApp->setObjectName( appName );
736 
737     csocket = new QWSSocket();
738     QObject::connect(csocket, SIGNAL(disconnected()),
739                      qApp, SLOT(quit()));
740     csocket->connectToLocalFile(pipe);
741 
742     QWSDisplay::Data::clientLock = new QWSLock();
743 
744     QWSIdentifyCommand cmd;
745     cmd.setId(appName, QWSDisplay::Data::clientLock->id());
746 
747 #ifndef QT_NO_SXE
748     QTransportAuth *a = QTransportAuth::getInstance();
749     QTransportAuth::Data *d = a->connectTransport(
750             QTransportAuth::UnixStreamSock |
751             QTransportAuth::Trusted,
752             csocket->socketDescriptor());
753     QAuthDevice *ad = a->authBuf( d, csocket );
754     ad->setClient( csocket );
755 
756     cmd.write(ad);
757 #else
758     cmd.write(csocket);
759 #endif
760 
761     // wait for connect confirmation
762     waitForConnection();
763 
764     qws_client_id = connected_event->simpleData.clientId;
765 
766     if (!QWSDisplay::initLock(pipe, false))
767         qFatal("Cannot get display lock");
768 
769     if (shm.attach(connected_event->simpleData.servershmid)) {
770         sharedRam = static_cast<uchar *>(shm.address());
771         QScreen *s = qt_get_screen(qws_display_id, qws_display_spec.constData());
772         if (s)
773             sharedRamSize += s->memoryNeeded(QLatin1String(qws_display_spec.constData()));
774     } else {
775         perror("QWSDisplay::Data::init");
776         qFatal("Client can't attach to main ram memory.");
777     }
778 
779     qApp->desktop();
780 
781     // We wait for creation mainly so that we can process important
782     // initialization events such as MaxWindowRect that are sent
783     // before object id creation.  Waiting here avoids later window
784     // resizing since we have the MWR before windows are displayed.
785     waitForCreation();
786 
787     sharedRamSize -= sizeof(int);
788     qt_last_x = reinterpret_cast<int *>(sharedRam + sharedRamSize);
789     sharedRamSize -= sizeof(int);
790     qt_last_y = reinterpret_cast<int *>(sharedRam + sharedRamSize);
791 
792 #ifndef QT_NO_COP
793     QCopChannel::reregisterAll();
794 #endif
795     csocket->flush();
796 }
797 #endif
798 
init()799 void QWSDisplay::Data::init()
800 {
801     connected_event = 0;
802     region_events_count = 0;
803 //    region_ack = 0;
804     mouse_event = 0;
805     mouse_state = -1;
806     mouse_winid = 0;
807 //    region_event = 0;
808     region_offset_window = 0;
809 #ifndef QT_NO_COP
810     qcop_response = 0;
811 #endif
812     current_event = 0;
813 #ifdef QAPPLICATION_EXTRA_DEBUG
814     mouse_event_count = 0;
815 #endif
816     mouseFilter = 0;
817 
818     QString pipe = qws_qtePipeFilename();
819 
820     sharedRamSize = qwsSharedRamSize;
821 
822 #ifndef QT_NO_QWS_MULTIPROCESS
823     if (csocket)    {
824         // QWS client
825 
826         connectToPipe();
827 
828         QWSDisplay::Data::clientLock = new QWSLock();
829 
830         QWSIdentifyCommand cmd;
831         cmd.setId(appName, QWSDisplay::Data::clientLock->id());
832 #ifndef QT_NO_SXE
833         QTransportAuth *a = QTransportAuth::getInstance();
834         QTransportAuth::Data *d = a->connectTransport(
835                 QTransportAuth::UnixStreamSock |
836                 QTransportAuth::Trusted,
837                 csocket->socketDescriptor());
838         QAuthDevice *ad = a->authBuf( d, csocket );
839         ad->setClient( csocket );
840         cmd.write(ad);
841 #else
842         cmd.write(csocket);
843 #endif
844 
845         // create(30); // not necessary, server will send ids anyway
846         waitForConnection();
847 
848         qws_client_id = connected_event->simpleData.clientId;
849 
850         // now we want to get the exact display spec to use if we haven't
851         // specified anything.
852         if (qws_display_spec.at(0) == ':')
853             qws_display_spec = connected_event->display;
854 
855         if (!QWSDisplay::initLock(pipe, false))
856             qFatal("Cannot get display lock");
857 
858         if (shm.attach(connected_event->simpleData.servershmid)) {
859             sharedRam = static_cast<uchar *>(shm.address());
860             QScreen *s = qt_get_screen(qws_display_id, qws_display_spec.constData());
861             if (s)
862                 sharedRamSize += s->memoryNeeded(QLatin1String(qws_display_spec.constData()));
863         } else {
864             perror("QWSDisplay::Data::init");
865             qFatal("Client can't attach to main ram memory.");
866         }
867 
868         // We wait for creation mainly so that we can process important
869         // initialization events such as MaxWindowRect that are sent
870         // before object id creation.  Waiting here avoids later window
871         // resizing since we have the MWR before windows are displayed.
872         waitForCreation();
873     } else
874 #endif
875     {
876         create(30);
877 
878         // QWS server
879         if (!QWSDisplay::initLock(pipe, true))
880             qFatal("Cannot get display lock");
881 
882         QScreen *s = qt_get_screen(qws_display_id, qws_display_spec.constData());
883         if (s)
884             sharedRamSize += s->memoryNeeded(QLatin1String(qws_display_spec.constData()));
885 
886 #ifndef QT_NO_QWS_MULTIPROCESS
887 
888         if (!shm.create(sharedRamSize)) {
889             perror("Cannot create main ram shared memory\n");
890             qFatal("Unable to allocate %d bytes of shared memory", sharedRamSize);
891         }
892         qt_servershmid = shm.id();
893         sharedRam = static_cast<uchar *>(shm.address());
894 #else
895         sharedRam=static_cast<uchar *>(malloc(sharedRamSize));
896 #endif
897         // Need to zero index count at end of block, might as well zero
898         // the rest too
899         memset(sharedRam,0,sharedRamSize);
900 
901         QWSIdentifyCommand cmd;
902         cmd.setId(appName, -1);
903         qt_server_enqueue(&cmd);
904     }
905 
906     // Allow some memory for the graphics driver too
907     //### Note that sharedRamSize() has side effects; it must be called
908     //### once, and only once, and before initDevice()
909     sharedRamSize -= qt_screen->sharedRamSize(sharedRam+sharedRamSize);
910 
911 #ifndef QT_NO_QWS_MULTIPROCESS
912     if(!csocket)
913 #endif
914     {
915         //QWS server process
916         if (!qt_screen->initDevice())
917             qFatal("Unable to initialize screen driver!");
918     }
919 
920     sharedRamSize -= sizeof(int);
921     qt_last_x = reinterpret_cast<int *>(sharedRam + sharedRamSize);
922     sharedRamSize -= sizeof(int);
923     qt_last_y = reinterpret_cast<int *>(sharedRam + sharedRamSize);
924 
925     /* Initialise framebuffer memory manager */
926     /* Add 4k for luck and to avoid clobbering hardware cursor */
927 //    int screensize=qt_screen->screenSize();
928 //     memorymanager=new QMemoryManager(qt_screen->base()+screensize+4096,
929 //         qt_screen->totalSize()-(screensize+4096),0);
930 
931 // #ifndef QT_NO_QWS_MULTIPROCESS
932 //     rgnMan = new QWSRegionManager(pipe, csocket);
933 // #else
934 //     rgnMan = new QWSRegionManager(pipe, 0); //####### not necessary
935 // #endif
936 #ifndef QT_NO_QWS_MULTIPROCESS
937     if (csocket)
938         csocket->flush();
939 #endif
940 }
941 
942 
readMore()943 QWSEvent* QWSDisplay::Data::readMore()
944 {
945 #ifdef QT_NO_QWS_MULTIPROCESS
946     return incoming.isEmpty() ? 0 : incoming.takeFirst();
947 #else
948     if (!csocket)
949         return incoming.isEmpty() ? 0 : incoming.takeFirst();
950     // read next event
951     if (!current_event) {
952         int event_type = qws_read_uint(csocket);
953 
954         if (event_type >= 0) {
955             current_event = QWSEvent::factory(event_type);
956         }
957     }
958 
959     if (current_event) {
960         if (current_event->read(csocket)) {
961             // Finished reading a whole event.
962             QWSEvent* result = current_event;
963             current_event = 0;
964             return result;
965         }
966     }
967 
968     // Not finished reading a whole event.
969     return 0;
970 #endif
971 }
972 
fillQueue()973 void QWSDisplay::Data::fillQueue()
974 {
975     QWSServer::processEventQueue();
976     QWSEvent *e = readMore();
977 #ifndef QT_NO_QWS_MULTIPROCESS
978     int bytesAvailable = csocket ? csocket->bytesAvailable() : 0;
979     int bytesRead = 0;
980 #endif
981     while (e) {
982 #ifndef QT_NO_QWS_MULTIPROCESS
983         bytesRead += QWS_PROTOCOL_ITEM_SIZE((*e));
984 #endif
985         if (e->type == QWSEvent::Connected) {
986             connected_event = static_cast<QWSConnectedEvent *>(e);
987             return;
988         } else if (e->type == QWSEvent::Creation) {
989             QWSCreationEvent *ce = static_cast<QWSCreationEvent*>(e);
990             int id = ce->simpleData.objectid;
991             int count = ce->simpleData.count;
992             for (int i = 0; i < count; ++i)
993                 unused_identifiers.append(id++);
994             delete e;
995         } else if (e->type == QWSEvent::Mouse) {
996             if (!qt_screen) {
997                 delete e;
998             } else {
999                 QWSMouseEvent *me = static_cast<QWSMouseEvent*>(e);
1000                 if (mouseFilter)
1001                     mouseFilter(me);
1002 #ifdef QAPPLICATION_EXTRA_DEBUG
1003                 static const char *defaultAction= "INITIAL";
1004                 const char * action = defaultAction;
1005 #endif
1006                 delete mouse_event;
1007                 if (mouse_winid != me->window ()
1008                     || mouse_state != me->simpleData.state) {
1009                         queue.append(me);
1010                         mouse_winid = me->window();
1011                         mouse_state = me->simpleData.state;
1012                         mouse_event = 0;
1013 #ifdef QAPPLICATION_EXTRA_DEBUG
1014                         mouse_event_count = 0;
1015                         action = "ENQUEUE";
1016 #endif
1017                 } else {
1018 #ifdef QAPPLICATION_EXTRA_DEBUG
1019                     if (mouse_event)
1020                         action = "COMPRESS";
1021                     mouse_event_count++;
1022 #endif
1023                     mouse_event = me;
1024                 }
1025 #ifdef QAPPLICATION_EXTRA_DEBUG
1026                 if (me->simpleData.state !=0 || action != defaultAction || mouse_event_count != 0)
1027                     qDebug("fillQueue %s (%d,%d), state %x win %d count %d", action,
1028                            me->simpleData.x_root, me->simpleData.y_root, me->simpleData.state,
1029                            me->window(), mouse_event_count);
1030 #endif
1031             }
1032 #ifndef QT_NO_QWS_MULTIPROCESS
1033         } else if (e->type == QWSEvent::Region && clientLock) {
1034             // not really an unlock, decrements the semaphore
1035             region_events_count++;
1036             clientLock->unlock(QWSLock::RegionEvent);
1037             queue.append(e);
1038 #endif
1039 #ifndef QT_NO_QWS_PROPERTIES
1040         } else if (e->type == QWSEvent::PropertyReply) {
1041             QWSPropertyReplyEvent *pe = static_cast<QWSPropertyReplyEvent*>(e);
1042             int len = pe->simpleData.len;
1043             char *data;
1044             if (len <= 0) {
1045                 data = 0;
1046             } else {
1047                 data = new char[len];
1048                 memcpy(data, pe->data, len) ;
1049             }
1050             QPaintDevice::qwsDisplay()->getPropertyLen = len;
1051             QPaintDevice::qwsDisplay()->getPropertyData = data;
1052             delete e;
1053 #endif // QT_NO_QWS_PROPERTIES
1054         } else if (e->type==QWSEvent::MaxWindowRect && qt_screen) {
1055             // Process this ASAP, in case new widgets are created (startup)
1056             setMaxWindowRect((static_cast<QWSMaxWindowRectEvent*>(e))->simpleData.rect);
1057             delete e;
1058 #ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION
1059         } else if (e->type == QWSEvent::ScreenTransformation) {
1060             QWSScreenTransformationEvent *pe = static_cast<QWSScreenTransformationEvent*>(e);
1061             setScreenTransformation(pe->simpleData.screen,
1062                                     pe->simpleData.transformation);
1063             delete e;
1064 #endif
1065 #ifndef QT_NO_COP
1066         } else if (e->type == QWSEvent::QCopMessage) {
1067             QWSQCopMessageEvent *pe = static_cast<QWSQCopMessageEvent*>(e);
1068             if (pe->simpleData.is_response) {
1069                 qcop_response = pe;
1070             } else {
1071                 queue.append(e);
1072             }
1073 #endif
1074         } else {
1075             queue.append(e);
1076         }
1077         //debugQueue();
1078 #ifndef QT_NO_QWS_MULTIPROCESS
1079         if (csocket && bytesRead >= bytesAvailable)
1080             break;
1081 #endif
1082         e = readMore();
1083     }
1084 }
1085 
1086 #ifndef QT_NO_QWS_MULTIPROCESS
1087 
1088 static int qws_connection_timeout = 5;
1089 
connectToPipe()1090 void QWSDisplay::Data::connectToPipe()
1091 {
1092     Q_ASSERT(csocket);
1093 
1094     int timeout = qgetenv("QWS_CONNECTION_TIMEOUT").toInt();
1095     if (timeout)
1096         qws_connection_timeout = timeout;
1097 
1098     const QString pipe = qws_qtePipeFilename();
1099     int i = 0;
1100     while (!csocket->connectToLocalFile(pipe)) {
1101         if (++i > qws_connection_timeout) {
1102             qWarning("No Qt for Embedded Linux server appears to be running.");
1103             qWarning("If you want to run this program as a server,");
1104             qWarning("add the \"-qws\" command-line option.");
1105             exit(1);
1106         }
1107         sleep(1);
1108     }
1109 }
1110 
waitForConnection()1111 void QWSDisplay::Data::waitForConnection()
1112 {
1113     connected_event = 0;
1114 
1115     for (int i = 0; i < qws_connection_timeout; i++) {
1116         fillQueue();
1117         if (connected_event)
1118             return;
1119         csocket->flush();
1120         csocket->waitForReadyRead(1000);
1121     }
1122 
1123     csocket->flush();
1124     if (!connected_event)
1125         qFatal("Did not receive a connection event from the qws server");
1126 }
1127 
waitForRegionAck(int winId)1128 void QWSDisplay::Data::waitForRegionAck(int winId)
1129 {
1130     QWSEvent *ack = 0;
1131 
1132     if (csocket) { // GuiClient
1133         int i = 0;
1134         while (!ack) {
1135             fillQueue();
1136 
1137             while (i < queue.size()) {
1138                 QWSEvent *e = queue.at(i);
1139                 if (e->type == QWSEvent::Region && e->window() == winId) {
1140                     ack = e;
1141                     queue.removeAt(i);
1142                     break;
1143                 }
1144                 ++i;
1145             }
1146 
1147             if (!ack) {
1148                 csocket->flush();
1149                 csocket->waitForReadyRead(1000);
1150             }
1151         }
1152     } else { // GuiServer
1153         fillQueue();
1154         for (int i = 0; i < queue.size(); /* nothing */) {
1155             QWSEvent *e = queue.at(i);
1156             if (e->type == QWSEvent::Region && e->window() == winId) {
1157                 ack = e;
1158                 queue.removeAt(i);
1159                 break;
1160             }
1161             ++i;
1162         }
1163         if (!ack) // already processed
1164             return;
1165     }
1166 
1167     Q_ASSERT(ack);
1168 
1169     qApp->qwsProcessEvent(ack);
1170     delete ack;
1171     region_events_count--;
1172 }
1173 
waitForRegionEvents(int winId,bool ungrabDisplay)1174 void QWSDisplay::Data::waitForRegionEvents(int winId, bool ungrabDisplay)
1175 {
1176     if (!clientLock)
1177         return;
1178 
1179     int removedEventsCount = 0;
1180 
1181     // fill queue with unreceived region events
1182     if (!clientLock->hasLock(QWSLock::RegionEvent)) {
1183         bool ungrabbed = false;
1184         if (ungrabDisplay && QWSDisplay::grabbed()) {
1185             QWSDisplay::ungrab();
1186             ungrabbed = true;
1187         }
1188 
1189         for (;;) {
1190             fillQueue();
1191             if (clientLock->hasLock(QWSLock::RegionEvent))
1192                 break;
1193             csocket->flush();
1194             csocket->waitForReadyRead(1000);
1195         }
1196 
1197         if (ungrabbed)
1198             QWSDisplay::grab(true);
1199     }
1200 
1201     // check the queue for pending region events
1202     QWSEvent *regionEvent = 0;
1203     for (int i = 0; i < queue.size(); /* nothing */) {
1204         QWSEvent *e = queue.at(i);
1205         if (e->type == QWSEvent::Region && e->window() == winId) {
1206             QWSRegionEvent *re = static_cast<QWSRegionEvent*>(e);
1207             if (re->simpleData.type == QWSRegionEvent::Allocation) {
1208                 delete regionEvent;
1209                 regionEvent = re;
1210             }
1211             queue.removeAt(i);
1212             removedEventsCount++;
1213         } else {
1214             ++i;
1215         }
1216     }
1217 
1218     if (regionEvent) {
1219         qApp->qwsProcessEvent(regionEvent);
1220         delete regionEvent;
1221     }
1222     region_events_count -= removedEventsCount;
1223 }
1224 
hasPendingRegionEvents() const1225 bool QWSDisplay::Data::hasPendingRegionEvents() const
1226 {
1227     if (clientLock && !clientLock->hasLock(QWSLock::RegionEvent))
1228         return true;
1229 
1230     return region_events_count > 0;
1231 }
1232 
1233 #endif // QT_NO_QWS_MULTIPROCESS
1234 
waitForCreation()1235 void QWSDisplay::Data::waitForCreation()
1236 {
1237     fillQueue();
1238 #ifndef QT_NO_QWS_MULTIPROCESS
1239     while (unused_identifiers.count() == 0) {
1240         if (csocket) {
1241             csocket->flush();
1242             csocket->waitForReadyRead(1000);
1243         }
1244         fillQueue();
1245     }
1246 #endif
1247 }
1248 
1249 
1250 #ifndef QT_NO_QWS_MULTIPROCESS
waitForPropertyReply()1251 void QWSDisplay::Data::waitForPropertyReply()
1252 {
1253     if (!csocket)
1254         return;
1255     fillQueue();
1256     while (qt_fbdpy->getPropertyLen == -2) {
1257         csocket->flush();
1258         csocket->waitForReadyRead(1000);
1259         fillQueue();
1260     }
1261 }
1262 #endif
1263 
1264 #ifndef QT_NO_COP
waitForQCopResponse()1265 void QWSDisplay::Data::waitForQCopResponse()
1266 {
1267     for (;;) {
1268         fillQueue();
1269         if (qcop_response)
1270             break;
1271 #ifndef QT_NO_QWS_MULTIPROCESS
1272         if (csocket) {
1273             csocket->flush();
1274             csocket->waitForReadyRead(1000);
1275         }
1276 #endif
1277     }
1278     queue.prepend(qcop_response);
1279     qcop_response = 0;
1280 }
1281 #endif
1282 
1283 /*!
1284     \class QWSDisplay
1285     \brief The QWSDisplay class provides a display for QWS; it is an internal class.
1286 
1287     \internal
1288 
1289     \ingroup qws
1290 */
1291 
QWSDisplay()1292 QWSDisplay::QWSDisplay()
1293 {
1294     d = new Data(0, qws_single_process);
1295 }
1296 
~QWSDisplay()1297 QWSDisplay::~QWSDisplay()
1298 {
1299     delete d;
1300     delete lock;
1301     lock = 0;
1302 }
1303 
grabbed()1304 bool QWSDisplay::grabbed()
1305 {
1306     return lock->locked();
1307 }
1308 
grab()1309 void QWSDisplay::grab()
1310 {
1311     lock->lock(QLock::Read);
1312 }
1313 
grab(bool write)1314 void QWSDisplay::grab(bool write)
1315 {
1316     lock->lock(write ? QLock::Write : QLock::Read);
1317 
1318 }
ungrab()1319 void QWSDisplay::ungrab()
1320 {
1321     lock->unlock();
1322 }
1323 
1324 #if 0
1325 QWSRegionManager *QWSDisplay::regionManager() const
1326 {
1327     return d->rgnMan;
1328 }
1329 #endif
1330 
eventPending() const1331 bool QWSDisplay::eventPending() const
1332 {
1333 #ifndef QT_NO_QWS_MULTIPROCESS
1334     d->flush();
1335 #endif
1336     d->fillQueue();
1337     return d->queueNotEmpty();
1338 }
1339 
1340 
1341 /*
1342   Caller must delete return value!
1343  */
getEvent()1344 QWSEvent *QWSDisplay::getEvent()
1345 {
1346     d->fillQueue();
1347     Q_ASSERT(d->queueNotEmpty());
1348     QWSEvent* e = d->dequeue();
1349 
1350     return e;
1351 }
1352 
frameBuffer() const1353 uchar* QWSDisplay::frameBuffer() const { return qt_screen->base(); }
width() const1354 int QWSDisplay::width() const { return qt_screen->width(); }
height() const1355 int QWSDisplay::height() const { return qt_screen->height(); }
depth() const1356 int QWSDisplay::depth() const { return qt_screen->depth(); }
pixmapDepth() const1357 int QWSDisplay::pixmapDepth() const { return qt_screen->pixmapDepth(); }
supportsDepth(int depth) const1358 bool QWSDisplay::supportsDepth(int depth) const { return qt_screen->supportsDepth(depth); }
sharedRam() const1359 uchar *QWSDisplay::sharedRam() const { return d->sharedRam; }
sharedRamSize() const1360 int QWSDisplay::sharedRamSize() const { return d->sharedRamSize; }
1361 
1362 #ifndef QT_NO_QWS_PROPERTIES
1363 
addProperty(int winId,int property)1364 void QWSDisplay::addProperty(int winId, int property)
1365 {
1366     QWSAddPropertyCommand cmd;
1367     cmd.simpleData.windowid = winId;
1368     cmd.simpleData.property = property;
1369     d->sendCommand(cmd);
1370 }
1371 
setProperty(int winId,int property,int mode,const QByteArray & data)1372 void QWSDisplay::setProperty(int winId, int property, int mode, const QByteArray &data)
1373 {
1374     QWSSetPropertyCommand cmd;
1375     cmd.simpleData.windowid = winId;
1376     cmd.simpleData.property = property;
1377     cmd.simpleData.mode = mode;
1378     cmd.setData(data.constData(), data.size());
1379     d->sendCommand(cmd);
1380 }
1381 
setProperty(int winId,int property,int mode,const char * data)1382 void QWSDisplay::setProperty(int winId, int property, int mode,
1383                               const char * data)
1384 {
1385     QWSSetPropertyCommand cmd;
1386     cmd.simpleData.windowid = winId;
1387     cmd.simpleData.property = property;
1388     cmd.simpleData.mode = mode;
1389     cmd.setData(data, strlen(data));
1390     d->sendCommand(cmd);
1391 }
1392 
removeProperty(int winId,int property)1393 void QWSDisplay::removeProperty(int winId, int property)
1394 {
1395     QWSRemovePropertyCommand cmd;
1396     cmd.simpleData.windowid = winId;
1397     cmd.simpleData.property = property;
1398     d->sendCommand(cmd);
1399 }
1400 
1401 /*
1402     It is the caller's responsibility to delete[] \a data.
1403  */
getProperty(int winId,int property,char * & data,int & len)1404 bool QWSDisplay::getProperty(int winId, int property, char *&data, int &len)
1405 {
1406     if (d->directServerConnection()) {
1407         const char *propertyData;
1408         bool retval = qwsServer->d_func()->get_property(winId, property, propertyData, len);
1409         if (len <= 0) {
1410             data = 0;
1411         } else {
1412             data = new char[len];
1413             memcpy(data, propertyData, len) ;
1414         }
1415         return retval;
1416     }
1417     QWSGetPropertyCommand cmd;
1418     cmd.simpleData.windowid = winId;
1419     cmd.simpleData.property = property;
1420     d->sendCommand(cmd);
1421 
1422     getPropertyLen = -2;
1423     getPropertyData = 0;
1424 
1425 #ifndef QT_NO_QWS_MULTIPROCESS
1426     d->waitForPropertyReply();
1427 #endif
1428 
1429     len = getPropertyLen;
1430     data = getPropertyData;
1431 
1432     getPropertyLen = -2;
1433     getPropertyData = 0;
1434 
1435     return len != -1;
1436 }
1437 
1438 #endif // QT_NO_QWS_PROPERTIES
1439 
setAltitude(int winId,int alt,bool fixed)1440 void QWSDisplay::setAltitude(int winId, int alt, bool fixed)
1441 {
1442     QWSChangeAltitudeCommand cmd;
1443 #ifdef QT_DEBUG
1444     memset(cmd.simpleDataPtr, 0, sizeof(cmd.simpleData)); //shut up Valgrind
1445 #endif
1446     cmd.simpleData.windowid = winId;
1447     cmd.simpleData.altitude = QWSChangeAltitudeCommand::Altitude(alt);
1448     cmd.simpleData.fixed = fixed;
1449     if (d->directServerConnection()) {
1450         qwsServer->d_func()->set_altitude(&cmd);
1451     } else {
1452         d->sendSynchronousCommand(cmd);
1453     }
1454 }
1455 
setOpacity(int winId,int opacity)1456 void QWSDisplay::setOpacity(int winId, int opacity)
1457 {
1458     QWSSetOpacityCommand cmd;
1459     cmd.simpleData.windowid = winId;
1460     cmd.simpleData.opacity = opacity;
1461     if (d->directServerConnection()) {
1462         qwsServer->d_func()->set_opacity(&cmd);
1463     } else {
1464         d->sendCommand(cmd);
1465     }
1466 }
1467 
1468 
1469 
requestFocus(int winId,bool get)1470 void QWSDisplay::requestFocus(int winId, bool get)
1471 {
1472     QWSRequestFocusCommand cmd;
1473     cmd.simpleData.windowid = winId;
1474     cmd.simpleData.flag = get;
1475     if (d->directServerConnection())
1476         qwsServer->d_func()->request_focus(&cmd);
1477     else
1478         d->sendCommand(cmd);
1479 }
1480 
setIdentity(const QString & appName)1481 void QWSDisplay::setIdentity(const QString &appName)
1482 {
1483     QWSIdentifyCommand cmd;
1484 #ifdef QT_NO_QWS_MULTIPROCESS
1485     const int id = -1;
1486 #else
1487     const int id = QWSDisplay::Data::clientLock ? QWSDisplay::Data::clientLock->id() : -1;
1488 #endif
1489     cmd.setId(appName, id);
1490     if (d->directServerConnection())
1491         qwsServer->d_func()->set_identity(&cmd);
1492     else
1493         d->sendCommand(cmd);
1494 }
1495 
nameRegion(int winId,const QString & n,const QString & c)1496 void QWSDisplay::nameRegion(int winId, const QString& n, const QString &c)
1497 {
1498     QWSRegionNameCommand cmd;
1499     cmd.simpleData.windowid = winId;
1500     cmd.setName(n, c);
1501     if (d->directServerConnection())
1502         qwsServer->d_func()->name_region(&cmd);
1503     else
1504         d->sendCommand(cmd);
1505 }
1506 
requestRegion(int winId,const QString & surfaceKey,const QByteArray & surfaceData,const QRegion & region)1507 void QWSDisplay::requestRegion(int winId, const QString &surfaceKey,
1508                                const QByteArray &surfaceData,
1509                                const QRegion &region)
1510 {
1511     if (d->directServerConnection()) {
1512         qwsServer->d_func()->request_region(winId, surfaceKey,
1513                                             surfaceData, region);
1514     } else {
1515         QWSRegionCommand cmd;
1516         cmd.setData(winId, surfaceKey, surfaceData, region);
1517         d->sendSynchronousCommand(cmd);
1518     }
1519 }
1520 
repaintRegion(int winId,int windowFlags,bool opaque,QRegion r)1521 void QWSDisplay::repaintRegion(int winId, int windowFlags, bool opaque, QRegion r)
1522 {
1523     if (d->directServerConnection()) {
1524         qwsServer->d_func()->repaint_region(winId, windowFlags, opaque, r);
1525     } else {
1526         QVector<QRect> ra = r.rects();
1527 
1528         /*
1529           for (int i = 0; i < ra.size(); i++) {
1530           QRect r(ra[i]);
1531           qDebug("rect: %d %d %d %d", r.x(), r.y(), r.right(), r.bottom());
1532           }
1533         */
1534 
1535         QWSRepaintRegionCommand cmd;
1536     /* XXX QWSRegionCommand is padded out in a compiler dependent way.
1537        Zeroed out to avoid valgrind reporting uninitialized memory usage.
1538        */
1539 #ifdef QT_DEBUG
1540         memset(cmd.simpleDataPtr, 0, sizeof(cmd.simpleData)); //shut up Valgrind
1541 #endif
1542         cmd.simpleData.windowid = winId;
1543         cmd.simpleData.windowFlags = windowFlags;
1544         cmd.simpleData.opaque = opaque;
1545         cmd.simpleData.nrectangles = ra.count();
1546         cmd.setData(reinterpret_cast<const char *>(ra.constData()),
1547                     ra.count() * sizeof(QRect), false);
1548 
1549         d->sendSynchronousCommand(cmd);
1550     }
1551 }
1552 
1553 
moveRegion(int winId,int dx,int dy)1554 void QWSDisplay::moveRegion(int winId, int dx, int dy)
1555 {
1556     QWSRegionMoveCommand cmd;
1557     cmd.simpleData.windowid = winId;
1558     cmd.simpleData.dx = dx;
1559     cmd.simpleData.dy = dy;
1560 
1561     if (d->directServerConnection()) {
1562         qwsServer->d_func()->move_region(&cmd);
1563     } else {
1564         d->sendSynchronousCommand(cmd);
1565     }
1566 //    d->offsetPendingExpose(winId, QPoint(cmd.simpleData.dx, cmd.simpleData.dy));
1567 }
1568 
destroyRegion(int winId)1569 void QWSDisplay::destroyRegion(int winId)
1570 {
1571     QWSRegionDestroyCommand cmd;
1572     cmd.simpleData.windowid = winId;
1573     if (d->directServerConnection()) {
1574         qwsServer->d_func()->destroy_region(&cmd);
1575     } else {
1576         d->sendCommand(cmd);
1577     }
1578 }
1579 
1580 #ifndef QT_NO_QWS_INPUTMETHODS
1581 
sendIMUpdate(int type,int winId,int widgetid)1582 void QWSDisplay::sendIMUpdate(int type, int winId, int widgetid)
1583 {
1584     QWSIMUpdateCommand cmd;
1585     cmd.simpleData.windowid = winId;
1586     cmd.simpleData.widgetid = widgetid;
1587 
1588     cmd.simpleData.type = type;
1589 
1590       if (d->directServerConnection()) {
1591         qwsServer->d_func()->im_update(&cmd);
1592     } else {
1593         d->sendCommand(cmd);
1594     }
1595 }
1596 
sendIMResponse(int winId,int property,const QVariant & result)1597 void QWSDisplay::sendIMResponse(int winId, int property, const QVariant &result)
1598 {
1599     QWSIMResponseCommand cmd;
1600     cmd.simpleData.windowid = winId;
1601     cmd.simpleData.property = property;
1602 
1603     cmd.setResult(result);
1604 
1605     if (d->directServerConnection()) {
1606         qwsServer->d_func()->im_response(&cmd);
1607     } else {
1608         d->sendCommand(cmd);
1609     }
1610 }
1611 
resetIM()1612 void QWSDisplay::resetIM()
1613 {
1614     sendIMUpdate(QWSInputMethod::Reset, -1, -1);
1615 }
1616 
sendIMMouseEvent(int index,bool isPress)1617 void QWSDisplay::sendIMMouseEvent(int index, bool isPress)
1618 {
1619     QWSIMMouseCommand cmd;
1620     cmd.simpleData.index = index;
1621     cmd.simpleData.state = isPress ? QWSServer::MousePress : QWSServer::MouseRelease;
1622     if (d->directServerConnection()) {
1623         qwsServer->d_func()->send_im_mouse(&cmd);
1624     } else {
1625         d->sendCommand(cmd);
1626     }
1627 }
1628 
1629 #endif
1630 
takeId()1631 int QWSDisplay::takeId()
1632 {
1633     return d->takeId();
1634 }
1635 
initLock(const QString & filename,bool create)1636 bool QWSDisplay::initLock(const QString &filename, bool create)
1637 {
1638     if (!lock) {
1639         lock = new QLock(filename, 'd', create);
1640 
1641         if (!lock->isValid()) {
1642             delete lock;
1643             lock = 0;
1644             return false;
1645         }
1646     }
1647 
1648     return true;
1649 }
1650 
setSelectionOwner(int winId,const QTime & time)1651 void QWSDisplay::setSelectionOwner(int winId, const QTime &time)
1652 {
1653     QWSSetSelectionOwnerCommand cmd;
1654     cmd.simpleData.windowid = winId;
1655     cmd.simpleData.hour = time.hour();
1656     cmd.simpleData.minute = time.minute();
1657     cmd.simpleData.sec = time.second();
1658     cmd.simpleData.ms = time.msec();
1659     d->sendCommand(cmd);
1660 }
1661 
convertSelection(int winId,int selectionProperty,const QString & mimeTypes)1662 void QWSDisplay::convertSelection(int winId, int selectionProperty, const QString &mimeTypes)
1663 {
1664 #ifdef QT_NO_QWS_PROPERTIES
1665     Q_UNUSED(mimeTypes);
1666 #else
1667     // ### we need the atom/property thingy like in X here
1668     addProperty(winId, QT_QWS_PROPERTY_CONVERTSELECTION);
1669     setProperty(winId, QT_QWS_PROPERTY_CONVERTSELECTION,
1670                  int(QWSPropertyManager::PropReplace), mimeTypes.toLatin1());
1671 #endif
1672     QWSConvertSelectionCommand cmd;
1673     cmd.simpleData.requestor = winId;
1674     cmd.simpleData.selection = selectionProperty;
1675     cmd.simpleData.mimeTypes = QT_QWS_PROPERTY_CONVERTSELECTION;
1676     d->sendCommand(cmd);
1677 }
1678 
defineCursor(int id,const QBitmap & curs,const QBitmap & mask,int hotX,int hotY)1679 void QWSDisplay::defineCursor(int id, const QBitmap &curs, const QBitmap &mask,
1680                             int hotX, int hotY)
1681 {
1682     const QImage cursImg = curs.toImage().convertToFormat(QImage::Format_MonoLSB);
1683     const QImage maskImg = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
1684 
1685     QWSDefineCursorCommand cmd;
1686     cmd.simpleData.width = curs.width();
1687     cmd.simpleData.height = curs.height();
1688     cmd.simpleData.hotX = hotX;
1689     cmd.simpleData.hotY = hotY;
1690     cmd.simpleData.id = id;
1691 
1692 
1693     // must copy each scanline since there might be gaps between them
1694     const int height = curs.height();
1695     const int width = curs.width();
1696     const int dst_bpl = (width + 7) / 8;
1697 
1698     int dataLen = dst_bpl * height;
1699     uchar *data = new uchar[dataLen*2];
1700     uchar *dst = data;
1701 
1702     int src_bpl = cursImg.bytesPerLine();
1703     const uchar *cursSrc = cursImg.bits();
1704     for (int i = 0; i < height; ++i) {
1705         memcpy(dst, cursSrc + i*src_bpl, dst_bpl);
1706         dst += dst_bpl;
1707     }
1708 
1709     src_bpl = maskImg.bytesPerLine();
1710     const uchar *maskSrc = maskImg.bits();
1711     for (int i = 0; i < height; ++i) {
1712         memcpy(dst, maskSrc + i*src_bpl, dst_bpl);
1713         dst += dst_bpl;
1714     }
1715 
1716     cmd.setData(reinterpret_cast<char*>(data), dataLen*2);
1717     delete [] data;
1718     d->sendCommand(cmd);
1719 }
1720 
destroyCursor(int id)1721 void QWSDisplay::destroyCursor(int id)
1722 {
1723     QWSDefineCursorCommand cmd;
1724     cmd.simpleData.width = 0;
1725     cmd.simpleData.height = 0;
1726     cmd.simpleData.hotX = 0;
1727     cmd.simpleData.hotY = 0;
1728     cmd.simpleData.id = id;
1729     cmd.setData(0, 0);
1730 
1731     d->sendCommand(cmd);
1732 }
1733 
1734 #ifndef QT_NO_SOUND
playSoundFile(const QString & f)1735 void QWSDisplay::playSoundFile(const QString& f)
1736 {
1737     QWSPlaySoundCommand cmd;
1738     cmd.setFileName(f);
1739     d->sendCommand(cmd);
1740 }
1741 #endif
1742 
1743 #ifndef QT_NO_COP
registerChannel(const QString & channel)1744 void QWSDisplay::registerChannel(const QString& channel)
1745 {
1746     QWSQCopRegisterChannelCommand reg;
1747     reg.setChannel(channel);
1748     qt_fbdpy->d->sendCommand(reg);
1749 }
1750 
sendMessage(const QString & channel,const QString & msg,const QByteArray & data)1751 void QWSDisplay::sendMessage(const QString &channel, const QString &msg,
1752                    const QByteArray &data)
1753 {
1754     QWSQCopSendCommand com;
1755     com.setMessage(channel, msg, data);
1756     qt_fbdpy->d->sendCommand(com);
1757 }
1758 
flushCommands()1759 void QWSDisplay::flushCommands()
1760 {
1761     qt_fbdpy->d->flushCommands();
1762 }
1763 
1764 /*
1765   caller deletes result
1766 */
waitForQCopResponse()1767 QWSQCopMessageEvent* QWSDisplay::waitForQCopResponse()
1768 {
1769     qt_fbdpy->d->waitForQCopResponse();
1770     QWSQCopMessageEvent *e = static_cast<QWSQCopMessageEvent*>(qt_fbdpy->d->dequeue());
1771     Q_ASSERT(e->type == QWSEvent::QCopMessage);
1772     return e;
1773 }
1774 #endif
1775 
sendFontCommand(int type,const QByteArray & fontName)1776 void QWSDisplay::sendFontCommand(int type, const QByteArray &fontName)
1777 {
1778     QWSFontCommand cmd;
1779     cmd.simpleData.type = type;
1780     cmd.setFontName(fontName);
1781     d->sendCommand(cmd);
1782 }
1783 
setWindowCaption(QWidget * w,const QString & c)1784 void QWSDisplay::setWindowCaption(QWidget *w, const QString &c)
1785 {
1786     if (w->isWindow()) {
1787         nameRegion(w->internalWinId(), w->objectName(), c);
1788         static_cast<QETWidget *>(w)->repaintDecoration(qApp->desktop()->rect(), true);
1789     }
1790 }
1791 
selectCursor(QWidget * w,unsigned int cursId)1792 void QWSDisplay::selectCursor(QWidget *w, unsigned int cursId)
1793 {
1794     if (cursId != qt_last_cursor)
1795     {
1796         QWidget *top = w->window();
1797         qt_last_cursor = cursId;
1798         QWSSelectCursorCommand cmd;
1799         cmd.simpleData.windowid = top->internalWinId();
1800         cmd.simpleData.id = cursId;
1801         d->sendCommand(cmd);
1802         d->flush();
1803     }
1804 }
1805 
setCursorPosition(int x,int y)1806 void QWSDisplay::setCursorPosition(int x, int y)
1807 {
1808     QWSPositionCursorCommand cmd;
1809     cmd.simpleData.newX = x;
1810     cmd.simpleData.newY = y;
1811     d->sendCommand(cmd);
1812     d->flush();
1813 }
1814 
grabMouse(QWidget * w,bool grab)1815 void QWSDisplay::grabMouse(QWidget *w, bool grab)
1816 {
1817     QWidget *top = w->window();
1818     QWSGrabMouseCommand cmd;
1819 #ifdef QT_DEBUG
1820     memset(cmd.simpleDataPtr, 0, sizeof(cmd.simpleData)); //shut up Valgrind
1821 #endif
1822     cmd.simpleData.windowid = top->winId();
1823     cmd.simpleData.grab = grab;
1824     d->sendCommand(cmd);
1825     d->flush();
1826 }
1827 
grabKeyboard(QWidget * w,bool grab)1828 void QWSDisplay::grabKeyboard(QWidget *w, bool grab)
1829 {
1830     QWidget *top = w->window();
1831     QWSGrabKeyboardCommand cmd;
1832 #ifdef QT_DEBUG
1833     memset(cmd.simpleDataPtr, 0, sizeof(cmd.simpleData)); //shut up Valgrind
1834 #endif
1835     cmd.simpleData.windowid = top->winId();
1836     cmd.simpleData.grab = grab;
1837     d->sendCommand(cmd);
1838     d->flush();
1839 }
1840 
windowList()1841 QList<QWSWindowInfo> QWSDisplay::windowList()
1842 {
1843     QList<QWSWindowInfo> ret;
1844     if(d->directServerConnection()) {
1845         QList<QWSInternalWindowInfo*> * qin=QWSServer::windowList();
1846         for (int i = 0; i < qin->count(); ++i) {
1847             QWSInternalWindowInfo * qwi = qin->at(i);
1848             QWSWindowInfo tmp;
1849             tmp.winid = qwi->winid;
1850             tmp.clientid = qwi->clientid;
1851             tmp.name = QString(qwi->name);
1852             ret.append(tmp);
1853         }
1854         qDeleteAll(*qin);
1855         delete qin;
1856     }
1857     return ret;
1858 }
1859 
windowAt(const QPoint & p)1860 int QWSDisplay::windowAt(const QPoint &p)
1861 {
1862     //### currently only implemented for the server process
1863     int ret = 0;
1864     if(d->directServerConnection()) {
1865         QWSWindow *win = qwsServer->windowAt(p);
1866         if (win)
1867             return win->winId();
1868     }
1869     return ret;
1870 }
1871 
setRawMouseEventFilter(void (* filter)(QWSMouseEvent *))1872 void QWSDisplay::setRawMouseEventFilter(void (*filter)(QWSMouseEvent *))
1873 {
1874     if (qt_fbdpy)
1875         qt_fbdpy->d->setMouseFilter(filter);
1876 }
1877 
1878 /*!
1879   \relates QScreen
1880 
1881   Here it is. \a transformation and \a screenNo
1882  */
setTransformation(int transformation,int screenNo)1883 void QWSDisplay::setTransformation(int transformation, int screenNo)
1884 {
1885     QWSScreenTransformCommand cmd;
1886     cmd.setTransformation(screenNo, transformation);
1887     QWSDisplay::instance()->d->sendCommand(cmd);
1888 }
1889 
1890 static bool qt_try_modal(QWidget *, QWSEvent *);
1891 
1892 /*****************************************************************************
1893   qt_init() - initializes Qt/FB
1894  *****************************************************************************/
1895 
qt_set_qws_resources()1896 static void qt_set_qws_resources()
1897 
1898 {
1899     if (QApplication::desktopSettingsAware())
1900         QApplicationPrivate::qws_apply_settings();
1901 
1902     if (appFont)
1903         QApplication::setFont(QFont(QString::fromLocal8Bit(appFont)));
1904 
1905     if (appBGCol || appBTNCol || appFGCol) {
1906         (void) QApplication::style();  // trigger creation of application style and system palettes
1907         QColor btn;
1908         QColor bg;
1909         QColor fg;
1910         if (appBGCol)
1911             bg = QColor(appBGCol);
1912         else
1913             bg = QApplicationPrivate::sys_pal->color(QPalette::Window);
1914         if (appFGCol)
1915             fg = QColor(appFGCol);
1916         else
1917             fg = QApplicationPrivate::sys_pal->color(QPalette::WindowText);
1918         if (appBTNCol)
1919             btn = QColor(appBTNCol);
1920         else
1921             btn = QApplicationPrivate::sys_pal->color(QPalette::Button);
1922 
1923         int h,s,v;
1924         fg.getHsv(&h,&s,&v);
1925         QColor base = Qt::white;
1926         bool bright_mode = false;
1927         if (v >= 255 - 50) {
1928             base = btn.darker(150);
1929             bright_mode = true;
1930         }
1931 
1932         QPalette pal(fg, btn, btn.lighter(), btn.darker(), btn.darker(150), fg, Qt::white, base, bg);
1933         if (bright_mode) {
1934             pal.setColor(QPalette::HighlightedText, base);
1935             pal.setColor(QPalette::Highlight, Qt::white);
1936         } else {
1937             pal.setColor(QPalette::HighlightedText, Qt::white);
1938             pal.setColor(QPalette::Highlight, Qt::darkBlue);
1939         }
1940         QColor disabled((fg.red()   + btn.red())  / 2,
1941                         (fg.green() + btn.green())/ 2,
1942                         (fg.blue()  + btn.blue()) / 2);
1943         pal.setColorGroup(QPalette::Disabled, disabled, btn, btn.lighter(125),
1944                           btn.darker(), btn.darker(150), disabled, Qt::white, Qt::white, bg);
1945         if (bright_mode) {
1946             pal.setColor(QPalette::Disabled, QPalette::HighlightedText, base);
1947             pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::white);
1948         } else {
1949             pal.setColor(QPalette::Disabled, QPalette::HighlightedText, Qt::white);
1950             pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::darkBlue);
1951         }
1952         QApplicationPrivate::setSystemPalette(pal);
1953 
1954     }
1955 }
1956 
initializeWidgetPaletteHash()1957 void QApplicationPrivate::initializeWidgetPaletteHash()
1958 {
1959 }
1960 
1961 /*! \internal
1962     apply the settings to the application
1963 */
qws_apply_settings()1964 bool QApplicationPrivate::qws_apply_settings()
1965 {
1966 #ifndef QT_NO_SETTINGS
1967     QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
1968     settings.beginGroup(QLatin1String("Qt"));
1969 
1970     QStringList strlist;
1971     int i;
1972     QPalette pal(Qt::black);
1973     int groupCount = 0;
1974     strlist = settings.value(QLatin1String("Palette/active")).toStringList();
1975     if (strlist.count() == QPalette::NColorRoles) {
1976         ++groupCount;
1977         for (i = 0; i < QPalette::NColorRoles; i++)
1978             pal.setColor(QPalette::Active, (QPalette::ColorRole) i,
1979                          QColor(strlist[i]));
1980     }
1981     strlist = settings.value(QLatin1String("Palette/inactive")).toStringList();
1982     if (strlist.count() == QPalette::NColorRoles) {
1983         ++groupCount;
1984         for (i = 0; i < QPalette::NColorRoles; i++)
1985             pal.setColor(QPalette::Inactive, (QPalette::ColorRole) i,
1986                          QColor(strlist[i]));
1987     }
1988     strlist = settings.value(QLatin1String("Palette/disabled")).toStringList();
1989     if (strlist.count() == QPalette::NColorRoles) {
1990         ++groupCount;
1991         for (i = 0; i < QPalette::NColorRoles; i++)
1992             pal.setColor(QPalette::Disabled, (QPalette::ColorRole) i,
1993                          QColor(strlist[i]));
1994     }
1995 
1996 
1997     if (groupCount == QPalette::NColorGroups)
1998         QApplicationPrivate::setSystemPalette(pal);
1999 
2000     QString str = settings.value(QLatin1String("font")).toString();
2001     if (!str.isEmpty()) {
2002         QFont font(QApplication::font());
2003         font.fromString(str);
2004         QApplicationPrivate::setSystemFont(font);
2005     }
2006 
2007     // read library (ie. plugin) path list
2008     QString libpathkey =
2009         QString::fromLatin1("%1.%2/libraryPath")
2010         .arg(QT_VERSION >> 16)
2011         .arg((QT_VERSION & 0xff00) >> 8);
2012     QStringList pathlist = settings.value(libpathkey).toString().split(QLatin1Char(':'));
2013 #ifndef QT_NO_LIBRARY
2014     if (! pathlist.isEmpty()) {
2015         QStringList::ConstIterator it = pathlist.constBegin();
2016         while (it != pathlist.constEnd())
2017             QApplication::addLibraryPath(*it++);
2018     }
2019 #endif
2020 
2021     // read new QStyle
2022     QString stylename = settings.value(QLatin1String("style")).toString();
2023     if (QCoreApplication::startingUp()) {
2024         if (!stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull())
2025             QApplicationPrivate::styleOverride = stylename;
2026     } else {
2027         QApplication::setStyle(stylename);
2028     }
2029 
2030     int num =
2031         settings.value(QLatin1String("doubleClickInterval"),
2032                        QApplication::doubleClickInterval()).toInt();
2033     QApplication::setDoubleClickInterval(num);
2034 
2035     num =
2036         settings.value(QLatin1String("cursorFlashTime"),
2037                        QApplication::cursorFlashTime()).toInt();
2038     QApplication::setCursorFlashTime(num);
2039 
2040 #ifndef QT_NO_WHEELEVENT
2041     num =
2042         settings.value(QLatin1String("wheelScrollLines"),
2043                        QApplication::wheelScrollLines()).toInt();
2044     QApplication::setWheelScrollLines(num);
2045 #endif
2046 
2047     QString colorspec = settings.value(QLatin1String("colorSpec"),
2048                                        QVariant(QLatin1String("default"))).toString();
2049     if (colorspec == QLatin1String("normal"))
2050         QApplication::setColorSpec(QApplication::NormalColor);
2051     else if (colorspec == QLatin1String("custom"))
2052         QApplication::setColorSpec(QApplication::CustomColor);
2053     else if (colorspec == QLatin1String("many"))
2054         QApplication::setColorSpec(QApplication::ManyColor);
2055     else if (colorspec != QLatin1String("default"))
2056         colorspec = QLatin1String("default");
2057 
2058 #ifndef QT_NO_TEXTCODEC
2059     QString defaultcodec = settings.value(QLatin1String("defaultCodec"),
2060                                           QVariant(QLatin1String("none"))).toString();
2061     if (defaultcodec != QLatin1String("none")) {
2062         QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1());
2063         if (codec)
2064             QTextCodec::setCodecForTr(codec);
2065     }
2066 #endif
2067 
2068     int w = settings.value(QLatin1String("globalStrut/width")).toInt();
2069     int h = settings.value(QLatin1String("globalStrut/height")).toInt();
2070     QSize strut(w, h);
2071     if (strut.isValid())
2072         QApplication::setGlobalStrut(strut);
2073 
2074     QStringList effects = settings.value(QLatin1String("GUIEffects")).toStringList();
2075     QApplication::setEffectEnabled(Qt::UI_General,
2076                                    effects.contains(QLatin1String("general")));
2077     QApplication::setEffectEnabled(Qt::UI_AnimateMenu,
2078                                    effects.contains(QLatin1String("animatemenu")));
2079     QApplication::setEffectEnabled(Qt::UI_FadeMenu,
2080                                    effects.contains(QLatin1String("fademenu")));
2081     QApplication::setEffectEnabled(Qt::UI_AnimateCombo,
2082                                    effects.contains(QLatin1String("animatecombo")));
2083     QApplication::setEffectEnabled(Qt::UI_AnimateTooltip,
2084                                    effects.contains(QLatin1String("animatetooltip")));
2085     QApplication::setEffectEnabled(Qt::UI_FadeTooltip,
2086                                    effects.contains(QLatin1String("fadetooltip")));
2087     QApplication::setEffectEnabled(Qt::UI_AnimateToolBox,
2088                                    effects.contains(QLatin1String("animatetoolbox")));
2089 
2090     settings.beginGroup(QLatin1String("Font Substitutions"));
2091     QStringList fontsubs = settings.childKeys();
2092     if (!fontsubs.isEmpty()) {
2093         QStringList::Iterator it = fontsubs.begin();
2094         for (; it != fontsubs.end(); ++it) {
2095             QString fam = *it;
2096             QStringList subs = settings.value(fam).toStringList();
2097             QFont::insertSubstitutions(fam, subs);
2098         }
2099     }
2100     settings.endGroup();
2101 
2102     settings.endGroup(); // Qt
2103 
2104     settings.beginGroup(QLatin1String("QWS Font Fallbacks"));
2105     if (!settings.childKeys().isEmpty()) {
2106         // from qfontdatabase_qws.cpp
2107         extern void qt_applyFontDatabaseSettings(const QSettings &);
2108         qt_applyFontDatabaseSettings(settings);
2109     }
2110     settings.endGroup();
2111 
2112     return true;
2113 #else
2114     return false;
2115 #endif // QT_NO_SETTINGS
2116 }
2117 
2118 
2119 
init_display()2120 static void init_display()
2121 {
2122     if (qt_fbdpy) return; // workaround server==client case
2123 
2124     // Connect to FB server
2125     qt_fbdpy = new QWSDisplay();
2126 
2127     // Get display parameters
2128     // Set paintdevice parameters
2129     // XXX initial info sent from server
2130     // Misc. initialization
2131 
2132     QColormap::initialize();
2133     QFont::initialize();
2134 #ifndef QT_NO_CURSOR
2135     QCursorData::initialize();
2136 #endif
2137 
2138     qApp->setObjectName(appName);
2139 
2140     if (!QApplicationPrivate::sys_font) {
2141 #ifdef QT_NO_FREETYPE
2142         QFont f = QFont(QLatin1String("helvetica"), 10);
2143 #else
2144         QFont f = QFont(QLatin1String("DejaVu Sans"), 12);
2145 #endif
2146         QApplicationPrivate::setSystemFont(f);
2147     }
2148     qt_set_qws_resources();
2149 }
2150 
qt_init_display()2151 void qt_init_display()
2152 {
2153     qt_is_gui_used = true;
2154     qws_single_process = true;
2155     init_display();
2156 }
2157 
read_bool_env_var(const char * var,bool defaultvalue)2158 static bool read_bool_env_var(const char *var, bool defaultvalue)
2159 {
2160     // returns true if env variable is set to non-zero
2161     // returns false if env var is set to zero
2162     // returns defaultvalue if env var not set
2163     char *x = ::getenv(var);
2164     return (x && *x) ? (strcmp(x,"0") != 0) : defaultvalue;
2165 }
2166 
read_int_env_var(const char * var,int defaultvalue)2167 static int read_int_env_var(const char *var, int defaultvalue)
2168 {
2169     bool ok;
2170     int r = qgetenv(var).toInt(&ok);
2171     return ok ? r : defaultvalue;
2172 }
2173 
qt_init(QApplicationPrivate * priv,int type)2174 void qt_init(QApplicationPrivate *priv, int type)
2175 {
2176 #ifdef QT_NO_QWS_MULTIPROCESS
2177     if (type == QApplication::GuiClient)
2178         type = QApplication::GuiServer;
2179 #endif
2180     if (type == QApplication::GuiServer)
2181         qt_is_gui_used = false; //we'll turn it on in a second
2182     qws_sw_cursor = read_bool_env_var("QWS_SW_CURSOR",qws_sw_cursor);
2183     qws_screen_is_interlaced = read_bool_env_var("QWS_INTERLACE",false);
2184 
2185     const char *display = ::getenv("QWS_DISPLAY");
2186 
2187 #ifdef QT_QWS_DEFAULT_DRIVER_NAME
2188     if (!display) display = QT_QWS_DEFAULT_DRIVER_NAME;
2189 #endif
2190 
2191     if (display)
2192         qws_display_spec = display; // since we setenv later!
2193 
2194     //qws_savefonts = qgetenv("QWS_SAVEFONTS") != 0;
2195     //qws_shared_memory = qgetenv("QWS_NOSHARED") == 0;
2196 
2197     mouse_double_click_distance = read_int_env_var("QWS_DBLCLICK_DISTANCE", 5);
2198 
2199     priv->inputContext = 0;
2200 
2201     int flags = 0;
2202     char *p;
2203     int argc = priv->argc;
2204     char **argv = priv->argv;
2205     int j;
2206 
2207     // Set application name
2208 
2209     if (argv && *argv) { //apparently, we allow people to pass 0 on the other platforms
2210         p = strrchr(argv[0], '/');
2211         appName = QString::fromLocal8Bit(p ? p + 1 : argv[0]);
2212     }
2213 
2214     // Get command line params
2215 
2216     j = argc ? 1 : 0;
2217     QString decoration;
2218     for (int i=1; i<argc; i++) {
2219         if (argv[i] && *argv[i] != '-') {
2220             argv[j++] = argv[i];
2221             continue;
2222         }
2223         QByteArray arg = argv[i];
2224         if (arg == "-fn" || arg == "-font") {
2225             if (++i < argc)
2226                 appFont = argv[i];
2227         } else if (arg == "-bg" || arg == "-background") {
2228             if (++i < argc)
2229                 appBGCol = argv[i];
2230         } else if (arg == "-btn" || arg == "-button") {
2231             if (++i < argc)
2232                 appBTNCol = argv[i];
2233         } else if (arg == "-fg" || arg == "-foreground") {
2234             if (++i < argc)
2235                 appFGCol = argv[i];
2236         } else if (arg == "-name") {
2237             if (++i < argc)
2238                 appName = QString::fromLocal8Bit(argv[i]);
2239         } else if (arg == "-title") {
2240             if (++i < argc)
2241                 mwTitle = argv[i];
2242         } else if (arg == "-geometry") {
2243             if (++i < argc)
2244                 mwGeometry = argv[i];
2245         } else if (arg == "-shared") {
2246             qws_shared_memory = true;
2247         } else if (arg == "-noshared") {
2248             qws_shared_memory = false;
2249         } else if (arg == "-savefonts") {
2250             qws_savefonts = true;
2251         } else if (arg == "-nosavefonts") {
2252             qws_savefonts = false;
2253         } else if (arg == "-swcursor") {
2254             qws_sw_cursor = true;
2255         } else if (arg == "-noswcursor") {
2256             qws_sw_cursor = false;
2257         } else if (arg == "-keyboard") {
2258             flags &= ~QWSServer::DisableKeyboard;
2259         } else if (arg == "-nokeyboard") {
2260             flags |= QWSServer::DisableKeyboard;
2261         } else if (arg == "-mouse") {
2262             flags &= ~QWSServer::DisableMouse;
2263         } else if (arg == "-nomouse") {
2264             flags |= QWSServer::DisableMouse;
2265         } else if (arg == "-qws") {
2266             type = QApplication::GuiServer;
2267         } else if (arg == "-interlaced") {
2268             qws_screen_is_interlaced = true;
2269         } else if (arg == "-display") {
2270             if (++i < argc)
2271                 qws_display_spec = argv[i];
2272         } else if (arg == "-decoration") {
2273             if (++i < argc)
2274                 decoration = QString::fromLocal8Bit(argv[i]);
2275         } else {
2276             argv[j++] = argv[i];
2277         }
2278     }
2279     if(j < priv->argc) {
2280         priv->argv[j] = 0;
2281         priv->argc = j;
2282     }
2283 
2284     mouseInWidget = new QPointer<QWidget>;
2285 
2286     const QString disp = QString::fromLatin1(qws_display_spec);
2287     QRegExp regexp(QLatin1String(":(\\d+)$"));
2288     if (regexp.lastIndexIn(disp) != -1) {
2289         const QString capture = regexp.cap(1);
2290         bool ok = false;
2291         int id = capture.toInt(&ok);
2292         if (ok)
2293             qws_display_id = id;
2294     }
2295 
2296     if (type == QApplication::GuiServer) {
2297         qt_appType = QApplication::Type(type);
2298         qws_single_process = true;
2299         QWSServer::startup(flags);
2300         if (!display) // if not already set
2301             qputenv("QWS_DISPLAY", qws_display_spec);
2302     }
2303 
2304     if(qt_is_gui_used) {
2305         init_display();
2306 #ifndef QT_NO_QWS_MANAGER
2307         if (decoration.isEmpty() && !qws_decoration) {
2308             const QStringList keys = QDecorationFactory::keys();
2309             if (!keys.isEmpty())
2310                 decoration = keys.first();
2311         }
2312         if (!decoration.isEmpty())
2313             qws_decoration = QApplication::qwsSetDecoration(decoration);
2314 #endif // QT_NO_QWS_MANAGER
2315 #ifndef QT_NO_QWS_INPUTMETHODS
2316         qApp->setInputContext(new QWSInputContext(qApp));
2317 #endif
2318     }
2319 
2320 /*### convert interlace style
2321     if (qws_screen_is_interlaced)
2322         QApplication::setStyle(new QInterlaceStyle);
2323 */
2324 }
2325 
2326 /*****************************************************************************
2327   qt_cleanup() - cleans up when the application is finished
2328  *****************************************************************************/
2329 
qt_cleanup()2330 void qt_cleanup()
2331 {
2332     QPixmapCache::clear();
2333 #ifndef QT_NO_CURSOR
2334     QCursorData::cleanup();
2335 #endif
2336     QFont::cleanup();
2337     QColormap::cleanup();
2338 
2339     if (qws_single_process) {
2340         QWSServer::closedown();
2341     }
2342 
2343     qDeleteAll(outgoing);
2344     outgoing.clear();
2345     qDeleteAll(incoming);
2346     incoming.clear();
2347 
2348     if (qt_is_gui_used) {
2349         delete qt_fbdpy;
2350     }
2351     qt_fbdpy = 0;
2352 
2353 #ifndef QT_NO_QWS_MANAGER
2354     delete qws_decoration;
2355     qws_decoration = 0;
2356 #endif
2357 
2358     delete mouseInWidget;
2359     mouseInWidget = 0;
2360 
2361 #if !defined(QT_NO_IM)
2362     delete QApplicationPrivate::inputContext;
2363     QApplicationPrivate::inputContext = 0;
2364 #endif
2365 }
2366 
2367 
2368 /*****************************************************************************
2369   Platform specific global and internal functions
2370  *****************************************************************************/
2371 
appName() const2372 QString QApplicationPrivate::appName() const // get application name
2373 {
2374     return QT_PREPEND_NAMESPACE(appName);
2375 }
2376 
2377 /*****************************************************************************
2378   Platform specific QApplication members
2379  *****************************************************************************/
2380 
2381 #define NoValue         0x0000
2382 #define XValue          0x0001
2383 #define YValue          0x0002
2384 #define WidthValue      0x0004
2385 #define HeightValue     0x0008
2386 #define AllValues       0x000F
2387 #define XNegative       0x0010
2388 #define YNegative       0x0020
2389 
2390 /* Copyright notice for ReadInteger and parseGeometry
2391 
2392 Copyright (c) 1985, 1986, 1987  X Consortium
2393 
2394 Permission is hereby granted, free of charge, to any person obtaining
2395 a copy of this software and associated documentation files (the
2396 "Software"), to deal in the Software without restriction, including
2397 without limitation the rights to use, copy, modify, merge, publish,
2398 distribute, sublicense, and/or sell copies of the Software, and to
2399 permit persons to whom the Software is furnished to do so, subject to
2400 the following conditions:
2401 
2402 The above copyright notice and this permission notice shall be included
2403 in all copies or substantial portions of the Software.
2404 
2405 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2406 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2407 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2408 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
2409 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2410 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2411 OTHER DEALINGS IN THE SOFTWARE.
2412 
2413 Except as contained in this notice, the name of the X Consortium shall
2414 not be used in advertising or otherwise to promote the sale, use or
2415 other dealings in this Software without prior written authorization
2416 from the X Consortium.
2417 
2418 */
2419 /*
2420  *    XParseGeometry parses strings of the form
2421  *   "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
2422  *   width, height, xoffset, and yoffset are unsigned integers.
2423  *   Example:  "=80x24+300-49"
2424  *   The equal sign is optional.
2425  *   It returns a bitmask that indicates which of the four values
2426  *   were actually found in the string. For each value found,
2427  *   the corresponding argument is updated;  for each value
2428  *   not found, the corresponding argument is left unchanged.
2429  */
2430 
2431 static int
ReadInteger(char * string,char ** NextString)2432 ReadInteger(char *string, char **NextString)
2433 {
2434     register int Result = 0;
2435     int Sign = 1;
2436 
2437     if (*string == '+')
2438         string++;
2439     else if (*string == '-')
2440     {
2441         string++;
2442         Sign = -1;
2443     }
2444     for (; (*string >= '0') && (*string <= '9'); string++)
2445     {
2446         Result = (Result * 10) + (*string - '0');
2447     }
2448     *NextString = string;
2449     if (Sign >= 0)
2450         return Result;
2451     else
2452         return -Result;
2453 }
2454 
parseGeometry(const char * string,int * x,int * y,int * width,int * height)2455 static int parseGeometry(const char* string,
2456                           int* x, int* y, int* width, int* height)
2457 {
2458         int mask = NoValue;
2459         register char *strind;
2460         unsigned int tempWidth=0, tempHeight=0;
2461         int tempX=0, tempY=0;
2462         char *nextCharacter;
2463 
2464         if (!string || (*string == '\0')) return mask;
2465         if (*string == '=')
2466                 string++;  /* ignore possible '=' at beg of geometry spec */
2467 
2468         strind = const_cast<char *>(string);
2469         if (*strind != '+' && *strind != '-' && *strind != 'x') {
2470                 tempWidth = ReadInteger(strind, &nextCharacter);
2471                 if (strind == nextCharacter)
2472                     return 0;
2473                 strind = nextCharacter;
2474                 mask |= WidthValue;
2475         }
2476 
2477         if (*strind == 'x' || *strind == 'X') {
2478                 strind++;
2479                 tempHeight = ReadInteger(strind, &nextCharacter);
2480                 if (strind == nextCharacter)
2481                     return 0;
2482                 strind = nextCharacter;
2483                 mask |= HeightValue;
2484         }
2485 
2486         if ((*strind == '+') || (*strind == '-')) {
2487                 if (*strind == '-') {
2488                         strind++;
2489                         tempX = -ReadInteger(strind, &nextCharacter);
2490                         if (strind == nextCharacter)
2491                             return 0;
2492                         strind = nextCharacter;
2493                         mask |= XNegative;
2494 
2495                 }
2496                 else
2497                 {        strind++;
2498                         tempX = ReadInteger(strind, &nextCharacter);
2499                         if (strind == nextCharacter)
2500                             return 0;
2501                         strind = nextCharacter;
2502                 }
2503                 mask |= XValue;
2504                 if ((*strind == '+') || (*strind == '-')) {
2505                         if (*strind == '-') {
2506                                 strind++;
2507                                 tempY = -ReadInteger(strind, &nextCharacter);
2508                                 if (strind == nextCharacter)
2509                                     return 0;
2510                                 strind = nextCharacter;
2511                                 mask |= YNegative;
2512 
2513                         }
2514                         else
2515                         {
2516                                 strind++;
2517                                 tempY = ReadInteger(strind, &nextCharacter);
2518                                 if (strind == nextCharacter)
2519                                     return 0;
2520                                 strind = nextCharacter;
2521                         }
2522                         mask |= YValue;
2523                 }
2524         }
2525 
2526         /* If strind isn't at the end of the string then it's an invalid
2527                 geometry specification. */
2528 
2529         if (*strind != '\0') return 0;
2530 
2531         if (mask & XValue)
2532             *x = tempX;
2533         if (mask & YValue)
2534             *y = tempY;
2535         if (mask & WidthValue)
2536             *width = tempWidth;
2537         if (mask & HeightValue)
2538             *height = tempHeight;
2539         return mask;
2540 }
2541 
2542 #ifdef QT3_SUPPORT
setMainWidget(QWidget * mainWidget)2543 void QApplication::setMainWidget(QWidget *mainWidget)
2544 {
2545     QApplicationPrivate::main_widget = mainWidget;
2546     if (QApplicationPrivate::main_widget) // give WM command line
2547         QApplicationPrivate::applyQWSSpecificCommandLineArguments(QApplicationPrivate::main_widget);
2548 }
2549 #endif
2550 
applyQWSSpecificCommandLineArguments(QWidget * main_widget)2551 void QApplicationPrivate::applyQWSSpecificCommandLineArguments(QWidget *main_widget)
2552 {
2553     static bool beenHereDoneThat = false;
2554     if (beenHereDoneThat)
2555         return;
2556     beenHereDoneThat = true;
2557     if (qApp->windowIcon().isNull() && main_widget->testAttribute(Qt::WA_SetWindowIcon))
2558         qApp->setWindowIcon(main_widget->windowIcon());
2559     if (mwTitle) //  && main_widget->windowTitle().isEmpty())
2560         main_widget->setWindowTitle(QString::fromLocal8Bit(mwTitle));
2561     if (mwGeometry) { // parse geometry
2562         int x = 0;
2563         int y = 0;
2564         int w = 0;
2565         int h = 0;
2566         int m = parseGeometry(mwGeometry, &x, &y, &w, &h);
2567         QSize minSize = main_widget->minimumSize();
2568         QSize maxSize = main_widget->maximumSize();
2569         if ((m & XValue) == 0)
2570             x = main_widget->geometry().x();
2571         if ((m & YValue) == 0)
2572             y = main_widget->geometry().y();
2573         if ((m & WidthValue) == 0)
2574             w = main_widget->width();
2575         if ((m & HeightValue) == 0)
2576             h = main_widget->height();
2577         w = qMin(w,maxSize.width());
2578         h = qMin(h,maxSize.height());
2579         w = qMax(w,minSize.width());
2580         h = qMax(h,minSize.height());
2581         if ((m & XNegative)) {
2582             x = qApp->desktop()->width()  + x - w;
2583             x -= (main_widget->frameGeometry().width() - main_widget->width()) / 2;
2584         } else {
2585             x += (main_widget->geometry().x() - main_widget->x());
2586         }
2587         if ((m & YNegative)) {
2588             y = qApp->desktop()->height() + y - h;
2589         } else {
2590             y += (main_widget->geometry().y() - main_widget->y());
2591         }
2592 
2593         main_widget->setGeometry(x, y, w, h);
2594     }
2595 }
2596 
2597 /*****************************************************************************
2598   QApplication cursor stack
2599  *****************************************************************************/
2600 #ifndef QT_NO_CURSOR
setOverrideCursor(const QCursor & cursor)2601 void QApplication::setOverrideCursor(const QCursor &cursor)
2602 {
2603     qApp->d_func()->cursor_list.prepend(cursor);
2604 
2605     QWidget *w = QWidget::mouseGrabber();
2606     if (!w && qt_last_x)
2607         w = topLevelAt(*qt_last_x, *qt_last_y);
2608     if (!w)
2609         w = desktop();
2610     QPaintDevice::qwsDisplay()->selectCursor(w, qApp->d_func()->cursor_list.first().handle());
2611 }
2612 
restoreOverrideCursor()2613 void QApplication::restoreOverrideCursor()
2614 {
2615     if (qApp->d_func()->cursor_list.isEmpty())
2616         return;
2617     qApp->d_func()->cursor_list.removeFirst();
2618 
2619     QWidget *w = QWidget::mouseGrabber();
2620     if (!w && qt_last_x)
2621         w = topLevelAt(*qt_last_x, *qt_last_y);
2622     if (!w)
2623         w = desktop();
2624 
2625     int cursor_handle = Qt::ArrowCursor;
2626     if (qApp->d_func()->cursor_list.isEmpty()) {
2627         qws_overrideCursor = false;
2628         QWidget *upw = QApplication::widgetAt(*qt_last_x, *qt_last_y);
2629         if (upw)
2630             cursor_handle = upw->cursor().handle();
2631     } else {
2632         cursor_handle = qApp->d_func()->cursor_list.first().handle();
2633     }
2634     QPaintDevice::qwsDisplay()->selectCursor(w, cursor_handle);
2635 }
2636 #endif// QT_NO_CURSOR
2637 
2638 
2639 
2640 /*****************************************************************************
2641   Routines to find a Qt widget from a screen position
2642  *****************************************************************************/
2643 
2644 /*!
2645     \internal
2646 */
findWidget(const QObjectList & list,const QPoint & pos,bool rec)2647 QWidget *QApplicationPrivate::findWidget(const QObjectList& list,
2648                                    const QPoint &pos, bool rec)
2649 {
2650     QWidget *w;
2651 
2652     for (int i = list.size()-1; i >= 0; --i) {
2653         if (list.at(i)->isWidgetType()) {
2654           w = static_cast<QWidget*>(list.at(i));
2655             if (w->isVisible() && !w->testAttribute(Qt::WA_TransparentForMouseEvents) &&  w->geometry().contains(pos)
2656                 && (!w->d_func()->extra || w->d_func()->extra->mask.isEmpty() ||  w->d_func()->extra->mask.contains(pos - w->geometry().topLeft()) )) {
2657                 if (!rec)
2658                     return w;
2659                 QWidget *c = w->childAt(w->mapFromParent(pos));
2660                 return c ? c : w;
2661             }
2662         }
2663     }
2664     return 0;
2665 }
2666 
2667 
topLevelAt(const QPoint & pos)2668 QWidget *QApplication::topLevelAt(const QPoint &pos)
2669 {
2670     //### QWSDisplay::windowAt() is currently only implemented in the server process
2671     int winId = QPaintDevice::qwsDisplay()->windowAt(pos);
2672     if (winId !=0)
2673         return QWidget::find(winId);
2674 
2675 #if 1
2676     // fallback implementation for client processes
2677 //### This is slightly wrong: we have no guarantee that the list is in
2678 //### stacking order, so if the topmost window is transparent, we may
2679 //### return the wrong widget
2680 
2681     QWidgetList list = topLevelWidgets();
2682     for (int i = list.size()-1; i >= 0; --i) {
2683         QWidget *w = list[i];
2684         if (w != QApplication::desktop() &&
2685              w->isVisible() && w->d_func()->localAllocatedRegion().contains(w->mapFromParent(pos))
2686             )
2687             return w;
2688     }
2689 #endif
2690     return 0;
2691 }
2692 
beep()2693 void QApplication::beep()
2694 {
2695 }
2696 
alert(QWidget *,int)2697 void QApplication::alert(QWidget *, int)
2698 {
2699 }
2700 
queryKeyboardModifiers()2701 Qt::KeyboardModifiers QApplication::queryKeyboardModifiers()
2702 {
2703     return keyboardModifiers(); // TODO proper implementation
2704 }
2705 
qwsProcessEvent(QWSEvent * event)2706 int QApplication::qwsProcessEvent(QWSEvent* event)
2707 {
2708     Q_D(QApplication);
2709     QScopedLoopLevelCounter loopLevelCounter(d->threadData);
2710     int oldstate = -1;
2711     bool isMove = false;
2712     if (event->type == QWSEvent::Mouse) {
2713         QWSMouseEvent::SimpleData &mouse = event->asMouse()->simpleData;
2714         isMove = mouse_x_root != mouse.x_root || mouse_y_root != mouse.y_root;
2715         oldstate = mouse_state;
2716         mouse_x_root = mouse.x_root;
2717         mouse_y_root = mouse.y_root;
2718         mouse_state = mouse.state;
2719     }
2720 
2721     long unused;
2722     if (filterEvent(event, &unused))                  // send through app filter
2723         return 1;
2724 
2725     if (qwsEventFilter(event))                        // send through app filter
2726         return 1;
2727 
2728 
2729 #ifndef QT_NO_QWS_PROPERTIES
2730     if (event->type == QWSEvent::PropertyNotify) {
2731         QWSPropertyNotifyEvent *e = static_cast<QWSPropertyNotifyEvent*>(event);
2732         if (e->simpleData.property == 424242) {       // Clipboard
2733 #ifndef QT_NO_CLIPBOARD
2734             if (qt_clipboard) {
2735                 QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
2736                 QApplication::sendEvent(qt_clipboard, &e);
2737             }
2738 #endif
2739         }
2740     }
2741 #endif //QT_NO_QWS_PROPERTIES
2742 #ifndef QT_NO_COP
2743     else if (event->type == QWSEvent::QCopMessage) {
2744         QWSQCopMessageEvent *e = static_cast<QWSQCopMessageEvent*>(event);
2745         QCopChannel::sendLocally(QLatin1String(e->channel), QLatin1String(e->message), e->data);
2746         return 0;
2747     }
2748 #endif
2749 #if !defined(QT_NO_QWS_QPF2)
2750     else if (event->type == QWSEvent::Font) {
2751         QWSFontEvent *e = static_cast<QWSFontEvent *>(event);
2752         if (e->simpleData.type == QWSFontEvent::FontRemoved) {
2753             QFontCache::instance()->removeEngineForFont(e->fontName);
2754         }
2755     }
2756 #endif
2757 
2758     QPointer<QETWidget> widget = static_cast<QETWidget*>(QWidget::find(WId(event->window())));
2759 #ifdef Q_BACKINGSTORE_SUBSURFACES
2760     if (!widget) { // XXX: hw: hack for accessing subsurfaces
2761         extern QWSWindowSurface* qt_findWindowSurface(int);
2762         QWSWindowSurface *s = qt_findWindowSurface(event->window());
2763         if (s)
2764             widget = static_cast<QETWidget*>(s->window());
2765     }
2766 #endif
2767 
2768 #ifndef QT_NO_DIRECTPAINTER
2769     if (!widget && d->directPainters) {
2770         QDirectPainter *dp = d->directPainters->value(WId(event->window()));
2771         if (dp == 0) {
2772         } else if (event->type == QWSEvent::Region) {
2773             QWSRegionEvent *e = static_cast<QWSRegionEvent*>(event);
2774             QRegion reg;
2775             reg.setRects(e->rectangles, e->simpleData.nrectangles);
2776             qt_directpainter_region(dp, reg, e->simpleData.type);
2777             return 1;
2778 #ifndef QT_NO_QWSEMBEDWIDGET
2779         } else if (event->type == QWSEvent::Embed) {
2780             QWSEmbedEvent *e = static_cast<QWSEmbedEvent*>(event);
2781             qt_directpainter_embedevent(dp, e);
2782             return 1;
2783  #endif // QT_NO_QWSEMBEDWIDGET
2784         }
2785     }
2786 #endif // QT_NO_DIRECTPAINTER
2787 
2788 #ifndef QT_NO_QWS_MANAGER
2789     if (d->last_manager && event->type == QWSEvent::Mouse) {
2790         QPoint pos(event->asMouse()->simpleData.x_root, event->asMouse()->simpleData.y_root);
2791         if (!d->last_manager->cachedRegion().contains(pos)) {
2792             // MouseEvent not yet delivered, so QCursor::pos() is not yet updated, sending 2 x pos
2793             QMouseEvent outside(QEvent::MouseMove, pos, pos, Qt::NoButton, 0, 0);
2794             QApplication::sendSpontaneousEvent(d->last_manager, &outside);
2795             d->last_manager = 0;
2796             qt_last_cursor = 0xffffffff; //decoration is like another window; must redo cursor
2797         }
2798     }
2799 #endif // QT_NO_QWS_MANAGER
2800 
2801     QETWidget *keywidget=0;
2802     bool grabbed=false;
2803     if (event->type==QWSEvent::Key || event->type == QWSEvent::IMEvent || event->type == QWSEvent::IMQuery) {
2804         keywidget = static_cast<QETWidget*>(QWidget::keyboardGrabber());
2805         if (keywidget) {
2806             grabbed = true;
2807         } else {
2808             if (QWidget *popup = QApplication::activePopupWidget()) {
2809                 if (popup->focusWidget())
2810                     keywidget = static_cast<QETWidget*>(popup->focusWidget());
2811                 else
2812                     keywidget = static_cast<QETWidget*>(popup);
2813             } else if (QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget->isVisible())
2814                 keywidget = static_cast<QETWidget*>(QApplicationPrivate::focus_widget);
2815             else if (widget)
2816                 keywidget = static_cast<QETWidget*>(widget->window());
2817         }
2818     } else if (event->type==QWSEvent::MaxWindowRect) {
2819         QRect r = static_cast<QWSMaxWindowRectEvent*>(event)->simpleData.rect;
2820         setMaxWindowRect(r);
2821         return 0;
2822 #ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION
2823     } else if (event->type == QWSEvent::ScreenTransformation) {
2824         QWSScreenTransformationEvent *pe = static_cast<QWSScreenTransformationEvent*>(event);
2825         setScreenTransformation(pe->simpleData.screen,
2826                                 pe->simpleData.transformation);
2827         return 0;
2828 #endif
2829     } else if (widget && event->type==QWSEvent::Mouse) {
2830         // The mouse event is to one of my top-level widgets
2831         // which one?
2832         const int btnMask = Qt::LeftButton | Qt::RightButton | Qt::MidButton;
2833         QPoint p(event->asMouse()->simpleData.x_root,
2834                  event->asMouse()->simpleData.y_root);
2835         int mouseButtonState = event->asMouse()->simpleData.state & btnMask;
2836         static int btnstate = 0;
2837 
2838         QETWidget *w = static_cast<QETWidget*>(QWidget::mouseGrabber());
2839         if (w && !mouseButtonState && qt_pressGrab == w)
2840             qt_pressGrab = 0;
2841 #ifndef QT_NO_QWS_MANAGER
2842         if (!w)
2843             w = static_cast<QETWidget*>(QWSManager::grabbedMouse());
2844 #endif
2845         if (w) {
2846             // Our mouse is grabbed - send it.
2847             widget = w;
2848             btnstate = mouseButtonState;
2849         } else {
2850             static QWidget *gw = 0;
2851             // Three jobs to do here:
2852             // 1. find the child widget this event belongs to.
2853             // 2. make sure the cursor is correct.
2854             // 3. handle implicit mouse grab due to button press.
2855             w = widget; // w is the widget the cursor is in.
2856 
2857             //### ??? alloc_region
2858             //#### why should we get events outside alloc_region ????
2859             if (1 /*widget->data->alloc_region.contains(dp) */) {
2860                 // Find the child widget that the cursor is in.
2861                 w = static_cast<QETWidget*>(widget->childAt(widget->mapFromParent(p)));
2862                 if (!w)
2863                     w = widget;
2864 #ifndef QT_NO_CURSOR
2865                 // Update Cursor.
2866                 if (!gw || gw != w || qt_last_cursor == 0xffffffff) {
2867                     QCursor *curs = 0;
2868                     if (!qApp->d_func()->cursor_list.isEmpty())
2869                         curs = &qApp->d_func()->cursor_list.first();
2870                     else if (w->d_func()->extraData())
2871                         curs = w->d_func()->extraData()->curs;
2872                     QWidget *pw = w;
2873                     // If this widget has no cursor set, try parent.
2874                     while (!curs) {
2875                         pw = pw->parentWidget();
2876                         if (!pw)
2877                             break;
2878                         if (pw->d_func()->extraData())
2879                             curs = pw->d_func()->extraData()->curs;
2880                     }
2881                     if (!qws_overrideCursor) {
2882                         if (curs)
2883                             QPaintDevice::qwsDisplay()->selectCursor(widget, curs->handle());
2884                         else
2885                             QPaintDevice::qwsDisplay()->selectCursor(widget, Qt::ArrowCursor);
2886                     }
2887                 }
2888 #endif
2889                 gw = w;
2890             } else {
2891                 // This event is not for any of our widgets
2892                 gw = 0;
2893             }
2894             if (mouseButtonState && !btnstate) {
2895                 // The server has grabbed the mouse for us.
2896                 // Remember which of my widgets has it.
2897                 qt_pressGrab = w;
2898                 if (!widget->isActiveWindow() &&
2899                     (!app_do_modal || QApplication::activeModalWidget() == widget) &&
2900                     !((widget->windowFlags() & Qt::FramelessWindowHint) || (widget->windowType() == Qt::Tool))) {
2901                     widget->activateWindow();
2902                     if (widget->raiseOnClick())
2903                         widget->raise();
2904                 }
2905             }
2906             btnstate = mouseButtonState;
2907             widget = w;
2908         }
2909     }
2910 
2911     if (!widget) {                                // don't know this window
2912         if (!QWidget::mouseGrabber()
2913 #ifndef QT_NO_QWS_MANAGER
2914             && !QWSManager::grabbedMouse()
2915 #endif
2916             ) {
2917             qt_last_cursor = 0xffffffff; // cursor can be changed by another application
2918         }
2919 
2920         QWidget* popup = QApplication::activePopupWidget();
2921         if (popup) {
2922 
2923             /*
2924               That is more than suboptimal. The real solution should
2925               do some keyevent and buttonevent translation, so that
2926               the popup still continues to work as the user expects.
2927               Unfortunately this translation is currently only
2928               possible with a known widget. I'll change that soon
2929               (Matthias).
2930             */
2931 
2932             // Danger - make sure we don't lock the server
2933             switch (event->type) {
2934             case QWSEvent::Mouse:
2935             case QWSEvent::Key:
2936                 do {
2937                     popup->close();
2938                 } while ((popup = qApp->activePopupWidget()));
2939                 return 1;
2940             }
2941         }
2942         if (event->type == QWSEvent::Mouse && *mouseInWidget) {
2943             QApplicationPrivate::dispatchEnterLeave(0, *mouseInWidget);
2944             (*mouseInWidget) = 0;
2945         }
2946         return -1;
2947     }
2948 
2949     if (app_do_modal)                                // modal event handling
2950         if (!qt_try_modal(widget, event)) {
2951             return 1;
2952         }
2953 
2954     if (widget->qwsEvent(event))                // send through widget filter
2955         return 1;
2956     switch (event->type) {
2957 
2958     case QWSEvent::Mouse: {                        // mouse event
2959         QWSMouseEvent *me = event->asMouse();
2960         QWSMouseEvent::SimpleData &mouse = me->simpleData;
2961 
2962         //  Translate a QWS event into separate move
2963         // and press/release events
2964         // Beware of reentrancy: we can enter a modal state
2965         // inside translateMouseEvent
2966 
2967         if (isMove) {
2968             QWSMouseEvent move = *me;
2969             move.simpleData.state = oldstate;
2970             widget->translateMouseEvent(&move, oldstate);
2971         }
2972         if ((mouse.state&Qt::MouseButtonMask) != (oldstate&Qt::MouseButtonMask)) {
2973             widget->translateMouseEvent(me, oldstate);
2974         }
2975 
2976         if (mouse.delta != 0)
2977             widget->translateWheelEvent(me);
2978 
2979         if (qt_button_down && (mouse_state & Qt::MouseButtonMask) == 0)
2980             qt_button_down = 0;
2981 
2982         break;
2983     }
2984     case QWSEvent::Key:                                // keyboard event
2985         if (keywidget) // should always exist
2986             keywidget->translateKeyEvent(static_cast<QWSKeyEvent*>(event), grabbed);
2987         break;
2988 
2989 #ifndef QT_NO_QWS_INPUTMETHODS
2990     case QWSEvent::IMEvent:
2991         if (keywidget) // should always exist
2992             QWSInputContext::translateIMEvent(keywidget, static_cast<QWSIMEvent*>(event));
2993         break;
2994 
2995     case QWSEvent::IMQuery:
2996         if (keywidget) // should always exist
2997             QWSInputContext::translateIMQueryEvent(keywidget, static_cast<QWSIMQueryEvent*>(event));
2998         break;
2999 
3000     case QWSEvent::IMInit:
3001         QWSInputContext::translateIMInitEvent(static_cast<QWSIMInitEvent*>(event));
3002         break;
3003 #endif
3004     case QWSEvent::Region:
3005         widget->translateRegionEvent(static_cast<QWSRegionEvent*>(event));
3006         break;
3007     case QWSEvent::Focus:
3008         if ((static_cast<QWSFocusEvent*>(event))->simpleData.get_focus) {
3009             if (widget == static_cast<QWidget *>(desktop()))
3010                 return true; // not interesting
3011             if (activeWindow() != widget) {
3012                 setActiveWindow(widget);
3013                 if (QApplicationPrivate::active_window)
3014                     static_cast<QETWidget *>(QApplicationPrivate::active_window)->repaintDecoration(desktop()->rect(), false);
3015                 if (widget && !d->inPopupMode()) {
3016                     QWidget *w = widget->focusWidget();
3017                     while (w && w->focusProxy())
3018                         w = w->focusProxy();
3019                     if (w && (w->focusPolicy() != Qt::NoFocus))
3020                         w->setFocus();
3021                     else
3022                         widget->QWidget::focusNextPrevChild(true);
3023                     if (!QApplicationPrivate::focus_widget) {
3024                         if (widget->focusWidget())
3025                             widget->focusWidget()->setFocus();
3026                         else
3027                             widget->window()->setFocus();
3028                     }
3029                 }
3030             }
3031         } else {        // lost focus
3032             if (widget == static_cast<QWidget *>(desktop()))
3033                 return true; // not interesting
3034             if (QApplicationPrivate::focus_widget) {
3035                 QETWidget *old = static_cast<QETWidget *>(QApplicationPrivate::active_window);
3036                 setActiveWindow(0);
3037                 qt_last_cursor = 0xffffffff;
3038                 //QApplicationPrivate::active_window = 0;
3039                 if (old)
3040                     old->repaintDecoration(desktop()->rect(), false);
3041                 /* activateWindow() sends focus events
3042                    QApplication::setFocusWidget(0);
3043                 */
3044             }
3045         }
3046         break;
3047 
3048     case QWSEvent::WindowOperation:
3049         if (static_cast<QWidget *>(widget) == desktop())
3050             return true;
3051         switch ((static_cast<QWSWindowOperationEvent *>(event))->simpleData.op) {
3052         case QWSWindowOperationEvent::Show:
3053             widget->show();
3054             break;
3055         case QWSWindowOperationEvent::Hide:
3056             widget->hide();
3057             break;
3058         case QWSWindowOperationEvent::ShowMaximized:
3059             widget->showMaximized();
3060             break;
3061         case QWSWindowOperationEvent::ShowMinimized:
3062             widget->showMinimized();
3063             break;
3064         case QWSWindowOperationEvent::ShowNormal:
3065             widget->showNormal();
3066             break;
3067         case QWSWindowOperationEvent::Close:
3068             widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
3069             break;
3070         }
3071         break;
3072 #ifndef QT_NO_QWSEMBEDWIDGET
3073     case QWSEvent::Embed:
3074         widget->translateEmbedEvent(static_cast<QWSEmbedEvent*>(event));
3075         break;
3076 #endif
3077     default:
3078         break;
3079     }
3080 
3081     return 0;
3082 }
3083 
qwsEventFilter(QWSEvent *)3084 bool QApplication::qwsEventFilter(QWSEvent *)
3085 {
3086     return false;
3087 }
3088 
qwsSetCustomColors(QRgb * colorTable,int start,int numColors)3089 void QApplication::qwsSetCustomColors(QRgb *colorTable, int start, int numColors)
3090 {
3091     if (start < 0 || start > 39) {
3092         qWarning("QApplication::qwsSetCustomColors: start < 0 || start > 39");
3093         return;
3094     }
3095     if (start + numColors > 40) {
3096         numColors = 40 - start;
3097         qWarning("QApplication::qwsSetCustomColors: Too many colors");
3098     }
3099     start += 216;
3100     for (int i = 0; i < numColors; i++) {
3101         qt_screen->set(start + i, qRed(colorTable[i]), qGreen(colorTable[i]),
3102                         qBlue(colorTable[i]));
3103     }
3104 }
3105 
3106 #ifndef QT_NO_QWS_MANAGER
qwsDecoration()3107 QDecoration &QApplication::qwsDecoration()
3108 {
3109     return *qws_decoration;
3110 }
3111 
qwsSetDecoration(QDecoration * dec)3112 void QApplication::qwsSetDecoration(QDecoration *dec)
3113 {
3114     if (dec) {
3115         delete qws_decoration;
3116         qws_decoration = dec;
3117         QWidgetList widgets = topLevelWidgets();
3118         for (int i = 0; i < widgets.size(); ++i) {
3119             QWidget *w = widgets[i];
3120             if (w->isVisible() && w != desktop()) {
3121                 static_cast<QETWidget *>(w)->updateRegion();
3122                 static_cast<QETWidget *>(w)->repaintDecoration(desktop()->rect(), false);
3123                 if (w->isMaximized())
3124                     w->showMaximized();
3125             }
3126         }
3127     }
3128 }
3129 
qwsSetDecoration(const QString & decoration)3130 QDecoration* QApplication::qwsSetDecoration(const QString &decoration)
3131 {
3132     QDecoration *decore = QDecorationFactory::create(decoration);
3133     if (!decore)
3134         return 0;
3135 
3136     qwsSetDecoration(decore);
3137     return decore;
3138 }
3139 
3140 #endif
3141 
modalState()3142 bool QApplicationPrivate::modalState()
3143 {
3144     return app_do_modal;
3145 }
3146 
enterModal_sys(QWidget * widget)3147 void QApplicationPrivate::enterModal_sys(QWidget *widget)
3148 {
3149     if (!qt_modal_stack)
3150         qt_modal_stack = new QWidgetList;
3151     qt_modal_stack->insert(0, widget);
3152     app_do_modal = true;
3153 }
3154 
leaveModal_sys(QWidget * widget)3155 void QApplicationPrivate::leaveModal_sys(QWidget *widget)
3156 {
3157     if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
3158         if (qt_modal_stack->isEmpty()) {
3159             delete qt_modal_stack;
3160             qt_modal_stack = 0;
3161         }
3162     }
3163     app_do_modal = qt_modal_stack != 0;
3164 }
3165 
qt_try_modal(QWidget * widget,QWSEvent * event)3166 static bool qt_try_modal(QWidget *widget, QWSEvent *event)
3167 {
3168     QWidget * top = 0;
3169 
3170     if (QApplicationPrivate::tryModalHelper(widget, &top))
3171         return true;
3172 
3173     bool block_event  = false;
3174     bool paint_event = false;
3175 
3176     switch (event->type) {
3177         case QWSEvent::Focus:
3178             if (!static_cast<QWSFocusEvent*>(event)->simpleData.get_focus)
3179                 break;
3180             // drop through
3181         case QWSEvent::Mouse:                        // disallow mouse/key events
3182         case QWSEvent::Key:
3183             block_event         = true;
3184             break;
3185     }
3186 
3187     if (top->parentWidget() == 0 && (block_event || paint_event))
3188         top->raise();
3189 
3190     return !block_event;
3191 }
3192 
3193 static int openPopupCount = 0;
openPopup(QWidget * popup)3194 void QApplicationPrivate::openPopup(QWidget *popup)
3195 {
3196     openPopupCount++;
3197     if (!popupWidgets) {                        // create list
3198         popupWidgets = new QWidgetList;
3199 
3200         /* only grab if you are the first/parent popup */
3201         QPaintDevice::qwsDisplay()->grabMouse(popup,true);
3202         QPaintDevice::qwsDisplay()->grabKeyboard(popup,true);
3203         popupGrabOk = true;
3204     }
3205     popupWidgets->append(popup);                // add to end of list
3206 
3207     // popups are not focus-handled by the window system (the first
3208     // popup grabbed the keyboard), so we have to do that manually: A
3209     // new popup gets the focus
3210     if (popup->focusWidget()) {
3211         popup->focusWidget()->setFocus(Qt::PopupFocusReason);
3212     } else if (popupWidgets->count() == 1) { // this was the first popup
3213         if (QWidget *fw = QApplication::focusWidget()) {
3214             QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
3215             QApplication::sendEvent(fw, &e);
3216         }
3217     }
3218 }
3219 
closePopup(QWidget * popup)3220 void QApplicationPrivate::closePopup(QWidget *popup)
3221 {
3222     if (!popupWidgets)
3223         return;
3224 
3225     popupWidgets->removeAll(popup);
3226     if (popup == popupOfPopupButtonFocus) {
3227         popupButtonFocus = 0;
3228         popupOfPopupButtonFocus = 0;
3229     }
3230     if (popupWidgets->count() == 0) {                // this was the last popup
3231         popupCloseDownMode = true;                // control mouse events
3232         delete popupWidgets;
3233         popupWidgets = 0;
3234         if (popupGrabOk) {        // grabbing not disabled
3235             QPaintDevice::qwsDisplay()->grabMouse(popup,false);
3236             QPaintDevice::qwsDisplay()->grabKeyboard(popup,false);
3237             popupGrabOk = false;
3238             // XXX ungrab keyboard
3239         }
3240         if (active_window) {
3241             if (QWidget *fw = active_window->focusWidget()) {
3242                 if (fw != QApplication::focusWidget()) {
3243                     fw->setFocus(Qt::PopupFocusReason);
3244                 } else {
3245                     QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
3246                     QApplication::sendEvent(fw, &e);
3247                 }
3248             }
3249         }
3250     } else {
3251         // popups are not focus-handled by the window system (the
3252         // first popup grabbed the keyboard), so we have to do that
3253         // manually: A popup was closed, so the previous popup gets
3254         // the focus.
3255         QWidget* aw = popupWidgets->last();
3256         if (QWidget *fw = aw->focusWidget())
3257             fw->setFocus(Qt::PopupFocusReason);
3258     }
3259 }
3260 
3261 /*****************************************************************************
3262   Event translation; translates FB events to Qt events
3263  *****************************************************************************/
3264 
3265 //
3266 // Mouse event translation
3267 //
3268 // FB doesn't give mouse double click events, so we generate them by
3269 // comparing window, time and position between two mouse press events.
3270 //
3271 
3272 
3273 // Needed for QCursor::pos
3274 
3275 static const int AnyButton = (Qt::LeftButton | Qt::MidButton | Qt::RightButton);
3276 
3277 
3278 
3279 //
3280 // Wheel event translation
3281 //
translateWheelEvent(const QWSMouseEvent * me)3282 bool QETWidget::translateWheelEvent(const QWSMouseEvent *me)
3283 {
3284 #ifdef QT_NO_WHEELEVENT
3285     Q_UNUSED(me);
3286     return false;
3287 #else
3288     const QWSMouseEvent::SimpleData &mouse = me->simpleData;
3289 
3290     // Figure out wheeling direction:
3291     //    Horizontal wheel w/o Alt
3292     // OR Vertical wheel   w/  Alt  ==> Horizontal wheeling
3293     //    ..all other permutations  ==> Vertical wheeling
3294     int axis = mouse.delta / 120; // WHEEL_DELTA?
3295     Qt::Orientation orient = ((axis == 2 || axis == -2) && ((mouse.state & Qt::AltModifier) == 0))
3296                              ||((axis == 1 || axis == -1) && mouse.state & Qt::AltModifier)
3297                              ? Qt::Horizontal : Qt::Vertical;
3298 
3299     QPoint mousePoint = QPoint(mouse.x_root, mouse.y_root);
3300 
3301     // send the event to the widget or its ancestors
3302     QWidget* popup = qApp->activePopupWidget();
3303     if (popup && window() != popup)
3304         popup->close();
3305     QWheelEvent we(mapFromGlobal(mousePoint), mousePoint, mouse.delta,
3306                    Qt::MouseButtons(mouse.state & Qt::MouseButtonMask),
3307                    Qt::KeyboardModifiers(mouse.state & Qt::KeyboardModifierMask), orient);
3308     if (QApplication::sendSpontaneousEvent(this, &we))
3309         return true;
3310 
3311     // send the event to the widget that has the focus or its ancestors, if different
3312     QWidget *w = this;
3313     if (w != qApp->focusWidget() && (w = qApp->focusWidget())) {
3314         QWidget* popup = qApp->activePopupWidget();
3315         if (popup && w != popup)
3316             popup->hide();
3317         if (QApplication::sendSpontaneousEvent(w, &we))
3318             return true;
3319     }
3320     return false;
3321 #endif
3322 }
3323 
translateMouseEvent(const QWSMouseEvent * event,int prevstate)3324 bool QETWidget::translateMouseEvent(const QWSMouseEvent *event, int prevstate)
3325 {
3326     static bool manualGrab = false;
3327     QPoint pos;
3328     QPoint globalPos;
3329     int button = 0;
3330 
3331     if (sm_blockUserInput) // block user interaction during session management
3332         return true;
3333     const QWSMouseEvent::SimpleData &mouse = event->simpleData;
3334     pos = mapFromGlobal(QPoint(mouse.x_root, mouse.y_root));
3335 //     if (qt_last_x) {
3336 //         *qt_last_x=mouse.x_root;
3337 //         *qt_last_y=mouse.y_root;
3338 //     }
3339     globalPos.rx() = mouse.x_root;
3340     globalPos.ry() = mouse.y_root;
3341 
3342     QEvent::Type type = QEvent::None;
3343 
3344     Qt::MouseButtons buttonstate = Qt::MouseButtons(mouse.state & Qt::MouseButtonMask);
3345     Qt::KeyboardModifiers keystate = Qt::KeyboardModifiers(mouse.state & Qt::KeyboardModifierMask);
3346 
3347     if (mouse.state == prevstate) {
3348         // mouse move
3349         type = QEvent::MouseMove;
3350     } else if ((mouse.state&AnyButton) != (prevstate&AnyButton)) {
3351         Qt::MouseButtons current_buttons = Qt::MouseButtons(prevstate&Qt::MouseButtonMask);
3352         for (button = Qt::LeftButton; !type && button <= Qt::MidButton; button<<=1) {
3353             if ((mouse.state&button) != (current_buttons&button)) {
3354                 // button press or release
3355                 current_buttons = Qt::MouseButtons(current_buttons ^ button);
3356 
3357 #ifndef QT_NO_QWS_INPUTMETHODS
3358                 //############ We used to do a QInputContext::reset(oldFocus);
3359                 // when we changed the focus widget. See change 93389 for where the
3360                 // focus code went. The IM code was (after testing for ClickToFocus):
3361                 //if (mouse.state&button && w != QInputContext::microFocusWidget()) //button press
3362                 //        QInputContext::reset(oldFocus);
3363 
3364 #endif
3365                 if (mouse.state&button) { //button press
3366                     qt_button_down = childAt(pos);
3367                     if (!qt_button_down)
3368                         qt_button_down = this;
3369                     if (/*XXX mouseActWindow == this &&*/
3370                         mouseButtonPressed == button &&
3371                         long(mouse.time) -long(mouseButtonPressTime)
3372                             < QApplication::doubleClickInterval() &&
3373                         qAbs(mouse.x_root - mouseXPos) < mouse_double_click_distance &&
3374                         qAbs(mouse.y_root - mouseYPos) < mouse_double_click_distance ) {
3375                         type = QEvent::MouseButtonDblClick;
3376                         mouseButtonPressTime -= 2000;        // no double-click next time
3377                     } else {
3378                         type = QEvent::MouseButtonPress;
3379                         mouseButtonPressTime = mouse.time;
3380                     }
3381                     mouseButtonPressed = button;        // save event params for
3382                     mouseXPos = globalPos.x();                // future double click tests
3383                     mouseYPos = globalPos.y();
3384                 } else {                                // mouse button released
3385                     if (manualGrab) {                        // release manual grab
3386                         manualGrab = false;
3387                         // XXX XUngrabPointer(x11Display(), CurrentTime);
3388                     }
3389 
3390                     type = QEvent::MouseButtonRelease;
3391                 }
3392             }
3393         }
3394         button >>= 1;
3395     }
3396     //XXX mouseActWindow = winId();                        // save some event params
3397 
3398     if (type == 0) {                                // event consumed
3399         return false; //EXIT in the normal case
3400     }
3401 
3402     if (qApp->d_func()->inPopupMode()) {                        // in popup mode
3403         QWidget *popup = qApp->activePopupWidget();
3404         // in X11, this would be the window we are over.
3405         // in QWS this is the top level popup.  to allow mouse
3406         // events to other widgets, need to go through qApp->QApplicationPrivate::popupWidgets.
3407         QSize s(qt_screen->width(), qt_screen->height());
3408         for (int i = 0; i < QApplicationPrivate::popupWidgets->size(); ++i) {
3409             QWidget *w = QApplicationPrivate::popupWidgets->at(i);
3410 
3411             if ((w->windowType() == Qt::Popup) && w->d_func()->localAllocatedRegion().contains(globalPos - w->geometry().topLeft()))
3412             {
3413                 popup = w;
3414                 break;
3415             }
3416         }
3417         pos = popup->mapFromGlobal(globalPos);
3418         bool releaseAfter = false;
3419         QWidget *popupChild  = popup->childAt(pos);
3420         QWidget *popupTarget = popupChild ? popupChild : popup;
3421 
3422         if (popup != popupOfPopupButtonFocus){
3423             popupButtonFocus = 0;
3424             popupOfPopupButtonFocus = 0;
3425         }
3426 
3427         if (!popupTarget->isEnabled()) {
3428             return false; //EXIT special case
3429         }
3430 
3431         switch (type) {
3432             case QEvent::MouseButtonPress:
3433             case QEvent::MouseButtonDblClick:
3434                 popupButtonFocus = popupChild;
3435                 popupOfPopupButtonFocus = popup;
3436                 break;
3437             case QEvent::MouseButtonRelease:
3438                 releaseAfter = true;
3439                 break;
3440             default:
3441                 break;                                // nothing for mouse move
3442         }
3443 
3444         int oldOpenPopupCount = openPopupCount;
3445 
3446         if (popupButtonFocus) {
3447             QMouseEvent e(type, popupButtonFocus->mapFromGlobal(globalPos),
3448                         globalPos, Qt::MouseButton(button), buttonstate, keystate);
3449             QApplication::sendSpontaneousEvent(popupButtonFocus, & e);
3450             if (releaseAfter) {
3451                 popupButtonFocus = 0;
3452                 popupOfPopupButtonFocus = 0;
3453             }
3454         } else if (popupChild) {
3455             QMouseEvent e(type, popupChild->mapFromGlobal(globalPos),
3456                         globalPos, Qt::MouseButton(button), buttonstate, keystate);
3457             QApplication::sendSpontaneousEvent(popupChild, & e);
3458         } else {
3459             QMouseEvent e(type, pos, globalPos, Qt::MouseButton(button), buttonstate, keystate);
3460             QApplication::sendSpontaneousEvent(popupChild ? popupChild : popup, & e);
3461         }
3462 #ifndef QT_NO_CONTEXTMENU
3463         if (type == QEvent::MouseButtonPress && button == Qt::RightButton && (openPopupCount == oldOpenPopupCount)) {
3464             QWidget *popupEvent = popup;
3465             if(popupButtonFocus)
3466                 popupEvent = popupButtonFocus;
3467             else if(popupChild)
3468                 popupEvent = popupChild;
3469             QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, keystate);
3470             QApplication::sendSpontaneousEvent(popupEvent, &e);
3471         }
3472 #endif // QT_NO_CONTEXTMENU
3473 
3474         if (releaseAfter)
3475             qt_button_down = 0;
3476 
3477     } else { //qApp not in popup mode
3478         QWidget *widget = this;
3479         QWidget *w = QWidget::mouseGrabber();
3480         if (!w && qt_button_down)
3481             w = qt_button_down;
3482         if (w && w != this) {
3483             widget = w;
3484             pos = mapToGlobal(pos);
3485             pos = w->mapFromGlobal(pos);
3486         }
3487 
3488         if (popupCloseDownMode) {
3489             popupCloseDownMode = false;
3490             if ((windowType() == Qt::Popup))        // ignore replayed event
3491                 return true; //EXIT
3492         }
3493 
3494         QPointer<QWidget> leaveAfterRelease = 0;
3495         if (type == QEvent::MouseButtonRelease &&
3496             (mouse.state & (~button) & (Qt::LeftButton |
3497                                     Qt::MidButton |
3498                                     Qt::RightButton)) == 0) {
3499             // Button released outside the widget -> leave the widget after the
3500             // release event has been delivered.
3501             if (widget == qt_button_down && (pos.x() < 0 || pos.y() < 0))
3502                 leaveAfterRelease = qt_button_down;
3503             qt_button_down = 0;
3504         }
3505 
3506         int oldOpenPopupCount = openPopupCount;
3507 
3508         QMouseEvent e(type, pos, globalPos, Qt::MouseButton(button), buttonstate, keystate);
3509 #ifndef QT_NO_QWS_MANAGER
3510         if (widget->isWindow() && widget->d_func()->topData()->qwsManager
3511             && (widget->d_func()->topData()->qwsManager->region().contains(globalPos)
3512                 || QWSManager::grabbedMouse() )) {
3513             if ((*mouseInWidget)) {
3514                 QApplicationPrivate::dispatchEnterLeave(0, *mouseInWidget);
3515                 (*mouseInWidget) = 0;
3516             }
3517             QApplication::sendSpontaneousEvent(widget->d_func()->topData()->qwsManager, &e);
3518             qApp->d_func()->last_manager = widget->d_func()->topData()->qwsManager;
3519         } else
3520 #endif
3521         {
3522             if (widget != (*mouseInWidget)) {
3523                 QApplicationPrivate::dispatchEnterLeave(widget, *mouseInWidget);
3524                 (*mouseInWidget) = widget;
3525                 qt_last_mouse_receiver = widget;
3526             }
3527             QApplication::sendSpontaneousEvent(widget, &e);
3528             if (leaveAfterRelease && !QWidget::mouseGrabber()) {
3529                 *mouseInWidget = QApplication::widgetAt(globalPos);
3530                 qt_last_mouse_receiver = *mouseInWidget;
3531                 QApplicationPrivate::dispatchEnterLeave(*mouseInWidget, leaveAfterRelease);
3532                 leaveAfterRelease = 0;
3533             }
3534         }
3535 #ifndef QT_NO_CONTEXTMENU
3536         if (type == QEvent::MouseButtonPress && button == Qt::RightButton && (openPopupCount == oldOpenPopupCount)) {
3537             QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, keystate);
3538             QApplication::sendSpontaneousEvent(widget, &e);
3539         }
3540 #endif // QT_NO_CONTEXTMENU
3541     }
3542     return true;
3543 }
3544 
3545 
translateKeyEvent(const QWSKeyEvent * event,bool grab)3546 bool QETWidget::translateKeyEvent(const QWSKeyEvent *event, bool grab) /* grab is used in the #ifdef */
3547 {
3548     int code = -1;
3549     //### Qt assumes keyboard state is state *before*, while QWS uses state after the event
3550     static Qt::KeyboardModifiers oldstate;
3551     Qt::KeyboardModifiers state = oldstate;
3552     oldstate = event->simpleData.modifiers;
3553 
3554     if (sm_blockUserInput) // block user interaction during session management
3555         return true;
3556 
3557     if (!isEnabled())
3558         return true;
3559 
3560     QEvent::Type type = event->simpleData.is_press ?
3561                         QEvent::KeyPress : QEvent::KeyRelease;
3562     bool autor = event->simpleData.is_auto_repeat;
3563     QString text;
3564     if (event->simpleData.unicode && event->simpleData.unicode != 0xffff)
3565         text += QChar(event->simpleData.unicode);
3566     code = event->simpleData.keycode;
3567 
3568 #if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT)
3569     if (type == QEvent::KeyPress && !grab
3570         && static_cast<QApplicationPrivate*>(qApp->d_ptr.data())->use_compat()) {
3571         // send accel events if the keyboard is not grabbed
3572         QKeyEvent a(type, code, state, text, autor, int(text.length()));
3573         if (static_cast<QApplicationPrivate*>(qApp->d_ptr.data())->qt_tryAccelEvent(this, &a))
3574             return true;
3575     }
3576 #else
3577     Q_UNUSED(grab);
3578 #endif
3579     if (!text.isEmpty() && testAttribute(Qt::WA_KeyCompression)) {
3580         // the widget wants key compression so it gets it
3581 
3582         // XXX not implemented
3583     }
3584 
3585     QKeyEvent e(type, code, state, text, autor, int(text.length()));
3586     return QApplication::sendSpontaneousEvent(this, &e);
3587 }
3588 
translateRegionEvent(const QWSRegionEvent * event)3589 bool QETWidget::translateRegionEvent(const QWSRegionEvent *event)
3590 {
3591     QWSWindowSurface *surface = static_cast<QWSWindowSurface*>(windowSurface());
3592     Q_ASSERT(surface);
3593 
3594     QRegion region;
3595     region.setRects(event->rectangles, event->simpleData.nrectangles);
3596 
3597     switch (event->simpleData.type) {
3598     case QWSRegionEvent::Allocation:
3599         region.translate(-mapToGlobal(QPoint()));
3600         surface->setClipRegion(region);
3601         break;
3602 #ifdef QT_QWS_CLIENTBLIT
3603     case QWSRegionEvent::DirectPaint:
3604         surface->setDirectRegion(region, event->simpleData.id);
3605         break;
3606 #endif
3607     default:
3608         break;
3609     }
3610 
3611     return true;
3612 }
3613 
3614 #ifndef QT_NO_QWSEMBEDWIDGET
translateEmbedEvent(const QWSEmbedEvent * event)3615 void QETWidget::translateEmbedEvent(const QWSEmbedEvent *event)
3616 {
3617     if (event->simpleData.type | QWSEmbedEvent::Region) {
3618         const QRegion region = event->region;
3619         setGeometry(region.boundingRect());
3620         setVisible(!region.isEmpty());
3621     }
3622 }
3623 #endif // QT_NO_QWSEMBEDWIDGET
3624 
repaintDecoration(QRegion r,bool post)3625 void QETWidget::repaintDecoration(QRegion r, bool post)
3626 {
3627     Q_UNUSED(post);
3628 #ifdef QT_NO_QWS_MANAGER
3629     Q_UNUSED(r);
3630 #else
3631     //please note that qwsManager is a QObject, not a QWidget.
3632     //therefore, normal ways of painting do not work.
3633     // However, it does listen to paint events.
3634 
3635     Q_D(QWidget);
3636     if (isWindow() && d->topData()->qwsManager && isVisible()) {
3637         QWSManager *manager = d->topData()->qwsManager;
3638         r &= manager->region();
3639         if (!r.isEmpty())
3640             manager->repaintRegion(QDecoration::All, QDecoration::Normal);
3641     }
3642 #endif
3643 }
3644 
updateRegion()3645 void QETWidget::updateRegion()
3646 {
3647     Q_D(QWidget);
3648 
3649     QTLWExtra *topextra = d->maybeTopData();
3650     if (!topextra)
3651         return;
3652 
3653     QRegion myregion = d->localRequestedRegion();
3654     myregion.translate(geometry().topLeft());
3655 
3656 #ifndef QT_NO_QWS_MANAGER
3657     QWSManager *manager = topextra->qwsManager;
3658     if (manager)
3659         myregion += manager->region();
3660 #endif
3661 
3662     QRect br(myregion.boundingRect());
3663     topextra->frameStrut.setCoords(d->data.crect.x() - br.x(),
3664                                    d->data.crect.y() - br.y(),
3665                                    br.right() - d->data.crect.right(),
3666                                    br.bottom() - d->data.crect.bottom());
3667 }
3668 
setCursorFlashTime(int msecs)3669 void  QApplication::setCursorFlashTime(int msecs)
3670 {
3671     QApplicationPrivate::cursor_flash_time = msecs;
3672 }
3673 
3674 
cursorFlashTime()3675 int QApplication::cursorFlashTime()
3676 {
3677     return QApplicationPrivate::cursor_flash_time;
3678 }
3679 
setDoubleClickInterval(int ms)3680 void QApplication::setDoubleClickInterval(int ms)
3681 {
3682     QApplicationPrivate::mouse_double_click_time = ms;
3683 }
3684 
doubleClickInterval()3685 int QApplication::doubleClickInterval()
3686 {
3687     return QApplicationPrivate::mouse_double_click_time;
3688 }
3689 
setKeyboardInputInterval(int ms)3690 void QApplication::setKeyboardInputInterval(int ms)
3691 {
3692     QApplicationPrivate::keyboard_input_time = ms;
3693 }
3694 
keyboardInputInterval()3695 int QApplication::keyboardInputInterval()
3696 {
3697     return QApplicationPrivate::keyboard_input_time;
3698 }
3699 
3700 #ifndef QT_NO_WHEELEVENT
setWheelScrollLines(int lines)3701 void QApplication::setWheelScrollLines(int lines)
3702 {
3703     QApplicationPrivate::wheel_scroll_lines = lines;
3704 }
3705 
wheelScrollLines()3706 int QApplication::wheelScrollLines()
3707 {
3708     return QApplicationPrivate::wheel_scroll_lines;
3709 }
3710 #endif
3711 
setEffectEnabled(Qt::UIEffect effect,bool enable)3712 void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
3713 {
3714     switch (effect) {
3715     case Qt::UI_AnimateMenu:
3716         QApplicationPrivate::animate_menu = enable;
3717         break;
3718     case Qt::UI_FadeMenu:
3719         if (enable)
3720             QApplicationPrivate::animate_menu = true;
3721         QApplicationPrivate::fade_menu = enable;
3722         break;
3723     case Qt::UI_AnimateCombo:
3724         QApplicationPrivate::animate_combo = enable;
3725         break;
3726     case Qt::UI_AnimateTooltip:
3727         QApplicationPrivate::animate_tooltip = enable;
3728         break;
3729     case Qt::UI_FadeTooltip:
3730         if (enable)
3731             QApplicationPrivate::animate_tooltip = true;
3732         QApplicationPrivate::fade_tooltip = enable;
3733         break;
3734     case Qt::UI_AnimateToolBox:
3735         QApplicationPrivate::animate_toolbox = enable;
3736         break;
3737     default:
3738         QApplicationPrivate::animate_ui = enable;
3739         break;
3740     }
3741 }
3742 
isEffectEnabled(Qt::UIEffect effect)3743 bool QApplication::isEffectEnabled(Qt::UIEffect effect)
3744 {
3745     if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui)
3746         return false;
3747 
3748     switch(effect) {
3749     case Qt::UI_AnimateMenu:
3750         return QApplicationPrivate::animate_menu;
3751     case Qt::UI_FadeMenu:
3752         return QApplicationPrivate::fade_menu;
3753     case Qt::UI_AnimateCombo:
3754         return QApplicationPrivate::animate_combo;
3755     case Qt::UI_AnimateTooltip:
3756         return QApplicationPrivate::animate_tooltip;
3757     case Qt::UI_FadeTooltip:
3758         return QApplicationPrivate::fade_tooltip;
3759     case Qt::UI_AnimateToolBox:
3760         return QApplicationPrivate::animate_toolbox;
3761     default:
3762         return QApplicationPrivate::animate_ui;
3763     }
3764 }
3765 
setArgs(int c,char ** v)3766 void QApplication::setArgs(int c, char **v)
3767 {
3768     Q_D(QApplication);
3769     d->argc = c;
3770     d->argv = v;
3771 }
3772 
initializeMultitouch_sys()3773 void QApplicationPrivate::initializeMultitouch_sys()
3774 { }
cleanupMultitouch_sys()3775 void QApplicationPrivate::cleanupMultitouch_sys()
3776 { }
3777 
3778 /* \internal
3779    This is used to clean up the qws server
3780    in case the QApplication constructor threw an exception
3781 */
~QWSServerCleaner()3782 QWSServerCleaner::~QWSServerCleaner()
3783 {
3784     if (qwsServer && qws_single_process)
3785         QWSServer::closedown();
3786 }
3787 
3788 QT_END_NAMESPACE
3789