aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2019-08-09 08:34:59 +0900
committerDrew DeVault <sir@cmpwn.com>2019-08-09 08:34:59 +0900
commit58b2584863201f32d1a4770a1d5cde5e57b300c6 (patch)
tree5e24e6cbb4078eff9c0d1aaeadd24134edea2b90
parent913cac18359d7962e74892771bf6bd3ecf54a4a1 (diff)
Remove rootston
-rw-r--r--.gitignore1
-rw-r--r--include/rootston/bindings.h9
-rw-r--r--include/rootston/config.h133
-rw-r--r--include/rootston/cursor.h114
-rw-r--r--include/rootston/desktop.h106
-rw-r--r--include/rootston/ini.h93
-rw-r--r--include/rootston/input.h37
-rw-r--r--include/rootston/keyboard.h34
-rw-r--r--include/rootston/layers.h35
-rw-r--r--include/rootston/output.h88
-rw-r--r--include/rootston/seat.h183
-rw-r--r--include/rootston/server.h37
-rw-r--r--include/rootston/switch.h18
-rw-r--r--include/rootston/text_input.h63
-rw-r--r--include/rootston/view.h257
-rw-r--r--include/rootston/virtual_keyboard.h7
-rw-r--r--include/rootston/xcursor.h12
-rw-r--r--meson.build1
-rw-r--r--meson_options.txt1
-rw-r--r--rootston/README.md18
-rw-r--r--rootston/bindings.c110
-rw-r--r--rootston/config.c674
-rw-r--r--rootston/cursor.c632
-rw-r--r--rootston/desktop.c465
-rw-r--r--rootston/ini.c195
-rw-r--r--rootston/input.c146
-rw-r--r--rootston/keyboard.c349
-rw-r--r--rootston/layer_shell.c506
-rw-r--r--rootston/main.c83
-rw-r--r--rootston/meson.build31
-rw-r--r--rootston/output.c688
-rw-r--r--rootston/render.c422
-rw-r--r--rootston/rootston.ini.example63
-rw-r--r--rootston/seat.c1642
-rw-r--r--rootston/switch.c22
-rw-r--r--rootston/text_input.c312
-rw-r--r--rootston/view.c685
-rw-r--r--rootston/virtual_keyboard.c21
-rw-r--r--rootston/xdg_shell.c572
-rw-r--r--rootston/xdg_shell_v6.c504
-rw-r--r--rootston/xwayland.c355
41 files changed, 0 insertions, 9724 deletions
diff --git a/.gitignore b/.gitignore
index 516afff1..f635e54f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,3 @@ build/
build-*/
wayland-*-protocol.*
wlr-example.ini
-rootston.ini
diff --git a/include/rootston/bindings.h b/include/rootston/bindings.h
deleted file mode 100644
index db38130b..00000000
--- a/include/rootston/bindings.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef ROOTSTON_BINDINGS_H
-#define ROOTSTON_BINDINGS_H
-
-#include "rootston/seat.h"
-#include "rootston/input.h"
-
-void execute_binding_command(struct roots_seat *seat, struct roots_input *input, const char *command);
-
-#endif //ROOTSTON_BINDINGS_H
diff --git a/include/rootston/config.h b/include/rootston/config.h
deleted file mode 100644
index f8132269..00000000
--- a/include/rootston/config.h
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifndef ROOTSTON_CONFIG_H
-#define ROOTSTON_CONFIG_H
-
-#include <xf86drmMode.h>
-#include <wlr/types/wlr_input_device.h>
-#include <wlr/types/wlr_switch.h>
-#include <wlr/types/wlr_output_layout.h>
-
-#define ROOTS_CONFIG_DEFAULT_SEAT_NAME "seat0"
-
-struct roots_output_mode_config {
- drmModeModeInfo info;
- struct wl_list link;
-};
-
-struct roots_output_config {
- char *name;
- bool enable;
- enum wl_output_transform transform;
- int x, y;
- float scale;
- struct wl_list link;
- struct {
- int width, height;
- float refresh_rate;
- } mode;
- struct wl_list modes;
-};
-
-struct roots_device_config {
- char *name;
- char *seat;
- char *mapped_output;
- bool tap_enabled;
- struct wlr_box *mapped_box;
- struct wl_list link;
-};
-
-struct roots_binding_config {
- uint32_t modifiers;
- xkb_keysym_t *keysyms;
- size_t keysyms_len;
- char *command;
- struct wl_list link;
-};
-
-struct roots_keyboard_config {
- char *name;
- char *seat;
- uint32_t meta_key;
- char *rules;
- char *model;
- char *layout;
- char *variant;
- char *options;
- int repeat_rate, repeat_delay;
- struct wl_list link;
-};
-
-struct roots_cursor_config {
- char *seat;
- char *mapped_output;
- struct wlr_box *mapped_box;
- char *theme;
- char *default_image;
- struct wl_list link;
-};
-
-struct roots_switch_config {
- char *name;
- enum wlr_switch_type switch_type;
- enum wlr_switch_state switch_state;
- char *command;
- struct wl_list link;
-};
-
-struct roots_config {
- bool xwayland;
- bool xwayland_lazy;
-
- struct wl_list outputs;
- struct wl_list devices;
- struct wl_list bindings;
- struct wl_list keyboards;
- struct wl_list cursors;
- struct wl_list switches;
-
- char *config_path;
- char *startup_cmd;
- bool debug_damage_tracking;
-};
-
-/**
- * Create a roots config from the given command line arguments. Command line
- * arguments can specify the location of the config file. If it is not
- * specified, the default location will be used.
- */
-struct roots_config *roots_config_create_from_args(int argc, char *argv[]);
-
-/**
- * Destroy the config and free its resources.
- */
-void roots_config_destroy(struct roots_config *config);
-
-/**
- * Get configuration for the output. If the output is not configured, returns
- * NULL.
- */
-struct roots_output_config *roots_config_get_output(struct roots_config *config,
- struct wlr_output *output);
-
-/**
- * Get configuration for the device. If the device is not configured, returns
- * NULL.
- */
-struct roots_device_config *roots_config_get_device(struct roots_config *config,
- struct wlr_input_device *device);
-
-/**
- * Get configuration for the keyboard. If the keyboard is not configured,
- * returns NULL. A NULL device returns the default config for keyboards.
- */
-struct roots_keyboard_config *roots_config_get_keyboard(
- struct roots_config *config, struct wlr_input_device *device);
-
-/**
- * Get configuration for the cursor. If the cursor is not configured, returns
- * NULL. A NULL seat_name returns the default config for cursors.
- */
-struct roots_cursor_config *roots_config_get_cursor(struct roots_config *config,
- const char *seat_name);
-
-#endif
diff --git a/include/rootston/cursor.h b/include/rootston/cursor.h
deleted file mode 100644
index 0d6b6014..00000000
--- a/include/rootston/cursor.h
+++ /dev/null
@@ -1,114 +0,0 @@
-#ifndef ROOTSTON_CURSOR_H
-#define ROOTSTON_CURSOR_H
-
-#include <wlr/types/wlr_pointer_constraints_v1.h>
-#include "rootston/seat.h"
-
-enum roots_cursor_mode {
- ROOTS_CURSOR_PASSTHROUGH = 0,
- ROOTS_CURSOR_MOVE = 1,
- ROOTS_CURSOR_RESIZE = 2,
- ROOTS_CURSOR_ROTATE = 3,
-};
-
-struct roots_cursor {
- struct roots_seat *seat;
- struct wlr_cursor *cursor;
-
- struct wlr_pointer_constraint_v1 *active_constraint;
- pixman_region32_t confine; // invalid if active_constraint == NULL
-
- const char *default_xcursor;
-
- enum roots_cursor_mode mode;
-
- // state from input (review if this is necessary)
- struct wlr_xcursor_manager *xcursor_manager;
- struct wlr_seat *wl_seat;
- struct wl_client *cursor_client;
- int offs_x, offs_y;
- int view_x, view_y, view_width, view_height;
- float view_rotation;
- uint32_t resize_edges;
-
- struct roots_seat_view *pointer_view;
- struct wlr_surface *wlr_surface;
-
- struct wl_listener motion;
- struct wl_listener motion_absolute;
- struct wl_listener button;
- struct wl_listener axis;
- struct wl_listener frame;
- struct wl_listener swipe_begin;
- struct wl_listener swipe_update;
- struct wl_listener swipe_end;
- struct wl_listener pinch_begin;
- struct wl_listener pinch_update;
- struct wl_listener pinch_end;
-
- struct wl_listener touch_down;
- struct wl_listener touch_up;
- struct wl_listener touch_motion;
-
- struct wl_listener tool_axis;
- struct wl_listener tool_tip;
- struct wl_listener tool_proximity;
- struct wl_listener tool_button;
-
- struct wl_listener request_set_cursor;
-
- struct wl_listener focus_change;
-
- struct wl_listener constraint_commit;
-};
-
-struct roots_cursor *roots_cursor_create(struct roots_seat *seat);
-
-void roots_cursor_destroy(struct roots_cursor *cursor);
-
-void roots_cursor_handle_motion(struct roots_cursor *cursor,
- struct wlr_event_pointer_motion *event);
-
-void roots_cursor_handle_motion_absolute(struct roots_cursor *cursor,
- struct wlr_event_pointer_motion_absolute *event);
-
-void roots_cursor_handle_button(struct roots_cursor *cursor,
- struct wlr_event_pointer_button *event);
-
-void roots_cursor_handle_axis(struct roots_cursor *cursor,
- struct wlr_event_pointer_axis *event);
-
-void roots_cursor_handle_frame(struct roots_cursor *cursor);
-
-void roots_cursor_handle_touch_down(struct roots_cursor *cursor,
- struct wlr_event_touch_down *event);
-
-void roots_cursor_handle_touch_up(struct roots_cursor *cursor,
- struct wlr_event_touch_up *event);
-
-void roots_cursor_handle_touch_motion(struct roots_cursor *cursor,
- struct wlr_event_touch_motion *event);
-
-void roots_cursor_handle_tool_axis(struct roots_cursor *cursor,
- struct wlr_event_tablet_tool_axis *event);
-
-void roots_cursor_handle_tool_tip(struct roots_cursor *cursor,
- struct wlr_event_tablet_tool_tip *event);
-
-void roots_cursor_handle_request_set_cursor(struct roots_cursor *cursor,
- struct wlr_seat_pointer_request_set_cursor_event *event);
-
-void roots_cursor_handle_focus_change(struct roots_cursor *cursor,
- struct wlr_seat_pointer_focus_change_event *event);
-
-void roots_cursor_handle_constraint_commit(struct roots_cursor *cursor);
-
-void roots_cursor_update_position(struct roots_cursor *cursor,
- uint32_t time);
-
-void roots_cursor_update_focus(struct roots_cursor *cursor);
-
-void roots_cursor_constrain(struct roots_cursor *cursor,
- struct wlr_pointer_constraint_v1 *constraint, double sx, double sy);
-
-#endif
diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h
deleted file mode 100644
index d3d6ec18..00000000
--- a/include/rootston/desktop.h
+++ /dev/null
@@ -1,106 +0,0 @@
-#ifndef ROOTSTON_DESKTOP_H
-#define ROOTSTON_DESKTOP_H
-#include <time.h>
-#include <wayland-server-core.h>
-#include <wlr/config.h>
-#include <wlr/types/wlr_compositor.h>
-#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
-#include <wlr/types/wlr_gamma_control_v1.h>
-#include <wlr/types/wlr_gtk_primary_selection.h>
-#include <wlr/types/wlr_idle_inhibit_v1.h>
-#include <wlr/types/wlr_idle.h>
-#include <wlr/types/wlr_input_inhibitor.h>
-#include <wlr/types/wlr_input_method_v2.h>
-#include <wlr/types/wlr_layer_shell_v1.h>
-#include <wlr/types/wlr_list.h>
-#include <wlr/types/wlr_output_layout.h>
-#include <wlr/types/wlr_output_management_v1.h>
-#include <wlr/types/wlr_output.h>
-#include <wlr/types/wlr_pointer_gestures_v1.h>
-#include <wlr/types/wlr_presentation_time.h>
-#include <wlr/types/wlr_relative_pointer_v1.h>
-#include <wlr/types/wlr_screencopy_v1.h>
-#include <wlr/types/wlr_text_input_v3.h>
-#include <wlr/types/wlr_virtual_keyboard_v1.h>
-#include <wlr/types/wlr_xcursor_manager.h>
-#include <wlr/types/wlr_xdg_decoration_v1.h>
-#include <wlr/types/wlr_xdg_shell_v6.h>
-#include <wlr/types/wlr_xdg_shell.h>
-#include "rootston/config.h"
-#include "rootston/output.h"
-#include "rootston/view.h"
-
-struct roots_desktop {
- struct wl_list views; // roots_view::link
-
- struct wl_list outputs; // roots_output::link
- struct timespec last_frame;
-
- struct roots_server *server;
- struct roots_config *config;
-
- struct wlr_output_layout *layout;
- struct wlr_xcursor_manager *xcursor_manager;
-
- struct wlr_compositor *compositor;
- struct wlr_xdg_shell_v6 *xdg_shell_v6;
- struct wlr_xdg_shell *xdg_shell;
- struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1;
- struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager_v1;
- struct wlr_server_decoration_manager *server_decoration_manager;
- struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager;
- struct wlr_gtk_primary_selection_device_manager *primary_selection_device_manager;
- struct wlr_idle *idle;
- struct wlr_idle_inhibit_manager_v1 *idle_inhibit;
- struct wlr_input_inhibit_manager *input_inhibit;
- struct wlr_layer_shell_v1 *layer_shell;
- struct wlr_input_method_manager_v2 *input_method;
- struct wlr_text_input_manager_v3 *text_input;
- struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard;
- struct wlr_screencopy_manager_v1 *screencopy;
- struct wlr_tablet_manager_v2 *tablet_v2;
- struct wlr_pointer_constraints_v1 *pointer_constraints;
- struct wlr_presentation *presentation;
- struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager_v1;
- struct wlr_relative_pointer_manager_v1 *relative_pointer_manager;
- struct wlr_pointer_gestures_v1 *pointer_gestures;
- struct wlr_output_manager_v1 *output_manager_v1;
-
- struct wl_listener new_output;
- struct wl_listener layout_change;
- struct wl_listener xdg_shell_v6_surface;
- struct wl_listener xdg_shell_surface;
- struct wl_listener layer_shell_surface;
- struct wl_listener xdg_toplevel_decoration;
- struct wl_listener input_inhibit_activate;
- struct wl_listener input_inhibit_deactivate;
- struct wl_listener virtual_keyboard_new;
- struct wl_listener pointer_constraint;
- struct wl_listener output_manager_apply;
- struct wl_listener output_manager_test;
-
-#if WLR_HAS_XWAYLAND
- struct wlr_xwayland *xwayland;
- struct wl_listener xwayland_surface;
-#endif
-};
-
-struct roots_server;
-
-struct roots_desktop *desktop_create(struct roots_server *server,
- struct roots_config *config);
-void desktop_destroy(struct roots_desktop *desktop);
-struct roots_output *desktop_output_from_wlr_output(
- struct roots_desktop *desktop, struct wlr_output *output);
-
-struct wlr_surface *desktop_surface_at(struct roots_desktop *desktop,
- double lx, double ly, double *sx, double *sy,
- struct roots_view **view);
-
-void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data);
-void handle_xdg_shell_surface(struct wl_listener *listener, void *data);
-void handle_xdg_toplevel_decoration(struct wl_listener *listener, void *data);
-void handle_layer_shell_surface(struct wl_listener *listener, void *data);
-void handle_xwayland_surface(struct wl_listener *listener, void *data);
-
-#endif
diff --git a/include/rootston/ini.h b/include/rootston/ini.h
deleted file mode 100644
index 2804255b..00000000
--- a/include/rootston/ini.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* inih -- simple .INI file parser
-
-inih is released under the New BSD license (see LICENSE.txt). Go to the project
-home page for more info:
-
-https://github.com/benhoyt/inih
-
-*/
-
-#ifndef __INI_H__
-#define __INI_H__
-
-/* Make this header file easier to include in C++ code */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdio.h>
-
-/* Typedef for prototype of handler function. */
-typedef int (*ini_handler)(void* user, const char* section,
- const char* name, const char* value);
-
-/* Typedef for prototype of fgets-style reader function. */
-typedef char* (*ini_reader)(char* str, int num, void* stream);
-
-/* Parse given INI-style file. May have [section]s, name=value pairs
- (whitespace stripped), and comments starting with ';' (semicolon). Section
- is "" if name=value pair parsed before any section heading. name:value
- pairs are also supported as a concession to Python's configparser.
-
- For each name=value pair parsed, call handler function with given user
- pointer as well as section, name, and value (data only valid for duration
- of handler call). Handler should return nonzero on success, zero on error.
-
- Returns 0 on success, line number of first error on parse error (doesn't
- stop on first error), -1 on file open error, or -2 on memory allocation
- error (only when INI_USE_STACK is zero).
-*/
-int ini_parse(const char* filename, ini_handler handler, void* user);
-
-/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
- close the file when it's finished -- the caller must do that. */
-int ini_parse_file(FILE* file, ini_handler handler, void* user);
-
-/* Same as ini_parse(), but takes an ini_reader function pointer instead of
- filename. Used for implementing custom or string-based I/O. */
-int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
- void* user);
-
-/* Nonzero to allow multi-line value parsing, in the style of Python's
- configparser. If allowed, ini_parse() will call the handler with the same
- name for each subsequent line parsed. */
-#ifndef INI_ALLOW_MULTILINE
-#define INI_ALLOW_MULTILINE 1
-#endif
-
-/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
- the file. See http://code.google.com/p/inih/issues/detail?id=21 */
-#ifndef INI_ALLOW_BOM
-#define INI_ALLOW_BOM 1
-#endif
-
-/* Nonzero to allow inline comments (with valid inline comment characters
- specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match
- Python 3.2+ configparser behaviour. */
-#ifndef INI_ALLOW_INLINE_COMMENTS
-#define INI_ALLOW_INLINE_COMMENTS 1
-#endif
-#ifndef INI_INLINE_COMMENT_PREFIXES
-#define INI_INLINE_COMMENT_PREFIXES ";"
-#endif
-
-/* Nonzero to use stack, zero to use heap (malloc/free). */
-#ifndef INI_USE_STACK
-#define INI_USE_STACK 1
-#endif
-
-/* Stop parsing on first error (default is to keep parsing). */
-#ifndef INI_STOP_ON_FIRST_ERROR
-#define INI_STOP_ON_FIRST_ERROR 0
-#endif
-
-/* Maximum line length for any line in INI file. */
-#ifndef INI_MAX_LINE
-#define INI_MAX_LINE 2000
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __INI_H__ */
diff --git a/include/rootston/input.h b/include/rootston/input.h
deleted file mode 100644
index a799db59..00000000
--- a/include/rootston/input.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef ROOTSTON_INPUT_H
-#define ROOTSTON_INPUT_H
-
-#include <wayland-server-core.h>
-#include <wlr/types/wlr_cursor.h>
-#include <wlr/types/wlr_input_device.h>
-#include <wlr/types/wlr_seat.h>
-#include "rootston/config.h"
-#include "rootston/cursor.h"
-#include "rootston/server.h"
-#include "rootston/view.h"
-
-struct roots_input {
- struct roots_config *config;
- struct roots_server *server;
-
- struct wl_listener new_input;
-
- struct wl_list seats; // roots_seat::link
-};
-
-struct roots_input *input_create(struct roots_server *server,
- struct roots_config *config);
-void input_destroy(struct roots_input *input);
-
-struct roots_seat *input_seat_from_wlr_seat(struct roots_input *input,
- struct wlr_seat *seat);
-
-bool input_view_has_focus(struct roots_input *input, struct roots_view *view);
-
-struct roots_seat *input_get_seat(struct roots_input *input, char *name);
-
-struct roots_seat *input_last_active_seat(struct roots_input *input);
-
-void input_update_cursor_focus(struct roots_input *input);
-
-#endif
diff --git a/include/rootston/keyboard.h b/include/rootston/keyboard.h
deleted file mode 100644
index 0140389a..00000000
--- a/include/rootston/keyboard.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef ROOTSTON_KEYBOARD_H
-#define ROOTSTON_KEYBOARD_H
-
-#include <xkbcommon/xkbcommon.h>
-#include "rootston/input.h"
-
-#define ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP 32
-
-struct roots_keyboard {
- struct roots_input *input;
- struct roots_seat *seat;
- struct wlr_input_device *device;
- struct roots_keyboard_config *config;
- struct wl_list link;
-
- struct wl_listener device_destroy;
- struct wl_listener keyboard_key;
- struct wl_listener keyboard_modifiers;
-
- xkb_keysym_t pressed_keysyms_translated[ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP];
- xkb_keysym_t pressed_keysyms_raw[ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP];
-};
-
-struct roots_keyboard *roots_keyboard_create(struct wlr_input_device *device,
- struct roots_input *input);
-
-void roots_keyboard_destroy(struct roots_keyboard *keyboard);
-
-void roots_keyboard_handle_key(struct roots_keyboard *keyboard,
- struct wlr_event_keyboard_key *event);
-
-void roots_keyboard_handle_modifiers(struct roots_keyboard *r_keyboard);
-
-#endif
diff --git a/include/rootston/layers.h b/include/rootston/layers.h
deleted file mode 100644
index 0dacf20f..00000000
--- a/include/rootston/layers.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef ROOTSTON_LAYERS_H
-#define ROOTSTON_LAYERS_H
-#include <stdbool.h>
-#include <wlr/types/wlr_box.h>
-#include <wlr/types/wlr_surface.h>
-#include <wlr/types/wlr_layer_shell_v1.h>
-
-struct roots_layer_surface {
- struct wlr_layer_surface_v1 *layer_surface;
- struct wl_list link;
-
- struct wl_listener destroy;
- struct wl_listener map;
- struct wl_listener unmap;
- struct wl_listener surface_commit;
- struct wl_listener output_destroy;
- struct wl_listener new_popup;
-
- bool configured;
- struct wlr_box geo;
-};
-
-struct roots_layer_popup {
- struct roots_layer_surface *parent;
- struct wlr_xdg_popup *wlr_popup;
- struct wl_listener map;
- struct wl_listener unmap;
- struct wl_listener destroy;
- struct wl_listener commit;
-};
-
-struct roots_output;
-void arrange_layers(struct roots_output *output);
-
-#endif
diff --git a/include/rootston/output.h b/include/rootston/output.h
deleted file mode 100644
index 257d9367..00000000
--- a/include/rootston/output.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef ROOTSTON_OUTPUT_H
-#define ROOTSTON_OUTPUT_H
-#include <pixman.h>
-#include <time.h>
-#include <wayland-server-core.h>
-#include <wlr/types/wlr_box.h>
-#include <wlr/types/wlr_output_damage.h>
-
-struct roots_desktop;
-
-struct roots_output {
- struct roots_desktop *desktop;
- struct wlr_output *wlr_output;
- struct wl_list link; // roots_desktop:outputs
-
- struct roots_view *fullscreen_view;
- struct wl_list layers[4]; // layer_surface::link
-
- struct timespec last_frame;
- struct wlr_output_damage *damage;
-
- struct wlr_box usable_area;
-
- struct wl_listener destroy;
- struct wl_listener enable;
- struct wl_listener mode;
- struct wl_listener transform;
- struct wl_listener present;
- struct wl_listener damage_frame;
- struct wl_listener damage_destroy;
-};
-
-typedef void (*roots_surface_iterator_func_t)(struct roots_output *output,
- struct wlr_surface *surface, struct wlr_box *box, float rotation,
- void *user_data);
-
-void rotate_child_position(double *sx, double *sy, double sw, double sh,
- double pw, double ph, float rotation);
-
-struct roots_input;
-
-void output_surface_for_each_surface(struct roots_output *output,
- struct wlr_surface *surface, double ox, double oy,
- roots_surface_iterator_func_t iterator, void *user_data);
-void output_view_for_each_surface(struct roots_output *output,
- struct roots_view *view, roots_surface_iterator_func_t iterator,
- void *user_data);
-void output_drag_icons_for_each_surface(struct roots_output *output,
- struct roots_input *input, roots_surface_iterator_func_t iterator,
- void *user_data);
-void output_layer_for_each_surface(struct roots_output *output,
- struct wl_list *layer_surfaces, roots_surface_iterator_func_t iterator,
- void *user_data);
-#if WLR_HAS_XWAYLAND
-struct wlr_xwayland_surface;
-void output_xwayland_children_for_each_surface(
- struct roots_output *output, struct wlr_xwayland_surface *surface,
- roots_surface_iterator_func_t iterator, void *user_data);
-#endif
-void output_for_each_surface(struct roots_output *output,
- roots_surface_iterator_func_t iterator, void *user_data);
-
-void handle_new_output(struct wl_listener *listener, void *data);
-void handle_output_manager_apply(struct wl_listener *listener, void *data);
-void handle_output_manager_test(struct wl_listener *listener, void *data);
-
-struct roots_view;
-struct roots_drag_icon;
-
-void output_damage_whole(struct roots_output *output);
-void output_damage_whole_view(struct roots_output *output,
- struct roots_view *view);
-void output_damage_from_view(struct roots_output *output,
- struct roots_view *view);
-void output_damage_whole_drag_icon(struct roots_output *output,
- struct roots_drag_icon *icon);
-void output_damage_from_local_surface(struct roots_output *output,
- struct wlr_surface *surface, double ox, double oy);
-void output_damage_whole_local_surface(struct roots_output *output,
- struct wlr_surface *surface, double ox, double oy);
-
-void output_render(struct roots_output *output);
-
-void scale_box(struct wlr_box *box, float scale);
-void get_decoration_box(struct roots_view *view,
- struct roots_output *output, struct wlr_box *box);
-
-#endif
diff --git a/include/rootston/seat.h b/include/rootston/seat.h
deleted file mode 100644
index fa3a83dd..00000000
--- a/include/rootston/seat.h
+++ /dev/null
@@ -1,183 +0,0 @@
-#ifndef ROOTSTON_SEAT_H
-#define ROOTSTON_SEAT_H
-
-#include <wayland-server-core.h>
-#include "rootston/input.h"
-#include "rootston/keyboard.h"
-#include "rootston/layers.h"
-#include "rootston/switch.h"
-#include "rootston/text_input.h"
-
-struct roots_seat {
- struct roots_input *input;
- struct wlr_seat *seat;
- struct roots_cursor *cursor;
- struct wl_list link; // roots_input::seats
-
- // coordinates of the first touch point if it exists
- int32_t touch_id;
- double touch_x, touch_y;
-
- // If the focused layer is set, views cannot receive keyboard focus
- struct wlr_layer_surface_v1 *focused_layer;
-
- struct roots_input_method_relay im_relay;
-
- // If non-null, only this client can receive input events
- struct wl_client *exclusive_client;
-
- struct wl_list views; // roots_seat_view::link
- bool has_focus;
-
- struct roots_drag_icon *drag_icon; // can be NULL
-
- struct wl_list keyboards;
- struct wl_list pointers;
- struct wl_list switches;
- struct wl_list touch;
- struct wl_list tablets;
- struct wl_list tablet_pads;
-
- struct wl_listener request_set_selection;
- struct wl_listener request_set_primary_selection;
- struct wl_listener request_start_drag;
- struct wl_listener start_drag;
- struct wl_listener destroy;
-};
-
-struct roots_seat_view {
- struct roots_seat *seat;
- struct roots_view *view;
-
- bool has_button_grab;
- double grab_sx;
- double grab_sy;
-
- struct wl_list link; // roots_seat::views
-
- struct wl_listener view_unmap;
- struct wl_listener view_destroy;
-};
-
-struct roots_drag_icon {
- struct roots_seat *seat;
- struct wlr_drag_icon *wlr_drag_icon;
-
- double x, y;
-
- struct wl_listener surface_commit;
- struct wl_listener map;
- struct wl_listener unmap;
- struct wl_listener destroy;
-};
-
-struct roots_pointer {
- struct roots_seat *seat;
- struct wlr_input_device *device;
- struct wl_listener device_destroy;
- struct wl_list link;
-};
-
-struct roots_touch {
- struct roots_seat *seat;
- struct wlr_input_device *device;
- struct wl_listener device_destroy;
- struct wl_list link;
-};
-
-struct roots_tablet {
- struct roots_seat *seat;
- struct wlr_input_device *device;
- struct wlr_tablet_v2_tablet *tablet_v2;
-
- struct wl_listener device_destroy;
- struct wl_listener axis;
- struct wl_listener proximity;
- struct wl_listener tip;
- struct wl_listener button;
- struct wl_list link;
-};
-
-struct roots_tablet_pad {
- struct wl_list link;
- struct wlr_tablet_v2_tablet_pad *tablet_v2_pad;
-
- struct roots_seat *seat;
- struct wlr_input_device *device;
-
- struct wl_listener device_destroy;
- struct wl_listener attach;
- struct wl_listener button;
- struct wl_listener ring;
- struct wl_listener strip;
-
- struct roots_tablet *tablet;
- struct wl_listener tablet_destroy;
-};
-
-struct roots_tablet_tool {
- struct wl_list link;
- struct wl_list tool_link;
- struct wlr_tablet_v2_tablet_tool *tablet_v2_tool;
-
- struct roots_seat *seat;
- double tilt_x, tilt_y;
-
- struct wl_listener set_cursor;
- struct wl_listener tool_destroy;
-
- struct roots_tablet *current_tablet;
- struct wl_listener tablet_destroy;
-};
-
-struct roots_pointer_constraint {
- struct wlr_pointer_constraint_v1 *constraint;
-
- struct wl_listener destroy;
-};
-
-struct roots_seat *roots_seat_create(struct roots_input *input, char *name);
-
-void roots_seat_destroy(struct roots_seat *seat);
-
-void roots_seat_add_device(struct roots_seat *seat,
- struct wlr_input_device *device);
-
-void roots_seat_configure_cursor(struct roots_seat *seat);
-
-void roots_seat_configure_xcursor(struct roots_seat *seat);
-
-bool roots_seat_has_meta_pressed(struct roots_seat *seat);
-
-struct roots_view *roots_seat_get_focus(struct roots_seat *seat);
-
-void roots_seat_set_focus(struct roots_seat *seat, struct roots_view *view);
-
-void roots_seat_set_focus_layer(struct roots_seat *seat,
- struct wlr_layer_surface_v1 *layer);
-
-void roots_seat_cycle_focus(struct roots_seat *seat);
-
-void roots_seat_begin_move(struct roots_seat *seat, struct roots_view *view);
-
-void roots_seat_begin_resize(struct roots_seat *seat, struct roots_view *view,
- uint32_t edges);
-
-void roots_seat_begin_rotate(struct roots_seat *seat, struct roots_view *view);
-
-void roots_seat_end_compositor_grab(struct roots_seat *seat);
-
-struct roots_seat_view *roots_seat_view_from_view( struct roots_seat *seat,
- struct roots_view *view);
-
-void roots_drag_icon_update_position(struct roots_drag_icon *icon);
-
-void roots_drag_icon_damage_whole(struct roots_drag_icon *icon);
-
-void roots_seat_set_exclusive_client(struct roots_seat *seat,
- struct wl_client *client);
-
-bool roots_seat_allow_input(struct roots_seat *seat,
- struct wl_resource *resource);
-
-#endif
diff --git a/include/rootston/server.h b/include/rootston/server.h
deleted file mode 100644
index f48549f2..00000000
--- a/include/rootston/server.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _ROOTSTON_SERVER_H
-#define _ROOTSTON_SERVER_H
-
-#include <wayland-server-core.h>
-#include <wlr/backend.h>
-#include <wlr/backend/session.h>
-#include <wlr/config.h>
-#include <wlr/render/wlr_renderer.h>
-#include <wlr/types/wlr_data_device.h>
-#if WLR_HAS_XWAYLAND
-#include <wlr/xwayland.h>
-#endif
-#include "rootston/config.h"
-#include "rootston/desktop.h"
-#include "rootston/input.h"
-
-struct roots_server {
- /* Rootston resources */
- struct roots_config *config;
- struct roots_desktop *desktop;
- struct roots_input *input;
-
- /* Wayland resources */
- struct wl_display *wl_display;
- struct wl_event_loop *wl_event_loop;
-
- /* WLR tools */
- struct wlr_backend *backend;
- struct wlr_renderer *renderer;
-
- /* Global resources */
- struct wlr_data_device_manager *data_device_manager;
-};
-
-extern struct roots_server server;
-
-#endif
diff --git a/include/rootston/switch.h b/include/rootston/switch.h
deleted file mode 100644
index 32bc3dab..00000000
--- a/include/rootston/switch.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef ROOTSTON_SWITCH_H
-#define ROOTSTON_SWITCH_H
-
-#include "rootston/input.h"
-
-struct roots_switch {
- struct roots_seat *seat;
- struct wlr_input_device *device;
- struct wl_listener device_destroy;
-
- struct wl_listener toggle;
- struct wl_list link;
-};
-
-void roots_switch_handle_toggle(struct roots_switch *switch_device,
- struct wlr_event_switch_toggle *event);
-
-#endif
diff --git a/include/rootston/text_input.h b/include/rootston/text_input.h
deleted file mode 100644
index 82e45e3e..00000000
--- a/include/rootston/text_input.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef ROOTSTON_TEXT_INPUT_H
-#define ROOTSTON_TEXT_INPUT_H
-
-#include <wlr/types/wlr_text_input_v3.h>
-#include <wlr/types/wlr_input_method_v2.h>
-#include <wlr/types/wlr_surface.h>
-#include "rootston/seat.h"
-
-/**
- * The relay structure manages the relationship between text-input and
- * input_method interfaces on a given seat. Multiple text-input interfaces may
- * be bound to a relay, but at most one will be focused (reveiving events) at
- * a time. At most one input-method interface may be bound to the seat. The
- * relay manages life cycle of both sides. When both sides are present and
- * focused, the relay passes messages between them.
- *
- * Text input focus is a subset of keyboard focus - if the text-input is
- * in the focused state, wl_keyboard sent an enter as well. However, having
- * wl_keyboard focused doesn't mean that text-input will be focused.
- */
-struct roots_input_method_relay {
- struct roots_seat *seat;
-
- struct wl_list text_inputs; // roots_text_input::link
- struct wlr_input_method_v2 *input_method; // doesn't have to be present
-
- struct wl_listener text_input_new;
- struct wl_listener text_input_enable;
- struct wl_listener text_input_commit;
- struct wl_listener text_input_disable;
- struct wl_listener text_input_destroy;
-
- struct wl_listener input_method_new;
- struct wl_listener input_method_commit;
- struct wl_listener input_method_destroy;
-};
-
-struct roots_text_input {
- struct roots_input_method_relay *relay;
-
- struct wlr_text_input_v3 *input;
- // The surface getting seat's focus. Stored for when text-input cannot
- // be sent an enter event immediately after getting focus, e.g. when
- // there's no input method available. Cleared once text-input is entered.
- struct wlr_surface *pending_focused_surface;
-
- struct wl_list link;
-
- struct wl_listener pending_focused_surface_destroy;
-};
-
-void roots_input_method_relay_init(struct roots_seat *seat,
- struct roots_input_method_relay *relay);
-
-// Updates currently focused surface. Surface must belong to the same seat.
-void roots_input_method_relay_set_focus(struct roots_input_method_relay *relay,
- struct wlr_surface *surface);
-
-struct roots_text_input *roots_text_input_create(
- struct roots_input_method_relay *relay,
- struct wlr_text_input_v3 *text_input);
-
-#endif
diff --git a/include/rootston/view.h b/include/rootston/view.h
deleted file mode 100644
index 1c5dcaff..00000000
--- a/include/rootston/view.h
+++ /dev/null
@@ -1,257 +0,0 @@
-#ifndef ROOTSTON_VIEW_H
-#define ROOTSTON_VIEW_H
-#include <stdbool.h>
-#include <wlr/config.h>
-#include <wlr/types/wlr_box.h>
-#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
-#include <wlr/types/wlr_surface.h>
-#include <wlr/types/wlr_xdg_decoration_v1.h>
-#include <wlr/types/wlr_xdg_shell_v6.h>
-#include <wlr/types/wlr_xdg_shell.h>
-
-struct roots_view;
-
-struct roots_view_interface {
- void (*activate)(struct roots_view *view, bool active);
- void (*move)(struct roots_view *view, double x, double y);
- void (*resize)(struct roots_view *view, uint32_t width, uint32_t height);
- void (*move_resize)(struct roots_view *view, double x, double y,
- uint32_t width, uint32_t height);
- void (*maximize)(struct roots_view *view, bool maximized);
- void (*set_fullscreen)(struct roots_view *view, bool fullscreen);
- void (*close)(struct roots_view *view);
- void (*for_each_surface)(struct roots_view *view,
- wlr_surface_iterator_func_t iterator, void *user_data);
- void (*destroy)(struct roots_view *view);
-};
-
-enum roots_view_type {
- ROOTS_XDG_SHELL_V6_VIEW,
- ROOTS_XDG_SHELL_VIEW,
-#if WLR_HAS_XWAYLAND
- ROOTS_XWAYLAND_VIEW,
-#endif
-};
-
-struct roots_view {
- enum roots_view_type type;
- const struct roots_view_interface *impl;
- struct roots_desktop *desktop;
- struct wl_list link; // roots_desktop::views
-
- struct wlr_box box;
- float rotation;
- float alpha;
-
- bool decorated;
- int border_width;
- int titlebar_height;
-
- bool maximized;
- struct roots_output *fullscreen_output;
- struct {
- double x, y;
- uint32_t width, height;
- float rotation;
- } saved;
-
- struct {
- bool update_x, update_y;
- double x, y;
- uint32_t width, height;
- } pending_move_resize;
-
- struct wlr_surface *wlr_surface;
- struct wl_list children; // roots_view_child::link
-
- struct wlr_foreign_toplevel_handle_v1 *toplevel_handle;
- struct wl_listener toplevel_handle_request_maximize;
- struct wl_listener toplevel_handle_request_activate;
- struct wl_listener toplevel_handle_request_fullscreen;
- struct wl_listener toplevel_handle_request_close;
-
- struct wl_listener new_subsurface;
-
- struct {
- struct wl_signal unmap;
- struct wl_signal destroy;
- } events;
-};
-
-struct roots_xdg_surface_v6 {
- struct roots_view view;
-
- struct wlr_xdg_surface_v6 *xdg_surface_v6;
-
- struct wl_listener destroy;
- struct wl_listener new_popup;
- struct wl_listener map;
- struct wl_listener unmap;
- struct wl_listener request_move;
- struct wl_listener request_resize;
- struct wl_listener request_maximize;
- struct wl_listener request_fullscreen;
- struct wl_listener set_title;
- struct wl_listener set_app_id;
-
- struct wl_listener surface_commit;
-
- uint32_t pending_move_resize_configure_serial;
-};
-
-struct roots_xdg_toplevel_decoration;
-
-struct roots_xdg_surface {
- struct roots_view view;
-
- struct wlr_xdg_surface *xdg_surface;
-
- struct wl_listener destroy;
- struct wl_listener new_popup;
- struct wl_listener map;
- struct wl_listener unmap;
- struct wl_listener request_move;
- struct wl_listener request_resize;
- struct wl_listener request_maximize;
- struct wl_listener request_fullscreen;
- struct wl_listener set_title;
- struct wl_listener set_app_id;
-
- struct wl_listener surface_commit;
-
- uint32_t pending_move_resize_configure_serial;
-
- struct roots_xdg_toplevel_decoration *xdg_toplevel_decoration;
-};
-
-#if WLR_HAS_XWAYLAND
-struct roots_xwayland_surface {
- struct roots_view view;
-
- struct wlr_xwayland_surface *xwayland_surface;
-
- struct wl_listener destroy;
- struct wl_listener request_configure;
- struct wl_listener request_move;
- struct wl_listener request_resize;
- struct wl_listener request_maximize;
- struct wl_listener request_fullscreen;
- struct wl_listener map;
- struct wl_listener unmap;
- struct wl_listener set_title;
- struct wl_listener set_class;
-
- struct wl_listener surface_commit;
-};
-#endif
-
-struct roots_view_child;
-
-struct roots_view_child_interface {
- void (*destroy)(struct roots_view_child *child);
-};
-
-struct roots_view_child {
- struct roots_view *view;
- const struct roots_view_child_interface *impl;
- struct wlr_surface *wlr_surface;
- struct wl_list link;
-
- struct wl_listener commit;
- struct wl_listener new_subsurface;
-};
-
-struct roots_subsurface {
- struct roots_view_child view_child;
- struct wlr_subsurface *wlr_subsurface;
- struct wl_listener destroy;
- struct wl_listener map;
- struct wl_listener unmap;
-};
-
-struct roots_xdg_popup_v6 {
- struct roots_view_child view_child;
- struct wlr_xdg_popup_v6 *wlr_popup;
- struct wl_listener destroy;
- struct wl_listener map;
- struct wl_listener unmap;
- struct wl_listener new_popup;
-};
-
-struct roots_xdg_popup {
- struct roots_view_child view_child;
- struct wlr_xdg_popup *wlr_popup;
- struct wl_listener destroy;
- struct wl_listener map;
- struct wl_listener unmap;
- struct wl_listener new_popup;
-};
-
-struct roots_xdg_toplevel_decoration {
- struct wlr_xdg_toplevel_decoration_v1 *wlr_decoration;
- struct roots_xdg_surface *surface;
- struct wl_listener destroy;
- struct wl_listener request_mode;
- struct wl_listener surface_commit;
-};
-
-void view_init(struct roots_view *view, const struct roots_view_interface *impl,
- enum roots_view_type type, struct roots_desktop *desktop);
-void view_destroy(struct roots_view *view);
-void view_apply_damage(struct roots_view *view);
-void view_damage_whole(struct roots_view *view);
-void view_update_position(struct roots_view *view, int x, int y);
-void view_update_size(struct roots_view *view, int width, int height);
-void view_update_decorated(struct roots_view *view, bool decorated);
-void view_initial_focus(struct roots_view *view);
-void view_map(struct roots_view *view, struct wlr_surface *surface);
-void view_unmap(struct roots_view *view);
-void view_arrange_maximized(struct roots_view *view);
-void view_get_box(const struct roots_view *view, struct wlr_box *box);
-void view_activate(struct roots_view *view, bool active);
-void view_move(struct roots_view *view, double x, double y);
-void view_resize(struct roots_view *view, uint32_t width, uint32_t height);
-void view_move_resize(struct roots_view *view, double x, double y,
- uint32_t width, uint32_t height);
-void view_maximize(struct roots_view *view, bool maximized);
-void view_set_fullscreen(struct roots_view *view, bool fullscreen,
- struct wlr_output *output);
-void view_rotate(struct roots_view *view, float rotation);
-void view_cycle_alpha(struct roots_view *view);
-void view_close(struct roots_view *view);
-bool view_center(struct roots_view *view);
-void view_setup(struct roots_view *view);
-void view_teardown(struct roots_view *view);
-void view_set_title(struct roots_view *view, const char *title);
-void view_set_app_id(struct roots_view *view, const char *app_id);
-void view_create_foreign_toplevel_handle(struct roots_view *view);
-void view_get_deco_box(const struct roots_view *view, struct wlr_box *box);
-void view_for_each_surface(struct roots_view *view,
- wlr_surface_iterator_func_t iterator, void *user_data);
-
-struct roots_xdg_surface *roots_xdg_surface_from_view(struct roots_view *view);
-struct roots_xdg_surface_v6 *roots_xdg_surface_v6_from_view(
- struct roots_view *view);
-struct roots_xwayland_surface *roots_xwayland_surface_from_view(
- struct roots_view *view);
-
-enum roots_deco_part {
- ROOTS_DECO_PART_NONE = 0,
- ROOTS_DECO_PART_TOP_BORDER = (1 << 0),
- ROOTS_DECO_PART_BOTTOM_BORDER = (1 << 1),
- ROOTS_DECO_PART_LEFT_BORDER = (1 << 2),
- ROOTS_DECO_PART_RIGHT_BORDER = (1 << 3),
- ROOTS_DECO_PART_TITLEBAR = (1 << 4),
-};
-
-enum roots_deco_part view_get_deco_part(struct roots_view *view, double sx, double sy);
-
-void view_child_init(struct roots_view_child *child,
- const struct roots_view_child_interface *impl, struct roots_view *view,
- struct wlr_surface *wlr_surface);
-void view_child_destroy(struct roots_view_child *child);
-
-struct roots_subsurface *subsurface_create(struct roots_view *view,
- struct wlr_subsurface *wlr_subsurface);
-
-#endif
diff --git a/include/rootston/virtual_keyboard.h b/include/rootston/virtual_keyboard.h
deleted file mode 100644
index 613e5595..00000000
--- a/include/rootston/virtual_keyboard.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef ROOTSTON_VIRTUAL_KEYBOARD_H
-#define ROOTSTON_VIRTUAL_KEYBOARD_H
-
-#include <wayland-server-core.h>
-
-void handle_virtual_keyboard(struct wl_listener *listener, void *data);
-#endif
diff --git a/include/rootston/xcursor.h b/include/rootston/xcursor.h
deleted file mode 100644
index f78489a4..00000000
--- a/include/rootston/xcursor.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef ROOTSTON_XCURSOR_H
-#define ROOTSTON_XCURSOR_H
-
-#include <stdint.h>
-
-#define ROOTS_XCURSOR_SIZE 24
-
-#define ROOTS_XCURSOR_DEFAULT "left_ptr"
-#define ROOTS_XCURSOR_MOVE "grabbing"
-#define ROOTS_XCURSOR_ROTATE "grabbing"
-
-#endif
diff --git a/meson.build b/meson.build
index cd280bf5..dfada444 100644
--- a/meson.build
+++ b/meson.build
@@ -202,7 +202,6 @@ summary = [
message('\n'.join(summary))
subdir('examples')
-subdir('rootston')
pkgconfig = import('pkgconfig')
pkgconfig.generate(
diff --git a/meson_options.txt b/meson_options.txt
index 5d322b0c..51b7f6c8 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -6,5 +6,4 @@ option('xcb-errors', type: 'feature', value: 'auto', description: 'Use xcb-error
option('xcb-icccm', type: 'feature', value: 'auto', description: 'Use xcb-icccm util library')
option('xwayland', type: 'feature', value: 'auto', yield: true, description: 'Enable support for X11 applications')
option('x11-backend', type: 'feature', value: 'auto', description: 'Enable X11 backend')
-option('rootston', type: 'boolean', value: true, description: 'Build the rootston example compositor')
option('examples', type: 'boolean', value: true, description: 'Build example applications')
diff --git a/rootston/README.md b/rootston/README.md
deleted file mode 100644
index be2e6698..00000000
--- a/rootston/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# rootston
-
-Rootston is the "big" wlroots test compositor. It implements basically every
-feature of wlroots and may be useful as a reference for new compositors.
-However, it's mostly used as a testbed for wlroots development and does not have
-particularly clean code and is not particularly well designed: proceed with a
-grain of salt. It is not designed for end-users.
-
-## Running rootston
-
-If you followed the build instructions in `../README.md`, the rootston
-executable can be found at `build/rootston/rootston`. To use it, refer to the
-example config at [rootston/rootston.ini.example][rootston.ini] and place a
-config file of your own at `rootston.ini` in the working directory (or in an
-arbitrary location via `rootston -C`). Other options are available, refer to
-`rootston -h`.
-
-[rootston.ini]: https://github.com/swaywm/wlroots/blob/master/rootston/rootston.ini.example
diff --git a/rootston/bindings.c b/rootston/bindings.c
deleted file mode 100644
index 9dc2223e..00000000
--- a/rootston/bindings.c
+++ /dev/null
@@ -1,110 +0,0 @@
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <wlr/util/log.h>
-#include "rootston/bindings.h"
-#include "rootston/view.h"
-
-static bool outputs_enabled = true;
-
-static const char exec_prefix[] = "exec ";
-
-static void double_fork_shell_cmd(const char *shell_cmd) {
- pid_t pid = fork();
- if (pid < 0) {
- wlr_log(WLR_ERROR, "cannot execute binding command: fork() failed");
- return;
- }
-
- if (pid == 0) {
- pid = fork();
- if (pid == 0) {
- execl("/bin/sh", "/bin/sh", "-c", shell_cmd, NULL);
- _exit(EXIT_FAILURE);
- } else {
- _exit(pid == -1);
- }
- }
-
- int status;
- while (waitpid(pid, &status, 0) < 0) {
- if (errno == EINTR) {
- continue;
- }
- wlr_log_errno(WLR_ERROR, "waitpid() on first child failed");
- return;
- }
-
- if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
- return;
- }
-
- wlr_log(WLR_ERROR, "first child failed to fork command");
-}
-
-void execute_binding_command(struct roots_seat *seat,
- struct roots_input *input, const char *command) {
- if (strcmp(command, "exit") == 0) {
- wl_display_terminate(input->server->wl_display);
- } else if (strcmp(command, "close") == 0) {
- struct roots_view *focus = roots_seat_get_focus(seat);
- if (focus != NULL) {
- view_close(focus);
- }
- } else if (strcmp(command, "fullscreen") == 0) {
- struct roots_view *focus = roots_seat_get_focus(seat);
- if (focus != NULL) {
- bool is_fullscreen = focus->fullscreen_output != NULL;
- view_set_fullscreen(focus, !is_fullscreen, NULL);
- }
- } else if (strcmp(command, "next_window") == 0) {
- roots_seat_cycle_focus(seat);
- } else if (strcmp(command, "alpha") == 0) {
- struct roots_view *focus = roots_seat_get_focus(seat);
- if (focus != NULL) {
- view_cycle_alpha(focus);
- }
- } else if (strncmp(exec_prefix, command, strlen(exec_prefix)) == 0) {
- const char *shell_cmd = command + strlen(exec_prefix);
- double_fork_shell_cmd(shell_cmd);
- } else if (strcmp(command, "maximize") == 0) {
- struct roots_view *focus = roots_seat_get_focus(seat);
- if (focus != NULL) {
- view_maximize(focus, !focus->maximized);
- }
- } else if (strcmp(command, "nop") == 0) {
- wlr_log(WLR_DEBUG, "nop command");
- } else if (strcmp(command, "toggle_outputs") == 0) {
- outputs_enabled = !outputs_enabled;
- struct roots_output *output;
- wl_list_for_each(output, &input->server->desktop->outputs, link) {
- wlr_output_enable(output->wlr_output, outputs_enabled);
- }
- } else if (strcmp(command, "toggle_decoration_mode") == 0) {
- struct roots_view *focus = roots_seat_get_focus(seat);
- if (focus != NULL && focus->type == ROOTS_XDG_SHELL_VIEW) {
- struct roots_xdg_surface *xdg_surface =
- roots_xdg_surface_from_view(focus);
- struct roots_xdg_toplevel_decoration *decoration =
- xdg_surface->xdg_toplevel_decoration;
- if (decoration != NULL) {
- enum wlr_xdg_toplevel_decoration_v1_mode mode =
- decoration->wlr_decoration->current_mode;
- mode = mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE
- ? WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE
- : WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
- wlr_xdg_toplevel_decoration_v1_set_mode(
- decoration->wlr_decoration, mode);
- }
- }
- } else if (strcmp(command, "break_pointer_constraint") == 0) {
- struct wl_list *list = &input->seats;
- struct roots_seat *seat;
- wl_list_for_each(seat, list, link) {
- roots_cursor_constrain(seat->cursor, NULL, NAN, NAN);
- }
- } else {
- wlr_log(WLR_ERROR, "unknown binding command: %s", command);
- }
-}
diff --git a/rootston/config.c b/rootston/config.c
deleted file mode 100644
index 314af264..00000000
--- a/rootston/config.c
+++ /dev/null
@@ -1,674 +0,0 @@
-#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 200809L
-#endif
-#include <assert.h>
-#include <getopt.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <sys/param.h>
-#include <unistd.h>
-#include <wlr/config.h>
-#include <wlr/types/wlr_box.h>
-#include <wlr/util/log.h>
-#include "rootston/config.h"
-#include "rootston/ini.h"
-#include "rootston/input.h"
-#include "rootston/keyboard.h"
-
-static void usage(const char *name, int ret) {
- fprintf(stderr,
- "usage: %s [-C <FILE>] [-E <COMMAND>]\n"
- "\n"
- " -C <FILE> Path to the configuration file\n"
- " (default: rootston.ini).\n"
- " See `rootston.ini.example` for config\n"
- " file documentation.\n"
- " -E <COMMAND> Command that will be ran at startup.\n"
- " -D Enable damage tracking debugging.\n"
- " -l <LEVEL> Set log verbosity, where,\n"
- " 0:SILENT, 1:ERROR, 2:INFO, 3+:DEBUG\n"
- " (default: DEBUG)\n",
- name);
-
- exit(ret);
-}
-
-static struct wlr_box *parse_geometry(const char *str) {
- // format: {width}x{height}+{x}+{y}
- if (strlen(str) > 255) {
- wlr_log(WLR_ERROR, "cannot parse geometry string, too long");
- return NULL;
- }
-
- char *buf = strdup(str);
- struct wlr_box *box = calloc(1, sizeof(struct wlr_box));
-
- bool has_width = false;
- bool has_height = false;
- bool has_x = false;
- bool has_y = false;
-
- char *pch = strtok(buf, "x+");
- while (pch != NULL) {
- errno = 0;
- char *endptr;
- long val = strtol(pch, &endptr, 0);
-
- if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) ||
- (errno != 0 && val == 0)) {
- goto invalid_input;
- }
-
- if (endptr == pch) {
- goto invalid_input;
- }
-
- if (!has_width) {
- box->width = val;
- has_width = true;
- } else if (!has_height) {
- box->height = val;
- has_height = true;
- } else if (!has_x) {
- box->x = val;
- has_x = true;
- } else if (!has_y) {
- box->y = val;
- has_y = true;
- } else {
- break;
- }
- pch = strtok(NULL, "x+");
- }
-
- if (!has_width || !has_height) {
- goto invalid_input;
- }
-
- free(buf);
- return box;
-
-invalid_input:
- wlr_log(WLR_ERROR, "could not parse geometry string: %s", str);
- free(buf);
- free(box);
- return NULL;
-}
-
-static uint32_t parse_modifier(const char *symname) {
- if (strcmp(symname, "Shift") == 0) {
- return WLR_MODIFIER_SHIFT;
- } else if (strcmp(symname, "Caps") == 0) {
- return WLR_MODIFIER_CAPS;
- } else if (strcmp(symname, "Ctrl") == 0) {
- return WLR_MODIFIER_CTRL;
- } else if (strcmp(symname, "Alt") == 0) {
- return WLR_MODIFIER_ALT;
- } else if (strcmp(symname, "Mod2") == 0) {
- return WLR_MODIFIER_MOD2;
- } else if (strcmp(symname, "Mod3") == 0) {
- return WLR_MODIFIER_MOD3;
- } else if (strcmp(symname, "Logo") == 0) {
- return WLR_MODIFIER_LOGO;
- } else if (strcmp(symname, "Mod5") == 0) {
- return WLR_MODIFIER_MOD5;
- } else {
- return 0;
- }
-}
-
-static bool parse_modeline(const char *s, drmModeModeInfo *mode) {
- char hsync[16];
- char vsync[16];
- float fclock;
-
- mode->type = DRM_MODE_TYPE_USERDEF;
-
- if (sscanf(s, "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s",
- &fclock,
- &mode->hdisplay,
- &mode->hsync_start,
- &mode->hsync_end,
- &mode->htotal,
- &mode->vdisplay,
- &mode->vsync_start,
- &mode->vsync_end,
- &mode->vtotal, hsync, vsync) != 11) {
- return false;
- }
-
- mode->clock = fclock * 1000;
- mode->vrefresh = mode->clock * 1000.0 * 1000.0
- / mode->htotal / mode->vtotal;
- if (strcasecmp(hsync, "+hsync") == 0) {
- mode->flags |= DRM_MODE_FLAG_PHSYNC;
- } else if (strcasecmp(hsync, "-hsync") == 0) {
- mode->flags |= DRM_MODE_FLAG_NHSYNC;
- } else {
- return false;
- }
-
- if (strcasecmp(vsync, "+vsync") == 0) {
- mode->flags |= DRM_MODE_FLAG_PVSYNC;
- } else if (strcasecmp(vsync, "-vsync") == 0) {
- mode->flags |= DRM_MODE_FLAG_NVSYNC;
- } else {
- return false;
- }
-
- snprintf(mode->name, sizeof(mode->name), "%dx%d@%d",
- mode->hdisplay, mode->vdisplay, mode->vrefresh / 1000);
-
- return true;
-}
-
-static void add_binding_config(struct wl_list *bindings, const char* combination,
- const char* command) {
- struct roots_binding_config *bc =
- calloc(1, sizeof(struct roots_binding_config));
-
- xkb_keysym_t keysyms[ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP];
- char *symnames = strdup(combination);
- char *symname = strtok(symnames, "+");
- while (symname) {
- uint32_t modifier = parse_modifier(symname);
- if (modifier != 0) {
- bc->modifiers |= modifier;
- } else {
- xkb_keysym_t sym = xkb_keysym_from_name(symname,
- XKB_KEYSYM_NO_FLAGS);
- if (sym == XKB_KEY_NoSymbol) {
- wlr_log(WLR_ERROR, "got unknown key binding symbol: %s",
- symname);
- free(bc);
- bc = NULL;
- break;
- }
- keysyms[bc->keysyms_len] = sym;
- bc->keysyms_len++;
- }
- symname = strtok(NULL, "+");
- }
- free(symnames);
-
- if (bc) {
- wl_list_insert(bindings, &bc->link);
- bc->command = strdup(command);
- bc->keysyms = malloc(bc->keysyms_len * sizeof(xkb_keysym_t));
- memcpy(bc->keysyms, keysyms, bc->keysyms_len * sizeof(xkb_keysym_t));
- }
-}
-
-static void add_switch_config(struct wl_list *switches, const char *switch_name,
- const char *action, const char *command) {
- struct roots_switch_config *sc =
- calloc(1, sizeof(struct roots_switch_config));
-
- if (strcmp(switch_name, "tablet") == 0) {
- sc->switch_type = WLR_SWITCH_TYPE_TABLET_MODE;
- } else if (strcmp(switch_name, "lid") == 0) {
- sc->switch_type = WLR_SWITCH_TYPE_LID;
- } else {
- sc->switch_type = -1;
- sc->name = strdup(switch_name);
- }
-
- if (strcmp(action, "on") == 0) {
- sc->switch_state = WLR_SWITCH_STATE_ON;
- } else if (strcmp(action, "off") == 0) {
- sc->switch_state = WLR_SWITCH_STATE_OFF;
- } else if (strcmp(action, "toggle") == 0) {
- sc->switch_state = WLR_SWITCH_STATE_TOGGLE;
- } else {
- wlr_log(WLR_ERROR, "Invalid switch action %s for switch %s:%s",
- action, switch_name, action);
- free(sc);
- return;
- }
-
- sc->command = strdup(command);
- wl_list_insert(switches, &sc->link);
-}
-
-static void config_handle_cursor(struct roots_config *config,
- const char *seat_name, const char *name, const char *value) {
- struct roots_cursor_config *cc;
- bool found = false;
- wl_list_for_each(cc, &config->cursors, link) {
- if (strcmp(cc->seat, seat_name) == 0) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- cc = calloc(1, sizeof(struct roots_cursor_config));
- cc->seat = strdup(seat_name);
- wl_list_insert(&config->cursors, &cc->link);
- }
-
- if (strcmp(name, "map-to-output") == 0) {
- free(cc->mapped_output);
- cc->mapped_output = strdup(value);
- } else if (strcmp(name, "geometry") == 0) {
- free(cc->mapped_box);
- cc->mapped_box = parse_geometry(value);
- } else if (strcmp(name, "theme") == 0) {
- free(cc->theme);
- cc->theme = strdup(value);
- } else if (strcmp(name, "default-image") == 0) {
- free(cc->default_image);
- cc->default_image = strdup(value);
- } else {
- wlr_log(WLR_ERROR, "got unknown cursor config: %s", name);
- }
-}
-
-static void config_handle_keyboard(struct roots_config *config,
- const char *device_name, const char *name, const char *value) {
- struct roots_keyboard_config *kc;
- bool found = false;
- wl_list_for_each(kc, &config->keyboards, link) {
- if (strcmp(kc->name, device_name) == 0) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- kc = calloc(1, sizeof(struct roots_keyboard_config));
- kc->name = strdup(device_name);
- wl_list_insert(&config->keyboards, &kc->link);
- }
-
- if (strcmp(name, "meta-key") == 0) {
- kc->meta_key = parse_modifier(value);
- if (kc->meta_key == 0) {
- wlr_log(WLR_ERROR, "got unknown meta key: %s", name);
- }
- } else if (strcmp(name, "rules") == 0) {
- kc->rules = strdup(value);
- } else if (strcmp(name, "model") == 0) {
- kc->model = strdup(value);
- } else if (strcmp(name, "layout") == 0) {
- kc->layout = strdup(value);
- } else if (strcmp(name, "variant") == 0) {
- kc->variant = strdup(value);
- } else if (strcmp(name, "options") == 0) {
- kc->options = strdup(value);
- } else if (strcmp(name, "repeat-rate") == 0) {
- kc->repeat_rate = strtol(value, NULL, 10);
- } else if (strcmp(name, "repeat-delay") == 0) {
- kc->repeat_delay = strtol(value, NULL, 10);
- } else {
- wlr_log(WLR_ERROR, "got unknown keyboard config: %s", name);
- }
-}
-
-static const char *output_prefix = "output:";
-static const char *device_prefix = "device:";
-static const char *keyboard_prefix = "keyboard:";
-static const char *cursor_prefix = "cursor:";
-static const char *switch_prefix = "switch:";
-
-static int config_ini_handler(void *user, const char *section, const char *name,
- const char *value) {
- struct roots_config *config = user;
- if (strcmp(section, "core") == 0) {
- if (strcmp(name, "xwayland") == 0) {
- if (strcasecmp(value, "true") == 0) {
- config->xwayland = true;
- } else if (strcasecmp(value, "immediate") == 0) {
- config->xwayland = true;
- config->xwayland_lazy = false;
- } else if (strcasecmp(value, "false") == 0) {
- config->xwayland = false;
- } else {
- wlr_log(WLR_ERROR, "got unknown xwayland value: %s", value);
- }
- } else {
- wlr_log(WLR_ERROR, "got unknown core config: %s", name);
- }
- } else if (strncmp(output_prefix, section, strlen(output_prefix)) == 0) {
- const char *output_name = section + strlen(output_prefix);
- struct roots_output_config *oc;
- bool found = false;
-
- wl_list_for_each(oc, &config->outputs, link) {
- if (strcmp(oc->name, output_name) == 0) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- oc = calloc(1, sizeof(struct roots_output_config));
- oc->name = strdup(output_name);
- oc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
- oc->scale = 1;
- oc->enable = true;
- wl_list_init(&oc->modes);
- wl_list_insert(&config->outputs, &oc->link);
- }
-
- if (strcmp(name, "enable") == 0) {
- if (strcasecmp(value, "true") == 0) {
- oc->enable = true;
- } else if (strcasecmp(value, "false") == 0) {
- oc->enable = false;
- } else {
- wlr_log(WLR_ERROR, "got invalid output enable value: %s", value);
- }
- } else if (strcmp(name, "x") == 0) {
- oc->x = strtol(value, NULL, 10);
- } else if (strcmp(name, "y") == 0) {
- oc->y = strtol(value, NULL, 10);
- } else if (strcmp(name, "scale") == 0) {
- oc->scale = strtof(value, NULL);
- assert(oc->scale > 0);
- } else if (strcmp(name, "rotate") == 0) {
- if (strcmp(value, "normal") == 0) {
- oc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
- } else if (strcmp(value, "90") == 0) {
- oc->transform = WL_OUTPUT_TRANSFORM_90;
- } else if (strcmp(value, "180") == 0) {
- oc->transform = WL_OUTPUT_TRANSFORM_180;
- } else if (strcmp(value, "270") == 0) {
- oc->transform = WL_OUTPUT_TRANSFORM_270;
- } else if (strcmp(value, "flipped") == 0) {
- oc->transform = WL_OUTPUT_TRANSFORM_FLIPPED;
- } else if (strcmp(value, "flipped-90") == 0) {
- oc->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90;
- } else if (strcmp(value, "flipped-180") == 0) {
- oc->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180;
- } else if (strcmp(value, "flipped-270") == 0) {
- oc->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270;
- } else {
- wlr_log(WLR_ERROR, "got unknown transform value: %s", value);
- }
- } else if (strcmp(name, "mode") == 0) {
- char *end;
- oc->mode.width = strtol(value, &end, 10);
- assert(*end == 'x');
- ++end;
- oc->mode.height = strtol(end, &end, 10);
- if (*end) {
- assert(*end == '@');
- ++end;
- oc->mode.refresh_rate = strtof(end, &end);
- assert(strcmp("Hz", end) == 0);
- }
- wlr_log(WLR_DEBUG, "Configured output %s with mode %dx%d@%f",
- oc->name, oc->mode.width, oc->mode.height,
- oc->mode.refresh_rate);
- } else if (strcmp(name, "modeline") == 0) {
- struct roots_output_mode_config *mode = calloc(1, sizeof(*mode));
-
- if (parse_modeline(value, &mode->info)) {
- wl_list_insert(&oc->modes, &mode->link);
- } else {
- free(mode);
- wlr_log(WLR_ERROR, "Invalid modeline: %s", value);
- }
- }
- } else if (strncmp(cursor_prefix, section, strlen(cursor_prefix)) == 0) {
- const char *seat_name = section + strlen(cursor_prefix);
- config_handle_cursor(config, seat_name, name, value);
- } else if (strcmp(section, "cursor") == 0) {
- config_handle_cursor(config, ROOTS_CONFIG_DEFAULT_SEAT_NAME, name,
- value);
- } else if (strncmp(device_prefix, section, strlen(device_prefix)) == 0) {
- const char *device_name = section + strlen(device_prefix);
-
- struct roots_device_config *dc;
- bool found = false;
- wl_list_for_each(dc, &config->devices, link) {
- if (strcmp(dc->name, device_name) == 0) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- dc = calloc(1, sizeof(struct roots_device_config));
- dc->name = strdup(device_name);
- dc->seat = strdup(ROOTS_CONFIG_DEFAULT_SEAT_NAME);
- wl_list_insert(&config->devices, &dc->link);
- }
-
- if (strcmp(name, "map-to-output") == 0) {
- free(dc->mapped_output);
- dc->mapped_output = strdup(value);
- } else if (strcmp(name, "geometry") == 0) {
- free(dc->mapped_box);
- dc->mapped_box = parse_geometry(value);
- } else if (strcmp(name, "seat") == 0) {
- free(dc->seat);
- dc->seat = strdup(value);
- } else if (strcmp(name, "tap_enabled") == 0) {
- if (strcasecmp(value, "true") == 0) {
- dc->tap_enabled = true;
- } else if (strcasecmp(value, "false") == 0) {
- dc->tap_enabled = false;
- } else {
- wlr_log(WLR_ERROR,
- "got unknown tap_enabled value: %s",
- value);
- }
- } else {
- wlr_log(WLR_ERROR, "got unknown device config: %s", name);
- }
- } else if (strcmp(section, "keyboard") == 0) {
- config_handle_keyboard(config, "", name, value);
- } else if (strncmp(keyboard_prefix,
- section, strlen(keyboard_prefix)) == 0) {
- const char *device_name = section + strlen(keyboard_prefix);
- config_handle_keyboard(config, device_name, name, value);
- } else if (strcmp(section, "bindings") == 0) {
- add_binding_config(&config->bindings, name, value);
- } else if (strncmp(switch_prefix, section, strlen(switch_prefix)) == 0) {
- const char *switch_name = section + strlen(switch_prefix);
- add_switch_config(&config->switches, switch_name, name, value);
- } else {
- wlr_log(WLR_ERROR, "got unknown config section: %s", section);
- }
-
- return 1;
-}
-
-struct roots_config *roots_config_create_from_args(int argc, char *argv[]) {
- struct roots_config *config = calloc(1, sizeof(struct roots_config));
- if (config == NULL) {
- return NULL;
- }
-
- config->xwayland = true;
- config->xwayland_lazy = true;
- wl_list_init(&config->outputs);
- wl_list_init(&config->devices);
- wl_list_init(&config->keyboards);
- wl_list_init(&config->cursors);
- wl_list_init(&config->bindings);
- wl_list_init(&config->switches);
-
- int c;
- unsigned int log_verbosity = WLR_DEBUG;
- while ((c = getopt(argc, argv, "C:E:hDl:")) != -1) {
- switch (c) {
- case 'C':
- config->config_path = strdup(optarg);
- break;
- case 'E':
- config->startup_cmd = strdup(optarg);
- break;
- case 'D':
- config->debug_damage_tracking = true;
- break;
- case 'l':
- log_verbosity = strtoul(optarg, NULL, 10);
- if (log_verbosity >= WLR_LOG_IMPORTANCE_LAST) {
- log_verbosity = WLR_LOG_IMPORTANCE_LAST - 1;
- }
- break;
- case 'h':
- case '?':
- usage(argv[0], c != 'h');
- }
- }
- wlr_log_init(log_verbosity, NULL);
-
- if (!config->config_path) {
- // get the config path from the current directory
- char cwd[MAXPATHLEN];
- if (getcwd(cwd, sizeof(cwd)) != NULL) {
- char buf[MAXPATHLEN];
- if (snprintf(buf, MAXPATHLEN, "%s/%s", cwd, "rootston.ini") >= MAXPATHLEN) {
- wlr_log(WLR_ERROR, "config path too long");
- exit(1);
- }
- config->config_path = strdup(buf);
- } else {
- wlr_log(WLR_ERROR, "could not get cwd");
- exit(1);
- }
- }
-
- int result = ini_parse(config->config_path, config_ini_handler, config);
-
- if (result == -1) {
- wlr_log(WLR_DEBUG, "No config file found. Using sensible defaults.");
- add_binding_config(&config->bindings, "Logo+Shift+E", "exit");
- add_binding_config(&config->bindings, "Ctrl+q", "close");
- add_binding_config(&config->bindings, "Alt+Tab", "next_window");
- add_binding_config(&config->bindings, "Logo+Escape", "break_pointer_constraint");
- struct roots_keyboard_config *kc =
- calloc(1, sizeof(struct roots_keyboard_config));
- kc->meta_key = WLR_MODIFIER_LOGO;
- kc->name = strdup("");
- wl_list_insert(&config->keyboards, &kc->link);
- } else if (result == -2) {
- wlr_log(WLR_ERROR, "Could not allocate memory to parse config file");
- exit(1);
- } else if (result != 0) {
- wlr_log(WLR_ERROR, "Could not parse config file");
- exit(1);
- }
-
- return config;
-}
-
-void roots_config_destroy(struct roots_config *config) {
- struct roots_output_config *oc, *otmp = NULL;
- wl_list_for_each_safe(oc, otmp, &config->outputs, link) {
- struct roots_output_mode_config *omc, *omctmp = NULL;
- wl_list_for_each_safe(omc, omctmp, &oc->modes, link) {
- free(omc);
- }
- free(oc->name);
- free(oc);
- }
-
- struct roots_device_config *dc, *dtmp = NULL;
- wl_list_for_each_safe(dc, dtmp, &config->devices, link) {
- free(dc->name);
- free(dc->seat);
- free(dc->mapped_output);
- free(dc->mapped_box);
- free(dc);
- }
-
- struct roots_keyboard_config *kc, *ktmp = NULL;
- wl_list_for_each_safe(kc, ktmp, &config->keyboards, link) {
- free(kc->name);
- free(kc->rules);
- free(kc->model);
- free(kc->layout);
- free(kc->variant);
- free(kc->options);
- free(kc);
- }
-
- struct roots_cursor_config *cc, *ctmp = NULL;
- wl_list_for_each_safe(cc, ctmp, &config->cursors, link) {
- free(cc->seat);
- free(cc->mapped_output);
- free(cc->mapped_box);
- free(cc->theme);
- free(cc->default_image);
- free(cc);
- }
-
- struct roots_binding_config *bc, *btmp = NULL;
- wl_list_for_each_safe(bc, btmp, &config->bindings, link) {
- free(bc->keysyms);
- free(bc->command);
- free(bc);
- }
-
- free(config->config_path);
- free(config);
-}
-
-struct roots_output_config *roots_config_get_output(struct roots_config *config,
- struct wlr_output *output) {
- char name[88];
- snprintf(name, sizeof(name), "%s %s %s", output->make, output->model,
- output->serial);
-
- struct roots_output_config *oc;
- wl_list_for_each(oc, &config->outputs, link) {
- if (strcmp(oc->name, output->name) == 0 ||
- strcmp(oc->name, name) == 0) {
- return oc;
- }
- }
-
- return NULL;
-}
-
-struct roots_device_config *roots_config_get_device(struct roots_config *config,
- struct wlr_input_device *device) {
- struct roots_device_config *d_config;
- wl_list_for_each(d_config, &config->devices, link) {
- if (strcmp(d_config->name, device->name) == 0) {
- return d_config;
- }
- }
-
- return NULL;
-}
-
-struct roots_keyboard_config *roots_config_get_keyboard(
- struct roots_config *config, struct wlr_input_device *device) {
- const char *device_name = "";
- if (device != NULL) {
- device_name = device->name;
- }
-
- struct roots_keyboard_config *kc;
- wl_list_for_each(kc, &config->keyboards, link) {
- if (strcmp(kc->name, device_name) == 0) {
- return kc;
- }
- }
-
- return NULL;
-}
-
-struct roots_cursor_config *roots_config_get_cursor(struct roots_config *config,
- const char *seat_name) {
- if (seat_name == NULL) {
- seat_name = ROOTS_CONFIG_DEFAULT_SEAT_NAME;
- }
-
- struct roots_cursor_config *cc;
- wl_list_for_each(cc, &config->cursors, link) {
- if (strcmp(cc->seat, seat_name) == 0) {
- return cc;
- }
- }
-
- return NULL;
-}
diff --git a/rootston/cursor.c b/rootston/cursor.c
deleted file mode 100644
index 6e09c06e..00000000
--- a/rootston/cursor.c
+++ /dev/null
@@ -1,632 +0,0 @@
-#define _XOPEN_SOURCE 700
-#include <assert.h>
-#include <math.h>
-#include <stdlib.h>
-#include <wlr/types/wlr_region.h>
-#include <wlr/types/wlr_xcursor_manager.h>
-#include <wlr/util/edges.h>
-#include <wlr/util/log.h>
-#include <wlr/util/region.h>
-#include <linux/input-event-codes.h>
-#include "rootston/cursor.h"
-#include "rootston/desktop.h"
-#include "rootston/view.h"
-#include "rootston/xcursor.h"
-
-struct roots_cursor *roots_cursor_create(struct roots_seat *seat) {
- struct roots_cursor *cursor = calloc(1, sizeof(struct roots_cursor));
- if (!cursor) {
- return NULL;
- }
- cursor->cursor = wlr_cursor_create();
- if (!cursor->cursor) {
- free(cursor);
- return NULL;
- }
- cursor->default_xcursor = ROOTS_XCURSOR_DEFAULT;
- return cursor;
-}
-
-void roots_cursor_destroy(struct roots_cursor *cursor) {
- // TODO
-}
-
-static void seat_view_deco_motion(struct roots_seat_view *view,
- double deco_sx, double deco_sy) {
- struct roots_cursor *cursor = view->seat->cursor;
-
- double sx = deco_sx;
- double sy = deco_sy;
- if (view->has_button_grab) {
- sx = view->grab_sx;
- sy = view->grab_sy;
- }
-
- enum roots_deco_part parts = view_get_deco_part(view->view, sx, sy);
-
- bool is_titlebar = (parts & ROOTS_DECO_PART_TITLEBAR);
- uint32_t edges = 0;
- if (parts & ROOTS_DECO_PART_LEFT_BORDER) {
- edges |= WLR_EDGE_LEFT;
- } else if (parts & ROOTS_DECO_PART_RIGHT_BORDER) {
- edges |= WLR_EDGE_RIGHT;
- } else if (parts & ROOTS_DECO_PART_BOTTOM_BORDER) {
- edges |= WLR_EDGE_BOTTOM;
- } else if (parts & ROOTS_DECO_PART_TOP_BORDER) {
- edges |= WLR_EDGE_TOP;
- }
-
- if (view->has_button_grab) {
- if (is_titlebar) {
- roots_seat_begin_move(view->seat, view->view);
- } else if (edges) {
- roots_seat_begin_resize(view->seat, view->view, edges);
- }
- view->has_button_grab = false;
- } else {
- if (is_titlebar) {
- wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager,
- cursor->default_xcursor, cursor->cursor);
- } else if (edges) {
- const char *resize_name = wlr_xcursor_get_resize_name(edges);
- wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager,
- resize_name, cursor->cursor);
- }
- }
-}
-
-static void seat_view_deco_leave(struct roots_seat_view *view) {
- struct roots_cursor *cursor = view->seat->cursor;
- wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager,
- cursor->default_xcursor, cursor->cursor);
- view->has_button_grab = false;
-}
-
-static void seat_view_deco_button(struct roots_seat_view *view, double sx,
- double sy, uint32_t button, uint32_t state) {
- if (button == BTN_LEFT && state == WLR_BUTTON_PRESSED) {
- view->has_button_grab = true;
- view->grab_sx = sx;
- view->grab_sy = sy;
- } else {
- view->has_button_grab = false;
- }
-
- enum roots_deco_part parts = view_get_deco_part(view->view, sx, sy);
- if (state == WLR_BUTTON_RELEASED && (parts & ROOTS_DECO_PART_TITLEBAR)) {
- struct roots_cursor *cursor = view->seat->cursor;
- wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager,
- cursor->default_xcursor, cursor->cursor);
- }
-}
-
-static void roots_passthrough_cursor(struct roots_cursor *cursor,
- uint32_t time) {
- double sx, sy;
- struct roots_view *view = NULL;
- struct roots_seat *seat = cursor->seat;
- struct roots_desktop *desktop = seat->input->server->desktop;
- struct wlr_surface *surface = desktop_surface_at(desktop,
- cursor->cursor->x, cursor->cursor->y, &sx, &sy, &view);
-
- struct wl_client *client = NULL;
- if (surface) {
- client = wl_resource_get_client(surface->resource);
- }
-
- if (surface && !roots_seat_allow_input(seat, surface->resource)) {
- return;
- }
-
- if (cursor->cursor_client != client) {
- wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager,
- cursor->default_xcursor, cursor->cursor);
- cursor->cursor_client = client;
- }
-
- if (view) {
- struct roots_seat_view *seat_view =
- roots_seat_view_from_view(seat, view);
-
- if (cursor->pointer_view &&
- !cursor->wlr_surface && (surface || seat_view != cursor->pointer_view)) {
- seat_view_deco_leave(cursor->pointer_view);
- }
-
- cursor->pointer_view = seat_view;
-
- if (!surface) {
- seat_view_deco_motion(seat_view, sx, sy);
- }
- } else {
- cursor->pointer_view = NULL;
- }
-
- cursor->wlr_surface = surface;
-
- if (surface) {
- wlr_seat_pointer_notify_enter(seat->seat, surface, sx, sy);
- wlr_seat_pointer_notify_motion(seat->seat, time, sx, sy);
- } else {
- wlr_seat_pointer_clear_focus(seat->seat);
- }
-
- if (seat->drag_icon != NULL) {
- roots_drag_icon_update_position(seat->drag_icon);
- }
-}
-
-static inline int64_t timespec_to_msec(const struct timespec *a) {
- return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000;
-}
-
-void roots_cursor_update_focus(struct roots_cursor *cursor) {
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
-
- roots_passthrough_cursor(cursor, timespec_to_msec(&now));
-}
-
-void roots_cursor_update_position(struct roots_cursor *cursor,
- uint32_t time) {
- struct roots_seat *seat = cursor->seat;
- struct roots_view *view;
- switch (cursor->mode) {
- case ROOTS_CURSOR_PASSTHROUGH:
- roots_passthrough_cursor(cursor, time);
- break;
- case ROOTS_CURSOR_MOVE:
- view = roots_seat_get_focus(seat);
- if (view != NULL) {
- double dx = cursor->cursor->x - cursor->offs_x;
- double dy = cursor->cursor->y - cursor->offs_y;
- view_move(view, cursor->view_x + dx,
- cursor->view_y + dy);
- }
- break;
- case ROOTS_CURSOR_RESIZE:
- view = roots_seat_get_focus(seat);
- if (view != NULL) {
- double dx = cursor->cursor->x - cursor->offs_x;
- double dy = cursor->cursor->y - cursor->offs_y;
- double x = view->box.x;
- double y = view->box.y;
- int width = cursor->view_width;
- int height = cursor->view_height;
- if (cursor->resize_edges & WLR_EDGE_TOP) {
- y = cursor->view_y + dy;
- height -= dy;
- if (height < 1) {
- y += height;
- }
- } else if (cursor->resize_edges & WLR_EDGE_BOTTOM) {
- height += dy;
- }
- if (cursor->resize_edges & WLR_EDGE_LEFT) {
- x = cursor->view_x + dx;
- width -= dx;
- if (width < 1) {
- x += width;
- }
- } else if (cursor->resize_edges & WLR_EDGE_RIGHT) {
- width += dx;
- }
- view_move_resize(view, x, y,
- width < 1 ? 1 : width,
- height < 1 ? 1 : height);
- }
- break;
- case ROOTS_CURSOR_ROTATE:
- view = roots_seat_get_focus(seat);
- if (view != NULL) {
- int ox = view->box.x + view->wlr_surface->current.width/2,
- oy = view->box.y + view->wlr_surface->current.height/2;
- int ux = cursor->offs_x - ox,
- uy = cursor->offs_y - oy;
- int vx = cursor->cursor->x - ox,
- vy = cursor->cursor->y - oy;
- float angle = atan2(ux*vy - uy*vx, vx*ux + vy*uy);
- int steps = 12;
- angle = round(angle/M_PI*steps) / (steps/M_PI);
- view_rotate(view, cursor->view_rotation + angle);
- }
- break;
- }
-}
-
-static void roots_cursor_press_button(struct roots_cursor *cursor,
- struct wlr_input_device *device, uint32_t time, uint32_t button,
- uint32_t state, double lx, double ly) {
- struct roots_seat *seat = cursor->seat;
- struct roots_desktop *desktop = seat->input->server->desktop;
-
- bool is_touch = device->type == WLR_INPUT_DEVICE_TOUCH;
-
- double sx, sy;
- struct roots_view *view;
- struct wlr_surface *surface = desktop_surface_at(desktop,
- lx, ly, &sx, &sy, &view);
-
- if (state == WLR_BUTTON_PRESSED && view &&
- roots_seat_has_meta_pressed(seat)) {
- roots_seat_set_focus(seat, view);
-
- uint32_t edges;
- switch (button) {
- case BTN_LEFT:
- roots_seat_begin_move(seat, view);
- break;
- case BTN_RIGHT:
- edges = 0;
- if (sx < view->wlr_surface->current.width/2) {
- edges |= WLR_EDGE_LEFT;
- } else {
- edges |= WLR_EDGE_RIGHT;
- }
- if (sy < view->wlr_surface->current.height/2) {
- edges |= WLR_EDGE_TOP;
- } else {
- edges |= WLR_EDGE_BOTTOM;
- }
- roots_seat_begin_resize(seat, view, edges);
- break;
- case BTN_MIDDLE:
- roots_seat_begin_rotate(seat, view);
- break;
- }
- } else {
- if (view && !surface && cursor->pointer_view) {
- seat_view_deco_button(cursor->pointer_view,
- sx, sy, button, state);
- }
-
- if (state == WLR_BUTTON_RELEASED &&
- cursor->mode != ROOTS_CURSOR_PASSTHROUGH) {
- cursor->mode = ROOTS_CURSOR_PASSTHROUGH;
- }
-
- if (state == WLR_BUTTON_PRESSED) {
- if (view) {
- roots_seat_set_focus(seat, view);
- }
- if (surface && wlr_surface_is_layer_surface(surface)) {
- struct wlr_layer_surface_v1 *layer =
- wlr_layer_surface_v1_from_wlr_surface(surface);
- if (layer->current.keyboard_interactive) {
- roots_seat_set_focus_layer(seat, layer);
- }
- }
- }
- }
-
- if (!is_touch) {
- wlr_seat_pointer_notify_button(seat->seat, time, button, state);
- }
-}
-
-void roots_cursor_handle_motion(struct roots_cursor *cursor,
- struct wlr_event_pointer_motion *event) {
- double dx = event->delta_x;
- double dy = event->delta_y;
-
- double dx_unaccel = event->unaccel_dx;
- double dy_unaccel = event->unaccel_dy;
-
- wlr_relative_pointer_manager_v1_send_relative_motion(
- cursor->seat->input->server->desktop->relative_pointer_manager,
- cursor->seat->seat, (uint64_t)event->time_msec * 1000, dx, dy,
- dx_unaccel, dy_unaccel);
-
- if (cursor->active_constraint) {
- struct roots_view *view = cursor->pointer_view->view;
- assert(view);
-
- // TODO: handle rotated views
- if (view->rotation == 0.0) {
- double lx1 = cursor->cursor->x;
- double ly1 = cursor->cursor->y;
-
- double lx2 = lx1 + dx;
- double ly2 = ly1 + dy;
-
- double sx1 = lx1 - view->box.x;
- double sy1 = ly1 - view->box.y;
-
- double sx2 = lx2 - view->box.x;
- double sy2 = ly2 - view->box.y;
-
- double sx2_confined, sy2_confined;
- if (!wlr_region_confine(&cursor->confine, sx1, sy1, sx2, sy2,
- &sx2_confined, &sy2_confined)) {
- return;
- }
-
- dx = sx2_confined - sx1;
- dy = sy2_confined - sy1;
- }
- }
-
- wlr_cursor_move(cursor->cursor, event->device, dx, dy);
- roots_cursor_update_position(cursor, event->time_msec);
-}
-
-void roots_cursor_handle_motion_absolute(struct roots_cursor *cursor,
- struct wlr_event_pointer_motion_absolute *event) {
- double lx, ly;
- wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, event->x,
- event->y, &lx, &ly);
-
- double dx = lx - cursor->cursor->x;
- double dy = ly - cursor->cursor->y;
- wlr_relative_pointer_manager_v1_send_relative_motion(
- cursor->seat->input->server->desktop->relative_pointer_manager,
- cursor->seat->seat, (uint64_t)event->time_msec * 1000, dx, dy, dx, dy);
-
- if (cursor->pointer_view) {
- struct roots_view *view = cursor->pointer_view->view;
-
- if (cursor->active_constraint &&
- !pixman_region32_contains_point(&cursor->confine,
- floor(lx - view->box.x), floor(ly - view->box.y), NULL)) {
- return;
- }
- }
-
- wlr_cursor_warp_closest(cursor->cursor, event->device, lx, ly);
- roots_cursor_update_position(cursor, event->time_msec);
-}
-
-void roots_cursor_handle_button(struct roots_cursor *cursor,
- struct wlr_event_pointer_button *event) {
- roots_cursor_press_button(cursor, event->device, event->time_msec,
- event->button, event->state, cursor->cursor->x, cursor->cursor->y);
-}
-
-void roots_cursor_handle_axis(struct roots_cursor *cursor,
- struct wlr_event_pointer_axis *event) {
- wlr_seat_pointer_notify_axis(cursor->seat->seat, event->time_msec,
- event->orientation, event->delta, event->delta_discrete, event->source);
-}
-
-void roots_cursor_handle_frame(struct roots_cursor *cursor) {
- wlr_seat_pointer_notify_frame(cursor->seat->seat);
-}
-
-void roots_cursor_handle_touch_down(struct roots_cursor *cursor,
- struct wlr_event_touch_down *event) {
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- double lx, ly;
- wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device,
- event->x, event->y, &lx, &ly);
-
- double sx, sy;
- struct wlr_surface *surface = desktop_surface_at(
- desktop, lx, ly, &sx, &sy, NULL);
-
- uint32_t serial = 0;
- if (surface && roots_seat_allow_input(cursor->seat, surface->resource)) {
- serial = wlr_seat_touch_notify_down(cursor->seat->seat, surface,
- event->time_msec, event->touch_id, sx, sy);
- }
-
- if (serial && wlr_seat_touch_num_points(cursor->seat->seat) == 1) {
- cursor->seat->touch_id = event->touch_id;
- cursor->seat->touch_x = lx;
- cursor->seat->touch_y = ly;
- roots_cursor_press_button(cursor, event->device, event->time_msec,
- BTN_LEFT, 1, lx, ly);
- }
-}
-
-void roots_cursor_handle_touch_up(struct roots_cursor *cursor,
- struct wlr_event_touch_up *event) {
- struct wlr_touch_point *point =
- wlr_seat_touch_get_point(cursor->seat->seat, event->touch_id);
- if (!point) {
- return;
- }
-
- if (wlr_seat_touch_num_points(cursor->seat->seat) == 1) {
- roots_cursor_press_button(cursor, event->device, event->time_msec,
- BTN_LEFT, 0, cursor->seat->touch_x, cursor->seat->touch_y);
- }
-
- wlr_seat_touch_notify_up(cursor->seat->seat, event->time_msec,
- event->touch_id);
-}
-
-void roots_cursor_handle_touch_motion(struct roots_cursor *cursor,
- struct wlr_event_touch_motion *event) {
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- struct wlr_touch_point *point =
- wlr_seat_touch_get_point(cursor->seat->seat, event->touch_id);
- if (!point) {
- return;
- }
-
- double lx, ly;
- wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device,
- event->x, event->y, &lx, &ly);
-
- double sx, sy;
- struct wlr_surface *surface = desktop_surface_at(
- desktop, lx, ly, &sx, &sy, NULL);
-
- if (surface && roots_seat_allow_input(cursor->seat, surface->resource)) {
- wlr_seat_touch_point_focus(cursor->seat->seat, surface,
- event->time_msec, event->touch_id, sx, sy);
- wlr_seat_touch_notify_motion(cursor->seat->seat, event->time_msec,
- event->touch_id, sx, sy);
- } else {
- wlr_seat_touch_point_clear_focus(cursor->seat->seat, event->time_msec,
- event->touch_id);
- }
-
- if (event->touch_id == cursor->seat->touch_id) {
- cursor->seat->touch_x = lx;
- cursor->seat->touch_y = ly;
- }
-}
-
-void roots_cursor_handle_tool_axis(struct roots_cursor *cursor,
- struct wlr_event_tablet_tool_axis *event) {
- double x = NAN, y = NAN;
- if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X) &&
- (event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) {
- x = event->x;
- y = event->y;
- } else if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X)) {
- x = event->x;
- } else if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) {
- y = event->y;
- }
-
- double lx, ly;
- wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device,
- x, y, &lx, &ly);
-
-
- if (cursor->pointer_view) {
- struct roots_view *view = cursor->pointer_view->view;
-
- if (cursor->active_constraint &&
- !pixman_region32_contains_point(&cursor->confine,
- floor(lx - view->box.x), floor(ly - view->box.y), NULL)) {
- return;
- }
- }
-
- wlr_cursor_warp_closest(cursor->cursor, event->device, lx, ly);
- roots_cursor_update_position(cursor, event->time_msec);
-}
-
-void roots_cursor_handle_tool_tip(struct roots_cursor *cursor,
- struct wlr_event_tablet_tool_tip *event) {
- roots_cursor_press_button(cursor, event->device,
- event->time_msec, BTN_LEFT, event->state, cursor->cursor->x,
- cursor->cursor->y);
-}
-
-void roots_cursor_handle_request_set_cursor(struct roots_cursor *cursor,
- struct wlr_seat_pointer_request_set_cursor_event *event) {
- struct wlr_surface *focused_surface =
- event->seat_client->seat->pointer_state.focused_surface;
- bool has_focused =
- focused_surface != NULL && focused_surface->resource != NULL;
- struct wl_client *focused_client = NULL;
- if (has_focused) {
- focused_client = wl_resource_get_client(focused_surface->resource);
- }
- if (event->seat_client->client != focused_client ||
- cursor->mode != ROOTS_CURSOR_PASSTHROUGH) {
- wlr_log(WLR_DEBUG, "Denying request to set cursor from unfocused client");
- return;
- }
-
- wlr_cursor_set_surface(cursor->cursor, event->surface, event->hotspot_x,
- event->hotspot_y);
- cursor->cursor_client = event->seat_client->client;
-}
-
-void roots_cursor_handle_focus_change(struct roots_cursor *cursor,
- struct wlr_seat_pointer_focus_change_event *event) {
- double sx = event->sx;
- double sy = event->sy;
-
- double lx = cursor->cursor->x;
- double ly = cursor->cursor->y;
-
- wlr_log(WLR_DEBUG, "entered surface %p, lx: %f, ly: %f, sx: %f, sy: %f",
- event->new_surface, lx, ly, sx, sy);
-
- roots_cursor_constrain(cursor,
- wlr_pointer_constraints_v1_constraint_for_surface(
- cursor->seat->input->server->desktop->pointer_constraints,
- event->new_surface, cursor->seat->seat),
- sx, sy);
-}
-
-void roots_cursor_handle_constraint_commit(struct roots_cursor *cursor) {
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
-
- struct roots_view *view;
- double sx, sy;
- struct wlr_surface *surface = desktop_surface_at(desktop,
- cursor->cursor->x, cursor->cursor->y, &sx, &sy, &view);
- // This should never happen but views move around right when they're
- // created from (0, 0) to their actual coordinates.
- if (surface != cursor->active_constraint->surface) {
- roots_cursor_update_focus(cursor);
- } else {
- roots_cursor_constrain(cursor, cursor->active_constraint, sx, sy);
- }
-}
-
-static void handle_constraint_commit(struct wl_listener *listener,
- void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, constraint_commit);
- assert(cursor->active_constraint->surface == data);
- roots_cursor_handle_constraint_commit(cursor);
-}
-
-void roots_cursor_constrain(struct roots_cursor *cursor,
- struct wlr_pointer_constraint_v1 *constraint, double sx, double sy) {
- if (cursor->active_constraint == constraint) {
- return;
- }
-
- wlr_log(WLR_DEBUG, "roots_cursor_constrain(%p, %p)",
- cursor, constraint);
- wlr_log(WLR_DEBUG, "cursor->active_constraint: %p",
- cursor->active_constraint);
-
- wl_list_remove(&cursor->constraint_commit.link);
- wl_list_init(&cursor->constraint_commit.link);
- if (cursor->active_constraint) {
- wlr_pointer_constraint_v1_send_deactivated(
- cursor->active_constraint);
- }
-
- cursor->active_constraint = constraint;
-
- if (constraint == NULL) {
- return;
- }
-
- wlr_pointer_constraint_v1_send_activated(constraint);
-
- wl_list_remove(&cursor->constraint_commit.link);
- wl_signal_add(&constraint->surface->events.commit,
- &cursor->constraint_commit);
- cursor->constraint_commit.notify = handle_constraint_commit;
-
- pixman_region32_clear(&cursor->confine);
-
- pixman_region32_t *region = &constraint->region;
-
- if (!pixman_region32_contains_point(region, floor(sx), floor(sy), NULL)) {
- // Warp into region if possible
- int nboxes;
- pixman_box32_t *boxes = pixman_region32_rectangles(region, &nboxes);
- if (nboxes > 0) {
- struct roots_view *view = cursor->pointer_view->view;
-
- double sx = (boxes[0].x1 + boxes[0].x2) / 2.;
- double sy = (boxes[0].y1 + boxes[0].y2) / 2.;
-
- rotate_child_position(&sx, &sy, 0, 0, view->box.width, view->box.height,
- view->rotation);
-
- double lx = view->box.x + sx;
- double ly = view->box.y + sy;
-
- wlr_cursor_warp_closest(cursor->cursor, NULL, lx, ly);
- }
- }
-
- // A locked pointer will result in an empty region, thus disallowing all movement
- if (constraint->type == WLR_POINTER_CONSTRAINT_V1_CONFINED) {
- pixman_region32_copy(&cursor->confine, region);
- }
-}
diff --git a/rootston/desktop.c b/rootston/desktop.c
deleted file mode 100644
index 3d9888e3..00000000
--- a/rootston/desktop.c
+++ /dev/null
@@ -1,465 +0,0 @@
-#define _POSIX_C_SOURCE 200112L
-#include <assert.h>
-#include <math.h>
-#include <stdlib.h>
-#include <time.h>
-#include <wlr/config.h>
-#include <wlr/types/wlr_box.h>
-#include <wlr/types/wlr_compositor.h>
-#include <wlr/types/wlr_cursor.h>
-#include <wlr/types/wlr_data_control_v1.h>
-#include <wlr/types/wlr_export_dmabuf_v1.h>
-#include <wlr/types/wlr_gamma_control_v1.h>
-#include <wlr/types/wlr_gtk_primary_selection.h>
-#include <wlr/types/wlr_idle_inhibit_v1.h>
-#include <wlr/types/wlr_idle.h>
-#include <wlr/types/wlr_input_inhibitor.h>
-#include <wlr/types/wlr_layer_shell_v1.h>
-#include <wlr/types/wlr_output_layout.h>
-#include <wlr/types/wlr_pointer_constraints_v1.h>
-#include <wlr/types/wlr_primary_selection_v1.h>
-#include <wlr/types/wlr_server_decoration.h>
-#include <wlr/types/wlr_tablet_v2.h>
-#include <wlr/types/wlr_xcursor_manager.h>
-#include <wlr/types/wlr_xdg_output_v1.h>
-#include <wlr/types/wlr_xdg_output_v1.h>
-#include <wlr/types/wlr_xdg_shell_v6.h>
-#include <wlr/types/wlr_xdg_shell.h>
-#include <wlr/util/log.h>
-#include "rootston/layers.h"
-#include "rootston/seat.h"
-#include "rootston/server.h"
-#include "rootston/view.h"
-#include "rootston/virtual_keyboard.h"
-#include "rootston/xcursor.h"
-#include "wlr-layer-shell-unstable-v1-protocol.h"
-
-static bool view_at(struct roots_view *view, double lx, double ly,
- struct wlr_surface **surface, double *sx, double *sy) {
- if (view->wlr_surface == NULL) {
- return false;
- }
-
- double view_sx = lx - view->box.x;
- double view_sy = ly - view->box.y;
- rotate_child_position(&view_sx, &view_sy, 0, 0,
- view->box.width, view->box.height, -view->rotation);
-
- double _sx, _sy;
- struct wlr_surface *_surface = NULL;
- switch (view->type) {
- case ROOTS_XDG_SHELL_V6_VIEW:;
- struct roots_xdg_surface_v6 *xdg_surface_v6 =
- roots_xdg_surface_v6_from_view(view);
- _surface = wlr_xdg_surface_v6_surface_at(xdg_surface_v6->xdg_surface_v6,
- view_sx, view_sy, &_sx, &_sy);
- break;
- case ROOTS_XDG_SHELL_VIEW:;
- struct roots_xdg_surface *xdg_surface =
- roots_xdg_surface_from_view(view);
- _surface = wlr_xdg_surface_surface_at(xdg_surface->xdg_surface,
- view_sx, view_sy, &_sx, &_sy);
- break;
-#if WLR_HAS_XWAYLAND
- case ROOTS_XWAYLAND_VIEW:
- _surface = wlr_surface_surface_at(view->wlr_surface,
- view_sx, view_sy, &_sx, &_sy);
- break;
-#endif
- }
- if (_surface != NULL) {
- *sx = _sx;
- *sy = _sy;
- *surface = _surface;
- return true;
- }
-
- if (view_get_deco_part(view, view_sx, view_sy)) {
- *sx = view_sx;
- *sy = view_sy;
- *surface = NULL;
- return true;
- }
-
- return false;
-}
-
-static struct roots_view *desktop_view_at(struct roots_desktop *desktop,
- double lx, double ly, struct wlr_surface **surface,
- double *sx, double *sy) {
- struct roots_view *view;
- wl_list_for_each(view, &desktop->views, link) {
- if (view_at(view, lx, ly, surface, sx, sy)) {
- return view;
- }
- }
- return NULL;
-}
-
-static struct wlr_surface *layer_surface_at(struct roots_output *output,
- struct wl_list *layer, double ox, double oy, double *sx, double *sy) {
- struct roots_layer_surface *roots_surface;
- wl_list_for_each_reverse(roots_surface, layer, link) {
- double _sx = ox - roots_surface->geo.x;
- double _sy = oy - roots_surface->geo.y;
-
- struct wlr_surface *sub = wlr_layer_surface_v1_surface_at(
- roots_surface->layer_surface, _sx, _sy, sx, sy);
-
- if (sub) {
- return sub;
- }
- }
-
- return NULL;
-}
-
-struct wlr_surface *desktop_surface_at(struct roots_desktop *desktop,
- double lx, double ly, double *sx, double *sy,
- struct roots_view **view) {
- struct wlr_surface *surface = NULL;
- struct wlr_output *wlr_output =
- wlr_output_layout_output_at(desktop->layout, lx, ly);
- struct roots_output *roots_output = NULL;
- double ox = lx, oy = ly;
- if (view) {
- *view = NULL;
- }
-
- if (wlr_output) {
- roots_output = wlr_output->data;
- wlr_output_layout_output_coords(desktop->layout, wlr_output, &ox, &oy);
-
- if ((surface = layer_surface_at(roots_output,
- &roots_output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
- ox, oy, sx, sy))) {
- return surface;
- }
-
- struct roots_output *output =
- desktop_output_from_wlr_output(desktop, wlr_output);
- if (output != NULL && output->fullscreen_view != NULL) {
- if (view_at(output->fullscreen_view, lx, ly, &surface, sx, sy)) {
- return surface;
- } else {
- return NULL;
- }
- }
-
- if ((surface = layer_surface_at(roots_output,
- &roots_output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
- ox, oy, sx, sy))) {
- return surface;
- }
- }
-
- struct roots_view *_view;
- if ((_view = desktop_view_at(desktop, lx, ly, &surface, sx, sy))) {
- if (view) {
- *view = _view;
- }
- return surface;
- }
-
- if (wlr_output) {
- if ((surface = layer_surface_at(roots_output,
- &roots_output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
- ox, oy, sx, sy))) {
- return surface;
- }
- if ((surface = layer_surface_at(roots_output,
- &roots_output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
- ox, oy, sx, sy))) {
- return surface;
- }
- }
- return NULL;
-}
-
-static void handle_layout_change(struct wl_listener *listener, void *data) {
- struct roots_desktop *desktop =
- wl_container_of(listener, desktop, layout_change);
-
- struct wlr_output *center_output =
- wlr_output_layout_get_center_output(desktop->layout);
- if (center_output == NULL) {
- return;
- }
-
- struct wlr_box *center_output_box =
- wlr_output_layout_get_box(desktop->layout, center_output);
- double center_x = center_output_box->x + center_output_box->width/2;
- double center_y = center_output_box->y + center_output_box->height/2;
-
- struct roots_view *view;
- wl_list_for_each(view, &desktop->views, link) {
- struct wlr_box box;
- view_get_box(view, &box);
-
- if (wlr_output_layout_intersects(desktop->layout, NULL, &box)) {
- continue;
- }
-
- view_move(view, center_x - box.width/2, center_y - box.height/2);
- }
-}
-
-static void input_inhibit_activate(struct wl_listener *listener, void *data) {
- struct roots_desktop *desktop = wl_container_of(
- listener, desktop, input_inhibit_activate);
- struct roots_seat *seat;
- wl_list_for_each(seat, &desktop->server->input->seats, link) {
- roots_seat_set_exclusive_client(seat,
- desktop->input_inhibit->active_client);
- }
-}
-
-static void input_inhibit_deactivate(struct wl_listener *listener, void *data) {
- struct roots_desktop *desktop = wl_container_of(
- listener, desktop, input_inhibit_deactivate);
- struct roots_seat *seat;
- wl_list_for_each(seat, &desktop->server->input->seats, link) {
- roots_seat_set_exclusive_client(seat, NULL);
- }
-}
-
-static void handle_constraint_destroy(struct wl_listener *listener,
- void *data) {
- struct roots_pointer_constraint *constraint =
- wl_container_of(listener, constraint, destroy);
- struct wlr_pointer_constraint_v1 *wlr_constraint = data;
- struct roots_seat *seat = wlr_constraint->seat->data;
-
- wl_list_remove(&constraint->destroy.link);
-
- if (seat->cursor->active_constraint == wlr_constraint) {
- wl_list_remove(&seat->cursor->constraint_commit.link);
- wl_list_init(&seat->cursor->constraint_commit.link);
- seat->cursor->active_constraint = NULL;
-
- if (wlr_constraint->current.committed &
- WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT &&
- seat->cursor->pointer_view) {
- double sx = wlr_constraint->current.cursor_hint.x;
- double sy = wlr_constraint->current.cursor_hint.y;
-
- struct roots_view *view = seat->cursor->pointer_view->view;
- rotate_child_position(&sx, &sy, 0, 0, view->box.width, view->box.height,
- view->rotation);
- double lx = view->box.x + sx;
- double ly = view->box.y + sy;
-
- wlr_cursor_warp(seat->cursor->cursor, NULL, lx, ly);
- }
- }
-
- free(constraint);
-}
-
-static void handle_pointer_constraint(struct wl_listener *listener,
- void *data) {
- struct wlr_pointer_constraint_v1 *wlr_constraint = data;
- struct roots_seat *seat = wlr_constraint->seat->data;
-
- struct roots_pointer_constraint *constraint =
- calloc(1, sizeof(struct roots_pointer_constraint));
- constraint->constraint = wlr_constraint;
-
- constraint->destroy.notify = handle_constraint_destroy;
- wl_signal_add(&wlr_constraint->events.destroy, &constraint->destroy);
-
- double sx, sy;
- struct wlr_surface *surface = desktop_surface_at(
- seat->input->server->desktop,
- seat->cursor->cursor->x, seat->cursor->cursor->y, &sx, &sy, NULL);
-
- if (surface == wlr_constraint->surface) {
- assert(!seat->cursor->active_constraint);
- roots_cursor_constrain(seat->cursor, wlr_constraint, sx, sy);
- }
-}
-
-struct roots_desktop *desktop_create(struct roots_server *server,
- struct roots_config *config) {
- wlr_log(WLR_DEBUG, "Initializing roots desktop");
-
- struct roots_desktop *desktop = calloc(1, sizeof(struct roots_desktop));
- if (desktop == NULL) {
- return NULL;
- }
-
- wl_list_init(&desktop->views);
- wl_list_init(&desktop->outputs);
-
- desktop->new_output.notify = handle_new_output;
- wl_signal_add(&server->backend->events.new_output, &desktop->new_output);
-
- desktop->server = server;
- desktop->config = config;
-
- desktop->layout = wlr_output_layout_create();
- wlr_xdg_output_manager_v1_create(server->wl_display, desktop->layout);
- desktop->layout_change.notify = handle_layout_change;
- wl_signal_add(&desktop->layout->events.change, &desktop->layout_change);
-
- desktop->compositor = wlr_compositor_create(server->wl_display,
- server->renderer);
-
- desktop->xdg_shell_v6 = wlr_xdg_shell_v6_create(server->wl_display);
- wl_signal_add(&desktop->xdg_shell_v6->events.new_surface,
- &desktop->xdg_shell_v6_surface);
- desktop->xdg_shell_v6_surface.notify = handle_xdg_shell_v6_surface;
-
- desktop->xdg_shell = wlr_xdg_shell_create(server->wl_display);
- wl_signal_add(&desktop->xdg_shell->events.new_surface,
- &desktop->xdg_shell_surface);
- desktop->xdg_shell_surface.notify = handle_xdg_shell_surface;
-
- desktop->layer_shell = wlr_layer_shell_v1_create(server->wl_display);
- wl_signal_add(&desktop->layer_shell->events.new_surface,
- &desktop->layer_shell_surface);
- desktop->layer_shell_surface.notify = handle_layer_shell_surface;
-
- desktop->tablet_v2 = wlr_tablet_v2_create(server->wl_display);
-
- const char *cursor_theme = NULL;
-#if WLR_HAS_XWAYLAND
- const char *cursor_default = ROOTS_XCURSOR_DEFAULT;
-#endif
- struct roots_cursor_config *cc =
- roots_config_get_cursor(config, ROOTS_CONFIG_DEFAULT_SEAT_NAME);
- if (cc != NULL) {
- cursor_theme = cc->theme;
-#if WLR_HAS_XWAYLAND
- if (cc->default_image != NULL) {
- cursor_default = cc->default_image;
- }
-#endif
- }
-
- char cursor_size_fmt[16];
- snprintf(cursor_size_fmt, sizeof(cursor_size_fmt),
- "%d", ROOTS_XCURSOR_SIZE);
- setenv("XCURSOR_SIZE", cursor_size_fmt, 1);
- if (cursor_theme != NULL) {
- setenv("XCURSOR_THEME", cursor_theme, 1);
- }
-
-#if WLR_HAS_XWAYLAND
- desktop->xcursor_manager = wlr_xcursor_manager_create(cursor_theme,
- ROOTS_XCURSOR_SIZE);
- if (desktop->xcursor_manager == NULL) {
- wlr_log(WLR_ERROR, "Cannot create XCursor manager for theme %s",
- cursor_theme);
- free(desktop);
- return NULL;
- }
-
- if (config->xwayland) {
- desktop->xwayland = wlr_xwayland_create(server->wl_display,
- desktop->compositor, config->xwayland_lazy);
- wl_signal_add(&desktop->xwayland->events.new_surface,
- &desktop->xwayland_surface);
- desktop->xwayland_surface.notify = handle_xwayland_surface;
-
- setenv("DISPLAY", desktop->xwayland->display_name, true);
-
- if (wlr_xcursor_manager_load(desktop->xcursor_manager, 1)) {
- wlr_log(WLR_ERROR, "Cannot load XWayland XCursor theme");
- }
- struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor(
- desktop->xcursor_manager, cursor_default, 1);
- if (xcursor != NULL) {
- struct wlr_xcursor_image *image = xcursor->images[0];
- wlr_xwayland_set_cursor(desktop->xwayland, image->buffer,
- image->width * 4, image->width, image->height, image->hotspot_x,
- image->hotspot_y);
- }
- }
-#endif
-
- desktop->gamma_control_manager_v1 = wlr_gamma_control_manager_v1_create(
- server->wl_display);
- desktop->export_dmabuf_manager_v1 =
- wlr_export_dmabuf_manager_v1_create(server->wl_display);
- desktop->server_decoration_manager =
- wlr_server_decoration_manager_create(server->wl_display);
- wlr_server_decoration_manager_set_default_mode(
- desktop->server_decoration_manager,
- WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT);
- desktop->idle = wlr_idle_create(server->wl_display);
- desktop->idle_inhibit = wlr_idle_inhibit_v1_create(server->wl_display);
- desktop->primary_selection_device_manager =
- wlr_gtk_primary_selection_device_manager_create(server->wl_display);
- desktop->input_inhibit =
- wlr_input_inhibit_manager_create(server->wl_display);
- desktop->input_inhibit_activate.notify = input_inhibit_activate;
- wl_signal_add(&desktop->input_inhibit->events.activate,
- &desktop->input_inhibit_activate);
- desktop->input_inhibit_deactivate.notify = input_inhibit_deactivate;
- wl_signal_add(&desktop->input_inhibit->events.deactivate,
- &desktop->input_inhibit_deactivate);
-
- desktop->input_method =
- wlr_input_method_manager_v2_create(server->wl_display);
-
- desktop->text_input = wlr_text_input_manager_v3_create(server->wl_display);
-
- desktop->virtual_keyboard = wlr_virtual_keyboard_manager_v1_create(
- server->wl_display);
- wl_signal_add(&desktop->virtual_keyboard->events.new_virtual_keyboard,
- &desktop->virtual_keyboard_new);
- desktop->virtual_keyboard_new.notify = handle_virtual_keyboard;
-
- desktop->screencopy = wlr_screencopy_manager_v1_create(server->wl_display);
-
- desktop->xdg_decoration_manager =
- wlr_xdg_decoration_manager_v1_create(server->wl_display);
- wl_signal_add(&desktop->xdg_decoration_manager->events.new_toplevel_decoration,
- &desktop->xdg_toplevel_decoration);
- desktop->xdg_toplevel_decoration.notify = handle_xdg_toplevel_decoration;
-
- desktop->pointer_constraints =
- wlr_pointer_constraints_v1_create(server->wl_display);
- desktop->pointer_constraint.notify = handle_pointer_constraint;
- wl_signal_add(&desktop->pointer_constraints->events.new_constraint,
- &desktop->pointer_constraint);
-
- desktop->presentation =
- wlr_presentation_create(server->wl_display, server->backend);
- desktop->foreign_toplevel_manager_v1 =
- wlr_foreign_toplevel_manager_v1_create(server->wl_display);
- desktop->relative_pointer_manager =
- wlr_relative_pointer_manager_v1_create(server->wl_display);
- desktop->pointer_gestures =
- wlr_pointer_gestures_v1_create(server->wl_display);
-
- desktop->output_manager_v1 =
- wlr_output_manager_v1_create(server->wl_display);
- desktop->output_manager_apply.notify = handle_output_manager_apply;
- wl_signal_add(&desktop->output_manager_v1->events.apply,
- &desktop->output_manager_apply);
- desktop->output_manager_test.notify = handle_output_manager_test;
- wl_signal_add(&desktop->output_manager_v1->events.test,
- &desktop->output_manager_test);
-
- wlr_primary_selection_v1_device_manager_create(server->wl_display);
- wlr_data_control_manager_v1_create(server->wl_display);
-
- return desktop;
-}
-
-void desktop_destroy(struct roots_desktop *desktop) {
- // TODO
-}
-
-struct roots_output *desktop_output_from_wlr_output(
- struct roots_desktop *desktop, struct wlr_output *wlr_output) {
- struct roots_output *output;
- wl_list_for_each(output, &desktop->outputs, link) {
- if (output->wlr_output == wlr_output) {
- return output;
- }
- }
- return NULL;
-}
diff --git a/rootston/ini.c b/rootston/ini.c
deleted file mode 100644
index f515dd38..00000000
--- a/rootston/ini.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/* inih -- simple .INI file parser
-
-inih is released under the New BSD license (see LICENSE.txt). Go to the project
-home page for more info:
-
-https://github.com/benhoyt/inih
-
-*/
-
-#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
-#define _CRT_SECURE_NO_WARNINGS
-#endif
-
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-
-#include "rootston/ini.h"
-
-#if !INI_USE_STACK
-#include <stdlib.h>
-#endif
-
-#define MAX_SECTION 50
-#define MAX_NAME 50
-
-/* Strip whitespace chars off end of given string, in place. Return s. */
-static char* rstrip(char* s)
-{
- char* p = s + strlen(s);
- while (p > s && isspace((unsigned char)(*--p)))
- *p = '\0';
- return s;
-}
-
-/* Return pointer to first non-whitespace char in given string. */
-static char* lskip(const char* s)
-{
- while (*s && isspace((unsigned char)(*s)))
- s++;
- return (char*)s;
-}
-
-/* Return pointer to first char (of chars) or inline comment in given string,
- or pointer to null at end of string if neither found. Inline comment must
- be prefixed by a whitespace character to register as a comment. */
-static char* find_chars_or_comment(const char* s, const char* chars)
-{
-#if INI_ALLOW_INLINE_COMMENTS
- int was_space = 0;
- while (*s && (!chars || !strchr(chars, *s)) &&
- !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) {
- was_space = isspace((unsigned char)(*s));
- s++;
- }
-#else
- while (*s && (!chars || !strchr(chars, *s))) {
- s++;
- }
-#endif
- return (char*)s;
-}
-
-/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
-static char* strncpy0(char* dest, const char* src, size_t size)
-{
- strncpy(dest, src, size-1);
- dest[size - 1] = '\0';
- return dest;
-}
-
-/* See documentation in header file. */
-int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
- void* user)
-{
- /* Uses a fair bit of stack (use heap instead if you need to) */
-#if INI_USE_STACK
- char line[INI_MAX_LINE];
-#else
- char* line;
-#endif
- char section[MAX_SECTION] = "";
- char prev_name[MAX_NAME] = "";
-
- char* start;
- char* end;
- char* name;
- char* value;
- int lineno = 0;
- int error = 0;
-
-#if !INI_USE_STACK
- line = (char*)malloc(INI_MAX_LINE);
- if (!line) {
- return -2;
- }
-#endif
-
- /* Scan through stream line by line */
- while (reader(line, INI_MAX_LINE, stream) != NULL) {
- lineno++;
-
- start = line;
-#if INI_ALLOW_BOM
- if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
- (unsigned char)start[1] == 0xBB &&
- (unsigned char)start[2] == 0xBF) {
- start += 3;
- }
-#endif
- start = lskip(rstrip(start));
-
- if (*start == ';' || *start == '#') {
- /* Per Python configparser, allow both ; and # comments at the
- start of a line */
- }
-#if INI_ALLOW_MULTILINE
- else if (*prev_name && *start && start > line) {
- /* Non-blank line with leading whitespace, treat as continuation
- of previous name's value (as per Python configparser). */
- if (!handler(user, section, prev_name, start) && !error)
- error = lineno;
- }
-#endif
- else if (*start == '[') {
- /* A "[section]" line */
- end = find_chars_or_comment(start + 1, "]");
- if (*end == ']') {
- *end = '\0';
- strncpy0(section, start + 1, sizeof(section));
- *prev_name = '\0';
- }
- else if (!error) {
- /* No ']' found on section line */
- error = lineno;
- }
- }
- else if (*start) {
- /* Not a comment, must be a name[=:]value pair */
- end = find_chars_or_comment(start, "=:");
- if (*end == '=' || *end == ':') {
- *end = '\0';
- name = rstrip(start);
- value = lskip(end + 1);
-#if INI_ALLOW_INLINE_COMMENTS
- end = find_chars_or_comment(value, NULL);
- if (*end)
- *end = '\0';
-#endif
- rstrip(value);
-
- /* Valid name[=:]value pair found, call handler */
- strncpy0(prev_name, name, sizeof(prev_name));
- if (!handler(user, section, name, value) && !error)
- error = lineno;
- memset(value, 0, strlen(value));
- }
- else if (!error) {
- /* No '=' or ':' found on name[=:]value line */
- error = lineno;
- }
- }
-
-#if INI_STOP_ON_FIRST_ERROR
- if (error)
- break;
-#endif
- }
-
-#if !INI_USE_STACK
- free(line);
-#endif
-
- return error;
-}
-
-/* See documentation in header file. */
-int ini_parse_file(FILE* file, ini_handler handler, void* user)
-{
- return ini_parse_stream((ini_reader)fgets, file, handler, user);
-}
-
-/* See documentation in header file. */
-int ini_parse(const char* filename, ini_handler handler, void* user)
-{
- FILE* file;
- int error;
-
- file = fopen(filename, "r");
- if (!file)
- return -1;
- error = ini_parse_file(file, handler, user);
- fclose(file);
- return error;
-}
diff --git a/rootston/input.c b/rootston/input.c
deleted file mode 100644
index d5e04d3d..00000000
--- a/rootston/input.c
+++ /dev/null
@@ -1,146 +0,0 @@
-#define _POSIX_C_SOURCE 200112L
-#include <assert.h>
-#include <stdlib.h>
-#include <time.h>
-#include <wayland-server-core.h>
-#include <wlr/backend/libinput.h>
-#include <wlr/config.h>
-#include <wlr/types/wlr_cursor.h>
-#include <wlr/util/log.h>
-#include <wlr/xcursor.h>
-#if WLR_HAS_XWAYLAND
-#include <wlr/xwayland.h>
-#endif
-#include "rootston/config.h"
-#include "rootston/input.h"
-#include "rootston/keyboard.h"
-#include "rootston/seat.h"
-#include "rootston/server.h"
-
-static const char *device_type(enum wlr_input_device_type type) {
- switch (type) {
- case WLR_INPUT_DEVICE_KEYBOARD:
- return "keyboard";
- case WLR_INPUT_DEVICE_POINTER:
- return "pointer";
- case WLR_INPUT_DEVICE_SWITCH:
- return "switch";
- case WLR_INPUT_DEVICE_TOUCH:
- return "touch";
- case WLR_INPUT_DEVICE_TABLET_TOOL:
- return "tablet tool";
- case WLR_INPUT_DEVICE_TABLET_PAD:
- return "tablet pad";
- }
- return NULL;
-}
-
-struct roots_seat *input_get_seat(struct roots_input *input, char *name) {
- struct roots_seat *seat = NULL;
- wl_list_for_each(seat, &input->seats, link) {
- if (strcmp(seat->seat->name, name) == 0) {
- return seat;
- }
- }
-
- seat = roots_seat_create(input, name);
- return seat;
-}
-
-static void handle_new_input(struct wl_listener *listener, void *data) {
- struct wlr_input_device *device = data;
- struct roots_input *input = wl_container_of(listener, input, new_input);
-
- char *seat_name = ROOTS_CONFIG_DEFAULT_SEAT_NAME;
- struct roots_device_config *dc =
- roots_config_get_device(input->config, device);
- if (dc) {
- seat_name = dc->seat;
- }
-
- struct roots_seat *seat = input_get_seat(input, seat_name);
- if (!seat) {
- wlr_log(WLR_ERROR, "could not create roots seat");
- return;
- }
-
- wlr_log(WLR_DEBUG, "New input device: %s (%d:%d) %s seat:%s", device->name,
- device->vendor, device->product, device_type(device->type), seat_name);
-
- roots_seat_add_device(seat, device);
-
- if (dc && wlr_input_device_is_libinput(device)) {
- struct libinput_device *libinput_dev =
- wlr_libinput_get_device_handle(device);
-
- wlr_log(WLR_DEBUG, "input has config, tap_enabled: %d\n", dc->tap_enabled);
- if (dc->tap_enabled) {
- libinput_device_config_tap_set_enabled(libinput_dev,
- LIBINPUT_CONFIG_TAP_ENABLED);
- }
- }
-}
-
-struct roots_input *input_create(struct roots_server *server,
- struct roots_config *config) {
- wlr_log(WLR_DEBUG, "Initializing roots input");
- assert(server->desktop);
-
- struct roots_input *input = calloc(1, sizeof(struct roots_input));
- if (input == NULL) {
- return NULL;
- }
-
- input->config = config;
- input->server = server;
-
- wl_list_init(&input->seats);
-
- input->new_input.notify = handle_new_input;
- wl_signal_add(&server->backend->events.new_input, &input->new_input);
-
- return input;
-}
-
-void input_destroy(struct roots_input *input) {
- // TODO
-}
-
-struct roots_seat *input_seat_from_wlr_seat(struct roots_input *input,
- struct wlr_seat *wlr_seat) {
- struct roots_seat *seat = NULL;
- wl_list_for_each(seat, &input->seats, link) {
- if (seat->seat == wlr_seat) {
- return seat;
- }
- }
- return seat;
-}
-
-bool input_view_has_focus(struct roots_input *input, struct roots_view *view) {
- if (!view) {
- return false;
- }
- struct roots_seat *seat;
- wl_list_for_each(seat, &input->seats, link) {
- if (view == roots_seat_get_focus(seat)) {
- return true;
- }
- }
-
- return false;
-}
-
-static inline int64_t timespec_to_msec(const struct timespec *a) {
- return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000;
-}
-
-void input_update_cursor_focus(struct roots_input *input) {
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
-
- struct roots_seat *seat;
- wl_list_for_each(seat, &input->seats, link) {
- roots_cursor_update_position(seat->cursor, timespec_to_msec(&now));
- }
-}
diff --git a/rootston/keyboard.c b/rootston/keyboard.c
deleted file mode 100644
index da88e914..00000000
--- a/rootston/keyboard.c
+++ /dev/null
@@ -1,349 +0,0 @@
-#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <wayland-server-core.h>
-#include <wlr/backend/session.h>
-#include <wlr/types/wlr_input_device.h>
-#include <wlr/types/wlr_pointer_constraints_v1.h>
-#include <wlr/types/wlr_pointer.h>
-#include <wlr/util/log.h>
-#include <xkbcommon/xkbcommon.h>
-#include "rootston/bindings.h"
-#include "rootston/input.h"
-#include "rootston/keyboard.h"
-#include "rootston/seat.h"
-
-static ssize_t pressed_keysyms_index(xkb_keysym_t *pressed_keysyms,
- xkb_keysym_t keysym) {
- for (size_t i = 0; i < ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) {
- if (pressed_keysyms[i] == keysym) {
- return i;
- }
- }
- return -1;
-}
-
-static size_t pressed_keysyms_length(xkb_keysym_t *pressed_keysyms) {
- size_t n = 0;
- for (size_t i = 0; i < ROOTS_KEYBOARD_PRESSED_KEYSYMS_CAP; ++i) {
- if (pressed_keysyms[i] != XKB_KEY_NoSymbol) {
- ++n;
- }
- }
- return n;
-}
-
-static void pressed_keysyms_add(xkb_keysym_t *pressed_keysyms,
- xkb_keysym_t keysym) {
- ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym);
- if (i < 0) {
- i = pressed_keysyms_index(pressed_keysyms, XKB_KEY_NoSymbol);
- if (i >= 0) {
- pressed_keysyms[i] = keysym;
- }
- }
-}
-
-static void pressed_keysyms_remove(xkb_keysym_t *pressed_keysyms,
- xkb_keysym_t keysym) {
- ssize_t i = pressed_keysyms_index(pressed_keysyms, keysym);
- if (i >= 0) {
- pressed_keysyms[i] = XKB_KEY_NoSymbol;
- }
-}
-
-static bool keysym_is_modifier(xkb_keysym_t keysym) {
- switch (keysym) {
- case XKB_KEY_Shift_L: case XKB_KEY_Shift_R:
- case XKB_KEY_Control_L: case XKB_KEY_Control_R:
- case XKB_KEY_Caps_Lock:
- case XKB_KEY_Shift_Lock:
- case XKB_KEY_Meta_L: case XKB_KEY_Meta_R:
- case XKB_KEY_Alt_L: case XKB_KEY_Alt_R:
- case XKB_KEY_Super_L: case XKB_KEY_Super_R:
- case XKB_KEY_Hyper_L: case XKB_KEY_Hyper_R:
- return true;
- default:
- return false;
- }
-}
-
-static void pressed_keysyms_update(xkb_keysym_t *pressed_keysyms,
- const xkb_keysym_t *keysyms, size_t keysyms_len,
- enum wlr_key_state state) {
- for (size_t i = 0; i < keysyms_len; ++i) {
- if (keysym_is_modifier(keysyms[i])) {
- continue;
- }
- if (state == WLR_KEY_PRESSED) {
- pressed_keysyms_add(pressed_keysyms, keysyms[i]);
- } else { // WLR_KEY_RELEASED
- pressed_keysyms_remove(pressed_keysyms, keysyms[i]);
- }
- }
-}
-
-static void keyboard_binding_execute(struct roots_keyboard *keyboard,
- const char *command) {
- execute_binding_command(keyboard->seat, keyboard->input, command);
-}
-
-/**
- * Execute a built-in, hardcoded compositor binding. These are triggered from a
- * single keysym.
- *
- * Returns true if the keysym was handled by a binding and false if the event
- * should be propagated to clients.
- */
-static bool keyboard_execute_compositor_binding(struct roots_keyboard *keyboard,
- xkb_keysym_t keysym) {
- if (keysym >= XKB_KEY_XF86Switch_VT_1 &&
- keysym <= XKB_KEY_XF86Switch_VT_12) {
- struct roots_server *server = keyboard->input->server;
-
- struct wlr_session *session = wlr_backend_get_session(server->backend);
- if (session) {
- unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
- wlr_session_change_vt(session, vt);
- }
-
- return true;
- }
-
- if (keysym == XKB_KEY_Escape) {
- wlr_seat_pointer_end_grab(keyboard->seat->seat);
- wlr_seat_keyboard_end_grab(keyboard->seat->seat);
- roots_seat_end_compositor_grab(keyboard->seat);
- }
-
- return false;
-}
-
-/**
- * Execute keyboard bindings. These include compositor bindings and user-defined
- * bindings.
- *
- * Returns true if the keysym was handled by a binding and false if the event
- * should be propagated to clients.
- */
-static bool keyboard_execute_binding(struct roots_keyboard *keyboard,
- xkb_keysym_t *pressed_keysyms, uint32_t modifiers,
- const xkb_keysym_t *keysyms, size_t keysyms_len) {
- for (size_t i = 0; i < keysyms_len; ++i) {
- if (keyboard_execute_compositor_binding(keyboard, keysyms[i])) {
- return true;
- }
- }
-
- // User-defined bindings
- size_t n = pressed_keysyms_length(pressed_keysyms);
- struct wl_list *bindings = &keyboard->input->server->config->bindings;
- struct roots_binding_config *bc;
- wl_list_for_each(bc, bindings, link) {
- if (modifiers ^ bc->modifiers || n != bc->keysyms_len) {
- continue;
- }
-
- bool ok = true;
- for (size_t i = 0; i < bc->keysyms_len; i++) {
- ssize_t j = pressed_keysyms_index(pressed_keysyms, bc->keysyms[i]);
- if (j < 0) {
- ok = false;
- break;
- }
- }
-
- if (ok) {
- keyboard_binding_execute(keyboard, bc->command);
- return true;
- }
- }
-
- return false;
-}
-
-/*
- * Get keysyms and modifiers from the keyboard as xkb sees them.
- *
- * This uses the xkb keysyms translation based on pressed modifiers and clears
- * the consumed modifiers from the list of modifiers passed to keybind
- * detection.
- *
- * On US layout, pressing Alt+Shift+2 will trigger Alt+@.
- */
-static size_t keyboard_keysyms_translated(struct roots_keyboard *keyboard,
- xkb_keycode_t keycode, const xkb_keysym_t **keysyms,
- uint32_t *modifiers) {
- *modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
- xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods2(
- keyboard->device->keyboard->xkb_state, keycode, XKB_CONSUMED_MODE_XKB);
- *modifiers = *modifiers & ~consumed;
-
- return xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state,
- keycode, keysyms);
-}
-
-/*
- * Get keysyms and modifiers from the keyboard as if modifiers didn't change
- * keysyms.
- *
- * This avoids the xkb keysym translation based on modifiers considered pressed
- * in the state.
- *
- * This will trigger keybinds such as Alt+Shift+2.
- */
-static size_t keyboard_keysyms_raw(struct roots_keyboard *keyboard,
- xkb_keycode_t keycode, const xkb_keysym_t **keysyms,
- uint32_t *modifiers) {
- *modifiers = wlr_keyboard_get_modifiers(keyboard->device->keyboard);
-
- xkb_layout_index_t layout_index = xkb_state_key_get_layout(
- keyboard->device->keyboard->xkb_state, keycode);
- return xkb_keymap_key_get_syms_by_level(keyboard->device->keyboard->keymap,
- keycode, layout_index, 0, keysyms);
-}
-
-void roots_keyboard_handle_key(struct roots_keyboard *keyboard,
- struct wlr_event_keyboard_key *event) {
- xkb_keycode_t keycode = event->keycode + 8;
-
- bool handled = false;
- uint32_t modifiers;
- const xkb_keysym_t *keysyms;
- size_t keysyms_len;
-
- // Handle translated keysyms
-
- keysyms_len = keyboard_keysyms_translated(keyboard, keycode, &keysyms,
- &modifiers);
- pressed_keysyms_update(keyboard->pressed_keysyms_translated, keysyms,
- keysyms_len, event->state);
- if (event->state == WLR_KEY_PRESSED) {
- handled = keyboard_execute_binding(keyboard,
- keyboard->pressed_keysyms_translated, modifiers, keysyms,
- keysyms_len);
- }
-
- // Handle raw keysyms
- keysyms_len = keyboard_keysyms_raw(keyboard, keycode, &keysyms, &modifiers);
- pressed_keysyms_update(keyboard->pressed_keysyms_raw, keysyms, keysyms_len,
- event->state);
- if (event->state == WLR_KEY_PRESSED && !handled) {
- handled = keyboard_execute_binding(keyboard,
- keyboard->pressed_keysyms_raw, modifiers, keysyms, keysyms_len);
- }
-
- if (!handled) {
- wlr_seat_set_keyboard(keyboard->seat->seat, keyboard->device);
- wlr_seat_keyboard_notify_key(keyboard->seat->seat, event->time_msec,
- event->keycode, event->state);
- }
-}
-
-void roots_keyboard_handle_modifiers(struct roots_keyboard *r_keyboard) {
- struct wlr_seat *seat = r_keyboard->seat->seat;
- wlr_seat_set_keyboard(seat, r_keyboard->device);
- wlr_seat_keyboard_notify_modifiers(seat,
- &r_keyboard->device->keyboard->modifiers);
-}
-
-static void keyboard_config_merge(struct roots_keyboard_config *config,
- struct roots_keyboard_config *fallback) {
- if (fallback == NULL) {
- return;
- }
- if (config->rules == NULL) {
- config->rules = fallback->rules;
- }
- if (config->model == NULL) {
- config->model = fallback->model;
- }
- if (config->layout == NULL) {
- config->layout = fallback->layout;
- }
- if (config->variant == NULL) {
- config->variant = fallback->variant;
- }
- if (config->options == NULL) {
- config->options = fallback->options;
- }
- if (config->meta_key == 0) {
- config->meta_key = fallback->meta_key;
- }
- if (config->name == NULL) {
- config->name = fallback->name;
- }
- if (config->repeat_rate <= 0) {
- config->repeat_rate = fallback->repeat_rate;
- }
- if (config->repeat_delay <= 0) {
- config->repeat_delay = fallback->repeat_delay;
- }
-}
-
-struct roots_keyboard *roots_keyboard_create(struct wlr_input_device *device,
- struct roots_input *input) {
- struct roots_keyboard *keyboard = calloc(sizeof(struct roots_keyboard), 1);
- if (keyboard == NULL) {
- return NULL;
- }
- device->data = keyboard;
- keyboard->device = device;
- keyboard->input = input;
-
- struct roots_keyboard_config *config =
- calloc(1, sizeof(struct roots_keyboard_config));
- if (config == NULL) {
- free(keyboard);
- return NULL;
- }
- keyboard_config_merge(config, roots_config_get_keyboard(input->config, device));
- keyboard_config_merge(config, roots_config_get_keyboard(input->config, NULL));
-
- struct roots_keyboard_config env_config = {
- .rules = getenv("XKB_DEFAULT_RULES"),
- .model = getenv("XKB_DEFAULT_MODEL"),
- .layout = getenv("XKB_DEFAULT_LAYOUT"),
- .variant = getenv("XKB_DEFAULT_VARIANT"),
- .options = getenv("XKB_DEFAULT_OPTIONS"),
- };
- keyboard_config_merge(config, &env_config);
- keyboard->config = config;
-
- struct xkb_rule_names rules = { 0 };
- rules.rules = config->rules;
- rules.model = config->model;
- rules.layout = config->layout;
- rules.variant = config->variant;
- rules.options = config->options;
- struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
- if (context == NULL) {
- wlr_log(WLR_ERROR, "Cannot create XKB context");
- return NULL;
- }
-
- struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules,
- XKB_KEYMAP_COMPILE_NO_FLAGS);
- if (keymap == NULL) {
- xkb_context_unref(context);
- wlr_log(WLR_ERROR, "Cannot create XKB keymap");
- return NULL;
- }
-
- wlr_keyboard_set_keymap(device->keyboard, keymap);
- xkb_keymap_unref(keymap);
- xkb_context_unref(context);
-
- int repeat_rate = (config->repeat_rate > 0) ? config->repeat_rate : 25;
- int repeat_delay = (config->repeat_delay > 0) ? config->repeat_delay : 600;
- wlr_keyboard_set_repeat_info(device->keyboard, repeat_rate, repeat_delay);
-
- return keyboard;
-}
-
-void roots_keyboard_destroy(struct roots_keyboard *keyboard) {
- wl_list_remove(&keyboard->link);
- free(keyboard->config);
- free(keyboard);
-}
diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c
deleted file mode 100644
index 278046a3..00000000
--- a/rootston/layer_shell.c
+++ /dev/null
@@ -1,506 +0,0 @@
-#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 200112L
-#endif
-#include <assert.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <wayland-server-core.h>
-#include <wlr/types/wlr_box.h>
-#include <wlr/types/wlr_surface.h>
-#include <wlr/types/wlr_layer_shell_v1.h>
-#include <wlr/util/log.h>
-#include "rootston/desktop.h"
-#include "rootston/layers.h"
-#include "rootston/output.h"
-#include "rootston/server.h"
-
-static void apply_exclusive(struct wlr_box *usable_area,
- uint32_t anchor, int32_t exclusive,
- int32_t margin_top, int32_t margin_right,
- int32_t margin_bottom, int32_t margin_left) {
- if (exclusive <= 0) {
- return;
- }
- struct {
- uint32_t anchors;
- int *positive_axis;
- int *negative_axis;
- int margin;
- } edges[] = {
- {
- .anchors =
- ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP,
- .positive_axis = &usable_area->y,
- .negative_axis = &usable_area->height,
- .margin = margin_top,
- },
- {
- .anchors =
- ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
- .positive_axis = NULL,
- .negative_axis = &usable_area->height,
- .margin = margin_bottom,
- },
- {
- .anchors =
- ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
- .positive_axis = &usable_area->x,
- .negative_axis = &usable_area->width,
- .margin = margin_left,
- },
- {
- .anchors =
- ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
- ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM,
- .positive_axis = NULL,
- .negative_axis = &usable_area->width,
- .margin = margin_right,
- },
- };
- for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) {
- if ((anchor & edges[i].anchors) == edges[i].anchors) {
- if (edges[i].positive_axis) {
- *edges[i].positive_axis += exclusive + edges[i].margin;
- }
- if (edges[i].negative_axis) {
- *edges[i].negative_axis -= exclusive + edges[i].margin;
- }
- }
- }
-}
-
-static void update_cursors(struct roots_layer_surface *roots_surface,
- struct wl_list *seats /* struct roots_seat */) {
- struct roots_seat *seat;
- wl_list_for_each(seat, seats, link) {
- double sx, sy;
-
- struct wlr_surface *surface = desktop_surface_at(
- seat->input->server->desktop,
- seat->cursor->cursor->x, seat->cursor->cursor->y, &sx, &sy, NULL);
-
- if (surface == roots_surface->layer_surface->surface) {
- struct timespec time;
- if (clock_gettime(CLOCK_MONOTONIC, &time) == 0) {
- roots_cursor_update_position(seat->cursor,
- time.tv_sec * 1000 + time.tv_nsec / 1000000);
- } else {
- wlr_log(WLR_ERROR, "Failed to get time, not updating"
- "position. Errno: %s\n", strerror(errno));
- }
- }
- }
-}
-
-static void arrange_layer(struct wlr_output *output,
- struct wl_list *seats /* struct *roots_seat */,
- struct wl_list *list /* struct *roots_layer_surface */,
- struct wlr_box *usable_area, bool exclusive) {
- struct roots_layer_surface *roots_surface;
- struct wlr_box full_area = { 0 };
- wlr_output_effective_resolution(output,
- &full_area.width, &full_area.height);
- wl_list_for_each_reverse(roots_surface, list, link) {
- struct wlr_layer_surface_v1 *layer = roots_surface->layer_surface;
- struct wlr_layer_surface_v1_state *state = &layer->current;
- if (exclusive != (state->exclusive_zone > 0)) {
- continue;
- }
- struct wlr_box bounds;
- if (state->exclusive_zone == -1) {
- bounds = full_area;
- } else {
- bounds = *usable_area;
- }
- struct wlr_box box = {
- .width = state->desired_width,
- .height = state->desired_height
- };
- // Horizontal axis
- const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
- | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
- if ((state->anchor & both_horiz) && box.width == 0) {
- box.x = bounds.x;
- box.width = bounds.width;
- } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
- box.x = bounds.x;
- } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
- box.x = bounds.x + (bounds.width - box.width);
- } else {
- box.x = bounds.x + ((bounds.width / 2) - (box.width / 2));
- }
- // Vertical axis
- const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
- | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
- if ((state->anchor & both_vert) && box.height == 0) {
- box.y = bounds.y;
- box.height = bounds.height;
- } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
- box.y = bounds.y;
- } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
- box.y = bounds.y + (bounds.height - box.height);
- } else {
- box.y = bounds.y + ((bounds.height / 2) - (box.height / 2));
- }
- // Margin
- if ((state->anchor & both_horiz) == both_horiz) {
- box.x += state->margin.left;
- box.width -= state->margin.left + state->margin.right;
- } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
- box.x += state->margin.left;
- } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
- box.x -= state->margin.right;
- }
- if ((state->anchor & both_vert) == both_vert) {
- box.y += state->margin.top;
- box.height -= state->margin.top + state->margin.bottom;
- } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
- box.y += state->margin.top;
- } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
- box.y -= state->margin.bottom;
- }
- if (box.width < 0 || box.height < 0) {
- // TODO: Bubble up a protocol error?
- wlr_layer_surface_v1_close(layer);
- continue;
- }
-
- // Apply
- struct wlr_box old_geo = roots_surface->geo;
- roots_surface->geo = box;
- apply_exclusive(usable_area, state->anchor, state->exclusive_zone,
- state->margin.top, state->margin.right,
- state->margin.bottom, state->margin.left);
- wlr_layer_surface_v1_configure(layer, box.width, box.height);
-
- // Having a cursor newly end up over the moved layer will not
- // automatically send a motion event to the surface. The event needs to
- // be synthesized.
- // Only update layer surfaces which kept their size (and so buffers) the
- // same, because those with resized buffers will be handled separately.
-
- if (roots_surface->geo.x != old_geo.x
- || roots_surface->geo.y != old_geo.y) {
- update_cursors(roots_surface, seats);
- }
- }
-}
-
-void arrange_layers(struct roots_output *output) {
- struct wlr_box usable_area = { 0 };
- wlr_output_effective_resolution(output->wlr_output,
- &usable_area.width, &usable_area.height);
-
- // Arrange exclusive surfaces from top->bottom
- arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
- &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
- &usable_area, true);
- arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
- &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
- &usable_area, true);
- arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
- &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
- &usable_area, true);
- arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
- &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
- &usable_area, true);
- memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box));
-
- struct roots_view *view;
- wl_list_for_each(view, &output->desktop->views, link) {
- if (view->maximized) {
- view_arrange_maximized(view);
- }
- }
-
- // Arrange non-exlusive surfaces from top->bottom
- arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
- &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
- &usable_area, false);
- arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
- &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
- &usable_area, false);
- arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
- &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
- &usable_area, false);
- arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
- &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
- &usable_area, false);
-
- // Find topmost keyboard interactive layer, if such a layer exists
- uint32_t layers_above_shell[] = {
- ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
- ZWLR_LAYER_SHELL_V1_LAYER_TOP,
- };
- size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]);
- struct roots_layer_surface *layer, *topmost = NULL;
- for (size_t i = 0; i < nlayers; ++i) {
- wl_list_for_each_reverse(layer,
- &output->layers[layers_above_shell[i]], link) {
- if (layer->layer_surface->current.keyboard_interactive) {
- topmost = layer;
- break;
- }
- }
- if (topmost != NULL) {
- break;
- }
- }
-
- struct roots_input *input = output->desktop->server->input;
- struct roots_seat *seat;
- wl_list_for_each(seat, &input->seats, link) {
- roots_seat_set_focus_layer(seat,
- topmost ? topmost->layer_surface : NULL);
- }
-}
-
-static void handle_output_destroy(struct wl_listener *listener, void *data) {
- struct roots_layer_surface *layer =
- wl_container_of(listener, layer, output_destroy);
- layer->layer_surface->output = NULL;
- wl_list_remove(&layer->output_destroy.link);
- wlr_layer_surface_v1_close(layer->layer_surface);
-}
-
-static void handle_surface_commit(struct wl_listener *listener, void *data) {
- struct roots_layer_surface *layer =
- wl_container_of(listener, layer, surface_commit);
- struct wlr_layer_surface_v1 *layer_surface = layer->layer_surface;
- struct wlr_output *wlr_output = layer_surface->output;
- if (wlr_output != NULL) {
- struct roots_output *output = wlr_output->data;
- struct wlr_box old_geo = layer->geo;
- arrange_layers(output);
-
- // Cursor changes which happen as a consequence of resizing a layer
- // surface are applied in arrange_layers. Because the resize happens
- // before the underlying surface changes, it will only receive a cursor
- // update if the new cursor position crosses the *old* sized surface in
- // the *new* layer surface.
- // Another cursor move event is needed when the surface actually
- // changes.
- struct wlr_surface *surface = layer_surface->surface;
- if (surface->previous.width != surface->current.width ||
- surface->previous.height != surface->current.height) {
- update_cursors(layer, &output->desktop->server->input->seats);
- }
-
- if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) {
- output_damage_whole_local_surface(output, layer_surface->surface,
- old_geo.x, old_geo.y);
- output_damage_whole_local_surface(output, layer_surface->surface,
- layer->geo.x, layer->geo.y);
- } else {
- output_damage_from_local_surface(output, layer_surface->surface,
- layer->geo.x, layer->geo.y);
- }
- }
-}
-
-static void unmap(struct wlr_layer_surface_v1 *layer_surface) {
- struct roots_layer_surface *layer = layer_surface->data;
- struct wlr_output *wlr_output = layer_surface->output;
- if (wlr_output != NULL) {
- struct roots_output *output = wlr_output->data;
- output_damage_whole_local_surface(output, layer_surface->surface,
- layer->geo.x, layer->geo.y);
- }
-}
-
-static void handle_destroy(struct wl_listener *listener, void *data) {
- struct roots_layer_surface *layer = wl_container_of(
- listener, layer, destroy);
- if (layer->layer_surface->mapped) {
- unmap(layer->layer_surface);
- }
- wl_list_remove(&layer->link);
- wl_list_remove(&layer->destroy.link);
- wl_list_remove(&layer->map.link);
- wl_list_remove(&layer->unmap.link);
- wl_list_remove(&layer->surface_commit.link);
- if (layer->layer_surface->output) {
- wl_list_remove(&layer->output_destroy.link);
- arrange_layers((struct roots_output *)layer->layer_surface->output->data);
- }
- free(layer);
-}
-
-static void handle_map(struct wl_listener *listener, void *data) {
- struct wlr_layer_surface_v1 *layer_surface = data;
- struct roots_layer_surface *layer = layer_surface->data;
- struct wlr_output *wlr_output = layer_surface->output;
- struct roots_output *output = wlr_output->data;
- output_damage_whole_local_surface(output, layer_surface->surface,
- layer->geo.x, layer->geo.y);
- wlr_surface_send_enter(layer_surface->surface, wlr_output);
-}
-
-static void handle_unmap(struct wl_listener *listener, void *data) {
- struct roots_layer_surface *layer = wl_container_of(
- listener, layer, unmap);
- struct wlr_output *wlr_output = layer->layer_surface->output;
- struct roots_output *output = wlr_output->data;
- unmap(layer->layer_surface);
- input_update_cursor_focus(output->desktop->server->input);
-}
-
-static void popup_handle_map(struct wl_listener *listener, void *data) {
- struct roots_layer_popup *popup = wl_container_of(listener, popup, map);
- struct roots_layer_surface *layer = popup->parent;
- struct wlr_output *wlr_output = layer->layer_surface->output;
- struct roots_output *output = wlr_output->data;
- int ox = popup->wlr_popup->geometry.x + layer->geo.x;
- int oy = popup->wlr_popup->geometry.y + layer->geo.y;
- output_damage_whole_local_surface(output, popup->wlr_popup->base->surface,
- ox, oy);
- input_update_cursor_focus(output->desktop->server->input);
-}
-
-static void popup_handle_unmap(struct wl_listener *listener, void *data) {
- struct roots_layer_popup *popup = wl_container_of(listener, popup, unmap);
- struct roots_layer_surface *layer = popup->parent;
- struct wlr_output *wlr_output = layer->layer_surface->output;
- struct roots_output *output = wlr_output->data;
- int ox = popup->wlr_popup->geometry.x + layer->geo.x;
- int oy = popup->wlr_popup->geometry.y + layer->geo.y;
- output_damage_whole_local_surface(output, popup->wlr_popup->base->surface,
- ox, oy);
-}
-
-static void popup_handle_commit(struct wl_listener *listener, void *data) {
- struct roots_layer_popup *popup = wl_container_of(listener, popup, commit);
- struct roots_layer_surface *layer = popup->parent;
- struct wlr_output *wlr_output = layer->layer_surface->output;
- struct roots_output *output = wlr_output->data;
- int ox = popup->wlr_popup->geometry.x + layer->geo.x;
- int oy = popup->wlr_popup->geometry.y + layer->geo.y;
- output_damage_from_local_surface(output, popup->wlr_popup->base->surface,
- ox, oy);
-}
-
-static void popup_handle_destroy(struct wl_listener *listener, void *data) {
- struct roots_layer_popup *popup =
- wl_container_of(listener, popup, destroy);
-
- wl_list_remove(&popup->map.link);
- wl_list_remove(&popup->unmap.link);
- wl_list_remove(&popup->destroy.link);
- wl_list_remove(&popup->commit.link);
- free(popup);
-}
-
-static struct roots_layer_popup *popup_create(struct roots_layer_surface *parent,
- struct wlr_xdg_popup *wlr_popup) {
- struct roots_layer_popup *popup =
- calloc(1, sizeof(struct roots_layer_popup));
- if (popup == NULL) {
- return NULL;
- }
- popup->wlr_popup = wlr_popup;
- popup->parent = parent;
- popup->map.notify = popup_handle_map;
- wl_signal_add(&wlr_popup->base->events.map, &popup->map);
- popup->unmap.notify = popup_handle_unmap;
- wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
- popup->destroy.notify = popup_handle_destroy;
- wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
- popup->commit.notify = popup_handle_commit;
- wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
- /* TODO: popups can have popups, see xdg_shell::popup_create */
-
- return popup;
-}
-
-static void handle_new_popup(struct wl_listener *listener, void *data) {
- struct roots_layer_surface *roots_layer_surface =
- wl_container_of(listener, roots_layer_surface, new_popup);
- struct wlr_xdg_popup *wlr_popup = data;
- popup_create(roots_layer_surface, wlr_popup);
-}
-
-void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
- struct wlr_layer_surface_v1 *layer_surface = data;
- struct roots_desktop *desktop =
- wl_container_of(listener, desktop, layer_shell_surface);
- wlr_log(WLR_DEBUG, "new layer surface: namespace %s layer %d anchor %d "
- "size %dx%d margin %d,%d,%d,%d",
- layer_surface->namespace, layer_surface->layer, layer_surface->layer,
- layer_surface->client_pending.desired_width,
- layer_surface->client_pending.desired_height,
- layer_surface->client_pending.margin.top,
- layer_surface->client_pending.margin.right,
- layer_surface->client_pending.margin.bottom,
- layer_surface->client_pending.margin.left);
-
- if (!layer_surface->output) {
- struct roots_input *input = desktop->server->input;
- struct roots_seat *seat = input_last_active_seat(input);
- assert(seat); // Technically speaking we should handle this case
- struct wlr_output *output =
- wlr_output_layout_output_at(desktop->layout,
- seat->cursor->cursor->x,
- seat->cursor->cursor->y);
- if (!output) {
- wlr_log(WLR_ERROR, "Couldn't find output at (%.0f,%.0f)",
- seat->cursor->cursor->x,
- seat->cursor->cursor->y);
- output = wlr_output_layout_get_center_output(desktop->layout);
- }
- if (output) {
- layer_surface->output = output;
- } else {
- wlr_layer_surface_v1_close(layer_surface);
- return;
- }
- }
-
- struct roots_layer_surface *roots_surface =
- calloc(1, sizeof(struct roots_layer_surface));
- if (!roots_surface) {
- return;
- }
-
- roots_surface->surface_commit.notify = handle_surface_commit;
- wl_signal_add(&layer_surface->surface->events.commit,
- &roots_surface->surface_commit);
-
- roots_surface->output_destroy.notify = handle_output_destroy;
- wl_signal_add(&layer_surface->output->events.destroy,
- &roots_surface->output_destroy);
-
- roots_surface->destroy.notify = handle_destroy;
- wl_signal_add(&layer_surface->events.destroy, &roots_surface->destroy);
- roots_surface->map.notify = handle_map;
- wl_signal_add(&layer_surface->events.map, &roots_surface->map);
- roots_surface->unmap.notify = handle_unmap;
- wl_signal_add(&layer_surface->events.unmap, &roots_surface->unmap);
- roots_surface->new_popup.notify = handle_new_popup;
- wl_signal_add(&layer_surface->events.new_popup, &roots_surface->new_popup);
- // TODO: Listen for subsurfaces
-
- roots_surface->layer_surface = layer_surface;
- layer_surface->data = roots_surface;
-
- struct roots_output *output = layer_surface->output->data;
- wl_list_insert(&output->layers[layer_surface->layer], &roots_surface->link);
-
- // Temporarily set the layer's current state to client_pending
- // So that we can easily arrange it
- struct wlr_layer_surface_v1_state old_state = layer_surface->current;
- layer_surface->current = layer_surface->client_pending;
-
- arrange_layers(output);
-
- layer_surface->current = old_state;
-}
diff --git a/rootston/main.c b/rootston/main.c
deleted file mode 100644
index 350906e3..00000000
--- a/rootston/main.c
+++ /dev/null
@@ -1,83 +0,0 @@
-#define _POSIX_C_SOURCE 200112L
-#include <assert.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <wayland-server-core.h>
-#include <wlr/backend.h>
-#include <wlr/backend/headless.h>
-#include <wlr/backend/multi.h>
-#include <wlr/config.h>
-#include <wlr/render/wlr_renderer.h>
-#include <wlr/util/log.h>
-#include "rootston/config.h"
-#include "rootston/server.h"
-
-struct roots_server server = { 0 };
-
-int main(int argc, char **argv) {
- wlr_log_init(WLR_DEBUG, NULL);
- server.config = roots_config_create_from_args(argc, argv);
- server.wl_display = wl_display_create();
- server.wl_event_loop = wl_display_get_event_loop(server.wl_display);
- assert(server.config && server.wl_display && server.wl_event_loop);
-
- server.backend = wlr_backend_autocreate(server.wl_display, NULL);
- if (server.backend == NULL) {
- wlr_log(WLR_ERROR, "could not start backend");
- return 1;
- }
-
- server.renderer = wlr_backend_get_renderer(server.backend);
- assert(server.renderer);
- server.data_device_manager =
- wlr_data_device_manager_create(server.wl_display);
- wlr_renderer_init_wl_display(server.renderer, server.wl_display);
- server.desktop = desktop_create(&server, server.config);
- server.input = input_create(&server, server.config);
-
- const char *socket = wl_display_add_socket_auto(server.wl_display);
- if (!socket) {
- wlr_log_errno(WLR_ERROR, "Unable to open wayland socket");
- wlr_backend_destroy(server.backend);
- return 1;
- }
-
- wlr_log(WLR_INFO, "Running compositor on wayland display '%s'", socket);
- setenv("_WAYLAND_DISPLAY", socket, true);
-
- if (!wlr_backend_start(server.backend)) {
- wlr_log(WLR_ERROR, "Failed to start backend");
- wlr_backend_destroy(server.backend);
- wl_display_destroy(server.wl_display);
- return 1;
- }
-
- setenv("WAYLAND_DISPLAY", socket, true);
-#if WLR_HAS_XWAYLAND
- if (server.desktop->xwayland != NULL) {
- struct roots_seat *xwayland_seat =
- input_get_seat(server.input, ROOTS_CONFIG_DEFAULT_SEAT_NAME);
- wlr_xwayland_set_seat(server.desktop->xwayland, xwayland_seat->seat);
- }
-#endif
-
- if (server.config->startup_cmd != NULL) {
- const char *cmd = server.config->startup_cmd;
- pid_t pid = fork();
- if (pid < 0) {
- wlr_log(WLR_ERROR, "cannot execute binding command: fork() failed");
- } else if (pid == 0) {
- execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL);
- }
- }
-
- wl_display_run(server.wl_display);
-#if WLR_HAS_XWAYLAND
- // We need to shutdown Xwayland before disconnecting all clients, otherwise
- // wlroots will restart it automatically.
- wlr_xwayland_destroy(server.desktop->xwayland);
-#endif
- wl_display_destroy_clients(server.wl_display);
- wl_display_destroy(server.wl_display);
- return 0;
-}
diff --git a/rootston/meson.build b/rootston/meson.build
deleted file mode 100644
index 853fecc8..00000000
--- a/rootston/meson.build
+++ /dev/null
@@ -1,31 +0,0 @@
-sources = [
- 'bindings.c',
- 'config.c',
- 'cursor.c',
- 'desktop.c',
- 'ini.c',
- 'input.c',
- 'keyboard.c',
- 'layer_shell.c',
- 'main.c',
- 'output.c',
- 'render.c',
- 'seat.c',
- 'switch.c',
- 'text_input.c',
- 'view.c',
- 'virtual_keyboard.c',
- 'xdg_shell_v6.c',
- 'xdg_shell.c',
-]
-
-if conf_data.get('WLR_HAS_XWAYLAND', 0) == 1
- sources += 'xwayland.c'
-endif
-
-executable(
- 'rootston',
- sources,
- dependencies: [wlroots, wlr_protos, pixman],
- build_by_default: get_option('rootston'),
-)
diff --git a/rootston/output.c b/rootston/output.c
deleted file mode 100644
index 66a43694..00000000
--- a/rootston/output.c
+++ /dev/null
@@ -1,688 +0,0 @@
-#define _POSIX_C_SOURCE 200809L
-#include <assert.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <time.h>
-#include <wlr/backend/drm.h>
-#include <wlr/config.h>
-#include <wlr/types/wlr_compositor.h>
-#include <wlr/types/wlr_output_layout.h>
-#include <wlr/types/wlr_presentation_time.h>
-#include <wlr/types/wlr_xdg_shell_v6.h>
-#include <wlr/types/wlr_xdg_shell.h>
-#include <wlr/util/log.h>
-#include <wlr/util/region.h>
-#include "rootston/config.h"
-#include "rootston/layers.h"
-#include "rootston/output.h"
-#include "rootston/server.h"
-
-/**
- * Rotate a child's position relative to a parent. The parent size is (pw, ph),
- * the child position is (*sx, *sy) and its size is (sw, sh).
- */
-void rotate_child_position(double *sx, double *sy, double sw, double sh,
- double pw, double ph, float rotation) {
- if (rotation == 0.0) {
- return;
- }
-
- // Coordinates relative to the center of the subsurface
- double cx = *sx - pw/2 + sw/2,
- cy = *sy - ph/2 + sh/2;
- // Rotated coordinates
- double rx = cos(rotation)*cx - sin(rotation)*cy,
- ry = cos(rotation)*cy + sin(rotation)*cx;
- *sx = rx + pw/2 - sw/2;
- *sy = ry + ph/2 - sh/2;
-}
-
-struct surface_iterator_data {
- roots_surface_iterator_func_t user_iterator;
- void *user_data;
-
- struct roots_output *output;
- double ox, oy;
- int width, height;
- float rotation;
-};
-
-static bool get_surface_box(struct surface_iterator_data *data,
- struct wlr_surface *surface, int sx, int sy,
- struct wlr_box *surface_box) {
- struct roots_output *output = data->output;
-
- if (!wlr_surface_has_buffer(surface)) {
- return false;
- }
-
- int sw = surface->current.width;
- int sh = surface->current.height;
-
- double _sx = sx + surface->sx;
- double _sy = sy + surface->sy;
- rotate_child_position(&_sx, &_sy, sw, sh, data->width, data->height,
- data->rotation);
-
- struct wlr_box box = {
- .x = data->ox + _sx,
- .y = data->oy + _sy,
- .width = sw,
- .height = sh,
- };
- if (surface_box != NULL) {
- *surface_box = box;
- }
-
- struct wlr_box rotated_box;
- wlr_box_rotated_bounds(&rotated_box, &box, data->rotation);
-
- struct wlr_box output_box = {0};
- wlr_output_effective_resolution(output->wlr_output,
- &output_box.width, &output_box.height);
-
- struct wlr_box intersection;
- return wlr_box_intersection(&intersection, &output_box, &rotated_box);
-}
-
-static void output_for_each_surface_iterator(struct wlr_surface *surface,
- int sx, int sy, void *_data) {
- struct surface_iterator_data *data = _data;
-
- struct wlr_box box;
- bool intersects = get_surface_box(data, surface, sx, sy, &box);
- if (!intersects) {
- return;
- }
-
- data->user_iterator(data->output, surface, &box, data->rotation,
- data->user_data);
-}
-
-void output_surface_for_each_surface(struct roots_output *output,
- struct wlr_surface *surface, double ox, double oy,
- roots_surface_iterator_func_t iterator, void *user_data) {
- struct surface_iterator_data data = {
- .user_iterator = iterator,
- .user_data = user_data,
- .output = output,
- .ox = ox,
- .oy = oy,
- .width = surface->current.width,
- .height = surface->current.height,
- .rotation = 0,
- };
-
- wlr_surface_for_each_surface(surface,
- output_for_each_surface_iterator, &data);
-}
-
-void output_view_for_each_surface(struct roots_output *output,
- struct roots_view *view, roots_surface_iterator_func_t iterator,
- void *user_data) {
- struct wlr_box *output_box =
- wlr_output_layout_get_box(output->desktop->layout, output->wlr_output);
- if (!output_box) {
- return;
- }
-
- struct surface_iterator_data data = {
- .user_iterator = iterator,
- .user_data = user_data,
- .output = output,
- .ox = view->box.x - output_box->x,
- .oy = view->box.y - output_box->y,
- .width = view->box.width,
- .height = view->box.height,
- .rotation = view->rotation,
- };
-
- view_for_each_surface(view, output_for_each_surface_iterator, &data);
-}
-
-#if WLR_HAS_XWAYLAND
-void output_xwayland_children_for_each_surface(
- struct roots_output *output, struct wlr_xwayland_surface *surface,
- roots_surface_iterator_func_t iterator, void *user_data) {
- struct wlr_box *output_box =
- wlr_output_layout_get_box(output->desktop->layout, output->wlr_output);
- if (!output_box) {
- return;
- }
-
- struct wlr_xwayland_surface *child;
- wl_list_for_each(child, &surface->children, parent_link) {
- if (child->mapped) {
- double ox = child->x - output_box->x;
- double oy = child->y - output_box->y;
- output_surface_for_each_surface(output, child->surface,
- ox, oy, iterator, user_data);
- }
- output_xwayland_children_for_each_surface(output, child,
- iterator, user_data);
- }
-}
-#endif
-
-void output_layer_for_each_surface(struct roots_output *output,
- struct wl_list *layer_surfaces, roots_surface_iterator_func_t iterator,
- void *user_data) {
- struct roots_layer_surface *layer_surface;
- wl_list_for_each(layer_surface, layer_surfaces, link) {
- struct wlr_layer_surface_v1 *wlr_layer_surface_v1 =
- layer_surface->layer_surface;
- output_surface_for_each_surface(output, wlr_layer_surface_v1->surface,
- layer_surface->geo.x, layer_surface->geo.y, iterator,
- user_data);
-
- struct wlr_xdg_popup *state;
- wl_list_for_each(state, &wlr_layer_surface_v1->popups, link) {
- struct wlr_xdg_surface *popup = state->base;
- if (!popup->configured) {
- continue;
- }
-
- double popup_sx, popup_sy;
- popup_sx = layer_surface->geo.x;
- popup_sx += popup->popup->geometry.x - popup->geometry.x;
- popup_sy = layer_surface->geo.y;
- popup_sy += popup->popup->geometry.y - popup->geometry.y;
-
- output_surface_for_each_surface(output, popup->surface,
- popup_sx, popup_sy, iterator, user_data);
- }
- }
-}
-
-void output_drag_icons_for_each_surface(struct roots_output *output,
- struct roots_input *input, roots_surface_iterator_func_t iterator,
- void *user_data) {
- struct wlr_box *output_box =
- wlr_output_layout_get_box(output->desktop->layout, output->wlr_output);
- if (!output_box) {
- return;
- }
-
- struct roots_seat *seat;
- wl_list_for_each(seat, &input->seats, link) {
- struct roots_drag_icon *drag_icon = seat->drag_icon;
- if (!drag_icon || !drag_icon->wlr_drag_icon->mapped) {
- continue;
- }
-
- double ox = drag_icon->x - output_box->x;
- double oy = drag_icon->y - output_box->y;
- output_surface_for_each_surface(output,
- drag_icon->wlr_drag_icon->surface, ox, oy, iterator, user_data);
- }
-}
-
-void output_for_each_surface(struct roots_output *output,
- roots_surface_iterator_func_t iterator, void *user_data) {
- struct roots_desktop *desktop = output->desktop;
-
- if (output->fullscreen_view != NULL) {
- struct roots_view *view = output->fullscreen_view;
-
- output_view_for_each_surface(output, view, iterator, user_data);
-
-#if WLR_HAS_XWAYLAND
- if (view->type == ROOTS_XWAYLAND_VIEW) {
- struct roots_xwayland_surface *xwayland_surface =
- roots_xwayland_surface_from_view(view);
- output_xwayland_children_for_each_surface(output,
- xwayland_surface->xwayland_surface, iterator, user_data);
- }
-#endif
- } else {
- struct roots_view *view;
- wl_list_for_each_reverse(view, &desktop->views, link) {
- output_view_for_each_surface(output, view, iterator, user_data);
- }
- }
-
- output_drag_icons_for_each_surface(output, desktop->server->input,
- iterator, user_data);
-
- size_t len = sizeof(output->layers) / sizeof(output->layers[0]);
- for (size_t i = 0; i < len; ++i) {
- output_layer_for_each_surface(output, &output->layers[i],
- iterator, user_data);
- }
-}
-
-static int scale_length(int length, int offset, float scale) {
- return round((offset + length) * scale) - round(offset * scale);
-}
-
-void scale_box(struct wlr_box *box, float scale) {
- box->width = scale_length(box->width, box->x, scale);
- box->height = scale_length(box->height, box->y, scale);
- box->x = round(box->x * scale);
- box->y = round(box->y * scale);
-}
-
-void get_decoration_box(struct roots_view *view,
- struct roots_output *output, struct wlr_box *box) {
- struct wlr_output *wlr_output = output->wlr_output;
-
- struct wlr_box deco_box;
- view_get_deco_box(view, &deco_box);
- double sx = deco_box.x - view->box.x;
- double sy = deco_box.y - view->box.y;
- rotate_child_position(&sx, &sy, deco_box.width, deco_box.height,
- view->wlr_surface->current.width,
- view->wlr_surface->current.height, view->rotation);
- double x = sx + view->box.x;
- double y = sy + view->box.y;
-
- wlr_output_layout_output_coords(output->desktop->layout, wlr_output, &x, &y);
-
- box->x = x * wlr_output->scale;
- box->y = y * wlr_output->scale;
- box->width = deco_box.width * wlr_output->scale;
- box->height = deco_box.height * wlr_output->scale;
-}
-
-void output_damage_whole(struct roots_output *output) {
- wlr_output_damage_add_whole(output->damage);
-}
-
-static bool view_accept_damage(struct roots_output *output,
- struct roots_view *view) {
- if (view->wlr_surface == NULL) {
- return false;
- }
- if (output->fullscreen_view == NULL) {
- return true;
- }
- if (output->fullscreen_view == view) {
- return true;
- }
-#if WLR_HAS_XWAYLAND
- if (output->fullscreen_view->type == ROOTS_XWAYLAND_VIEW &&
- view->type == ROOTS_XWAYLAND_VIEW) {
- // Special case: accept damage from children
- struct wlr_xwayland_surface *xsurface =
- roots_xwayland_surface_from_view(view)->xwayland_surface;
- struct wlr_xwayland_surface *fullscreen_xsurface =
- roots_xwayland_surface_from_view(output->fullscreen_view)->xwayland_surface;
- while (xsurface != NULL) {
- if (fullscreen_xsurface == xsurface) {
- return true;
- }
- xsurface = xsurface->parent;
- }
- }
-#endif
- return false;
-}
-
-static void damage_surface_iterator(struct roots_output *output,
- struct wlr_surface *surface, struct wlr_box *_box, float rotation,
- void *data) {
- bool *whole = data;
-
- struct wlr_box box = *_box;
- scale_box(&box, output->wlr_output->scale);
-
- int center_x = box.x + box.width/2;
- int center_y = box.y + box.height/2;
-
- if (pixman_region32_not_empty(&surface->buffer_damage)) {
- pixman_region32_t damage;
- pixman_region32_init(&damage);
- wlr_surface_get_effective_damage(surface, &damage);
- wlr_region_scale(&damage, &damage, output->wlr_output->scale);
- if (ceil(output->wlr_output->scale) > surface->current.scale) {
- // When scaling up a surface, it'll become blurry so we need to
- // expand the damage region
- wlr_region_expand(&damage, &damage,
- ceil(output->wlr_output->scale) - surface->current.scale);
- }
- pixman_region32_translate(&damage, box.x, box.y);
- wlr_region_rotated_bounds(&damage, &damage, rotation,
- center_x, center_y);
- wlr_output_damage_add(output->damage, &damage);
- pixman_region32_fini(&damage);
- }
-
- if (*whole) {
- wlr_box_rotated_bounds(&box, &box, rotation);
- wlr_output_damage_add_box(output->damage, &box);
- }
-
- wlr_output_schedule_frame(output->wlr_output);
-}
-
-void output_damage_whole_local_surface(struct roots_output *output,
- struct wlr_surface *surface, double ox, double oy) {
- bool whole = true;
- output_surface_for_each_surface(output, surface, ox, oy,
- damage_surface_iterator, &whole);
-}
-
-static void damage_whole_decoration(struct roots_view *view,
- struct roots_output *output) {
- if (!view->decorated || view->wlr_surface == NULL) {
- return;
- }
-
- struct wlr_box box;
- get_decoration_box(view, output, &box);
-
- wlr_box_rotated_bounds(&box, &box, view->rotation);
-
- wlr_output_damage_add_box(output->damage, &box);
-}
-
-void output_damage_whole_view(struct roots_output *output,
- struct roots_view *view) {
- if (!view_accept_damage(output, view)) {
- return;
- }
-
- damage_whole_decoration(view, output);
-
- bool whole = true;
- output_view_for_each_surface(output, view, damage_surface_iterator, &whole);
-}
-
-void output_damage_whole_drag_icon(struct roots_output *output,
- struct roots_drag_icon *icon) {
- bool whole = true;
- output_surface_for_each_surface(output, icon->wlr_drag_icon->surface,
- icon->x, icon->y, damage_surface_iterator, &whole);
-}
-
-void output_damage_from_local_surface(struct roots_output *output,
- struct wlr_surface *surface, double ox, double oy) {
- bool whole = false;
- output_surface_for_each_surface(output, surface, ox, oy,
- damage_surface_iterator, &whole);
-}
-
-void output_damage_from_view(struct roots_output *output,
- struct roots_view *view) {
- if (!view_accept_damage(output, view)) {
- return;
- }
-
- bool whole = false;
- output_view_for_each_surface(output, view, damage_surface_iterator, &whole);
-}
-
-static void set_mode(struct wlr_output *output,
- struct roots_output_config *oc) {
- int mhz = (int)(oc->mode.refresh_rate * 1000);
-
- if (wl_list_empty(&output->modes)) {
- // Output has no mode, try setting a custom one
- wlr_output_set_custom_mode(output, oc->mode.width, oc->mode.height, mhz);
- return;
- }
-
- struct wlr_output_mode *mode, *best = NULL;
- wl_list_for_each(mode, &output->modes, link) {
- if (mode->width == oc->mode.width && mode->height == oc->mode.height) {
- if (mode->refresh == mhz) {
- best = mode;
- break;
- }
- best = mode;
- }
- }
- if (!best) {
- wlr_log(WLR_ERROR, "Configured mode for %s not available", output->name);
- } else {
- wlr_log(WLR_DEBUG, "Assigning configured mode to %s", output->name);
- wlr_output_set_mode(output, best);
- }
-}
-
-static void update_output_manager_config(struct roots_desktop *desktop) {
- struct wlr_output_configuration_v1 *config =
- wlr_output_configuration_v1_create();
-
- struct roots_output *output;
- wl_list_for_each(output, &desktop->outputs, link) {
- struct wlr_output_configuration_head_v1 *config_head =
- wlr_output_configuration_head_v1_create(config, output->wlr_output);
- struct wlr_box *output_box = wlr_output_layout_get_box(
- output->desktop->layout, output->wlr_output);
- if (output_box) {
- config_head->state.x = output_box->x;
- config_head->state.y = output_box->y;
- }
- }
-
- wlr_output_manager_v1_set_configuration(desktop->output_manager_v1, config);
-}
-
-void handle_output_manager_apply(struct wl_listener *listener, void *data) {
- struct roots_desktop *desktop =
- wl_container_of(listener, desktop, output_manager_apply);
- struct wlr_output_configuration_v1 *config = data;
-
- bool ok = true;
- struct wlr_output_configuration_head_v1 *config_head;
- // First disable outputs we need to disable
- wl_list_for_each(config_head, &config->heads, link) {
- struct wlr_output *wlr_output = config_head->state.output;
- if (!config_head->state.enabled) {
- ok &= wlr_output_enable(wlr_output, false);
- wlr_output_layout_remove(desktop->layout, wlr_output);
- }
- }
-
- // Then enable outputs that need to
- wl_list_for_each(config_head, &config->heads, link) {
- struct wlr_output *wlr_output = config_head->state.output;
- if (!config_head->state.enabled) {
- continue;
- }
- ok &= wlr_output_enable(wlr_output, true);
- if (config_head->state.mode != NULL) {
- ok &= wlr_output_set_mode(wlr_output, config_head->state.mode);
- } else {
- ok &= wlr_output_set_custom_mode(wlr_output,
- config_head->state.custom_mode.width,
- config_head->state.custom_mode.height,
- config_head->state.custom_mode.refresh);
- }
- wlr_output_layout_add(desktop->layout, wlr_output,
- config_head->state.x, config_head->state.y);
- wlr_output_set_transform(wlr_output, config_head->state.transform);
- wlr_output_set_scale(wlr_output, config_head->state.scale);
- }
-
- if (ok) {
- wlr_output_configuration_v1_send_succeeded(config);
- } else {
- wlr_output_configuration_v1_send_failed(config);
- }
- wlr_output_configuration_v1_destroy(config);
-
- update_output_manager_config(desktop);
-}
-
-void handle_output_manager_test(struct wl_listener *listener, void *data) {
- struct roots_desktop *desktop =
- wl_container_of(listener, desktop, output_manager_test);
- struct wlr_output_configuration_v1 *config = data;
-
- // TODO: implement test-only mode
- wlr_output_configuration_v1_send_succeeded(config);
- wlr_output_configuration_v1_destroy(config);
-}
-
-static void output_destroy(struct roots_output *output) {
- // TODO: cursor
- //example_config_configure_cursor(sample->config, sample->cursor,
- // sample->compositor);
-
- wl_list_remove(&output->link);
- wl_list_remove(&output->destroy.link);
- wl_list_remove(&output->enable.link);
- wl_list_remove(&output->mode.link);
- wl_list_remove(&output->transform.link);
- wl_list_remove(&output->present.link);
- wl_list_remove(&output->damage_frame.link);
- wl_list_remove(&output->damage_destroy.link);
- free(output);
-}
-
-static void output_handle_destroy(struct wl_listener *listener, void *data) {
- struct roots_output *output = wl_container_of(listener, output, destroy);
- struct roots_desktop *desktop = output->desktop;
- output_destroy(output);
- update_output_manager_config(desktop);
-}
-
-static void output_handle_enable(struct wl_listener *listener, void *data) {
- struct roots_output *output = wl_container_of(listener, output, enable);
- update_output_manager_config(output->desktop);
-}
-
-static void output_damage_handle_frame(struct wl_listener *listener,
- void *data) {
- struct roots_output *output =
- wl_container_of(listener, output, damage_frame);
- output_render(output);
-}
-
-static void output_damage_handle_destroy(struct wl_listener *listener,
- void *data) {
- struct roots_output *output =
- wl_container_of(listener, output, damage_destroy);
- output_destroy(output);
-}
-
-static void output_handle_mode(struct wl_listener *listener, void *data) {
- struct roots_output *output =
- wl_container_of(listener, output, mode);
- arrange_layers(output);
- update_output_manager_config(output->desktop);
-}
-
-static void output_handle_transform(struct wl_listener *listener, void *data) {
- struct roots_output *output =
- wl_container_of(listener, output, transform);
- arrange_layers(output);
-}
-
-static void surface_send_presented_iterator(struct roots_output *output,
- struct wlr_surface *surface, struct wlr_box *_box, float rotation,
- void *data) {
- struct wlr_presentation_event *event = data;
- wlr_presentation_send_surface_presented(output->desktop->presentation,
- surface, event);
-}
-
-static void output_handle_present(struct wl_listener *listener, void *data) {
- struct roots_output *output =
- wl_container_of(listener, output, present);
- struct wlr_output_event_present *output_event = data;
-
- struct wlr_presentation_event event = {
- .output = output->wlr_output,
- .tv_sec = (uint64_t)output_event->when->tv_sec,
- .tv_nsec = (uint32_t)output_event->when->tv_nsec,
- .refresh = (uint32_t)output_event->refresh,
- .seq = (uint64_t)output_event->seq,
- .flags = output_event->flags,
- };
-
- output_for_each_surface(output,
- surface_send_presented_iterator, &event);
-}
-
-void handle_new_output(struct wl_listener *listener, void *data) {
- struct roots_desktop *desktop = wl_container_of(listener, desktop,
- new_output);
- struct wlr_output *wlr_output = data;
- struct roots_input *input = desktop->server->input;
- struct roots_config *config = desktop->config;
-
- wlr_log(WLR_DEBUG, "Output '%s' added", wlr_output->name);
- wlr_log(WLR_DEBUG, "'%s %s %s' %"PRId32"mm x %"PRId32"mm", wlr_output->make,
- wlr_output->model, wlr_output->serial, wlr_output->phys_width,
- wlr_output->phys_height);
-
- struct roots_output *output = calloc(1, sizeof(struct roots_output));
- clock_gettime(CLOCK_MONOTONIC, &output->last_frame);
- output->desktop = desktop;
- output->wlr_output = wlr_output;
- wlr_output->data = output;
- wl_list_insert(&desktop->outputs, &output->link);
-
- output->damage = wlr_output_damage_create(wlr_output);
-
- output->destroy.notify = output_handle_destroy;
- wl_signal_add(&wlr_output->events.destroy, &output->destroy);
- output->enable.notify = output_handle_enable;
- wl_signal_add(&wlr_output->events.enable, &output->enable);
- output->mode.notify = output_handle_mode;
- wl_signal_add(&wlr_output->events.mode, &output->mode);
- output->transform.notify = output_handle_transform;
- wl_signal_add(&wlr_output->events.transform, &output->transform);
- output->present.notify = output_handle_present;
- wl_signal_add(&wlr_output->events.present, &output->present);
-
- output->damage_frame.notify = output_damage_handle_frame;
- wl_signal_add(&output->damage->events.frame, &output->damage_frame);
- output->damage_destroy.notify = output_damage_handle_destroy;
- wl_signal_add(&output->damage->events.destroy, &output->damage_destroy);
-
- size_t len = sizeof(output->layers) / sizeof(output->layers[0]);
- for (size_t i = 0; i < len; ++i) {
- wl_list_init(&output->layers[i]);
- }
-
- struct roots_output_config *output_config =
- roots_config_get_output(config, wlr_output);
-
- struct wlr_output_mode *preferred_mode =
- wlr_output_preferred_mode(wlr_output);
- if (output_config) {
- if (output_config->enable) {
- if (wlr_output_is_drm(wlr_output)) {
- struct roots_output_mode_config *mode_config;
- wl_list_for_each(mode_config, &output_config->modes, link) {
- wlr_drm_connector_add_mode(wlr_output, &mode_config->info);
- }
- } else if (!wl_list_empty(&output_config->modes)) {
- wlr_log(WLR_ERROR, "Can only add modes for DRM backend");
- }
-
- if (output_config->mode.width) {
- set_mode(wlr_output, output_config);
- } else if (preferred_mode != NULL) {
- wlr_output_set_mode(wlr_output, preferred_mode);
- }
-
- wlr_output_set_scale(wlr_output, output_config->scale);
- wlr_output_set_transform(wlr_output, output_config->transform);
- wlr_output_layout_add(desktop->layout, wlr_output, output_config->x,
- output_config->y);
- } else {
- wlr_output_enable(wlr_output, false);
- }
- } else {
- if (preferred_mode != NULL) {
- wlr_output_set_mode(wlr_output, preferred_mode);
- }
- wlr_output_layout_add_auto(desktop->layout, wlr_output);
- }
-
- struct roots_seat *seat;
- wl_list_for_each(seat, &input->seats, link) {
- roots_seat_configure_cursor(seat);
- roots_seat_configure_xcursor(seat);
- }
-
- arrange_layers(output);
- output_damage_whole(output);
-
- update_output_manager_config(desktop);
-}
diff --git a/rootston/render.c b/rootston/render.c
deleted file mode 100644
index 3b242b88..00000000
--- a/rootston/render.c
+++ /dev/null
@@ -1,422 +0,0 @@
-#define _POSIX_C_SOURCE 200809L
-#include <assert.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <time.h>
-#include <wlr/config.h>
-#include <wlr/types/wlr_compositor.h>
-#include <wlr/types/wlr_matrix.h>
-#include <wlr/types/wlr_buffer.h>
-#include <wlr/types/wlr_linux_dmabuf_v1.h>
-#include <wlr/util/log.h>
-#include <wlr/util/region.h>
-#include "rootston/layers.h"
-#include "rootston/output.h"
-#include "rootston/server.h"
-
-struct render_data {
- pixman_region32_t *damage;
- float alpha;
-};
-
-static void scissor_output(struct wlr_output *wlr_output,
- pixman_box32_t *rect) {
- struct wlr_renderer *renderer =
- wlr_backend_get_renderer(wlr_output->backend);
- assert(renderer);
-
- struct wlr_box box = {
- .x = rect->x1,
- .y = rect->y1,
- .width = rect->x2 - rect->x1,
- .height = rect->y2 - rect->y1,
- };
-
- int ow, oh;
- wlr_output_transformed_resolution(wlr_output, &ow, &oh);
-
- enum wl_output_transform transform =
- wlr_output_transform_invert(wlr_output->transform);
- wlr_box_transform(&box, &box, transform, ow, oh);
-
- wlr_renderer_scissor(renderer, &box);
-}
-
-static void render_texture(struct wlr_output *wlr_output,
- pixman_region32_t *output_damage, struct wlr_texture *texture,
- const struct wlr_box *box, const float matrix[static 9],
- float rotation, float alpha) {
- struct wlr_renderer *renderer =
- wlr_backend_get_renderer(wlr_output->backend);
- assert(renderer);
-
- struct wlr_box rotated;
- wlr_box_rotated_bounds(&rotated, box, rotation);
-
- pixman_region32_t damage;
- pixman_region32_init(&damage);
- pixman_region32_union_rect(&damage, &damage, rotated.x, rotated.y,
- rotated.width, rotated.height);
- pixman_region32_intersect(&damage, &damage, output_damage);
- bool damaged = pixman_region32_not_empty(&damage);
- if (!damaged) {
- goto buffer_damage_finish;
- }
-
- int nrects;
- pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
- for (int i = 0; i < nrects; ++i) {
- scissor_output(wlr_output, &rects[i]);
- wlr_render_texture_with_matrix(renderer, texture, matrix, alpha);
- }
-
-buffer_damage_finish:
- pixman_region32_fini(&damage);
-}
-
-static void render_surface_iterator(struct roots_output *output,
- struct wlr_surface *surface, struct wlr_box *_box, float rotation,
- void *_data) {
- struct render_data *data = _data;
- struct wlr_output *wlr_output = output->wlr_output;
- pixman_region32_t *output_damage = data->damage;
- float alpha = data->alpha;
-
- struct wlr_texture *texture = wlr_surface_get_texture(surface);
- if (!texture) {
- return;
- }
-
- struct wlr_box box = *_box;
- scale_box(&box, wlr_output->scale);
-
- float matrix[9];
- enum wl_output_transform transform =
- wlr_output_transform_invert(surface->current.transform);
- wlr_matrix_project_box(matrix, &box, transform, rotation,
- wlr_output->transform_matrix);
-
- render_texture(wlr_output, output_damage,
- texture, &box, matrix, rotation, alpha);
-}
-
-static void render_decorations(struct roots_output *output,
- struct roots_view *view, struct render_data *data) {
- if (!view->decorated || view->wlr_surface == NULL) {
- return;
- }
-
- struct wlr_renderer *renderer =
- wlr_backend_get_renderer(output->wlr_output->backend);
- assert(renderer);
-
- struct wlr_box box;
- get_decoration_box(view, output, &box);
-
- struct wlr_box rotated;
- wlr_box_rotated_bounds(&rotated, &box, view->rotation);
-
- pixman_region32_t damage;
- pixman_region32_init(&damage);
- pixman_region32_union_rect(&damage, &damage, rotated.x, rotated.y,
- rotated.width, rotated.height);
- pixman_region32_intersect(&damage, &damage, data->damage);
- bool damaged = pixman_region32_not_empty(&damage);
- if (!damaged) {
- goto buffer_damage_finish;
- }
-
- float matrix[9];
- wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL,
- view->rotation, output->wlr_output->transform_matrix);
- float color[] = { 0.2, 0.2, 0.2, view->alpha };
-
- int nrects;
- pixman_box32_t *rects =
- pixman_region32_rectangles(&damage, &nrects);
- for (int i = 0; i < nrects; ++i) {
- scissor_output(output->wlr_output, &rects[i]);
- wlr_render_quad_with_matrix(renderer, color, matrix);
- }
-
-buffer_damage_finish:
- pixman_region32_fini(&damage);
-}
-
-static void render_view(struct roots_output *output, struct roots_view *view,
- struct render_data *data) {
- // Do not render views fullscreened on other outputs
- if (view->fullscreen_output != NULL && view->fullscreen_output != output) {
- return;
- }
-
- data->alpha = view->alpha;
- if (view->fullscreen_output == NULL) {
- render_decorations(output, view, data);
- }
- output_view_for_each_surface(output, view, render_surface_iterator, data);
-}
-
-static void render_layer(struct roots_output *output,
- pixman_region32_t *damage, struct wl_list *layer_surfaces) {
- struct render_data data = {
- .damage = damage,
- .alpha = 1.0f,
- };
- output_layer_for_each_surface(output, layer_surfaces,
- render_surface_iterator, &data);
-}
-
-static void render_drag_icons(struct roots_output *output,
- pixman_region32_t *damage, struct roots_input *input) {
- struct render_data data = {
- .damage = damage,
- .alpha = 1.0f,
- };
- output_drag_icons_for_each_surface(output, input,
- render_surface_iterator, &data);
-}
-
-static void count_surface_iterator(struct roots_output *output,
- struct wlr_surface *surface, struct wlr_box *_box, float rotation,
- void *data) {
- size_t *n = data;
- n++;
-}
-
-static bool scan_out_fullscreen_view(struct roots_output *output) {
- struct wlr_output *wlr_output = output->wlr_output;
- struct roots_desktop *desktop = output->desktop;
-
- struct roots_seat *seat;
- wl_list_for_each(seat, &desktop->server->input->seats, link) {
- struct roots_drag_icon *drag_icon = seat->drag_icon;
- if (drag_icon && drag_icon->wlr_drag_icon->mapped) {
- return false;
- }
- }
-
- if (!wl_list_empty(&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY])) {
- return false;
- }
-
- struct wlr_output_cursor *cursor;
- wl_list_for_each(cursor, &wlr_output->cursors, link) {
- if (cursor->enabled && cursor->visible &&
- wlr_output->hardware_cursor != cursor) {
- return false;
- }
- }
-
- struct roots_view *view = output->fullscreen_view;
- assert(view != NULL);
- if (view->wlr_surface == NULL) {
- return false;
- }
- size_t n_surfaces = 0;
- output_view_for_each_surface(output, view,
- count_surface_iterator, &n_surfaces);
- if (n_surfaces > 1) {
- return false;
- }
-
-#if WLR_HAS_XWAYLAND
- if (view->type == ROOTS_XWAYLAND_VIEW) {
- struct roots_xwayland_surface *xwayland_surface =
- roots_xwayland_surface_from_view(view);
- if (!wl_list_empty(&xwayland_surface->xwayland_surface->children)) {
- return false;
- }
- }
-#endif
-
- struct wlr_surface *surface = view->wlr_surface;
-
- if (surface->buffer == NULL) {
- return false;
- }
-
- if ((float)surface->current.scale != wlr_output->scale ||
- surface->current.transform != wlr_output->transform) {
- return false;
- }
-
- if (!wlr_output_attach_buffer(wlr_output, surface->buffer)) {
- return false;
- }
- return wlr_output_commit(wlr_output);
-}
-
-static void surface_send_frame_done_iterator(struct roots_output *output,
- struct wlr_surface *surface, struct wlr_box *box, float rotation,
- void *data) {
- struct timespec *when = data;
- wlr_surface_send_frame_done(surface, when);
-}
-
-void output_render(struct roots_output *output) {
- struct wlr_output *wlr_output = output->wlr_output;
- struct roots_desktop *desktop = output->desktop;
- struct roots_server *server = desktop->server;
- struct wlr_renderer *renderer =
- wlr_backend_get_renderer(wlr_output->backend);
- assert(renderer);
-
- if (!wlr_output->enabled) {
- return;
- }
-
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
-
- float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
-
- const struct wlr_box *output_box =
- wlr_output_layout_get_box(desktop->layout, wlr_output);
-
- // Check if we can delegate the fullscreen surface to the output
- if (output->fullscreen_view != NULL &&
- output->fullscreen_view->wlr_surface != NULL) {
- struct roots_view *view = output->fullscreen_view;
-
- // Make sure the view is centered on screen
- struct wlr_box view_box;
- view_get_box(view, &view_box);
- double view_x = (double)(output_box->width - view_box.width) / 2 +
- output_box->x;
- double view_y = (double)(output_box->height - view_box.height) / 2 +
- output_box->y;
- view_move(view, view_x, view_y);
-
- // Fullscreen views are rendered on a black background
- clear_color[0] = clear_color[1] = clear_color[2] = 0;
-
- // Check if we can scan-out the fullscreen view
- static bool last_scanned_out = false;
- bool scanned_out = scan_out_fullscreen_view(output);
-
- if (scanned_out && !last_scanned_out) {
- wlr_log(WLR_DEBUG, "Scanning out fullscreen view");
- }
- if (last_scanned_out && !scanned_out) {
- wlr_log(WLR_DEBUG, "Stopping fullscreen view scan out");
- }
- last_scanned_out = scanned_out;
-
- if (scanned_out) {
- goto send_frame_done;
- }
- }
-
- bool needs_frame;
- pixman_region32_t buffer_damage;
- pixman_region32_init(&buffer_damage);
- if (!wlr_output_damage_attach_render(output->damage, &needs_frame,
- &buffer_damage)) {
- return;
- }
-
- struct render_data data = {
- .damage = &buffer_damage,
- .alpha = 1.0,
- };
-
- if (!needs_frame) {
- // Output doesn't need swap and isn't damaged, skip rendering completely
- goto buffer_damage_finish;
- }
-
- wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height);
-
- if (!pixman_region32_not_empty(&buffer_damage)) {
- // Output isn't damaged but needs buffer swap
- goto renderer_end;
- }
-
- if (server->config->debug_damage_tracking) {
- wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1});
- }
-
- int nrects;
- pixman_box32_t *rects = pixman_region32_rectangles(&buffer_damage, &nrects);
- for (int i = 0; i < nrects; ++i) {
- scissor_output(output->wlr_output, &rects[i]);
- wlr_renderer_clear(renderer, clear_color);
- }
-
- // If a view is fullscreen on this output, render it
- if (output->fullscreen_view != NULL) {
- struct roots_view *view = output->fullscreen_view;
- render_view(output, view, &data);
-
- // During normal rendering the xwayland window tree isn't traversed
- // because all windows are rendered. Here we only want to render
- // the fullscreen window's children so we have to traverse the tree.
-#if WLR_HAS_XWAYLAND
- if (view->type == ROOTS_XWAYLAND_VIEW) {
- struct roots_xwayland_surface *xwayland_surface =
- roots_xwayland_surface_from_view(view);
- output_xwayland_children_for_each_surface(output,
- xwayland_surface->xwayland_surface,
- render_surface_iterator, &data);
- }
-#endif
- } else {
- // Render background and bottom layers under views
- render_layer(output, &buffer_damage,
- &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]);
- render_layer(output, &buffer_damage,
- &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
-
- // Render all views
- struct roots_view *view;
- wl_list_for_each_reverse(view, &desktop->views, link) {
- render_view(output, view, &data);
- }
-
- // Render top layer above views
- render_layer(output, &buffer_damage,
- &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
- }
-
- render_drag_icons(output, &buffer_damage, server->input);
-
- render_layer(output, &buffer_damage,
- &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
-
-renderer_end:
- wlr_output_render_software_cursors(wlr_output, &buffer_damage);
- wlr_renderer_scissor(renderer, NULL);
- wlr_renderer_end(renderer);
-
- int width, height;
- wlr_output_transformed_resolution(wlr_output, &width, &height);
-
- pixman_region32_t frame_damage;
- pixman_region32_init(&frame_damage);
-
- enum wl_output_transform transform =
- wlr_output_transform_invert(wlr_output->transform);
- wlr_region_transform(&frame_damage, &output->damage->current,
- transform, width, height);
-
- if (server->config->debug_damage_tracking) {
- pixman_region32_union_rect(&frame_damage, &frame_damage,
- 0, 0, wlr_output->width, wlr_output->height);
- }
-
- wlr_output_set_damage(wlr_output, &frame_damage);
- pixman_region32_fini(&frame_damage);
-
- if (!wlr_output_commit(wlr_output)) {
- goto buffer_damage_finish;
- }
- output->last_frame = desktop->last_frame = now;
-
-buffer_damage_finish:
- pixman_region32_fini(&buffer_damage);
-
-send_frame_done:
- // Send frame done events to all surfaces
- output_for_each_surface(output, surface_send_frame_done_iterator, &now);
-}
diff --git a/rootston/rootston.ini.example b/rootston/rootston.ini.example
deleted file mode 100644
index 4b75e9c6..00000000
--- a/rootston/rootston.ini.example
+++ /dev/null
@@ -1,63 +0,0 @@
-[core]
-# X11 support
-# - true: enables X11, xwayland is started only when an X11 client connects
-# - immediate: enables X11, xwayland is started immediately
-# - false: disables xwayland
-xwayland=false
-
-# Single output configuration. String after colon must match output's name.
-[output:VGA-1]
-# Set logical (layout) coordinates for this screen
-x = 1920
-y = 0
-
-# Screen transformation
-# possible values are:
-# '90', '180' or '270' - rotate output by specified angle clockwise
-# 'flipped' - flip output horizontally
-# 'flipped-90', 'flipped-180', 'flipped-270' - flip output horizontally
-# and rotate by specified angle
-rotate = 90
-
-# Additional video mode to add
-# Format is generated by cvt and is documented in x.org.conf(5)
-modeline = 87.25 720 776 848 976 1440 1443 1453 1493 -hsync +vsync
-modeline = 65.13 768 816 896 1024 1024 1025 1028 1060 -HSync +VSync
-# Select one of the above modes
-mode = 768x1024
-
-[cursor]
-# Restrict cursor movements to single output
-map-to-output = VGA-1
-# Restrict cursor movements to concrete rectangle
-geometry = 2500x800
-# Load a custom XCursor theme
-theme = default
-
-# Single device configuration. String after colon must match device's name.
-[device:PixArt Dell MS116 USB Optical Mouse]
-# Restrict cursor movements for this mouse to single output
-map-to-output = VGA-1
-# Restrict cursor movements for this mouse to concrete rectangle
-geometry = 2500x800
-# tap_enabled=true
-
-[keyboard]
-meta-key = Logo
-
-# Keybindings
-# Maps key combinations with commands to execute
-# Commands include:
-# - "exit" to stop the compositor
-# - "exec" to execute a shell command
-# - "close" to close the current view
-# - "next_window" to cycle through windows
-# - "alpha" to cycle a window's alpha channel
-# - "break_pointer_constraint" to decline and deactivate all pointer constraints
-[bindings]
-Logo+Shift+e = exit
-Logo+q = close
-Logo+m = maximize
-Logo+Escape = break_pointer_constraint
-Alt+Tab = next_window
-Ctrl+Shift+a = alpha
diff --git a/rootston/seat.c b/rootston/seat.c
deleted file mode 100644
index c51d6ee5..00000000
--- a/rootston/seat.c
+++ /dev/null
@@ -1,1642 +0,0 @@
-#define _POSIX_C_SOURCE 200112L
-#include <assert.h>
-#include <libinput.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <wayland-server-core.h>
-#include <wlr/backend/libinput.h>
-#include <wlr/config.h>
-#include <wlr/types/wlr_data_device.h>
-#include <wlr/types/wlr_idle.h>
-#include <wlr/types/wlr_layer_shell_v1.h>
-#include <wlr/types/wlr_primary_selection.h>
-#include <wlr/types/wlr_switch.h>
-#include <wlr/types/wlr_tablet_v2.h>
-#include <wlr/types/wlr_xcursor_manager.h>
-#include <wlr/util/log.h>
-#include "rootston/cursor.h"
-#include "rootston/input.h"
-#include "rootston/keyboard.h"
-#include "rootston/seat.h"
-#include "rootston/text_input.h"
-#include "rootston/xcursor.h"
-
-static void handle_keyboard_key(struct wl_listener *listener, void *data) {
- struct roots_keyboard *keyboard =
- wl_container_of(listener, keyboard, keyboard_key);
- struct roots_desktop *desktop = keyboard->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, keyboard->seat->seat);
- struct wlr_event_keyboard_key *event = data;
- roots_keyboard_handle_key(keyboard, event);
-}
-
-static void handle_keyboard_modifiers(struct wl_listener *listener,
- void *data) {
- struct roots_keyboard *keyboard =
- wl_container_of(listener, keyboard, keyboard_modifiers);
- struct roots_desktop *desktop = keyboard->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, keyboard->seat->seat);
- roots_keyboard_handle_modifiers(keyboard);
-}
-
-static void handle_cursor_motion(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, motion);
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
- struct wlr_event_pointer_motion *event = data;
- roots_cursor_handle_motion(cursor, event);
-}
-
-static void handle_cursor_motion_absolute(struct wl_listener *listener,
- void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, motion_absolute);
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
- struct wlr_event_pointer_motion_absolute *event = data;
- roots_cursor_handle_motion_absolute(cursor, event);
-}
-
-static void handle_cursor_button(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, button);
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
- struct wlr_event_pointer_button *event = data;
- roots_cursor_handle_button(cursor, event);
-}
-
-static void handle_cursor_axis(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, axis);
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
- struct wlr_event_pointer_axis *event = data;
- roots_cursor_handle_axis(cursor, event);
-}
-
-static void handle_cursor_frame(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, frame);
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
- roots_cursor_handle_frame(cursor);
-}
-
-static void handle_swipe_begin(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, swipe_begin);
- struct wlr_pointer_gestures_v1 *gestures =
- cursor->seat->input->server->desktop->pointer_gestures;
- struct wlr_event_pointer_swipe_begin *event = data;
- wlr_pointer_gestures_v1_send_swipe_begin(gestures, cursor->seat->seat,
- event->time_msec, event->fingers);
-}
-
-static void handle_swipe_update(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, swipe_update);
- struct wlr_pointer_gestures_v1 *gestures =
- cursor->seat->input->server->desktop->pointer_gestures;
- struct wlr_event_pointer_swipe_update *event = data;
- wlr_pointer_gestures_v1_send_swipe_update(gestures, cursor->seat->seat,
- event->time_msec, event->dx, event->dy);
-}
-
-static void handle_swipe_end(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, swipe_end);
- struct wlr_pointer_gestures_v1 *gestures =
- cursor->seat->input->server->desktop->pointer_gestures;
- struct wlr_event_pointer_swipe_end *event = data;
- wlr_pointer_gestures_v1_send_swipe_end(gestures, cursor->seat->seat,
- event->time_msec, event->cancelled);
-}
-
-static void handle_pinch_begin(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, pinch_begin);
- struct wlr_pointer_gestures_v1 *gestures =
- cursor->seat->input->server->desktop->pointer_gestures;
- struct wlr_event_pointer_pinch_begin *event = data;
- wlr_pointer_gestures_v1_send_pinch_begin(gestures, cursor->seat->seat,
- event->time_msec, event->fingers);
-}
-
-static void handle_pinch_update(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, pinch_update);
- struct wlr_pointer_gestures_v1 *gestures =
- cursor->seat->input->server->desktop->pointer_gestures;
- struct wlr_event_pointer_pinch_update *event = data;
- wlr_pointer_gestures_v1_send_pinch_update(gestures, cursor->seat->seat,
- event->time_msec, event->dx, event->dy,
- event->scale, event->rotation);
-}
-
-static void handle_pinch_end(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, pinch_end);
- struct wlr_pointer_gestures_v1 *gestures =
- cursor->seat->input->server->desktop->pointer_gestures;
- struct wlr_event_pointer_pinch_end *event = data;
- wlr_pointer_gestures_v1_send_pinch_end(gestures, cursor->seat->seat,
- event->time_msec, event->cancelled);
-}
-
-static void handle_switch_toggle(struct wl_listener *listener, void *data) {
- struct roots_switch *switch_device =
- wl_container_of(listener, switch_device, toggle);
- struct roots_desktop *desktop = switch_device->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, switch_device->seat->seat);
- struct wlr_event_switch_toggle *event = data;
- roots_switch_handle_toggle(switch_device, event);
-}
-
-static void handle_touch_down(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, touch_down);
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
- struct wlr_event_touch_down *event = data;
- roots_cursor_handle_touch_down(cursor, event);
-}
-
-static void handle_touch_up(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, touch_up);
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
- struct wlr_event_touch_up *event = data;
- roots_cursor_handle_touch_up(cursor, event);
-}
-
-static void handle_touch_motion(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, touch_motion);
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
- struct wlr_event_touch_motion *event = data;
- roots_cursor_handle_touch_motion(cursor, event);
-}
-
-static void handle_tablet_tool_position(struct roots_cursor *cursor,
- struct roots_tablet *tablet,
- struct wlr_tablet_tool *tool,
- bool change_x, bool change_y,
- double x, double y, double dx, double dy) {
- if (!change_x && !change_y) {
- return;
- }
-
- switch (tool->type) {
- case WLR_TABLET_TOOL_TYPE_MOUSE:
- // They are 0 either way when they weren't modified
- wlr_cursor_move(cursor->cursor, tablet->device, dx, dy);
- break;
- default:
- wlr_cursor_warp_absolute(cursor->cursor, tablet->device,
- change_x ? x : NAN, change_y ? y : NAN);
- }
-
- double sx, sy;
- struct roots_view *view = NULL;
- struct roots_seat *seat = cursor->seat;
- struct roots_desktop *desktop = seat->input->server->desktop;
- struct wlr_surface *surface = desktop_surface_at(desktop,
- cursor->cursor->x, cursor->cursor->y, &sx, &sy, &view);
- struct roots_tablet_tool *roots_tool = tool->data;
-
- if (!surface) {
- wlr_tablet_v2_tablet_tool_notify_proximity_out(roots_tool->tablet_v2_tool);
- /* XXX: TODO: Fallback pointer semantics */
- return;
- }
-
- if (!wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) {
- wlr_tablet_v2_tablet_tool_notify_proximity_out(roots_tool->tablet_v2_tool);
- /* XXX: TODO: Fallback pointer semantics */
- return;
- }
-
- wlr_tablet_v2_tablet_tool_notify_proximity_in(roots_tool->tablet_v2_tool,
- tablet->tablet_v2, surface);
-
- wlr_tablet_v2_tablet_tool_notify_motion(roots_tool->tablet_v2_tool, sx, sy);
-}
-
-static void handle_tool_axis(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, tool_axis);
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
- struct wlr_event_tablet_tool_axis *event = data;
- struct roots_tablet_tool *roots_tool = event->tool->data;
-
- if (!roots_tool) { // Should this be an assert?
- wlr_log(WLR_DEBUG, "Tool Axis, before proximity");
- return;
- }
-
- /**
- * We need to handle them ourselves, not pass it into the cursor
- * without any consideration
- */
- handle_tablet_tool_position(cursor, event->device->data, event->tool,
- event->updated_axes & WLR_TABLET_TOOL_AXIS_X,
- event->updated_axes & WLR_TABLET_TOOL_AXIS_Y,
- event->x, event->y, event->dx, event->dy);
-
- if (event->updated_axes & WLR_TABLET_TOOL_AXIS_PRESSURE) {
- wlr_tablet_v2_tablet_tool_notify_pressure(
- roots_tool->tablet_v2_tool, event->pressure);
- }
-
- if (event->updated_axes & WLR_TABLET_TOOL_AXIS_DISTANCE) {
- wlr_tablet_v2_tablet_tool_notify_distance(
- roots_tool->tablet_v2_tool, event->distance);
- }
-
- if (event->updated_axes & WLR_TABLET_TOOL_AXIS_TILT_X) {
- roots_tool->tilt_x = event->tilt_x;
- }
-
- if (event->updated_axes & WLR_TABLET_TOOL_AXIS_TILT_Y) {
- roots_tool->tilt_y = event->tilt_y;
- }
-
- if (event->updated_axes & (WLR_TABLET_TOOL_AXIS_TILT_X | WLR_TABLET_TOOL_AXIS_TILT_Y)) {
- wlr_tablet_v2_tablet_tool_notify_tilt(
- roots_tool->tablet_v2_tool,
- roots_tool->tilt_x, roots_tool->tilt_y);
- }
-
- if (event->updated_axes & WLR_TABLET_TOOL_AXIS_ROTATION) {
- wlr_tablet_v2_tablet_tool_notify_rotation(
- roots_tool->tablet_v2_tool, event->rotation);
- }
-
- if (event->updated_axes & WLR_TABLET_TOOL_AXIS_SLIDER) {
- wlr_tablet_v2_tablet_tool_notify_slider(
- roots_tool->tablet_v2_tool, event->slider);
- }
-
- if (event->updated_axes & WLR_TABLET_TOOL_AXIS_WHEEL) {
- wlr_tablet_v2_tablet_tool_notify_wheel(
- roots_tool->tablet_v2_tool, event->wheel_delta, 0);
- }
-}
-
-static void handle_tool_tip(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, tool_tip);
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
- struct wlr_event_tablet_tool_tip *event = data;
- struct roots_tablet_tool *roots_tool = event->tool->data;
-
- if (event->state == WLR_TABLET_TOOL_TIP_DOWN) {
- wlr_tablet_v2_tablet_tool_notify_down(roots_tool->tablet_v2_tool);
- wlr_tablet_tool_v2_start_implicit_grab(roots_tool->tablet_v2_tool);
- } else {
- wlr_tablet_v2_tablet_tool_notify_up(roots_tool->tablet_v2_tool);
- }
-}
-
-static void handle_tablet_tool_destroy(struct wl_listener *listener, void *data) {
- struct roots_tablet_tool *tool =
- wl_container_of(listener, tool, tool_destroy);
-
- wl_list_remove(&tool->link);
- wl_list_remove(&tool->tool_link);
-
- wl_list_remove(&tool->tool_destroy.link);
- wl_list_remove(&tool->set_cursor.link);
-
- free(tool);
-}
-
-static void handle_tool_button(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, tool_button);
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
- struct wlr_event_tablet_tool_button *event = data;
- struct roots_tablet_tool *roots_tool = event->tool->data;
-
- wlr_tablet_v2_tablet_tool_notify_button(roots_tool->tablet_v2_tool,
- (enum zwp_tablet_pad_v2_button_state)event->button,
- (enum zwp_tablet_pad_v2_button_state)event->state);
-}
-
-static void handle_tablet_tool_set_cursor(struct wl_listener *listener, void *data) {
- struct roots_tablet_tool *tool =
- wl_container_of(listener, tool, set_cursor);
- struct wlr_tablet_v2_event_cursor *evt = data;
-
-
- struct wlr_seat_pointer_request_set_cursor_event event = {
- .surface = evt->surface,
- .hotspot_x = evt->hotspot_x,
- .hotspot_y = evt->hotspot_y,
- .serial = evt->serial,
- .seat_client = evt->seat_client,
- };
-
- roots_cursor_handle_request_set_cursor(tool->seat->cursor, &event);
-}
-
-static void handle_tool_proximity(struct wl_listener *listener, void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, tool_proximity);
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
- struct wlr_event_tablet_tool_proximity *event = data;
-
- struct wlr_tablet_tool *tool = event->tool;
- if (!tool->data) {
- struct roots_tablet_tool *roots_tool =
- calloc(1, sizeof(struct roots_tablet_tool));
- roots_tool->seat = cursor->seat;
- tool->data = roots_tool;
- roots_tool->tablet_v2_tool =
- wlr_tablet_tool_create(desktop->tablet_v2,
- cursor->seat->seat, tool);
- roots_tool->tool_destroy.notify = handle_tablet_tool_destroy;
- wl_signal_add(&tool->events.destroy, &roots_tool->tool_destroy);
-
- roots_tool->set_cursor.notify = handle_tablet_tool_set_cursor;
- wl_signal_add(&roots_tool->tablet_v2_tool->events.set_cursor,
- &roots_tool->set_cursor);
-
- wl_list_init(&roots_tool->link);
- wl_list_init(&roots_tool->tool_link);
- }
-
- if (event->state == WLR_TABLET_TOOL_PROXIMITY_OUT) {
- struct roots_tablet_tool *roots_tool = tool->data;
- wlr_tablet_v2_tablet_tool_notify_proximity_out(roots_tool->tablet_v2_tool);
- return;
- }
-
- handle_tablet_tool_position(cursor, event->device->data, event->tool,
- true, true, event->x, event->y, 0, 0);
-}
-
-static void handle_request_set_cursor(struct wl_listener *listener,
- void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, request_set_cursor);
- struct roots_desktop *desktop = cursor->seat->input->server->desktop;
- wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
- struct wlr_seat_pointer_request_set_cursor_event *event = data;
- roots_cursor_handle_request_set_cursor(cursor, event);
-}
-
-static void handle_pointer_focus_change(struct wl_listener *listener,
- void *data) {
- struct roots_cursor *cursor =
- wl_container_of(listener, cursor, focus_change);
- struct wlr_seat_pointer_focus_change_event *event = data;
- roots_cursor_handle_focus_change(cursor, event);
-}
-
-static void seat_reset_device_mappings(struct roots_seat *seat,
- struct wlr_input_device *device) {
- struct wlr_cursor *cursor = seat->cursor->cursor;
- struct roots_config *config = seat->input->config;
-
- wlr_cursor_map_input_to_output(cursor, device, NULL);
- struct roots_device_config *dconfig;
- if ((dconfig = roots_config_get_device(config, device))) {
- wlr_cursor_map_input_to_region(cursor, device, dconfig->mapped_box);
- }
-}
-
-static void seat_set_device_output_mappings(struct roots_seat *seat,
- struct wlr_input_device *device, struct wlr_output *output) {
- struct wlr_cursor *cursor = seat->cursor->cursor;
- struct roots_config *config = seat->input->config;
- struct roots_device_config *dconfig =
- roots_config_get_device(config, device);
-
- const char *mapped_output = NULL;
- if (dconfig != NULL) {
- mapped_output = dconfig->mapped_output;
- }
- if (mapped_output == NULL) {
- mapped_output = device->output_name;
- }
-
- if (mapped_output && strcmp(mapped_output, output->name) == 0) {
- wlr_cursor_map_input_to_output(cursor, device, output);
- }
-}
-
-void roots_seat_configure_cursor(struct roots_seat *seat) {
- struct roots_config *config = seat->input->config;
- struct roots_desktop *desktop = seat->input->server->desktop;
- struct wlr_cursor *cursor = seat->cursor->cursor;
-
- struct roots_pointer *pointer;
- struct roots_touch *touch;
- struct roots_tablet *tablet;
- struct roots_output *output;
-
- // reset mappings
- wlr_cursor_map_to_output(cursor, NULL);
- wl_list_for_each(pointer, &seat->pointers, link) {
- seat_reset_device_mappings(seat, pointer->device);
- }
- wl_list_for_each(touch, &seat->touch, link) {
- seat_reset_device_mappings(seat, touch->device);
- }
- wl_list_for_each(tablet, &seat->tablets, link) {
- seat_reset_device_mappings(seat, tablet->device);
- }
-
- // configure device to output mappings
- const char *mapped_output = NULL;
- struct roots_cursor_config *cc =
- roots_config_get_cursor(config, seat->seat->name);
- if (cc != NULL) {
- mapped_output = cc->mapped_output;
- }
- wl_list_for_each(output, &desktop->outputs, link) {
- if (mapped_output &&
- strcmp(mapped_output, output->wlr_output->name) == 0) {
- wlr_cursor_map_to_output(cursor, output->wlr_output);
- }
-
- wl_list_for_each(pointer, &seat->pointers, link) {
- seat_set_device_output_mappings(seat, pointer->device,
- output->wlr_output);
- }
- wl_list_for_each(tablet, &seat->tablets, link) {
- seat_set_device_output_mappings(seat, tablet->device,
- output->wlr_output);
- }
- wl_list_for_each(touch, &seat->touch, link) {
- seat_set_device_output_mappings(seat, touch->device,
- output->wlr_output);
- }
- }
-}
-
-static void roots_seat_init_cursor(struct roots_seat *seat) {
- seat->cursor = roots_cursor_create(seat);
- if (!seat->cursor) {
- return;
- }
- seat->cursor->seat = seat;
- struct wlr_cursor *wlr_cursor = seat->cursor->cursor;
- struct roots_desktop *desktop = seat->input->server->desktop;
- wlr_cursor_attach_output_layout(wlr_cursor, desktop->layout);
-
- roots_seat_configure_cursor(seat);
- roots_seat_configure_xcursor(seat);
-
- // add input signals
- wl_signal_add(&wlr_cursor->events.motion, &seat->cursor->motion);
- seat->cursor->motion.notify = handle_cursor_motion;
-
- wl_signal_add(&wlr_cursor->events.motion_absolute,
- &seat->cursor->motion_absolute);
- seat->cursor->motion_absolute.notify = handle_cursor_motion_absolute;
-
- wl_signal_add(&wlr_cursor->events.button, &seat->cursor->button);
- seat->cursor->button.notify = handle_cursor_button;
-
- wl_signal_add(&wlr_cursor->events.axis, &seat->cursor->axis);
- seat->cursor->axis.notify = handle_cursor_axis;
-
- wl_signal_add(&wlr_cursor->events.frame, &seat->cursor->frame);
- seat->cursor->frame.notify = handle_cursor_frame;
-
- wl_signal_add(&wlr_cursor->events.swipe_begin, &seat->cursor->swipe_begin);
- seat->cursor->swipe_begin.notify = handle_swipe_begin;
-
- wl_signal_add(&wlr_cursor->events.swipe_update, &seat->cursor->swipe_update);
- seat->cursor->swipe_update.notify = handle_swipe_update;
-
- wl_signal_add(&wlr_cursor->events.swipe_end, &seat->cursor->swipe_end);
- seat->cursor->swipe_end.notify = handle_swipe_end;
-
- wl_signal_add(&wlr_cursor->events.pinch_begin, &seat->cursor->pinch_begin);
- seat->cursor->pinch_begin.notify = handle_pinch_begin;
-
- wl_signal_add(&wlr_cursor->events.pinch_update, &seat->cursor->pinch_update);
- seat->cursor->pinch_update.notify = handle_pinch_update;
-
- wl_signal_add(&wlr_cursor->events.pinch_end, &seat->cursor->pinch_end);
- seat->cursor->pinch_end.notify = handle_pinch_end;
-
- wl_signal_add(&wlr_cursor->events.touch_down, &seat->cursor->touch_down);
- seat->cursor->touch_down.notify = handle_touch_down;
-
- wl_signal_add(&wlr_cursor->events.touch_up, &seat->cursor->touch_up);
- seat->cursor->touch_up.notify = handle_touch_up;
-
- wl_signal_add(&wlr_cursor->events.touch_motion,
- &seat->cursor->touch_motion);
- seat->cursor->touch_motion.notify = handle_touch_motion;
-
- wl_signal_add(&wlr_cursor->events.tablet_tool_axis,
- &seat->cursor->tool_axis);
- seat->cursor->tool_axis.notify = handle_tool_axis;
-
- wl_signal_add(&wlr_cursor->events.tablet_tool_tip, &seat->cursor->tool_tip);
- seat->cursor->tool_tip.notify = handle_tool_tip;
-
- wl_signal_add(&wlr_cursor->events.tablet_tool_proximity, &seat->cursor->tool_proximity);
- seat->cursor->tool_proximity.notify = handle_tool_proximity;
-
- wl_signal_add(&wlr_cursor->events.tablet_tool_button, &seat->cursor->tool_button);
- seat->cursor->tool_button.notify = handle_tool_button;
-
- wl_signal_add(&seat->seat->events.request_set_cursor,
- &seat->cursor->request_set_cursor);
- seat->cursor->request_set_cursor.notify = handle_request_set_cursor;
-
- wl_signal_add(&seat->seat->pointer_state.events.focus_change,
- &seat->cursor->focus_change);
- seat->cursor->focus_change.notify = handle_pointer_focus_change;
-
- wl_list_init(&seat->cursor->constraint_commit.link);
-}
-
-static void roots_drag_icon_handle_surface_commit(struct wl_listener *listener,
- void *data) {
- struct roots_drag_icon *icon =
- wl_container_of(listener, icon, surface_commit);
- roots_drag_icon_update_position(icon);
-}
-
-static void roots_drag_icon_handle_map(struct wl_listener *listener,
- void *data) {
- struct roots_drag_icon *icon =
- wl_container_of(listener, icon, map);
- roots_drag_icon_damage_whole(icon);
-}
-
-static void roots_drag_icon_handle_unmap(struct wl_listener *listener,
- void *data) {
- struct roots_drag_icon *icon =
- wl_container_of(listener, icon, unmap);
- roots_drag_icon_damage_whole(icon);
-}
-
-static void roots_drag_icon_handle_destroy(struct wl_listener *listener,
- void *data) {
- struct roots_drag_icon *icon =
- wl_container_of(listener, icon, destroy);
- roots_drag_icon_damage_whole(icon);
-
- assert(icon->seat->drag_icon == icon);
- icon->seat->drag_icon = NULL;
-
- wl_list_remove(&icon->surface_commit.link);
- wl_list_remove(&icon->unmap.link);
- wl_list_remove(&icon->destroy.link);
- free(icon);
-}
-
-static void roots_seat_handle_request_start_drag(struct wl_listener *listener,
- void *data) {
- struct roots_seat *seat =
- wl_container_of(listener, seat, request_start_drag);
- struct wlr_seat_request_start_drag_event *event = data;
-
- if (wlr_seat_validate_pointer_grab_serial(seat->seat,
- event->origin, event->serial)) {
- wlr_seat_start_pointer_drag(seat->seat, event->drag, event->serial);
- return;
- }
-
- struct wlr_touch_point *point;
- if (wlr_seat_validate_touch_grab_serial(seat->seat,
- event->origin, event->serial, &point)) {
- wlr_seat_start_touch_drag(seat->seat, event->drag, event->serial, point);
- return;
- }
-
- wlr_log(WLR_DEBUG, "Ignoring start_drag request: "
- "could not validate pointer or touch serial %" PRIu32, event->serial);
- wlr_data_source_destroy(event->drag->source);
-}
-
-static void roots_seat_handle_start_drag(struct wl_listener *listener,
- void *data) {
- struct roots_seat *seat = wl_container_of(listener, seat, start_drag);
- struct wlr_drag *wlr_drag = data;
- struct wlr_drag_icon *wlr_drag_icon = wlr_drag->icon;
- if (wlr_drag_icon == NULL) {
- return;
- }
-
- struct roots_drag_icon *icon = calloc(1, sizeof(struct roots_drag_icon));
- if (icon == NULL) {
- return;
- }
- icon->seat = seat;
- icon->wlr_drag_icon = wlr_drag_icon;
-
- icon->surface_commit.notify = roots_drag_icon_handle_surface_commit;
- wl_signal_add(&wlr_drag_icon->surface->events.commit, &icon->surface_commit);
- icon->unmap.notify = roots_drag_icon_handle_unmap;
- wl_signal_add(&wlr_drag_icon->events.unmap, &icon->unmap);
- icon->map.notify = roots_drag_icon_handle_map;
- wl_signal_add(&wlr_drag_icon->events.map, &icon->map);
- icon->destroy.notify = roots_drag_icon_handle_destroy;
- wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy);
-
- assert(seat->drag_icon == NULL);
- seat->drag_icon = icon;
-
- roots_drag_icon_update_position(icon);
-}
-
-static void roots_seat_handle_request_set_selection(
- struct wl_listener *listener, void *data) {
- struct roots_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 roots_seat_handle_request_set_primary_selection(
- struct wl_listener *listener, void *data) {
- struct roots_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);
-}
-
-void roots_drag_icon_update_position(struct roots_drag_icon *icon) {
- roots_drag_icon_damage_whole(icon);
-
- struct roots_seat *seat = icon->seat;
- struct wlr_drag *wlr_drag = icon->wlr_drag_icon->drag;
- assert(wlr_drag != NULL);
-
- switch (seat->seat->drag->grab_type) {
- case WLR_DRAG_GRAB_KEYBOARD:
- assert(false);
- case WLR_DRAG_GRAB_KEYBOARD_POINTER:;
- struct wlr_cursor *cursor = seat->cursor->cursor;
- icon->x = cursor->x;
- icon->y = cursor->y;
- break;
- case WLR_DRAG_GRAB_KEYBOARD_TOUCH:;
- struct wlr_touch_point *point =
- wlr_seat_touch_get_point(seat->seat, wlr_drag->touch_id);
- if (point == NULL) {
- return;
- }
- icon->x = seat->touch_x;
- icon->y = seat->touch_y;
- break;
- }
-
- roots_drag_icon_damage_whole(icon);
-}
-
-void roots_drag_icon_damage_whole(struct roots_drag_icon *icon) {
- struct roots_output *output;
- wl_list_for_each(output, &icon->seat->input->server->desktop->outputs,
- link) {
- output_damage_whole_drag_icon(output, icon);
- }
-}
-
-static void seat_view_destroy(struct roots_seat_view *seat_view);
-
-static void roots_seat_handle_destroy(struct wl_listener *listener,
- void *data) {
- struct roots_seat *seat = wl_container_of(listener, seat, destroy);
-
- // TODO: probably more to be freed here
- wl_list_remove(&seat->destroy.link);
-
- struct roots_seat_view *view, *nview;
- wl_list_for_each_safe(view, nview, &seat->views, link) {
- seat_view_destroy(view);
- }
-}
-
-void roots_seat_destroy(struct roots_seat *seat) {
- roots_seat_handle_destroy(&seat->destroy, seat->seat);
- wlr_seat_destroy(seat->seat);
-}
-
-struct roots_seat *roots_seat_create(struct roots_input *input, char *name) {
- struct roots_seat *seat = calloc(1, sizeof(struct roots_seat));
- if (!seat) {
- return NULL;
- }
-
- wl_list_init(&seat->keyboards);
- wl_list_init(&seat->pointers);
- wl_list_init(&seat->touch);
- wl_list_init(&seat->tablets);
- wl_list_init(&seat->tablet_pads);
- wl_list_init(&seat->switches);
- wl_list_init(&seat->views);
-
- seat->input = input;
-
- seat->seat = wlr_seat_create(input->server->wl_display, name);
- if (!seat->seat) {
- free(seat);
- return NULL;
- }
- seat->seat->data = seat;
-
- roots_seat_init_cursor(seat);
- if (!seat->cursor) {
- wlr_seat_destroy(seat->seat);
- free(seat);
- return NULL;
- }
-
- roots_input_method_relay_init(seat, &seat->im_relay);
-
- wl_list_insert(&input->seats, &seat->link);
-
- seat->request_set_selection.notify =
- roots_seat_handle_request_set_selection;
- wl_signal_add(&seat->seat->events.request_set_selection,
- &seat->request_set_selection);
- seat->request_set_primary_selection.notify =
- roots_seat_handle_request_set_primary_selection;
- wl_signal_add(&seat->seat->events.request_set_primary_selection,
- &seat->request_set_primary_selection);
- seat->request_start_drag.notify = roots_seat_handle_request_start_drag;
- wl_signal_add(&seat->seat->events.request_start_drag,
- &seat->request_start_drag);
- seat->start_drag.notify = roots_seat_handle_start_drag;
- wl_signal_add(&seat->seat->events.start_drag, &seat->start_drag);
- seat->destroy.notify = roots_seat_handle_destroy;
- wl_signal_add(&seat->seat->events.destroy, &seat->destroy);
-
- return seat;
-}
-
-static void seat_update_capabilities(struct roots_seat *seat) {
- uint32_t caps = 0;
- if (!wl_list_empty(&seat->keyboards)) {
- caps |= WL_SEAT_CAPABILITY_KEYBOARD;
- }
- if (!wl_list_empty(&seat->pointers) || !wl_list_empty(&seat->tablets)) {
- caps |= WL_SEAT_CAPABILITY_POINTER;
- }
- if (!wl_list_empty(&seat->touch)) {
- caps |= WL_SEAT_CAPABILITY_TOUCH;
- }
- wlr_seat_set_capabilities(seat->seat, caps);
-
- // Hide cursor if seat doesn't have pointer capability
- if ((caps & WL_SEAT_CAPABILITY_POINTER) == 0) {
- wlr_cursor_set_image(seat->cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
- } else {
- wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager,
- seat->cursor->default_xcursor, seat->cursor->cursor);
- }
-}
-
-static void handle_keyboard_destroy(struct wl_listener *listener, void *data) {
- struct roots_keyboard *keyboard =
- wl_container_of(listener, keyboard, device_destroy);
- struct roots_seat *seat = keyboard->seat;
- wl_list_remove(&keyboard->device_destroy.link);
- wl_list_remove(&keyboard->keyboard_key.link);
- wl_list_remove(&keyboard->keyboard_modifiers.link);
- roots_keyboard_destroy(keyboard);
- seat_update_capabilities(seat);
-}
-
-static void seat_add_keyboard(struct roots_seat *seat,
- struct wlr_input_device *device) {
- assert(device->type == WLR_INPUT_DEVICE_KEYBOARD);
- struct roots_keyboard *keyboard =
- roots_keyboard_create(device, seat->input);
- if (keyboard == NULL) {
- wlr_log(WLR_ERROR, "could not allocate keyboard for seat");
- return;
- }
-
- keyboard->seat = seat;
-
- wl_list_insert(&seat->keyboards, &keyboard->link);
-
- keyboard->device_destroy.notify = handle_keyboard_destroy;
- wl_signal_add(&keyboard->device->events.destroy, &keyboard->device_destroy);
- keyboard->keyboard_key.notify = handle_keyboard_key;
- wl_signal_add(&keyboard->device->keyboard->events.key,
- &keyboard->keyboard_key);
- keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers;
- wl_signal_add(&keyboard->device->keyboard->events.modifiers,
- &keyboard->keyboard_modifiers);
-
- wlr_seat_set_keyboard(seat->seat, device);
-}
-
-static void handle_pointer_destroy(struct wl_listener *listener, void *data) {
- struct roots_pointer *pointer =
- wl_container_of(listener, pointer, device_destroy);
- struct roots_seat *seat = pointer->seat;
-
- wl_list_remove(&pointer->link);
- wlr_cursor_detach_input_device(seat->cursor->cursor, pointer->device);
- wl_list_remove(&pointer->device_destroy.link);
- free(pointer);
-
- seat_update_capabilities(seat);
-}
-
-static void seat_add_pointer(struct roots_seat *seat,
- struct wlr_input_device *device) {
- struct roots_pointer *pointer = calloc(1, sizeof(struct roots_pointer));
- if (!pointer) {
- wlr_log(WLR_ERROR, "could not allocate pointer for seat");
- return;
- }
-
- device->data = pointer;
- pointer->device = device;
- pointer->seat = seat;
- wl_list_insert(&seat->pointers, &pointer->link);
-
- pointer->device_destroy.notify = handle_pointer_destroy;
- wl_signal_add(&pointer->device->events.destroy, &pointer->device_destroy);
-
- wlr_cursor_attach_input_device(seat->cursor->cursor, device);
- roots_seat_configure_cursor(seat);
-}
-
-static void handle_switch_destroy(struct wl_listener *listener, void *data) {
- struct roots_switch *switch_device =
- wl_container_of(listener, switch_device, device_destroy);
- struct roots_seat *seat = switch_device->seat;
-
- wl_list_remove(&switch_device->link);
- wl_list_remove(&switch_device->device_destroy.link);
- free(switch_device);
-
- seat_update_capabilities(seat);
-}
-
-static void seat_add_switch(struct roots_seat *seat,
- struct wlr_input_device *device) {
- assert(device->type == WLR_INPUT_DEVICE_SWITCH);
- struct roots_switch *switch_device = calloc(1, sizeof(struct roots_switch));
- if (!switch_device) {
- wlr_log(WLR_ERROR, "could not allocate switch for seat");
- return;
- }
- device->data = switch_device;
- switch_device->device = device;
- switch_device->seat = seat;
- wl_list_insert(&seat->switches, &switch_device->link);
- switch_device->device_destroy.notify = handle_switch_destroy;
-
- switch_device->toggle.notify = handle_switch_toggle;
- wl_signal_add(&switch_device->device->switch_device->events.toggle, &switch_device->toggle);
-}
-
-static void handle_touch_destroy(struct wl_listener *listener, void *data) {
- struct roots_pointer *touch =
- wl_container_of(listener, touch, device_destroy);
- struct roots_seat *seat = touch->seat;
-
- wl_list_remove(&touch->link);
- wlr_cursor_detach_input_device(seat->cursor->cursor, touch->device);
- wl_list_remove(&touch->device_destroy.link);
- free(touch);
-
- seat_update_capabilities(seat);
-}
-
-static void seat_add_touch(struct roots_seat *seat,
- struct wlr_input_device *device) {
- struct roots_touch *touch = calloc(1, sizeof(struct roots_touch));
- if (!touch) {
- wlr_log(WLR_ERROR, "could not allocate touch for seat");
- return;
- }
-
- device->data = touch;
- touch->device = device;
- touch->seat = seat;
- wl_list_insert(&seat->touch, &touch->link);
-
- touch->device_destroy.notify = handle_touch_destroy;
- wl_signal_add(&touch->device->events.destroy, &touch->device_destroy);
-
- wlr_cursor_attach_input_device(seat->cursor->cursor, device);
- roots_seat_configure_cursor(seat);
-}
-
-static void handle_tablet_pad_destroy(struct wl_listener *listener,
- void *data) {
- struct roots_tablet_pad *tablet_pad =
- wl_container_of(listener, tablet_pad, device_destroy);
- struct roots_seat *seat = tablet_pad->seat;
-
- wl_list_remove(&tablet_pad->device_destroy.link);
- wl_list_remove(&tablet_pad->tablet_destroy.link);
- wl_list_remove(&tablet_pad->attach.link);
- wl_list_remove(&tablet_pad->link);
-
- wl_list_remove(&tablet_pad->button.link);
- wl_list_remove(&tablet_pad->strip.link);
- wl_list_remove(&tablet_pad->ring.link);
- free(tablet_pad);
-
- seat_update_capabilities(seat);
-}
-
-static void handle_pad_tool_destroy(struct wl_listener *listener, void *data) {
- struct roots_tablet_pad *pad =
- wl_container_of(listener, pad, tablet_destroy);
-
- pad->tablet = NULL;
-
- wl_list_remove(&pad->tablet_destroy.link);
- wl_list_init(&pad->tablet_destroy.link);
-}
-
-static void attach_tablet_pad(struct roots_tablet_pad *pad,
- struct roots_tablet *tool) {
- wlr_log(WLR_DEBUG, "Attaching tablet pad \"%s\" to tablet tool \"%s\"",
- pad->device->name, tool->device->name);
-
- pad->tablet = tool;
-
- wl_list_remove(&pad->tablet_destroy.link);
- pad->tablet_destroy.notify = handle_pad_tool_destroy;
- wl_signal_add(&tool->device->events.destroy, &pad->tablet_destroy);
-}
-
-static void handle_tablet_pad_attach(struct wl_listener *listener, void *data) {
- struct roots_tablet_pad *pad =
- wl_container_of(listener, pad, attach);
- struct wlr_tablet_tool *wlr_tool = data;
- struct roots_tablet *tool = wlr_tool->data;
-
- attach_tablet_pad(pad, tool);
-}
-
-static void handle_tablet_pad_ring(struct wl_listener *listener, void *data) {
- struct roots_tablet_pad *pad =
- wl_container_of(listener, pad, ring);
- struct wlr_event_tablet_pad_ring *event = data;
-
- wlr_tablet_v2_tablet_pad_notify_ring(pad->tablet_v2_pad,
- event->ring, event->position,
- event->source == WLR_TABLET_PAD_RING_SOURCE_FINGER,
- event->time_msec);
-}
-
-static void handle_tablet_pad_strip(struct wl_listener *listener, void *data) {
- struct roots_tablet_pad *pad =
- wl_container_of(listener, pad, strip);
- struct wlr_event_tablet_pad_strip *event = data;
-
- wlr_tablet_v2_tablet_pad_notify_strip(pad->tablet_v2_pad,
- event->strip, event->position,
- event->source == WLR_TABLET_PAD_STRIP_SOURCE_FINGER,
- event->time_msec);
-}
-
-static void handle_tablet_pad_button(struct wl_listener *listener, void *data) {
- struct roots_tablet_pad *pad =
- wl_container_of(listener, pad, button);
- struct wlr_event_tablet_pad_button *event = data;
-
- wlr_tablet_v2_tablet_pad_notify_mode(pad->tablet_v2_pad,
- event->group, event->mode, event->time_msec);
-
- wlr_tablet_v2_tablet_pad_notify_button(pad->tablet_v2_pad,
- event->button, event->time_msec,
- (enum zwp_tablet_pad_v2_button_state)event->state);
-}
-
-static void seat_add_tablet_pad(struct roots_seat *seat,
- struct wlr_input_device *device) {
- struct roots_tablet_pad *tablet_pad =
- calloc(1, sizeof(struct roots_tablet_pad));
- if (!tablet_pad) {
- wlr_log(WLR_ERROR, "could not allocate tablet_pad for seat");
- return;
- }
-
- device->data = tablet_pad;
- tablet_pad->device = device;
- tablet_pad->seat = seat;
- wl_list_insert(&seat->tablet_pads, &tablet_pad->link);
-
- tablet_pad->device_destroy.notify = handle_tablet_pad_destroy;
- wl_signal_add(&tablet_pad->device->events.destroy,
- &tablet_pad->device_destroy);
-
- tablet_pad->attach.notify = handle_tablet_pad_attach;
- wl_signal_add(&tablet_pad->device->tablet_pad->events.attach_tablet,
- &tablet_pad->attach);
-
- tablet_pad->button.notify = handle_tablet_pad_button;
- wl_signal_add(&tablet_pad->device->tablet_pad->events.button, &tablet_pad->button);
-
- tablet_pad->strip.notify = handle_tablet_pad_strip;
- wl_signal_add(&tablet_pad->device->tablet_pad->events.strip, &tablet_pad->strip);
-
- tablet_pad->ring.notify = handle_tablet_pad_ring;
- wl_signal_add(&tablet_pad->device->tablet_pad->events.ring, &tablet_pad->ring);
-
- wl_list_init(&tablet_pad->tablet_destroy.link);
-
- struct roots_desktop *desktop = seat->input->server->desktop;
- tablet_pad->tablet_v2_pad =
- wlr_tablet_pad_create(desktop->tablet_v2, seat->seat, device);
-
- /* Search for a sibling tablet */
- if (!wlr_input_device_is_libinput(device)) {
- /* We can only do this on libinput devices */
- return;
- }
-
- struct libinput_device_group *group =
- libinput_device_get_device_group(wlr_libinput_get_device_handle(device));
- struct roots_tablet *tool;
- wl_list_for_each(tool, &seat->tablets, link) {
- if (!wlr_input_device_is_libinput(tool->device)) {
- continue;
- }
-
- struct libinput_device *li_dev =
- wlr_libinput_get_device_handle(tool->device);
- if (libinput_device_get_device_group(li_dev) == group) {
- attach_tablet_pad(tablet_pad, tool);
- break;
- }
- }
-}
-
-static void handle_tablet_destroy(struct wl_listener *listener,
- void *data) {
- struct roots_tablet *tablet =
- wl_container_of(listener, tablet, device_destroy);
- struct roots_seat *seat = tablet->seat;
-
- wlr_cursor_detach_input_device(seat->cursor->cursor, tablet->device);
- wl_list_remove(&tablet->device_destroy.link);
- wl_list_remove(&tablet->link);
- free(tablet);
-
- seat_update_capabilities(seat);
-}
-
-static void seat_add_tablet_tool(struct roots_seat *seat,
- struct wlr_input_device *device) {
- struct roots_tablet *tablet =
- calloc(1, sizeof(struct roots_tablet));
- if (!tablet) {
- wlr_log(WLR_ERROR, "could not allocate tablet for seat");
- return;
- }
-
- device->data = tablet;
- tablet->device = device;
- tablet->seat = seat;
- wl_list_insert(&seat->tablets, &tablet->link);
-
- tablet->device_destroy.notify = handle_tablet_destroy;
- wl_signal_add(&tablet->device->events.destroy,
- &tablet->device_destroy);
-
- wlr_cursor_attach_input_device(seat->cursor->cursor, device);
- roots_seat_configure_cursor(seat);
-
- struct roots_desktop *desktop = seat->input->server->desktop;
-
- tablet->tablet_v2 =
- wlr_tablet_create(desktop->tablet_v2, seat->seat, device);
-
- struct libinput_device_group *group =
- libinput_device_get_device_group(wlr_libinput_get_device_handle(device));
- struct roots_tablet_pad *pad;
- wl_list_for_each(pad, &seat->tablet_pads, link) {
- if (!wlr_input_device_is_libinput(pad->device)) {
- continue;
- }
-
- struct libinput_device *li_dev =
- wlr_libinput_get_device_handle(pad->device);
- if (libinput_device_get_device_group(li_dev) == group) {
- attach_tablet_pad(pad, tablet);
- }
- }
-}
-
-void roots_seat_add_device(struct roots_seat *seat,
- struct wlr_input_device *device) {
- switch (device->type) {
- case WLR_INPUT_DEVICE_KEYBOARD:
- seat_add_keyboard(seat, device);
- break;
- case WLR_INPUT_DEVICE_POINTER:
- seat_add_pointer(seat, device);
- break;
- case WLR_INPUT_DEVICE_SWITCH:
- seat_add_switch(seat, device);
- break;
- case WLR_INPUT_DEVICE_TOUCH:
- seat_add_touch(seat, device);
- break;
- case WLR_INPUT_DEVICE_TABLET_PAD:
- seat_add_tablet_pad(seat, device);
- break;
- case WLR_INPUT_DEVICE_TABLET_TOOL:
- seat_add_tablet_tool(seat, device);
- break;
- }
-
- seat_update_capabilities(seat);
-}
-
-void roots_seat_configure_xcursor(struct roots_seat *seat) {
- const char *cursor_theme = NULL;
- struct roots_cursor_config *cc =
- roots_config_get_cursor(seat->input->config, seat->seat->name);
- if (cc != NULL) {
- cursor_theme = cc->theme;
- if (cc->default_image != NULL) {
- seat->cursor->default_xcursor = cc->default_image;
- }
- }
-
- if (!seat->cursor->xcursor_manager) {
- seat->cursor->xcursor_manager =
- wlr_xcursor_manager_create(cursor_theme, ROOTS_XCURSOR_SIZE);
- if (seat->cursor->xcursor_manager == NULL) {
- wlr_log(WLR_ERROR, "Cannot create XCursor manager for theme %s",
- cursor_theme);
- return;
- }
- }
-
- struct roots_output *output;
- wl_list_for_each(output, &seat->input->server->desktop->outputs, link) {
- float scale = output->wlr_output->scale;
- if (wlr_xcursor_manager_load(seat->cursor->xcursor_manager, scale)) {
- wlr_log(WLR_ERROR, "Cannot load xcursor theme for output '%s' "
- "with scale %f", output->wlr_output->name, scale);
- }
- }
-
- wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager,
- seat->cursor->default_xcursor, seat->cursor->cursor);
- wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x,
- seat->cursor->cursor->y);
-}
-
-bool roots_seat_has_meta_pressed(struct roots_seat *seat) {
- struct roots_keyboard *keyboard;
- wl_list_for_each(keyboard, &seat->keyboards, link) {
- if (!keyboard->config->meta_key) {
- continue;
- }
-
- uint32_t modifiers =
- wlr_keyboard_get_modifiers(keyboard->device->keyboard);
- if ((modifiers ^ keyboard->config->meta_key) == 0) {
- return true;
- }
- }
-
- return false;
-}
-
-struct roots_view *roots_seat_get_focus(struct roots_seat *seat) {
- if (!seat->has_focus || wl_list_empty(&seat->views)) {
- return NULL;
- }
- struct roots_seat_view *seat_view =
- wl_container_of(seat->views.next, seat_view, link);
- return seat_view->view;
-}
-
-static void seat_view_destroy(struct roots_seat_view *seat_view) {
- struct roots_seat *seat = seat_view->seat;
-
- if (seat_view->view == roots_seat_get_focus(seat)) {
- seat->has_focus = false;
- seat->cursor->mode = ROOTS_CURSOR_PASSTHROUGH;
- }
-
- if (seat_view == seat->cursor->pointer_view) {
- seat->cursor->pointer_view = NULL;
- }
-
- wl_list_remove(&seat_view->view_unmap.link);
- wl_list_remove(&seat_view->view_destroy.link);
- wl_list_remove(&seat_view->link);
- free(seat_view);
-
- // Focus first view
- if (!wl_list_empty(&seat->views)) {
- struct roots_seat_view *first_seat_view = wl_container_of(
- seat->views.next, first_seat_view, link);
- roots_seat_set_focus(seat, first_seat_view->view);
- }
-}
-
-static void seat_view_handle_unmap(struct wl_listener *listener, void *data) {
- struct roots_seat_view *seat_view =
- wl_container_of(listener, seat_view, view_unmap);
- seat_view_destroy(seat_view);
-}
-
-static void seat_view_handle_destroy(struct wl_listener *listener, void *data) {
- struct roots_seat_view *seat_view =
- wl_container_of(listener, seat_view, view_destroy);
- seat_view_destroy(seat_view);
-}
-
-static struct roots_seat_view *seat_add_view(struct roots_seat *seat,
- struct roots_view *view) {
- struct roots_seat_view *seat_view =
- calloc(1, sizeof(struct roots_seat_view));
- if (seat_view == NULL) {
- return NULL;
- }
- seat_view->seat = seat;
- seat_view->view = view;
-
- wl_list_insert(seat->views.prev, &seat_view->link);
-
- seat_view->view_unmap.notify = seat_view_handle_unmap;
- wl_signal_add(&view->events.unmap, &seat_view->view_unmap);
- seat_view->view_destroy.notify = seat_view_handle_destroy;
- wl_signal_add(&view->events.destroy, &seat_view->view_destroy);
-
- return seat_view;
-}
-
-struct roots_seat_view *roots_seat_view_from_view(
- struct roots_seat *seat, struct roots_view *view) {
- if (view == NULL) {
- return NULL;
- }
-
- bool found = false;
- struct roots_seat_view *seat_view = NULL;
- wl_list_for_each(seat_view, &seat->views, link) {
- if (seat_view->view == view) {
- found = true;
- break;
- }
- }
- if (!found) {
- seat_view = seat_add_view(seat, view);
- if (seat_view == NULL) {
- wlr_log(WLR_ERROR, "Allocation failed");
- return NULL;
- }
- }
-
- return seat_view;
-}
-
-bool roots_seat_allow_input(struct roots_seat *seat,
- struct wl_resource *resource) {
- return !seat->exclusive_client ||
- wl_resource_get_client(resource) == seat->exclusive_client;
-}
-
-void roots_seat_set_focus(struct roots_seat *seat, struct roots_view *view) {
- if (view && !roots_seat_allow_input(seat, view->wlr_surface->resource)) {
- return;
- }
-
- // Make sure the view will be rendered on top of others, even if it's
- // already focused in this seat
- if (view != NULL) {
- wl_list_remove(&view->link);
- wl_list_insert(&seat->input->server->desktop->views, &view->link);
- }
-
- bool unfullscreen = true;
-
-#if WLR_HAS_XWAYLAND
- if (view && view->type == ROOTS_XWAYLAND_VIEW) {
- struct roots_xwayland_surface *xwayland_surface =
- roots_xwayland_surface_from_view(view);
- if (xwayland_surface->xwayland_surface->override_redirect) {
- unfullscreen = false;
- }
- }
-#endif
-
- if (view && unfullscreen) {
- struct roots_desktop *desktop = view->desktop;
- struct roots_output *output;
- struct wlr_box box;
- view_get_box(view, &box);
- wl_list_for_each(output, &desktop->outputs, link) {
- if (output->fullscreen_view &&
- output->fullscreen_view != view &&
- wlr_output_layout_intersects(
- desktop->layout,
- output->wlr_output, &box)) {
- view_set_fullscreen(output->fullscreen_view,
- false, NULL);
- }
- }
- }
-
- struct roots_view *prev_focus = roots_seat_get_focus(seat);
- if (view == prev_focus) {
- return;
- }
-
-#if WLR_HAS_XWAYLAND
- if (view && view->type == ROOTS_XWAYLAND_VIEW) {
- struct roots_xwayland_surface *xwayland_surface =
- roots_xwayland_surface_from_view(view);
- if (!wlr_xwayland_or_surface_wants_focus(
- xwayland_surface->xwayland_surface)) {
- return;
- }
- }
-#endif
- struct roots_seat_view *seat_view = NULL;
- if (view != NULL) {
- seat_view = roots_seat_view_from_view(seat, view);
- if (seat_view == NULL) {
- return;
- }
- }
-
- seat->has_focus = false;
-
- // Deactivate the old view if it is not focused by some other seat
- if (prev_focus != NULL && !input_view_has_focus(seat->input, prev_focus)) {
- view_activate(prev_focus, false);
- }
-
- if (view == NULL) {
- seat->cursor->mode = ROOTS_CURSOR_PASSTHROUGH;
- wlr_seat_keyboard_clear_focus(seat->seat);
- roots_input_method_relay_set_focus(&seat->im_relay, NULL);
- return;
- }
-
- wl_list_remove(&seat_view->link);
- wl_list_insert(&seat->views, &seat_view->link);
-
- view_damage_whole(view);
-
- if (seat->focused_layer) {
- return;
- }
-
- view_activate(view, true);
- seat->has_focus = true;
-
- // An existing keyboard grab might try to deny setting focus, so cancel it
- wlr_seat_keyboard_end_grab(seat->seat);
-
- struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->seat);
- if (keyboard != NULL) {
- wlr_seat_keyboard_notify_enter(seat->seat, view->wlr_surface,
- keyboard->keycodes, keyboard->num_keycodes,
- &keyboard->modifiers);
- /* FIXME: Move this to a better place */
- struct roots_tablet_pad *pad;
- wl_list_for_each(pad, &seat->tablet_pads, link) {
- if (pad->tablet) {
- wlr_tablet_v2_tablet_pad_notify_enter(pad->tablet_v2_pad, pad->tablet->tablet_v2, view->wlr_surface);
- }
- }
- } else {
- wlr_seat_keyboard_notify_enter(seat->seat, view->wlr_surface,
- NULL, 0, NULL);
- }
-
- if (seat->cursor) {
- roots_cursor_update_focus(seat->cursor);
- }
-
- roots_input_method_relay_set_focus(&seat->im_relay, view->wlr_surface);
-}
-
-/**
- * Focus semantics of layer surfaces are somewhat detached from the normal focus
- * flow. For layers above the shell layer, for example, you cannot unfocus them.
- * You also cannot alt-tab between layer surfaces and shell surfaces.
- */
-void roots_seat_set_focus_layer(struct roots_seat *seat,
- struct wlr_layer_surface_v1 *layer) {
- if (!layer) {
- if (seat->focused_layer) {
- seat->focused_layer = NULL;
- if (!wl_list_empty(&seat->views)) {
- // Focus first view
- struct roots_seat_view *first_seat_view = wl_container_of(
- seat->views.next, first_seat_view, link);
- roots_seat_set_focus(seat, first_seat_view->view);
- }
- }
- return;
- }
- struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->seat);
- if (!roots_seat_allow_input(seat, layer->resource)) {
- return;
- }
- if (seat->has_focus) {
- struct roots_view *prev_focus = roots_seat_get_focus(seat);
- wlr_seat_keyboard_clear_focus(seat->seat);
- view_activate(prev_focus, false);
- }
- seat->has_focus = false;
- if (layer->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
- seat->focused_layer = layer;
- }
- if (keyboard != NULL) {
- wlr_seat_keyboard_notify_enter(seat->seat, layer->surface,
- keyboard->keycodes, keyboard->num_keycodes,
- &keyboard->modifiers);
- } else {
- wlr_seat_keyboard_notify_enter(seat->seat, layer->surface,
- NULL, 0, NULL);
- }
-
-
- if (seat->cursor) {
- roots_cursor_update_focus(seat->cursor);
- }
-}
-
-void roots_seat_set_exclusive_client(struct roots_seat *seat,
- struct wl_client *client) {
- if (!client) {
- seat->exclusive_client = client;
- // Triggers a refocus of the topmost surface layer if necessary
- // TODO: Make layer surface focus per-output based on cursor position
- struct roots_output *output;
- wl_list_for_each(output, &seat->input->server->desktop->outputs, link) {
- arrange_layers(output);
- }
- return;
- }
- if (seat->focused_layer) {
- if (wl_resource_get_client(seat->focused_layer->resource) != client) {
- roots_seat_set_focus_layer(seat, NULL);
- }
- }
- if (seat->has_focus) {
- struct roots_view *focus = roots_seat_get_focus(seat);
- if (wl_resource_get_client(focus->wlr_surface->resource) != client) {
- roots_seat_set_focus(seat, NULL);
- }
- }
- if (seat->seat->pointer_state.focused_client) {
- if (seat->seat->pointer_state.focused_client->client != client) {
- wlr_seat_pointer_clear_focus(seat->seat);
- }
- }
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
- struct wlr_touch_point *point;
- wl_list_for_each(point, &seat->seat->touch_state.touch_points, link) {
- if (point->client->client != client) {
- wlr_seat_touch_point_clear_focus(seat->seat,
- now.tv_nsec / 1000, point->touch_id);
- }
- }
- seat->exclusive_client = client;
-}
-
-void roots_seat_cycle_focus(struct roots_seat *seat) {
- if (wl_list_empty(&seat->views)) {
- return;
- }
-
- struct roots_seat_view *first_seat_view = wl_container_of(
- seat->views.next, first_seat_view, link);
- if (!seat->has_focus) {
- roots_seat_set_focus(seat, first_seat_view->view);
- return;
- }
- if (wl_list_length(&seat->views) < 2) {
- return;
- }
-
- // Focus the next view
- struct roots_seat_view *next_seat_view = wl_container_of(
- first_seat_view->link.next, next_seat_view, link);
- roots_seat_set_focus(seat, next_seat_view->view);
-
- // Move the first view to the end of the list
- wl_list_remove(&first_seat_view->link);
- wl_list_insert(seat->views.prev, &first_seat_view->link);
-}
-
-void roots_seat_begin_move(struct roots_seat *seat, struct roots_view *view) {
- struct roots_cursor *cursor = seat->cursor;
- cursor->mode = ROOTS_CURSOR_MOVE;
- cursor->offs_x = cursor->cursor->x;
- cursor->offs_y = cursor->cursor->y;
- if (view->maximized) {
- cursor->view_x = view->saved.x;
- cursor->view_y = view->saved.y;
- } else {
- cursor->view_x = view->box.x;
- cursor->view_y = view->box.y;
- }
- view_maximize(view, false);
- wlr_seat_pointer_clear_focus(seat->seat);
-
- wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager,
- ROOTS_XCURSOR_MOVE, seat->cursor->cursor);
-}
-
-void roots_seat_begin_resize(struct roots_seat *seat, struct roots_view *view,
- uint32_t edges) {
- struct roots_cursor *cursor = seat->cursor;
- cursor->mode = ROOTS_CURSOR_RESIZE;
- cursor->offs_x = cursor->cursor->x;
- cursor->offs_y = cursor->cursor->y;
- if (view->maximized) {
- cursor->view_x = view->saved.x;
- cursor->view_y = view->saved.y;
- cursor->view_width = view->saved.width;
- cursor->view_height = view->saved.height;
- } else {
- cursor->view_x = view->box.x;
- cursor->view_y = view->box.y;
- struct wlr_box box;
- view_get_box(view, &box);
- cursor->view_width = box.width;
- cursor->view_height = box.height;
- }
- cursor->resize_edges = edges;
- view_maximize(view, false);
- wlr_seat_pointer_clear_focus(seat->seat);
-
- const char *resize_name = wlr_xcursor_get_resize_name(edges);
- wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager,
- resize_name, seat->cursor->cursor);
-}
-
-void roots_seat_begin_rotate(struct roots_seat *seat, struct roots_view *view) {
- struct roots_cursor *cursor = seat->cursor;
- cursor->mode = ROOTS_CURSOR_ROTATE;
- cursor->offs_x = cursor->cursor->x;
- cursor->offs_y = cursor->cursor->y;
- cursor->view_rotation = view->rotation;
- view_maximize(view, false);
- wlr_seat_pointer_clear_focus(seat->seat);
-
- wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager,
- ROOTS_XCURSOR_ROTATE, seat->cursor->cursor);
-}
-
-void roots_seat_end_compositor_grab(struct roots_seat *seat) {
- struct roots_cursor *cursor = seat->cursor;
- struct roots_view *view = roots_seat_get_focus(seat);
-
- if (view == NULL) {
- return;
- }
-
- switch(cursor->mode) {
- case ROOTS_CURSOR_MOVE:
- view_move(view, cursor->view_x, cursor->view_y);
- break;
- case ROOTS_CURSOR_RESIZE:
- view_move_resize(view, cursor->view_x, cursor->view_y, cursor->view_width, cursor->view_height);
- break;
- case ROOTS_CURSOR_ROTATE:
- view->rotation = cursor->view_rotation;
- break;
- case ROOTS_CURSOR_PASSTHROUGH:
- break;
- }
-
- cursor->mode = ROOTS_CURSOR_PASSTHROUGH;
-}
-
-struct roots_seat *input_last_active_seat(struct roots_input *input) {
- struct roots_seat *seat = NULL, *_seat;
- wl_list_for_each(_seat, &input->seats, link) {
- if (!seat || (seat->seat->last_event.tv_sec > _seat->seat->last_event.tv_sec &&
- seat->seat->last_event.tv_nsec > _seat->seat->last_event.tv_nsec)) {
- seat = _seat;
- }
- }
- return seat;
-}
diff --git a/rootston/switch.c b/rootston/switch.c
deleted file mode 100644
index f95a8e07..00000000
--- a/rootston/switch.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <stdlib.h>
-#include <wlr/util/log.h>
-#include "rootston/bindings.h"
-
-void roots_switch_handle_toggle(struct roots_switch *switch_device,
- struct wlr_event_switch_toggle *event) {
- struct wl_list *bound_switches =
- &switch_device->seat->input->server->config->switches;
- struct roots_switch_config *sc;
- wl_list_for_each(sc, bound_switches, link) {
- if ((sc->name != NULL && strcmp(event->device->name, sc->name) != 0) &&
- (sc->name == NULL && event->switch_type != sc->switch_type)) {
- continue;
- }
- if (sc->switch_state != WLR_SWITCH_STATE_TOGGLE &&
- event->switch_state != sc->switch_state) {
- continue;
- }
- execute_binding_command(switch_device->seat,
- switch_device->seat->input, sc->command);
- }
-}
diff --git a/rootston/text_input.c b/rootston/text_input.c
deleted file mode 100644
index dcd81104..00000000
--- a/rootston/text_input.c
+++ /dev/null
@@ -1,312 +0,0 @@
-#include <assert.h>
-#include <stdlib.h>
-#include <wlr/util/log.h>
-#include "rootston/seat.h"
-#include "rootston/text_input.h"
-
-static struct roots_text_input *relay_get_focusable_text_input(
- struct roots_input_method_relay *relay) {
- struct roots_text_input *text_input = NULL;
- wl_list_for_each(text_input, &relay->text_inputs, link) {
- if (text_input->pending_focused_surface) {
- return text_input;
- }
- }
- return NULL;
-}
-
-static struct roots_text_input *relay_get_focused_text_input(
- struct roots_input_method_relay *relay) {
- struct roots_text_input *text_input = NULL;
- wl_list_for_each(text_input, &relay->text_inputs, link) {
- if (text_input->input->focused_surface) {
- return text_input;
- }
- }
- return NULL;
-}
-
-static void handle_im_commit(struct wl_listener *listener, void *data) {
- struct roots_input_method_relay *relay = wl_container_of(listener, relay,
- input_method_commit);
-
- struct roots_text_input *text_input = relay_get_focused_text_input(relay);
- if (!text_input) {
- return;
- }
- struct wlr_input_method_v2 *context = data;
- assert(context == relay->input_method);
- if (context->current.preedit.text) {
- wlr_text_input_v3_send_preedit_string(text_input->input,
- context->current.preedit.text,
- context->current.preedit.cursor_begin,
- context->current.preedit.cursor_end);
- }
- if (context->current.commit_text) {
- wlr_text_input_v3_send_commit_string(text_input->input,
- context->current.commit_text);
- }
- if (context->current.delete.before_length
- || context->current.delete.after_length) {
- wlr_text_input_v3_send_delete_surrounding_text(text_input->input,
- context->current.delete.before_length,
- context->current.delete.after_length);
- }
- wlr_text_input_v3_send_done(text_input->input);
-}
-
-static void text_input_set_pending_focused_surface(
- struct roots_text_input *text_input, struct wlr_surface *surface) {
- text_input->pending_focused_surface = surface;
- wl_signal_add(&surface->events.destroy,
- &text_input->pending_focused_surface_destroy);
-}
-
-static void text_input_clear_pending_focused_surface(
- struct roots_text_input *text_input) {
- wl_list_remove(&text_input->pending_focused_surface_destroy.link);
- wl_list_init(&text_input->pending_focused_surface_destroy.link);
- text_input->pending_focused_surface = NULL;
-}
-
-static void handle_im_destroy(struct wl_listener *listener, void *data) {
- struct roots_input_method_relay *relay = wl_container_of(listener, relay,
- input_method_destroy);
- struct wlr_input_method_v2 *context = data;
- assert(context == relay->input_method);
- relay->input_method = NULL;
- struct roots_text_input *text_input = relay_get_focused_text_input(relay);
- if (text_input) {
- // keyboard focus is still there, so keep the surface at hand in case
- // the input method returns
- text_input_set_pending_focused_surface(text_input,
- text_input->input->focused_surface);
- wlr_text_input_v3_send_leave(text_input->input);
- }
-}
-
-static void relay_send_im_done(struct roots_input_method_relay *relay,
- struct wlr_text_input_v3 *input) {
- struct wlr_input_method_v2 *input_method = relay->input_method;
- if (!input_method) {
- wlr_log(WLR_INFO, "Sending IM_DONE but im is gone");
- return;
- }
- // TODO: only send each of those if they were modified
- wlr_input_method_v2_send_surrounding_text(input_method,
- input->current.surrounding.text, input->current.surrounding.cursor,
- input->current.surrounding.anchor);
- wlr_input_method_v2_send_text_change_cause(input_method,
- input->current.text_change_cause);
- wlr_input_method_v2_send_content_type(input_method,
- input->current.content_type.hint, input->current.content_type.purpose);
- wlr_input_method_v2_send_done(input_method);
- // TODO: pass intent, display popup size
-}
-
-static struct roots_text_input *text_input_to_roots(
- struct roots_input_method_relay *relay,
- struct wlr_text_input_v3 *text_input) {
- struct roots_text_input *roots_text_input = NULL;
- wl_list_for_each(roots_text_input, &relay->text_inputs, link) {
- if (roots_text_input->input == text_input) {
- return roots_text_input;
- }
- }
- return NULL;
-}
-
-static void handle_text_input_enable(struct wl_listener *listener, void *data) {
- struct roots_input_method_relay *relay = wl_container_of(listener, relay,
- text_input_enable);
- if (relay->input_method == NULL) {
- wlr_log(WLR_INFO, "Enabling text input when input method is gone");
- return;
- }
- struct roots_text_input *text_input = text_input_to_roots(relay,
- (struct wlr_text_input_v3*)data);
- wlr_input_method_v2_send_activate(relay->input_method);
- relay_send_im_done(relay, text_input->input);
-}
-
-static void handle_text_input_commit(struct wl_listener *listener,
- void *data) {
- struct roots_input_method_relay *relay = wl_container_of(listener, relay,
- text_input_commit);
- struct roots_text_input *text_input = text_input_to_roots(relay,
- (struct wlr_text_input_v3*)data);
- if (!text_input->input->current_enabled) {
- wlr_log(WLR_INFO, "Inactive text input tried to commit an update");
- return;
- }
- wlr_log(WLR_DEBUG, "Text input committed update");
- if (relay->input_method == NULL) {
- wlr_log(WLR_INFO, "Text input committed, but input method is gone");
- return;
- }
- relay_send_im_done(relay, text_input->input);
-}
-
-static void relay_disable_text_input(struct roots_input_method_relay *relay,
- struct roots_text_input *text_input) {
- if (relay->input_method == NULL) {
- wlr_log(WLR_DEBUG, "Disabling text input, but input method is gone");
- return;
- }
- wlr_input_method_v2_send_deactivate(relay->input_method);
- relay_send_im_done(relay, text_input->input);
-}
-
-static void handle_text_input_disable(struct wl_listener *listener,
- void *data) {
- struct roots_input_method_relay *relay = wl_container_of(listener, relay,
- text_input_disable);
- struct roots_text_input *text_input = text_input_to_roots(relay,
- (struct wlr_text_input_v3*)data);
- relay_disable_text_input(relay, text_input);
-}
-
-static void handle_text_input_destroy(struct wl_listener *listener,
- void *data) {
- struct roots_input_method_relay *relay = wl_container_of(listener, relay,
- text_input_destroy);
- struct roots_text_input *text_input = text_input_to_roots(relay,
- (struct wlr_text_input_v3*)data);
-
- if (text_input->input->current_enabled) {
- relay_disable_text_input(relay, text_input);
- }
- text_input_clear_pending_focused_surface(text_input);
- wl_list_remove(&text_input->link);
- text_input->input = NULL;
- free(text_input);
-}
-
-static void handle_pending_focused_surface_destroy(struct wl_listener *listener,
- void *data) {
- struct roots_text_input *text_input = wl_container_of(listener, text_input,
- pending_focused_surface_destroy);
- struct wlr_surface *surface = data;
- assert(text_input->pending_focused_surface == surface);
- text_input->pending_focused_surface = NULL;
-}
-
-struct roots_text_input *roots_text_input_create(
- struct roots_input_method_relay *relay,
- struct wlr_text_input_v3 *text_input) {
- struct roots_text_input *input = calloc(1, sizeof(struct roots_text_input));
- if (!input) {
- return NULL;
- }
- input->input = text_input;
- input->relay = relay;
-
- wl_signal_add(&text_input->events.enable, &relay->text_input_enable);
- relay->text_input_enable.notify = handle_text_input_enable;
-
- wl_signal_add(&text_input->events.commit, &relay->text_input_commit);
- relay->text_input_commit.notify = handle_text_input_commit;
-
- wl_signal_add(&text_input->events.disable, &relay->text_input_disable);
- relay->text_input_disable.notify = handle_text_input_disable;
-
- wl_signal_add(&text_input->events.destroy, &relay->text_input_destroy);
- relay->text_input_destroy.notify = handle_text_input_destroy;
-
- input->pending_focused_surface_destroy.notify =
- handle_pending_focused_surface_destroy;
- wl_list_init(&input->pending_focused_surface_destroy.link);
- return input;
-}
-
-static void relay_handle_text_input(struct wl_listener *listener,
- void *data) {
- struct roots_input_method_relay *relay = wl_container_of(listener, relay,
- text_input_new);
- struct wlr_text_input_v3 *wlr_text_input = data;
- if (relay->seat->seat != wlr_text_input->seat) {
- return;
- }
-
- struct roots_text_input *text_input = roots_text_input_create(relay,
- wlr_text_input);
- if (!text_input) {
- return;
- }
- wl_list_insert(&relay->text_inputs, &text_input->link);
-}
-
-static void relay_handle_input_method(struct wl_listener *listener,
- void *data) {
- struct roots_input_method_relay *relay = wl_container_of(listener, relay,
- input_method_new);
- struct wlr_input_method_v2 *input_method = data;
- if (relay->seat->seat != input_method->seat) {
- return;
- }
-
- if (relay->input_method != NULL) {
- wlr_log(WLR_INFO, "Attempted to connect second input method to a seat");
- wlr_input_method_v2_send_unavailable(input_method);
- return;
- }
-
- relay->input_method = input_method;
- wl_signal_add(&relay->input_method->events.commit,
- &relay->input_method_commit);
- relay->input_method_commit.notify = handle_im_commit;
- wl_signal_add(&relay->input_method->events.destroy,
- &relay->input_method_destroy);
- relay->input_method_destroy.notify = handle_im_destroy;
-
- struct roots_text_input *text_input = relay_get_focusable_text_input(relay);
- if (text_input) {
- wlr_text_input_v3_send_enter(text_input->input,
- text_input->pending_focused_surface);
- text_input_clear_pending_focused_surface(text_input);
- }
-}
-
-void roots_input_method_relay_init(struct roots_seat *seat,
- struct roots_input_method_relay *relay) {
- relay->seat = seat;
- wl_list_init(&relay->text_inputs);
-
- relay->text_input_new.notify = relay_handle_text_input;
- wl_signal_add(&seat->input->server->desktop->text_input->events.text_input,
- &relay->text_input_new);
-
- relay->input_method_new.notify = relay_handle_input_method;
- wl_signal_add(
- &seat->input->server->desktop->input_method->events.input_method,
- &relay->input_method_new);
-}
-
-void roots_input_method_relay_set_focus(struct roots_input_method_relay *relay,
- struct wlr_surface *surface) {
- struct roots_text_input *text_input;
- wl_list_for_each(text_input, &relay->text_inputs, link) {
- if (text_input->pending_focused_surface) {
- assert(text_input->input->focused_surface == NULL);
- if (surface != text_input->pending_focused_surface) {
- text_input_clear_pending_focused_surface(text_input);
- }
- } else if (text_input->input->focused_surface) {
- assert(text_input->pending_focused_surface == NULL);
- if (surface != text_input->input->focused_surface) {
- relay_disable_text_input(relay, text_input);
- wlr_text_input_v3_send_leave(text_input->input);
- }
- }
-
- if (surface
- && wl_resource_get_client(text_input->input->resource)
- == wl_resource_get_client(surface->resource)) {
- if (relay->input_method) {
- wlr_text_input_v3_send_enter(text_input->input, surface);
- } else {
- text_input_set_pending_focused_surface(text_input, surface);
- }
- }
- }
-}
diff --git a/rootston/view.c b/rootston/view.c
deleted file mode 100644
index 6619743a..00000000
--- a/rootston/view.c
+++ /dev/null
@@ -1,685 +0,0 @@
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wlr/types/wlr_output_layout.h>
-#include "rootston/desktop.h"
-#include "rootston/input.h"
-#include "rootston/seat.h"
-#include "rootston/server.h"
-#include "rootston/view.h"
-
-void view_init(struct roots_view *view, const struct roots_view_interface *impl,
- enum roots_view_type type, struct roots_desktop *desktop) {
- assert(impl->destroy);
- view->impl = impl;
- view->type = type;
- view->desktop = desktop;
- view->alpha = 1.0f;
- wl_signal_init(&view->events.unmap);
- wl_signal_init(&view->events.destroy);
- wl_list_init(&view->children);
-}
-
-void view_destroy(struct roots_view *view) {
- if (view == NULL) {
- return;
- }
-
- wl_signal_emit(&view->events.destroy, view);
-
- if (view->wlr_surface != NULL) {
- view_unmap(view);
- }
-
- // Can happen if fullscreened while unmapped, and hasn't been mapped
- if (view->fullscreen_output != NULL) {
- view->fullscreen_output->fullscreen_view = NULL;
- }
-
- view->impl->destroy(view);
-}
-
-void view_get_box(const struct roots_view *view, struct wlr_box *box) {
- box->x = view->box.x;
- box->y = view->box.y;
- box->width = view->box.width;
- box->height = view->box.height;
-}
-
-void view_get_deco_box(const struct roots_view *view, struct wlr_box *box) {
- view_get_box(view, box);
- if (!view->decorated) {
- return;
- }
-
- box->x -= view->border_width;
- box->y -= (view->border_width + view->titlebar_height);
- box->width += view->border_width * 2;
- box->height += (view->border_width * 2 + view->titlebar_height);
-}
-
-enum roots_deco_part view_get_deco_part(struct roots_view *view, double sx,
- double sy) {
- if (!view->decorated) {
- return ROOTS_DECO_PART_NONE;
- }
-
- int sw = view->wlr_surface->current.width;
- int sh = view->wlr_surface->current.height;
- int bw = view->border_width;
- int titlebar_h = view->titlebar_height;
-
- if (sx > 0 && sx < sw && sy < 0 && sy > -view->titlebar_height) {
- return ROOTS_DECO_PART_TITLEBAR;
- }
-
- enum roots_deco_part parts = 0;
- if (sy >= -(titlebar_h + bw) &&
- sy <= sh + bw) {
- if (sx < 0 && sx > -bw) {
- parts |= ROOTS_DECO_PART_LEFT_BORDER;
- } else if (sx > sw && sx < sw + bw) {
- parts |= ROOTS_DECO_PART_RIGHT_BORDER;
- }
- }
-
- if (sx >= -bw && sx <= sw + bw) {
- if (sy > sh && sy <= sh + bw) {
- parts |= ROOTS_DECO_PART_BOTTOM_BORDER;
- } else if (sy >= -(titlebar_h + bw) && sy < 0) {
- parts |= ROOTS_DECO_PART_TOP_BORDER;
- }
- }
-
- // TODO corners
-
- return parts;
-}
-
-static void view_update_output(const struct roots_view *view,
- const struct wlr_box *before) {
- struct roots_desktop *desktop = view->desktop;
-
- if (view->wlr_surface == NULL) {
- return;
- }
-
- struct wlr_box box;
- view_get_box(view, &box);
-
- struct roots_output *output;
- wl_list_for_each(output, &desktop->outputs, link) {
- bool intersected = before != NULL && wlr_output_layout_intersects(
- desktop->layout, output->wlr_output, before);
- bool intersects = wlr_output_layout_intersects(desktop->layout,
- output->wlr_output, &box);
- if (intersected && !intersects) {
- wlr_surface_send_leave(view->wlr_surface, output->wlr_output);
- if (view->toplevel_handle) {
- wlr_foreign_toplevel_handle_v1_output_leave(
- view->toplevel_handle, output->wlr_output);
- }
- }
- if (!intersected && intersects) {
- wlr_surface_send_enter(view->wlr_surface, output->wlr_output);
- if (view->toplevel_handle) {
- wlr_foreign_toplevel_handle_v1_output_enter(
- view->toplevel_handle, output->wlr_output);
- }
- }
- }
-}
-
-void view_move(struct roots_view *view, double x, double y) {
- if (view->box.x == x && view->box.y == y) {
- return;
- }
-
- struct wlr_box before;
- view_get_box(view, &before);
- if (view->impl->move) {
- view->impl->move(view, x, y);
- } else {
- view_update_position(view, x, y);
- }
- view_update_output(view, &before);
-}
-
-void view_activate(struct roots_view *view, bool activate) {
- if (view->impl->activate) {
- view->impl->activate(view, activate);
- }
-
- if (view->toplevel_handle) {
- wlr_foreign_toplevel_handle_v1_set_activated(view->toplevel_handle,
- activate);
- }
-}
-
-void view_resize(struct roots_view *view, uint32_t width, uint32_t height) {
- struct wlr_box before;
- view_get_box(view, &before);
- if (view->impl->resize) {
- view->impl->resize(view, width, height);
- }
- view_update_output(view, &before);
-}
-
-void view_move_resize(struct roots_view *view, double x, double y,
- uint32_t width, uint32_t height) {
- bool update_x = x != view->box.x;
- bool update_y = y != view->box.y;
- if (!update_x && !update_y) {
- view_resize(view, width, height);
- return;
- }
-
- if (view->impl->move_resize) {
- view->impl->move_resize(view, x, y, width, height);
- return;
- }
-
- view->pending_move_resize.update_x = update_x;
- view->pending_move_resize.update_y = update_y;
- view->pending_move_resize.x = x;
- view->pending_move_resize.y = y;
- view->pending_move_resize.width = width;
- view->pending_move_resize.height = height;
-
- view_resize(view, width, height);
-}
-
-static struct wlr_output *view_get_output(struct roots_view *view) {
- struct wlr_box view_box;
- view_get_box(view, &view_box);
-
- double output_x, output_y;
- wlr_output_layout_closest_point(view->desktop->layout, NULL,
- view->box.x + (double)view_box.width/2,
- view->box.y + (double)view_box.height/2,
- &output_x, &output_y);
- return wlr_output_layout_output_at(view->desktop->layout, output_x,
- output_y);
-}
-
-void view_arrange_maximized(struct roots_view *view) {
- if (view->fullscreen_output != NULL) {
- return;
- }
-
- struct wlr_box view_box;
- view_get_box(view, &view_box);
-
- struct wlr_output *output = view_get_output(view);
- struct roots_output *roots_output = output->data;
- struct wlr_box *output_box =
- wlr_output_layout_get_box(view->desktop->layout, output);
- struct wlr_box usable_area;
- memcpy(&usable_area, &roots_output->usable_area,
- sizeof(struct wlr_box));
- usable_area.x += output_box->x;
- usable_area.y += output_box->y;
-
- view_move_resize(view, usable_area.x, usable_area.y,
- usable_area.width, usable_area.height);
- view_rotate(view, 0);
-}
-
-void view_maximize(struct roots_view *view, bool maximized) {
- if (view->maximized == maximized || view->fullscreen_output != NULL) {
- return;
- }
-
- if (view->impl->maximize) {
- view->impl->maximize(view, maximized);
- }
-
- if (view->toplevel_handle) {
- wlr_foreign_toplevel_handle_v1_set_maximized(view->toplevel_handle,
- maximized);
- }
-
- if (!view->maximized && maximized) {
- view->maximized = true;
- view->saved.x = view->box.x;
- view->saved.y = view->box.y;
- view->saved.rotation = view->rotation;
- view->saved.width = view->box.width;
- view->saved.height = view->box.height;
-
- view_arrange_maximized(view);
- }
-
- if (view->maximized && !maximized) {
- view->maximized = false;
-
- view_move_resize(view, view->saved.x, view->saved.y, view->saved.width,
- view->saved.height);
- view_rotate(view, view->saved.rotation);
- }
-}
-
-void view_set_fullscreen(struct roots_view *view, bool fullscreen,
- struct wlr_output *output) {
- bool was_fullscreen = view->fullscreen_output != NULL;
- if (was_fullscreen == fullscreen) {
- // TODO: support changing the output?
- return;
- }
-
- // TODO: check if client is focused?
-
- if (view->impl->set_fullscreen) {
- view->impl->set_fullscreen(view, fullscreen);
- }
-
- if (view->toplevel_handle) {
- wlr_foreign_toplevel_handle_v1_set_fullscreen(view->toplevel_handle,
- fullscreen);
- }
-
- if (!was_fullscreen && fullscreen) {
- if (output == NULL) {
- output = view_get_output(view);
- }
- struct roots_output *roots_output =
- desktop_output_from_wlr_output(view->desktop, output);
- if (roots_output == NULL) {
- return;
- }
-
- struct wlr_box view_box;
- view_get_box(view, &view_box);
-
- view->saved.x = view->box.x;
- view->saved.y = view->box.y;
- view->saved.rotation = view->rotation;
- view->saved.width = view_box.width;
- view->saved.height = view_box.height;
-
- struct wlr_box *output_box =
- wlr_output_layout_get_box(view->desktop->layout, output);
- view_move_resize(view, output_box->x, output_box->y, output_box->width,
- output_box->height);
- view_rotate(view, 0);
-
- roots_output->fullscreen_view = view;
- view->fullscreen_output = roots_output;
- output_damage_whole(roots_output);
- }
-
- if (was_fullscreen && !fullscreen) {
- view_move_resize(view, view->saved.x, view->saved.y, view->saved.width,
- view->saved.height);
- view_rotate(view, view->saved.rotation);
-
- output_damage_whole(view->fullscreen_output);
- view->fullscreen_output->fullscreen_view = NULL;
- view->fullscreen_output = NULL;
- }
-}
-
-void view_rotate(struct roots_view *view, float rotation) {
- if (view->rotation == rotation) {
- return;
- }
-
- view_damage_whole(view);
- view->rotation = rotation;
- view_damage_whole(view);
-}
-
-void view_cycle_alpha(struct roots_view *view) {
- view->alpha -= 0.05;
- /* Don't go completely transparent */
- if (view->alpha < 0.1) {
- view->alpha = 1.0;
- }
- view_damage_whole(view);
-}
-
-void view_close(struct roots_view *view) {
- if (view->impl->close) {
- view->impl->close(view);
- }
-}
-
-bool view_center(struct roots_view *view) {
- struct wlr_box box;
- view_get_box(view, &box);
-
- struct roots_desktop *desktop = view->desktop;
- struct roots_input *input = desktop->server->input;
- struct roots_seat *seat = input_last_active_seat(input);
- if (!seat) {
- return false;
- }
-
- struct wlr_output *output = wlr_output_layout_output_at(desktop->layout,
- seat->cursor->cursor->x, seat->cursor->cursor->y);
- if (!output) {
- // empty layout
- return false;
- }
-
- const struct wlr_output_layout_output *l_output =
- wlr_output_layout_get(desktop->layout, output);
-
- int width, height;
- wlr_output_effective_resolution(output, &width, &height);
-
- double view_x = (double)(width - box.width) / 2 + l_output->x;
- double view_y = (double)(height - box.height) / 2 + l_output->y;
- view_move(view, view_x, view_y);
-
- return true;
-}
-
-void view_child_destroy(struct roots_view_child *child) {
- if (child == NULL) {
- return;
- }
- view_damage_whole(child->view);
- wl_list_remove(&child->link);
- wl_list_remove(&child->commit.link);
- wl_list_remove(&child->new_subsurface.link);
- child->impl->destroy(child);
-}
-
-static void view_child_handle_commit(struct wl_listener *listener,
- void *data) {
- struct roots_view_child *child = wl_container_of(listener, child, commit);
- view_apply_damage(child->view);
-}
-
-static void view_child_handle_new_subsurface(struct wl_listener *listener,
- void *data) {
- struct roots_view_child *child =
- wl_container_of(listener, child, new_subsurface);
- struct wlr_subsurface *wlr_subsurface = data;
- subsurface_create(child->view, wlr_subsurface);
-}
-
-void view_child_init(struct roots_view_child *child,
- const struct roots_view_child_interface *impl, struct roots_view *view,
- struct wlr_surface *wlr_surface) {
- assert(impl->destroy);
- child->impl = impl;
- child->view = view;
- child->wlr_surface = wlr_surface;
- child->commit.notify = view_child_handle_commit;
- wl_signal_add(&wlr_surface->events.commit, &child->commit);
- child->new_subsurface.notify = view_child_handle_new_subsurface;
- wl_signal_add(&wlr_surface->events.new_subsurface, &child->new_subsurface);
- wl_list_insert(&view->children, &child->link);
-}
-
-static const struct roots_view_child_interface subsurface_impl;
-
-static void subsurface_destroy(struct roots_view_child *child) {
- assert(child->impl == &subsurface_impl);
- struct roots_subsurface *subsurface = (struct roots_subsurface *)child;
- wl_list_remove(&subsurface->destroy.link);
- wl_list_remove(&subsurface->map.link);
- wl_list_remove(&subsurface->unmap.link);
- free(subsurface);
-}
-
-static const struct roots_view_child_interface subsurface_impl = {
- .destroy = subsurface_destroy,
-};
-
-static void subsurface_handle_destroy(struct wl_listener *listener,
- void *data) {
- struct roots_subsurface *subsurface =
- wl_container_of(listener, subsurface, destroy);
- view_child_destroy(&subsurface->view_child);
-}
-
-static void subsurface_handle_map(struct wl_listener *listener,
- void *data) {
- struct roots_subsurface *subsurface =
- wl_container_of(listener, subsurface, map);
- struct roots_view *view = subsurface->view_child.view;
- view_damage_whole(view);
- input_update_cursor_focus(view->desktop->server->input);
-}
-
-static void subsurface_handle_unmap(struct wl_listener *listener,
- void *data) {
- struct roots_subsurface *subsurface =
- wl_container_of(listener, subsurface, unmap);
- struct roots_view *view = subsurface->view_child.view;
- view_damage_whole(view);
- input_update_cursor_focus(view->desktop->server->input);
-}
-
-struct roots_subsurface *subsurface_create(struct roots_view *view,
- struct wlr_subsurface *wlr_subsurface) {
- struct roots_subsurface *subsurface =
- calloc(1, sizeof(struct roots_subsurface));
- if (subsurface == NULL) {
- return NULL;
- }
- subsurface->wlr_subsurface = wlr_subsurface;
- view_child_init(&subsurface->view_child, &subsurface_impl,
- view, wlr_subsurface->surface);
- subsurface->destroy.notify = subsurface_handle_destroy;
- wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy);
- subsurface->map.notify = subsurface_handle_map;
- wl_signal_add(&wlr_subsurface->events.map, &subsurface->map);
- subsurface->unmap.notify = subsurface_handle_unmap;
- wl_signal_add(&wlr_subsurface->events.unmap, &subsurface->unmap);
- return subsurface;
-}
-
-static void view_handle_new_subsurface(struct wl_listener *listener,
- void *data) {
- struct roots_view *view = wl_container_of(listener, view, new_subsurface);
- struct wlr_subsurface *wlr_subsurface = data;
- subsurface_create(view, wlr_subsurface);
-}
-
-void view_map(struct roots_view *view, struct wlr_surface *surface) {
- assert(view->wlr_surface == NULL);
-
- view->wlr_surface = surface;
-
- struct wlr_subsurface *subsurface;
- wl_list_for_each(subsurface, &view->wlr_surface->subsurfaces,
- parent_link) {
- subsurface_create(view, subsurface);
- }
-
- view->new_subsurface.notify = view_handle_new_subsurface;
- wl_signal_add(&view->wlr_surface->events.new_subsurface,
- &view->new_subsurface);
-
- wl_list_insert(&view->desktop->views, &view->link);
- view_damage_whole(view);
- input_update_cursor_focus(view->desktop->server->input);
-}
-
-void view_unmap(struct roots_view *view) {
- assert(view->wlr_surface != NULL);
-
- wl_signal_emit(&view->events.unmap, view);
-
- view_damage_whole(view);
- wl_list_remove(&view->link);
-
- wl_list_remove(&view->new_subsurface.link);
-
- struct roots_view_child *child, *tmp;
- wl_list_for_each_safe(child, tmp, &view->children, link) {
- view_child_destroy(child);
- }
-
- if (view->fullscreen_output != NULL) {
- output_damage_whole(view->fullscreen_output);
- view->fullscreen_output->fullscreen_view = NULL;
- view->fullscreen_output = NULL;
- }
-
- view->wlr_surface = NULL;
- view->box.width = view->box.height = 0;
-
- if (view->toplevel_handle) {
- wlr_foreign_toplevel_handle_v1_destroy(view->toplevel_handle);
- view->toplevel_handle = NULL;
- }
-}
-
-void view_initial_focus(struct roots_view *view) {
- struct roots_input *input = view->desktop->server->input;
- // TODO what seat gets focus? the one with the last input event?
- struct roots_seat *seat;
- wl_list_for_each(seat, &input->seats, link) {
- roots_seat_set_focus(seat, view);
- }
-}
-
-void view_setup(struct roots_view *view) {
- view_initial_focus(view);
-
- if (view->fullscreen_output == NULL && !view->maximized) {
- view_center(view);
- }
-
- view_create_foreign_toplevel_handle(view);
- view_update_output(view, NULL);
-}
-
-void view_apply_damage(struct roots_view *view) {
- struct roots_output *output;
- wl_list_for_each(output, &view->desktop->outputs, link) {
- output_damage_from_view(output, view);
- }
-}
-
-void view_damage_whole(struct roots_view *view) {
- struct roots_output *output;
- wl_list_for_each(output, &view->desktop->outputs, link) {
- output_damage_whole_view(output, view);
- }
-}
-
-void view_for_each_surface(struct roots_view *view,
- wlr_surface_iterator_func_t iterator, void *user_data) {
- if (view->impl->for_each_surface) {
- view->impl->for_each_surface(view, iterator, user_data);
- } else if (view->wlr_surface) {
- wlr_surface_for_each_surface(view->wlr_surface, iterator, user_data);
- }
-}
-
-void view_update_position(struct roots_view *view, int x, int y) {
- if (view->box.x == x && view->box.y == y) {
- return;
- }
-
- view_damage_whole(view);
- view->box.x = x;
- view->box.y = y;
- view_damage_whole(view);
-}
-
-void view_update_size(struct roots_view *view, int width, int height) {
- if (view->box.width == width && view->box.height == height) {
- return;
- }
-
- view_damage_whole(view);
- view->box.width = width;
- view->box.height = height;
- view_damage_whole(view);
-}
-
-void view_update_decorated(struct roots_view *view, bool decorated) {
- if (view->decorated == decorated) {
- return;
- }
-
- view_damage_whole(view);
- view->decorated = decorated;
- if (decorated) {
- view->border_width = 4;
- view->titlebar_height = 12;
- } else {
- view->border_width = 0;
- view->titlebar_height = 0;
- }
- view_damage_whole(view);
-}
-
-void view_set_title(struct roots_view *view, const char *title) {
- if (view->toplevel_handle) {
- wlr_foreign_toplevel_handle_v1_set_title(view->toplevel_handle, title);
- }
-}
-
-void view_set_app_id(struct roots_view *view, const char *app_id) {
- if (view->toplevel_handle) {
- wlr_foreign_toplevel_handle_v1_set_app_id(view->toplevel_handle, app_id);
- }
-}
-
-static void handle_toplevel_handle_request_maximize(struct wl_listener *listener,
- void *data) {
- struct roots_view *view = wl_container_of(listener, view,
- toplevel_handle_request_maximize);
- struct wlr_foreign_toplevel_handle_v1_maximized_event *event = data;
- view_maximize(view, event->maximized);
-}
-
-static void handle_toplevel_handle_request_activate(struct wl_listener *listener,
- void *data) {
- struct roots_view *view =
- wl_container_of(listener, view, toplevel_handle_request_activate);
- struct wlr_foreign_toplevel_handle_v1_activated_event *event = data;
-
- struct roots_seat *seat;
- wl_list_for_each(seat, &view->desktop->server->input->seats, link) {
- if (event->seat == seat->seat) {
- roots_seat_set_focus(seat, view);
- }
- }
-}
-
-static void handle_toplevel_handle_request_fullscreen(struct wl_listener *listener,
- void *data) {
- struct roots_view *view =
- wl_container_of(listener, view, toplevel_handle_request_fullscreen);
- struct wlr_foreign_toplevel_handle_v1_fullscreen_event *event = data;
- view_set_fullscreen(view, event->fullscreen, event->output);
-}
-
-static void handle_toplevel_handle_request_close(struct wl_listener *listener,
- void *data) {
- struct roots_view *view =
- wl_container_of(listener, view, toplevel_handle_request_close);
- view_close(view);
-}
-
-void view_create_foreign_toplevel_handle(struct roots_view *view) {
- view->toplevel_handle =
- wlr_foreign_toplevel_handle_v1_create(
- view->desktop->foreign_toplevel_manager_v1);
-
- view->toplevel_handle_request_maximize.notify =
- handle_toplevel_handle_request_maximize;
- wl_signal_add(&view->toplevel_handle->events.request_maximize,
- &view->toplevel_handle_request_maximize);
- view->toplevel_handle_request_activate.notify =
- handle_toplevel_handle_request_activate;
- wl_signal_add(&view->toplevel_handle->events.request_activate,
- &view->toplevel_handle_request_activate);
- view->toplevel_handle_request_fullscreen.notify =
- handle_toplevel_handle_request_fullscreen;
- wl_signal_add(&view->toplevel_handle->events.request_fullscreen,
- &view->toplevel_handle_request_fullscreen);
- view->toplevel_handle_request_close.notify =
- handle_toplevel_handle_request_close;
- wl_signal_add(&view->toplevel_handle->events.request_close,
- &view->toplevel_handle_request_close);
-}
diff --git a/rootston/virtual_keyboard.c b/rootston/virtual_keyboard.c
deleted file mode 100644
index e862caf4..00000000
--- a/rootston/virtual_keyboard.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#define _POSIX_C_SOURCE 199309L
-
-#include <wlr/util/log.h>
-#include <wlr/types/wlr_virtual_keyboard_v1.h>
-#include "rootston/virtual_keyboard.h"
-#include "rootston/seat.h"
-
-void handle_virtual_keyboard(struct wl_listener *listener, void *data) {
- struct roots_desktop *desktop =
- wl_container_of(listener, desktop, virtual_keyboard_new);
- struct wlr_virtual_keyboard_v1 *keyboard = data;
-
- struct roots_seat *seat = input_seat_from_wlr_seat(desktop->server->input,
- keyboard->seat);
- if (!seat) {
- wlr_log(WLR_ERROR, "could not find roots seat");
- return;
- }
-
- roots_seat_add_device(seat, &keyboard->input_device);
-}
diff --git a/rootston/xdg_shell.c b/rootston/xdg_shell.c
deleted file mode 100644
index 7b565392..00000000
--- a/rootston/xdg_shell.c
+++ /dev/null
@@ -1,572 +0,0 @@
-#include <assert.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <wayland-server-core.h>
-#include <wlr/types/wlr_box.h>
-#include <wlr/types/wlr_surface.h>
-#include <wlr/types/wlr_xdg_shell.h>
-#include <wlr/util/log.h>
-#include "rootston/cursor.h"
-#include "rootston/desktop.h"
-#include "rootston/input.h"
-#include "rootston/server.h"
-#include "rootston/view.h"
-
-static const struct roots_view_child_interface popup_impl;
-
-static void popup_destroy(struct roots_view_child *child) {
- assert(child->impl == &popup_impl);
- struct roots_xdg_popup *popup = (struct roots_xdg_popup *)child;
- wl_list_remove(&popup->destroy.link);
- wl_list_remove(&popup->new_popup.link);
- wl_list_remove(&popup->map.link);
- wl_list_remove(&popup->unmap.link);
- free(popup);
-}
-
-static const struct roots_view_child_interface popup_impl = {
- .destroy = popup_destroy,
-};
-
-static void popup_handle_destroy(struct wl_listener *listener, void *data) {
- struct roots_xdg_popup *popup =
- wl_container_of(listener, popup, destroy);
- view_child_destroy(&popup->view_child);
-}
-
-static void popup_handle_map(struct wl_listener *listener, void *data) {
- struct roots_xdg_popup *popup = wl_container_of(listener, popup, map);
- view_damage_whole(popup->view_child.view);
- input_update_cursor_focus(popup->view_child.view->desktop->server->input);
-}
-
-static void popup_handle_unmap(struct wl_listener *listener, void *data) {
- struct roots_xdg_popup *popup = wl_container_of(listener, popup, unmap);
- view_damage_whole(popup->view_child.view);
-}
-
-static struct roots_xdg_popup *popup_create(struct roots_view *view,
- struct wlr_xdg_popup *wlr_popup);
-
-static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
- struct roots_xdg_popup *popup =
- wl_container_of(listener, popup, new_popup);
- struct wlr_xdg_popup *wlr_popup = data;
- popup_create(popup->view_child.view, wlr_popup);
-}
-
-static void popup_unconstrain(struct roots_xdg_popup *popup) {
- // get the output of the popup's positioner anchor point and convert it to
- // the toplevel parent's coordinate system and then pass it to
- // wlr_xdg_popup_v6_unconstrain_from_box
-
- // TODO: unconstrain popups for rotated windows
- if (popup->view_child.view->rotation != 0.0) {
- return;
- }
-
- struct roots_view *view = popup->view_child.view;
- struct wlr_output_layout *layout = view->desktop->layout;
- struct wlr_xdg_popup *wlr_popup = popup->wlr_popup;
-
- int anchor_lx, anchor_ly;
- wlr_xdg_popup_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly);
-
- int popup_lx, popup_ly;
- wlr_xdg_popup_get_toplevel_coords(wlr_popup, wlr_popup->geometry.x,
- wlr_popup->geometry.y, &popup_lx, &popup_ly);
- popup_lx += view->box.x;
- popup_ly += view->box.y;
-
- anchor_lx += popup_lx;
- anchor_ly += popup_ly;
-
- double dest_x = 0, dest_y = 0;
- wlr_output_layout_closest_point(layout, NULL, anchor_lx, anchor_ly,
- &dest_x, &dest_y);
-
- struct wlr_output *output =
- wlr_output_layout_output_at(layout, dest_x, dest_y);
- if (output == NULL) {
- return;
- }
-
- struct wlr_box *output_box =
- wlr_output_layout_get_box(view->desktop->layout, output);
-
- // the output box expressed in the coordinate system of the toplevel parent
- // of the popup
- struct wlr_box output_toplevel_sx_box = {
- .x = output_box->x - view->box.x,
- .y = output_box->y - view->box.y,
- .width = output_box->width,
- .height = output_box->height,
- };
-
- wlr_xdg_popup_unconstrain_from_box(
- popup->wlr_popup, &output_toplevel_sx_box);
-}
-
-static struct roots_xdg_popup *popup_create(struct roots_view *view,
- struct wlr_xdg_popup *wlr_popup) {
- struct roots_xdg_popup *popup =
- calloc(1, sizeof(struct roots_xdg_popup));
- if (popup == NULL) {
- return NULL;
- }
- popup->wlr_popup = wlr_popup;
- view_child_init(&popup->view_child, &popup_impl,
- view, wlr_popup->base->surface);
- popup->destroy.notify = popup_handle_destroy;
- wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
- popup->map.notify = popup_handle_map;
- wl_signal_add(&wlr_popup->base->events.map, &popup->map);
- popup->unmap.notify = popup_handle_unmap;
- wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
- popup->new_popup.notify = popup_handle_new_popup;
- wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
-
- popup_unconstrain(popup);
-
- return popup;
-}
-
-
-static void get_size(struct roots_view *view, struct wlr_box *box) {
- struct wlr_xdg_surface *xdg_surface =
- roots_xdg_surface_from_view(view)->xdg_surface;
-
- struct wlr_box geo_box;
- wlr_xdg_surface_get_geometry(xdg_surface, &geo_box);
- box->width = geo_box.width;
- box->height = geo_box.height;
-}
-
-static void activate(struct roots_view *view, bool active) {
- struct wlr_xdg_surface *xdg_surface =
- roots_xdg_surface_from_view(view)->xdg_surface;
- if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
- wlr_xdg_toplevel_set_activated(xdg_surface, active);
- }
-}
-
-static void apply_size_constraints(struct wlr_xdg_surface *xdg_surface,
- uint32_t width, uint32_t height, uint32_t *dest_width,
- uint32_t *dest_height) {
- *dest_width = width;
- *dest_height = height;
-
- struct wlr_xdg_toplevel_state *state = &xdg_surface->toplevel->current;
- if (width < state->min_width) {
- *dest_width = state->min_width;
- } else if (state->max_width > 0 &&
- width > state->max_width) {
- *dest_width = state->max_width;
- }
- if (height < state->min_height) {
- *dest_height = state->min_height;
- } else if (state->max_height > 0 &&
- height > state->max_height) {
- *dest_height = state->max_height;
- }
-}
-
-static void resize(struct roots_view *view, uint32_t width, uint32_t height) {
- struct wlr_xdg_surface *xdg_surface =
- roots_xdg_surface_from_view(view)->xdg_surface;
- if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
- return;
- }
-
- uint32_t constrained_width, constrained_height;
- apply_size_constraints(xdg_surface, width, height, &constrained_width,
- &constrained_height);
-
- wlr_xdg_toplevel_set_size(xdg_surface, constrained_width,
- constrained_height);
-}
-
-static void move_resize(struct roots_view *view, double x, double y,
- uint32_t width, uint32_t height) {
- struct roots_xdg_surface *xdg_surface =
- roots_xdg_surface_from_view(view);
- struct wlr_xdg_surface *wlr_xdg_surface = xdg_surface->xdg_surface;
- if (wlr_xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
- return;
- }
-
- bool update_x = x != view->box.x;
- bool update_y = y != view->box.y;
-
- uint32_t constrained_width, constrained_height;
- apply_size_constraints(wlr_xdg_surface, width, height, &constrained_width,
- &constrained_height);
-
- if (update_x) {
- x = x + width - constrained_width;
- }
- if (update_y) {
- y = y + height - constrained_height;
- }
-
- view->pending_move_resize.update_x = update_x;
- view->pending_move_resize.update_y = update_y;
- view->pending_move_resize.x = x;
- view->pending_move_resize.y = y;
- view->pending_move_resize.width = constrained_width;
- view->pending_move_resize.height = constrained_height;
-
- uint32_t serial = wlr_xdg_toplevel_set_size(wlr_xdg_surface,
- constrained_width, constrained_height);
- if (serial > 0) {
- xdg_surface->pending_move_resize_configure_serial = serial;
- } else if (xdg_surface->pending_move_resize_configure_serial == 0) {
- view_update_position(view, x, y);
- }
-}
-
-static void maximize(struct roots_view *view, bool maximized) {
- struct wlr_xdg_surface *xdg_surface =
- roots_xdg_surface_from_view(view)->xdg_surface;
- if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
- return;
- }
-
- wlr_xdg_toplevel_set_maximized(xdg_surface, maximized);
-}
-
-static void set_fullscreen(struct roots_view *view, bool fullscreen) {
- struct wlr_xdg_surface *xdg_surface =
- roots_xdg_surface_from_view(view)->xdg_surface;
- if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
- return;
- }
-
- wlr_xdg_toplevel_set_fullscreen(xdg_surface, fullscreen);
-}
-
-static void close(struct roots_view *view) {
- struct wlr_xdg_surface *xdg_surface =
- roots_xdg_surface_from_view(view)->xdg_surface;
- struct wlr_xdg_popup *popup = NULL;
- wl_list_for_each(popup, &xdg_surface->popups, link) {
- wlr_xdg_popup_destroy(popup->base);
- }
- wlr_xdg_toplevel_send_close(xdg_surface);
-}
-
-static void for_each_surface(struct roots_view *view,
- wlr_surface_iterator_func_t iterator, void *user_data) {
- struct wlr_xdg_surface *xdg_surface =
- roots_xdg_surface_from_view(view)->xdg_surface;
- wlr_xdg_surface_for_each_surface(xdg_surface, iterator, user_data);
-}
-
-static void destroy(struct roots_view *view) {
- struct roots_xdg_surface *roots_xdg_surface =
- roots_xdg_surface_from_view(view);
- wl_list_remove(&roots_xdg_surface->surface_commit.link);
- wl_list_remove(&roots_xdg_surface->destroy.link);
- wl_list_remove(&roots_xdg_surface->new_popup.link);
- wl_list_remove(&roots_xdg_surface->map.link);
- wl_list_remove(&roots_xdg_surface->unmap.link);
- wl_list_remove(&roots_xdg_surface->request_move.link);
- wl_list_remove(&roots_xdg_surface->request_resize.link);
- wl_list_remove(&roots_xdg_surface->request_maximize.link);
- wl_list_remove(&roots_xdg_surface->request_fullscreen.link);
- wl_list_remove(&roots_xdg_surface->set_title.link);
- wl_list_remove(&roots_xdg_surface->set_app_id.link);
- roots_xdg_surface->xdg_surface->data = NULL;
- free(roots_xdg_surface);
-}
-
-static const struct roots_view_interface view_impl = {
- .activate = activate,
- .resize = resize,
- .move_resize = move_resize,
- .maximize = maximize,
- .set_fullscreen = set_fullscreen,
- .close = close,
- .for_each_surface = for_each_surface,
- .destroy = destroy,
-};
-
-static void handle_request_move(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, request_move);
- struct roots_view *view = &roots_xdg_surface->view;
- struct roots_input *input = view->desktop->server->input;
- struct wlr_xdg_toplevel_move_event *e = data;
- struct roots_seat *seat = input_seat_from_wlr_seat(input, e->seat->seat);
- // TODO verify event serial
- if (!seat || seat->cursor->mode != ROOTS_CURSOR_PASSTHROUGH) {
- return;
- }
- roots_seat_begin_move(seat, view);
-}
-
-static void handle_request_resize(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, request_resize);
- struct roots_view *view = &roots_xdg_surface->view;
- struct roots_input *input = view->desktop->server->input;
- struct wlr_xdg_toplevel_resize_event *e = data;
- // TODO verify event serial
- struct roots_seat *seat = input_seat_from_wlr_seat(input, e->seat->seat);
- assert(seat);
- if (!seat || seat->cursor->mode != ROOTS_CURSOR_PASSTHROUGH) {
- return;
- }
- roots_seat_begin_resize(seat, view, e->edges);
-}
-
-static void handle_request_maximize(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, request_maximize);
- struct roots_view *view = &roots_xdg_surface->view;
- struct wlr_xdg_surface *surface = roots_xdg_surface->xdg_surface;
-
- if (surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
- return;
- }
-
- view_maximize(view, surface->toplevel->client_pending.maximized);
-}
-
-static void handle_request_fullscreen(struct wl_listener *listener,
- void *data) {
- struct roots_xdg_surface *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, request_fullscreen);
- struct roots_view *view = &roots_xdg_surface->view;
- struct wlr_xdg_surface *surface = roots_xdg_surface->xdg_surface;
- struct wlr_xdg_toplevel_set_fullscreen_event *e = data;
-
- if (surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
- return;
- }
-
- view_set_fullscreen(view, e->fullscreen, e->output);
-}
-
-static void handle_set_title(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, set_title);
-
- view_set_title(&roots_xdg_surface->view,
- roots_xdg_surface->xdg_surface->toplevel->title);
-}
-
-static void handle_set_app_id(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, set_app_id);
-
- view_set_app_id(&roots_xdg_surface->view,
- roots_xdg_surface->xdg_surface->toplevel->app_id);
-}
-
-static void handle_surface_commit(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface *roots_surface =
- wl_container_of(listener, roots_surface, surface_commit);
- struct roots_view *view = &roots_surface->view;
- struct wlr_xdg_surface *surface = roots_surface->xdg_surface;
-
- if (!surface->mapped) {
- return;
- }
-
- view_apply_damage(view);
-
- struct wlr_box size;
- get_size(view, &size);
- view_update_size(view, size.width, size.height);
-
- uint32_t pending_serial =
- roots_surface->pending_move_resize_configure_serial;
- if (pending_serial > 0 && pending_serial >= surface->configure_serial) {
- double x = view->box.x;
- double y = view->box.y;
- if (view->pending_move_resize.update_x) {
- x = view->pending_move_resize.x + view->pending_move_resize.width -
- size.width;
- }
- if (view->pending_move_resize.update_y) {
- y = view->pending_move_resize.y + view->pending_move_resize.height -
- size.height;
- }
- view_update_position(view, x, y);
-
- if (pending_serial == surface->configure_serial) {
- roots_surface->pending_move_resize_configure_serial = 0;
- }
- }
-}
-
-static void handle_new_popup(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, new_popup);
- struct wlr_xdg_popup *wlr_popup = data;
- popup_create(&roots_xdg_surface->view, wlr_popup);
-}
-
-static void handle_map(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, map);
- struct roots_view *view = &roots_xdg_surface->view;
-
- struct wlr_box box;
- get_size(view, &box);
- view->box.width = box.width;
- view->box.height = box.height;
-
- view_map(view, roots_xdg_surface->xdg_surface->surface);
- view_setup(view);
-
- wlr_foreign_toplevel_handle_v1_set_title(view->toplevel_handle,
- roots_xdg_surface->xdg_surface->toplevel->title ?: "none");
- wlr_foreign_toplevel_handle_v1_set_app_id(view->toplevel_handle,
- roots_xdg_surface->xdg_surface->toplevel->app_id ?: "none");
-}
-
-static void handle_unmap(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, unmap);
- view_unmap(&roots_xdg_surface->view);
-}
-
-static void handle_destroy(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, destroy);
- view_destroy(&roots_xdg_surface->view);
-}
-
-void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
- struct wlr_xdg_surface *surface = data;
- assert(surface->role != WLR_XDG_SURFACE_ROLE_NONE);
-
- if (surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
- wlr_log(WLR_DEBUG, "new xdg popup");
- return;
- }
-
- struct roots_desktop *desktop =
- wl_container_of(listener, desktop, xdg_shell_surface);
-
- wlr_log(WLR_DEBUG, "new xdg toplevel: title=%s, app_id=%s",
- surface->toplevel->title, surface->toplevel->app_id);
- wlr_xdg_surface_ping(surface);
-
- struct roots_xdg_surface *roots_surface =
- calloc(1, sizeof(struct roots_xdg_surface));
- if (!roots_surface) {
- return;
- }
-
- view_init(&roots_surface->view, &view_impl, ROOTS_XDG_SHELL_VIEW, desktop);
- roots_surface->xdg_surface = surface;
- surface->data = roots_surface;
-
- view_maximize(&roots_surface->view, surface->toplevel->client_pending.maximized);
- view_set_fullscreen(&roots_surface->view, surface->toplevel->client_pending.fullscreen,
- surface->toplevel->client_pending.fullscreen_output);
-
- roots_surface->surface_commit.notify = handle_surface_commit;
- wl_signal_add(&surface->surface->events.commit,
- &roots_surface->surface_commit);
- roots_surface->destroy.notify = handle_destroy;
- wl_signal_add(&surface->events.destroy, &roots_surface->destroy);
- roots_surface->map.notify = handle_map;
- wl_signal_add(&surface->events.map, &roots_surface->map);
- roots_surface->unmap.notify = handle_unmap;
- wl_signal_add(&surface->events.unmap, &roots_surface->unmap);
- roots_surface->request_move.notify = handle_request_move;
- wl_signal_add(&surface->toplevel->events.request_move,
- &roots_surface->request_move);
- roots_surface->request_resize.notify = handle_request_resize;
- wl_signal_add(&surface->toplevel->events.request_resize,
- &roots_surface->request_resize);
- roots_surface->request_maximize.notify = handle_request_maximize;
- wl_signal_add(&surface->toplevel->events.request_maximize,
- &roots_surface->request_maximize);
- roots_surface->request_fullscreen.notify = handle_request_fullscreen;
- wl_signal_add(&surface->toplevel->events.request_fullscreen,
- &roots_surface->request_fullscreen);
- roots_surface->set_title.notify = handle_set_title;
- wl_signal_add(&surface->toplevel->events.set_title, &roots_surface->set_title);
- roots_surface->set_app_id.notify = handle_set_app_id;
- wl_signal_add(&surface->toplevel->events.set_app_id,
- &roots_surface->set_app_id);
- roots_surface->new_popup.notify = handle_new_popup;
- wl_signal_add(&surface->events.new_popup, &roots_surface->new_popup);
-}
-
-
-static void decoration_handle_destroy(struct wl_listener *listener,
- void *data) {
- struct roots_xdg_toplevel_decoration *decoration =
- wl_container_of(listener, decoration, destroy);
-
- decoration->surface->xdg_toplevel_decoration = NULL;
- view_update_decorated(&decoration->surface->view, false);
- wl_list_remove(&decoration->destroy.link);
- wl_list_remove(&decoration->request_mode.link);
- wl_list_remove(&decoration->surface_commit.link);
- free(decoration);
-}
-
-static void decoration_handle_request_mode(struct wl_listener *listener,
- void *data) {
- struct roots_xdg_toplevel_decoration *decoration =
- wl_container_of(listener, decoration, request_mode);
-
- enum wlr_xdg_toplevel_decoration_v1_mode mode =
- decoration->wlr_decoration->client_pending_mode;
- if (mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_NONE) {
- mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
- }
- wlr_xdg_toplevel_decoration_v1_set_mode(decoration->wlr_decoration, mode);
-}
-
-static void decoration_handle_surface_commit(struct wl_listener *listener,
- void *data) {
- struct roots_xdg_toplevel_decoration *decoration =
- wl_container_of(listener, decoration, surface_commit);
-
- bool decorated = decoration->wlr_decoration->current_mode ==
- WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
- view_update_decorated(&decoration->surface->view, decorated);
-}
-
-void handle_xdg_toplevel_decoration(struct wl_listener *listener, void *data) {
- struct wlr_xdg_toplevel_decoration_v1 *wlr_decoration = data;
-
- wlr_log(WLR_DEBUG, "new xdg toplevel decoration");
-
- struct roots_xdg_surface *xdg_surface = wlr_decoration->surface->data;
- assert(xdg_surface != NULL);
- struct wlr_xdg_surface *wlr_xdg_surface = xdg_surface->xdg_surface;
-
- struct roots_xdg_toplevel_decoration *decoration =
- calloc(1, sizeof(struct roots_xdg_toplevel_decoration));
- if (decoration == NULL) {
- return;
- }
- decoration->wlr_decoration = wlr_decoration;
- decoration->surface = xdg_surface;
- xdg_surface->xdg_toplevel_decoration = decoration;
-
- decoration->destroy.notify = decoration_handle_destroy;
- wl_signal_add(&wlr_decoration->events.destroy, &decoration->destroy);
- decoration->request_mode.notify = decoration_handle_request_mode;
- wl_signal_add(&wlr_decoration->events.request_mode,
- &decoration->request_mode);
- decoration->surface_commit.notify = decoration_handle_surface_commit;
- wl_signal_add(&wlr_xdg_surface->surface->events.commit,
- &decoration->surface_commit);
-
- decoration_handle_request_mode(&decoration->request_mode, wlr_decoration);
-}
-
-struct roots_xdg_surface *roots_xdg_surface_from_view(struct roots_view *view) {
- assert(view->impl == &view_impl);
- return (struct roots_xdg_surface *)view;
-}
diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c
deleted file mode 100644
index 5830d344..00000000
--- a/rootston/xdg_shell_v6.c
+++ /dev/null
@@ -1,504 +0,0 @@
-#include <assert.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <wayland-server-core.h>
-#include <wlr/types/wlr_box.h>
-#include <wlr/types/wlr_surface.h>
-#include <wlr/types/wlr_xdg_shell_v6.h>
-#include <wlr/util/log.h>
-#include "rootston/desktop.h"
-#include "rootston/input.h"
-#include "rootston/server.h"
-
-static const struct roots_view_child_interface popup_impl;
-
-static void popup_destroy(struct roots_view_child *child) {
- assert(child->impl == &popup_impl);
- struct roots_xdg_popup_v6 *popup = (struct roots_xdg_popup_v6 *)child;
- wl_list_remove(&popup->destroy.link);
- wl_list_remove(&popup->new_popup.link);
- wl_list_remove(&popup->map.link);
- wl_list_remove(&popup->unmap.link);
- free(popup);
-}
-
-static const struct roots_view_child_interface popup_impl = {
- .destroy = popup_destroy,
-};
-
-static void popup_handle_destroy(struct wl_listener *listener, void *data) {
- struct roots_xdg_popup_v6 *popup =
- wl_container_of(listener, popup, destroy);
- view_child_destroy(&popup->view_child);
-}
-
-static void popup_handle_map(struct wl_listener *listener, void *data) {
- struct roots_xdg_popup_v6 *popup =
- wl_container_of(listener, popup, map);
- view_damage_whole(popup->view_child.view);
- input_update_cursor_focus(popup->view_child.view->desktop->server->input);
-}
-
-static void popup_handle_unmap(struct wl_listener *listener, void *data) {
- struct roots_xdg_popup_v6 *popup =
- wl_container_of(listener, popup, unmap);
- view_damage_whole(popup->view_child.view);
-}
-
-static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view,
- struct wlr_xdg_popup_v6 *wlr_popup);
-
-static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
- struct roots_xdg_popup_v6 *popup =
- wl_container_of(listener, popup, new_popup);
- struct wlr_xdg_popup_v6 *wlr_popup = data;
- popup_create(popup->view_child.view, wlr_popup);
-}
-
-static void popup_unconstrain(struct roots_xdg_popup_v6 *popup) {
- // get the output of the popup's positioner anchor point and convert it to
- // the toplevel parent's coordinate system and then pass it to
- // wlr_xdg_popup_v6_unconstrain_from_box
-
- // TODO: unconstrain popups for rotated windows
- if (popup->view_child.view->rotation != 0.0) {
- return;
- }
-
- struct roots_view *view = popup->view_child.view;
- struct wlr_output_layout *layout = view->desktop->layout;
- struct wlr_xdg_popup_v6 *wlr_popup = popup->wlr_popup;
-
- int anchor_lx, anchor_ly;
- wlr_xdg_popup_v6_get_anchor_point(wlr_popup, &anchor_lx, &anchor_ly);
-
- int popup_lx, popup_ly;
- wlr_xdg_popup_v6_get_toplevel_coords(wlr_popup, wlr_popup->geometry.x,
- wlr_popup->geometry.y, &popup_lx, &popup_ly);
- popup_lx += view->box.x;
- popup_ly += view->box.y;
-
- anchor_lx += popup_lx;
- anchor_ly += popup_ly;
-
- double dest_x = 0, dest_y = 0;
- wlr_output_layout_closest_point(layout, NULL, anchor_lx, anchor_ly,
- &dest_x, &dest_y);
-
- struct wlr_output *output =
- wlr_output_layout_output_at(layout, dest_x, dest_y);
- if (output == NULL) {
- return;
- }
-
- struct wlr_box *output_box =
- wlr_output_layout_get_box(view->desktop->layout, output);
-
- // the output box expressed in the coordinate system of the toplevel parent
- // of the popup
- struct wlr_box output_toplevel_sx_box = {
- .x = output_box->x - view->box.x,
- .y = output_box->y - view->box.y,
- .width = output_box->width,
- .height = output_box->height,
- };
-
- wlr_xdg_popup_v6_unconstrain_from_box(popup->wlr_popup, &output_toplevel_sx_box);
-}
-
-static struct roots_xdg_popup_v6 *popup_create(struct roots_view *view,
- struct wlr_xdg_popup_v6 *wlr_popup) {
- struct roots_xdg_popup_v6 *popup =
- calloc(1, sizeof(struct roots_xdg_popup_v6));
- if (popup == NULL) {
- return NULL;
- }
- popup->wlr_popup = wlr_popup;
- view_child_init(&popup->view_child, &popup_impl,
- view, wlr_popup->base->surface);
- popup->destroy.notify = popup_handle_destroy;
- wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
- popup->map.notify = popup_handle_map;
- wl_signal_add(&wlr_popup->base->events.map, &popup->map);
- popup->unmap.notify = popup_handle_unmap;
- wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
- popup->new_popup.notify = popup_handle_new_popup;
- wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
-
- popup_unconstrain(popup);
-
- return popup;
-}
-
-
-static void get_size(struct roots_view *view, struct wlr_box *box) {
- struct wlr_xdg_surface_v6 *surface =
- roots_xdg_surface_v6_from_view(view)->xdg_surface_v6;
-
- struct wlr_box geo_box;
- wlr_xdg_surface_v6_get_geometry(surface, &geo_box);
- box->width = geo_box.width;
- box->height = geo_box.height;
-}
-
-static void activate(struct roots_view *view, bool active) {
- struct wlr_xdg_surface_v6 *surface =
- roots_xdg_surface_v6_from_view(view)->xdg_surface_v6;
- if (surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) {
- wlr_xdg_toplevel_v6_set_activated(surface, active);
- }
-}
-
-static void apply_size_constraints(struct wlr_xdg_surface_v6 *surface,
- uint32_t width, uint32_t height, uint32_t *dest_width,
- uint32_t *dest_height) {
- *dest_width = width;
- *dest_height = height;
-
- struct wlr_xdg_toplevel_v6_state *state = &surface->toplevel->current;
- if (width < state->min_width) {
- *dest_width = state->min_width;
- } else if (state->max_width > 0 &&
- width > state->max_width) {
- *dest_width = state->max_width;
- }
- if (height < state->min_height) {
- *dest_height = state->min_height;
- } else if (state->max_height > 0 &&
- height > state->max_height) {
- *dest_height = state->max_height;
- }
-}
-
-static void resize(struct roots_view *view, uint32_t width, uint32_t height) {
- struct wlr_xdg_surface_v6 *surface =
- roots_xdg_surface_v6_from_view(view)->xdg_surface_v6;
- if (surface->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) {
- return;
- }
-
- uint32_t constrained_width, constrained_height;
- apply_size_constraints(surface, width, height, &constrained_width,
- &constrained_height);
-
- wlr_xdg_toplevel_v6_set_size(surface, constrained_width,
- constrained_height);
-}
-
-static void move_resize(struct roots_view *view, double x, double y,
- uint32_t width, uint32_t height) {
- struct roots_xdg_surface_v6 *roots_surface =
- roots_xdg_surface_v6_from_view(view);
- struct wlr_xdg_surface_v6 *surface = roots_surface->xdg_surface_v6;
- if (surface->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) {
- return;
- }
-
- bool update_x = x != view->box.x;
- bool update_y = y != view->box.y;
-
- uint32_t constrained_width, constrained_height;
- apply_size_constraints(surface, width, height, &constrained_width,
- &constrained_height);
-
- if (update_x) {
- x = x + width - constrained_width;
- }
- if (update_y) {
- y = y + height - constrained_height;
- }
-
- view->pending_move_resize.update_x = update_x;
- view->pending_move_resize.update_y = update_y;
- view->pending_move_resize.x = x;
- view->pending_move_resize.y = y;
- view->pending_move_resize.width = constrained_width;
- view->pending_move_resize.height = constrained_height;
-
- uint32_t serial = wlr_xdg_toplevel_v6_set_size(surface, constrained_width,
- constrained_height);
- if (serial > 0) {
- roots_surface->pending_move_resize_configure_serial = serial;
- } else if (roots_surface->pending_move_resize_configure_serial == 0) {
- view_update_position(view, x, y);
- }
-}
-
-static void maximize(struct roots_view *view, bool maximized) {
- struct wlr_xdg_surface_v6 *surface =
- roots_xdg_surface_v6_from_view(view)->xdg_surface_v6;
- if (surface->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) {
- return;
- }
-
- wlr_xdg_toplevel_v6_set_maximized(surface, maximized);
-}
-
-static void set_fullscreen(struct roots_view *view, bool fullscreen) {
- struct wlr_xdg_surface_v6 *surface =
- roots_xdg_surface_v6_from_view(view)->xdg_surface_v6;
- if (surface->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) {
- return;
- }
-
- wlr_xdg_toplevel_v6_set_fullscreen(surface, fullscreen);
-}
-
-static void close(struct roots_view *view) {
- struct wlr_xdg_surface_v6 *surface =
- roots_xdg_surface_v6_from_view(view)->xdg_surface_v6;
- struct wlr_xdg_popup_v6 *popup = NULL;
- wl_list_for_each(popup, &surface->popups, link) {
- wlr_xdg_surface_v6_send_close(popup->base);
- }
- wlr_xdg_surface_v6_send_close(surface);
-}
-
-static void for_each_surface(struct roots_view *view,
- wlr_surface_iterator_func_t iterator, void *user_data) {
- struct wlr_xdg_surface_v6 *surface =
- roots_xdg_surface_v6_from_view(view)->xdg_surface_v6;
- wlr_xdg_surface_v6_for_each_surface(surface, iterator, user_data);
-}
-
-static void destroy(struct roots_view *view) {
- struct roots_xdg_surface_v6 *roots_xdg_surface =
- roots_xdg_surface_v6_from_view(view);
- wl_list_remove(&roots_xdg_surface->surface_commit.link);
- wl_list_remove(&roots_xdg_surface->destroy.link);
- wl_list_remove(&roots_xdg_surface->new_popup.link);
- wl_list_remove(&roots_xdg_surface->map.link);
- wl_list_remove(&roots_xdg_surface->unmap.link);
- wl_list_remove(&roots_xdg_surface->request_move.link);
- wl_list_remove(&roots_xdg_surface->request_resize.link);
- wl_list_remove(&roots_xdg_surface->request_maximize.link);
- wl_list_remove(&roots_xdg_surface->request_fullscreen.link);
- wl_list_remove(&roots_xdg_surface->set_title.link);
- wl_list_remove(&roots_xdg_surface->set_app_id.link);
- free(roots_xdg_surface);
-}
-
-static const struct roots_view_interface view_impl = {
- .activate = activate,
- .resize = resize,
- .move_resize = move_resize,
- .maximize = maximize,
- .set_fullscreen = set_fullscreen,
- .close = close,
- .for_each_surface = for_each_surface,
- .destroy = destroy,
-};
-
-static void handle_request_move(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface_v6 *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, request_move);
- struct roots_view *view = &roots_xdg_surface->view;
- struct roots_input *input = view->desktop->server->input;
- struct wlr_xdg_toplevel_v6_move_event *e = data;
- struct roots_seat *seat = input_seat_from_wlr_seat(input, e->seat->seat);
- // TODO verify event serial
- if (!seat || seat->cursor->mode != ROOTS_CURSOR_PASSTHROUGH) {
- return;
- }
- roots_seat_begin_move(seat, view);
-}
-
-static void handle_request_resize(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface_v6 *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, request_resize);
- struct roots_view *view = &roots_xdg_surface->view;
- struct roots_input *input = view->desktop->server->input;
- struct wlr_xdg_toplevel_v6_resize_event *e = data;
- // TODO verify event serial
- struct roots_seat *seat = input_seat_from_wlr_seat(input, e->seat->seat);
- assert(seat);
- if (!seat || seat->cursor->mode != ROOTS_CURSOR_PASSTHROUGH) {
- return;
- }
- roots_seat_begin_resize(seat, view, e->edges);
-}
-
-static void handle_request_maximize(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface_v6 *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, request_maximize);
- struct roots_view *view = &roots_xdg_surface->view;
- struct wlr_xdg_surface_v6 *surface = roots_xdg_surface->xdg_surface_v6;
-
- if (surface->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) {
- return;
- }
-
- view_maximize(view, surface->toplevel->client_pending.maximized);
-}
-
-static void handle_request_fullscreen(struct wl_listener *listener,
- void *data) {
- struct roots_xdg_surface_v6 *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, request_fullscreen);
- struct roots_view *view = &roots_xdg_surface->view;
- struct wlr_xdg_surface_v6 *surface = roots_xdg_surface->xdg_surface_v6;
- struct wlr_xdg_toplevel_v6_set_fullscreen_event *e = data;
-
- if (surface->role != WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) {
- return;
- }
-
- view_set_fullscreen(view, e->fullscreen, e->output);
-}
-
-static void handle_set_title(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface_v6 *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, set_title);
-
- view_set_title(&roots_xdg_surface->view,
- roots_xdg_surface->xdg_surface_v6->toplevel->title);
-}
-
-static void handle_set_app_id(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface_v6 *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, set_app_id);
-
- view_set_app_id(&roots_xdg_surface->view,
- roots_xdg_surface->xdg_surface_v6->toplevel->app_id);
-}
-
-static void handle_surface_commit(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface_v6 *roots_surface =
- wl_container_of(listener, roots_surface, surface_commit);
- struct roots_view *view = &roots_surface->view;
- struct wlr_xdg_surface_v6 *surface = roots_surface->xdg_surface_v6;
-
- if (!surface->mapped) {
- return;
- }
-
- view_apply_damage(view);
-
- struct wlr_box size;
- get_size(view, &size);
- view_update_size(view, size.width, size.height);
-
- uint32_t pending_serial =
- roots_surface->pending_move_resize_configure_serial;
- if (pending_serial > 0 && pending_serial >= surface->configure_serial) {
- double x = view->box.x;
- double y = view->box.y;
- if (view->pending_move_resize.update_x) {
- x = view->pending_move_resize.x + view->pending_move_resize.width -
- size.width;
- }
- if (view->pending_move_resize.update_y) {
- y = view->pending_move_resize.y + view->pending_move_resize.height -
- size.height;
- }
- view_update_position(view, x, y);
-
- if (pending_serial == surface->configure_serial) {
- roots_surface->pending_move_resize_configure_serial = 0;
- }
- }
-}
-
-static void handle_new_popup(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface_v6 *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, new_popup);
- struct wlr_xdg_popup_v6 *wlr_popup = data;
- popup_create(&roots_xdg_surface->view, wlr_popup);
-}
-
-static void handle_map(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface_v6 *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, map);
- struct roots_view *view = &roots_xdg_surface->view;
-
- struct wlr_box box;
- get_size(view, &box);
- view->box.width = box.width;
- view->box.height = box.height;
-
- view_map(view, roots_xdg_surface->xdg_surface_v6->surface);
- view_setup(view);
-
- wlr_foreign_toplevel_handle_v1_set_title(view->toplevel_handle,
- roots_xdg_surface->xdg_surface_v6->toplevel->title ?: "none");
- wlr_foreign_toplevel_handle_v1_set_app_id(view->toplevel_handle,
- roots_xdg_surface->xdg_surface_v6->toplevel->app_id ?: "none");
-}
-
-static void handle_unmap(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface_v6 *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, unmap);
- view_unmap(&roots_xdg_surface->view);
-}
-
-static void handle_destroy(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface_v6 *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, destroy);
- view_destroy(&roots_xdg_surface->view);
-}
-
-void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
- struct wlr_xdg_surface_v6 *surface = data;
- assert(surface->role != WLR_XDG_SURFACE_V6_ROLE_NONE);
-
- if (surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) {
- wlr_log(WLR_DEBUG, "new xdg popup");
- return;
- }
-
- struct roots_desktop *desktop =
- wl_container_of(listener, desktop, xdg_shell_v6_surface);
-
- wlr_log(WLR_DEBUG, "new xdg toplevel: title=%s, app_id=%s",
- surface->toplevel->title, surface->toplevel->app_id);
- wlr_xdg_surface_v6_ping(surface);
-
- struct roots_xdg_surface_v6 *roots_surface =
- calloc(1, sizeof(struct roots_xdg_surface_v6));
- if (!roots_surface) {
- return;
- }
-
- view_init(&roots_surface->view, &view_impl, ROOTS_XDG_SHELL_V6_VIEW, desktop);
- roots_surface->xdg_surface_v6 = surface;
-
- view_maximize(&roots_surface->view, surface->toplevel->client_pending.maximized);
- view_set_fullscreen(&roots_surface->view, surface->toplevel->client_pending.fullscreen,
- surface->toplevel->client_pending.fullscreen_output);
-
- roots_surface->surface_commit.notify = handle_surface_commit;
- wl_signal_add(&surface->surface->events.commit,
- &roots_surface->surface_commit);
- roots_surface->destroy.notify = handle_destroy;
- wl_signal_add(&surface->events.destroy, &roots_surface->destroy);
- roots_surface->map.notify = handle_map;
- wl_signal_add(&surface->events.map, &roots_surface->map);
- roots_surface->unmap.notify = handle_unmap;
- wl_signal_add(&surface->events.unmap, &roots_surface->unmap);
- roots_surface->request_move.notify = handle_request_move;
- wl_signal_add(&surface->toplevel->events.request_move,
- &roots_surface->request_move);
- roots_surface->request_resize.notify = handle_request_resize;
- wl_signal_add(&surface->toplevel->events.request_resize,
- &roots_surface->request_resize);
- roots_surface->request_maximize.notify = handle_request_maximize;
- wl_signal_add(&surface->toplevel->events.request_maximize,
- &roots_surface->request_maximize);
- roots_surface->request_fullscreen.notify = handle_request_fullscreen;
- wl_signal_add(&surface->toplevel->events.request_fullscreen,
- &roots_surface->request_fullscreen);
- roots_surface->set_title.notify = handle_set_title;
- wl_signal_add(&surface->toplevel->events.set_title,
- &roots_surface->set_title);
- roots_surface->set_app_id.notify = handle_set_app_id;
- wl_signal_add(&surface->toplevel->events.set_app_id,
- &roots_surface->set_app_id);
- roots_surface->new_popup.notify = handle_new_popup;
- wl_signal_add(&surface->events.new_popup, &roots_surface->new_popup);
-}
-
-struct roots_xdg_surface_v6 *roots_xdg_surface_v6_from_view(
- struct roots_view *view) {
- assert(view->impl == &view_impl);
- return (struct roots_xdg_surface_v6 *)view;
-}
diff --git a/rootston/xwayland.c b/rootston/xwayland.c
deleted file mode 100644
index 7dc637ce..00000000
--- a/rootston/xwayland.c
+++ /dev/null
@@ -1,355 +0,0 @@
-#include <assert.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <wayland-server-core.h>
-#include <wlr/config.h>
-#include <wlr/types/wlr_box.h>
-#include <wlr/types/wlr_surface.h>
-#include <wlr/util/log.h>
-#include <wlr/xwayland.h>
-#include "rootston/server.h"
-
-static void activate(struct roots_view *view, bool active) {
- struct wlr_xwayland_surface *xwayland_surface =
- roots_xwayland_surface_from_view(view)->xwayland_surface;
- wlr_xwayland_surface_activate(xwayland_surface, active);
-}
-
-static void move(struct roots_view *view, double x, double y) {
- struct wlr_xwayland_surface *xwayland_surface =
- roots_xwayland_surface_from_view(view)->xwayland_surface;
- view_update_position(view, x, y);
- wlr_xwayland_surface_configure(xwayland_surface, x, y,
- xwayland_surface->width, xwayland_surface->height);
-}
-
-static void apply_size_constraints(
- struct wlr_xwayland_surface *xwayland_surface, uint32_t width,
- uint32_t height, uint32_t *dest_width, uint32_t *dest_height) {
- *dest_width = width;
- *dest_height = height;
-
- struct wlr_xwayland_surface_size_hints *size_hints =
- xwayland_surface->size_hints;
- if (size_hints != NULL) {
- if (width < (uint32_t)size_hints->min_width) {
- *dest_width = size_hints->min_width;
- } else if (size_hints->max_width > 0 &&
- width > (uint32_t)size_hints->max_width) {
- *dest_width = size_hints->max_width;
- }
- if (height < (uint32_t)size_hints->min_height) {
- *dest_height = size_hints->min_height;
- } else if (size_hints->max_height > 0 &&
- height > (uint32_t)size_hints->max_height) {
- *dest_height = size_hints->max_height;
- }
- }
-}
-
-static void resize(struct roots_view *view, uint32_t width, uint32_t height) {
- struct wlr_xwayland_surface *xwayland_surface =
- roots_xwayland_surface_from_view(view)->xwayland_surface;
-
- uint32_t constrained_width, constrained_height;
- apply_size_constraints(xwayland_surface, width, height, &constrained_width,
- &constrained_height);
-
- wlr_xwayland_surface_configure(xwayland_surface, xwayland_surface->x,
- xwayland_surface->y, constrained_width, constrained_height);
-}
-
-static void move_resize(struct roots_view *view, double x, double y,
- uint32_t width, uint32_t height) {
- struct wlr_xwayland_surface *xwayland_surface =
- roots_xwayland_surface_from_view(view)->xwayland_surface;
-
- bool update_x = x != view->box.x;
- bool update_y = y != view->box.y;
-
- uint32_t constrained_width, constrained_height;
- apply_size_constraints(xwayland_surface, width, height, &constrained_width,
- &constrained_height);
-
- if (update_x) {
- x = x + width - constrained_width;
- }
- if (update_y) {
- y = y + height - constrained_height;
- }
-
- view->pending_move_resize.update_x = update_x;
- view->pending_move_resize.update_y = update_y;
- view->pending_move_resize.x = x;
- view->pending_move_resize.y = y;
- view->pending_move_resize.width = constrained_width;
- view->pending_move_resize.height = constrained_height;
-
- wlr_xwayland_surface_configure(xwayland_surface, x, y, constrained_width,
- constrained_height);
-}
-
-static void close(struct roots_view *view) {
- struct wlr_xwayland_surface *xwayland_surface =
- roots_xwayland_surface_from_view(view)->xwayland_surface;
- wlr_xwayland_surface_close(xwayland_surface);
-}
-
-static void maximize(struct roots_view *view, bool maximized) {
- struct wlr_xwayland_surface *xwayland_surface =
- roots_xwayland_surface_from_view(view)->xwayland_surface;
- wlr_xwayland_surface_set_maximized(xwayland_surface, maximized);
-}
-
-static void set_fullscreen(struct roots_view *view, bool fullscreen) {
- struct wlr_xwayland_surface *xwayland_surface =
- roots_xwayland_surface_from_view(view)->xwayland_surface;
- wlr_xwayland_surface_set_fullscreen(xwayland_surface, fullscreen);
-}
-
-static void destroy(struct roots_view *view) {
- struct roots_xwayland_surface *roots_surface =
- roots_xwayland_surface_from_view(view);
- wl_list_remove(&roots_surface->destroy.link);
- wl_list_remove(&roots_surface->request_configure.link);
- wl_list_remove(&roots_surface->request_move.link);
- wl_list_remove(&roots_surface->request_resize.link);
- wl_list_remove(&roots_surface->request_maximize.link);
- wl_list_remove(&roots_surface->set_title.link);
- wl_list_remove(&roots_surface->set_class.link);
- wl_list_remove(&roots_surface->map.link);
- wl_list_remove(&roots_surface->unmap.link);
- free(roots_surface);
-}
-
-static const struct roots_view_interface view_impl = {
- .activate = activate,
- .resize = resize,
- .move = move,
- .move_resize = move_resize,
- .maximize = maximize,
- .set_fullscreen = set_fullscreen,
- .close = close,
- .destroy = destroy,
-};
-
-static void handle_destroy(struct wl_listener *listener, void *data) {
- struct roots_xwayland_surface *roots_surface =
- wl_container_of(listener, roots_surface, destroy);
- view_destroy(&roots_surface->view);
-}
-
-static void handle_request_configure(struct wl_listener *listener, void *data) {
- struct roots_xwayland_surface *roots_surface =
- wl_container_of(listener, roots_surface, request_configure);
- struct wlr_xwayland_surface *xwayland_surface =
- roots_surface->xwayland_surface;
- struct wlr_xwayland_surface_configure_event *event = data;
-
- view_update_position(&roots_surface->view, event->x, event->y);
-
- wlr_xwayland_surface_configure(xwayland_surface, event->x, event->y,
- event->width, event->height);
-}
-
-static struct roots_seat *guess_seat_for_view(struct roots_view *view) {
- // the best we can do is to pick the first seat that has the surface focused
- // for the pointer
- struct roots_input *input = view->desktop->server->input;
- struct roots_seat *seat;
- wl_list_for_each(seat, &input->seats, link) {
- if (seat->seat->pointer_state.focused_surface == view->wlr_surface) {
- return seat;
- }
- }
- return NULL;
-}
-
-static void handle_request_move(struct wl_listener *listener, void *data) {
- struct roots_xwayland_surface *roots_surface =
- wl_container_of(listener, roots_surface, request_move);
- struct roots_view *view = &roots_surface->view;
- struct roots_seat *seat = guess_seat_for_view(view);
-
- if (!seat || seat->cursor->mode != ROOTS_CURSOR_PASSTHROUGH) {
- return;
- }
-
- roots_seat_begin_move(seat, view);
-}
-
-static void handle_request_resize(struct wl_listener *listener, void *data) {
- struct roots_xwayland_surface *roots_surface =
- wl_container_of(listener, roots_surface, request_resize);
- struct roots_view *view = &roots_surface->view;
- struct roots_seat *seat = guess_seat_for_view(view);
- struct wlr_xwayland_resize_event *e = data;
-
- if (!seat || seat->cursor->mode != ROOTS_CURSOR_PASSTHROUGH) {
- return;
- }
- roots_seat_begin_resize(seat, view, e->edges);
-}
-
-static void handle_request_maximize(struct wl_listener *listener, void *data) {
- struct roots_xwayland_surface *roots_surface =
- wl_container_of(listener, roots_surface, request_maximize);
- struct roots_view *view = &roots_surface->view;
- struct wlr_xwayland_surface *xwayland_surface =
- roots_surface->xwayland_surface;
-
- bool maximized = xwayland_surface->maximized_vert &&
- xwayland_surface->maximized_horz;
- view_maximize(view, maximized);
-}
-
-static void handle_request_fullscreen(struct wl_listener *listener,
- void *data) {
- struct roots_xwayland_surface *roots_surface =
- wl_container_of(listener, roots_surface, request_fullscreen);
- struct roots_view *view = &roots_surface->view;
- struct wlr_xwayland_surface *xwayland_surface =
- roots_surface->xwayland_surface;
-
- view_set_fullscreen(view, xwayland_surface->fullscreen, NULL);
-}
-
-static void handle_set_title(struct wl_listener *listener, void *data) {
- struct roots_xwayland_surface *roots_surface =
- wl_container_of(listener, roots_surface, set_title);
-
- view_set_title(&roots_surface->view,
- roots_surface->xwayland_surface->title);
-}
-
-static void handle_set_class(struct wl_listener *listener, void *data) {
- struct roots_xwayland_surface *roots_surface =
- wl_container_of(listener, roots_surface, set_class);
-
- view_set_app_id(&roots_surface->view,
- roots_surface->xwayland_surface->class);
-}
-
-static void handle_surface_commit(struct wl_listener *listener, void *data) {
- struct roots_xwayland_surface *roots_surface =
- wl_container_of(listener, roots_surface, surface_commit);
- struct roots_view *view = &roots_surface->view;
- struct wlr_surface *wlr_surface = view->wlr_surface;
-
- view_apply_damage(view);
-
- int width = wlr_surface->current.width;
- int height = wlr_surface->current.height;
- view_update_size(view, width, height);
-
- double x = view->box.x;
- double y = view->box.y;
- if (view->pending_move_resize.update_x) {
- x = view->pending_move_resize.x + view->pending_move_resize.width -
- width;
- view->pending_move_resize.update_x = false;
- }
- if (view->pending_move_resize.update_y) {
- y = view->pending_move_resize.y + view->pending_move_resize.height -
- height;
- view->pending_move_resize.update_y = false;
- }
- view_update_position(view, x, y);
-}
-
-static void handle_map(struct wl_listener *listener, void *data) {
- struct roots_xwayland_surface *roots_surface =
- wl_container_of(listener, roots_surface, map);
- struct wlr_xwayland_surface *surface = data;
- struct roots_view *view = &roots_surface->view;
-
- view->box.x = surface->x;
- view->box.y = surface->y;
- view->box.width = surface->surface->current.width;
- view->box.height = surface->surface->current.height;
-
- roots_surface->surface_commit.notify = handle_surface_commit;
- wl_signal_add(&surface->surface->events.commit,
- &roots_surface->surface_commit);
-
- view_map(view, surface->surface);
-
- if (!surface->override_redirect) {
- if (surface->decorations == WLR_XWAYLAND_SURFACE_DECORATIONS_ALL) {
- view->decorated = true;
- view->border_width = 4;
- view->titlebar_height = 12;
- }
-
- view_setup(view);
-
- wlr_foreign_toplevel_handle_v1_set_title(view->toplevel_handle,
- roots_surface->xwayland_surface->title ?: "none");
- wlr_foreign_toplevel_handle_v1_set_app_id(view->toplevel_handle,
- roots_surface->xwayland_surface->class ?: "none");
- } else {
- view_initial_focus(view);
- }
-}
-
-static void handle_unmap(struct wl_listener *listener, void *data) {
- struct roots_xwayland_surface *roots_surface =
- wl_container_of(listener, roots_surface, unmap);
- struct roots_view *view = &roots_surface->view;
-
- wl_list_remove(&roots_surface->surface_commit.link);
- view_unmap(view);
-}
-
-void handle_xwayland_surface(struct wl_listener *listener, void *data) {
- struct roots_desktop *desktop =
- wl_container_of(listener, desktop, xwayland_surface);
-
- struct wlr_xwayland_surface *surface = data;
- wlr_log(WLR_DEBUG, "new xwayland surface: title=%s, class=%s, instance=%s",
- surface->title, surface->class, surface->instance);
- wlr_xwayland_surface_ping(surface);
-
- struct roots_xwayland_surface *roots_surface =
- calloc(1, sizeof(struct roots_xwayland_surface));
- if (roots_surface == NULL) {
- return;
- }
-
- view_init(&roots_surface->view, &view_impl, ROOTS_XWAYLAND_VIEW, desktop);
- roots_surface->view.box.x = surface->x;
- roots_surface->view.box.y = surface->y;
- roots_surface->xwayland_surface = surface;
-
- roots_surface->destroy.notify = handle_destroy;
- wl_signal_add(&surface->events.destroy, &roots_surface->destroy);
- roots_surface->request_configure.notify = handle_request_configure;
- wl_signal_add(&surface->events.request_configure,
- &roots_surface->request_configure);
- roots_surface->map.notify = handle_map;
- wl_signal_add(&surface->events.map, &roots_surface->map);
- roots_surface->unmap.notify = handle_unmap;
- wl_signal_add(&surface->events.unmap, &roots_surface->unmap);
- roots_surface->request_move.notify = handle_request_move;
- wl_signal_add(&surface->events.request_move, &roots_surface->request_move);
- roots_surface->request_resize.notify = handle_request_resize;
- wl_signal_add(&surface->events.request_resize,
- &roots_surface->request_resize);
- roots_surface->request_maximize.notify = handle_request_maximize;
- wl_signal_add(&surface->events.request_maximize,
- &roots_surface->request_maximize);
- roots_surface->request_fullscreen.notify = handle_request_fullscreen;
- wl_signal_add(&surface->events.request_fullscreen,
- &roots_surface->request_fullscreen);
- roots_surface->set_title.notify = handle_set_title;
- wl_signal_add(&surface->events.set_title, &roots_surface->set_title);
- roots_surface->set_class.notify = handle_set_class;
- wl_signal_add(&surface->events.set_class,
- &roots_surface->set_class);
-}
-
-struct roots_xwayland_surface *roots_xwayland_surface_from_view(
- struct roots_view *view) {
- assert(view->impl == &view_impl);
- return (struct roots_xwayland_surface *)view;
-}