189 lines
5.1 KiB
C
189 lines
5.1 KiB
C
|
/* Copyright (c), Niclas Meyer <niclas@countingsort.com>
|
||
|
*
|
||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||
|
* You can obtain one at https://mozilla.org/MPL/2.0/.
|
||
|
*/
|
||
|
|
||
|
#include "input/seat.h"
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include <wlr/types/wlr_cursor.h>
|
||
|
#include <wlr/types/wlr_data_device.h>
|
||
|
#include <wlr/types/wlr_layer_shell_v1.h>
|
||
|
#include <wlr/types/wlr_primary_selection.h>
|
||
|
#include <wlr/types/wlr_seat.h>
|
||
|
#include <wlr/util/log.h>
|
||
|
|
||
|
#include "desktop/layer_shell.h"
|
||
|
#include "desktop/view.h"
|
||
|
#include "input/cursor.h"
|
||
|
#include "server.h"
|
||
|
|
||
|
void
|
||
|
seat_focus_surface(struct kiwmi_seat *seat, struct wlr_surface *wlr_surface)
|
||
|
{
|
||
|
if (seat->focused_layer) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->seat);
|
||
|
if (!keyboard) {
|
||
|
wlr_seat_keyboard_enter(seat->seat, wlr_surface, NULL, 0, NULL);
|
||
|
}
|
||
|
|
||
|
wlr_seat_keyboard_enter(
|
||
|
seat->seat,
|
||
|
wlr_surface,
|
||
|
keyboard->keycodes,
|
||
|
keyboard->num_keycodes,
|
||
|
&keyboard->modifiers);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
seat_focus_layer(struct kiwmi_seat *seat, struct kiwmi_layer *layer)
|
||
|
{
|
||
|
if (!layer) {
|
||
|
seat->focused_layer = NULL;
|
||
|
|
||
|
if (seat->focused_view) {
|
||
|
seat_focus_surface(seat, seat->focused_view->wlr_surface);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (seat->focused_layer == layer) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
seat->focused_layer = NULL;
|
||
|
|
||
|
seat_focus_surface(seat, layer->layer_surface->surface);
|
||
|
|
||
|
seat->focused_layer = layer;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
seat_focus_view(struct kiwmi_seat *seat, struct kiwmi_view *view)
|
||
|
{
|
||
|
if (!view) {
|
||
|
seat_focus_surface(seat, NULL);
|
||
|
seat->focused_view = NULL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
struct kiwmi_desktop *desktop = view->desktop;
|
||
|
|
||
|
if (seat->focused_view) {
|
||
|
view_set_activated(seat->focused_view, false);
|
||
|
}
|
||
|
|
||
|
// move view to front
|
||
|
wl_list_remove(&view->link);
|
||
|
wl_list_insert(&desktop->views, &view->link);
|
||
|
cursor_refresh_focus(seat->input->cursor, NULL, NULL, NULL);
|
||
|
|
||
|
seat->focused_view = view;
|
||
|
view_set_activated(view, true);
|
||
|
seat_focus_surface(seat, view->wlr_surface);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
request_set_cursor_notify(struct wl_listener *listener, void *data)
|
||
|
{
|
||
|
struct kiwmi_seat *seat =
|
||
|
wl_container_of(listener, seat, request_set_cursor);
|
||
|
struct kiwmi_cursor *cursor = seat->input->cursor;
|
||
|
struct wlr_seat_pointer_request_set_cursor_event *event = data;
|
||
|
|
||
|
struct wlr_surface *focused_surface =
|
||
|
event->seat_client->seat->pointer_state.focused_surface;
|
||
|
struct wl_client *focused_client = NULL;
|
||
|
|
||
|
if (focused_surface && focused_surface->resource) {
|
||
|
focused_client = wl_resource_get_client(focused_surface->resource);
|
||
|
}
|
||
|
|
||
|
if (event->seat_client->client != focused_client) {
|
||
|
wlr_log(
|
||
|
WLR_DEBUG, "Ignoring request to set cursor on unfocused client");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
struct kiwmi_input *input = seat->input;
|
||
|
struct kiwmi_server *server = wl_container_of(input, server, input);
|
||
|
|
||
|
struct kiwmi_output *output;
|
||
|
wl_list_for_each (output, &server->desktop.outputs, link) {
|
||
|
output_damage(output);
|
||
|
}
|
||
|
|
||
|
wlr_cursor_set_surface(
|
||
|
cursor->cursor, event->surface, event->hotspot_x, event->hotspot_y);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
request_set_selection_notify(struct wl_listener *listener, void *data)
|
||
|
{
|
||
|
struct kiwmi_seat *seat =
|
||
|
wl_container_of(listener, seat, request_set_selection);
|
||
|
struct wlr_seat_request_set_selection_event *event = data;
|
||
|
wlr_seat_set_selection(seat->seat, event->source, event->serial);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
request_set_primary_selection_notify(struct wl_listener *listener, void *data)
|
||
|
{
|
||
|
struct kiwmi_seat *seat =
|
||
|
wl_container_of(listener, seat, request_set_primary_selection);
|
||
|
struct wlr_seat_request_set_primary_selection_event *event = data;
|
||
|
wlr_seat_set_primary_selection(seat->seat, event->source, event->serial);
|
||
|
}
|
||
|
|
||
|
struct kiwmi_seat *
|
||
|
seat_create(struct kiwmi_input *input)
|
||
|
{
|
||
|
struct kiwmi_server *server = wl_container_of(input, server, input);
|
||
|
|
||
|
struct kiwmi_seat *seat = malloc(sizeof(*seat));
|
||
|
if (!seat) {
|
||
|
wlr_log(WLR_ERROR, "Failed to allocate kiwmi_seat");
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
seat->input = input;
|
||
|
seat->seat = wlr_seat_create(server->wl_display, "seat-0");
|
||
|
|
||
|
seat->focused_view = NULL;
|
||
|
seat->focused_layer = NULL;
|
||
|
|
||
|
seat->request_set_cursor.notify = request_set_cursor_notify;
|
||
|
wl_signal_add(
|
||
|
&seat->seat->events.request_set_cursor, &seat->request_set_cursor);
|
||
|
|
||
|
wl_signal_add(
|
||
|
&seat->seat->events.request_set_selection,
|
||
|
&seat->request_set_selection);
|
||
|
seat->request_set_selection.notify = request_set_selection_notify;
|
||
|
|
||
|
wl_signal_add(
|
||
|
&seat->seat->events.request_set_primary_selection,
|
||
|
&seat->request_set_primary_selection);
|
||
|
seat->request_set_primary_selection.notify =
|
||
|
request_set_primary_selection_notify;
|
||
|
|
||
|
return seat;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
seat_destroy(struct kiwmi_seat *seat)
|
||
|
{
|
||
|
wl_list_remove(&seat->request_set_cursor.link);
|
||
|
wl_list_remove(&seat->request_set_selection.link);
|
||
|
wl_list_remove(&seat->request_set_primary_selection.link);
|
||
|
|
||
|
free(seat);
|
||
|
}
|