diff --git a/Makefile b/Makefile index f1453d4..c26363e 100644 --- a/Makefile +++ b/Makefile @@ -6,4 +6,4 @@ proto: compile: proto gcc -o absinthe src/* \ -I./ -I./include -DWLR_USE_UNSTABLE $(shell pkg-config wlroots-0.19 --libs --cflags) -lwayland-server -lxkbcommon \ - -ggdb -Wall -Wextra + -ggdb diff --git a/include/output.h b/include/output.h index de7b163..80cb80f 100644 --- a/include/output.h +++ b/include/output.h @@ -5,3 +5,4 @@ void output_frame(struct wl_listener *listener, void *data); void output_request_state(struct wl_listener *listener, void *data); void output_destroy(struct wl_listener *listener, void *data); +void output_layout_change(struct wl_listener *listener, void *data); diff --git a/include/server.h b/include/server.h index 9682c30..df97446 100644 --- a/include/server.h +++ b/include/server.h @@ -5,8 +5,8 @@ void server_new_output(struct wl_listener *listener, void *data); void server_new_xdg_toplevel(struct wl_listener *listener, void *data); - void server_new_xdg_popup(struct wl_listener *listener, void *data); +void server_new_xdg_decoration(struct wl_listener *listener, void *data); void server_cursor_motion(struct wl_listener *listener, void *data); void server_cursor_motion_absolute(struct wl_listener *listener, void *data); diff --git a/include/types.h b/include/types.h index 75ce144..2ed838e 100644 --- a/include/types.h +++ b/include/types.h @@ -13,6 +13,8 @@ #include #include #include +#include +#include #define ABSINTHE_CURSOR_MOD WLR_MODIFIER_ALT #define ABSINTHE_CURSOR_MOVE_BUTTON BTN_LEFT @@ -36,6 +38,7 @@ struct absinthe_server { struct wlr_backend *backend; struct wlr_renderer *renderer; struct wlr_allocator *allocator; + struct wlr_compositor *compositor; struct wlr_scene *scene; struct wlr_scene_output_layout *scene_layout; @@ -43,6 +46,8 @@ struct absinthe_server { struct wl_listener new_xdg_toplevel; struct wl_listener new_xdg_popup; struct wl_list toplevels; + struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr; + struct wl_listener new_xdg_decoration; struct wlr_cursor *cursor; struct wlr_xcursor_manager *cursor_mgr; @@ -60,14 +65,17 @@ struct absinthe_server { struct wl_list keyboards; enum absinthe_cursor_mode cursor_mode; struct absinthe_toplevel *grabbed_toplevel; - uint32_t grabbed_toplevel_x, grabbed_toplevel_y; - uint32_t grabbed_toplevel_width, grabbed_toplevel_height; + struct wlr_box grabbed_box; uint32_t grab_x, grab_y; enum absinthe_cursor_resize_corner cursor_resize_corner; - struct wlr_output_layout *output_layout; struct wl_list outputs; struct wl_listener new_output; + struct wlr_output_layout *output_layout; + struct wl_listener output_layout_change; + struct wlr_output_manager_v1 *output_mgr; + struct wl_listener output_mgr_apply; + struct wl_listener output_mgr_test; }; struct absinthe_output { @@ -82,8 +90,8 @@ struct absinthe_output { struct absinthe_toplevel { struct wl_list link; struct absinthe_server *server; - struct wlr_xdg_toplevel *xdg_toplevel; struct wlr_scene_tree *scene_tree; + struct wlr_xdg_toplevel *xdg_toplevel; struct wl_listener map; struct wl_listener unmap; struct wl_listener commit; @@ -92,6 +100,9 @@ struct absinthe_toplevel { struct wl_listener request_resize; struct wl_listener request_maximize; struct wl_listener request_fullscreen; + struct wlr_xdg_toplevel_decoration_v1 *decoration; + struct wl_listener decoration_request_mode; + struct wl_listener decoration_destroy; }; struct absinthe_popup { diff --git a/include/xdg-decoration.h b/include/xdg-decoration.h new file mode 100644 index 0000000..0f953c3 --- /dev/null +++ b/include/xdg-decoration.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +void xdg_decoration_request_mode(struct wl_listener *listener, void *data); +void xdg_decoration_destroy(struct wl_listener *listener, void *data); diff --git a/src/cursor.c b/src/cursor.c index 9a6385e..963e339 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -16,8 +16,8 @@ static void process_cursor_move(struct absinthe_server *server) { if (!toplevel) return; uint32_t new_x, new_y; - new_x = server->cursor->x - server->grab_x + server->grabbed_toplevel_x; - new_y = server->cursor->y - server->grab_y + server->grabbed_toplevel_y; + new_x = server->cursor->x - server->grab_x + server->grabbed_box.x; + new_y = server->cursor->y - server->grab_y + server->grabbed_box.y; wlr_scene_node_set_position(&toplevel->scene_tree->node, new_x, new_y); } @@ -27,10 +27,10 @@ static void process_cursor_resize(struct absinthe_server *server) { if (!toplevel) return; int32_t new_x, new_y, new_width, new_height; - new_x = server->grabbed_toplevel_x; - new_y = server->grabbed_toplevel_y; - new_width = server->grabbed_toplevel_width; - new_height = server->grabbed_toplevel_height; + new_x = server->grabbed_box.x; + new_y = server->grabbed_box.y; + new_width = server->grabbed_box.width; + new_height = server->grabbed_box.height; switch (server->cursor_resize_corner) { case ABSINTHE_CURSOR_RESIZE_CORNER_TOP_LEFT: diff --git a/src/keyboard.c b/src/keyboard.c index 9be903e..af342c2 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -19,6 +20,16 @@ static bool keyboard_handle_keybind(struct absinthe_server *server, xkb_keysym_t case XKB_KEY_Escape: wl_display_terminate(server->display); break; + case XKB_KEY_Q: + if (fork() == 0) { + execl("/bin/sh", "sh", "-c", "wofi --show drun", NULL); + } + break; + case XKB_KEY_Return: + if (fork() == 0) { + execl("/bin/sh", "sh", "-c", "alacritty", NULL); + } + break; default: return false; } diff --git a/src/main.c b/src/main.c index b77ea31..c92f362 100644 --- a/src/main.c +++ b/src/main.c @@ -3,10 +3,23 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "types.h" #include "server.h" #include "seat.h" +#include "output.h" int main(int argc, char **argv) { @@ -40,16 +53,38 @@ int main(int argc, char **argv) return 1; } - wlr_compositor_create(server.display, 5, server.renderer); + server.compositor = wlr_compositor_create(server.display, 6, server.renderer); wlr_subcompositor_create(server.display); wlr_data_device_manager_create(server.display); + wlr_screencopy_manager_v1_create(server.display); + wlr_data_control_manager_v1_create(server.display); + wlr_viewporter_create(server.display); + wlr_single_pixel_buffer_manager_v1_create(server.display); + wlr_fractional_scale_manager_v1_create(server.display, 1); + wlr_presentation_create(server.display, server.backend, 2); + wlr_alpha_modifier_v1_create(server.display); + wlr_export_dmabuf_manager_v1_create(server.display); + wlr_ext_foreign_toplevel_list_v1_create(server.display, 1); - server.output_layout = wlr_output_layout_create(server.display); + wlr_server_decoration_manager_set_default_mode( + wlr_server_decoration_manager_create(server.display), + WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); + server.xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(server.display); + server.new_xdg_decoration.notify = server_new_xdg_decoration; + wl_signal_add(&server.xdg_decoration_mgr->events.new_toplevel_decoration, &server.new_xdg_decoration); wl_list_init(&server.outputs); server.new_output.notify = server_new_output; wl_signal_add(&server.backend->events.new_output, &server.new_output); + server.output_layout = wlr_output_layout_create(server.display); + server.output_layout_change.notify = output_layout_change; + wl_signal_add(&server.output_layout->events.change, &server.output_layout_change); + + server.output_mgr = wlr_output_manager_v1_create(server.display); + + wlr_xdg_output_manager_v1_create(server.display, server.output_layout); + server.scene = wlr_scene_create(); server.scene_layout = wlr_scene_attach_output_layout(server.scene, server.output_layout); @@ -111,6 +146,7 @@ int main(int argc, char **argv) wl_list_remove(&server.new_xdg_toplevel.link); wl_list_remove(&server.new_xdg_popup.link); + wl_list_remove(&server.new_xdg_decoration.link); wl_list_remove(&server.cursor_motion.link); wl_list_remove(&server.cursor_motion_absolute.link); diff --git a/src/output.c b/src/output.c index 6172a31..3021bcd 100644 --- a/src/output.c +++ b/src/output.c @@ -33,3 +33,26 @@ void output_destroy(struct wl_listener *listener, void *data) wl_list_remove(&output->link); free(output); } + +void output_layout_change(struct wl_listener *listener, void *data) +{ + struct absinthe_server *server = wl_container_of(listener, server, output_layout_change); + struct wlr_output_configuration_v1 *config = wlr_output_configuration_v1_create(); + + struct wlr_output_configuration_head_v1 *config_head; + struct absinthe_output *output; + wl_list_for_each(output, &server->outputs, link) { + if (output->wlr_output->enabled) continue; + + config_head = wlr_output_configuration_head_v1_create(config, output->wlr_output); + config_head->state.enabled = false; + wlr_output_layout_remove(server->output_layout, output->wlr_output); + } + + wl_list_for_each(output, &server->outputs, link) { + if (!output->wlr_output->enabled || !wlr_output_layout_get(server->output_layout, output->wlr_output)) continue; + wlr_output_layout_add_auto(server->output_layout, output->wlr_output); + } + + wlr_output_manager_v1_set_configuration(server->output_mgr, config); +} diff --git a/src/server.c b/src/server.c index fc42ac7..7601a89 100644 --- a/src/server.c +++ b/src/server.c @@ -7,6 +7,7 @@ #include "output.h" #include "xdg-toplevel.h" #include "xdg-popup.h" +#include "xdg-decoration.h" #include "absinthe-toplevel.h" #include "focus.h" #include "keyboard.h" @@ -59,7 +60,7 @@ void server_new_xdg_toplevel(struct wl_listener *listener, void *data) toplevel->xdg_toplevel = xdg_toplevel; toplevel->scene_tree = wlr_scene_xdg_surface_create(&toplevel->server->scene->tree, xdg_toplevel->base); toplevel->scene_tree->node.data = toplevel; - xdg_toplevel->base->data = toplevel->scene_tree; + xdg_toplevel->base->data = toplevel; toplevel->map.notify = xdg_toplevel_map; wl_signal_add(&xdg_toplevel->base->surface->events.map, &toplevel->map); @@ -101,6 +102,20 @@ void server_new_xdg_popup(struct wl_listener *listener, void *data) wl_signal_add(&xdg_popup->base->surface->events.destroy, &popup->destroy); } +void server_new_xdg_decoration(struct wl_listener *listener, void *data) +{ + struct wlr_xdg_toplevel_decoration_v1 *xdg_decoration = data; + struct absinthe_toplevel *toplevel = xdg_decoration->toplevel->base->data; + toplevel->decoration = xdg_decoration; + + toplevel->decoration_request_mode.notify = xdg_decoration_request_mode; + wl_signal_add(&xdg_decoration->events.request_mode, &toplevel->decoration_request_mode); + toplevel->decoration_destroy.notify = xdg_decoration_destroy; + wl_signal_add(&xdg_decoration->events.destroy, &toplevel->decoration_destroy); + + xdg_decoration_request_mode(&toplevel->decoration_request_mode, xdg_decoration); +} + void server_cursor_motion(struct wl_listener *listener, void *data) { struct absinthe_server *server = wl_container_of(listener, server, cursor_motion); @@ -122,7 +137,7 @@ void server_cursor_button(struct wl_listener *listener, void *data) struct absinthe_server *server = wl_container_of(listener, server, cursor_button); struct wlr_pointer_button_event *event = data; - wlr_seat_pointer_notify_button(server->seat, event->time_msec, event->button, event->state); + bool handled = false; if (event->state == WL_POINTER_BUTTON_STATE_RELEASED) { reset_cursor_mode(server); } else { @@ -136,8 +151,10 @@ void server_cursor_button(struct wl_listener *listener, void *data) if (mods & ABSINTHE_CURSOR_MOD) { if (event->button == ABSINTHE_CURSOR_MOVE_BUTTON) { server->cursor_mode = ABSINTHE_CURSOR_MOVE; + handled = true; } else if (event->button == ABSINTHE_CURSOR_RESIZE_BUTTON) { server->cursor_mode = ABSINTHE_CURSOR_RESIZE; + handled = true; } } if (toplevel) { @@ -146,11 +163,11 @@ void server_cursor_button(struct wl_listener *listener, void *data) int lx, ly; wlr_scene_node_coords(&toplevel->scene_tree->node, &lx, &ly); - server->grabbed_toplevel_x = lx; - server->grabbed_toplevel_y = ly; - server->grabbed_toplevel_width = toplevel->xdg_toplevel->base->geometry.width; - server->grabbed_toplevel_height = toplevel->xdg_toplevel->base->geometry.height; - wlr_log(WLR_DEBUG, "%d, %d", server->grabbed_toplevel_width, server->grabbed_toplevel_width); + server->grabbed_box.x = lx; + server->grabbed_box.y = ly; + server->grabbed_box.width = toplevel->xdg_toplevel->base->geometry.width; + server->grabbed_box.height = toplevel->xdg_toplevel->base->geometry.height; + wlr_log(WLR_DEBUG, "%d, %d", server->grabbed_box.width, server->grabbed_box.height); server->grabbed_toplevel = toplevel; int width = toplevel->xdg_toplevel->base->geometry.width; @@ -167,6 +184,10 @@ void server_cursor_button(struct wl_listener *listener, void *data) } } } + + if (!handled) { + wlr_seat_pointer_notify_button(server->seat, event->time_msec, event->button, event->state); + } } void server_cursor_axis(struct wl_listener *listener, void *data) diff --git a/src/xdg-decoration.c b/src/xdg-decoration.c new file mode 100644 index 0000000..eb59fe1 --- /dev/null +++ b/src/xdg-decoration.c @@ -0,0 +1,19 @@ +#include + +#include "types.h" + +void xdg_decoration_request_mode(struct wl_listener *listener, void *data) +{ + struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, decoration_request_mode); + if (toplevel->xdg_toplevel->base->initialized) { + wlr_xdg_toplevel_decoration_v1_set_mode(toplevel->decoration, WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); + } +} + +void xdg_decoration_destroy(struct wl_listener *listener, void *data) +{ + struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, decoration_destroy); + + wl_list_remove(&toplevel->decoration_request_mode.link); + wl_list_remove(&toplevel->decoration_destroy.link); +} diff --git a/src/xdg-toplevel.c b/src/xdg-toplevel.c index 37fb351..c6e94d0 100644 --- a/src/xdg-toplevel.c +++ b/src/xdg-toplevel.c @@ -3,6 +3,20 @@ #include #include "types.h" +#include "xdg-decoration.h" + +void xdg_toplevel_commit(struct wl_listener *listener, void *data) +{ + struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, commit); + + if (toplevel->xdg_toplevel->base->initial_commit) { + wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, 0, 0); + + if (toplevel->decoration) { + xdg_decoration_request_mode(&toplevel->decoration_request_mode, toplevel->decoration); + } + } +} void xdg_toplevel_map(struct wl_listener *listener, void *data) { @@ -18,15 +32,6 @@ void xdg_toplevel_unmap(struct wl_listener *listener, void *data) wl_list_remove(&toplevel->link); } -void xdg_toplevel_commit(struct wl_listener *listener, void *data) -{ - struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, commit); - - if (toplevel->xdg_toplevel->base->initial_commit) { - wlr_xdg_toplevel_set_size(toplevel->xdg_toplevel, 0, 0); - } -} - void xdg_toplevel_destroy(struct wl_listener *listener, void *data) { struct absinthe_toplevel *toplevel = wl_container_of(listener, toplevel, destroy);