OLD | NEW |
(Empty) | |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "ui/wayland/wayland_input_device.h" |
| 6 |
| 7 #include <X11/X.h> |
| 8 #include <linux/input.h> |
| 9 #include <wayland-client.h> |
| 10 |
| 11 #include <wayland-egl.h> |
| 12 #include <GLES2/gl2.h> |
| 13 #include <GLES2/gl2ext.h> |
| 14 #include <EGL/egl.h> |
| 15 #include <EGL/eglext.h> |
| 16 |
| 17 #include "base/wayland/wayland_event.h" |
| 18 #include "ui/wayland/wayland_delegate.h" |
| 19 #include "ui/wayland/wayland_window.h" |
| 20 #include "ui/base/events/event.h" |
| 21 #include "ui/base/events/event_constants.h" |
| 22 #include "ui/base/hit_test.h" |
| 23 #include "ui/base/ui_base_types.h" |
| 24 |
| 25 using namespace base::wayland; |
| 26 |
| 27 namespace ui { |
| 28 |
| 29 // static |
| 30 BoundsChangeType WaylandInputDevice::GetBoundsChangeForWindowComponent(int compo
nent) |
| 31 { |
| 32 BoundsChangeType bounds_change = kBoundsChange_None; |
| 33 switch (component) { |
| 34 case HTCAPTION: |
| 35 bounds_change = kBoundsChange_Repositions; |
| 36 break; |
| 37 case HTTOPLEFT: |
| 38 case HTTOP: |
| 39 case HTTOPRIGHT: |
| 40 case HTLEFT: |
| 41 case HTBOTTOMLEFT: |
| 42 case HTRIGHT: |
| 43 case HTBOTTOMRIGHT: |
| 44 case HTBOTTOM: |
| 45 //case HTGROWBOX: |
| 46 bounds_change = kBoundsChange_Resizes; |
| 47 break; |
| 48 default: |
| 49 break; |
| 50 } |
| 51 return bounds_change; |
| 52 } |
| 53 |
| 54 // static |
| 55 int WaylandInputDevice::GetPointerImageForWindowComponent(int component) |
| 56 { |
| 57 WindowLocation location = WaylandInputDevice::GetLocationForWindowComponent(co
mponent); |
| 58 |
| 59 switch (location) { |
| 60 case WINDOW_RESIZING_TOP: |
| 61 return CURSOR_TOP; |
| 62 case WINDOW_RESIZING_BOTTOM: |
| 63 return CURSOR_BOTTOM; |
| 64 case WINDOW_RESIZING_LEFT: |
| 65 return CURSOR_LEFT; |
| 66 case WINDOW_RESIZING_RIGHT: |
| 67 return CURSOR_RIGHT; |
| 68 case WINDOW_RESIZING_TOP_LEFT: |
| 69 return CURSOR_TOP_LEFT; |
| 70 case WINDOW_RESIZING_TOP_RIGHT: |
| 71 return CURSOR_TOP_RIGHT; |
| 72 case WINDOW_RESIZING_BOTTOM_LEFT: |
| 73 return CURSOR_BOTTOM_LEFT; |
| 74 case WINDOW_RESIZING_BOTTOM_RIGHT: |
| 75 return CURSOR_BOTTOM_RIGHT; |
| 76 case WINDOW_EXTERIOR: |
| 77 case WINDOW_TITLEBAR: |
| 78 default: |
| 79 return CURSOR_LEFT_PTR; |
| 80 } |
| 81 } |
| 82 |
| 83 // static |
| 84 WindowLocation WaylandInputDevice::GetLocationForWindowComponent(int component) |
| 85 { |
| 86 WindowLocation location = WINDOW_INTERIOR; |
| 87 switch (component) { |
| 88 case HTCAPTION: |
| 89 location = WINDOW_TITLEBAR; |
| 90 break; |
| 91 case HTTOPLEFT: |
| 92 location = WINDOW_RESIZING_TOP_LEFT; |
| 93 break; |
| 94 case HTTOP: |
| 95 location = WINDOW_RESIZING_TOP; |
| 96 break; |
| 97 case HTTOPRIGHT: |
| 98 location = WINDOW_RESIZING_TOP_RIGHT; |
| 99 break; |
| 100 case HTLEFT: |
| 101 location = WINDOW_RESIZING_LEFT; |
| 102 break; |
| 103 case HTBOTTOMLEFT: |
| 104 location = WINDOW_RESIZING_BOTTOM_LEFT; |
| 105 break; |
| 106 case HTRIGHT: |
| 107 location = WINDOW_RESIZING_RIGHT; |
| 108 break; |
| 109 case HTBOTTOMRIGHT: |
| 110 location = WINDOW_RESIZING_BOTTOM_RIGHT; |
| 111 break; |
| 112 case HTBOTTOM: |
| 113 location = WINDOW_RESIZING_BOTTOM; |
| 114 break; |
| 115 default: |
| 116 break; |
| 117 } |
| 118 return location; |
| 119 } |
| 120 |
| 121 WaylandInputDevice::WaylandInputDevice(WaylandDisplay* disp, uint32_t id) |
| 122 : input_seat_(NULL), |
| 123 display_(disp->display()), |
| 124 current_pointer_image_(CURSOR_LEFT_PTR), |
| 125 input_pointer_(NULL), |
| 126 input_keyboard_(NULL), |
| 127 pointer_focus_(NULL), |
| 128 keyboard_focus_(NULL), |
| 129 keyboard_modifiers_(0) |
| 130 { |
| 131 static const struct wl_seat_listener kInputSeatListener = { |
| 132 WaylandInputDevice::OnSeatCapabilities, |
| 133 }; |
| 134 |
| 135 input_seat_ = static_cast<wl_seat*>( |
| 136 wl_registry_bind(disp->registry(), id, &wl_seat_interface, 1)); |
| 137 wl_seat_add_listener(input_seat_, &kInputSeatListener, this); |
| 138 wl_seat_set_user_data(input_seat_, this); |
| 139 |
| 140 InitXKB(); |
| 141 } |
| 142 |
| 143 WaylandInputDevice::~WaylandInputDevice() |
| 144 { |
| 145 if (input_seat_) |
| 146 wl_seat_destroy(input_seat_); |
| 147 |
| 148 FiniXKB(); |
| 149 } |
| 150 |
| 151 void WaylandInputDevice::InitXKB() |
| 152 { |
| 153 // Initialize XKB |
| 154 xkb_.names.rules = "evdev"; |
| 155 xkb_.names.model = "pc105"; |
| 156 xkb_.names.layout = "us"; |
| 157 xkb_.names.variant = ""; |
| 158 xkb_.names.options = ""; |
| 159 |
| 160 xkb_.context = xkb_context_new((xkb_context_flags)0); |
| 161 if (!xkb_.context) { |
| 162 return; |
| 163 } |
| 164 |
| 165 xkb_.keymap = |
| 166 xkb_map_new_from_names(xkb_.context, &xkb_.names, (xkb_map_compile_flags)0); |
| 167 if (!xkb_.keymap) { |
| 168 return; |
| 169 } |
| 170 |
| 171 xkb_.state = xkb_state_new(xkb_.keymap); |
| 172 if (!xkb_.state) { |
| 173 return; |
| 174 } |
| 175 |
| 176 xkb_.control_mask = |
| 177 1 << xkb_map_mod_get_index(xkb_.keymap, "Control"); |
| 178 xkb_.alt_mask = |
| 179 1 << xkb_map_mod_get_index(xkb_.keymap, "Mod1"); |
| 180 xkb_.shift_mask = |
| 181 1 << xkb_map_mod_get_index(xkb_.keymap, "Shift"); |
| 182 } |
| 183 |
| 184 void WaylandInputDevice::FiniXKB() |
| 185 { |
| 186 xkb_state_unref(xkb_.state); |
| 187 xkb_map_unref(xkb_.keymap); |
| 188 xkb_context_unref(xkb_.context); |
| 189 } |
| 190 |
| 191 void WaylandInputDevice::OnSeatCapabilities(void *data, wl_seat *seat, uint32_t
caps) |
| 192 { |
| 193 WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
| 194 |
| 195 static const struct wl_pointer_listener kInputPointerListener = { |
| 196 WaylandInputDevice::OnPointerEnter, |
| 197 WaylandInputDevice::OnPointerLeave, |
| 198 WaylandInputDevice::OnMotionNotify, |
| 199 WaylandInputDevice::OnButtonNotify, |
| 200 WaylandInputDevice::OnAxisNotify, |
| 201 }; |
| 202 |
| 203 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !device->input_pointer_) { |
| 204 device->input_pointer_ = wl_seat_get_pointer(seat); |
| 205 wl_pointer_set_user_data(device->input_pointer_, device); |
| 206 wl_pointer_add_listener(device->input_pointer_, &kInputPointerListener, |
| 207 device); |
| 208 } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && device->input_pointer_) { |
| 209 wl_pointer_destroy(device->input_pointer_); |
| 210 device->input_pointer_ = NULL; |
| 211 } |
| 212 |
| 213 static const struct wl_keyboard_listener kInputKeyboardListener = { |
| 214 WaylandInputDevice::OnKeyboardKeymap, |
| 215 WaylandInputDevice::OnKeyboardEnter, |
| 216 WaylandInputDevice::OnKeyboardLeave, |
| 217 WaylandInputDevice::OnKeyNotify, |
| 218 WaylandInputDevice::OnKeyModifiers, |
| 219 }; |
| 220 |
| 221 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !device->input_keyboard_) { |
| 222 device->input_keyboard_ = wl_seat_get_keyboard(seat); |
| 223 wl_keyboard_set_user_data(device->input_keyboard_, device); |
| 224 wl_keyboard_add_listener(device->input_keyboard_, &kInputKeyboardListener, |
| 225 device); |
| 226 } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && device->input_keyboard_) { |
| 227 wl_keyboard_destroy(device->input_keyboard_); |
| 228 device->input_keyboard_ = NULL; |
| 229 } |
| 230 } |
| 231 |
| 232 void WaylandInputDevice::OnMotionNotify(void* data, |
| 233 wl_pointer* input_pointer, |
| 234 uint32_t time, |
| 235 wl_fixed_t sx_w, |
| 236 wl_fixed_t sy_w) |
| 237 { |
| 238 WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
| 239 WaylandWindow* window = device->pointer_focus_; |
| 240 GLfloat sx = wl_fixed_to_double(sx_w); |
| 241 GLfloat sy = wl_fixed_to_double(sy_w); |
| 242 |
| 243 device->surface_position_.SetPoint(sx, sy); |
| 244 |
| 245 WaylandEvent event; |
| 246 event.type = WAYLAND_MOTION; |
| 247 event.motion.time = time; |
| 248 event.motion.modifiers = device->keyboard_modifiers_; |
| 249 event.motion.x = sx; |
| 250 event.motion.y = sy; |
| 251 |
| 252 if (!window->delegate()) |
| 253 return; |
| 254 |
| 255 gfx::Point pt(event.motion.x, event.motion.y); |
| 256 int component = window->delegate()->GetNonClientComponent(pt); |
| 257 BoundsChangeType type = WaylandInputDevice::GetBoundsChangeForWindowComponent(
component); |
| 258 |
| 259 switch(type) |
| 260 { |
| 261 case kBoundsChange_Resizes: |
| 262 WaylandDisplay::GetDisplay(device->display_)->SetPointerImage( |
| 263 device, time, WaylandInputDevice::GetPointerImageForWindowComponent(co
mponent)); |
| 264 break; |
| 265 case kBoundsChange_Repositions: |
| 266 default: |
| 267 WaylandDisplay::GetDisplay(device->display_)->SetPointerImage( |
| 268 device, time, CURSOR_LEFT_PTR); |
| 269 break; |
| 270 } |
| 271 |
| 272 if(type == kBoundsChange_None) |
| 273 window->delegate()->OnMouseEvent(&event); |
| 274 } |
| 275 |
| 276 void WaylandInputDevice::OnAxisNotify(void* data, |
| 277 wl_pointer* input_pointer, |
| 278 uint32_t time, |
| 279 uint32_t axis, |
| 280 int32_t value) |
| 281 { |
| 282 WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
| 283 WaylandWindow* window = device->pointer_focus_; |
| 284 |
| 285 WaylandEvent event; |
| 286 event.type = WAYLAND_BUTTON; |
| 287 event.button.time = time; |
| 288 event.button.button = value > 0 ? BTN_SIDE : BTN_EXTRA; |
| 289 event.button.state = 1; |
| 290 event.button.modifiers = device->keyboard_modifiers_; |
| 291 event.button.x = device->surface_position_.x(); |
| 292 event.button.y = device->surface_position_.y(); |
| 293 |
| 294 if (!window->delegate()) |
| 295 return; |
| 296 |
| 297 window->delegate()->OnMouseEvent(&event); |
| 298 } |
| 299 |
| 300 void WaylandInputDevice::OnButtonNotify(void* data, |
| 301 wl_pointer* input_pointer, |
| 302 uint32_t serial, |
| 303 uint32_t time, |
| 304 uint32_t button, |
| 305 uint32_t state) |
| 306 { |
| 307 WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
| 308 WaylandWindow* window = device->pointer_focus_; |
| 309 |
| 310 WaylandDisplay::GetDisplay(device->display_)->SetSerial(serial); |
| 311 |
| 312 WaylandEvent event; |
| 313 event.type = WAYLAND_BUTTON; |
| 314 event.button.time = time; |
| 315 event.button.button = button; |
| 316 event.button.state = state; |
| 317 event.button.modifiers = device->keyboard_modifiers_; |
| 318 event.button.x = device->surface_position_.x(); |
| 319 event.button.y = device->surface_position_.y(); |
| 320 |
| 321 if (!window->delegate()) |
| 322 return; |
| 323 |
| 324 gfx::Point pt(event.button.x, event.button.y); |
| 325 int component = window->delegate()->GetNonClientComponent(pt); |
| 326 BoundsChangeType type = WaylandInputDevice::GetBoundsChangeForWindowComponent(
component); |
| 327 |
| 328 if(WaylandDisplay::GetDisplay(device->display_)->shell() && |
| 329 button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) |
| 330 { |
| 331 switch(type) |
| 332 { |
| 333 case kBoundsChange_Repositions: |
| 334 if(!window->shell_surface()) |
| 335 break; |
| 336 |
| 337 WaylandDisplay::GetDisplay(device->display_)->SetPointerImage( |
| 338 device, time, CURSOR_DRAGGING); |
| 339 wl_shell_surface_move(window->shell_surface(), device->input_seat_, seri
al); |
| 340 break; |
| 341 case kBoundsChange_Resizes: |
| 342 if(!window->shell_surface()) |
| 343 break; |
| 344 |
| 345 wl_shell_surface_resize(window->shell_surface(), device->input_seat_, se
rial, |
| 346 WaylandInputDevice::GetLocationForWindowComponent(component)); |
| 347 break; |
| 348 default: |
| 349 break; |
| 350 } |
| 351 } |
| 352 |
| 353 if(type == kBoundsChange_None) |
| 354 window->delegate()->OnMouseEvent(&event); |
| 355 } |
| 356 |
| 357 void WaylandInputDevice::OnKeyNotify(void* data, |
| 358 wl_keyboard* input_keyboard, |
| 359 uint32_t serial, |
| 360 uint32_t time, |
| 361 uint32_t key, |
| 362 uint32_t state) |
| 363 { |
| 364 WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
| 365 WaylandWindow* window = device->keyboard_focus_; |
| 366 uint32_t code, num_syms; |
| 367 const xkb_keysym_t *syms; |
| 368 xkb_keysym_t sym; |
| 369 xkb_mod_mask_t mask; |
| 370 |
| 371 WaylandDisplay::GetDisplay(device->display_)->SetSerial(serial); |
| 372 |
| 373 WaylandEvent event; |
| 374 event.type = WAYLAND_KEY; |
| 375 event.key.time = time; |
| 376 event.key.key = key; |
| 377 event.key.state = state; |
| 378 |
| 379 code = key + 8; |
| 380 num_syms = xkb_key_get_syms(device->xkb_.state, code, &syms); |
| 381 |
| 382 mask = xkb_state_serialize_mods(device->xkb_.state, |
| 383 (xkb_state_component)(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED)); |
| 384 device->keyboard_modifiers_ = 0; |
| 385 if (mask & device->xkb_.control_mask) |
| 386 device->keyboard_modifiers_ |= MOD_CONTROL_MASK; |
| 387 if (mask & device->xkb_.alt_mask) |
| 388 device->keyboard_modifiers_ |= MOD_ALT_MASK; |
| 389 if (mask & device->xkb_.shift_mask) |
| 390 device->keyboard_modifiers_ |= MOD_SHIFT_MASK; |
| 391 |
| 392 if(num_syms == 1) |
| 393 event.key.sym = syms[0]; |
| 394 else |
| 395 event.key.sym = NoSymbol; |
| 396 event.key.modifiers = device->keyboard_modifiers_; |
| 397 |
| 398 if (!window->delegate()) |
| 399 return; |
| 400 |
| 401 // TODO: Add key processing |
| 402 // |
| 403 window->delegate()->OnKeyNotify(&event); |
| 404 } |
| 405 |
| 406 void WaylandInputDevice::OnKeyModifiers(void *data, wl_keyboard *keyboard, |
| 407 uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, |
| 408 uint32_t mods_locked, uint32_t group) |
| 409 { |
| 410 WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
| 411 |
| 412 xkb_state_update_mask(device->xkb_.state, mods_depressed, mods_latched, |
| 413 mods_locked, 0, 0, group); |
| 414 } |
| 415 |
| 416 void WaylandInputDevice::OnPointerEnter(void* data, |
| 417 wl_pointer* input_pointer, |
| 418 uint32_t serial, |
| 419 wl_surface* surface, |
| 420 wl_fixed_t sx_w, |
| 421 wl_fixed_t sy_w) |
| 422 { |
| 423 WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
| 424 WaylandWindow* window; |
| 425 |
| 426 GLfloat sx = wl_fixed_to_double(sx_w); |
| 427 GLfloat sy = wl_fixed_to_double(sy_w); |
| 428 |
| 429 WaylandDisplay::GetDisplay(device->display_)->SetSerial(serial); |
| 430 device->pointer_enter_serial_ = serial; |
| 431 |
| 432 WaylandEvent event; |
| 433 event.type = WAYLAND_POINTER_FOCUS; |
| 434 event.pointer_focus.serial = serial; |
| 435 event.pointer_focus.x = (int32_t)sx; |
| 436 event.pointer_focus.y = (int32_t)sy; |
| 437 |
| 438 // If we have a surface, then a new window is in focus |
| 439 event.pointer_focus.state = 1; |
| 440 window = static_cast<WaylandWindow*>(wl_surface_get_user_data(surface)); |
| 441 device->pointer_focus_ = window; |
| 442 |
| 443 if (!window->delegate()) |
| 444 return; |
| 445 |
| 446 window->delegate()->OnMouseEnter(&event); |
| 447 } |
| 448 |
| 449 void WaylandInputDevice::OnPointerLeave(void* data, |
| 450 wl_pointer* input_pointer, |
| 451 uint32_t serial, |
| 452 wl_surface* surface) |
| 453 { |
| 454 WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
| 455 WaylandWindow* window = device->pointer_focus_; |
| 456 |
| 457 WaylandDisplay::GetDisplay(device->display_)->SetSerial(serial); |
| 458 |
| 459 WaylandEvent event; |
| 460 event.type = WAYLAND_POINTER_FOCUS; |
| 461 event.pointer_focus.serial = serial; |
| 462 |
| 463 // If we have a window, then this means it loses focus |
| 464 if (window) { |
| 465 if(!WaylandDisplay::GetDisplay(device->display_)->IsWindow(window)) |
| 466 return; |
| 467 |
| 468 event.pointer_focus.state = 0; |
| 469 device->pointer_focus_ = NULL; |
| 470 device->current_pointer_image_ = POINTER_UNSET; |
| 471 |
| 472 if (!window->delegate()) |
| 473 return; |
| 474 |
| 475 window->delegate()->OnMouseLeave(&event); |
| 476 } |
| 477 } |
| 478 |
| 479 void WaylandInputDevice::OnKeyboardKeymap(void *data, |
| 480 struct wl_keyboard *keyboard, |
| 481 uint32_t format, int fd, uint32_t size) |
| 482 { |
| 483 } |
| 484 |
| 485 void WaylandInputDevice::OnKeyboardEnter(void* data, |
| 486 wl_keyboard* input_keyboard, |
| 487 uint32_t serial, |
| 488 wl_surface* surface, |
| 489 wl_array* keys) |
| 490 { |
| 491 WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
| 492 WaylandWindow* window; |
| 493 |
| 494 WaylandDisplay::GetDisplay(device->display_)->SetSerial(serial); |
| 495 window = device->keyboard_focus_ = |
| 496 static_cast<WaylandWindow*>(wl_surface_get_user_data(surface)); |
| 497 |
| 498 WaylandEvent event; |
| 499 event.type = WAYLAND_KEYBOARD_FOCUS; |
| 500 event.keyboard_focus.serial = serial; |
| 501 device->keyboard_modifiers_ = 0; |
| 502 event.keyboard_focus.modifiers = device->keyboard_modifiers_; |
| 503 event.keyboard_focus.state = 1; |
| 504 |
| 505 if (!window->delegate()) |
| 506 return; |
| 507 |
| 508 window->delegate()->OnKeyboardEnter(&event); |
| 509 } |
| 510 |
| 511 void WaylandInputDevice::OnKeyboardLeave(void* data, |
| 512 wl_keyboard* input_keyboard, |
| 513 uint32_t serial, |
| 514 wl_surface* surface) |
| 515 { |
| 516 WaylandInputDevice* device = static_cast<WaylandInputDevice*>(data); |
| 517 WaylandWindow* window = device->keyboard_focus_; |
| 518 |
| 519 WaylandDisplay::GetDisplay(device->display_)->SetSerial(serial); |
| 520 |
| 521 WaylandEvent event; |
| 522 event.type = WAYLAND_KEYBOARD_FOCUS; |
| 523 event.keyboard_focus.serial = serial; |
| 524 device->keyboard_modifiers_ = 0; |
| 525 |
| 526 // If there is a window, then it loses focus |
| 527 if (window) { |
| 528 if(!WaylandDisplay::GetDisplay(device->display_)->IsWindow(window)) |
| 529 return; |
| 530 |
| 531 event.keyboard_focus.state = 0; |
| 532 device->keyboard_focus_ = NULL; |
| 533 |
| 534 if (!window->delegate()) |
| 535 return; |
| 536 |
| 537 window->delegate()->OnKeyboardLeave(&event); |
| 538 } |
| 539 } |
| 540 |
| 541 } // namespace ui |
OLD | NEW |