Index: ui/wayland/wayland_input_device.cc |
diff --git a/ui/wayland/wayland_input_device.cc b/ui/wayland/wayland_input_device.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..250cded5d0fe3900575b2c76cfc035668c360276 |
--- /dev/null |
+++ b/ui/wayland/wayland_input_device.cc |
@@ -0,0 +1,541 @@ |
+// Copyright 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ui/wayland/wayland_input_device.h" |
+ |
+#include <X11/X.h> |
+#include <linux/input.h> |
+#include <wayland-client.h> |
+ |
+#include <wayland-egl.h> |
+#include <GLES2/gl2.h> |
+#include <GLES2/gl2ext.h> |
+#include <EGL/egl.h> |
+#include <EGL/eglext.h> |
+ |
+#include "base/wayland/wayland_event.h" |
+#include "ui/wayland/wayland_delegate.h" |
+#include "ui/wayland/wayland_window.h" |
+#include "ui/base/events/event.h" |
+#include "ui/base/events/event_constants.h" |
+#include "ui/base/hit_test.h" |
+#include "ui/base/ui_base_types.h" |
+ |
+using namespace base::wayland; |
+ |
+namespace ui { |
+ |
+// static |
+BoundsChangeType WaylandInputDevice::GetBoundsChangeForWindowComponent(int component) |
+{ |
+ BoundsChangeType bounds_change = kBoundsChange_None; |
+ switch (component) { |
+ case HTCAPTION: |
+ bounds_change = kBoundsChange_Repositions; |
+ break; |
+ case HTTOPLEFT: |
+ case HTTOP: |
+ case HTTOPRIGHT: |
+ case HTLEFT: |
+ case HTBOTTOMLEFT: |
+ case HTRIGHT: |
+ case HTBOTTOMRIGHT: |
+ case HTBOTTOM: |
+ //case HTGROWBOX: |
+ bounds_change = kBoundsChange_Resizes; |
+ break; |
+ default: |
+ break; |
+ } |
+ return bounds_change; |
+} |
+ |
+// static |
+int WaylandInputDevice::GetPointerImageForWindowComponent(int component) |
+{ |
+ WindowLocation location = WaylandInputDevice::GetLocationForWindowComponent(component); |
+ |
+ switch (location) { |
+ case WINDOW_RESIZING_TOP: |
+ return CURSOR_TOP; |
+ case WINDOW_RESIZING_BOTTOM: |
+ return CURSOR_BOTTOM; |
+ case WINDOW_RESIZING_LEFT: |
+ return CURSOR_LEFT; |
+ case WINDOW_RESIZING_RIGHT: |
+ return CURSOR_RIGHT; |
+ case WINDOW_RESIZING_TOP_LEFT: |
+ return CURSOR_TOP_LEFT; |
+ case WINDOW_RESIZING_TOP_RIGHT: |
+ return CURSOR_TOP_RIGHT; |
+ case WINDOW_RESIZING_BOTTOM_LEFT: |
+ return CURSOR_BOTTOM_LEFT; |
+ case WINDOW_RESIZING_BOTTOM_RIGHT: |
+ return CURSOR_BOTTOM_RIGHT; |
+ case WINDOW_EXTERIOR: |
+ case WINDOW_TITLEBAR: |
+ default: |
+ return CURSOR_LEFT_PTR; |
+ } |
+} |
+ |
+// static |
+WindowLocation WaylandInputDevice::GetLocationForWindowComponent(int component) |
+{ |
+ WindowLocation location = WINDOW_INTERIOR; |
+ switch (component) { |
+ case HTCAPTION: |
+ location = WINDOW_TITLEBAR; |
+ break; |
+ case HTTOPLEFT: |
+ location = WINDOW_RESIZING_TOP_LEFT; |
+ break; |
+ case HTTOP: |
+ location = WINDOW_RESIZING_TOP; |
+ break; |
+ case HTTOPRIGHT: |
+ location = WINDOW_RESIZING_TOP_RIGHT; |
+ break; |
+ case HTLEFT: |
+ location = WINDOW_RESIZING_LEFT; |
+ break; |
+ case HTBOTTOMLEFT: |
+ location = WINDOW_RESIZING_BOTTOM_LEFT; |
+ break; |
+ case HTRIGHT: |
+ location = WINDOW_RESIZING_RIGHT; |
+ break; |
+ case HTBOTTOMRIGHT: |
+ location = WINDOW_RESIZING_BOTTOM_RIGHT; |
+ break; |
+ case HTBOTTOM: |
+ location = WINDOW_RESIZING_BOTTOM; |
+ break; |
+ default: |
+ break; |
+ } |
+ return location; |
+} |
+ |
+WaylandInputDevice::WaylandInputDevice(WaylandDisplay* disp, uint32_t id) |
+ : input_seat_(NULL), |
+ display_(disp->display()), |
+ current_pointer_image_(CURSOR_LEFT_PTR), |
+ input_pointer_(NULL), |
+ input_keyboard_(NULL), |
+ pointer_focus_(NULL), |
+ keyboard_focus_(NULL), |
+ keyboard_modifiers_(0) |
+{ |
+ static const struct wl_seat_listener kInputSeatListener = { |
+ WaylandInputDevice::OnSeatCapabilities, |
+ }; |
+ |
+ input_seat_ = static_cast<wl_seat*>( |
+ wl_registry_bind(disp->registry(), id, &wl_seat_interface, 1)); |
+ wl_seat_add_listener(input_seat_, &kInputSeatListener, this); |
+ wl_seat_set_user_data(input_seat_, this); |
+ |
+ InitXKB(); |
+} |
+ |
+WaylandInputDevice::~WaylandInputDevice() |
+{ |
+ if (input_seat_) |
+ wl_seat_destroy(input_seat_); |
+ |
+ FiniXKB(); |
+} |
+ |
+void WaylandInputDevice::InitXKB() |
+{ |
+ // Initialize XKB |
+ xkb_.names.rules = "evdev"; |
+ xkb_.names.model = "pc105"; |
+ xkb_.names.layout = "us"; |
+ xkb_.names.variant = ""; |
+ xkb_.names.options = ""; |
+ |
+ xkb_.context = xkb_context_new((xkb_context_flags)0); |
+ if (!xkb_.context) { |
+ return; |
+ } |
+ |
+ xkb_.keymap = |
+ xkb_map_new_from_names(xkb_.context, &xkb_.names, (xkb_map_compile_flags)0); |
+ if (!xkb_.keymap) { |
+ return; |
+ } |
+ |
+ xkb_.state = xkb_state_new(xkb_.keymap); |
+ if (!xkb_.state) { |
+ return; |
+ } |
+ |
+ xkb_.control_mask = |
+ 1 << xkb_map_mod_get_index(xkb_.keymap, "Control"); |
+ xkb_.alt_mask = |
+ 1 << xkb_map_mod_get_index(xkb_.keymap, "Mod1"); |
+ xkb_.shift_mask = |
+ 1 << xkb_map_mod_get_index(xkb_.keymap, "Shift"); |
+} |
+ |
+void WaylandInputDevice::FiniXKB() |
+{ |
+ xkb_state_unref(xkb_.state); |
+ xkb_map_unref(xkb_.keymap); |
+ xkb_context_unref(xkb_.context); |
+} |
+ |
+void WaylandInputDevice::OnSeatCapabilities(void *data, wl_seat *seat, uint32_t caps) |
+{ |
+ WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
+ |
+ static const struct wl_pointer_listener kInputPointerListener = { |
+ WaylandInputDevice::OnPointerEnter, |
+ WaylandInputDevice::OnPointerLeave, |
+ WaylandInputDevice::OnMotionNotify, |
+ WaylandInputDevice::OnButtonNotify, |
+ WaylandInputDevice::OnAxisNotify, |
+ }; |
+ |
+ if ((caps & WL_SEAT_CAPABILITY_POINTER) && !device->input_pointer_) { |
+ device->input_pointer_ = wl_seat_get_pointer(seat); |
+ wl_pointer_set_user_data(device->input_pointer_, device); |
+ wl_pointer_add_listener(device->input_pointer_, &kInputPointerListener, |
+ device); |
+ } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && device->input_pointer_) { |
+ wl_pointer_destroy(device->input_pointer_); |
+ device->input_pointer_ = NULL; |
+ } |
+ |
+ static const struct wl_keyboard_listener kInputKeyboardListener = { |
+ WaylandInputDevice::OnKeyboardKeymap, |
+ WaylandInputDevice::OnKeyboardEnter, |
+ WaylandInputDevice::OnKeyboardLeave, |
+ WaylandInputDevice::OnKeyNotify, |
+ WaylandInputDevice::OnKeyModifiers, |
+ }; |
+ |
+ if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !device->input_keyboard_) { |
+ device->input_keyboard_ = wl_seat_get_keyboard(seat); |
+ wl_keyboard_set_user_data(device->input_keyboard_, device); |
+ wl_keyboard_add_listener(device->input_keyboard_, &kInputKeyboardListener, |
+ device); |
+ } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && device->input_keyboard_) { |
+ wl_keyboard_destroy(device->input_keyboard_); |
+ device->input_keyboard_ = NULL; |
+ } |
+} |
+ |
+void WaylandInputDevice::OnMotionNotify(void* data, |
+ wl_pointer* input_pointer, |
+ uint32_t time, |
+ wl_fixed_t sx_w, |
+ wl_fixed_t sy_w) |
+{ |
+ WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
+ WaylandWindow* window = device->pointer_focus_; |
+ GLfloat sx = wl_fixed_to_double(sx_w); |
+ GLfloat sy = wl_fixed_to_double(sy_w); |
+ |
+ device->surface_position_.SetPoint(sx, sy); |
+ |
+ WaylandEvent event; |
+ event.type = WAYLAND_MOTION; |
+ event.motion.time = time; |
+ event.motion.modifiers = device->keyboard_modifiers_; |
+ event.motion.x = sx; |
+ event.motion.y = sy; |
+ |
+ if (!window->delegate()) |
+ return; |
+ |
+ gfx::Point pt(event.motion.x, event.motion.y); |
+ int component = window->delegate()->GetNonClientComponent(pt); |
+ BoundsChangeType type = WaylandInputDevice::GetBoundsChangeForWindowComponent(component); |
+ |
+ switch(type) |
+ { |
+ case kBoundsChange_Resizes: |
+ WaylandDisplay::GetDisplay(device->display_)->SetPointerImage( |
+ device, time, WaylandInputDevice::GetPointerImageForWindowComponent(component)); |
+ break; |
+ case kBoundsChange_Repositions: |
+ default: |
+ WaylandDisplay::GetDisplay(device->display_)->SetPointerImage( |
+ device, time, CURSOR_LEFT_PTR); |
+ break; |
+ } |
+ |
+ if(type == kBoundsChange_None) |
+ window->delegate()->OnMouseEvent(&event); |
+} |
+ |
+void WaylandInputDevice::OnAxisNotify(void* data, |
+ wl_pointer* input_pointer, |
+ uint32_t time, |
+ uint32_t axis, |
+ int32_t value) |
+{ |
+ WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
+ WaylandWindow* window = device->pointer_focus_; |
+ |
+ WaylandEvent event; |
+ event.type = WAYLAND_BUTTON; |
+ event.button.time = time; |
+ event.button.button = value > 0 ? BTN_SIDE : BTN_EXTRA; |
+ event.button.state = 1; |
+ event.button.modifiers = device->keyboard_modifiers_; |
+ event.button.x = device->surface_position_.x(); |
+ event.button.y = device->surface_position_.y(); |
+ |
+ if (!window->delegate()) |
+ return; |
+ |
+ window->delegate()->OnMouseEvent(&event); |
+} |
+ |
+void WaylandInputDevice::OnButtonNotify(void* data, |
+ wl_pointer* input_pointer, |
+ uint32_t serial, |
+ uint32_t time, |
+ uint32_t button, |
+ uint32_t state) |
+{ |
+ WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
+ WaylandWindow* window = device->pointer_focus_; |
+ |
+ WaylandDisplay::GetDisplay(device->display_)->SetSerial(serial); |
+ |
+ WaylandEvent event; |
+ event.type = WAYLAND_BUTTON; |
+ event.button.time = time; |
+ event.button.button = button; |
+ event.button.state = state; |
+ event.button.modifiers = device->keyboard_modifiers_; |
+ event.button.x = device->surface_position_.x(); |
+ event.button.y = device->surface_position_.y(); |
+ |
+ if (!window->delegate()) |
+ return; |
+ |
+ gfx::Point pt(event.button.x, event.button.y); |
+ int component = window->delegate()->GetNonClientComponent(pt); |
+ BoundsChangeType type = WaylandInputDevice::GetBoundsChangeForWindowComponent(component); |
+ |
+ if(WaylandDisplay::GetDisplay(device->display_)->shell() && |
+ button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) |
+ { |
+ switch(type) |
+ { |
+ case kBoundsChange_Repositions: |
+ if(!window->shell_surface()) |
+ break; |
+ |
+ WaylandDisplay::GetDisplay(device->display_)->SetPointerImage( |
+ device, time, CURSOR_DRAGGING); |
+ wl_shell_surface_move(window->shell_surface(), device->input_seat_, serial); |
+ break; |
+ case kBoundsChange_Resizes: |
+ if(!window->shell_surface()) |
+ break; |
+ |
+ wl_shell_surface_resize(window->shell_surface(), device->input_seat_, serial, |
+ WaylandInputDevice::GetLocationForWindowComponent(component)); |
+ break; |
+ default: |
+ break; |
+ } |
+ } |
+ |
+ if(type == kBoundsChange_None) |
+ window->delegate()->OnMouseEvent(&event); |
+} |
+ |
+void WaylandInputDevice::OnKeyNotify(void* data, |
+ wl_keyboard* input_keyboard, |
+ uint32_t serial, |
+ uint32_t time, |
+ uint32_t key, |
+ uint32_t state) |
+{ |
+ WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
+ WaylandWindow* window = device->keyboard_focus_; |
+ uint32_t code, num_syms; |
+ const xkb_keysym_t *syms; |
+ xkb_keysym_t sym; |
+ xkb_mod_mask_t mask; |
+ |
+ WaylandDisplay::GetDisplay(device->display_)->SetSerial(serial); |
+ |
+ WaylandEvent event; |
+ event.type = WAYLAND_KEY; |
+ event.key.time = time; |
+ event.key.key = key; |
+ event.key.state = state; |
+ |
+ code = key + 8; |
+ num_syms = xkb_key_get_syms(device->xkb_.state, code, &syms); |
+ |
+ mask = xkb_state_serialize_mods(device->xkb_.state, |
+ (xkb_state_component)(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED)); |
+ device->keyboard_modifiers_ = 0; |
+ if (mask & device->xkb_.control_mask) |
+ device->keyboard_modifiers_ |= MOD_CONTROL_MASK; |
+ if (mask & device->xkb_.alt_mask) |
+ device->keyboard_modifiers_ |= MOD_ALT_MASK; |
+ if (mask & device->xkb_.shift_mask) |
+ device->keyboard_modifiers_ |= MOD_SHIFT_MASK; |
+ |
+ if(num_syms == 1) |
+ event.key.sym = syms[0]; |
+ else |
+ event.key.sym = NoSymbol; |
+ event.key.modifiers = device->keyboard_modifiers_; |
+ |
+ if (!window->delegate()) |
+ return; |
+ |
+ // TODO: Add key processing |
+ // |
+ window->delegate()->OnKeyNotify(&event); |
+} |
+ |
+void WaylandInputDevice::OnKeyModifiers(void *data, wl_keyboard *keyboard, |
+ uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, |
+ uint32_t mods_locked, uint32_t group) |
+{ |
+ WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
+ |
+ xkb_state_update_mask(device->xkb_.state, mods_depressed, mods_latched, |
+ mods_locked, 0, 0, group); |
+} |
+ |
+void WaylandInputDevice::OnPointerEnter(void* data, |
+ wl_pointer* input_pointer, |
+ uint32_t serial, |
+ wl_surface* surface, |
+ wl_fixed_t sx_w, |
+ wl_fixed_t sy_w) |
+{ |
+ WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
+ WaylandWindow* window; |
+ |
+ GLfloat sx = wl_fixed_to_double(sx_w); |
+ GLfloat sy = wl_fixed_to_double(sy_w); |
+ |
+ WaylandDisplay::GetDisplay(device->display_)->SetSerial(serial); |
+ device->pointer_enter_serial_ = serial; |
+ |
+ WaylandEvent event; |
+ event.type = WAYLAND_POINTER_FOCUS; |
+ event.pointer_focus.serial = serial; |
+ event.pointer_focus.x = (int32_t)sx; |
+ event.pointer_focus.y = (int32_t)sy; |
+ |
+ // If we have a surface, then a new window is in focus |
+ event.pointer_focus.state = 1; |
+ window = static_cast<WaylandWindow*>(wl_surface_get_user_data(surface)); |
+ device->pointer_focus_ = window; |
+ |
+ if (!window->delegate()) |
+ return; |
+ |
+ window->delegate()->OnMouseEnter(&event); |
+} |
+ |
+void WaylandInputDevice::OnPointerLeave(void* data, |
+ wl_pointer* input_pointer, |
+ uint32_t serial, |
+ wl_surface* surface) |
+{ |
+ WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
+ WaylandWindow* window = device->pointer_focus_; |
+ |
+ WaylandDisplay::GetDisplay(device->display_)->SetSerial(serial); |
+ |
+ WaylandEvent event; |
+ event.type = WAYLAND_POINTER_FOCUS; |
+ event.pointer_focus.serial = serial; |
+ |
+ // If we have a window, then this means it loses focus |
+ if (window) { |
+ if(!WaylandDisplay::GetDisplay(device->display_)->IsWindow(window)) |
+ return; |
+ |
+ event.pointer_focus.state = 0; |
+ device->pointer_focus_ = NULL; |
+ device->current_pointer_image_ = POINTER_UNSET; |
+ |
+ if (!window->delegate()) |
+ return; |
+ |
+ window->delegate()->OnMouseLeave(&event); |
+ } |
+} |
+ |
+void WaylandInputDevice::OnKeyboardKeymap(void *data, |
+ struct wl_keyboard *keyboard, |
+ uint32_t format, int fd, uint32_t size) |
+{ |
+} |
+ |
+void WaylandInputDevice::OnKeyboardEnter(void* data, |
+ wl_keyboard* input_keyboard, |
+ uint32_t serial, |
+ wl_surface* surface, |
+ wl_array* keys) |
+{ |
+ WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
+ WaylandWindow* window; |
+ |
+ WaylandDisplay::GetDisplay(device->display_)->SetSerial(serial); |
+ window = device->keyboard_focus_ = |
+ static_cast<WaylandWindow*>(wl_surface_get_user_data(surface)); |
+ |
+ WaylandEvent event; |
+ event.type = WAYLAND_KEYBOARD_FOCUS; |
+ event.keyboard_focus.serial = serial; |
+ device->keyboard_modifiers_ = 0; |
+ event.keyboard_focus.modifiers = device->keyboard_modifiers_; |
+ event.keyboard_focus.state = 1; |
+ |
+ if (!window->delegate()) |
+ return; |
+ |
+ window->delegate()->OnKeyboardEnter(&event); |
+} |
+ |
+void WaylandInputDevice::OnKeyboardLeave(void* data, |
+ wl_keyboard* input_keyboard, |
+ uint32_t serial, |
+ wl_surface* surface) |
+{ |
+ WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
+ WaylandWindow* window = device->keyboard_focus_; |
+ |
+ WaylandDisplay::GetDisplay(device->display_)->SetSerial(serial); |
+ |
+ WaylandEvent event; |
+ event.type = WAYLAND_KEYBOARD_FOCUS; |
+ event.keyboard_focus.serial = serial; |
+ device->keyboard_modifiers_ = 0; |
+ |
+ // If there is a window, then it loses focus |
+ if (window) { |
+ if(!WaylandDisplay::GetDisplay(device->display_)->IsWindow(window)) |
+ return; |
+ |
+ event.keyboard_focus.state = 0; |
+ device->keyboard_focus_ = NULL; |
+ |
+ if (!window->delegate()) |
+ return; |
+ |
+ window->delegate()->OnKeyboardLeave(&event); |
+ } |
+} |
+ |
+} // namespace ui |