Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(566)

Side by Side Diff: base/message_pump_glib_x.cc

Issue 7050030: Fixing the issue of GDK discarding unsupported XInput events. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: addressing some comments Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/message_pump_glib_x.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/message_pump_glib_x.h" 5 #include "base/message_pump_glib_x.h"
6 6
7 #include <gdk/gdkx.h> 7 #include <gdk/gdkx.h>
8 #if defined(HAVE_XINPUT2) 8 #if defined(HAVE_XINPUT2)
9 #include <X11/extensions/XInput2.h> 9 #include <X11/extensions/XInput2.h>
10 #else 10 #else
(...skipping 15 matching lines...) Expand all
26 namespace base { 26 namespace base {
27 27
28 MessagePumpGlibX::MessagePumpGlibX() : base::MessagePumpForUI(), 28 MessagePumpGlibX::MessagePumpGlibX() : base::MessagePumpForUI(),
29 #if defined(HAVE_XINPUT2) 29 #if defined(HAVE_XINPUT2)
30 xiopcode_(-1), 30 xiopcode_(-1),
31 #endif 31 #endif
32 gdksource_(NULL), 32 gdksource_(NULL),
33 dispatching_event_(false), 33 dispatching_event_(false),
34 capture_x_events_(0), 34 capture_x_events_(0),
35 capture_gdk_events_(0) { 35 capture_gdk_events_(0) {
36 gdk_window_add_filter(NULL, &GdkEventFilter, this);
36 gdk_event_handler_set(&EventDispatcherX, this, NULL); 37 gdk_event_handler_set(&EventDispatcherX, this, NULL);
37 38
38 #if defined(HAVE_XINPUT2) 39 #if defined(HAVE_XINPUT2)
39 InitializeXInput2(); 40 InitializeXInput2();
40 #endif 41 #endif
41 InitializeEventsToCapture(); 42 InitializeEventsToCapture();
42 } 43 }
43 44
44 MessagePumpGlibX::~MessagePumpGlibX() { 45 MessagePumpGlibX::~MessagePumpGlibX() {
45 } 46 }
46 47
48 bool MessagePumpGlibX::ShouldCaptureXEvent(XEvent* xev) {
49 return capture_x_events_[xev->type]
50 #if defined(HAVE_XINPUT2)
51 && (xev->type != GenericEvent || xev->xcookie.extension == xiopcode_)
52 #endif
53 ;
54 }
55
56
57 bool MessagePumpGlibX::ProcessXEvent(XEvent* xev) {
58 bool should_quit = false;
59
60 #if defined(HAVE_XINPUT2)
61 bool have_cookie = false;
62 if (xev->type == GenericEvent &&
63 XGetEventData(xev->xgeneric.display, &xev->xcookie)) {
64 have_cookie = true;
65 }
66 #endif
67
68 if (!WillProcessXEvent(xev)) {
69 MessagePumpGlibXDispatcher::DispatchStatus status =
70 static_cast<MessagePumpGlibXDispatcher*>
71 (GetDispatcher())->DispatchX(xev);
72
73 if (status == MessagePumpGlibXDispatcher::EVENT_QUIT) {
74 should_quit = true;
75 Quit();
76 } else if (status == MessagePumpGlibXDispatcher::EVENT_IGNORED) {
77 DLOG(WARNING) << "Event (" << xev->type << ") not handled.";
78 }
79 }
80
81 #if defined(HAVE_XINPUT2)
82 if (have_cookie) {
83 XFreeEventData(xev->xgeneric.display, &xev->xcookie);
84 }
85 #endif
86
87 return should_quit;
88 }
89
47 bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) { 90 bool MessagePumpGlibX::RunOnce(GMainContext* context, bool block) {
48 GdkDisplay* gdisp = gdk_display_get_default(); 91 GdkDisplay* gdisp = gdk_display_get_default();
49 if (!gdisp || !GetDispatcher()) 92 if (!gdisp || !GetDispatcher())
50 return MessagePumpForUI::RunOnce(context, block); 93 return MessagePumpForUI::RunOnce(context, block);
51 94
52 Display* display = GDK_DISPLAY_XDISPLAY(gdisp); 95 Display* display = GDK_DISPLAY_XDISPLAY(gdisp);
53 bool should_quit = false;
54 96
55 if (XPending(display)) { 97 if (XPending(display)) {
56 XEvent xev; 98 XEvent xev;
57 XPeekEvent(display, &xev); 99 XPeekEvent(display, &xev);
58 if (capture_x_events_[xev.type] 100
59 #if defined(HAVE_XINPUT2) 101 if (ShouldCaptureXEvent(&xev)) {
60 && (xev.type != GenericEvent || xev.xcookie.extension == xiopcode_)
61 #endif
62 ) {
63 XNextEvent(display, &xev); 102 XNextEvent(display, &xev);
64 103 if (ProcessXEvent(&xev))
65 #if defined(HAVE_XINPUT2) 104 return true;
66 bool have_cookie = false;
67 if (xev.type == GenericEvent &&
68 XGetEventData(xev.xgeneric.display, &xev.xcookie)) {
69 have_cookie = true;
70 }
71 #endif
72
73 if (!WillProcessXEvent(&xev)) {
74 MessagePumpGlibXDispatcher::DispatchStatus status =
75 static_cast<MessagePumpGlibXDispatcher*>
76 (GetDispatcher())->DispatchX(&xev);
77
78 if (status == MessagePumpGlibXDispatcher::EVENT_QUIT) {
79 should_quit = true;
80 Quit();
81 } else if (status == MessagePumpGlibXDispatcher::EVENT_IGNORED) {
82 DLOG(WARNING) << "Event (" << xev.type << ") not handled.";
83 }
84 }
85
86 #if defined(HAVE_XINPUT2)
87 if (have_cookie) {
88 XFreeEventData(xev.xgeneric.display, &xev.xcookie);
89 }
90 #endif
91 } else { 105 } else {
92 // TODO(sad): A couple of extra events can still sneak in during this. 106 // TODO(sad): A couple of extra events can still sneak in during this.
93 // Those should be sent back to the X queue from the dispatcher 107 // Those should be sent back to the X queue from the dispatcher
94 // EventDispatcherX. 108 // EventDispatcherX.
95 if (gdksource_) 109 if (gdksource_)
96 gdksource_->source_funcs->dispatch = gdkdispatcher_; 110 gdksource_->source_funcs->dispatch = gdkdispatcher_;
97 g_main_context_iteration(context, FALSE); 111 g_main_context_iteration(context, FALSE);
98 } 112 }
99 } 113 }
100 114
101 if (should_quit)
102 return true;
103
104 bool retvalue; 115 bool retvalue;
105 if (gdksource_) { 116 if (gdksource_) {
106 // Replace the dispatch callback of the GDK event source temporarily so that 117 // Replace the dispatch callback of the GDK event source temporarily so that
107 // it doesn't read events from X. 118 // it doesn't read events from X.
108 gboolean (*cb)(GSource*, GSourceFunc, void*) = 119 gboolean (*cb)(GSource*, GSourceFunc, void*) =
109 gdksource_->source_funcs->dispatch; 120 gdksource_->source_funcs->dispatch;
110 gdksource_->source_funcs->dispatch = PlaceholderDispatch; 121 gdksource_->source_funcs->dispatch = PlaceholderDispatch;
111 122
112 dispatching_event_ = true; 123 dispatching_event_ = true;
113 retvalue = g_main_context_iteration(context, block); 124 retvalue = g_main_context_iteration(context, block);
114 dispatching_event_ = false; 125 dispatching_event_ = false;
115 126
116 gdksource_->source_funcs->dispatch = cb; 127 gdksource_->source_funcs->dispatch = cb;
117 } else { 128 } else {
118 retvalue = g_main_context_iteration(context, block); 129 retvalue = g_main_context_iteration(context, block);
119 } 130 }
120 131
121 return retvalue; 132 return retvalue;
122 } 133 }
123 134
135 GdkFilterReturn MessagePumpGlibX::GdkEventFilter(GdkXEvent* gxevent,
136 GdkEvent* gevent,
137 gpointer data) {
138 MessagePumpGlibX* pump = static_cast<MessagePumpGlibX*>(data);
139 XEvent* xev = static_cast<XEvent*>(gxevent);
140
141 if (pump->ShouldCaptureXEvent(xev) && pump->GetDispatcher()) {
142 pump->ProcessXEvent(xev);
143 return GDK_FILTER_REMOVE;
144 }
145
146 return GDK_FILTER_CONTINUE;
147 }
148
124 bool MessagePumpGlibX::WillProcessXEvent(XEvent* xevent) { 149 bool MessagePumpGlibX::WillProcessXEvent(XEvent* xevent) {
125 ObserverListBase<Observer>::Iterator it(observers()); 150 ObserverListBase<Observer>::Iterator it(observers());
126 Observer* obs; 151 Observer* obs;
127 while ((obs = it.GetNext()) != NULL) { 152 while ((obs = it.GetNext()) != NULL) {
128 MessagePumpXObserver* xobs = 153 MessagePumpXObserver* xobs =
129 static_cast<MessagePumpXObserver*>(obs); 154 static_cast<MessagePumpXObserver*>(obs);
130 if (xobs->WillProcessXEvent(xevent)) 155 if (xobs->WillProcessXEvent(xevent))
131 return true; 156 return true;
132 } 157 }
133 return false; 158 return false;
134 } 159 }
135 160
136 void MessagePumpGlibX::EventDispatcherX(GdkEvent* event, gpointer data) { 161 void MessagePumpGlibX::EventDispatcherX(GdkEvent* event, gpointer data) {
137 MessagePumpGlibX* pump_x = reinterpret_cast<MessagePumpGlibX*>(data); 162 MessagePumpGlibX* pump_x = reinterpret_cast<MessagePumpGlibX*>(data);
138 163
139 if (!pump_x->gdksource_) { 164 if (!pump_x->gdksource_) {
140 pump_x->gdksource_ = g_main_current_source(); 165 pump_x->gdksource_ = g_main_current_source();
141 if (pump_x->gdksource_) 166 if (pump_x->gdksource_)
142 pump_x->gdkdispatcher_ = pump_x->gdksource_->source_funcs->dispatch; 167 pump_x->gdkdispatcher_ = pump_x->gdksource_->source_funcs->dispatch;
143 } else if (!pump_x->IsDispatchingEvent()) { 168 } else if (!pump_x->IsDispatchingEvent()) {
144 if (event->type != GDK_NOTHING && 169 if (event->type != GDK_NOTHING &&
145 pump_x->capture_gdk_events_[event->type]) { 170 pump_x->capture_gdk_events_[event->type]) {
146 // TODO(sad): An X event is caught by the GDK handler. Put it back in the 171 NOTREACHED() << "GDK received an event it shouldn't have";
147 // X queue so that we catch it in the next iteration. When done, the
148 // following DLOG statement will be removed.
149 DLOG(WARNING) << "GDK received an event it shouldn't have";
150 } 172 }
151 } 173 }
152 174
153 pump_x->DispatchEvents(event); 175 pump_x->DispatchEvents(event);
154 } 176 }
155 177
156 void MessagePumpGlibX::InitializeEventsToCapture(void) { 178 void MessagePumpGlibX::InitializeEventsToCapture(void) {
157 // TODO(sad): Decide which events we want to capture and update the tables 179 // TODO(sad): Decide which events we want to capture and update the tables
158 // accordingly. 180 // accordingly.
159 capture_x_events_[KeyPress] = true; 181 capture_x_events_[KeyPress] = true;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 return; 220 return;
199 } 221 }
200 } 222 }
201 #endif // HAVE_XINPUT2 223 #endif // HAVE_XINPUT2
202 224
203 bool MessagePumpXObserver::WillProcessXEvent(XEvent* xev) { 225 bool MessagePumpXObserver::WillProcessXEvent(XEvent* xev) {
204 return false; 226 return false;
205 } 227 }
206 228
207 } // namespace base 229 } // namespace base
OLDNEW
« no previous file with comments | « base/message_pump_glib_x.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698