diff --git a/config/layouts/tmp/init.lua b/config/layouts/tmp/init.lua index f50e507c..06026315 100644 --- a/config/layouts/tmp/init.lua +++ b/config/layouts/tmp/init.lua @@ -123,4 +123,3 @@ local resize_groups = {} resize_groups[1] = {{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}} layout:set_resize_data(resize_groups) opt.resize_direction = Direction.all -print("works") diff --git a/include/client.h b/include/client.h index 60d76361..ff086b5e 100644 --- a/include/client.h +++ b/include/client.h @@ -30,10 +30,14 @@ struct client { struct wl_listener set_app_id; struct wl_listener map; struct wl_listener unmap; + struct wl_listener associate; + struct wl_listener dissociate; struct wl_listener destroy; struct wl_listener new_popup; struct wl_listener new_subsurface; + struct scene_surface *scene_surface; + enum shell type; const char *title; const char *app_id; @@ -44,10 +48,6 @@ struct client { // enum zwlr_layer_surface_v1_layer layer; int layer; - // used to determine what to damage - bool resized; - bool moved_tag; - bool is_independent; // this is currently only used for layer_shell surfaces to help determine if // arrange_layers should be called bool mapped; diff --git a/include/container.h b/include/container.h index 350e68cc..839b1e83 100644 --- a/include/container.h +++ b/include/container.h @@ -83,13 +83,9 @@ struct wlr_box get_monitor_local_box(struct wlr_box box, struct monitor *m); struct wlr_fbox lua_togeometry(lua_State *L); void ack_configure(struct wl_listener *listener, void *data); -struct wlr_box apply_bounds(struct container *con, struct wlr_box bbox); +void apply_bounds(struct wlr_box *geom, struct wlr_box box); void commit_notify(struct wl_listener *listener, void *data); void configure_notify(struct wl_listener *listener, void *data); -void container_damage_borders_at_monitor(struct container *con, struct monitor *m); -void container_damage_borders(struct container *con); -void container_damage_part(struct container *con); -void container_damage_whole(struct container *con); void container_fix_position_to_begin(struct container *con); void container_fix_position(struct container *con); void focus_on_hidden_stack(struct monitor *m, int i); @@ -104,9 +100,14 @@ void container_set_floating(struct container *con, void (*fix_position)(struct c void container_set_hidden(struct container *con, bool b); void container_set_hidden_at_tag(struct container *con, bool b, struct tag *tag); void set_container_monitor(struct container *con, struct monitor *m); +void container_update_border(struct container *con); +void container_update_border_geometry(struct container *con); +void container_update_border_color(struct container *con); +void container_update_border_visibility(struct container *con); void resize_container(struct container *con, struct wlr_cursor *cursor, int dx, int dy); void resize_container_in_layout(struct container *con, struct wlr_box geom); void move_container(struct container *con, struct wlr_cursor *cursor, int offsetx, int offsety); +void scale_box(struct wlr_box *box, float scale); struct container_property *container_get_property(struct container *con); struct container_property *container_get_property_at_tag( @@ -168,8 +169,8 @@ void container_resize_with_cursor(struct cursor *cursor); struct monitor *container_get_monitor(struct container *con); -int absolute_x_to_container_relative(struct wlr_box geom, int x); -int absolute_y_to_container_relative(struct wlr_box geom, int y); +int absolute_x_to_container_local(struct wlr_box geom, int x); +int absolute_y_to_container_local(struct wlr_box geom, int y); int get_position_in_container_focus_stack(struct container *con); int get_position_in_container_stack(struct container *con); @@ -196,5 +197,7 @@ bool container_is_managed(struct container *con); bool container_is_tiled_and_managed(struct container *con); bool container_is_on_scratchpad(struct container *con); +struct wlr_scene_node *container_get_scene_node(struct container *con); + const char *container_get_app_id(struct container *con); #endif /* CONTAINER_H */ diff --git a/include/monitor.h b/include/monitor.h index fb99a05d..ce7e50af 100644 --- a/include/monitor.h +++ b/include/monitor.h @@ -2,7 +2,7 @@ #define MONITOR_H #include #include -#include +#include #include "server.h" #include "bitset/bitset.h" @@ -13,7 +13,6 @@ struct monitor { struct wlr_output *wlr_output; struct wlr_output_damage *damage; - struct wl_listener mode; struct wl_listener frame; struct wl_listener damage_frame; struct wl_listener destroy; @@ -22,6 +21,8 @@ struct monitor { struct root *root; float scale; + struct wlr_scene_output *scene_output; + int tag_id; }; diff --git a/include/popup.h b/include/popup.h index 03975fc6..07b05b24 100644 --- a/include/popup.h +++ b/include/popup.h @@ -10,6 +10,8 @@ struct xdg_popup { struct container *toplevel; struct wlr_box geom; struct monitor *m; + void *parent; + struct wlr_scene_surface *scene_surface; struct wl_listener map; struct wl_listener unmap; @@ -19,10 +21,16 @@ struct xdg_popup { }; struct xdg_popup *create_popup(struct monitor *m, struct wlr_xdg_popup *xdg_popup, - struct wlr_box parent_geom, struct container* toplevel); + void *parent, struct container* toplevel); void popup_handle_destroy(struct wl_listener *listener, void *data); void destroy_popups(); struct wlr_surface *get_popup_surface_under_cursor(struct cursor *cursor, double *sx, double *sy); struct xdg_popup *get_latest_popup(); bool popups_exist(); + +void popup_set_x(struct xdg_popup *popup, int x); +void popup_set_y(struct xdg_popup *popup, int y); +void popup_set_width(struct xdg_popup *popup, int width); +void popup_set_height(struct xdg_popup *popup, int height); +void pupup_update_position(struct xdg_popup *popup); #endif /* POPUP_H */ diff --git a/include/render.h b/include/render.h new file mode 100644 index 00000000..40f7028c --- /dev/null +++ b/include/render.h @@ -0,0 +1,27 @@ +#ifndef RENDER_H +#define RENDER_H + +#include + +#include "container.h" + +#define BORDER_COUNT 4 + +struct scene_surface { + struct wlr_surface *wlr; + struct wlr_scene_tree *surface_tree; + struct wlr_scene_surface *scene_surface; + struct wlr_scene_rect *borders[4]; + struct wl_list link; + + struct wl_listener commit; + struct wl_listener destroy; + struct wl_listener new_subsurface; +}; + +void scene_create(struct wlr_scene **scene); +void server_handle_new_surface(struct wl_listener *listener, void *data); + +struct client *wlr_surface_get_client(struct wlr_surface *wlr_surface); + +#endif /* RENDER_H */ diff --git a/include/render/render.h b/include/render/render.h deleted file mode 100644 index badfda33..00000000 --- a/include/render/render.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef RENDER_H -#define RENDER_H -#include "utils/coreUtils.h" -#include "client.h" -#include "monitor.h" -#include -#include -#include -#include -#include - -typedef void (*surface_iterator_func_t)(struct monitor *m, struct - wlr_surface *surface, struct wlr_box *box, void *user_data); - -struct surface_iterator_data { - surface_iterator_func_t user_iterator; - void *user_data; - - struct monitor *m; - - /* Output-local coordinates. */ - struct wlr_box render_box; -}; - -struct render_texture_data { - pixman_region32_t *output_damage; - float alpha; -}; - -void render_monitor(struct monitor *m, pixman_region32_t *damage); -void scale_box(struct wlr_box *box, float scale); -void output_damage_surface(struct monitor *m, struct wlr_surface *surface, - struct wlr_box *geom, bool whole); -#endif /* RENDER_H */ diff --git a/include/server.h b/include/server.h index 57ed4a99..90a2e435 100644 --- a/include/server.h +++ b/include/server.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "cursor.h" #include "layout.h" @@ -21,6 +22,7 @@ #include "input_manager.h" #include "utils/coreUtils.h" #include "bitset/bitset.h" +#include "render.h" struct server { bool is_running; @@ -29,6 +31,7 @@ struct server { struct wl_display *wl_display; struct wl_event_loop *wl_event_loop; + struct wlr_session *wlr_session; struct wlr_backend *backend; struct wlr_compositor *compositor; struct wlr_renderer *renderer; @@ -44,6 +47,16 @@ struct server { struct event_handler *event_handler; + struct wlr_scene *scene; + struct wlr_scene_tree *scene_background; + struct wlr_scene_tree *scene_tiled; + struct wlr_scene_tree *scene_floating; + struct wlr_scene_tree *scene_popups; + struct wlr_scene_tree *scene_overlay; + + + struct wl_listener new_surface; + struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr; diff --git a/include/utils/coreUtils.h b/include/utils/coreUtils.h index 241bb062..ba584910 100644 --- a/include/utils/coreUtils.h +++ b/include/utils/coreUtils.h @@ -21,9 +21,6 @@ typedef GPtrArray GPtrArray2D; /* macros */ //NOLINTNEXTLINE #define LENGTH(X) (sizeof X / sizeof X[0]) -#define END(A) ((A) + LENGTH(A)) -/* number of chars a string should contain */ -#define ARR_STRING_LENGTH(X) strlen(X) + 2*(strlen("[]") + NUM_DIGITS) // those constants are arbitrary and are bound to change #define MAXLEN 15 @@ -42,9 +39,10 @@ typedef GPtrArray GPtrArray2D; #define MIN_CONTAINER_HEIGHT 30 #define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) -#define foreach(item, array)\ - for(int keep = 1, count = 0, size = LENGTH(array); keep && count < size; keep = 1, count++)\ - for(item = array[count]; keep; keep = 0)\ +// version management +#define WL_COMPOSITOR_VERSION 6 +#define LAYER_SHELL_VERSION 4 +#define XDG_SHELL_VERSION 2 extern struct lua_State *L; @@ -147,7 +145,9 @@ void *get_relative_item_in_composed_list(GPtrArray *arrays, int i, int j); int exec(const char *cmd); bool is_approx_equal(double a, double b, double error_range); +// Converts a Lua table index (1-based) to a C array index (0-based). int lua_idx_to_c_idx(int lua_idx); +// Converts a C array index (0-based) to a Lua table index (1-based). int c_idx_to_lua_idx(int c_idx); int scale_percent_to_integer(float percent); diff --git a/include/utils/writeFile.h b/include/utils/writeFile.h index 5cca7157..e282dbe3 100644 --- a/include/utils/writeFile.h +++ b/include/utils/writeFile.h @@ -6,7 +6,6 @@ #include #include "utils/stringUtils.h" -#include "render/render.h" int write_to_file(int fd, const char *content); void write_container_to_file(int fd, struct wlr_fbox box); diff --git a/meson.build b/meson.build index 162ded77..1faa36ee 100644 --- a/meson.build +++ b/meson.build @@ -163,7 +163,7 @@ deps = [\ wayland_client, wayland_protos, dependency('pixman-1'), - dependency('wlroots', version: ['>=0.15' ,'<0.17']), + dependency('wlroots', version: ['>=0.15' ,'<0.18']), dependency('x11'), dependency('json-c'), dependency('libnotify'), diff --git a/src/client.c b/src/client.c index 2c26edd9..ae8c0c79 100644 --- a/src/client.c +++ b/src/client.c @@ -27,6 +27,21 @@ struct client *create_client(enum shell shell_type, union surface_t surface) c->type = shell_type; c->surface = surface; + // HACK: this is a hack. first wlr_surface->data is filled with the surface + // then we will override it with the client afterwards + switch (shell_type) { + case XDG_SHELL: + c->scene_surface = surface.xdg->surface->data; + break; + case LAYER_SHELL: + c->scene_surface = surface.layer->surface->data; + break; + case X11_MANAGED: + case X11_UNMANAGED: + c->scene_surface = surface.xwayland->data; + break; + } + return c; } @@ -104,6 +119,7 @@ static void unfocus_client(struct client *c) default: break; } + container_update_border_color(c->con); } void focus_surface(struct seat *seat, struct wlr_surface *surface) @@ -131,8 +147,6 @@ void focus_client(struct seat *seat, struct client *old, struct client *c) if (old_surface != new_surface) { cursor_constrain(seat->cursor, NULL); unfocus_client(old); - struct container *old_con = old->con; - container_damage_borders(old_con); } } @@ -152,10 +166,6 @@ void focus_client(struct seat *seat, struct client *old, struct client *c) /* Update wlroots'c keyboard focus */ focus_surface(seat, get_wlrsurface(c)); - struct container *con = c->con; - struct monitor *m = container_get_monitor(con); - container_damage_borders_at_monitor(con, m); - /* Activate the new client */ switch (c->type) { case XDG_SHELL: @@ -208,7 +218,7 @@ void client_handle_new_popup(struct wl_listener *listener, void *data) struct container *con = client->con; struct monitor *m = container_get_monitor(con); - create_popup(m, xdg_popup, container_get_current_geom(con), con); + create_popup(m, xdg_popup, con, con); } void client_handle_set_title(struct wl_listener *listener, void *data) @@ -282,6 +292,5 @@ void reset_floating_client_borders(int border_px) continue; } container_set_border_width(con, direction_value_uniform(border_px)); - container_damage_whole(con); } } diff --git a/src/container.c b/src/container.c index 9fa4dc0e..c38c7ce3 100644 --- a/src/container.c +++ b/src/container.c @@ -11,11 +11,9 @@ #include "cursor.h" #include "list_sets/container_stack_set.h" #include "list_sets/list_set.h" -#include "popup.h" #include "server.h" #include "monitor.h" #include "tile/tileUtils.h" -#include "render/render.h" #include "options.h" #include "utils/parseConfigUtils.h" #include "scratchpad.h" @@ -23,12 +21,12 @@ #include "ipc-server.h" #include "layer_shell.h" #include "tag.h" -#include "rules/rule.h" #include "list_sets/focus_stack_set.h" #include "options.h" #include "lib/lib_container.h" #include "lib/lib_layout.h" #include "lib/lib_geom.h" +#include "root.h" static void add_container_to_tag(struct container *con, struct tag *tag); @@ -98,8 +96,6 @@ void container_property_set_floating(struct container_property *property, bool f } lift_container(con); - con->client->resized = true; - container_damage_whole(con); container_update_size(con); } @@ -182,81 +178,12 @@ void remove_container_from_tile(struct container *con) ipc_event_tag(); } -void container_damage_borders_at_monitor(struct container *con, struct monitor *m) +void scale_box(struct wlr_box *box, float scale) { - if (!con) - return; - if (!m) - return; - - struct wlr_box *borders; - borders = (struct wlr_box[4]) { - container_get_current_border_geom(con, WLR_EDGE_TOP), - container_get_current_border_geom(con, WLR_EDGE_LEFT), - container_get_current_border_geom(con, WLR_EDGE_RIGHT), - container_get_current_border_geom(con, WLR_EDGE_BOTTOM), - }; - - for (int i = 0; i < 4; i++) { - struct wlr_box border = borders[i]; - double ox = border.x; - double oy = border.y; - wlr_output_layout_output_coords(server.output_layout, m->wlr_output, &ox, &oy); - struct wlr_box obox = { - .x = ox, - .y = oy, - .width = border.width, - .height = border.height, - }; - scale_box(&obox, m->wlr_output->scale); - wlr_output_damage_add_box(m->damage, &obox); - } -} - -void container_damage_borders(struct container *con) -{ - if (!con) - return; - - for (int i = 0; i < server.mons->len; i++) { - struct monitor *m = g_ptr_array_index(server.mons, i); - container_damage_borders_at_monitor(con, m); - } -} - -static void damage_container_area(struct container *con, struct wlr_box geom, - bool whole) -{ - for (int i = 0; i < server.mons->len; i++) { - struct monitor *m = g_ptr_array_index(server.mons, i); - output_damage_surface(m, get_wlrsurface(con->client), &geom, whole); - } - container_damage_borders(con); -} - -static void container_damage(struct container *con, bool whole) -{ - for (int i = 0; i < server.mons->len; i++) { - struct wlr_box con_geom = container_get_current_content_geom(con); - damage_container_area(con, con_geom, whole); - } - - struct client *c = con->client; - if (c->resized || c->moved_tag) { - damage_container_area(con, con->prev_geom, whole); - c->resized = false; - c->moved_tag = false; - } -} - -void container_damage_part(struct container *con) -{ - container_damage(con, false); -} - -void container_damage_whole(struct container *con) -{ - container_damage(con, true); + box->x *= scale; + box->y *= scale; + box->width *= scale; + box->height *= scale; } struct container *monitor_get_focused_container(struct monitor *m) @@ -402,30 +329,20 @@ struct wlr_fbox lua_togeometry(lua_State *L) } // TODO: look if this function is still needed -struct wlr_box apply_bounds(struct container *con, struct wlr_box box) +void apply_bounds(struct wlr_box *geom, struct wlr_box box) { /* set minimum possible */ - struct wlr_box con_geom = container_get_current_content_geom(con); - - if (container_is_tiled(con)) - return con_geom; + geom->width = MAX(MIN_CONTAINER_WIDTH, geom->width); + geom->height = MAX(MIN_CONTAINER_HEIGHT, geom->height); - con_geom.width = MAX(MIN_CONTAINER_WIDTH, con_geom.width); - con_geom.height = MAX(MIN_CONTAINER_HEIGHT, con_geom.height); - - struct direction_value bw = container_get_border_width(con); - - if (con_geom.x >= box.x + box.width) - con_geom.x = box.x + box.width - con_geom.width; - if (con_geom.y >= box.y + box.height) - con_geom.y = box.y + box.height - con_geom.height; - if (con_geom.x + con_geom.width + bw.left + bw.right <= box.x) - con_geom.x = box.x; - if (con_geom.y + con_geom.height + bw.top + bw.bottom <= box.y) - con_geom.y = box.y; - - container_set_current_content_geom(con, con_geom); - return con_geom; + if (geom->x >= box.x + box.width) + geom->x = box.x + box.width - geom->width; + if (geom->y >= box.y + box.height) + geom->y = box.y + box.height - geom->height; + if (geom->x + geom->width <= box.x) + geom->x = box.x; + if (geom->y + geom->height <= box.y) + geom->y = box.y; } void commit_notify(struct wl_listener *listener, void *data) @@ -437,7 +354,6 @@ void commit_notify(struct wl_listener *listener, void *data) struct container *con = c->con; if (con->is_on_tile) { - container_damage_part(c->con); } } @@ -704,6 +620,13 @@ void container_set_floating(struct container *con, void (*fix_position)(struct c if (fix_position) fix_position(con); + struct wlr_scene_node *node = container_get_scene_node(con); + if (floating) { + wlr_scene_node_reparent(node, server.scene_floating); + } else { + wlr_scene_node_reparent(node, server.scene_tiled); + } + container_property_set_floating(property, floating); } @@ -775,8 +698,7 @@ void move_container(struct container *con, struct wlr_cursor *cursor, int offset struct layout *lt = tag_get_layout(tag); container_set_border_width(con, direction_value_uniform(lt->options->float_border_px)); - con->client->resized = true; - container_damage(con, true); + container_update_size(con); } struct container_property *container_get_property(struct container *con) @@ -1041,44 +963,21 @@ struct wlr_box container_get_current_content_geom(struct container *con) struct wlr_box container_get_current_border_geom(struct container *con, enum wlr_edges dir) { struct wlr_box geom = container_get_current_geom(con); - enum wlr_edges hidden_edges = container_get_hidden_edges(con); + struct direction_value d = container_get_border_width(con); switch (dir) { case WLR_EDGE_TOP: - { - if (!(hidden_edges & WLR_EDGE_TOP)) { - struct direction_value d = container_get_border_width(con); - geom.height = d.top; - } - break; - } + geom.height = d.top; + break; case WLR_EDGE_BOTTOM: - { - if (!(hidden_edges & WLR_EDGE_BOTTOM)) { - struct direction_value d = container_get_border_width(con); - geom.y += geom.height - d.bottom; - geom.height = d.bottom; - } - break; - } + geom.y += geom.height - d.bottom; + geom.height = d.bottom; break; case WLR_EDGE_LEFT: - { - if (!(hidden_edges & WLR_EDGE_LEFT)) { - struct direction_value d = container_get_border_width(con); - geom.width = d.left; - } - break; - } + geom.width = d.left; break; case WLR_EDGE_RIGHT: - { - if (!(hidden_edges & WLR_EDGE_RIGHT)) { - struct direction_value d = container_get_border_width(con); - geom.x += geom.width - d.right; - geom.width = d.right; - } - break; - } + geom.x += geom.width - d.right; + geom.width = d.right; break; default: break; @@ -1167,6 +1066,136 @@ struct direction_value container_get_border_width(struct container *con) return property->border_width; } +// TODO refactor the name it doesn't represent what this does perfectly +// returns the newly accquired hidden edges +static enum wlr_edges container_update_hidden_edges(struct container *con, struct wlr_box *borders, enum wlr_edges hidden_edges) +{ + struct monitor *m = container_get_monitor(con); + + enum wlr_edges containers_hidden_edges = WLR_EDGE_NONE; + struct wlr_box con_geom = container_get_current_geom(con); + // int border_width = container_get_border_width(con); + // hide edges if needed + if (hidden_edges & WLR_EDGE_LEFT) { + if (con_geom.x == m->root->geom.x) { + containers_hidden_edges |= WLR_EDGE_LEFT; + } + } + if (hidden_edges & WLR_EDGE_RIGHT) { + if (is_approx_equal(con_geom.x + con_geom.width, m->root->geom.x + m->root->geom.width, 3)) { + containers_hidden_edges |= WLR_EDGE_RIGHT; + } + } + if (hidden_edges & WLR_EDGE_TOP) { + if (con_geom.y == m->root->geom.y) { + containers_hidden_edges |= WLR_EDGE_TOP; + } + } + if (hidden_edges & WLR_EDGE_BOTTOM) { + if (is_approx_equal(con_geom.y + con_geom.height, m->root->geom.y + m->root->geom.height, 3)) { + containers_hidden_edges |= WLR_EDGE_BOTTOM; + } + } + + container_set_hidden_edges(con, containers_hidden_edges); + return containers_hidden_edges; +} +void container_update_border(struct container *con) +{ + // optimization to not update the border if it's not needed + container_update_border_geometry(con); + container_update_border_color(con); +} + +void container_update_border_geometry(struct container *con) +{ + container_update_border_visibility(con); + // the visibility always has to be updated because has_border might have changed + if (!con->has_border) + return; + + struct scene_surface *surface = con->client->scene_surface; + + struct wlr_box *borders = (struct wlr_box[4]) { + container_get_current_border_geom(con, WLR_EDGE_TOP), + container_get_current_border_geom(con, WLR_EDGE_BOTTOM), + container_get_current_border_geom(con, WLR_EDGE_LEFT), + container_get_current_border_geom(con, WLR_EDGE_RIGHT), + }; + + for (int i = 0; i < BORDER_COUNT; i++) { + struct wlr_scene_rect *border = surface->borders[i]; + struct wlr_box geom = borders[i]; + wlr_scene_node_set_position(&border->node, geom.x, geom.y); + wlr_scene_rect_set_size(border, geom.width, geom.height); + } +} + +void container_update_border_color(struct container *con) +{ + if (!con->has_border) + return; + struct scene_surface *surface = con->client->scene_surface; + + struct monitor *m = container_get_monitor(con); + struct tag *tag = monitor_get_active_tag(m); + struct layout *lt = tag_get_layout(tag); + + struct container *sel = monitor_get_focused_container(m); + const struct color color = (con == sel) ? lt->options->focus_color : + lt->options->border_color; + + for (int i = 0; i < BORDER_COUNT; i++) { + struct wlr_scene_rect *border = surface->borders[i]; + float border_color[4]; + color_to_wlr_color(border_color, color); + wlr_scene_rect_set_color(border, border_color); + } +} + +void container_update_border_visibility(struct container *con) +{ + struct scene_surface *surface = con->client->scene_surface; + + if (!con->has_border) { + for (int i = 0; i < BORDER_COUNT; i++) { + struct wlr_scene_rect *border = surface->borders[i]; + wlr_scene_node_set_enabled(&border->node, false); + } + return; + } + + struct monitor *m = container_get_monitor(con); + struct tag *tag = monitor_get_active_tag(m); + struct layout *lt = tag_get_layout(tag); + + struct wlr_box *borders = (struct wlr_box[4]) { + container_get_current_border_geom(con, WLR_EDGE_TOP), + container_get_current_border_geom(con, WLR_EDGE_BOTTOM), + container_get_current_border_geom(con, WLR_EDGE_LEFT), + container_get_current_border_geom(con, WLR_EDGE_RIGHT), + }; + + enum wlr_edges hidden_edges = WLR_EDGE_NONE; + if (lt->options->smart_hidden_edges) { + if (tag->visible_con_set->tiled_containers->len <= 1) { + hidden_edges = container_update_hidden_edges(con, borders, + lt->options->hidden_edges); + } + } else { + hidden_edges = container_update_hidden_edges(con, borders, + lt->options->hidden_edges); + } + + for (int i = 0; i < BORDER_COUNT; i++) { + struct wlr_scene_rect *border = surface->borders[i]; + + bool is_hidden = hidden_edges & (1 << i); + // hide or show the border + wlr_scene_node_set_enabled(&border->node, !is_hidden); + } +} + void resize_container(struct container *con, struct wlr_cursor *cursor, int offsetx, int offsety) { if (!con) @@ -1174,8 +1203,8 @@ void resize_container(struct container *con, struct wlr_cursor *cursor, int offs struct wlr_box geom = container_get_current_geom(con); - geom.width = absolute_x_to_container_relative(geom, cursor->x - offsetx); - geom.height = absolute_y_to_container_relative(geom, cursor->y - offsety); + geom.width = absolute_x_to_container_local(geom, cursor->x - offsetx); + geom.height = absolute_y_to_container_local(geom, cursor->y - offsety); if (con->on_scratchpad) { remove_container_from_scratchpad(con); @@ -1185,7 +1214,6 @@ void resize_container(struct container *con, struct wlr_cursor *cursor, int offs arrange(); } - container_damage_borders(con); container_set_floating_geom(con, geom); struct tag *tag = container_get_current_tag(con); @@ -1283,12 +1311,12 @@ struct monitor *container_get_monitor(struct container *con) return m; } -inline int absolute_x_to_container_relative(struct wlr_box geom, int x) +inline int absolute_x_to_container_local(struct wlr_box geom, int x) { return x - geom.x; } -inline int absolute_y_to_container_relative(struct wlr_box geom, int y) +inline int absolute_y_to_container_local(struct wlr_box geom, int y) { return y - geom.y; } @@ -1415,8 +1443,6 @@ void move_container_to_tag(struct container *con, struct tag *tag) return; container_set_tag(con, tag); - con->client->moved_tag = true; - container_damage_whole(con); struct tag *old_tag = container_get_current_tag(con); @@ -1533,22 +1559,22 @@ void container_resize_with_cursor(struct cursor *cursor) switch (edge) { case WLR_EDGE_LEFT: printf("left\n"); - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_mgr, - "left_side", wlr_cursor); + wlr_cursor_set_xcursor(wlr_cursor, + cursor->xcursor_mgr, "left_side"); break; case WLR_EDGE_RIGHT: printf("right\n"); - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_mgr, - "right_side", wlr_cursor); + wlr_cursor_set_xcursor(wlr_cursor, + cursor->xcursor_mgr, "right_side"); break; case WLR_EDGE_TOP: printf("top\n"); - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_mgr, - "top_side", wlr_cursor); + wlr_cursor_set_xcursor(wlr_cursor, + cursor->xcursor_mgr, "top_side"); break; case WLR_EDGE_BOTTOM: - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_mgr, - "bottom_side", wlr_cursor); + wlr_cursor_set_xcursor(wlr_cursor, + cursor->xcursor_mgr, "bottom_side"); break; default: break; @@ -1696,3 +1722,10 @@ const char *container_get_app_id(struct container *con) } return name; } + +struct wlr_scene_node *container_get_scene_node(struct container *con) +{ + struct client *c = con->client; + struct scene_surface *surface = c->scene_surface; + return &surface->surface_tree->node; +} diff --git a/src/cursor.c b/src/cursor.c index d93f60c9..7438a2c4 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -9,7 +9,6 @@ #include "keybinding.h" #include "monitor.h" #include "popup.h" -#include "render/render.h" #include "seat.h" #include "server.h" #include "tile/tileUtils.h" @@ -99,7 +98,7 @@ static void handle_image_surface_destroy(struct wl_listener *listener, } static void cursor_hide(struct cursor *cursor) { - wlr_cursor_set_image(cursor->wlr_cursor, NULL, 0, 0, 0, 0, 0, 0); + wlr_cursor_set_buffer(cursor->wlr_cursor, NULL, 0, 0, 0); cursor->hidden = true; wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat); } @@ -216,10 +215,10 @@ void cursor_set_image(struct cursor *cursor, const char *image, struct wl_client } if (!image) { - wlr_cursor_set_image(cursor->wlr_cursor, NULL, 0, 0, 0, 0, 0, 0); + wlr_cursor_set_buffer(cursor->wlr_cursor, NULL, 0, 0, 0); } else if (!current_image || strcmp(current_image, image) != 0) { - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_mgr, image, - cursor->wlr_cursor); + wlr_cursor_set_xcursor(cursor->wlr_cursor, cursor->xcursor_mgr, + image); } } @@ -318,8 +317,8 @@ void focus_under_cursor(struct cursor *cursor, uint32_t time) struct container *focus_con = xy_to_container(cursorx, cursory); if (!is_popup_under_cursor && focus_con) { final_focus_surface = wlr_surface_surface_at(get_wlrsurface(focus_con->client), - absolute_x_to_container_relative(container_get_current_geom(focus_con), cursorx), - absolute_y_to_container_relative(container_get_current_geom(focus_con), cursory), + absolute_x_to_container_local(container_get_current_geom(focus_con), cursorx), + absolute_y_to_container_local(container_get_current_geom(focus_con), cursory), &sx, &sy); } @@ -425,8 +424,8 @@ void handle_cursor_button(struct wl_listener *listener, void *data) * mode. */ /* XXX should reset to the pointer focus's current setcursor */ if (cursor->cursor_mode != CURSOR_NORMAL) { - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_mgr, - "left_ptr", cursor->wlr_cursor); + wlr_cursor_set_xcursor(cursor->wlr_cursor, + cursor->xcursor_mgr, "left_ptr"); cursor->cursor_mode = CURSOR_NORMAL; /* Drop the window off on its new monitor */ struct monitor *m = xy_to_monitor(cursor->wlr_cursor->x, @@ -477,9 +476,9 @@ void move_resize(struct cursor *cursor, int ui) struct wlr_cursor *wlr_cursor = cursor->wlr_cursor; switch (cursor->cursor_mode = ui) { case CURSOR_MOVE: - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_mgr, "fleur", wlr_cursor); - offsetx = absolute_x_to_container_relative(grabc_geom, wlr_cursor->x); - offsety = absolute_y_to_container_relative(grabc_geom, wlr_cursor->y); + wlr_cursor_set_xcursor(wlr_cursor, cursor->xcursor_mgr, "fleur"); + offsetx = absolute_x_to_container_local(grabc_geom, wlr_cursor->x); + offsety = absolute_y_to_container_local(grabc_geom, wlr_cursor->y); break; case CURSOR_RESIZE: /* Doesn't work for X11 output - the next absolute motion event @@ -487,8 +486,8 @@ void move_resize(struct cursor *cursor, int ui) wlr_cursor_warp_closest(wlr_cursor, NULL, grabc_geom.x + grabc_geom.width, grabc_geom.y + grabc_geom.height); - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_mgr, - "bottom_right_corner", wlr_cursor); + wlr_cursor_set_xcursor(wlr_cursor, + cursor->xcursor_mgr, "bottom_right_corner"); break; default: break; @@ -714,8 +713,8 @@ static void update_cursor(struct cursor *cursor) return; if (!xy_to_container(cursor->wlr_cursor->x, cursor->wlr_cursor->y)) { - wlr_xcursor_manager_set_cursor_image(cursor->xcursor_mgr, - "left_ptr", cursor->wlr_cursor); + wlr_cursor_set_xcursor(cursor->wlr_cursor, + cursor->xcursor_mgr, "left_ptr"); return; } diff --git a/src/ipc-server.c b/src/ipc-server.c index 9e23a958..6b63c842 100644 --- a/src/ipc-server.c +++ b/src/ipc-server.c @@ -25,7 +25,6 @@ #include "client.h" #include "command.h" #include "monitor.h" -#include "root.h" static int ipc_socket = -1; static struct sockaddr_un *ipc_sockaddr = NULL; @@ -289,6 +288,17 @@ static void ipc_send_event(const char *json_string, enum ipc_command_type event) void ipc_event_tag() { ipc_send_event("", IPC_EVENT_TAG); + + // TODO: this doesn't belong here + // HACK: just for the time being + // update container visibility + for (int i = server.container_stack->len-1; i >= 0; i--) { + struct container *con = g_ptr_array_index(server.container_stack, i); + struct monitor *m = server_get_selected_monitor(); + bool viewable = container_viewable_on_monitor(m, con); + struct wlr_scene_node *node = container_get_scene_node(con); + wlr_scene_node_set_enabled(node, viewable); + } } int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { diff --git a/src/keyboard.c b/src/keyboard.c index 9e03ab9a..884cbed1 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4,6 +4,7 @@ #include "server.h" #include "keybinding.h" #include "utils/coreUtils.h" +#include static bool handle_VT_keys(struct keyboard *kb, uint32_t keycode) { @@ -18,8 +19,7 @@ static bool handle_VT_keys(struct keyboard *kb, uint32_t keycode) break; /* if required switch to different virtual terminal */ - struct wlr_session *session = - wlr_backend_get_session(server.backend); + struct wlr_session *session = server.wlr_session; if (!session) break; diff --git a/src/layer_shell.c b/src/layer_shell.c index 0cab3d2f..3c858c53 100644 --- a/src/layer_shell.c +++ b/src/layer_shell.c @@ -5,11 +5,9 @@ #include #include "monitor.h" -#include "popup.h" #include "server.h" #include "container.h" #include "tile/tileUtils.h" -#include "render/render.h" #include "input_manager.h" #include "root.h" #include "tagset.h" @@ -19,6 +17,10 @@ void create_notify_layer_shell(struct wl_listener *listener, void *data) { struct wlr_layer_surface_v1 *wlr_layer_surface = data; + printf("create layershell\n"); + printf("create layershell\n"); + printf("create layershell\n"); + printf("create layershell\n"); if (!wlr_layer_surface->output) { struct monitor *m = server_get_selected_monitor(); wlr_layer_surface->output = m->wlr_output; @@ -29,8 +31,8 @@ void create_notify_layer_shell(struct wl_listener *listener, void *data) struct client *client = create_client(LAYER_SHELL, surface); LISTEN(&wlr_layer_surface->surface->events.commit, &client->commit, commit_layer_surface_notify); - LISTEN(&wlr_layer_surface->events.map, &client->map, map_layer_surface_notify); - LISTEN(&wlr_layer_surface->events.unmap, &client->unmap, unmap_layer_surface_notify); + LISTEN(&wlr_layer_surface->surface->events.map, &client->map, map_layer_surface_notify); + LISTEN(&wlr_layer_surface->surface->events.unmap, &client->unmap, unmap_layer_surface_notify); LISTEN(&wlr_layer_surface->events.destroy, &client->destroy, destroy_layer_surface_notify); LISTEN(&wlr_layer_surface->events.new_popup, &client->new_popup, client_handle_new_popup); LISTEN(&wlr_layer_surface->surface->events.new_subsurface, &client->new_subsurface, handle_new_subsurface); @@ -57,7 +59,7 @@ void unmap_layer_surface(struct client *c) struct container *con = c->con; struct tag *tag = server_get_selected_tag(); struct container *sel_con = tag_get_focused_container(tag); - c->surface.layer->mapped = 0; + c->surface.layer->surface->mapped = 0; if (con == sel_con) { tag_this_focus_container(sel_con); } @@ -67,14 +69,13 @@ void unmap_layer_surface_notify(struct wl_listener *listener, void *data) { struct client *c = wl_container_of(listener, c, unmap); unmap_layer_surface(c); - container_damage_whole(c->con); } void destroy_layer_surface_notify(struct wl_listener *listener, void *data) { struct client *c = wl_container_of(listener, c, destroy); - if (c->surface.layer->mapped) + if (c->surface.layer->surface->mapped) unmap_layer_surface(c); remove_in_composed_list(server.layer_visual_stack_lists, cmp_ptr, c->con); @@ -109,17 +110,15 @@ void commit_layer_surface_notify(struct wl_listener *listener, void *data) struct wlr_layer_surface_v1 *layer_surface = c->surface.layer; bool layer_changed = false; if (layer_surface->current.committed != 0 || - c->mapped != layer_surface->mapped) { + c->mapped != layer_surface->surface->mapped) { layer_changed = c->layer != layer_surface->current.layer; if (layer_changed) { remove_in_composed_list(server.layer_visual_stack_lists, cmp_ptr, con); add_container_to_layer_stack(con); } - c->mapped = layer_surface->mapped; + c->mapped = layer_surface->surface->mapped; arrange_layers(c->m); } - - container_damage_part(con); } bool layer_shell_is_bar(struct container *con) @@ -192,7 +191,7 @@ void arrange_layers(struct monitor *m) struct container *con = g_ptr_array_index(layer_list, j); struct client *c = con->client; struct wlr_layer_surface_v1 *layer_surface = c->surface.layer; - if (layer_surface->current.keyboard_interactive && layer_surface->mapped) { + if (layer_surface->current.keyboard_interactive && layer_surface->surface->mapped) { // Deactivate the focused client. // TODO fix this NULL is not supported in focus_container tag_this_focus_container(con); diff --git a/src/main.c b/src/main.c index f6eda9c6..8b15db5c 100644 --- a/src/main.c +++ b/src/main.c @@ -13,20 +13,12 @@ #include #include #include -#include #include #include #include #include -#include "keyboard.h" -#include "layer_shell.h" -#include "render/render.h" -#include "scratchpad.h" #include "server.h" -#include "translationLayer.h" -#include "utils/parseConfigUtils.h" -#include "xdg_shell.h" #include "stringop.h" void print_help() diff --git a/src/meson.build b/src/meson.build index bf120c38..8c5f03ad 100644 --- a/src/meson.build +++ b/src/meson.build @@ -75,7 +75,7 @@ srcs = files( 'list_sets/container_stack_set.c', 'list_sets/focus_stack_set.c', 'list_sets/list_set.c', - 'render/render.c', + 'render.c', 'rules/mon_rule.c', 'rules/rule.c', 'tile/tileUtils.c', diff --git a/src/monitor.c b/src/monitor.c index 8bed65c6..90d25715 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -2,15 +2,12 @@ #include #include #include -#include #include #include #include #include #include -#include "ipc-server.h" -#include "render/render.h" #include "server.h" #include "tile/tileUtils.h" #include "tag.h" @@ -23,7 +20,6 @@ #include "client.h" #include "container.h" -static void handle_output_damage_frame(struct wl_listener *listener, void *data); static void handle_output_frame(struct wl_listener *listener, void *data); static void handle_output_mode(struct wl_listener *listener, void *data); static void monitor_get_initial_tag(struct monitor *m, GList *tags); @@ -53,9 +49,6 @@ void create_monitor(struct wl_listener *listener, void *data) /* damage tracking must be initialized before setting the tag because * it to damage a region */ - m->damage = wlr_output_damage_create(m->wlr_output); - m->damage_frame.notify = handle_output_damage_frame; - wl_signal_add(&m->damage->events.frame, &m->damage_frame); m->frame.notify = handle_output_frame; wl_signal_add(&m->wlr_output->events.frame, &m->frame); @@ -63,8 +56,6 @@ void create_monitor(struct wl_listener *listener, void *data) /* Set up event listeners */ m->destroy.notify = handle_destroy_monitor; wl_signal_add(&output->events.destroy, &m->destroy); - m->mode.notify = handle_output_mode; - wl_signal_add(&output->events.mode, &m->mode); bool is_first_monitor = server.mons->len == 0; g_ptr_array_add(server.mons, m); @@ -82,6 +73,8 @@ void create_monitor(struct wl_listener *listener, void *data) wlr_output_enable(output, true); + m->scene_output = wlr_scene_output_create(server.scene, output); + wlr_output_layout_get_box(server.output_layout, m->wlr_output, &m->geom); m->root = create_root(m, m->geom); @@ -144,47 +137,18 @@ void create_output(struct wlr_backend *backend, void *data) /* #endif */ } -int i = 0; static void handle_output_frame(struct wl_listener *listener, void *data) { - struct monitor *m = wl_container_of(listener, m, damage_frame); - - /* NOOP */ -} - -int j = 0; -static void handle_output_damage_frame(struct wl_listener *listener, void *data) -{ - struct monitor *m = wl_container_of(listener, m, damage_frame); - - if (!m->wlr_output->enabled) { - return; - } + struct monitor *m = wl_container_of(listener, m, frame); - /* Check if we can scan-out the primary view. */ - pixman_region32_t frame_damage; - pixman_region32_init(&frame_damage); - bool needs_frame; - if (!wlr_output_damage_attach_render(m->damage, &needs_frame, &frame_damage)) { - goto damage_finish; - } - - if (!needs_frame) { - wlr_output_rollback(m->wlr_output); - goto damage_finish; - } + if (!wlr_scene_output_commit(m->scene_output, NULL)) { + return; + } - render_monitor(m, &frame_damage); - -damage_finish: - pixman_region32_fini(&frame_damage); -} - -static void handle_output_mode(struct wl_listener *listener, void *data) -{ - struct monitor *m = wl_container_of(listener, m, mode); - wlr_output_layout_get_box(server.output_layout, m->wlr_output, &m->geom); - arrange_layers(m); + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + wlr_scene_output_send_frame_done(m->scene_output, &now); + /* NOOP */ } static void monitor_get_initial_tag(struct monitor *m, GList *tags) @@ -205,7 +169,6 @@ void handle_destroy_monitor(struct wl_listener *listener, void *data) { struct monitor *m = wl_container_of(listener, m, destroy); - wl_list_remove(&m->mode.link); wl_list_remove(&m->frame.link); wl_list_remove(&m->destroy.link); @@ -513,7 +476,7 @@ static void prepare_output( config_head->state.custom_mode.height, config_head->state.custom_mode.refresh); - wlr_output_layout_move(server.output_layout, wlr_output, + wlr_output_layout_add(server.output_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); diff --git a/src/popup.c b/src/popup.c index 7df675c0..d34baaf2 100644 --- a/src/popup.c +++ b/src/popup.c @@ -9,44 +9,30 @@ #include "client.h" #include "container.h" #include "monitor.h" -#include "render/render.h" -#include "root.h" #include "server.h" #include "utils/coreUtils.h" #include "xdg-shell-protocol.h" static void popup_handle_new_popup(struct wl_listener *listener, void *data); -static void popup_handle_new_subpopup(struct wl_listener *listener, void *data); static void destroy_popup(struct xdg_popup *xdg_popup); static void popup_handle_commit(struct wl_listener *listener, void *data); -static void popup_handle_map(struct wl_listener *listener, void *data); -static void popup_handle_unmap(struct wl_listener *listener, void *data); -static void popup_damage(struct xdg_popup *xdg_popup, bool whole); +static void popup_handle_map(struct xdg_popup *popup); struct xdg_popup *create_popup(struct monitor *m, struct wlr_xdg_popup *xdg_popup, - struct wlr_box parent_geom, struct container* toplevel) + void *parent, struct container* toplevel) { - struct xdg_popup *popup = xdg_popup->base->data = calloc(1, sizeof(*popup)); popup->xdg = xdg_popup; popup->toplevel = toplevel; + popup->parent = parent; - struct wlr_box box = xdg_popup->current.geometry; - box.x = 0; - box.y = 0; - box.width = m->geom.width; - box.height = m->geom.height; + // TODO: what does this exactly do? + // struct wlr_box output_geom = monitor_get_active_geom(m); + // wlr_xdg_popup_unconstrain_from_box(xdg_popup, &output_geom); - wlr_xdg_popup_unconstrain_from_box(popup->xdg, &box); // the root window may be resized. This must be adjusted - popup->geom.x = xdg_popup->current.geometry.x + parent_geom.x; - popup->geom.y = xdg_popup->current.geometry.y + parent_geom.y; - popup->geom.width = xdg_popup->current.geometry.width; - popup->geom.height = xdg_popup->current.geometry.height; popup->m = m; - LISTEN(&popup->xdg->base->events.map, &popup->map, popup_handle_map); - LISTEN(&popup->xdg->base->events.unmap, &popup->unmap, popup_handle_unmap); LISTEN(&popup->xdg->base->events.new_popup, &popup->new_popup, popup_handle_new_popup); LISTEN(&popup->xdg->base->events.destroy, &popup->destroy, popup_handle_destroy); @@ -68,35 +54,53 @@ static void destroy_popup(struct xdg_popup *xdg_popup) static void popup_handle_commit(struct wl_listener *listener, void *data) { struct xdg_popup *popup = wl_container_of(listener, popup, commit); - popup_damage(popup, false); } -static void popup_handle_map(struct wl_listener *listener, void *data) +static void popup_handle_map(struct xdg_popup *popup) { - struct xdg_popup *popup = wl_container_of(listener, popup, map); - popup_damage(popup, true); + struct wlr_xdg_popup *xdg_popup = popup->xdg; - popup->commit.notify = popup_handle_commit; - wl_signal_add(&popup->xdg->base->surface->events.commit, &popup->commit); -} + double sx, sy; + wlr_xdg_popup_get_position(xdg_popup, &sx, &sy); -static void popup_handle_unmap(struct wl_listener *listener, void *data) -{ - struct xdg_popup *popup = wl_container_of(listener, popup, unmap); - wl_list_remove(&popup->commit.link); - popup_damage(popup, true); -} + popup->scene_surface = xdg_popup->base->surface->data; + struct wlr_scene_surface *scene_surface = popup->scene_surface; -static void popup_damage(struct xdg_popup *xdg_popup, bool whole) -{ - if (!xdg_popup) - return; + int offset_x = 0; + int offset_y = 0; - struct wlr_xdg_popup *popup = xdg_popup->xdg; - struct wlr_surface *surface = popup->base->surface; - struct monitor *m = xdg_popup->m; + for (struct xdg_popup *curr_popup = popup; + curr_popup->parent != curr_popup->toplevel; + curr_popup = curr_popup->parent) { + struct xdg_popup *parent_popup = curr_popup->parent; + double sx, sy; + wlr_xdg_popup_get_position(parent_popup->xdg, &sx, &sy); + offset_x += sx; + offset_y += sy; + } + struct container *toplevel = popup->toplevel; + struct wlr_box toplevel_geom = container_get_current_content_geom(toplevel); - output_damage_surface(m, surface, &xdg_popup->geom, whole); + offset_x += toplevel_geom.x; + offset_y += toplevel_geom.y; + + + // the root window may be resized. This must be adjusted + popup_set_x(popup, offset_x + sx); + popup_set_y(popup, offset_y + sy); + popup_set_width(popup, xdg_popup->current.geometry.width); + popup_set_height(popup, xdg_popup->current.geometry.height); + pupup_update_position(popup); + + wlr_scene_node_set_position(&scene_surface->buffer->node, sx, sy); + + // TODO: either use this or use actual xdg constraints + struct monitor *m = server_get_selected_monitor(); + struct wlr_box output_geom = monitor_get_active_geom(m); + apply_bounds(&popup->geom, output_geom); + + popup->commit.notify = popup_handle_commit; + wl_signal_add(&popup->xdg->base->surface->events.commit, &popup->commit); } static void popup_handle_new_popup(struct wl_listener *listener, void *data) @@ -105,13 +109,21 @@ static void popup_handle_new_popup(struct wl_listener *listener, void *data) wl_container_of(listener, parent_popup, new_popup); struct wlr_xdg_popup *xdg_popup = data; + popup_handle_map(parent_popup); + + struct wlr_scene_surface *scene_surface = xdg_popup->base->surface->data; + struct wlr_scene_node *node = &scene_surface->buffer->node; + wlr_scene_node_set_position(node, 0, 0); create_popup(parent_popup->m, xdg_popup, - parent_popup->geom, parent_popup->toplevel); + parent_popup, parent_popup->toplevel); } void popup_handle_destroy(struct wl_listener *listener, void *data) { struct xdg_popup *popup = wl_container_of(listener, popup, destroy); + + wl_list_remove(&popup->commit.link); + list_remove(server.popups, cmp_ptr, popup); destroy_popup(popup); @@ -141,15 +153,15 @@ struct wlr_surface *get_popup_surface_under_cursor(struct cursor *cursor, double con->client->surface.xdg, /* absolute mouse position to relative in regards to * the client */ - absolute_x_to_container_relative(con_geom, cursorx), - absolute_y_to_container_relative(con_geom, cursory), + absolute_x_to_container_local(con_geom, cursorx), + absolute_y_to_container_local(con_geom, cursory), sx, sy); break; case LAYER_SHELL: surface = wlr_layer_surface_v1_surface_at( con->client->surface.layer, - absolute_x_to_container_relative(con_geom, cursorx), - absolute_y_to_container_relative(con_geom, cursory), + absolute_x_to_container_local(con_geom, cursorx), + absolute_y_to_container_local(con_geom, cursory), sx, sy); break; default: @@ -182,3 +194,31 @@ inline bool popups_exist() { return server.popups->len > 0; } + +void popup_set_x(struct xdg_popup *popup, int x) +{ + popup->geom.x = x; +} + +void popup_set_y(struct xdg_popup *popup, int y) +{ + popup->geom.y = y; +} + +void popup_set_width(struct xdg_popup *popup, int width) +{ + popup->geom.width = width; +} + +void popup_set_height(struct xdg_popup *popup, int height) +{ + popup->geom.height = height; +} + +void pupup_update_position(struct xdg_popup *popup) +{ + struct wlr_scene_surface *scene_surface = popup->scene_surface; + struct wlr_box geom = popup->geom; + printf("set x: %i y: %i\n", geom.x, geom.y); + wlr_scene_node_set_position(&scene_surface->buffer->node, 0, 0); +} diff --git a/src/render.c b/src/render.c new file mode 100644 index 00000000..4661aecb --- /dev/null +++ b/src/render.c @@ -0,0 +1,76 @@ +#include "render.h" + +#include +#include + +#include "container.h" +#include "client.h" +#include "tag.h" +#include "monitor.h" +#include "layout.h" +#include "list_sets/container_stack_set.h" +#include "root.h" +#include "tagset.h" + +static void surface_handle_destroy(struct wl_listener *listener, void *data) +{ + struct scene_surface *surface = wl_container_of(listener, surface, destroy); + for (int i = 0; i < BORDER_COUNT; i++) { + struct wlr_scene_rect *border = surface->borders[i]; + wlr_scene_node_destroy(&border->node); + } + wlr_scene_node_destroy(&surface->scene_surface->buffer->node); + wl_list_remove(&surface->destroy.link); + free(surface); +} + +static void surface_handle_commit(struct wl_listener *listener, void *data) +{ + struct scene_surface *surface = wl_container_of(listener, surface, commit); + + struct client *c = wlr_surface_get_client(surface->wlr); + struct container *con = c->con; + container_update_border_color(con); +} + +static void surface_handle_new_subsurface(struct wl_listener *listener, void *data) +{ +} + +void server_handle_new_surface(struct wl_listener *listener, void *data) +{ + struct server *server = wl_container_of(listener, server, new_surface); + struct wlr_surface *wlr_surface = data; + + struct scene_surface *surface = calloc(1, sizeof(struct scene_surface)); + surface->wlr = wlr_surface; + printf("wlr_surface: %p\n", wlr_surface); + surface->commit.notify = surface_handle_commit; + wl_signal_add(&wlr_surface->events.commit, &surface->commit); + surface->destroy.notify = surface_handle_destroy; + wl_signal_add(&wlr_surface->events.destroy, &surface->destroy); + + surface->new_subsurface.notify = surface_handle_new_subsurface;; + wl_signal_add(&wlr_surface->events.new_subsurface, &surface->new_subsurface); + + surface->surface_tree = wlr_scene_tree_create(server->scene_tiled); + + surface->scene_surface = + wlr_scene_surface_create(surface->surface_tree, wlr_surface); + // TODO: this doesn't work for popups + // wlr_scene_node_set_position(&surface->scene_surface->buffer->node, 100, 100); + // wlr_scene_node_set_position(&surface->scene_surface->buffer->node, 200, 200); + + for (int i = 0; i < BORDER_COUNT; i++) { + surface->borders[i] = + wlr_scene_rect_create(surface->surface_tree, + 0, 0, (float[4]){ 1.0f, 0.0f, 0.0f, 1 }); + } + + wlr_surface->data = surface; +} + +struct client *wlr_surface_get_client(struct wlr_surface *wlr_surface) +{ + return wlr_surface->data; +} diff --git a/src/render/render.c b/src/render/render.c deleted file mode 100644 index b8568d84..00000000 --- a/src/render/render.c +++ /dev/null @@ -1,431 +0,0 @@ -#include "render/render.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "container.h" -#include "client.h" -#include "list_sets/container_stack_set.h" -#include "monitor.h" -#include "popup.h" -#include "root.h" -#include "server.h" -#include "tile/tileUtils.h" -#include "utils/gapUtils.h" -#include "tag.h" -#include "tagset.h" - -static void render_stack(struct monitor *m, pixman_region32_t *output_damage); -static void scissor_output(struct wlr_output *output, pixman_box32_t *rect); -static void render_texture(struct wlr_output *wlr_output, - pixman_region32_t *output_damage, struct wlr_texture *texture, - const struct wlr_box *box, float alpha); - -/* _box.x and .y are expected to be layout-local - _box.width and .height are expected to be output-buffer-local */ -void render_rect(struct monitor *m, pixman_region32_t *output_damage, - const struct wlr_box *_box, const struct color color) { - struct wlr_output *wlr_output = m->wlr_output; - struct wlr_renderer *renderer = server.renderer; - - struct wlr_box box; - memcpy(&box, _box, sizeof(struct wlr_box)); - - pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_union_rect(&damage, &damage, box.x, box.y, - box.width, box.height); - pixman_region32_intersect(&damage, &damage, output_damage); - bool damaged = pixman_region32_not_empty(&damage); - if (!damaged) { - pixman_region32_fini(&damage); - return; - } - - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); - for (int i = 0; i < nrects; ++i) { - scissor_output(wlr_output, &rects[i]); - float wlr_color[4]; - color_to_wlr_color(wlr_color, color); - wlr_render_rect(renderer, &box, wlr_color, - wlr_output->transform_matrix); - } -} - -static bool intersects_with_output(struct monitor *m, - struct wlr_output_layout *output_layout, struct wlr_box *surface_box) -{ - /* Since the surface_box's x- and y-coordinates are already output local, - * the x- and y-coordinates of this box need to be 0 for this function to - * work correctly. */ - struct wlr_box output_box = {0}; - wlr_output_effective_resolution(m->wlr_output, &output_box.width, &output_box.height); - - struct wlr_box intersection; - return wlr_box_intersection(&intersection, &output_box, surface_box); -} - -static void output_for_each_surface_iterator(struct wlr_surface *surface, int sx, int sy, void *user_data) -{ - struct surface_iterator_data *data = user_data; - - if (!wlr_surface_has_buffer(surface)) - return; - - struct wlr_box surface_box = data->render_box; - data->user_iterator(data->m, surface, &surface_box, data->user_data); -} - -static void render_texture(struct wlr_output *wlr_output, - pixman_region32_t *output_damage, struct wlr_texture *texture, - const struct wlr_box *box, float alpha) -{ - struct wlr_renderer *renderer = server.renderer; - - pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_union_rect(&damage, &damage, box->x, box->y, box->width, box->height); - pixman_region32_intersect(&damage, &damage, output_damage); - if (!pixman_region32_not_empty(&damage)) { - goto finish_damage; - } - - 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(renderer, texture, wlr_output->transform_matrix, - box->x, box->y, alpha); - } - -finish_damage: - pixman_region32_fini(&damage); -} - -static void render_surface_iterator(struct monitor *m, struct wlr_surface *surface, - struct wlr_box *box, void *data) -{ - struct render_texture_data *render_data = data; - float alpha = render_data->alpha; - pixman_region32_t *output_damage = render_data->output_damage; - - struct wlr_texture *texture = wlr_surface_get_texture(surface); - struct wlr_output *wlr_output = m->wlr_output; - - if (!texture) - return; - - scale_box(box, wlr_output->scale); - - /* The client has a position in layout coordinates. If you have two displays, - * one next to the other, both 1080p, a client on the rightmost display might - * have layout coordinates of 2000,100. We need to translate that to - * output-local coordinates, or (2000 - 1920). */ - double ox = box->x; - double oy = box->y; - wlr_output_layout_output_coords(server.output_layout, wlr_output, &ox, &oy); - - struct wlr_box obox = { - /* We also have to apply the scale factor for HiDPI outputs. This is only - * part of the puzzle, dwl does not fully support HiDPI. */ - .x = ox, - .y = oy, - .width = box->width, - .height = box->height - }; - - render_texture(wlr_output, output_damage, texture, &obox, alpha); - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - wlr_surface_send_frame_done(surface, &now); -} - -static void -damage_surface_iterator(struct monitor *m, struct wlr_surface *surface, - struct wlr_box *box, void *user_data) -{ - struct wlr_output *wlr_output = m->wlr_output; - bool whole = *(bool *) user_data; - struct wlr_box geom = *box; - - scale_box(&geom, wlr_output->scale); - - if (whole) { - wlr_output_damage_add_box(m->damage, &geom); - } else 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, wlr_output->scale); - if (ceil(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(wlr_output->scale) - surface->current.scale); - } - pixman_region32_translate(&damage, geom.x, geom.y); - wlr_output_damage_add(m->damage, &damage); - pixman_region32_fini(&damage); - } -} - -void output_damage_surface(struct monitor *m, struct wlr_surface *surface, struct wlr_box *geom, bool whole) -{ - assert(m != NULL); - if (!m->wlr_output->enabled) - return; - - double ox = geom->x, oy = geom->y; - wlr_output_layout_output_coords(server.output_layout, m->wlr_output, &ox, &oy); - - struct surface_iterator_data data = { - .user_iterator = damage_surface_iterator, - .user_data = &whole, - .m = m, - .render_box = { - .x = ox, - .y = oy, - .width = geom->width, - .height = geom->height, - }, - }; - - wlr_surface_for_each_surface(surface, output_for_each_surface_iterator, &data); -} - -static void scissor_output(struct wlr_output *output, pixman_box32_t *rect) -{ - struct wlr_renderer *renderer = server.renderer; - - struct wlr_box box = { - .x = rect->x1, - .y = rect->y1, - .width = rect->x2 - rect->x1, - .height = rect->y2 - rect->y1, - }; - - int output_width, output_height; - wlr_output_transformed_resolution(output, &output_width, &output_height); - enum wl_output_transform transform = wlr_output_transform_invert(output->transform); - wlr_box_transform(&box, &box, transform, output_width, output_height); - - wlr_renderer_scissor(renderer, &box); -} - -// TODO refactor the name it doesn't represent what this does perfectly -// returns the newly accquired hidden edges -static enum wlr_edges container_update_hidden_edges(struct container *con, struct wlr_box *borders, enum wlr_edges hidden_edges) -{ - struct monitor *m = container_get_monitor(con); - - enum wlr_edges containers_hidden_edges = WLR_EDGE_NONE; - struct wlr_box con_geom = container_get_current_geom(con); - // int border_width = container_get_border_width(con); - // hide edges if needed - if (hidden_edges & WLR_EDGE_LEFT) { - if (con_geom.x == m->root->geom.x) { - containers_hidden_edges |= WLR_EDGE_LEFT; - } - } - if (hidden_edges & WLR_EDGE_RIGHT) { - if (is_approx_equal(con_geom.x + con_geom.width, m->root->geom.x + m->root->geom.width, 3)) { - containers_hidden_edges |= WLR_EDGE_RIGHT; - } - } - if (hidden_edges & WLR_EDGE_TOP) { - if (con_geom.y == m->root->geom.y) { - containers_hidden_edges |= WLR_EDGE_TOP; - } - } - if (hidden_edges & WLR_EDGE_BOTTOM) { - if (is_approx_equal(con_geom.y + con_geom.height, m->root->geom.y + m->root->geom.height, 3)) { - containers_hidden_edges |= WLR_EDGE_BOTTOM; - } - } - - container_set_hidden_edges(con, containers_hidden_edges); - return containers_hidden_edges; -} - -static void render_borders(struct container *con, struct monitor *m, pixman_region32_t *output_damage) -{ - // TODO: reimplement me - if (!con->has_border) - return; - - struct wlr_box *borders = (struct wlr_box[4]) { - container_get_current_border_geom(con, WLR_EDGE_TOP), - container_get_current_border_geom(con, WLR_EDGE_BOTTOM), - container_get_current_border_geom(con, WLR_EDGE_LEFT), - container_get_current_border_geom(con, WLR_EDGE_RIGHT), - }; - - enum wlr_edges hidden_edges = WLR_EDGE_NONE; - struct tag *tag = monitor_get_active_tag(m); - struct layout *lt = tag_get_layout(tag); - if (lt->options->smart_hidden_edges) { - if (tag->visible_con_set->tiled_containers->len <= 1) { - hidden_edges = container_update_hidden_edges(con, borders, lt->options->hidden_edges); - } - } else { - hidden_edges = container_update_hidden_edges(con, borders, lt->options->hidden_edges); - } - - /* Draw window borders */ - struct container *sel = monitor_get_focused_container(m); - const struct color color = (con == sel) ? lt->options->focus_color : lt->options->border_color; - for (int i = 0; i < 4; i++) { - if ((hidden_edges & (1 << i)) == 0) { - struct wlr_box border = borders[i]; - double ox = border.x; - double oy = border.y; - wlr_output_layout_output_coords(server.output_layout, m->wlr_output, &ox, &oy); - struct wlr_box obox = { - .x = ox, - .y = oy, - .width = border.width, - .height = border.height, - }; - scale_box(&obox, m->wlr_output->scale); - render_rect(m, output_damage, &obox, color); - } - } -} - -void output_surface_for_each_surface(struct monitor *m, - struct wlr_surface *surface, struct wlr_box obox, - surface_iterator_func_t iterator, void *user_data) { - - struct surface_iterator_data data = { - .user_iterator = iterator, - .user_data = user_data, - .m = m, - .render_box = obox, - }; - - wlr_surface_for_each_surface(surface, - output_for_each_surface_iterator, &data); -} - -static void send_frame_done_func(struct wlr_surface *surface, - int sx, int sy, void *data) -{ - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - wlr_surface_send_frame_done(surface, &now); -} - -static void render_stack(struct monitor *m, pixman_region32_t *output_damage) -{ - /* Each subsequent window we render is rendered on top of the last. Because - * our stacking list is ordered front-to-back, we iterate over it backwards. */ - struct tag *tag = monitor_get_active_tag(m); - GPtrArray *stack_list = tag_get_complete_stack_copy(tag); - for (int i = stack_list->len-1; i >= 0; i--) { - struct container *con = g_ptr_array_index(stack_list, i); - if (!container_viewable_on_monitor(m, con)) - continue; - - render_borders(con, m, output_damage); - - /* This calls our render function for each surface among the - * xdg_surface's toplevel and popups. */ - - struct wlr_surface *surface = get_wlrsurface(con->client); - struct wlr_box obox = container_get_current_content_geom(con); - - struct render_texture_data render_data; - render_data.alpha = con->alpha; - render_data.output_damage = output_damage; - output_surface_for_each_surface(m, surface, obox, - render_surface_iterator, &render_data); - } - g_ptr_array_unref(stack_list); -} - -static void render_popups(struct monitor *m, pixman_region32_t *output_damage) -{ - for (int i = 0; i < server.popups->len; i++) { - struct xdg_popup *popup = g_ptr_array_index(server.popups, i); - struct wlr_surface *surface = popup->xdg->base->surface; - - // popups are weird and require to use the dimensions of the surface - // instead - popup->geom.width = surface->current.width; - popup->geom.height = surface->current.height; - struct wlr_box obox = popup->geom; - - struct render_texture_data render_data; - render_data.alpha = 1.0f; - render_data.output_damage = output_damage; - output_surface_for_each_surface(m, surface, obox, - render_surface_iterator, &render_data); - - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - wlr_surface_send_frame_done(surface, &now); - } -} - -static void clear_frame( - struct monitor *m, - struct color color, - pixman_region32_t *damage) -{ - struct wlr_renderer *renderer = server.renderer; - - /* // debug stuff */ - /* float color2[4] = {0.4f, 0.1f, 0.0f, 1.0f}; */ - /* wlr_renderer_clear(renderer, color2); */ - - float wlr_color[4]; - color_to_wlr_color(wlr_color, color); - int nrects; - pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); - for (int i = 0; i < nrects; i++) { - scissor_output(m->wlr_output, &rects[i]); - wlr_renderer_clear(renderer, wlr_color); - } -} - -void render_monitor(struct monitor *m, pixman_region32_t *damage) -{ - /* Begin the renderer (calls glViewport and some other GL sanity checks) */ - wlr_renderer_begin(server.renderer, m->wlr_output->width, m->wlr_output->height); - - clear_frame(m, m->root->color, damage); - render_stack(m, damage); - render_popups(m, damage); - - /* Hardware cursors are rendered by the GPU on a separate plane, and can be - * moved around without re-rendering what's beneath them - which is more - * efficient. However, not all hardware supports hardware cursors. For this - * reason, wlroots provides a software fallback, which we ask it to render - * here. wlr_cursor handles configuring hardware vs software cursors for you, - * and this function is a no-op when hardware cursors are in use. */ - struct wlr_renderer *renderer = server.renderer; - wlr_renderer_scissor(renderer, NULL); - wlr_output_render_software_cursors(m->wlr_output, damage); - - /* Conclude rendering and swap the buffers, showing the final frame - * on-screen. */ - wlr_renderer_end(renderer); - - wlr_output_commit(m->wlr_output); -} - -void scale_box(struct wlr_box *box, float scale) -{ - box->x *= scale; - box->y *= scale; - box->width *= scale; - box->height *= scale; -} diff --git a/src/root.c b/src/root.c index eca609b2..08f6b06f 100644 --- a/src/root.c +++ b/src/root.c @@ -89,9 +89,9 @@ void root_damage_whole(struct root *root) { if (!root) return; - struct monitor *m = root->m; - struct wlr_box geom = get_monitor_local_box(root->geom, m); - wlr_output_damage_add_box(m->damage, &geom); + // struct monitor *m = root->m; + // struct wlr_box geom = get_monitor_local_box(root->geom, m); + // wlr_output_damage_add_box(m->damage, &geom); } static enum wlr_edges bar_get_direction(struct container *con) diff --git a/src/scratchpad.c b/src/scratchpad.c index 246ae269..7888acf4 100644 --- a/src/scratchpad.c +++ b/src/scratchpad.c @@ -34,7 +34,6 @@ void move_to_scratchpad(struct container *con, int position) struct tag *tag = monitor_get_active_tag(m); tagset_reload(tag); - container_damage_whole(con); arrange(); tag_focus_most_recent_container(tag); } diff --git a/src/server.c b/src/server.c index 4bfcee0e..b351f02d 100644 --- a/src/server.c +++ b/src/server.c @@ -2,9 +2,9 @@ #include "list_sets/container_stack_set.h" #include "list_sets/focus_stack_set.h" -#include "tag.h" #include "monitor.h" #include "stringop.h" +#include "tag.h" #include #include @@ -12,11 +12,12 @@ #include #include #include +#include +#include #include #include #include #include -#include #include #include #include @@ -24,27 +25,22 @@ #include #include #include -#include #include -#include -#include +#include "ipc-server.h" +#include "keybinding.h" #include "layer_shell.h" #include "monitor.h" +#include "ring_buffer.h" +#include "translationLayer.h" #include "utils/coreUtils.h" #include "utils/parseConfigUtils.h" #include "xdg_shell.h" -#include "translationLayer.h" -#include "ipc-server.h" -#include "render/render.h" -#include "keybinding.h" -#include "ring_buffer.h" - -#define XDG_SHELL_VERSION 2 +#include "container.h" struct server server; -static void init_event_handlers(struct server *server); +static void setup_event_handlers(struct server *server); static void init_lists(struct server *server); static void init_timers(struct server *server); static void init_lua_api(struct server *server); @@ -56,8 +52,7 @@ static void finalize_lua_api(struct server *server); static struct tag *handle_too_few_tags(uint32_t tag_id); -static struct tag *handle_too_few_tags(uint32_t tag_id) -{ +static struct tag *handle_too_few_tags(uint32_t tag_id) { // no number has more than 11 digits when int is 32 bit long char name[12]; // TODO explain why +1 @@ -68,32 +63,46 @@ static struct tag *handle_too_few_tags(uint32_t tag_id) *tag_id_ptr = tag_id; g_hash_table_insert(server.tags, tag_id_ptr, new_tag); struct tag *tag = get_tag(0); - wlr_list_cat(new_tag->con_set->tiled_containers, tag->con_set->tiled_containers); - - wlr_list_cat(new_tag->focus_set->focus_stack_layer_background, tag->focus_set->focus_stack_layer_background); - wlr_list_cat(new_tag->focus_set->focus_stack_layer_bottom, tag->focus_set->focus_stack_layer_bottom); - wlr_list_cat(new_tag->focus_set->focus_stack_layer_top, tag->focus_set->focus_stack_layer_top); - wlr_list_cat(new_tag->focus_set->focus_stack_layer_overlay, tag->focus_set->focus_stack_layer_overlay); - wlr_list_cat(new_tag->focus_set->focus_stack_on_top, tag->focus_set->focus_stack_on_top); - wlr_list_cat(new_tag->focus_set->focus_stack_normal, tag->focus_set->focus_stack_normal); - wlr_list_cat(new_tag->focus_set->focus_stack_not_focusable, tag->focus_set->focus_stack_not_focusable); - - wlr_list_cat(new_tag->visible_con_set->tiled_containers, tag->visible_con_set->tiled_containers); - - wlr_list_cat(new_tag->visible_focus_set->focus_stack_layer_background, tag->visible_focus_set->focus_stack_layer_background); - wlr_list_cat(new_tag->visible_focus_set->focus_stack_layer_bottom, tag->visible_focus_set->focus_stack_layer_bottom); - wlr_list_cat(new_tag->visible_focus_set->focus_stack_layer_top, tag->visible_focus_set->focus_stack_layer_top); - wlr_list_cat(new_tag->visible_focus_set->focus_stack_layer_overlay, tag->visible_focus_set->focus_stack_layer_overlay); - wlr_list_cat(new_tag->visible_focus_set->focus_stack_on_top, tag->visible_focus_set->focus_stack_on_top); - wlr_list_cat(new_tag->visible_focus_set->focus_stack_normal, tag->visible_focus_set->focus_stack_normal); - wlr_list_cat(new_tag->visible_focus_set->focus_stack_not_focusable, tag->visible_focus_set->focus_stack_not_focusable); + wlr_list_cat(new_tag->con_set->tiled_containers, + tag->con_set->tiled_containers); + + wlr_list_cat(new_tag->focus_set->focus_stack_layer_background, + tag->focus_set->focus_stack_layer_background); + wlr_list_cat(new_tag->focus_set->focus_stack_layer_bottom, + tag->focus_set->focus_stack_layer_bottom); + wlr_list_cat(new_tag->focus_set->focus_stack_layer_top, + tag->focus_set->focus_stack_layer_top); + wlr_list_cat(new_tag->focus_set->focus_stack_layer_overlay, + tag->focus_set->focus_stack_layer_overlay); + wlr_list_cat(new_tag->focus_set->focus_stack_on_top, + tag->focus_set->focus_stack_on_top); + wlr_list_cat(new_tag->focus_set->focus_stack_normal, + tag->focus_set->focus_stack_normal); + wlr_list_cat(new_tag->focus_set->focus_stack_not_focusable, + tag->focus_set->focus_stack_not_focusable); + + wlr_list_cat(new_tag->visible_con_set->tiled_containers, + tag->visible_con_set->tiled_containers); + + wlr_list_cat(new_tag->visible_focus_set->focus_stack_layer_background, + tag->visible_focus_set->focus_stack_layer_background); + wlr_list_cat(new_tag->visible_focus_set->focus_stack_layer_bottom, + tag->visible_focus_set->focus_stack_layer_bottom); + wlr_list_cat(new_tag->visible_focus_set->focus_stack_layer_top, + tag->visible_focus_set->focus_stack_layer_top); + wlr_list_cat(new_tag->visible_focus_set->focus_stack_layer_overlay, + tag->visible_focus_set->focus_stack_layer_overlay); + wlr_list_cat(new_tag->visible_focus_set->focus_stack_on_top, + tag->visible_focus_set->focus_stack_on_top); + wlr_list_cat(new_tag->visible_focus_set->focus_stack_normal, + tag->visible_focus_set->focus_stack_normal); + wlr_list_cat(new_tag->visible_focus_set->focus_stack_not_focusable, + tag->visible_focus_set->focus_stack_not_focusable); return new_tag; } - -static void init_lists(struct server *server) -{ +static void init_lists(struct server *server) { server->layer_visual_stack_lists = g_ptr_array_new(); server->layer_visual_stack_background = g_ptr_array_new(); @@ -101,14 +110,17 @@ static void init_lists(struct server *server) server->layer_visual_stack_top = g_ptr_array_new(); server->layer_visual_stack_overlay = g_ptr_array_new(); - g_ptr_array_add(server->layer_visual_stack_lists, server->layer_visual_stack_overlay); - g_ptr_array_add(server->layer_visual_stack_lists, server->layer_visual_stack_top); - g_ptr_array_add(server->layer_visual_stack_lists, server->layer_visual_stack_bottom); - g_ptr_array_add(server->layer_visual_stack_lists, server->layer_visual_stack_background); + g_ptr_array_add(server->layer_visual_stack_lists, + server->layer_visual_stack_overlay); + g_ptr_array_add(server->layer_visual_stack_lists, + server->layer_visual_stack_top); + g_ptr_array_add(server->layer_visual_stack_lists, + server->layer_visual_stack_bottom); + g_ptr_array_add(server->layer_visual_stack_lists, + server->layer_visual_stack_background); } -static void finalize_lists(struct server *server) -{ +static void finalize_lists(struct server *server) { g_ptr_array_unref(server->layer_visual_stack_background); g_ptr_array_unref(server->layer_visual_stack_bottom); g_ptr_array_unref(server->layer_visual_stack_top); @@ -119,7 +131,8 @@ static void finalize_lists(struct server *server) static int clear_key_combo_timer_callback(void *data) { GPtrArray *registered_key_combos = server.registered_key_combos; - char *bind = join_string((const char **)registered_key_combos->pdata, registered_key_combos->len, " "); + char *bind = join_string((const char **)registered_key_combos->pdata, + registered_key_combos->len, " "); struct tag *tag = server_get_selected_tag(); struct layout *lt = tag_get_layout(tag); @@ -131,22 +144,17 @@ static int clear_key_combo_timer_callback(void *data) { return 0; } -static void init_timers(struct server *server) -{ +static void init_timers(struct server *server) { server->combo_timer_source = wl_event_loop_add_timer( - server->wl_event_loop, - clear_key_combo_timer_callback, - server->registered_key_combos - ); + server->wl_event_loop, clear_key_combo_timer_callback, + server->registered_key_combos); } -static void finalize_timers(struct server *server) -{ +static void finalize_timers(struct server *server) { wl_event_source_remove(server->combo_timer_source); } -static int init_backend(struct server *server) -{ +static int init_backend(struct server *server) { /* The Wayland display is managed by libwayland. It handles accepting * clients from the Unix socket, manging Wayland globals, and so on. */ server->wl_display = wl_display_create(); @@ -159,49 +167,74 @@ static int init_backend(struct server *server) * backend based on the current environment, such as opening an X11 window * if an X11 server is running. The NULL argument here optionally allows you * to pass in a custom renderer if wlr_renderer doesnt). */ - if (!(server->backend = wlr_backend_autocreate(server->wl_display))) { + if (!(server->backend = wlr_backend_autocreate(server->wl_display, &server->wlr_session))) { printf("couldn't create backend\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; } -static void init_event_handlers(struct server *server) -{ - LISTEN(&server->backend->events.new_output, &server->new_output, create_monitor); +static void init_xdg_shell(struct server *server) { /* Use xdg_decoration protocol to negotiate server-side decorations */ server->xdeco_mgr = wlr_xdg_decoration_manager_v1_create(server->wl_display); - LISTEN(&server->xdeco_mgr->events.new_toplevel_decoration, &server->new_xdeco, createxdeco); + LISTEN(&server->xdeco_mgr->events.new_toplevel_decoration, &server->new_xdeco, + createxdeco); - server->xdg_shell = wlr_xdg_shell_create(server->wl_display, XDG_SHELL_VERSION); + server->xdg_shell = + wlr_xdg_shell_create(server->wl_display, XDG_SHELL_VERSION); // remove csd(client side decorations) completely from xdg based windows wlr_server_decoration_manager_set_default_mode( wlr_server_decoration_manager_create(server->wl_display), WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); - LISTEN(&server->xdg_shell->events.new_surface, &server->new_xdg_surface, create_notify_xdg); - - server->layer_shell = wlr_layer_shell_v1_create(server->wl_display); - LISTEN(&server->layer_shell->events.new_surface, &server->new_layer_shell_surface, create_notify_layer_shell); + LISTEN(&server->xdg_shell->events.new_surface, &server->new_xdg_surface, + create_notify_xdg); +} - server->pointer_constraints = wlr_pointer_constraints_v1_create(server->wl_display); - LISTEN(&server->pointer_constraints->events.new_constraint, &server->new_pointer_constraint, handle_new_pointer_constraint); +static void init_layer_shell(struct server *server) { + server->layer_shell = wlr_layer_shell_v1_create(server->wl_display, LAYER_SHELL_VERSION); + LISTEN(&server->layer_shell->events.new_surface, + &server->new_layer_shell_surface, create_notify_layer_shell); +} +static void init_output_management(struct server *server) { + LISTEN(&server->backend->events.new_output, &server->new_output, + create_monitor); server->output_mgr = wlr_output_manager_v1_create(server->wl_display); - LISTEN(&server->output_mgr->events.apply, &server->output_mgr_apply, handle_output_mgr_apply); - LISTEN(&server->output_mgr->events.test, &server->output_mgr_test, handle_output_mgr_test); + LISTEN(&server->output_mgr->events.apply, &server->output_mgr_apply, + handle_output_mgr_apply); + LISTEN(&server->output_mgr->events.test, &server->output_mgr_test, + handle_output_mgr_test); +} + +static void init_pointer_constraints(struct server *server) { + server->pointer_constraints = + wlr_pointer_constraints_v1_create(server->wl_display); + LISTEN(&server->pointer_constraints->events.new_constraint, + &server->new_pointer_constraint, handle_new_pointer_constraint); +} - server->tablet_mgr = wlr_tablet_v2_create(server->wl_display); +static void init_tablet_v2(struct server *server) { + server->tablet_v2 = wlr_tablet_v2_create(server->wl_display); } -static void finalize_event_handlers(struct server *server) +static void setup_event_handlers(struct server *server) { + init_output_management(server); + + init_xdg_shell(server); + init_layer_shell(server); + + // input methods + init_pointer_constraints(server); + init_tablet_v2(server); +} + +static void finalize_event_handlers(struct server *server) { destroy_event_handler(server->event_handler); } -void init_server() -{ - server = (struct server) { - }; +void init_server() { + server = (struct server){}; server.registered_key_combos = g_ptr_array_new(); server.named_key_combos = g_ptr_array_new(); @@ -250,8 +283,7 @@ void init_server() server.output_layout = wlr_output_layout_create(); } -void finalize_server() -{ +void finalize_server() { g_ptr_array_unref(server.registered_key_combos); g_ptr_array_unref(server.named_key_combos); @@ -278,14 +310,12 @@ void finalize_server() g_ptr_array_unref(server.container_stack); } -void server_terminate(struct server *server) -{ +void server_terminate(struct server *server) { server->is_running = false; wl_display_terminate(server->wl_display); uv_loop_close(server->uv_loop); } - static void run_event_loop() { int pfd_size = 2; struct pollfd pfds[pfd_size]; @@ -310,32 +340,24 @@ static void run_event_loop() { } } - -static void run(char *startup_cmd) -{ - pid_t startup_pid = -1; - - /* Add a Unix socket to the Wayland display. */ - const char *socket = wl_display_add_socket_auto(server.wl_display); - - if (!socket) - printf("startup: display_add_socket_auto\n"); - - /* Set the WAYLAND_DISPLAY environment variable to our socket and run the - * startup command if requested. */ +static void initialize_wayland_display(struct server *server) { + const char *socket = wl_display_add_socket_auto(server->wl_display); + if (!socket) { + fprintf(stderr, "startup: display_add_socket_auto failed\n"); + exit(EXIT_FAILURE); + } setenv("WAYLAND_DISPLAY", socket, 1); +} - /* Start the backend. This will enumerate outputs and inputs, become the DRM - * master, etc */ - if (!wlr_backend_start(server.backend)) { - printf("Failed to start backend"); - wlr_backend_destroy(server.backend); - return; +static void start_backend(struct server *server) { + if (!wlr_backend_start(server->backend)) { + fprintf(stderr, "Failed to start backend\n"); + wlr_backend_destroy(server->backend); + exit(EXIT_FAILURE); } +} - /* Now that outputs are initialized, choose initial selMon based on - * cursor position, and set default cursor image */ - update_monitor_geometries(); +static void initialize_cursor(struct server *server) { struct seat *seat = input_manager_get_default_seat(); struct cursor *cursor = seat->cursor; struct monitor *m = xy_to_monitor(cursor->wlr_cursor->x, cursor->wlr_cursor->y); @@ -346,13 +368,29 @@ static void run(char *startup_cmd) * initialized, as the image/coordinates are not transformed for the * monitor when displayed here */ wlr_cursor_warp_closest(seat->cursor->wlr_cursor, NULL, cursor->wlr_cursor->x, cursor->wlr_cursor->y); - wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_mgr, "left_ptr", cursor->wlr_cursor); + wlr_cursor_set_xcursor(cursor->wlr_cursor, seat->cursor->xcursor_mgr, "left_ptr"); +} + +static pid_t execute_startup_command(const char *startup_cmd) { + pid_t pid = fork(); + if (pid == 0) { // Child process + execl("/bin/sh", "/bin/sh", "-c", startup_cmd, (void *)NULL); + fprintf(stderr, "Failed to execute startup command\n"); + exit(EXIT_FAILURE); + } + return pid; +} + +static void run(char *startup_cmd) { + pid_t startup_pid = -1; + + initialize_wayland_display(&server); + start_backend(&server); + update_monitor_geometries(); + initialize_cursor(&server); if (startup_cmd) { - startup_pid = fork(); - if (startup_pid == 0) { - execl("/bin/sh", "/bin/sh", "-c", startup_cmd, (void *)NULL); - } + startup_pid = execute_startup_command(startup_cmd); } run_event_loop(); @@ -363,27 +401,21 @@ static void run(char *startup_cmd) } } -static void init_lua_api(struct server *server) -{ +static void init_lua_api(struct server *server) { L = luaL_newstate(); luaL_openlibs(L); lua_setwarnf(L, handle_warning, NULL); } -static void finalize_lua_api(struct server *server) -{ - lua_close(L); -} +static void finalize_lua_api(struct server *server) { lua_close(L); } -void server_reset_layout_ring(struct ring_buffer *layout_ring) -{ +void server_reset_layout_ring(struct ring_buffer *layout_ring) { list_clear(layout_ring->names, NULL); g_ptr_array_add(layout_ring->names, strdup("tile")); g_ptr_array_add(layout_ring->names, strdup("monocle")); } -static void _async_handler_function(struct uv_async_s *arg) -{ +static void _async_handler_function(struct uv_async_s *arg) { // struct function_data *func_data = data->data; // printf("the end\n"); // free(func_data->output); @@ -402,31 +434,17 @@ static void _async_handler_function(struct uv_async_s *arg) free(data); } -int setup_server(struct server *server) -{ - server->uv_loop = uv_default_loop(); - - uv_async_init(uv_default_loop(), &server->async_handler, _async_handler_function); - - /* If we don't provide a renderer, autocreate makes a GLES2 renderer for us. - * The renderer is responsible for defining the various pixel formats it - * supports for shared memory, this configures that for clients. */ - server->renderer = wlr_renderer_autocreate(server->backend); - - wlr_renderer_init_wl_display(server->renderer, server->wl_display); - - server->allocator = wlr_allocator_autocreate(server->backend, server->renderer); - - /* This creates some hands-off wlroots interfaces. The compositor is - * necessary for clients to allocate surfaces and the data device manager - * handles the clipboard. Each of these wlroots interfaces has room for you - * to dig your fingers in and play with their behavior if you want. Note that - * the clients cannot set the selection directly without compositor approval, - * see the setsel() function. */ - server->compositor = wlr_compositor_create(server->wl_display, server->renderer); +/* This creates some hands-off wlroots interfaces. The compositor is + * necessary for clients to allocate surfaces and the data device manager + * handles the clipboard. Each of these wlroots interfaces has room for you + * to dig your fingers in and play with their behavior if you want. Note that + * the clients cannot set the selection directly without compositor approval, + * see the setsel() function. */ +static void setup_wayland_interfaces(struct server *server) { + server->compositor = + wlr_compositor_create(server->wl_display, WL_COMPOSITOR_VERSION, server->renderer); wlr_subcompositor_create(server->wl_display); - wlr_export_dmabuf_manager_v1_create(server->wl_display); wlr_screencopy_manager_v1_create(server->wl_display); wlr_data_control_manager_v1_create(server->wl_display); @@ -434,75 +452,97 @@ int setup_server(struct server *server) wlr_gamma_control_manager_v1_create(server->wl_display); wlr_primary_selection_v1_device_manager_create(server->wl_display); wlr_viewporter_create(server->wl_display); - wlr_idle_create(server->wl_display); wlr_idle_inhibit_v1_create(server->wl_display); - wlr_xdg_output_manager_v1_create(server->wl_display, server->output_layout); +} - /* Set up the xdg-shell. The xdg-shell is a - * Wayland protocol which is used for application windows. For more - * detail on shells, refer to the article: - * - * https://drewdevault.com/2018/07/29/Wayland-shells.html - */ +static void setup_scene_graph(struct server *server) { + server->scene = wlr_scene_create(); + struct wlr_scene *server_scene = server->scene; + server->scene_background = wlr_scene_tree_create(&server_scene->tree); + server->scene_tiled = wlr_scene_tree_create(&server_scene->tree); + server->scene_floating = wlr_scene_tree_create(&server_scene->tree); + server->scene_popups = wlr_scene_tree_create(&server_scene->tree); + server->scene_overlay = wlr_scene_tree_create(&server_scene->tree); +} +static void setup_input_managers(struct server *server) { server->input_inhibitor_mgr = wlr_input_inhibit_manager_create(server->wl_display); - - /* setup virtual pointer manager*/ server->virtual_pointer_mgr = wlr_virtual_pointer_manager_v1_create(server->wl_display); - - /* setup virtual keyboard manager */ server->virtual_keyboard_mgr = wlr_virtual_keyboard_manager_v1_create(server->wl_display); - - /* setup relative pointer manager */ server->relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(server->wl_display); - /* wl_signal_add(&server.virtual_keyboard_mgr->events.new_virtual_keyboard, &new_virtual_keyboard); */ - init_event_handlers(server); - - /* - * Configures a seat, which is a single "seat" at which a user sits and - * operates the computer. This conceptually includes up to one keyboard, - * pointer, touch, and drawing tablet device. We also rig up a listener to - * let us know when new input devices are available on the backend. - */ - server->input_manager = create_input_manager(); - struct seat *seat = create_seat("seat0"); - g_ptr_array_add(server->input_manager->seats, seat); + // Uncomment and implement if necessary: + // wl_signal_add(&server->virtual_keyboard_mgr->events.new_virtual_keyboard, &new_virtual_keyboard); + + server->tablet_v2 = wlr_tablet_v2_create(server->wl_display); +} - server->output_mgr = wlr_output_manager_v1_create(server->wl_display); +static void setup_output_management(struct server *server) { + server->output_mgr = wlr_output_manager_v1_create(server->wl_display); wl_signal_add(&server->output_mgr->events.apply, &server->output_mgr_apply); wl_signal_add(&server->output_mgr->events.test, &server->output_mgr_test); +} - server->tablet_v2 = wlr_tablet_v2_create(server->wl_display); +static void initialize_renderer_and_allocator(struct server *server) { + server->renderer = wlr_renderer_autocreate(server->backend); + wlr_renderer_init_wl_display(server->renderer, server->wl_display); + server->allocator = wlr_allocator_autocreate(server->backend, server->renderer); +} + +static void setup_seat(struct server *server) { + server->input_manager = create_input_manager(); + struct seat *seat = create_seat("seat0"); + g_ptr_array_add(server->input_manager->seats, seat); #ifdef JAPOKWM_HAS_XWAYLAND init_xwayland(server->wl_display, seat); #endif +} + +static void setup_compositor_events(struct server *server) { + server->new_surface.notify = server_handle_new_surface; + wl_signal_add(&server->compositor->events.new_surface, &server->new_surface); +} + +int setup_server(struct server *server) { + server->uv_loop = uv_default_loop(); + uv_async_init(uv_default_loop(), &server->async_handler, _async_handler_function); + + initialize_renderer_and_allocator(server); + setup_wayland_interfaces(server); + setup_input_managers(server); + setup_event_handlers(server); + setup_seat(server); + setup_output_management(server); + setup_scene_graph(server); + setup_compositor_events(server); return 0; } -int start_server(char *startup_cmd) -{ - if (setup_server(&server)) { - printf("failed to setup japokwm\n"); + +int start_server(char *startup_cmd) { + // Attempt to set up the server. If this fails, report the error and exit. + if (setup_server(&server) != 0) { + fprintf(stderr, "Failed to set up japokwm\n"); return EXIT_FAILURE; } + // Run the server with the provided startup command. + // This function contains the main event loop and will block until the server exits. run(startup_cmd); + return EXIT_SUCCESS; } -int finalize(struct server *server) -{ +int finalize(struct server *server) { finalize_timers(server); destroy_layout(server->default_layout); destroy_ring_buffer(server->default_layout_ring); return 0; } -int stop_server() -{ +int stop_server() { #if JAPOKWM_HAS_XWAYLAND wlr_xwayland_destroy(server.xwayland.wlr_xwayland); #endif @@ -520,26 +560,22 @@ int stop_server() return EXIT_SUCCESS; } -int server_get_tag_count() -{ +int server_get_tag_count() { size_t len = server.default_layout->options->tag_names->len; return len; } -int server_get_tag_key_count() -{ +int server_get_tag_key_count() { size_t count = g_hash_table_size(server.tags); return count; } -GList *server_get_tags() -{ +GList *server_get_tags() { GList *values = g_hash_table_get_values(server.tags); return values; } -struct tag *get_tag(int id) -{ +struct tag *get_tag(int id) { if (id < 0) return NULL; struct tag *tag = g_hash_table_lookup(server.tags, &id); @@ -551,40 +587,34 @@ struct tag *get_tag(int id) return tag; } -struct monitor *server_get_selected_monitor() -{ +struct monitor *server_get_selected_monitor() { return server.selected_monitor; } -void server_set_selected_monitor(struct monitor *m) -{ +void server_set_selected_monitor(struct monitor *m) { server.selected_monitor = m; } -void server_center_default_cursor_in_monitor(struct monitor *m) -{ +void server_center_default_cursor_in_monitor(struct monitor *m) { struct seat *seat = input_manager_get_default_seat(); struct cursor *cursor = seat->cursor; center_cursor_in_monitor(cursor, m); } -BitSet *server_bitset_get_tmp() -{ +BitSet *server_bitset_get_tmp() { if (!server.tmp_bitset) { server.tmp_bitset = bitset_create(); } return server.tmp_bitset; } -BitSet *server_bitset_get_tmp_copy(BitSet *bitset) -{ +BitSet *server_bitset_get_tmp_copy(BitSet *bitset) { BitSet *tmp = server_bitset_get_tmp(); bitset_assign_bitset(&tmp, bitset); return tmp; } -BitSet *server_bitset_get_local_tmp() -{ +BitSet *server_bitset_get_local_tmp() { if (!server.local_tmp_bitset) { server.local_tmp_bitset = bitset_create(); } @@ -592,57 +622,43 @@ BitSet *server_bitset_get_local_tmp() return server.local_tmp_bitset; } -BitSet *server_bitset_get_local_tmp_copy(BitSet *bitset) -{ +BitSet *server_bitset_get_local_tmp_copy(BitSet *bitset) { BitSet *tmp = server_bitset_get_local_tmp(); bitset_assign_bitset(&tmp, bitset); return tmp; } -struct tag *server_get_selected_tag() -{ +struct tag *server_get_selected_tag() { struct monitor *m = server_get_selected_monitor(); struct tag *tag = monitor_get_active_tag(m); return tag; } -struct layout *server_get_selected_layout() -{ +struct layout *server_get_selected_layout() { struct tag *tag = server_get_selected_tag(); struct layout *lt = tag_get_layout(tag); return lt; } -void server_prohibit_reloading_config() -{ +void server_prohibit_reloading_config() { server.prohibit_reload_config = true; } -void server_allow_reloading_config() -{ - server.prohibit_reload_config = false; -} +void server_allow_reloading_config() { server.prohibit_reload_config = false; } -bool server_is_config_reloading_prohibited() -{ +bool server_is_config_reloading_prohibited() { return server.prohibit_reload_config; } -int cmp_str_bool(const void *s1, const void *s2) -{ - return strcmp(s1, s2) == 0; -} +int cmp_str_bool(const void *s1, const void *s2) { return strcmp(s1, s2) == 0; } -void server_start_keycombo(const char *key_combo_name) -{ +void server_start_keycombo(const char *key_combo_name) { g_ptr_array_add(server.named_key_combos, strdup(key_combo_name)); } -bool server_is_keycombo(const char *key_combo_name) -{ +bool server_is_keycombo(const char *key_combo_name) { guint pos = 0; bool found = g_ptr_array_find_with_equal_func( - server.named_key_combos, - key_combo_name, cmp_str_bool, &pos); + server.named_key_combos, key_combo_name, cmp_str_bool, &pos); return found; } diff --git a/src/subsurface.c b/src/subsurface.c index f407c2c8..da66a4d2 100644 --- a/src/subsurface.c +++ b/src/subsurface.c @@ -22,13 +22,11 @@ static void handle_subsurface_commit(struct wl_listener *listener, void *data) // TODO: We should damage the subsurface directly and render the damage // directly instead of leaving this job to the parent surface. This should // save us cpu cycles - container_damage_part(xdg_subsurface->parent); } static void handle_subsurface_destroy(struct wl_listener *listener, void *data) { struct subsurface *subsurface = wl_container_of(listener, subsurface, destroy); - container_damage_whole(subsurface->parent); destroy_subsurface(subsurface); } diff --git a/src/tag.c b/src/tag.c index 02bb95ec..ecd9bdbf 100644 --- a/src/tag.c +++ b/src/tag.c @@ -876,6 +876,22 @@ void add_container_to_layer_stack(struct container *con) con->client->layer = con->client->surface.layer->current.layer; g_ptr_array_insert(get_layer_list(con->client->layer), 0, con); + + struct wlr_scene_node *node = container_get_scene_node(con); + switch(con->client->layer) { + case ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND: + wlr_scene_node_reparent(node, server.scene_background); + break; + case ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM: + wlr_scene_node_reparent(node, server.scene_tiled); + break; + case ZWLR_LAYER_SHELL_V1_LAYER_TOP: + wlr_scene_node_reparent(node, server.scene_floating); + break; + case ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY: + wlr_scene_node_reparent(node, server.scene_overlay); + break; + } return; } diff --git a/src/tile/tileUtils.c b/src/tile/tileUtils.c index 4c4b2248..72c49695 100644 --- a/src/tile/tileUtils.c +++ b/src/tile/tileUtils.c @@ -238,9 +238,18 @@ void arrange_monitor(struct monitor *m) arrange_containers(tag, active_geom, tiled_containers); g_ptr_array_unref(tiled_containers); - wlr_output_damage_add_whole(m->damage); update_reduced_focus_stack(tag); tag_focus_most_recent_container(tag); + + // update container visibility + GPtrArray *stack_list = tag_get_complete_stack_copy(tag); + for (int i = stack_list->len-1; i >= 0; i--) { + struct container *con = g_ptr_array_index(stack_list, i); + bool viewable = container_viewable_on_monitor(m, con); + struct wlr_scene_node *node = container_get_scene_node(con); + wlr_scene_node_set_enabled(node, viewable); + } + g_ptr_array_unref(stack_list); } void arrange_containers( @@ -296,13 +305,17 @@ static void arrange_container(struct container *con, struct monitor *m, void container_update_size(struct container *con) { - con->client->resized = true; + struct wlr_box con_geom = container_get_current_geom(con); - struct wlr_box con_geom = container_get_current_content_geom(con); - struct wlr_box output_geom; - wlr_output_layout_get_box(server.output_layout, NULL, &output_geom); - con_geom = apply_bounds(con, output_geom); + if (!container_is_tiled(con)) { + struct monitor *m = server_get_selected_monitor(); + struct wlr_box output_geom = monitor_get_active_geom(m); + apply_bounds(&con_geom, output_geom); + container_set_current_geom(con, con_geom); + } + struct scene_surface *surface = con->client->scene_surface; + wlr_scene_node_set_position(&surface->scene_surface->buffer->node, con_geom.x, con_geom.y); /* wlroots makes this a no-op if size hasn't changed */ switch (con->client->type) { case XDG_SHELL: @@ -331,6 +344,7 @@ void container_update_size(struct container *con) con_geom.x, con_geom.y, con_geom.width, con_geom.height); } + container_update_border_geometry(con); } void update_hidden_status_of_containers(struct monitor *m, GPtrArray *tiled_containers) diff --git a/src/utils/coreUtils.c b/src/utils/coreUtils.c index 68bdf904..aaec9401 100644 --- a/src/utils/coreUtils.c +++ b/src/utils/coreUtils.c @@ -1,6 +1,5 @@ #include "utils/coreUtils.h" -#include #include #include #include @@ -9,11 +8,9 @@ #include #include #include -#include #include #include -#include "utils/parseConfigUtils.h" #include "ring_buffer.h" struct lua_State *L; diff --git a/src/xdg_shell.c b/src/xdg_shell.c index 60a3ece6..48290e87 100644 --- a/src/xdg_shell.c +++ b/src/xdg_shell.c @@ -6,13 +6,11 @@ #include "client.h" #include "monitor.h" -#include "popup.h" #include "server.h" #include "utils/coreUtils.h" #include "container.h" #include "tile/tileUtils.h" #include "tag.h" -#include "rules/rule.h" #include "subsurface.h" static void destroyxdeco(struct wl_listener *listener, void *data); @@ -37,6 +35,7 @@ static void getxdecomode(struct wl_listener *listener, void *data) void create_notify_xdg(struct wl_listener *listener, void *data) { + printf("create notify xdg\n"); /* This event is raised when wlr_xdg_shell receives a new xdg surface from a * client, either a toplevel (application window) or popup. */ struct wlr_xdg_surface *xdg_surface = data; @@ -48,17 +47,18 @@ void create_notify_xdg(struct wl_listener *listener, void *data) surface.xdg = xdg_surface; /* Allocate a Client for this surface */ struct client *c = xdg_surface->data = create_client(XDG_SHELL, surface); + xdg_surface->surface->data = c; /* Tell the client not to try anything fancy */ wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); /* Listen to the various events it can emit */ - LISTEN(&xdg_surface->events.map, &c->map, map_request); + LISTEN(&xdg_surface->surface->events.map, &c->map, map_request); LISTEN(&xdg_surface->surface->events.commit, &c->commit, commit_notify); LISTEN(&xdg_surface->events.configure, &c->configure, configure_notify); LISTEN(&xdg_surface->events.ack_configure, &c->ack_configure, ack_configure); - LISTEN(&xdg_surface->events.unmap, &c->unmap, unmap_notify); + LISTEN(&xdg_surface->surface->events.unmap, &c->unmap, unmap_notify); LISTEN(&xdg_surface->events.destroy, &c->destroy, destroy_notify); LISTEN(&xdg_surface->surface->events.new_subsurface, &c->new_subsurface, handle_new_subsurface); @@ -76,10 +76,11 @@ void destroy_notify(struct wl_listener *listener, void *data) wl_list_remove(&c->map.link); wl_list_remove(&c->commit.link); - wl_list_remove(&c->unmap.link); - wl_list_remove(&c->destroy.link); wl_list_remove(&c->configure.link); wl_list_remove(&c->ack_configure.link); + wl_list_remove(&c->unmap.link); + wl_list_remove(&c->destroy.link); + wl_list_remove(&c->new_subsurface.link); wl_list_remove(&c->set_title.link); wl_list_remove(&c->set_app_id.link); @@ -108,7 +109,6 @@ void unmap_notify(struct wl_listener *listener, void *data) struct client *c = wl_container_of(listener, c, unmap); struct container *con = c->con; - container_damage_whole(c->con); remove_container_from_tile(con); arrange(); diff --git a/src/xwayland.c b/src/xwayland.c index 68863894..441c9d21 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -50,8 +50,8 @@ void create_notifyx11(struct wl_listener *listener, void *data) // set default value will be overriden on maprequest /* Listen to the various events it can emit */ - LISTEN(&xwayland_surface->events.map, &c->map, maprequestx11); - LISTEN(&xwayland_surface->events.unmap, &c->unmap, unmap_notifyx11); + LISTEN(&xwayland_surface->events.associate, &c->associate, maprequestx11); + LISTEN(&xwayland_surface->events.dissociate, &c->dissociate, unmap_notifyx11); LISTEN(&xwayland_surface->events.destroy, &c->destroy, destroy_notifyx11); LISTEN(&xwayland_surface->events.set_title, &c->set_title, client_handle_set_title); LISTEN(&xwayland_surface->events.set_class, &c->set_app_id, client_handle_set_app_id); @@ -71,11 +71,12 @@ void destroy_notifyx11(struct wl_listener *listener, void *data) } destroy_container(c->con); - wl_list_remove(&c->map.link); - wl_list_remove(&c->unmap.link); + wl_list_remove(&c->associate.link); + wl_list_remove(&c->dissociate.link); wl_list_remove(&c->destroy.link); wl_list_remove(&c->set_title.link); wl_list_remove(&c->set_app_id.link); + wl_list_remove(&c->activate.link); destroy_client(c); } @@ -123,12 +124,11 @@ void handle_xwayland_ready(struct wl_listener *listener, void *data) void unmap_notifyx11(struct wl_listener *listener, void *data) { /* Called when the surface is unmapped, and should no longer be shown. */ - struct client *c = wl_container_of(listener, c, unmap); + struct client *c = wl_container_of(listener, c, dissociate); wl_list_remove(&c->commit.link); struct container *con = c->con; - container_damage_whole(c->con); remove_container_from_tile(con); arrange(); @@ -138,12 +138,15 @@ void unmap_notifyx11(struct wl_listener *listener, void *data) void maprequestx11(struct wl_listener *listener, void *data) { /* Called when the surface is mapped, or ready to display on-screen. */ - struct client *c = wl_container_of(listener, c, map); + struct client *c = wl_container_of(listener, c, associate); struct wlr_xwayland_surface *xwayland_surface = c->surface.xwayland; struct monitor *m = server_get_selected_monitor(); c->type = xwayland_surface->override_redirect ? X11_UNMANAGED : X11_MANAGED; + c->scene_surface = xwayland_surface->surface->data; + xwayland_surface->surface->data = c; + struct container *con = c->con; con->tag_id = m->tag_id; @@ -194,7 +197,6 @@ void maprequestx11(struct wl_listener *listener, void *data) case X11_UNMANAGED: { con->is_unmanaged = true; - c->is_independent = true; debug_print("is unmanaged\n"); struct tag *tag = monitor_get_active_tag(m); @@ -224,8 +226,7 @@ void maprequestx11(struct wl_listener *listener, void *data) struct container *sel = monitor_get_focused_container(m); tag_this_focus_container(sel); struct seat *seat = input_manager_get_default_seat(); - wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_mgr, - "left_ptr", seat->cursor->wlr_cursor); + wlr_cursor_set_xcursor(seat->cursor->wlr_cursor, seat->cursor->xcursor_mgr, "left_ptr"); } bool xwayland_popups_exist()