blob: 41edb3e332ca10a715a0f8da2feff7ca38607ee7 [file] [log] [blame]
// Copyright 2016 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/ozone/platform/wayland/wayland_pointer.h"
#include <linux/input.h>
#include <wayland-client.h>
#include "ui/events/event.h"
#include "ui/ozone/platform/wayland/wayland_window.h"
// TODO(forney): Handle version 5 of wl_pointer.
namespace ui {
WaylandPointer::WaylandPointer(wl_pointer* pointer,
const EventDispatchCallback& callback)
: obj_(pointer), callback_(callback) {
static const wl_pointer_listener listener = {
&WaylandPointer::Enter, &WaylandPointer::Leave, &WaylandPointer::Motion,
&WaylandPointer::Button, &WaylandPointer::Axis,
};
wl_pointer_add_listener(obj_.get(), &listener, this);
}
WaylandPointer::~WaylandPointer() {}
// static
void WaylandPointer::Enter(void* data,
wl_pointer* obj,
uint32_t serial,
wl_surface* surface,
wl_fixed_t surface_x,
wl_fixed_t surface_y) {
WaylandPointer* pointer = static_cast<WaylandPointer*>(data);
pointer->location_.SetPoint(wl_fixed_to_double(surface_x),
wl_fixed_to_double(surface_y));
if (surface)
WaylandWindow::FromSurface(surface)->set_pointer_focus(true);
}
// static
void WaylandPointer::Leave(void* data,
wl_pointer* obj,
uint32_t serial,
wl_surface* surface) {
if (surface)
WaylandWindow::FromSurface(surface)->set_pointer_focus(false);
}
// static
void WaylandPointer::Motion(void* data,
wl_pointer* obj,
uint32_t time,
wl_fixed_t surface_x,
wl_fixed_t surface_y) {
WaylandPointer* pointer = static_cast<WaylandPointer*>(data);
pointer->location_.SetPoint(wl_fixed_to_double(surface_x),
wl_fixed_to_double(surface_y));
MouseEvent event(ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
base::TimeTicks() + base::TimeDelta::FromMilliseconds(time),
pointer->flags_, 0);
event.set_location_f(pointer->location_);
event.set_root_location_f(pointer->location_);
pointer->callback_.Run(&event);
}
// static
void WaylandPointer::Button(void* data,
wl_pointer* obj,
uint32_t serial,
uint32_t time,
uint32_t button,
uint32_t state) {
WaylandPointer* pointer = static_cast<WaylandPointer*>(data);
int flag;
switch (button) {
case BTN_LEFT:
flag = EF_LEFT_MOUSE_BUTTON;
break;
case BTN_MIDDLE:
flag = EF_MIDDLE_MOUSE_BUTTON;
break;
case BTN_RIGHT:
flag = EF_RIGHT_MOUSE_BUTTON;
break;
case BTN_BACK:
flag = EF_BACK_MOUSE_BUTTON;
break;
case BTN_FORWARD:
flag = EF_FORWARD_MOUSE_BUTTON;
break;
default:
return;
}
int flags = pointer->flags_ | flag;
EventType type;
if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
type = ET_MOUSE_PRESSED;
pointer->flags_ |= flag;
} else {
type = ET_MOUSE_RELEASED;
pointer->flags_ &= ~flag;
}
MouseEvent event(type, gfx::Point(), gfx::Point(),
base::TimeTicks() + base::TimeDelta::FromMilliseconds(time),
flags, flag);
event.set_location_f(pointer->location_);
event.set_root_location_f(pointer->location_);
pointer->callback_.Run(&event);
}
// static
void WaylandPointer::Axis(void* data,
wl_pointer* obj,
uint32_t time,
uint32_t axis,
wl_fixed_t value) {
static const double kAxisValueScale = 10.0;
WaylandPointer* pointer = static_cast<WaylandPointer*>(data);
gfx::Vector2d offset;
// Wayland compositors send axis events with values in the surface coordinate
// space. They send a value of 10 per mouse wheel click by convention, so
// clients (e.g. GTK+) typically scale down by this amount to convert to
// discrete step coordinates. wl_pointer version 5 improves the situation by
// adding axis sources and discrete axis events.
if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
offset.set_y(-wl_fixed_to_double(value) / kAxisValueScale *
MouseWheelEvent::kWheelDelta);
else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
offset.set_x(wl_fixed_to_double(value) / kAxisValueScale *
MouseWheelEvent::kWheelDelta);
else
return;
MouseWheelEvent event(
offset, gfx::Point(), gfx::Point(),
base::TimeTicks() + base::TimeDelta::FromMilliseconds(time),
pointer->flags_, 0);
event.set_location_f(pointer->location_);
event.set_root_location_f(pointer->location_);
pointer->callback_.Run(&event);
}
} // namespace ui