Skip to content

Commit

Permalink
Implement constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
serebit committed Oct 28, 2023
1 parent 569d020 commit a336c85
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 14 deletions.
7 changes: 5 additions & 2 deletions src/input/constraint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ static void constraint_destroy_notify(wl_listener* listener, void* data) {
(void) data;

auto& current_constraint = constraint.seat.current_constraint;
if (current_constraint.has_value() && current_constraint.value().wlr == constraint.wlr) {
if (current_constraint.has_value() && current_constraint.value().get().wlr == constraint.wlr) {
constraint.seat.cursor.warp_to_constraint(current_constraint.value());
constraint.deactivate();
current_constraint.reset();
}

delete &constraint;
}

PointerConstraint::PointerConstraint(Seat& seat, wlr_pointer_constraint_v1* constraint) noexcept
Expand All @@ -40,7 +44,6 @@ PointerConstraint::PointerConstraint(Seat& seat, wlr_pointer_constraint_v1* cons
}

PointerConstraint::~PointerConstraint() noexcept {
deactivate();
wl_list_remove(&listeners.set_region.link);
wl_list_remove(&listeners.surface_commit.link);
wl_list_remove(&listeners.destroy.link);
Expand Down
43 changes: 36 additions & 7 deletions src/input/cursor.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "cursor.hpp"

#include "input/constraint.hpp"
#include "seat.hpp"
#include "server.hpp"
#include "surface/surface.hpp"
Expand Down Expand Up @@ -120,7 +121,13 @@ static void cursor_motion_absolute_notify(wl_listener* listener, void* data) {
wlr_relative_pointer_manager_v1_send_relative_motion(
cursor.relative_pointer_mgr, cursor.seat.seat, (uint64_t) event->time_msec * 1000, dx, dy, dx, dy);

wlr_cursor_warp_absolute(cursor.cursor, &event->pointer->base, event->x, event->y);
if (cursor.seat.is_pointer_locked(event->pointer)) {
return;
}

cursor.seat.apply_constraint(event->pointer, &dx, &dy);

wlr_cursor_move(cursor.cursor, &event->pointer->base, dx, dy);
cursor.process_motion(event->time_msec);
}

Expand Down Expand Up @@ -158,12 +165,15 @@ static void cursor_motion_notify(wl_listener* listener, void* data) {
wlr_relative_pointer_manager_v1_send_relative_motion(cursor.relative_pointer_mgr, cursor.seat.seat,
(uint64_t) event->time_msec * 1000, event->delta_x, event->delta_y, event->unaccel_dx, event->unaccel_dy);

/* The cursor doesn't move unless we tell it to. The cursor automatically
* handles constraining the motion to the output layout, as well as any
* special configuration applied for the specific input device which
* generated the event. You can pass NULL for the device if you want to move
* the cursor around without any input. */
wlr_cursor_move(cursor.cursor, &event->pointer->base, event->delta_x, event->delta_y);
if (cursor.seat.is_pointer_locked(event->pointer)) {
return;
}

double dx = event->delta_x;
double dy = event->delta_y;
cursor.seat.apply_constraint(event->pointer, &dx, &dy);

wlr_cursor_move(cursor.cursor, &event->pointer->base, dx, dy);
cursor.process_motion(event->time_msec);
}

Expand Down Expand Up @@ -339,3 +349,22 @@ void Cursor::reset_mode() {
mode = MAGPIE_CURSOR_PASSTHROUGH;
seat.server.grabbed_view = NULL;
}

void Cursor::warp_to_constraint(PointerConstraint& constraint) {
if (seat.server.focused_view->surface != constraint.wlr->surface) {
return;
}

if (seat.server.focused_view == nullptr) {
// only warp to constraints tied to views...
return;
}

if (constraint.wlr->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
double x = constraint.wlr->current.cursor_hint.x;
double y = constraint.wlr->current.cursor_hint.y;

wlr_cursor_warp(cursor, nullptr, seat.server.focused_view->current.x + x, seat.server.focused_view->current.y + y);
wlr_seat_pointer_warp(seat.seat, x, y);
}
}
2 changes: 2 additions & 0 deletions src/input/cursor.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef MAGPIE_CURSOR_HPP
#define MAGPIE_CURSOR_HPP

#include "input/constraint.hpp"
#include "types.hpp"

#include <functional>
Expand Down Expand Up @@ -54,6 +55,7 @@ class Cursor {
void attach_input_device(wlr_input_device* device);
void process_motion(uint32_t time);
void reset_mode();
void warp_to_constraint(PointerConstraint& constraint);
};

#endif
42 changes: 39 additions & 3 deletions src/input/seat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "cursor.hpp"
#include "keyboard.hpp"
#include "server.hpp"
#include "surface/view.hpp"
#include "types.hpp"

#include <wayland-util.h>
Expand All @@ -13,6 +14,7 @@
#include <wlr/types/wlr_input_device.h>
#include <wlr/types/wlr_keyboard.h>
#include <wlr/types/wlr_pointer_constraints_v1.h>
#include <wlr/util/region.h>
#include "wlr-wrap-end.hpp"

static void new_input_notify(wl_listener* listener, void* data) {
Expand Down Expand Up @@ -124,17 +126,51 @@ void Seat::new_input_device(wlr_input_device* device) {
}

void Seat::set_constraint(wlr_pointer_constraint_v1* wlr_constraint) {
printf("Setting constraint %p\n", (void*) wlr_constraint);

if (current_constraint.has_value()) {
if (current_constraint.value().wlr == wlr_constraint) {
if (current_constraint.value().get().wlr == wlr_constraint) {
// we already have this constraint marked as the current constraint
return;
}

cursor.warp_to_constraint(current_constraint.value());
current_constraint.reset();
}

if (wlr_constraint != nullptr) {
current_constraint.emplace(PointerConstraint(*this, wlr_constraint));
current_constraint.value().activate();
current_constraint = *(new PointerConstraint(*this, wlr_constraint));
current_constraint.value().get().activate();
}
}

void Seat::apply_constraint(const wlr_pointer* pointer, double* dx, double* dy) const {
if (!current_constraint.has_value() || pointer->base.type != WLR_INPUT_DEVICE_POINTER) {
return;
}

if (server.focused_view == nullptr) {
return;
}

double x = cursor.cursor->x;
double y = cursor.cursor->y;

x -= server.focused_view->current.x;
y -= server.focused_view->current.y;

double confined_x = 0;
double confined_y = 0;
if (!wlr_region_confine(&current_constraint->get().wlr->region, x, y, x + *dx, y + *dy, &confined_x, &confined_y)) {
printf("Couldn't confine\n");
return;
}

*dx = confined_x - x;
*dy = confined_y - y;
}

bool Seat::is_pointer_locked(const wlr_pointer* pointer) const {
return current_constraint.has_value() && pointer->base.type == WLR_INPUT_DEVICE_POINTER &&
current_constraint->get().wlr->type == WLR_POINTER_CONSTRAINT_V1_LOCKED;
}
4 changes: 3 additions & 1 deletion src/input/seat.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ class Seat {
wlr_virtual_pointer_manager_v1* virtual_pointer_mgr;
wlr_virtual_keyboard_manager_v1* virtual_keyboard_mgr;
wlr_pointer_constraints_v1* pointer_constraints;
std::optional<PointerConstraint> current_constraint = {};
std::optional<std::reference_wrapper<PointerConstraint>> current_constraint = {};

Seat(Server& server) noexcept;
~Seat() noexcept;

void new_input_device(wlr_input_device* device);
void set_constraint(wlr_pointer_constraint_v1* wlr_constraint);
void apply_constraint(const wlr_pointer* pointer, double* dx, double* dy) const;
bool is_pointer_locked(const wlr_pointer* pointer) const;
};

#endif
1 change: 1 addition & 0 deletions src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ void Server::focus_view(View& view, wlr_surface* surface) {
/* Activate the new surface */
server.views.insert(server.views.begin(), &view);
view.set_activated(true);
focused_view = &view;

/*
* Tell the seat to have the keyboard enter this surface. wlroots will keep
Expand Down
3 changes: 2 additions & 1 deletion src/server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ class Server {
Seat* seat;

std::list<View*> views;
View* grabbed_view;
View* focused_view = nullptr;
View* grabbed_view = nullptr;
double grab_x, grab_y;
wlr_box grab_geobox;
uint32_t resize_edges;
Expand Down
4 changes: 4 additions & 0 deletions src/surface/xdg_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,10 @@ void XdgView::unmap() {
if (this == server.grabbed_view) {
server.seat->cursor.reset_mode();
}

if (this == server.focused_view) {
server.focused_view = nullptr;
}
}

void XdgView::impl_set_position(const int new_x, const int new_y) {
Expand Down
4 changes: 4 additions & 0 deletions src/surface/xwayland_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ void XWaylandView::unmap() {
cursor.reset_mode();
}

if (this == server.focused_view) {
server.focused_view = nullptr;
}

if (server.seat->seat->keyboard_state.focused_surface == surface) {
server.seat->seat->keyboard_state.focused_surface = NULL;
}
Expand Down

0 comments on commit a336c85

Please sign in to comment.