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