aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig4
-rw-r--r--README.md2
-rw-r--r--backend/libinput/pointer.c2
-rw-r--r--backend/meson.build7
-rw-r--r--backend/session/direct-freebsd.c217
-rw-r--r--backend/session/direct-ipc.c13
-rw-r--r--backend/session/session.c6
-rw-r--r--backend/wayland/os-compatibility.c2
-rw-r--r--backend/x11/backend.c20
-rw-r--r--examples/output-layout.c2
-rw-r--r--include/rootston/view.h6
-rw-r--r--include/wlr/types/wlr_output_layout.h6
-rw-r--r--include/wlr/types/wlr_xdg_shell_v6.h1
-rw-r--r--include/wlr/util/log.h2
-rw-r--r--meson.build3
-rw-r--r--protocol/meson.build3
-rw-r--r--rootston/config.c89
-rw-r--r--rootston/cursor.c7
-rw-r--r--rootston/desktop.c45
-rw-r--r--rootston/keyboard.c7
-rw-r--r--rootston/output.c2
-rw-r--r--rootston/rootston.ini.example1
-rw-r--r--rootston/wl_shell.c10
-rw-r--r--rootston/xdg_shell_v6.c11
-rw-r--r--types/wlr_keyboard.c6
-rw-r--r--types/wlr_output.c2
-rw-r--r--types/wlr_output_layout.c17
-rw-r--r--types/wlr_seat.c1
-rw-r--r--types/wlr_xdg_shell_v6.c22
-rw-r--r--util/log.c2
-rw-r--r--xcursor/meson.build1
-rw-r--r--xwayland/sockets.c9
-rw-r--r--xwayland/xwayland.c12
33 files changed, 424 insertions, 116 deletions
diff --git a/.editorconfig b/.editorconfig
index 4b8b3e12..64f18915 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -7,3 +7,7 @@ charset = utf-8
indent_style = tab
indent_size = 4
trim_trailing_whitespace = true
+
+[*.xml]
+indent_style = space
+indent_size = 2
diff --git a/README.md b/README.md
index d232804a..0f221e3c 100644
--- a/README.md
+++ b/README.md
@@ -31,3 +31,5 @@ Run these commands:
meson build
ninja -C build
+
+(On FreeBSD, you need to pass an extra flag to prevent a linking error: `meson build -D b_lundef=false`)
diff --git a/backend/libinput/pointer.c b/backend/libinput/pointer.c
index 005c9516..ad9b8f02 100644
--- a/backend/libinput/pointer.c
+++ b/backend/libinput/pointer.c
@@ -128,7 +128,7 @@ void handle_pointer_axis(struct libinput_event *event,
}
wlr_event.delta = libinput_event_pointer_get_axis_value(
pevent, axies[i]);
+ wl_signal_emit(&wlr_dev->pointer->events.axis, &wlr_event);
}
- wl_signal_emit(&wlr_dev->pointer->events.axis, &wlr_event);
}
}
diff --git a/backend/meson.build b/backend/meson.build
index cf62a56f..5ed7b227 100644
--- a/backend/meson.build
+++ b/backend/meson.build
@@ -1,7 +1,6 @@
backend_files = files(
'backend.c',
'session/direct-ipc.c',
- 'session/direct.c',
'session/session.c',
'drm/atomic.c',
'drm/backend.c',
@@ -26,6 +25,12 @@ backend_files = files(
'x11/backend.c',
)
+if host_machine.system().startswith('freebsd')
+ backend_files += files('session/direct-freebsd.c')
+else
+ backend_files += files('session/direct.c')
+endif
+
if systemd.found()
backend_files += files('session/logind.c')
endif
diff --git a/backend/session/direct-freebsd.c b/backend/session/direct-freebsd.c
new file mode 100644
index 00000000..fc4bab04
--- /dev/null
+++ b/backend/session/direct-freebsd.c
@@ -0,0 +1,217 @@
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <dev/evdev/input.h>
+#include <sys/kbio.h>
+#include <sys/consio.h>
+#include <wayland-server.h>
+#include <wlr/backend/session/interface.h>
+#include <wlr/util/log.h>
+#include "backend/session/direct-ipc.h"
+
+const struct session_impl session_direct;
+
+struct direct_session {
+ struct wlr_session base;
+ int tty_fd;
+ int old_kbmode;
+ int sock;
+ pid_t child;
+
+ struct wl_event_source *vt_source;
+};
+
+static int direct_session_open(struct wlr_session *base, const char *path) {
+ struct direct_session *session = wl_container_of(base, session, base);
+
+ int fd = direct_ipc_open(session->sock, path);
+ if (fd < 0) {
+ wlr_log(L_ERROR, "Failed to open %s: %s%s", path, strerror(-fd),
+ fd == -EINVAL ? "; is another display server running?" : "");
+ return fd;
+ }
+
+ struct stat st;
+ if (fstat(fd, &st) < 0) {
+ close(fd);
+ return -errno;
+ }
+
+ return fd;
+}
+
+static void direct_session_close(struct wlr_session *base, int fd) {
+ struct direct_session *session = wl_container_of(base, session, base);
+
+ struct stat st;
+ if (fstat(fd, &st) < 0) {
+ wlr_log_errno(L_ERROR, "Stat failed");
+ close(fd);
+ return;
+ }
+
+ close(fd);
+}
+
+static bool direct_change_vt(struct wlr_session *base, unsigned vt) {
+ struct direct_session *session = wl_container_of(base, session, base);
+ return ioctl(session->tty_fd, VT_ACTIVATE, (int)vt) == 0;
+}
+
+static void direct_session_destroy(struct wlr_session *base) {
+ struct direct_session *session = wl_container_of(base, session, base);
+ struct vt_mode mode = {
+ .mode = VT_AUTO,
+ };
+
+ errno = 0;
+
+ ioctl(session->tty_fd, KDSKBMODE, session->old_kbmode);
+ ioctl(session->tty_fd, KDSETMODE, KD_TEXT);
+ ioctl(session->tty_fd, VT_SETMODE, &mode);
+
+ if (errno) {
+ wlr_log(L_ERROR, "Failed to restore tty");
+ }
+
+ direct_ipc_finish(session->sock, session->child);
+ close(session->sock);
+
+ wl_event_source_remove(session->vt_source);
+ close(session->tty_fd);
+ free(session);
+}
+
+static int vt_handler(int signo, void *data) {
+ struct direct_session *session = data;
+
+ if (session->base.active) {
+ session->base.active = false;
+ wl_signal_emit(&session->base.session_signal, session);
+ ioctl(session->tty_fd, VT_RELDISP, 1);
+ } else {
+ ioctl(session->tty_fd, VT_RELDISP, VT_ACKACQ);
+ session->base.active = true;
+ wl_signal_emit(&session->base.session_signal, session);
+ }
+
+ return 1;
+}
+
+static bool setup_tty(struct direct_session *session, struct wl_display *display) {
+ int fd = -1, tty = -1, tty0_fd = -1;
+ if ((tty0_fd = open("/dev/ttyv0", O_RDWR | O_CLOEXEC)) < 0) {
+ wlr_log_errno(L_ERROR, "Could not open /dev/ttyv0 to find a free vt");
+ goto error;
+ }
+ if (ioctl(tty0_fd, VT_OPENQRY, &tty) != 0) {
+ wlr_log_errno(L_ERROR, "Could not find a free vt");
+ goto error;
+ }
+ close(tty0_fd);
+ char tty_path[64];
+ snprintf(tty_path, sizeof(tty_path), "/dev/ttyv%d", tty - 1);
+ wlr_log(L_INFO, "Using tty %s", tty_path);
+ fd = open(tty_path, O_RDWR | O_NOCTTY | O_CLOEXEC);
+
+ if (fd == -1) {
+ wlr_log_errno(L_ERROR, "Cannot open tty");
+ return false;
+ }
+
+ ioctl(fd, VT_ACTIVATE, tty);
+ ioctl(fd, VT_WAITACTIVE, tty);
+
+ int old_kbmode;
+ if (ioctl(fd, KDGKBMODE, &old_kbmode)) {
+ wlr_log_errno(L_ERROR, "Failed to read tty %d keyboard mode", tty);
+ goto error;
+ }
+
+ if (ioctl(fd, KDSKBMODE, K_CODE)) {
+ wlr_log_errno(L_ERROR, "Failed to set keyboard mode K_CODE on tty %d", tty);
+ goto error;
+ }
+
+ if (ioctl(fd, KDSETMODE, KD_GRAPHICS)) {
+ wlr_log_errno(L_ERROR, "Failed to set graphics mode on tty %d", tty);
+ goto error;
+ }
+
+ struct vt_mode mode = {
+ .mode = VT_PROCESS,
+ .relsig = SIGUSR1,
+ .acqsig = SIGUSR1,
+ .frsig = SIGIO, // has to be set
+ };
+
+ if (ioctl(fd, VT_SETMODE, &mode) < 0) {
+ wlr_log(L_ERROR, "Failed to take control of tty %d", tty);
+ goto error;
+ }
+
+ struct wl_event_loop *loop = wl_display_get_event_loop(display);
+ session->vt_source = wl_event_loop_add_signal(loop, SIGUSR1,
+ vt_handler, session);
+ if (!session->vt_source) {
+ goto error;
+ }
+
+ session->base.vtnr = tty;
+ session->tty_fd = fd;
+ session->old_kbmode = old_kbmode;
+
+ return true;
+
+error:
+ // Drop back to tty 1, better than hanging in a useless blank console
+ ioctl(fd, VT_ACTIVATE, 1);
+ close(fd);
+ return false;
+}
+
+static struct wlr_session *direct_session_create(struct wl_display *disp) {
+ struct direct_session *session = calloc(1, sizeof(*session));
+ if (!session) {
+ wlr_log_errno(L_ERROR, "Allocation failed");
+ return NULL;
+ }
+
+ session->sock = direct_ipc_init(&session->child);
+ if (session->sock == -1) {
+ goto error_session;
+ }
+
+ if (!setup_tty(session, disp)) {
+ goto error_ipc;
+ }
+
+ wlr_log(L_INFO, "Successfully loaded direct session");
+
+ snprintf(session->base.seat, sizeof(session->base.seat), "seat0");
+ session->base.impl = &session_direct;
+ return &session->base;
+
+error_ipc:
+ direct_ipc_finish(session->sock, session->child);
+ close(session->sock);
+error_session:
+ free(session);
+ return NULL;
+}
+
+const struct session_impl session_direct = {
+ .create = direct_session_create,
+ .destroy = direct_session_destroy,
+ .open = direct_session_open,
+ .close = direct_session_close,
+ .change_vt = direct_change_vt,
+};
diff --git a/backend/session/direct-ipc.c b/backend/session/direct-ipc.c
index 5f1494a6..0ea51e2f 100644
--- a/backend/session/direct-ipc.c
+++ b/backend/session/direct-ipc.c
@@ -1,4 +1,8 @@
#define _POSIX_C_SOURCE 200809L
+#ifdef __FreeBSD__
+#define __BSD_VISIBLE 1
+#define INPUT_MAJOR 0
+#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -8,10 +12,12 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <sys/sysmacros.h>
#include <sys/wait.h>
-#include <xf86drm.h>
+#ifdef __linux__
+#include <sys/sysmacros.h>
#include <linux/major.h>
+#endif
+#include <xf86drm.h>
#include <wlr/util/log.h>
#include "backend/session/direct-ipc.h"
@@ -35,11 +41,12 @@ static bool have_permissions(void) {
}
#else
static bool have_permissions(void) {
+#ifdef __linux__
if (geteuid() != 0) {
wlr_log(L_ERROR, "Do not have root privileges; cannot become DRM master");
return false;
}
-
+#endif
return true;
}
#endif
diff --git a/backend/session/session.c b/backend/session/session.c
index b73952fd..b14ca4d0 100644
--- a/backend/session/session.c
+++ b/backend/session/session.c
@@ -263,6 +263,11 @@ size_t wlr_session_find_gpus(struct wlr_session *session,
return explicit_find_gpus(session, ret_len, ret, explicit);
}
+#ifdef __FreeBSD__
+ // XXX: libudev-devd does not return any GPUs (yet?)
+ return explicit_find_gpus(session, ret_len, ret, "/dev/drm/0");
+#else
+
struct udev_enumerate *en = udev_enumerate_new(session->udev);
if (!en) {
wlr_log(L_ERROR, "Failed to create udev enumeration");
@@ -329,4 +334,5 @@ size_t wlr_session_find_gpus(struct wlr_session *session,
udev_enumerate_unref(en);
return i;
+#endif
}
diff --git a/backend/wayland/os-compatibility.c b/backend/wayland/os-compatibility.c
index cd268539..14125793 100644
--- a/backend/wayland/os-compatibility.c
+++ b/backend/wayland/os-compatibility.c
@@ -29,7 +29,9 @@
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
+#ifdef __linux__
#include <sys/epoll.h>
+#endif
#include <string.h>
#include <stdlib.h>
diff --git a/backend/x11/backend.c b/backend/x11/backend.c
index 1eb5a952..11dd8568 100644
--- a/backend/x11/backend.c
+++ b/backend/x11/backend.c
@@ -1,4 +1,4 @@
-#define _POSIX_C_SOURCE 199309L
+#define _POSIX_C_SOURCE 200112L
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -8,7 +8,11 @@
#include <xcb/xcb.h>
#include <xcb/glx.h>
#include <X11/Xlib-xcb.h>
+#ifdef __linux__
#include <linux/input-event-codes.h>
+#elif __FreeBSD__
+#include <dev/evdev/input-event-codes.h>
+#endif
#include <wlr/backend/interface.h>
#include <wlr/backend/x11.h>
#include <wlr/egl.h>
@@ -59,8 +63,7 @@ static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *e
x11->time = ev->time;
break;
}
- case XCB_BUTTON_PRESS:
- case XCB_BUTTON_RELEASE: {
+ case XCB_BUTTON_PRESS: {
xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event;
if (ev->detail == XCB_BUTTON_INDEX_4 ||
@@ -75,7 +78,16 @@ static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *e
.delta = delta,
};
wl_signal_emit(&x11->pointer.events.axis, &axis);
- } else {
+ x11->time = ev->time;
+ break;
+ }
+ }
+ /* fallthrough */
+ case XCB_BUTTON_RELEASE: {
+ xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event;
+
+ if (ev->detail != XCB_BUTTON_INDEX_4 &&
+ ev->detail != XCB_BUTTON_INDEX_5) {
struct wlr_event_pointer_button button = {
.device = &x11->pointer_dev,
.time_sec = ev->time / 1000,
diff --git a/examples/output-layout.c b/examples/output-layout.c
index 560a7113..771ccd77 100644
--- a/examples/output-layout.c
+++ b/examples/output-layout.c
@@ -1,5 +1,5 @@
#define _POSIX_C_SOURCE 199309L
-#define _XOPEN_SOURCE 500
+#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
diff --git a/include/rootston/view.h b/include/rootston/view.h
index af087182..a4fb6f01 100644
--- a/include/rootston/view.h
+++ b/include/rootston/view.h
@@ -17,8 +17,6 @@ struct roots_wl_shell_surface {
struct wl_listener request_set_maximized;
struct wl_listener surface_commit;
-
- bool initialized;
};
struct roots_xdg_surface_v6 {
@@ -32,8 +30,6 @@ struct roots_xdg_surface_v6 {
struct wl_listener request_move;
struct wl_listener request_resize;
struct wl_listener request_show_window_menu;
-
- bool initialized;
};
struct roots_xwayland_surface {
@@ -85,6 +81,6 @@ void view_activate(struct roots_view *view, bool active);
void view_resize(struct roots_view *view, uint32_t width, uint32_t height);
void view_close(struct roots_view *view);
bool view_center(struct roots_view *view);
-bool view_initialize(struct roots_view *view);
+void view_initialize(struct roots_view *view);
#endif
diff --git a/include/wlr/types/wlr_output_layout.h b/include/wlr/types/wlr_output_layout.h
index fe09106f..ea8dbcd2 100644
--- a/include/wlr/types/wlr_output_layout.h
+++ b/include/wlr/types/wlr_output_layout.h
@@ -84,4 +84,10 @@ struct wlr_box *wlr_output_layout_get_box(
void wlr_output_layout_add_auto(struct wlr_output_layout *layout,
struct wlr_output *output);
+/**
+ * Get the output closest to the center of the layout extents.
+ */
+struct wlr_output *wlr_output_layout_get_center_output(
+ struct wlr_output_layout *layout);
+
#endif
diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h
index 48da6604..b0de41e2 100644
--- a/include/wlr/types/wlr_xdg_shell_v6.h
+++ b/include/wlr/types/wlr_xdg_shell_v6.h
@@ -106,6 +106,7 @@ struct wlr_xdg_surface_v6 {
struct wl_list popup_link;
bool configured;
+ bool added;
struct wl_event_source *configure_idle;
struct wl_list configure_list;
diff --git a/include/wlr/util/log.h b/include/wlr/util/log.h
index 3de2cacf..b017cc96 100644
--- a/include/wlr/util/log.h
+++ b/include/wlr/util/log.h
@@ -16,7 +16,7 @@ typedef enum {
typedef void (*log_callback_t)(log_importance_t importance, const char *fmt, va_list args);
-void wlr_init_log(log_callback_t callback);
+void wlr_log_init(log_callback_t callback);
#ifdef __GNUC__
#define ATTRIB_PRINTF(start, end) __attribute__((format(printf, start, end)))
diff --git a/meson.build b/meson.build
index d885484b..3e4cab38 100644
--- a/meson.build
+++ b/meson.build
@@ -34,6 +34,9 @@ if cc.get_id() == 'clang'
add_project_arguments('-Wno-missing-braces', language: 'c')
endif
+# Avoid wl_buffer deprecation warnings
+add_project_arguments('-DWL_HIDE_DEPRECATED', language: 'c')
+
wayland_server = dependency('wayland-server')
wayland_client = dependency('wayland-client')
wayland_egl = dependency('wayland-egl')
diff --git a/protocol/meson.build b/protocol/meson.build
index 79871fea..2cbb5b6d 100644
--- a/protocol/meson.build
+++ b/protocol/meson.build
@@ -46,7 +46,8 @@ foreach p : client_protocols
wl_protos_headers += wayland_scanner_client.process(xml)
endforeach
-lib_wl_protos = static_library('wl_protos', wl_protos_src + wl_protos_headers)
+lib_wl_protos = static_library('wl_protos', wl_protos_src + wl_protos_headers,
+ dependencies: [wayland_client]) # for the include directory
wlr_protos = declare_dependency(
link_with: lib_wl_protos,
diff --git a/rootston/config.c b/rootston/config.c
index 4918c8dd..5e911e39 100644
--- a/rootston/config.c
+++ b/rootston/config.c
@@ -11,6 +11,7 @@
#include <wlr/util/log.h>
#include <wlr/types/wlr_box.h>
#include "rootston/config.h"
+#include "rootston/input.h"
#include "rootston/ini.h"
static void usage(const char *name, int ret) {
@@ -109,6 +110,42 @@ static uint32_t parse_modifier(const char *symname) {
}
}
+void add_binding_config(struct wl_list *bindings, const char* combination,
+ const char* command) {
+ struct binding_config *bc = calloc(1, sizeof(struct 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(L_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 const char *output_prefix = "output:";
static const char *device_prefix = "device:";
@@ -216,45 +253,7 @@ static int config_ini_handler(void *user, const char *section, const char *name,
wlr_log(L_ERROR, "got unknown keyboard config: %s", name);
}
} else if (strcmp(section, "bindings") == 0) {
- struct binding_config *bc = calloc(1, sizeof(struct binding_config));
- wl_list_insert(&config->bindings, &bc->link);
-
- bc->command = strdup(value);
-
- size_t keysyms_len = 1;
- char *symnames = strdup(name);
- for (char *c = symnames; *c != '\0'; c++) {
- if (*c == '+') {
- *c = '\0';
- keysyms_len++;
- }
- }
-
- // TODO: bc->keysyms is larger than needed
- bc->keysyms = calloc(1, keysyms_len * sizeof(xkb_keysym_t));
- char *symname = symnames;
- for (size_t i = 0; i < keysyms_len; i++) {
- 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(L_ERROR, "got unknown key binding symbol: %s",
- symname);
- wl_list_remove(&bc->link);
- free(bc->keysyms);
- free(bc);
- break;
- }
- bc->keysyms[bc->keysyms_len] = sym;
- bc->keysyms_len++;
- }
- symname += strlen(symname) + 1;
- }
-
- free(symnames);
+ add_binding_config(&config->bindings, name, value);
} else {
wlr_log(L_ERROR, "got unknown config section: %s", section);
}
@@ -298,15 +297,9 @@ struct roots_config *parse_args(int argc, char *argv[]) {
if (result == -1) {
wlr_log(L_DEBUG, "No config file found. Using empty config.");
-
- struct binding_config *bc = calloc(1, sizeof(struct binding_config));
- wl_list_insert(&config->bindings, &bc->link);
- bc->command = strdup("exit");
- bc->modifiers = WLR_MODIFIER_LOGO;
- bc->keysyms_len = 2;
- bc->keysyms = calloc(1, bc->keysyms_len * sizeof(xkb_keysym_t));
- bc->keysyms[0] = XKB_KEY_Meta_L;
- bc->keysyms[1] = XKB_KEY_q;
+ 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");
} else if (result == -2) {
wlr_log(L_ERROR, "Could not allocate memory to parse config file");
exit(1);
diff --git a/rootston/cursor.c b/rootston/cursor.c
index 03189587..65109534 100644
--- a/rootston/cursor.c
+++ b/rootston/cursor.c
@@ -1,10 +1,13 @@
-#define _XOPEN_SOURCE 500
+#define _XOPEN_SOURCE 700
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
-// TODO: BSD et al
+#ifdef __linux__
#include <linux/input-event-codes.h>
+#elif __FreeBSD__
+#include <dev/evdev/input-event-codes.h>
+#endif
#include <wayland-server.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/util/log.h>
diff --git a/rootston/desktop.c b/rootston/desktop.c
index d5cac575..a7137255 100644
--- a/rootston/desktop.c
+++ b/rootston/desktop.c
@@ -67,35 +67,42 @@ void view_close(struct roots_view *view) {
bool view_center(struct roots_view *view) {
struct wlr_box size;
view_get_size(view, &size);
- if (size.width == 0 && size.height == 0) {
- return false;
- }
struct roots_desktop *desktop = view->desktop;
struct wlr_cursor *cursor = desktop->server->input->cursor;
- struct wlr_output *output = wlr_output_layout_output_at(desktop->layout,
- cursor->x, cursor->y);
- const struct wlr_output_layout_output *output_layout =
- wlr_output_layout_get(desktop->layout, output);
+
+ struct wlr_output *output =
+ wlr_output_layout_output_at(desktop->layout, cursor->x, cursor->y);
+
+ if (!output) {
+ output = wlr_output_layout_get_center_output(desktop->layout);
+ }
+
if (!output) {
+ // empty layout
return false;
}
- view->x = (double)(output->width - size.width) / 2
- + output_layout->x;
- view->y = (double)(output->height - size.height) / 2
- + output_layout->y;
+ 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);
+
+ view->x = (double)(width - size.width) / 2
+ + l_output->x;
+ view->y = (double)(height - size.height) / 2
+ + l_output->y;
+
return true;
}
-bool view_initialize(struct roots_view *view) {
- bool centered = view_center(view);
- if (centered) {
- struct roots_input *input = view->desktop->server->input;
- set_view_focus(input, view->desktop, view);
- wlr_seat_keyboard_notify_enter(input->wl_seat, view->wlr_surface);
- }
- return centered;
+void view_initialize(struct roots_view *view) {
+ view_center(view);
+ struct roots_input *input = view->desktop->server->input;
+
+ set_view_focus(input, view->desktop, view);
+ wlr_seat_keyboard_notify_enter(input->wl_seat, view->wlr_surface);
}
struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly,
diff --git a/rootston/keyboard.c b/rootston/keyboard.c
index 6f4334af..aee6b098 100644
--- a/rootston/keyboard.c
+++ b/rootston/keyboard.c
@@ -32,6 +32,13 @@ static void keyboard_binding_execute(struct roots_keyboard *keyboard,
if (keyboard->input->last_active_view != NULL) {
view_close(keyboard->input->last_active_view);
}
+ } else if (strcmp(command, "next_window") == 0) {
+ if (server->desktop->views->length > 0) {
+ struct roots_view *view = server->desktop->views->items[0];
+ set_view_focus(keyboard->input, server->desktop, view);
+ wlr_seat_keyboard_notify_enter(keyboard->input->wl_seat,
+ view->wlr_surface);
+ }
} else if (strncmp(exec_prefix, command, strlen(exec_prefix)) == 0) {
const char *shell_cmd = command + strlen(exec_prefix);
pid_t pid = fork();
diff --git a/rootston/output.c b/rootston/output.c
index 2c061739..39a90fe3 100644
--- a/rootston/output.c
+++ b/rootston/output.c
@@ -1,4 +1,4 @@
-#define _POSIX_C_SOURCE 199309L
+#define _POSIX_C_SOURCE 200809L
#include <time.h>
#include <stdlib.h>
#include <stdbool.h>
diff --git a/rootston/rootston.ini.example b/rootston/rootston.ini.example
index 460efa13..4774108a 100644
--- a/rootston/rootston.ini.example
+++ b/rootston/rootston.ini.example
@@ -38,3 +38,4 @@ meta-key = Logo
[bindings]
Logo+Shift+e = exit # Stop the compositor
Logo+q = close # Close the current view
+Alt+Tab = next_window # Cycle through windows
diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c
index 34f53c7a..33f54a32 100644
--- a/rootston/wl_shell.c
+++ b/rootston/wl_shell.c
@@ -50,14 +50,7 @@ static void handle_request_resize(struct wl_listener *listener, void *data) {
}
static void handle_surface_commit(struct wl_listener *listener, void *data) {
- struct roots_wl_shell_surface *roots_surface =
- wl_container_of(listener, roots_surface, surface_commit);
- struct roots_view *view = roots_surface->view;
-
- if (view->wl_shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_TOPLEVEL &&
- !roots_surface->initialized) {
- roots_surface->initialized = view_initialize(view);
- }
+ // TODO do we need to do anything here?
}
static void handle_destroy(struct wl_listener *listener, void *data) {
@@ -137,4 +130,5 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
view->desktop = desktop;
roots_surface->view = view;
list_add(desktop->views, view);
+ view_initialize(view);
}
diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c
index 9b8d8882..1e21fa02 100644
--- a/rootston/xdg_shell_v6.c
+++ b/rootston/xdg_shell_v6.c
@@ -68,14 +68,7 @@ static void handle_request_resize(struct wl_listener *listener, void *data) {
}
static void handle_commit(struct wl_listener *listener, void *data) {
- struct roots_xdg_surface_v6 *roots_xdg_surface =
- wl_container_of(listener, roots_xdg_surface, commit);
- struct roots_view *view = roots_xdg_surface->view;
-
- if (view->xdg_surface_v6->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL &&
- !roots_xdg_surface->initialized) {
- roots_xdg_surface->initialized = view_initialize(view);
- }
+ // TODO is there anything we need to do here?
}
static void handle_destroy(struct wl_listener *listener, void *data) {
@@ -141,4 +134,6 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
view->desktop = desktop;
roots_surface->view = view;
list_add(desktop->views, view);
+
+ view_initialize(view);
}
diff --git a/types/wlr_keyboard.c b/types/wlr_keyboard.c
index f37895b0..c27264ef 100644
--- a/types/wlr_keyboard.c
+++ b/types/wlr_keyboard.c
@@ -48,6 +48,9 @@ static void keyboard_modifier_update(struct wlr_keyboard *keyboard) {
void wlr_keyboard_notify_modifiers(struct wlr_keyboard *keyboard,
uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked,
uint32_t group) {
+ if (!keyboard->xkb_state) {
+ return;
+ }
xkb_state_update_mask(keyboard->xkb_state, mods_depressed, mods_latched,
mods_locked, 0, 0, group);
keyboard_modifier_update(keyboard);
@@ -55,6 +58,9 @@ void wlr_keyboard_notify_modifiers(struct wlr_keyboard *keyboard,
void wlr_keyboard_notify_key(struct wlr_keyboard *keyboard,
struct wlr_event_keyboard_key *event) {
+ if (!keyboard->xkb_state) {
+ return;
+ }
if (event->update_state) {
uint32_t keycode = event->keycode + 8;
xkb_state_update_key(keyboard->xkb_state, keycode,
diff --git a/types/wlr_output.c b/types/wlr_output.c
index d3b37d65..4c9814ef 100644
--- a/types/wlr_output.c
+++ b/types/wlr_output.c
@@ -1,4 +1,4 @@
-#define _POSIX_C_SOURCE 199309L
+#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <stdlib.h>
#include <string.h>
diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c
index 1890074b..8c3f1d88 100644
--- a/types/wlr_output_layout.c
+++ b/types/wlr_output_layout.c
@@ -343,3 +343,20 @@ void wlr_output_layout_add_auto(struct wlr_output_layout *layout,
l_output->state->auto_configured = true;
wlr_output_layout_reconfigure(layout);
}
+
+struct wlr_output *wlr_output_layout_get_center_output(
+ struct wlr_output_layout *layout) {
+ if (wl_list_empty(&layout->outputs)) {
+ return NULL;
+ }
+
+ struct wlr_box *extents = wlr_output_layout_get_box(layout, NULL);
+ double center_x = extents->width / 2 + extents->x;
+ double center_y = extents->height / 2 + extents->y;
+
+ double dest_x = 0, dest_y = 0;
+ wlr_output_layout_closest_point(layout, NULL, center_x, center_y,
+ &dest_x, &dest_y);
+
+ return wlr_output_layout_output_at(layout, dest_x, dest_y);
+}
diff --git a/types/wlr_seat.c b/types/wlr_seat.c
index aea4196b..ce055520 100644
--- a/types/wlr_seat.c
+++ b/types/wlr_seat.c
@@ -516,6 +516,7 @@ void wlr_seat_pointer_end_grab(struct wlr_seat *wlr_seat) {
struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab;
if (grab != wlr_seat->pointer_state.default_grab) {
wlr_seat->pointer_state.grab = wlr_seat->pointer_state.default_grab;
+ wl_signal_emit(&wlr_seat->events.pointer_grab_end, grab);
}
}
diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c
index a16d3319..c8c09dc9 100644
--- a/types/wlr_xdg_shell_v6.c
+++ b/types/wlr_xdg_shell_v6.c
@@ -9,6 +9,7 @@
#include <wlr/types/wlr_surface.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/util/log.h>
+#include <wlr/render/interface.h>
#include "xdg-shell-unstable-v6-protocol.h"
static const char *wlr_desktop_xdg_toplevel_role = "xdg_toplevel";
@@ -802,10 +803,7 @@ static void xdg_surface_ack_configure(struct wl_client *client,
break;
}
- if (!surface->configured) {
- surface->configured = true;
- wl_signal_emit(&surface->client->shell->events.new_surface, surface);
- }
+ surface->configured = true;
wl_signal_emit(&surface->events.ack_configure, surface);
@@ -996,7 +994,7 @@ static void wlr_xdg_surface_v6_toplevel_committed(
struct wlr_xdg_surface_v6 *surface) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
- if (!surface->surface->current->buffer && !surface->toplevel_state->added) {
+ if (!surface->surface->texture->valid && !surface->toplevel_state->added) {
// on the first commit, send a configure request to tell the client it
// is added
wlr_xdg_surface_v6_schedule_configure(surface, true);
@@ -1004,7 +1002,7 @@ static void wlr_xdg_surface_v6_toplevel_committed(
return;
}
- if (!surface->surface->current->buffer) {
+ if (!surface->surface->texture->valid) {
return;
}
@@ -1026,7 +1024,7 @@ static void handle_wlr_surface_committed(struct wl_listener *listener,
struct wlr_xdg_surface_v6 *surface =
wl_container_of(listener, surface, surface_commit_listener);
- if (surface->surface->current->buffer && !surface->configured) {
+ if (surface->surface->texture->valid && !surface->configured) {
wl_resource_post_error(surface->resource,
ZXDG_SURFACE_V6_ERROR_UNCONFIGURED_BUFFER,
"xdg_surface has never been configured");
@@ -1055,6 +1053,11 @@ static void handle_wlr_surface_committed(struct wl_listener *listener,
break;
}
+ if (surface->configured && !surface->added) {
+ surface->added = true;
+ wl_signal_emit(&surface->client->shell->events.new_surface, surface);
+ }
+
wl_signal_emit(&surface->events.commit, surface);
}
@@ -1090,7 +1093,7 @@ static void xdg_shell_get_xdg_surface(struct wl_client *wl_client,
&zxdg_surface_v6_interface, wl_resource_get_version(client_resource),
id);
- if (surface->surface->current->buffer != NULL) {
+ if (surface->surface->texture->valid) {
wl_resource_post_error(surface->resource,
ZXDG_SURFACE_V6_ERROR_UNCONFIGURED_BUFFER,
"xdg_surface must not have a buffer at creation");
@@ -1147,8 +1150,7 @@ static void wlr_xdg_client_v6_destroy(struct wl_resource *resource) {
struct wlr_xdg_surface_v6 *surface, *tmp = NULL;
wl_list_for_each_safe(surface, tmp, &client->surfaces, link) {
- wl_list_remove(&surface->link);
- wl_list_init(&surface->link);
+ xdg_surface_destroy(surface);
}
if (client->ping_timer != NULL) {
diff --git a/util/log.c b/util/log.c
index 78dc97f9..3661b73c 100644
--- a/util/log.c
+++ b/util/log.c
@@ -1,4 +1,4 @@
-#define _POSIX_C_SOURCE 1
+#define _POSIX_C_SOURCE 199506L
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
diff --git a/xcursor/meson.build b/xcursor/meson.build
index e8d456cb..afaab915 100644
--- a/xcursor/meson.build
+++ b/xcursor/meson.build
@@ -5,4 +5,5 @@ lib_wlr_xcursor = static_library(
'wlr_xcursor.c',
),
include_directories: wlr_inc,
+ dependencies: [egl] # header required via include/wlr/render.h
)
diff --git a/xwayland/sockets.c b/xwayland/sockets.c
index 48bcc822..dd732dd7 100644
--- a/xwayland/sockets.c
+++ b/xwayland/sockets.c
@@ -1,4 +1,8 @@
#define _XOPEN_SOURCE 700
+#ifdef __FreeBSD__
+// for SOCK_CLOEXEC
+#define __BSD_VISIBLE 1
+#endif
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
@@ -65,9 +69,12 @@ static bool open_sockets(int socks[2], int display) {
mkdir(socket_dir, 0777);
- // TODO: non-linux apparently want another format
+#ifdef __linux__
addr.sun_path[0] = 0;
path_size = snprintf(addr.sun_path + 1, sizeof(addr.sun_path) - 1, socket_fmt, display);
+#else
+ path_size = snprintf(addr.sun_path, sizeof(addr.sun_path), socket_fmt, display);
+#endif
socks[0] = open_socket(&addr, path_size);
if (socks[0] < 0) {
return false;
diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c
index 2bec1b63..f1599911 100644
--- a/xwayland/xwayland.c
+++ b/xwayland/xwayland.c
@@ -1,5 +1,9 @@
#define _XOPEN_SOURCE 700
#define _DEFAULT_SOURCE
+#ifdef __FreeBSD__
+// for SOCK_CLOEXEC
+#define __BSD_VISIBLE 1
+#endif
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
@@ -17,6 +21,14 @@
#include "sockets.h"
#include "xwm.h"
+#ifdef __FreeBSD__
+static inline int clearenv(void) {
+ extern char **environ;
+ environ[0] = NULL;
+ return 0;
+}
+#endif
+
static void safe_close(int fd) {
if (fd >= 0) {
close(fd);