Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass pointer events to surface layers #1674

Merged
merged 1 commit into from
Mar 31, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 66 additions & 12 deletions sway/input/cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
#include "list.h"
#include "log.h"
#include "sway/input/cursor.h"
#include "sway/layers.h"
#include "sway/output.h"
#include "sway/tree/view.h"
#include "wlr-layer-shell-unstable-v1-protocol.h"

static void cursor_update_position(struct sway_cursor *cursor) {
double x = cursor->cursor->x;
Expand All @@ -20,9 +22,35 @@ static void cursor_update_position(struct sway_cursor *cursor) {
cursor->y = y;
}

static struct wlr_surface *layer_surface_at(struct sway_output *output,
struct wl_list *layer, double ox, double oy, double *sx, double *sy) {
struct sway_layer_surface *sway_layer;
wl_list_for_each_reverse(sway_layer, layer, link) {
struct wlr_surface *wlr_surface =
sway_layer->layer_surface->surface;
double _sx = ox - sway_layer->geo.x;
double _sy = oy - sway_layer->geo.y;
struct wlr_box box = {
.x = sway_layer->geo.x,
.y = sway_layer->geo.y,
.width = wlr_surface->current->width,
.height = wlr_surface->current->height,
};
// TODO: Test popups/subsurfaces
if (wlr_box_contains_point(&box, ox, oy) &&
pixman_region32_contains_point(
&wlr_surface->current->input, _sx, _sy, NULL)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll probably want to wrap this into a wlr function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

meh

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alright you convinced me

*sx = _sx;
*sy = _sy;
return wlr_surface;
}
}
return NULL;
}

/**
* Returns the container at the cursor's position. If the container is a view,
* stores the surface at the cursor's position in `*surface`.
* Returns the container at the cursor's position. If there is a surface at that
* location, it is stored in **surface (it may not be a view).
*/
static struct sway_container *container_at_cursor(struct sway_cursor *cursor,
struct wlr_surface **surface, double *sx, double *sy) {
Expand Down Expand Up @@ -57,29 +85,55 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor,
return NULL;
}
struct sway_output *output = wlr_output->data;
double ox = cursor->x, oy = cursor->y;
wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy);

// find the focused workspace on the output for this seat
struct sway_container *workspace_cont =
struct sway_container *ws =
sway_seat_get_focus_inactive(cursor->seat, output->swayc);
if (workspace_cont != NULL && workspace_cont->type != C_WORKSPACE) {
workspace_cont = container_parent(workspace_cont, C_WORKSPACE);
if (ws && ws->type != C_WORKSPACE) {
ws = container_parent(ws, C_WORKSPACE);
}
if (workspace_cont == NULL) {
if (!ws) {
return output->swayc;
}

struct sway_container *view_cont = container_at(workspace_cont,
cursor->x, cursor->y, surface, sx, sy);
return view_cont != NULL ? view_cont : workspace_cont;
if ((*surface = layer_surface_at(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
ox, oy, sx, sy))) {
return ws;
}
if ((*surface = layer_surface_at(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
ox, oy, sx, sy))) {
return ws;
}

struct sway_container *c;
if ((c = container_at(ws, cursor->x, cursor->y, surface, sx, sy))) {
return c;
}

if ((*surface = layer_surface_at(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
ox, oy, sx, sy))) {
return ws;
}
if ((*surface = layer_surface_at(output,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
ox, oy, sx, sy))) {
return ws;
}

return NULL;
}

static void cursor_send_pointer_motion(struct sway_cursor *cursor,
uint32_t time) {
struct wlr_seat *seat = cursor->seat->wlr_seat;
struct wlr_surface *surface = NULL;
double sx, sy;
struct sway_container *cont =
container_at_cursor(cursor, &surface, &sx, &sy);
container_at_cursor(cursor, &surface, &sx, &sy);

// reset cursor if switching between clients
struct wl_client *client = NULL;
Expand All @@ -93,7 +147,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor,
}

// send pointer enter/leave
if (cont != NULL && surface != NULL) {
if (surface != NULL) {
wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
wlr_seat_pointer_notify_motion(seat, time, sx, sy);
} else {
Expand Down