#include "labwc.h" static void server_new_pointer(struct server *server, struct wlr_input_device *device) { /* TODO: Configure libinput on device to set tap, acceleration, etc */ wlr_cursor_attach_input_device(server->cursor, device); } void server_new_input(struct wl_listener *listener, void *data) { /* * This event is raised by the backend when a new input device becomes * available. */ struct server *server = wl_container_of(listener, server, new_input); struct wlr_input_device *device = data; switch (device->type) { case WLR_INPUT_DEVICE_KEYBOARD: keyboard_new(server, device); break; case WLR_INPUT_DEVICE_POINTER: server_new_pointer(server, device); break; default: break; } /* * We need to let the wlr_seat know what our capabilities are, which is * communiciated to the client. */ uint32_t caps = WL_SEAT_CAPABILITY_POINTER; if (!wl_list_empty(&server->keyboards)) { caps |= WL_SEAT_CAPABILITY_KEYBOARD; } wlr_seat_set_capabilities(server->seat, caps); } void seat_request_cursor(struct wl_listener *listener, void *data) { struct server *server = wl_container_of(listener, server, request_cursor); /* * This event is rasied by the seat when a client provides a cursor * image */ struct wlr_seat_pointer_request_set_cursor_event *event = data; struct wlr_seat_client *focused_client = server->seat->pointer_state.focused_client; /* This can be sent by any client, so we check to make sure this one is * actually has pointer focus first. */ if (focused_client == event->seat_client) { /* Once we've vetted the client, we can tell the cursor to use * the provided surface as the cursor image. It will set the * hardware cursor on the output that it's currently on and * continue to do so as the cursor moves between outputs. */ wlr_cursor_set_surface(server->cursor, event->surface, event->hotspot_x, event->hotspot_y); } } void seat_request_set_selection(struct wl_listener *listener, void *data) { struct server *server = wl_container_of(listener, server, request_set_selection); struct wlr_seat_request_set_selection_event *event = data; wlr_seat_set_selection(server->seat, event->source, event->serial); } void server_new_output(struct wl_listener *listener, void *data) { /* This event is rasied by the backend when a new output (aka a display * or monitor) becomes available. */ struct server *server = wl_container_of(listener, server, new_output); struct wlr_output *wlr_output = data; /* * Some backends don't have modes. DRM+KMS does, and we need to set a * mode before we can use the output. The mode is a tuple of (width, * height, refresh rate), and each monitor supports only a specific set * of modes. We just pick the monitor's preferred mode. * TODO: support user configuration */ if (!wl_list_empty(&wlr_output->modes)) { struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output); wlr_output_set_mode(wlr_output, mode); wlr_output_enable(wlr_output, true); if (!wlr_output_commit(wlr_output)) { return; } } /* Allocates and configures our state for this output */ struct output *output = calloc(1, sizeof(struct output)); output->wlr_output = wlr_output; output->server = server; /* Sets up a listener for the frame notify event. */ output->frame.notify = output_frame; wl_signal_add(&wlr_output->events.frame, &output->frame); wl_list_insert(&server->outputs, &output->link); /* Adds this to the output layout. The add_auto function arranges * outputs from left-to-right in the order they appear. A more * sophisticated compositor would let the user configure the arrangement * of outputs in the layout. * * The output layout utility automatically adds a wl_output global to * the display, which Wayland clients can see to find out information * about the output (such as DPI, scale factor, manufacturer, etc). */ wlr_output_layout_add_auto(server->output_layout, wlr_output); }