1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** All rights reserved.
|
---|
5 | ** Contact: Nokia Corporation (qt-info@nokia.com)
|
---|
6 | **
|
---|
7 | ** This file is part of the QtGui module of the Qt Toolkit.
|
---|
8 | **
|
---|
9 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
10 | ** Commercial Usage
|
---|
11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
14 | ** a written agreement between you and Nokia.
|
---|
15 | **
|
---|
16 | ** GNU Lesser General Public License Usage
|
---|
17 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
18 | ** General Public License version 2.1 as published by the Free Software
|
---|
19 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
20 | ** packaging of this file. Please review the following information to
|
---|
21 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
23 | **
|
---|
24 | ** In addition, as a special exception, Nokia gives you certain additional
|
---|
25 | ** rights. These rights are described in the Nokia Qt LGPL Exception
|
---|
26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
---|
27 | **
|
---|
28 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you have questions regarding the use of this file, please contact
|
---|
37 | ** Nokia at qt-info@nokia.com.
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #include "qplatformdefs.h"
|
---|
43 |
|
---|
44 | #include "qwindowsystem_qws.h"
|
---|
45 | #include "qwsevent_qws.h"
|
---|
46 | #include "qwscommand_qws_p.h"
|
---|
47 | #include "qtransportauth_qws_p.h"
|
---|
48 | #include "qwsutils_qws.h"
|
---|
49 | #include "qwscursor_qws.h"
|
---|
50 | #include "qwsdisplay_qws.h"
|
---|
51 | #include "qmouse_qws.h"
|
---|
52 | #include "qcopchannel_qws.h"
|
---|
53 | #include "qwssocket_qws.h"
|
---|
54 |
|
---|
55 | #include "qapplication.h"
|
---|
56 | #include "private/qapplication_p.h"
|
---|
57 | #include "qsocketnotifier.h"
|
---|
58 | #include "qpolygon.h"
|
---|
59 | #include "qimage.h"
|
---|
60 | #include "qcursor.h"
|
---|
61 | #include <private/qpaintengine_raster_p.h>
|
---|
62 | #include "qscreen_qws.h"
|
---|
63 | #include "qwindowdefs.h"
|
---|
64 | #include "private/qlock_p.h"
|
---|
65 | #include "qwslock_p.h"
|
---|
66 | #include "qfile.h"
|
---|
67 | #include "qtimer.h"
|
---|
68 | #include "qpen.h"
|
---|
69 | #include "qdesktopwidget.h"
|
---|
70 | #include "qevent.h"
|
---|
71 | #include "qinputcontext.h"
|
---|
72 | #include "qpainter.h"
|
---|
73 |
|
---|
74 | #include <qdebug.h>
|
---|
75 |
|
---|
76 | #include "qkbddriverfactory_qws.h"
|
---|
77 | #include "qmousedriverfactory_qws.h"
|
---|
78 |
|
---|
79 | #include <qbuffer.h>
|
---|
80 | #include <qdir.h>
|
---|
81 |
|
---|
82 | #include <private/qwindowsurface_qws_p.h>
|
---|
83 | #include <private/qfontengine_qpf_p.h>
|
---|
84 |
|
---|
85 | #include "qwindowsystem_p.h"
|
---|
86 |
|
---|
87 |
|
---|
88 | #include <stdlib.h>
|
---|
89 | #include <stdio.h>
|
---|
90 | #include <errno.h>
|
---|
91 |
|
---|
92 | #ifndef QT_NO_QWS_MULTIPROCESS
|
---|
93 | #include <sys/param.h>
|
---|
94 | #include <sys/mount.h>
|
---|
95 | #endif
|
---|
96 |
|
---|
97 | #if !defined(QT_NO_SOUND) && !defined(Q_OS_DARWIN)
|
---|
98 | #ifdef QT_USE_OLD_QWS_SOUND
|
---|
99 | #include <sys/types.h>
|
---|
100 | #include <sys/stat.h>
|
---|
101 | #include <sys/ioctl.h>
|
---|
102 | #include <sys/soundcard.h>
|
---|
103 | #else
|
---|
104 | #include "qsoundqss_qws.h"
|
---|
105 | #endif
|
---|
106 | #endif
|
---|
107 |
|
---|
108 | //#define QWS_DEBUG_FONTCLEANUP
|
---|
109 |
|
---|
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"
|
---|