source: trunk/src/gui/kernel/qguieventdispatcher_glib.cpp@ 858

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

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

File size: 7.4 KB
RevLine 
[2]1/****************************************************************************
2**
[846]3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
[561]4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
[2]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**
[561]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.
[2]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**
[561]36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
[2]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) {
[561]123 if (event.xclient.message_type == ATOM(WM_PROTOCOLS) &&
[2]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
[561]155 source->d->runTimersOnceWithNormalPriority();
156
[2]157 if (callback)
158 callback(user_data);
159 return true;
160}
161
162static GSourceFuncs x11EventSourceFuncs = {
163 x11EventSourcePrepare,
164 x11EventSourceCheck,
165 x11EventSourceDispatch,
166 NULL,
167 NULL,
168 NULL
169};
170
171QGuiEventDispatcherGlibPrivate::QGuiEventDispatcherGlibPrivate()
172{
173 x11EventSource = reinterpret_cast<GX11EventSource *>(g_source_new(&x11EventSourceFuncs,
174 sizeof(GX11EventSource)));
175 g_source_set_can_recurse(&x11EventSource->source, true);
176
177 memset(&x11EventSource->pollfd, 0, sizeof(GPollFD));
178 x11EventSource->flags = QEventLoop::AllEvents;
179 x11EventSource->q = 0;
180 x11EventSource->d = 0;
181
182 g_source_attach(&x11EventSource->source, mainContext);
183}
184
185QGuiEventDispatcherGlib::QGuiEventDispatcherGlib(QObject *parent)
186 : QEventDispatcherGlib(*new QGuiEventDispatcherGlibPrivate, parent)
187{
188}
189
190QGuiEventDispatcherGlib::~QGuiEventDispatcherGlib()
191{
192 Q_D(QGuiEventDispatcherGlib);
193
194 g_source_remove_poll(&d->x11EventSource->source, &d->x11EventSource->pollfd);
195 g_source_destroy(&d->x11EventSource->source);
196 d->x11EventSource = 0;
197}
198
199bool QGuiEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
200{
201 Q_D(QGuiEventDispatcherGlib);
202 QEventLoop::ProcessEventsFlags saved_flags = d->x11EventSource->flags;
203 d->x11EventSource->flags = flags;
204 bool returnValue = QEventDispatcherGlib::processEvents(flags);
205 d->x11EventSource->flags = saved_flags;
206 return returnValue;
207}
208
209void QGuiEventDispatcherGlib::startingUp()
210{
211 Q_D(QGuiEventDispatcherGlib);
212 d->x11EventSource->pollfd.fd = XConnectionNumber(X11->display);
213 d->x11EventSource->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
214 d->x11EventSource->q = this;
215 d->x11EventSource->d = d;
216 g_source_add_poll(&d->x11EventSource->source, &d->x11EventSource->pollfd);
217}
218
[846]219void QGuiEventDispatcherGlib::flush()
220{
221 XFlush(X11->display);
222}
223
[2]224QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.