source: branches/4.5.1/src/gui/kernel/qguieventdispatcher_glib.cpp@ 559

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

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 7.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qguieventdispatcher_glib_p.h"
43
44#include "qapplication.h"
45#include "qx11info_x11.h"
46
47#include "qt_x11_p.h"
48
49#include <glib.h>
50
51QT_BEGIN_NAMESPACE
52
53struct GX11EventSource
54{
55 GSource source;
56 GPollFD pollfd;
57 QEventLoop::ProcessEventsFlags flags;
58 QGuiEventDispatcherGlib *q;
59 QGuiEventDispatcherGlibPrivate *d;
60};
61
62class QGuiEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate
63{
64 Q_DECLARE_PUBLIC(QGuiEventDispatcherGlib)
65
66public:
67 QGuiEventDispatcherGlibPrivate();
68 GX11EventSource *x11EventSource;
69 QList<XEvent> queuedUserInputEvents;
70};
71
72static gboolean x11EventSourcePrepare(GSource *s, gint *timeout)
73{
74 if (timeout)
75 *timeout = -1;
76 GX11EventSource *source = reinterpret_cast<GX11EventSource *>(s);
77 return (XEventsQueued(X11->display, QueuedAfterFlush)
78 || (!(source->flags & QEventLoop::ExcludeUserInputEvents)
79 && !source->d->queuedUserInputEvents.isEmpty()));
80}
81
82static gboolean x11EventSourceCheck(GSource *s)
83{
84 GX11EventSource *source = reinterpret_cast<GX11EventSource *>(s);
85 return (XEventsQueued(X11->display, QueuedAfterFlush)
86 || (!(source->flags & QEventLoop::ExcludeUserInputEvents)
87 && !source->d->queuedUserInputEvents.isEmpty()));
88}
89
90static gboolean x11EventSourceDispatch(GSource *s, GSourceFunc callback, gpointer user_data)
91{
92 GX11EventSource *source = reinterpret_cast<GX11EventSource *>(s);
93
94 ulong marker = XNextRequest(X11->display);
95 do {
96 XEvent event;
97 if (!(source->flags & QEventLoop::ExcludeUserInputEvents)
98 && !source->d->queuedUserInputEvents.isEmpty()) {
99 // process a pending user input event
100 event = source->d->queuedUserInputEvents.takeFirst();
101 } else if (XEventsQueued(X11->display, QueuedAlready)) {
102 // process events from the X server
103 XNextEvent(X11->display, &event);
104
105 if (source->flags & QEventLoop::ExcludeUserInputEvents) {
106 // queue user input events
107 switch (event.type) {
108 case ButtonPress:
109 case ButtonRelease:
110 case MotionNotify:
111 case XKeyPress:
112 case XKeyRelease:
113 case EnterNotify:
114 case LeaveNotify:
115 source->d->queuedUserInputEvents.append(event);
116 continue;
117
118 case ClientMessage:
119 // only keep the wm_take_focus and
120 // _qt_scrolldone protocols, queue all other
121 // client messages
122 if (event.xclient.format == 32) {
123 if (event.xclient.message_type == ATOM(WM_PROTOCOLS) ||
124 (Atom) event.xclient.data.l[0] == ATOM(WM_TAKE_FOCUS)) {
125 break;
126 } else if (event.xclient.message_type == ATOM(_QT_SCROLL_DONE)) {
127 break;
128 }
129 }
130 source->d->queuedUserInputEvents.append(event);
131 continue;
132
133 default:
134 break;
135 }
136 }
137 } else {
138 // no event to process
139 break;
140 }
141
142 // send through event filter
143 if (source->q->filterEvent(&event))
144 continue;
145
146 if (qApp->x11ProcessEvent(&event) == 1)
147 return true;
148
149 if (event.xany.serial >= marker)
150 goto out;
151 } while (XEventsQueued(X11->display, QueuedAfterFlush));
152
153 out:
154
155 if (callback)
156 callback(user_data);
157 return true;
158}
159
160static GSourceFuncs x11EventSourceFuncs = {
161 x11EventSourcePrepare,
162 x11EventSourceCheck,
163 x11EventSourceDispatch,
164 NULL,
165 NULL,
166 NULL
167};
168
169QGuiEventDispatcherGlibPrivate::QGuiEventDispatcherGlibPrivate()
170{
171 x11EventSource = reinterpret_cast<GX11EventSource *>(g_source_new(&x11EventSourceFuncs,
172 sizeof(GX11EventSource)));
173 g_source_set_can_recurse(&x11EventSource->source, true);
174
175 memset(&x11EventSource->pollfd, 0, sizeof(GPollFD));
176 x11EventSource->flags = QEventLoop::AllEvents;
177 x11EventSource->q = 0;
178 x11EventSource->d = 0;
179
180 g_source_attach(&x11EventSource->source, mainContext);
181}
182
183QGuiEventDispatcherGlib::QGuiEventDispatcherGlib(QObject *parent)
184 : QEventDispatcherGlib(*new QGuiEventDispatcherGlibPrivate, parent)
185{
186}
187
188QGuiEventDispatcherGlib::~QGuiEventDispatcherGlib()
189{
190 Q_D(QGuiEventDispatcherGlib);
191
192 g_source_remove_poll(&d->x11EventSource->source, &d->x11EventSource->pollfd);
193 g_source_destroy(&d->x11EventSource->source);
194 d->x11EventSource = 0;
195}
196
197bool QGuiEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
198{
199 Q_D(QGuiEventDispatcherGlib);
200 QEventLoop::ProcessEventsFlags saved_flags = d->x11EventSource->flags;
201 d->x11EventSource->flags = flags;
202 bool returnValue = QEventDispatcherGlib::processEvents(flags);
203 d->x11EventSource->flags = saved_flags;
204 return returnValue;
205}
206
207void QGuiEventDispatcherGlib::startingUp()
208{
209 Q_D(QGuiEventDispatcherGlib);
210 d->x11EventSource->pollfd.fd = XConnectionNumber(X11->display);
211 d->x11EventSource->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
212 d->x11EventSource->q = this;
213 d->x11EventSource->d = d;
214 g_source_add_poll(&d->x11EventSource->source, &d->x11EventSource->pollfd);
215}
216
217QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.