| 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 "views/focus/accelerator_handler.h" | 5 #include "views/focus/accelerator_handler.h" |
| 6 | 6 |
| 7 #include <bitset> | 7 #include <bitset> |
| 8 #include <gtk/gtk.h> | 8 #include <gtk/gtk.h> |
| 9 #if defined(HAVE_XINPUT2) | 9 #if defined(HAVE_XINPUT2) |
| 10 #include <X11/extensions/XInput2.h> | 10 #include <X11/extensions/XInput2.h> |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 } | 34 } |
| 35 NativeWidget* widget = NativeWidget::GetNativeWidgetForNativeView(gtk_widget); | 35 NativeWidget* widget = NativeWidget::GetNativeWidgetForNativeView(gtk_widget); |
| 36 | 36 |
| 37 if (!widget) { | 37 if (!widget) { |
| 38 DLOG(WARNING) << "no WidgetGtk found for that GtkWidget"; | 38 DLOG(WARNING) << "no WidgetGtk found for that GtkWidget"; |
| 39 return NULL; | 39 return NULL; |
| 40 } | 40 } |
| 41 return widget->GetWidget(); | 41 return widget->GetWidget(); |
| 42 } | 42 } |
| 43 | 43 |
| 44 #if defined(HAVE_XINPUT2) | |
| 45 bool X2EventIsTouchEvent(XEvent* xev) { | |
| 46 // TODO(sad): Determine if the captured event is a touch-event. | |
| 47 XGenericEventCookie* cookie = &xev->xcookie; | |
| 48 switch (cookie->evtype) { | |
| 49 case XI_ButtonPress: | |
| 50 case XI_ButtonRelease: | |
| 51 case XI_Motion: { | |
| 52 // Is the event coming from a touch device? | |
| 53 return TouchFactory::GetInstance()->IsTouchDevice( | |
| 54 static_cast<XIDeviceEvent*>(cookie->data)->sourceid); | |
| 55 } | |
| 56 default: | |
| 57 return false; | |
| 58 } | |
| 59 } | |
| 60 #endif // HAVE_XINPUT2 | |
| 61 | |
| 62 } // namespace | 44 } // namespace |
| 63 | 45 |
| 64 #if defined(HAVE_XINPUT2) | 46 #if defined(HAVE_XINPUT2) |
| 65 bool DispatchX2Event(RootView* root, XEvent* xev) { | 47 bool DispatchX2Event(Widget* widget, XEvent* xev) { |
| 66 XGenericEventCookie* cookie = &xev->xcookie; | 48 XGenericEventCookie* cookie = &xev->xcookie; |
| 67 bool touch_event = false; | |
| 68 | |
| 69 if (X2EventIsTouchEvent(xev)) { | |
| 70 // Hide the cursor when a touch event comes in. | |
| 71 TouchFactory::GetInstance()->SetCursorVisible(false, false); | |
| 72 touch_event = true; | |
| 73 | |
| 74 // Create a TouchEvent, and send it off to |root|. If the event | |
| 75 // is processed by |root|, then return. Otherwise let it fall through so it | |
| 76 // can be used (if desired) as a mouse event. | |
| 77 Event::FromNativeEvent2 from_native; | |
| 78 TouchEvent touch(xev, from_native); | |
| 79 if (root->OnTouchEvent(touch) != views::View::TOUCH_STATUS_UNKNOWN) | |
| 80 return true; | |
| 81 } | |
| 82 | |
| 83 switch (cookie->evtype) { | 49 switch (cookie->evtype) { |
| 84 case XI_KeyPress: | 50 case XI_KeyPress: |
| 85 case XI_KeyRelease: { | 51 case XI_KeyRelease: { |
| 86 // TODO(sad): We don't capture XInput2 events from keyboard yet. | 52 // TODO(sad): We don't capture XInput2 events from keyboard yet. |
| 87 break; | 53 break; |
| 88 } | 54 } |
| 89 case XI_ButtonPress: | 55 case XI_ButtonPress: |
| 90 case XI_ButtonRelease: | 56 case XI_ButtonRelease: |
| 91 case XI_Motion: { | 57 case XI_Motion: { |
| 58 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(cookie->data); |
| 59 Event::FromNativeEvent2 from_native; |
| 60 |
| 92 // Scrolling the wheel generates press/release events with button id's 4 | 61 // Scrolling the wheel generates press/release events with button id's 4 |
| 93 // and 5. In case of a wheelscroll, we do not want to show the cursor. | 62 // and 5. In case of a wheelscroll, we do not want to show the cursor. |
| 94 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(cookie->data); | |
| 95 if (xievent->detail == 4 || xievent->detail == 5) { | 63 if (xievent->detail == 4 || xievent->detail == 5) { |
| 96 Event::FromNativeEvent2 from_native; | |
| 97 MouseWheelEvent wheelev(xev, from_native); | 64 MouseWheelEvent wheelev(xev, from_native); |
| 98 return root->OnMouseWheel(wheelev); | 65 return widget->OnMouseEvent(wheelev); |
| 99 } | 66 } |
| 100 | 67 |
| 101 Event::FromNativeEvent2 from_native; | |
| 102 MouseEvent mouseev(xev, from_native); | 68 MouseEvent mouseev(xev, from_native); |
| 103 if (!touch_event) { | |
| 104 // Show the cursor, and decide whether or not the cursor should be | |
| 105 // automatically hidden after a certain time of inactivity. | |
| 106 int button_flags = mouseev.flags() & (ui::EF_RIGHT_BUTTON_DOWN | | |
| 107 ui::EF_MIDDLE_BUTTON_DOWN | ui::EF_LEFT_BUTTON_DOWN); | |
| 108 bool start_timer = false; | |
| 109 | 69 |
| 110 switch (cookie->evtype) { | 70 // TODO(sad): Determine if the captured event is a touch-event. |
| 111 case XI_ButtonPress: | 71 // Is the event coming from a touch device? |
| 112 start_timer = false; | 72 if (TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid)) { |
| 113 break; | 73 // Hide the cursor when a touch event comes in. |
| 114 case XI_ButtonRelease: | 74 TouchFactory::GetInstance()->SetCursorVisible(false, false); |
| 115 // For a release, start the timer if this was only button pressed | 75 // If the TouchEvent is processed by |root|, then return. Otherwise let |
| 116 // that is being released. | 76 // it fall through so it can be used as a MouseEvent, if desired. |
| 117 if (button_flags == ui::EF_RIGHT_BUTTON_DOWN || | 77 TouchEvent touch(xev, from_native); |
| 118 button_flags == ui::EF_LEFT_BUTTON_DOWN || | 78 RootView* root = widget->GetRootView(); |
| 119 button_flags == ui::EF_MIDDLE_BUTTON_DOWN) | 79 if (root->OnTouchEvent(touch) != views::View::TOUCH_STATUS_UNKNOWN) |
| 120 start_timer = true; | 80 return true; |
| 121 break; | 81 } else { |
| 122 case XI_Motion: | 82 // Show the cursor. Start a timer to hide the cursor after a delay on |
| 123 start_timer = !button_flags; | 83 // move (not drag) events, or if the only button pressed is released. |
| 124 break; | 84 bool start_timer = mouseev.type() == ui::ET_MOUSE_MOVED; |
| 125 } | 85 start_timer |= mouseev.type() == ui::ET_MOUSE_RELEASED && |
| 86 (mouseev.IsOnlyLeftMouseButton() || |
| 87 mouseev.IsOnlyMiddleMouseButton() || |
| 88 mouseev.IsOnlyRightMouseButton()); |
| 126 TouchFactory::GetInstance()->SetCursorVisible(true, start_timer); | 89 TouchFactory::GetInstance()->SetCursorVisible(true, start_timer); |
| 127 } | 90 } |
| 128 | 91 |
| 129 // Dispatch the event. | 92 return widget->OnMouseEvent(mouseev); |
| 130 switch (cookie->evtype) { | |
| 131 case XI_ButtonPress: | |
| 132 return root->OnMousePressed(mouseev); | |
| 133 case XI_ButtonRelease: | |
| 134 root->OnMouseReleased(mouseev); | |
| 135 return true; | |
| 136 case XI_Motion: { | |
| 137 if (mouseev.type() == ui::ET_MOUSE_DRAGGED) { | |
| 138 return root->OnMouseDragged(mouseev); | |
| 139 } else { | |
| 140 root->OnMouseMoved(mouseev); | |
| 141 return true; | |
| 142 } | |
| 143 } | |
| 144 } | |
| 145 } | 93 } |
| 146 } | 94 } |
| 147 | 95 |
| 148 return false; | 96 return false; |
| 149 } | 97 } |
| 150 | 98 |
| 151 #endif // HAVE_XINPUT2 | 99 #endif // HAVE_XINPUT2 |
| 152 | 100 |
| 153 bool DispatchXEvent(XEvent* xev) { | 101 bool DispatchXEvent(XEvent* xev) { |
| 154 GdkDisplay* gdisp = gdk_display_get_default(); | 102 GdkDisplay* gdisp = gdk_display_get_default(); |
| 155 XID xwindow = xev->xany.window; | 103 XID xwindow = xev->xany.window; |
| 156 | 104 |
| 157 #if defined(HAVE_XINPUT2) | 105 #if defined(HAVE_XINPUT2) |
| 158 if (xev->type == GenericEvent) { | 106 if (xev->type == GenericEvent) { |
| 159 XGenericEventCookie* cookie = &xev->xcookie; | 107 XGenericEventCookie* cookie = &xev->xcookie; |
| 160 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(cookie->data); | 108 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(cookie->data); |
| 161 xwindow = xiev->event; | 109 xwindow = xiev->event; |
| 162 } | 110 } |
| 163 #endif | 111 #endif |
| 164 | 112 |
| 165 GdkWindow* gwind = gdk_window_lookup_for_display(gdisp, xwindow); | 113 GdkWindow* gwind = gdk_window_lookup_for_display(gdisp, xwindow); |
| 166 Widget* widget = FindWidgetForGdkWindow(gwind); | 114 Widget* widget = FindWidgetForGdkWindow(gwind); |
| 167 if (widget) { | 115 if (widget) { |
| 168 RootView* root = widget->GetRootView(); | 116 Event::FromNativeEvent2 from_native; |
| 169 switch (xev->type) { | 117 switch (xev->type) { |
| 170 case KeyPress: | 118 case KeyPress: |
| 171 case KeyRelease: { | 119 case KeyRelease: { |
| 172 Event::FromNativeEvent2 from_native; | |
| 173 KeyEvent keyev(xev, from_native); | 120 KeyEvent keyev(xev, from_native); |
| 174 InputMethod* ime = widget->GetInputMethod(); | 121 return widget->OnKeyEvent(keyev); |
| 175 // Always dispatch key events to the input method first, to make sure | |
| 176 // that the input method's hotkeys work all time. | |
| 177 if (ime) { | |
| 178 ime->DispatchKeyEvent(keyev); | |
| 179 return true; | |
| 180 } | |
| 181 return root->ProcessKeyEvent(keyev); | |
| 182 } | 122 } |
| 183 | |
| 184 case ButtonPress: | 123 case ButtonPress: |
| 185 case ButtonRelease: { | 124 case ButtonRelease: |
| 186 if (xev->xbutton.button == 4 || xev->xbutton.button == 5) { | 125 if (xev->xbutton.button == 4 || xev->xbutton.button == 5) { |
| 187 // Scrolling the wheel triggers button press/release events. | 126 // Scrolling the wheel triggers button press/release events. |
| 188 Event::FromNativeEvent2 from_native; | |
| 189 MouseWheelEvent wheelev(xev, from_native); | 127 MouseWheelEvent wheelev(xev, from_native); |
| 190 return root->OnMouseWheel(wheelev); | 128 return widget->OnMouseEvent(wheelev); |
| 191 } else { | |
| 192 Event::FromNativeEvent2 from_native; | |
| 193 MouseEvent mouseev(xev, from_native); | |
| 194 if (xev->type == ButtonPress) { | |
| 195 return root->OnMousePressed(mouseev); | |
| 196 } else { | |
| 197 root->OnMouseReleased(mouseev); | |
| 198 return true; // Assume the event has been processed to make sure we | |
| 199 // don't process it twice. | |
| 200 } | |
| 201 } | 129 } |
| 130 // fallthrough |
| 131 case MotionNotify: { |
| 132 MouseEvent mouseev(xev, from_native); |
| 133 return widget->OnMouseEvent(mouseev); |
| 202 } | 134 } |
| 203 | |
| 204 case MotionNotify: { | |
| 205 Event::FromNativeEvent2 from_native; | |
| 206 MouseEvent mouseev(xev, from_native); | |
| 207 if (mouseev.type() == ui::ET_MOUSE_DRAGGED) { | |
| 208 return root->OnMouseDragged(mouseev); | |
| 209 } else { | |
| 210 root->OnMouseMoved(mouseev); | |
| 211 return true; | |
| 212 } | |
| 213 } | |
| 214 | |
| 215 #if defined(HAVE_XINPUT2) | 135 #if defined(HAVE_XINPUT2) |
| 216 case GenericEvent: { | 136 case GenericEvent: { |
| 217 return DispatchX2Event(root, xev); | 137 return DispatchX2Event(widget, xev); |
| 218 } | 138 } |
| 219 #endif | 139 #endif |
| 220 } | 140 } |
| 221 } | 141 } |
| 222 | 142 |
| 223 return false; | 143 return false; |
| 224 } | 144 } |
| 225 | 145 |
| 226 #if defined(HAVE_XINPUT2) | 146 #if defined(HAVE_XINPUT2) |
| 227 void SetTouchDeviceList(std::vector<unsigned int>& devices) { | 147 void SetTouchDeviceList(std::vector<unsigned int>& devices) { |
| 228 TouchFactory::GetInstance()->SetTouchDeviceList(devices); | 148 TouchFactory::GetInstance()->SetTouchDeviceList(devices); |
| 229 } | 149 } |
| 230 #endif | 150 #endif |
| 231 | 151 |
| 232 AcceleratorHandler::AcceleratorHandler() {} | 152 AcceleratorHandler::AcceleratorHandler() {} |
| 233 | 153 |
| 234 bool AcceleratorHandler::Dispatch(GdkEvent* event) { | 154 bool AcceleratorHandler::Dispatch(GdkEvent* event) { |
| 235 gtk_main_do_event(event); | 155 gtk_main_do_event(event); |
| 236 return true; | 156 return true; |
| 237 } | 157 } |
| 238 | 158 |
| 239 base::MessagePumpGlibXDispatcher::DispatchStatus | 159 base::MessagePumpGlibXDispatcher::DispatchStatus |
| 240 AcceleratorHandler::DispatchX(XEvent* xev) { | 160 AcceleratorHandler::DispatchX(XEvent* xev) { |
| 241 return DispatchXEvent(xev) ? | 161 return DispatchXEvent(xev) ? |
| 242 base::MessagePumpGlibXDispatcher::EVENT_PROCESSED : | 162 base::MessagePumpGlibXDispatcher::EVENT_PROCESSED : |
| 243 base::MessagePumpGlibXDispatcher::EVENT_IGNORED; | 163 base::MessagePumpGlibXDispatcher::EVENT_IGNORED; |
| 244 } | 164 } |
| 245 | 165 |
| 246 } // namespace views | 166 } // namespace views |
| OLD | NEW |