| 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(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 166 } | 114 } |
| 167 | 115 |
| 168 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(cookie->data); | 116 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(cookie->data); |
| 169 xwindow = xiev->event; | 117 xwindow = xiev->event; |
| 170 } | 118 } |
| 171 #endif | 119 #endif |
| 172 | 120 |
| 173 GdkWindow* gwind = gdk_window_lookup_for_display(gdisp, xwindow); | 121 GdkWindow* gwind = gdk_window_lookup_for_display(gdisp, xwindow); |
| 174 Widget* widget = FindWidgetForGdkWindow(gwind); | 122 Widget* widget = FindWidgetForGdkWindow(gwind); |
| 175 if (widget) { | 123 if (widget) { |
| 176 RootView* root = widget->GetRootView(); | 124 Event::FromNativeEvent2 from_native; |
| 177 switch (xev->type) { | 125 switch (xev->type) { |
| 178 case KeyPress: | 126 case KeyPress: |
| 179 case KeyRelease: { | 127 case KeyRelease: { |
| 180 Event::FromNativeEvent2 from_native; | |
| 181 KeyEvent keyev(xev, from_native); | 128 KeyEvent keyev(xev, from_native); |
| 182 InputMethod* ime = widget->GetInputMethod(); | 129 return widget->OnKeyEvent(keyev); |
| 183 // Always dispatch key events to the input method first, to make sure | |
| 184 // that the input method's hotkeys work all time. | |
| 185 if (ime) { | |
| 186 ime->DispatchKeyEvent(keyev); | |
| 187 return true; | |
| 188 } | |
| 189 return root->ProcessKeyEvent(keyev); | |
| 190 } | 130 } |
| 191 | |
| 192 case ButtonPress: | 131 case ButtonPress: |
| 193 case ButtonRelease: { | 132 case ButtonRelease: |
| 194 if (xev->xbutton.button == 4 || xev->xbutton.button == 5) { | 133 if (xev->xbutton.button == 4 || xev->xbutton.button == 5) { |
| 195 // Scrolling the wheel triggers button press/release events. | 134 // Scrolling the wheel triggers button press/release events. |
| 196 Event::FromNativeEvent2 from_native; | |
| 197 MouseWheelEvent wheelev(xev, from_native); | 135 MouseWheelEvent wheelev(xev, from_native); |
| 198 return root->OnMouseWheel(wheelev); | 136 return widget->OnMouseEvent(wheelev); |
| 199 } else { | |
| 200 Event::FromNativeEvent2 from_native; | |
| 201 MouseEvent mouseev(xev, from_native); | |
| 202 if (xev->type == ButtonPress) { | |
| 203 return root->OnMousePressed(mouseev); | |
| 204 } else { | |
| 205 root->OnMouseReleased(mouseev); | |
| 206 return true; // Assume the event has been processed to make sure we | |
| 207 // don't process it twice. | |
| 208 } | |
| 209 } | 137 } |
| 138 // fallthrough |
| 139 case MotionNotify: { |
| 140 MouseEvent mouseev(xev, from_native); |
| 141 return widget->OnMouseEvent(mouseev); |
| 210 } | 142 } |
| 211 | |
| 212 case MotionNotify: { | |
| 213 Event::FromNativeEvent2 from_native; | |
| 214 MouseEvent mouseev(xev, from_native); | |
| 215 if (mouseev.type() == ui::ET_MOUSE_DRAGGED) { | |
| 216 return root->OnMouseDragged(mouseev); | |
| 217 } else { | |
| 218 root->OnMouseMoved(mouseev); | |
| 219 return true; | |
| 220 } | |
| 221 } | |
| 222 | |
| 223 #if defined(HAVE_XINPUT2) | 143 #if defined(HAVE_XINPUT2) |
| 224 case GenericEvent: { | 144 case GenericEvent: { |
| 225 return DispatchX2Event(root, xev); | 145 return DispatchX2Event(widget, xev); |
| 226 } | 146 } |
| 227 #endif | 147 #endif |
| 228 } | 148 } |
| 229 } | 149 } |
| 230 | 150 |
| 231 return false; | 151 return false; |
| 232 } | 152 } |
| 233 | 153 |
| 234 #if defined(HAVE_XINPUT2) | 154 #if defined(HAVE_XINPUT2) |
| 235 void SetTouchDeviceList(std::vector<unsigned int>& devices) { | 155 void SetTouchDeviceList(std::vector<unsigned int>& devices) { |
| 236 TouchFactory::GetInstance()->SetTouchDeviceList(devices); | 156 TouchFactory::GetInstance()->SetTouchDeviceList(devices); |
| 237 } | 157 } |
| 238 #endif | 158 #endif |
| 239 | 159 |
| 240 AcceleratorHandler::AcceleratorHandler() {} | 160 AcceleratorHandler::AcceleratorHandler() {} |
| 241 | 161 |
| 242 bool AcceleratorHandler::Dispatch(GdkEvent* event) { | 162 bool AcceleratorHandler::Dispatch(GdkEvent* event) { |
| 243 gtk_main_do_event(event); | 163 gtk_main_do_event(event); |
| 244 return true; | 164 return true; |
| 245 } | 165 } |
| 246 | 166 |
| 247 base::MessagePumpGlibXDispatcher::DispatchStatus | 167 base::MessagePumpGlibXDispatcher::DispatchStatus |
| 248 AcceleratorHandler::DispatchX(XEvent* xev) { | 168 AcceleratorHandler::DispatchX(XEvent* xev) { |
| 249 return DispatchXEvent(xev) ? | 169 return DispatchXEvent(xev) ? |
| 250 base::MessagePumpGlibXDispatcher::EVENT_PROCESSED : | 170 base::MessagePumpGlibXDispatcher::EVENT_PROCESSED : |
| 251 base::MessagePumpGlibXDispatcher::EVENT_IGNORED; | 171 base::MessagePumpGlibXDispatcher::EVENT_IGNORED; |
| 252 } | 172 } |
| 253 | 173 |
| 254 } // namespace views | 174 } // namespace views |
| OLD | NEW |