OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |