diff --git a/src/lib/client.c b/src/lib/client.c index a3879fb..25245e8 100644 --- a/src/lib/client.c +++ b/src/lib/client.c @@ -1,4 +1,4 @@ -#include "lib/client.h" +#include "client.h" void applybounds(Client *c, struct wlr_box *bbox) { /* set minimum possible */ @@ -15,34 +15,6 @@ void applybounds(Client *c, struct wlr_box *bbox) { c->geom.y = bbox->y; } -void applyrules(Client *c) { - /* rule matching */ - const char *appid, *title; - uint32_t newtags = 0; - int i; - const Rule *r; - Monitor *mon = selmon, *m; - - appid = client_get_appid(c); - title = client_get_title(c); - - for (r = rules; r < END(rules); r++) { - if ((!r->title || strstr(title, r->title)) && - (!r->id || strstr(appid, r->id))) { - c->isfloating = r->isfloating; - newtags |= r->tags; - i = 0; - wl_list_for_each(m, &mons, link) { - if (r->monitor == i++) - mon = m; - } - } - } - - c->isfloating |= client_is_float_type(c); - setmon(c, mon, newtags); -} - void focusclient(Client *c, int lift) { struct wlr_surface *old = seat->keyboard_state.focused_surface; int unused_lx, unused_ly, old_client_type; @@ -278,39 +250,6 @@ void view(const Arg *arg) { printstatus(); } -void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, - LayerSurface **pl, double *nx, double *ny) { - struct wlr_scene_node *node, *pnode; - struct wlr_surface *surface = NULL; - Client *c = NULL; - LayerSurface *l = NULL; - int layer; - - for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) { - if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny))) - continue; - - if (node->type == WLR_SCENE_NODE_BUFFER) - surface = - wlr_scene_surface_try_from_buffer(wlr_scene_buffer_from_node(node)) - ->surface; - /* Walk the tree to find a node that knows the client */ - for (pnode = node; pnode && !c; pnode = &pnode->parent->node) - c = pnode->data; - if (c && c->type == LayerShell) { - c = NULL; - l = pnode->data; - } - } - - if (psurface) - *psurface = surface; - if (pc) - *pc = c; - if (pl) - *pl = l; -} - void zoom(const Arg *arg) { Client *c, *sel = focustop(selmon); diff --git a/src/lib/client.h b/src/lib/client.h index 64f55dc..8b5beff 100644 --- a/src/lib/client.h +++ b/src/lib/client.h @@ -7,6 +7,9 @@ #ifndef CRYWL_CLIENT_H #define CRYWL_CLIENT_H +#include "../wayland.h" +#include "../util.h" + enum { XDGShell, LayerShell, X11 }; /* client types */ typedef struct Monitor Monitor; // forward declare @@ -52,392 +55,21 @@ typedef struct { } Client; /* ===== Function Declarations ===== */ -static void applybounds(Client *c, struct wlr_box *bbox); -static void applyrules(Client *c); -static void focusclient(Client *c, int lift); -static void killclient(const Arg *arg); -static void resize(Client *c, struct wlr_box geo, int interact); -static void setfloating(Client *c, int floating); -static void setfullscreen(Client *c, int fullscreen); -static void setpsel(struct wl_listener *listener, void *data); -static void setsel(struct wl_listener *listener, void *data); -static void togglefloating(const Arg *arg); -static void togglefullscreen(const Arg *arg); -static void toggletag(const Arg *arg); -static void toggleview(const Arg *arg); -static void updatetitle(struct wl_listener *listener, void *data); -static void urgent(struct wl_listener *listener, void *data); -static void view(const Arg *arg); -static void xytonode(double x, double y, struct wlr_surface **psurface, - Client **pc, LayerSurface **pl, double *nx, double *ny); -static void zoom(const Arg *arg); - -/* Leave these functions first; they're used in the others */ -static inline int client_is_x11(Client *c) { -#ifdef XWAYLAND - return c->type == X11; -#endif - return 0; -} - -static inline struct wlr_surface *client_surface(Client *c) { -#ifdef XWAYLAND - if (client_is_x11(c)) - return c->surface.xwayland->surface; -#endif - return c->surface.xdg->surface; -} - -static inline int toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, - LayerSurface **pl) { - struct wlr_xdg_surface *xdg_surface, *tmp_xdg_surface; - struct wlr_surface *root_surface; - struct wlr_layer_surface_v1 *layer_surface; - Client *c = NULL; - LayerSurface *l = NULL; - int type = -1; -#ifdef XWAYLAND - struct wlr_xwayland_surface *xsurface; -#endif - - if (!s) - return -1; - root_surface = wlr_surface_get_root_surface(s); - -#ifdef XWAYLAND - if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(root_surface))) { - c = xsurface->data; - type = c->type; - goto end; - } -#endif - - if ((layer_surface = - wlr_layer_surface_v1_try_from_wlr_surface(root_surface))) { - l = layer_surface->data; - type = LayerShell; - goto end; - } - - xdg_surface = wlr_xdg_surface_try_from_wlr_surface(root_surface); - while (xdg_surface) { - tmp_xdg_surface = NULL; - switch (xdg_surface->role) { - case WLR_XDG_SURFACE_ROLE_POPUP: - if (!xdg_surface->popup || !xdg_surface->popup->parent) - return -1; - - tmp_xdg_surface = - wlr_xdg_surface_try_from_wlr_surface(xdg_surface->popup->parent); - - if (!tmp_xdg_surface) - return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl); - - xdg_surface = tmp_xdg_surface; - break; - case WLR_XDG_SURFACE_ROLE_TOPLEVEL: - c = xdg_surface->data; - type = c->type; - goto end; - case WLR_XDG_SURFACE_ROLE_NONE: - return -1; - } - } - -end: - if (pl) - *pl = l; - if (pc) - *pc = c; - return type; -} - -/* The others */ -static inline void client_activate_surface(struct wlr_surface *s, - int activated) { - struct wlr_xdg_toplevel *toplevel; -#ifdef XWAYLAND - struct wlr_xwayland_surface *xsurface; - if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(s))) { - wlr_xwayland_surface_activate(xsurface, activated); - return; - } -#endif - if ((toplevel = wlr_xdg_toplevel_try_from_wlr_surface(s))) - wlr_xdg_toplevel_set_activated(toplevel, activated); -} - -static inline uint32_t client_set_bounds(Client *c, int32_t width, - int32_t height) { -#ifdef XWAYLAND - if (client_is_x11(c)) - return 0; -#endif - if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >= - XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION && - width >= 0 && height >= 0 && - (c->bounds.width != width || c->bounds.height != height)) { - c->bounds.width = width; - c->bounds.height = height; - return wlr_xdg_toplevel_set_bounds(c->surface.xdg->toplevel, width, height); - } - return 0; -} - -static inline const char *client_get_appid(Client *c) { -#ifdef XWAYLAND - if (client_is_x11(c)) - return c->surface.xwayland->class ? c->surface.xwayland->class : "broken"; -#endif - return c->surface.xdg->toplevel->app_id ? c->surface.xdg->toplevel->app_id - : "broken"; -} - -static inline void client_get_clip(Client *c, struct wlr_box *clip) { - *clip = (struct wlr_box){ - .x = 0, - .y = 0, - .width = c->geom.width - c->bw, - .height = c->geom.height - c->bw, - }; - -#ifdef XWAYLAND - if (client_is_x11(c)) - return; -#endif - - clip->x = c->surface.xdg->geometry.x; - clip->y = c->surface.xdg->geometry.y; -} - -static inline void client_get_geometry(Client *c, struct wlr_box *geom) { -#ifdef XWAYLAND - if (client_is_x11(c)) { - geom->x = c->surface.xwayland->x; - geom->y = c->surface.xwayland->y; - geom->width = c->surface.xwayland->width; - geom->height = c->surface.xwayland->height; - return; - } -#endif - *geom = c->surface.xdg->geometry; -} - -static inline Client *client_get_parent(Client *c) { - Client *p = NULL; -#ifdef XWAYLAND - if (client_is_x11(c)) { - if (c->surface.xwayland->parent) - toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL); - return p; - } -#endif - if (c->surface.xdg->toplevel->parent) - toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, - &p, NULL); - return p; -} - -static inline int client_has_children(Client *c) { -#ifdef XWAYLAND - if (client_is_x11(c)) - return !wl_list_empty(&c->surface.xwayland->children); -#endif - /* surface.xdg->link is never empty because it always contains at least the - * surface itself. */ - return wl_list_length(&c->surface.xdg->link) > 1; -} - -static inline const char *client_get_title(Client *c) { -#ifdef XWAYLAND - if (client_is_x11(c)) - return c->surface.xwayland->title ? c->surface.xwayland->title : "broken"; -#endif - return c->surface.xdg->toplevel->title ? c->surface.xdg->toplevel->title - : "broken"; -} - -static inline int client_is_float_type(Client *c) { - struct wlr_xdg_toplevel *toplevel; - struct wlr_xdg_toplevel_state state; - -#ifdef XWAYLAND - if (client_is_x11(c)) { - struct wlr_xwayland_surface *surface = c->surface.xwayland; - xcb_size_hints_t *size_hints = surface->size_hints; - if (surface->modal) - return 1; - - if (wlr_xwayland_surface_has_window_type( - surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DIALOG) || - wlr_xwayland_surface_has_window_type( - surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_SPLASH) || - wlr_xwayland_surface_has_window_type( - surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLBAR) || - wlr_xwayland_surface_has_window_type( - surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_UTILITY)) { - return 1; - } - - return size_hints && size_hints->min_width > 0 && - size_hints->min_height > 0 && - (size_hints->max_width == size_hints->min_width || - size_hints->max_height == size_hints->min_height); - } -#endif - - toplevel = c->surface.xdg->toplevel; - state = toplevel->current; - return toplevel->parent || (state.min_width != 0 && state.min_height != 0 && - (state.min_width == state.max_width || - state.min_height == state.max_height)); -} - -static inline int client_is_rendered_on_mon(Client *c, Monitor *m) { - /* This is needed for when you don't want to check formal assignment, - * but rather actual displaying of the pixels. - * Usually VISIBLEON suffices and is also faster. */ - struct wlr_surface_output *s; - int unused_lx, unused_ly; - if (!wlr_scene_node_coords(&c->scene->node, &unused_lx, &unused_ly)) - return 0; - wl_list_for_each(s, &client_surface(c)->current_outputs, - link) if (s->output == m->wlr_output) return 1; - return 0; -} - -static inline int client_is_stopped(Client *c) { - int pid; - siginfo_t in = {0}; -#ifdef XWAYLAND - if (client_is_x11(c)) - return 0; -#endif - - wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL); - if (waitid(P_PID, pid, &in, WNOHANG | WCONTINUED | WSTOPPED | WNOWAIT) < 0) { - /* This process is not our child process, while is very unlikely that - * it is stopped, in order to do not skip frames, assume that it is. */ - if (errno == ECHILD) - return 1; - } else if (in.si_pid) { - if (in.si_code == CLD_STOPPED || in.si_code == CLD_TRAPPED) - return 1; - if (in.si_code == CLD_CONTINUED) - return 0; - } - - return 0; -} - -static inline int client_is_unmanaged(Client *c) { -#ifdef XWAYLAND - if (client_is_x11(c)) - return c->surface.xwayland->override_redirect; -#endif - return 0; -} - -static inline void client_notify_enter(struct wlr_surface *s, - struct wlr_keyboard *kb) { - if (kb) - wlr_seat_keyboard_notify_enter(seat, s, kb->keycodes, kb->num_keycodes, - &kb->modifiers); - else - wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL); -} - -static inline void client_send_close(Client *c) { -#ifdef XWAYLAND - if (client_is_x11(c)) { - wlr_xwayland_surface_close(c->surface.xwayland); - return; - } -#endif - wlr_xdg_toplevel_send_close(c->surface.xdg->toplevel); -} - -static inline void client_set_border_color(Client *c, - const float color[static 4]) { - int i; - for (i = 0; i < 4; i++) - wlr_scene_rect_set_color(c->border[i], color); -} - -static inline void client_set_fullscreen(Client *c, int fullscreen) { -#ifdef XWAYLAND - if (client_is_x11(c)) { - wlr_xwayland_surface_set_fullscreen(c->surface.xwayland, fullscreen); - return; - } -#endif - wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen); -} - -static inline void client_set_scale(struct wlr_surface *s, float scale) { - wlr_fractional_scale_v1_notify_scale(s, scale); - wlr_surface_set_preferred_buffer_scale(s, (int32_t)ceilf(scale)); -} - -static inline uint32_t client_set_size(Client *c, uint32_t width, - uint32_t height) { -#ifdef XWAYLAND - if (client_is_x11(c)) { - wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x + c->bw, - c->geom.y + c->bw, width, height); - return 0; - } -#endif - if ((int32_t)width == c->surface.xdg->toplevel->current.width && - (int32_t)height == c->surface.xdg->toplevel->current.height) - return 0; - return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width, - (int32_t)height); -} - -static inline void client_set_tiled(Client *c, uint32_t edges) { -#ifdef XWAYLAND - if (client_is_x11(c)) { - wlr_xwayland_surface_set_maximized( - c->surface.xwayland, edges != WLR_EDGE_NONE, edges != WLR_EDGE_NONE); - return; - } -#endif - if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >= - XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) { - wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges); - } else { - wlr_xdg_toplevel_set_maximized(c->surface.xdg->toplevel, - edges != WLR_EDGE_NONE); - } -} - -static inline void client_set_suspended(Client *c, int suspended) { -#ifdef XWAYLAND - if (client_is_x11(c)) - return; -#endif - - wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended); -} - -static inline int client_wants_focus(Client *c) { -#ifdef XWAYLAND - return client_is_unmanaged(c) && - wlr_xwayland_surface_override_redirect_wants_focus( - c->surface.xwayland) && - wlr_xwayland_surface_icccm_input_model(c->surface.xwayland) != - WLR_ICCCM_INPUT_MODEL_NONE; -#endif - return 0; -} - -static inline int client_wants_fullscreen(Client *c) { -#ifdef XWAYLAND - if (client_is_x11(c)) - return c->surface.xwayland->fullscreen; -#endif - return c->surface.xdg->toplevel->requested.fullscreen; -} +void applybounds(Client *c, struct wlr_box *bbox); +void focusclient(Client *c, int lift); +void killclient(const Arg *arg); +void resize(Client *c, struct wlr_box geo, int interact); +void setfloating(Client *c, int floating); +void setfullscreen(Client *c, int fullscreen); +void setpsel(struct wl_listener *listener, void *data); +void setsel(struct wl_listener *listener, void *data); +void togglefloating(const Arg *arg); +void togglefullscreen(const Arg *arg); +void toggletag(const Arg *arg); +void toggleview(const Arg *arg); +void updatetitle(struct wl_listener *listener, void *data); +void urgent(struct wl_listener *listener, void *data); +void view(const Arg *arg); +void zoom(const Arg *arg); #endif /* CRYWL_CLIENT_H */ diff --git a/src/lib/clientutil.h b/src/lib/clientutil.h new file mode 100644 index 0000000..4799d69 --- /dev/null +++ b/src/lib/clientutil.h @@ -0,0 +1,376 @@ +#ifndef CRYWL_CLIENTUTIL_H +#define CRYWL_CLIENTUTIL_H + +#include "sys/wait.h" + +#include "layers.h" + +/* Leave these functions first; they're used in the others */ +static inline int client_is_x11(Client *c) { +#ifdef XWAYLAND + return c->type == X11; +#endif + return 0; +} + +static inline struct wlr_surface *client_surface(Client *c) { +#ifdef XWAYLAND + if (client_is_x11(c)) + return c->surface.xwayland->surface; +#endif + return c->surface.xdg->surface; +} + +static inline int toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, + LayerSurface **pl) { + struct wlr_xdg_surface *xdg_surface, *tmp_xdg_surface; + struct wlr_surface *root_surface; + struct wlr_layer_surface_v1 *layer_surface; + Client *c = NULL; + LayerSurface *l = NULL; + int type = -1; +#ifdef XWAYLAND + struct wlr_xwayland_surface *xsurface; +#endif + + if (!s) + return -1; + root_surface = wlr_surface_get_root_surface(s); + +#ifdef XWAYLAND + if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(root_surface))) { + c = xsurface->data; + type = c->type; + goto end; + } +#endif + + if ((layer_surface = + wlr_layer_surface_v1_try_from_wlr_surface(root_surface))) { + l = layer_surface->data; + type = LayerShell; + goto end; + } + + xdg_surface = wlr_xdg_surface_try_from_wlr_surface(root_surface); + while (xdg_surface) { + tmp_xdg_surface = NULL; + switch (xdg_surface->role) { + case WLR_XDG_SURFACE_ROLE_POPUP: + if (!xdg_surface->popup || !xdg_surface->popup->parent) + return -1; + + tmp_xdg_surface = + wlr_xdg_surface_try_from_wlr_surface(xdg_surface->popup->parent); + + if (!tmp_xdg_surface) + return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl); + + xdg_surface = tmp_xdg_surface; + break; + case WLR_XDG_SURFACE_ROLE_TOPLEVEL: + c = xdg_surface->data; + type = c->type; + goto end; + case WLR_XDG_SURFACE_ROLE_NONE: + return -1; + } + } + +end: + if (pl) + *pl = l; + if (pc) + *pc = c; + return type; +} + +/* The others */ +static inline void client_activate_surface(struct wlr_surface *s, + int activated) { + struct wlr_xdg_toplevel *toplevel; +#ifdef XWAYLAND + struct wlr_xwayland_surface *xsurface; + if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(s))) { + wlr_xwayland_surface_activate(xsurface, activated); + return; + } +#endif + if ((toplevel = wlr_xdg_toplevel_try_from_wlr_surface(s))) + wlr_xdg_toplevel_set_activated(toplevel, activated); +} + +static inline uint32_t client_set_bounds(Client *c, int32_t width, + int32_t height) { +#ifdef XWAYLAND + if (client_is_x11(c)) + return 0; +#endif + if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >= + XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION && + width >= 0 && height >= 0 && + (c->bounds.width != width || c->bounds.height != height)) { + c->bounds.width = width; + c->bounds.height = height; + return wlr_xdg_toplevel_set_bounds(c->surface.xdg->toplevel, width, height); + } + return 0; +} + +static inline const char *client_get_appid(Client *c) { +#ifdef XWAYLAND + if (client_is_x11(c)) + return c->surface.xwayland->class ? c->surface.xwayland->class : "broken"; +#endif + return c->surface.xdg->toplevel->app_id ? c->surface.xdg->toplevel->app_id + : "broken"; +} + +static inline void client_get_clip(Client *c, struct wlr_box *clip) { + *clip = (struct wlr_box){ + .x = 0, + .y = 0, + .width = c->geom.width - c->bw, + .height = c->geom.height - c->bw, + }; + +#ifdef XWAYLAND + if (client_is_x11(c)) + return; +#endif + + clip->x = c->surface.xdg->geometry.x; + clip->y = c->surface.xdg->geometry.y; +} + +static inline void client_get_geometry(Client *c, struct wlr_box *geom) { +#ifdef XWAYLAND + if (client_is_x11(c)) { + geom->x = c->surface.xwayland->x; + geom->y = c->surface.xwayland->y; + geom->width = c->surface.xwayland->width; + geom->height = c->surface.xwayland->height; + return; + } +#endif + *geom = c->surface.xdg->geometry; +} + +static inline Client *client_get_parent(Client *c) { + Client *p = NULL; +#ifdef XWAYLAND + if (client_is_x11(c)) { + if (c->surface.xwayland->parent) + toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL); + return p; + } +#endif + if (c->surface.xdg->toplevel->parent) + toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, + &p, NULL); + return p; +} + +static inline int client_has_children(Client *c) { +#ifdef XWAYLAND + if (client_is_x11(c)) + return !wl_list_empty(&c->surface.xwayland->children); +#endif + /* surface.xdg->link is never empty because it always contains at least the + * surface itself. */ + return wl_list_length(&c->surface.xdg->link) > 1; +} + +static inline const char *client_get_title(Client *c) { +#ifdef XWAYLAND + if (client_is_x11(c)) + return c->surface.xwayland->title ? c->surface.xwayland->title : "broken"; +#endif + return c->surface.xdg->toplevel->title ? c->surface.xdg->toplevel->title + : "broken"; +} + +static inline int client_is_float_type(Client *c) { + struct wlr_xdg_toplevel *toplevel; + struct wlr_xdg_toplevel_state state; + +#ifdef XWAYLAND + if (client_is_x11(c)) { + struct wlr_xwayland_surface *surface = c->surface.xwayland; + xcb_size_hints_t *size_hints = surface->size_hints; + if (surface->modal) + return 1; + + if (wlr_xwayland_surface_has_window_type( + surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_DIALOG) || + wlr_xwayland_surface_has_window_type( + surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_SPLASH) || + wlr_xwayland_surface_has_window_type( + surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_TOOLBAR) || + wlr_xwayland_surface_has_window_type( + surface, WLR_XWAYLAND_NET_WM_WINDOW_TYPE_UTILITY)) { + return 1; + } + + return size_hints && size_hints->min_width > 0 && + size_hints->min_height > 0 && + (size_hints->max_width == size_hints->min_width || + size_hints->max_height == size_hints->min_height); + } +#endif + + toplevel = c->surface.xdg->toplevel; + state = toplevel->current; + return toplevel->parent || (state.min_width != 0 && state.min_height != 0 && + (state.min_width == state.max_width || + state.min_height == state.max_height)); +} + +static inline int client_is_rendered_on_mon(Client *c, Monitor *m) { + /* This is needed for when you don't want to check formal assignment, + * but rather actual displaying of the pixels. + * Usually VISIBLEON suffices and is also faster. */ + struct wlr_surface_output *s; + int unused_lx, unused_ly; + if (!wlr_scene_node_coords(&c->scene->node, &unused_lx, &unused_ly)) + return 0; + wl_list_for_each(s, &client_surface(c)->current_outputs, + link) if (s->output == m->wlr_output) return 1; + return 0; +} + +static inline int client_is_stopped(Client *c) { + int pid; + siginfo_t in = {0}; +#ifdef XWAYLAND + if (client_is_x11(c)) + return 0; +#endif + + wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL); + if (waitid(P_PID, pid, &in, WNOHANG | WCONTINUED | WSTOPPED | WNOWAIT) < 0) { + /* This process is not our child process, while is very unlikely that + * it is stopped, in order to do not skip frames, assume that it is. */ + if (errno == ECHILD) + return 1; + } else if (in.si_pid) { + if (in.si_code == CLD_STOPPED || in.si_code == CLD_TRAPPED) + return 1; + if (in.si_code == CLD_CONTINUED) + return 0; + } + + return 0; +} + +static inline int client_is_unmanaged(Client *c) { +#ifdef XWAYLAND + if (client_is_x11(c)) + return c->surface.xwayland->override_redirect; +#endif + return 0; +} + +static inline void client_notify_enter(struct wlr_surface *s, + struct wlr_keyboard *kb) { + if (kb) + wlr_seat_keyboard_notify_enter(seat, s, kb->keycodes, kb->num_keycodes, + &kb->modifiers); + else + wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL); +} + +static inline void client_send_close(Client *c) { +#ifdef XWAYLAND + if (client_is_x11(c)) { + wlr_xwayland_surface_close(c->surface.xwayland); + return; + } +#endif + wlr_xdg_toplevel_send_close(c->surface.xdg->toplevel); +} + +static inline void client_set_border_color(Client *c, + const float color[static 4]) { + int i; + for (i = 0; i < 4; i++) + wlr_scene_rect_set_color(c->border[i], color); +} + +static inline void client_set_fullscreen(Client *c, int fullscreen) { +#ifdef XWAYLAND + if (client_is_x11(c)) { + wlr_xwayland_surface_set_fullscreen(c->surface.xwayland, fullscreen); + return; + } +#endif + wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen); +} + +static inline void client_set_scale(struct wlr_surface *s, float scale) { + wlr_fractional_scale_v1_notify_scale(s, scale); + wlr_surface_set_preferred_buffer_scale(s, (int32_t)ceilf(scale)); +} + +static inline uint32_t client_set_size(Client *c, uint32_t width, + uint32_t height) { +#ifdef XWAYLAND + if (client_is_x11(c)) { + wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x + c->bw, + c->geom.y + c->bw, width, height); + return 0; + } +#endif + if ((int32_t)width == c->surface.xdg->toplevel->current.width && + (int32_t)height == c->surface.xdg->toplevel->current.height) + return 0; + return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, (int32_t)width, + (int32_t)height); +} + +static inline void client_set_tiled(Client *c, uint32_t edges) { +#ifdef XWAYLAND + if (client_is_x11(c)) { + wlr_xwayland_surface_set_maximized( + c->surface.xwayland, edges != WLR_EDGE_NONE, edges != WLR_EDGE_NONE); + return; + } +#endif + if (wl_resource_get_version(c->surface.xdg->toplevel->resource) >= + XDG_TOPLEVEL_STATE_TILED_RIGHT_SINCE_VERSION) { + wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges); + } else { + wlr_xdg_toplevel_set_maximized(c->surface.xdg->toplevel, + edges != WLR_EDGE_NONE); + } +} + +static inline void client_set_suspended(Client *c, int suspended) { +#ifdef XWAYLAND + if (client_is_x11(c)) + return; +#endif + + wlr_xdg_toplevel_set_suspended(c->surface.xdg->toplevel, suspended); +} + +static inline int client_wants_focus(Client *c) { +#ifdef XWAYLAND + return client_is_unmanaged(c) && + wlr_xwayland_surface_override_redirect_wants_focus( + c->surface.xwayland) && + wlr_xwayland_surface_icccm_input_model(c->surface.xwayland) != + WLR_ICCCM_INPUT_MODEL_NONE; +#endif + return 0; +} + +static inline int client_wants_fullscreen(Client *c) { +#ifdef XWAYLAND + if (client_is_x11(c)) + return c->surface.xwayland->fullscreen; +#endif + return c->surface.xdg->toplevel->requested.fullscreen; +} + +#endif /* CRYWL_CLIENTUTIL_H */ diff --git a/src/lib/cursor.c b/src/lib/cursor.c index d22f599..fad876b 100644 --- a/src/lib/cursor.c +++ b/src/lib/cursor.c @@ -1,3 +1,10 @@ +#include + +#include "cursor.h" +#include "clientutil.h" + +/* Applies a constraint to the pointer cursor, deactivating the old one. + * Noop occurs if constraint matches the current applied constraint. */ void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) { if (active_constraint == constraint) return; @@ -9,15 +16,6 @@ void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint) { wlr_pointer_constraint_v1_send_activated(constraint); } -void cursorframe(struct wl_listener *listener, void *data) { - /* This event is forwarded by the cursor when a pointer emits a frame - * event. Frame events are sent after regular pointer events to group - * multiple events together. For instance, two axis events may happen at the - * same time, in which case a frame event won't be sent in between. */ - /* Notify the client with pointer focus of the frame event. */ - wlr_seat_pointer_notify_frame(seat); -} - void cursorwarptohint(void) { Client *c = NULL; double sx = active_constraint->current.cursor_hint.x; @@ -30,33 +28,3 @@ void cursorwarptohint(void) { wlr_seat_pointer_warp(active_constraint->seat, sx, sy); } } - -void setcursor(struct wl_listener *listener, void *data) { - /* This event is raised by the seat when a client provides a cursor image */ - struct wlr_seat_pointer_request_set_cursor_event *event = data; - /* If we're "grabbing" the cursor, don't use the client's image, we will - * restore it after "grabbing" sending a leave event, followed by a enter - * event, which will result in the client requesting set the cursor surface */ - if (cursor_mode != CurNormal && cursor_mode != CurPressed) - return; - /* This can be sent by any client, so we check to make sure this one - * actually has pointer focus first. If so, we can tell the cursor to - * use the provided surface as the cursor image. It will set the - * hardware cursor on the output that it's currently on and continue to - * do so as the cursor moves between outputs. */ - if (event->seat_client == seat->pointer_state.focused_client) - wlr_cursor_set_surface(cursor, event->surface, event->hotspot_x, - event->hotspot_y); -} - -void setcursorshape(struct wl_listener *listener, void *data) { - struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data; - if (cursor_mode != CurNormal && cursor_mode != CurPressed) - return; - /* This can be sent by any client, so we check to make sure this one - * actually has pointer focus first. If so, we can tell the cursor to - * use the provided cursor shape. */ - if (event->seat_client == seat->pointer_state.focused_client) - wlr_cursor_set_xcursor(cursor, cursor_mgr, - wlr_cursor_shape_v1_name(event->shape)); -} diff --git a/src/lib/cursor.h b/src/lib/cursor.h index bb706a3..bfba63f 100644 --- a/src/lib/cursor.h +++ b/src/lib/cursor.h @@ -1,13 +1,16 @@ #ifndef CRYWL_CURSOR_H #define CRYWL_CURSOR_H +#include + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ +struct wlr_cursor *cursor; +unsigned int cursor_mode; +struct wlr_pointer_constraint_v1 *active_constraint; + /* ===== Function Declarations ===== */ -static void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); -static void cursorframe(struct wl_listener *listener, void *data); -static void cursorwarptohint(void); -static void setcursor(struct wl_listener *listener, void *data); -static void setcursorshape(struct wl_listener *listener, void *data); +void cursorconstrain(struct wlr_pointer_constraint_v1 *constraint); +void cursorwarptohint(void); #endif /* CRYWL_CURSOR_H */ diff --git a/src/lib/decoration.c b/src/lib/decoration.c deleted file mode 100644 index 9f4dc51..0000000 --- a/src/lib/decoration.c +++ /dev/null @@ -1,25 +0,0 @@ -void createdecoration(struct wl_listener *listener, void *data) { - struct wlr_xdg_toplevel_decoration_v1 *deco = data; - Client *c = deco->toplevel->base->data; - c->decoration = deco; - - LISTEN(&deco->events.request_mode, &c->set_decoration_mode, - requestdecorationmode); - LISTEN(&deco->events.destroy, &c->destroy_decoration, destroydecoration); - - requestdecorationmode(&c->set_decoration_mode, deco); -} - -void destroydecoration(struct wl_listener *listener, void *data) { - Client *c = wl_container_of(listener, c, destroy_decoration); - - wl_list_remove(&c->destroy_decoration.link); - wl_list_remove(&c->set_decoration_mode.link); -} - -void requestdecorationmode(struct wl_listener *listener, void *data) { - Client *c = wl_container_of(listener, c, set_decoration_mode); - if (c->surface.xdg->initialized) - wlr_xdg_toplevel_decoration_v1_set_mode( - c->decoration, WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); -} diff --git a/src/lib/decoration.h b/src/lib/decoration.h index 624499c..92c8cf2 100644 --- a/src/lib/decoration.h +++ b/src/lib/decoration.h @@ -1,9 +1,22 @@ #ifndef CRYWL_DECORATION_H #define CRYWL_DECORATION_H -/* ===== Function Declarations ===== */ -static void createdecoration(struct wl_listener *listener, void *data); -static void destroydecoration(struct wl_listener *listener, void *data); -static void requestdecorationmode(struct wl_listener *listener, void *data); +#include + +#include "client.h" + +static inline void destroydecoration(struct wl_listener *listener, void *data) { + Client *c = wl_container_of(listener, c, destroy_decoration); + + wl_list_remove(&c->destroy_decoration.link); + wl_list_remove(&c->set_decoration_mode.link); +} + +static inline void requestdecorationmode(struct wl_listener *listener, void *data) { + Client *c = wl_container_of(listener, c, set_decoration_mode); + if (c->surface.xdg->initialized) + wlr_xdg_toplevel_decoration_v1_set_mode( + c->decoration, WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); +} #endif /* CRYWL_DECORATION_H */ diff --git a/src/lib/drag.h b/src/lib/drag.h deleted file mode 100644 index 5985e63..0000000 --- a/src/lib/drag.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef CRYWL_DRAG_H -#define CRYWL_DRAG_H - -/* ===== Function Declarations ===== */ -static void destroydragicon(struct wl_listener *listener, void *data); -static void requeststartdrag(struct wl_listener *listener, void *data); -static void startdrag(struct wl_listener *listener, void *data); - -#endif /* CRYWL_DRAG_H */ diff --git a/src/lib/input.c b/src/lib/input.c index 68d980f..71b2684 100644 --- a/src/lib/input.c +++ b/src/lib/input.c @@ -1,55 +1,16 @@ -void buttonpress(struct wl_listener *listener, void *data) { - struct wlr_pointer_button_event *event = data; - struct wlr_keyboard *keyboard; - uint32_t mods; - Client *c; - const Button *b; +#include +#include +#include +#include +#include +#include - wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); +#include "../util.h" +#include "input.h" - switch (event->state) { - case WL_POINTER_BUTTON_STATE_PRESSED: - cursor_mode = CurPressed; - selmon = xytomon(cursor->x, cursor->y); - if (locked) - break; - - /* Change focus if the button was _pressed_ over a client */ - xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); - if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) - focusclient(c, 1); - - keyboard = wlr_seat_get_keyboard(seat); - mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; - for (b = buttons; b < END(buttons); b++) { - if (CLEANMASK(mods) == CLEANMASK(b->mod) && event->button == b->button && - b->func) { - b->func(&b->arg); - return; - } - } - break; - case WL_POINTER_BUTTON_STATE_RELEASED: - /* If you released any buttons, we exit interactive move/resize mode. */ - /* TODO: should reset to the pointer focus's current setcursor */ - if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) { - wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); - cursor_mode = CurNormal; - /* Drop the window off on its new monitor */ - selmon = xytomon(cursor->x, cursor->y); - setmon(grabc, selmon, 0); - grabc = NULL; - return; - } - cursor_mode = CurNormal; - break; - } - /* If the event wasn't handled by the compositor, notify the client with - * pointer focus that a button press has occurred */ - wlr_seat_pointer_notify_button(seat, event->time_msec, event->button, - event->state); -} +static KeyboardGroup *kb_group; +/* ===== EVENTS ===== */ void createkeyboard(struct wlr_keyboard *keyboard) { /* Set the keymap to match the group keymap */ wlr_keyboard_set_keymap(keyboard, kb_group->wlr_group->keyboard.keymap); @@ -289,39 +250,6 @@ int keyrepeat(void *data) { return 0; } -void motionabsolute(struct wl_listener *listener, void *data) { - /* This event is forwarded by the cursor when a pointer emits an _absolute_ - * motion event, from 0..1 on each axis. This happens, for example, when - * wlroots is running under a Wayland window rather than KMS+DRM, and you - * move the mouse over the window. You could enter the window from any edge, - * so we have to warp the mouse there. Also, some hardware emits these events. - */ - struct wlr_pointer_motion_absolute_event *event = data; - double lx, ly, dx, dy; - - if (!event->time_msec) /* this is 0 with virtual pointers */ - wlr_cursor_warp_absolute(cursor, &event->pointer->base, event->x, event->y); - - wlr_cursor_absolute_to_layout_coords(cursor, &event->pointer->base, event->x, - event->y, &lx, &ly); - dx = lx - cursor->x; - dy = ly - cursor->y; - motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy); -} - -void motionrelative(struct wl_listener *listener, void *data) { - /* This event is forwarded by the cursor when a pointer emits a _relative_ - * pointer motion event (i.e. a delta) */ - struct wlr_pointer_motion_event *event = data; - /* The cursor doesn't move unless we tell it to. The cursor automatically - * handles constraining the motion to the output layout, as well as any - * special configuration applied for the specific input device which - * generated the event. You can pass NULL for the device if you want to move - * the cursor around without any input. */ - motionnotify(event->time_msec, &event->pointer->base, event->delta_x, - event->delta_y, event->unaccel_dx, event->unaccel_dy); -} - void moveresize(const Arg *arg) { if (cursor_mode != CurNormal && cursor_mode != CurPressed) return; @@ -372,25 +300,3 @@ void pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); } - -void virtualkeyboard(struct wl_listener *listener, void *data) { - struct wlr_virtual_keyboard_v1 *kb = data; - /* virtual keyboards shouldn't share keyboard group */ - KeyboardGroup *group = createkeyboardgroup(); - /* Set the keymap to match the group keymap */ - wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap); - LISTEN(&kb->keyboard.base.events.destroy, &group->destroy, - destroykeyboardgroup); - - /* Add the new keyboard to the group */ - wlr_keyboard_group_add_keyboard(group->wlr_group, &kb->keyboard); -} - -void virtualpointer(struct wl_listener *listener, void *data) { - struct wlr_virtual_pointer_v1_new_pointer_event *event = data; - struct wlr_input_device *device = &event->new_pointer->pointer.base; - - wlr_cursor_attach_input_device(cursor, device); - if (event->suggested_output) - wlr_cursor_map_input_to_output(cursor, device, event->suggested_output); -} diff --git a/src/lib/input.h b/src/lib/input.h index ff513c3..9c76b55 100644 --- a/src/lib/input.h +++ b/src/lib/input.h @@ -1,6 +1,13 @@ #ifndef CRYWL_INPUT_H #define CRYWL_INPUT_H +#include +#include +#include +#include + +#include "client.h" + typedef struct { unsigned int mod; unsigned int button; @@ -33,8 +40,11 @@ typedef struct { struct wl_listener destroy; } PointerConstraint; +/* ===== Event Handlers ===== */ +static void virtualkeyboard(struct wl_listener *listener, void *data); +static void virtualpointer(struct wl_listener *listener, void *data); + /* ===== Function Declarations ===== */ -static void buttonpress(struct wl_listener *listener, void *data); static void createkeyboard(struct wlr_keyboard *keyboard); static KeyboardGroup *createkeyboardgroup(void); static void createpointer(struct wlr_pointer *pointer); @@ -46,12 +56,8 @@ static int keybinding(uint32_t mods, xkb_keysym_t sym); static void keypress(struct wl_listener *listener, void *data); static void keypressmod(struct wl_listener *listener, void *data); static int keyrepeat(void *data); -static void motionabsolute(struct wl_listener *listener, void *data); -static void motionrelative(struct wl_listener *listener, void *data); static void moveresize(const Arg *arg); static void pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, uint32_t time); -static void virtualkeyboard(struct wl_listener *listener, void *data); -static void virtualpointer(struct wl_listener *listener, void *data); #endif /* CRYWL_INPUT_H */ diff --git a/src/lib/layers.c b/src/lib/layers.c index ddeb7f0..1f4308d 100644 --- a/src/lib/layers.c +++ b/src/lib/layers.c @@ -1,5 +1,71 @@ -#include "lib/layers.h" +#include "layers.h" +void commitlayersurfacenotify(struct wl_listener *listener, void *data) { + LayerSurface *l = wl_container_of(listener, l, surface_commit); + struct wlr_layer_surface_v1 *layer_surface = l->layer_surface; + struct wlr_scene_tree *scene_layer = + layers[layermap[layer_surface->current.layer]]; + struct wlr_layer_surface_v1_state old_state; + + if (l->layer_surface->initial_commit) { + client_set_scale(layer_surface->surface, l->mon->wlr_output->scale); + + /* Temporarily set the layer's current state to pending + * so that we can easily arrange it */ + old_state = l->layer_surface->current; + l->layer_surface->current = l->layer_surface->pending; + arrangelayers(l->mon); + l->layer_surface->current = old_state; + return; + } + + if (layer_surface->current.committed == 0 && + l->mapped == layer_surface->surface->mapped) + return; + l->mapped = layer_surface->surface->mapped; + + if (scene_layer != l->scene->node.parent) { + wlr_scene_node_reparent(&l->scene->node, scene_layer); + wl_list_remove(&l->link); + wl_list_insert(&l->mon->layers[layer_surface->current.layer], &l->link); + wlr_scene_node_reparent( + &l->popups->node, + (layer_surface->current.layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP + ? layers[LyrTop] + : scene_layer)); + } + + arrangelayers(l->mon); +} + +void unmaplayersurfacenotify(struct wl_listener *listener, void *data) { + LayerSurface *l = wl_container_of(listener, l, unmap); + + l->mapped = 0; + wlr_scene_node_set_enabled(&l->scene->node, 0); + if (l == exclusive_focus) + exclusive_focus = NULL; + if (l->layer_surface->output && (l->mon = l->layer_surface->output->data)) + arrangelayers(l->mon); + if (l->layer_surface->surface == seat->keyboard_state.focused_surface) + focusclient(focustop(selmon), 1); + motionnotify(0, NULL, 0, 0, 0, 0); +} + +void destroylayersurfacenotify(struct wl_listener *listener, void *data) { + LayerSurface *l = wl_container_of(listener, l, destroy); + + wl_list_remove(&l->link); + wl_list_remove(&l->destroy.link); + wl_list_remove(&l->unmap.link); + wl_list_remove(&l->surface_commit.link); + wlr_scene_node_destroy(&l->scene->node); + wlr_scene_node_destroy(&l->popups->node); + free(l); +} + +/* Binds commitlayersurfacenotify, unmaplayersurfacenotify, destroylayersurfacenotify + */ void createlayersurface(struct wl_listener *listener, void *data) { struct wlr_layer_surface_v1 *layer_surface = data; LayerSurface *l; @@ -34,3 +100,36 @@ void createlayersurface(struct wl_listener *listener, void *data) { wl_list_insert(&l->mon->layers[layer_surface->pending.layer], &l->link); wlr_surface_send_enter(surface, layer_surface->output); } + +void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, + LayerSurface **pl, double *nx, double *ny) { + struct wlr_scene_node *node, *pnode; + struct wlr_surface *surface = NULL; + Client *c = NULL; + LayerSurface *l = NULL; + int layer; + + for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) { + if (!(node = wlr_scene_node_at(&layers[layer]->node, x, y, nx, ny))) + continue; + + if (node->type == WLR_SCENE_NODE_BUFFER) + surface = + wlr_scene_surface_try_from_buffer(wlr_scene_buffer_from_node(node)) + ->surface; + /* Walk the tree to find a node that knows the client */ + for (pnode = node; pnode && !c; pnode = &pnode->parent->node) + c = pnode->data; + if (c && c->type == LayerShell) { + c = NULL; + l = pnode->data; + } + } + + if (psurface) + *psurface = surface; + if (pc) + *pc = c; + if (pl) + *pl = l; +} diff --git a/src/lib/layers.h b/src/lib/layers.h index f789804..b829a21 100644 --- a/src/lib/layers.h +++ b/src/lib/layers.h @@ -1,19 +1,7 @@ #ifndef CRYWL_LAYERS_H #define CRYWL_LAYERS_H -#include "lib/monitor.h" - -enum { - LyrBg, - LyrBottom, - LyrTile, - LyrFloat, - LyrTop, - LyrFS, - LyrOverlay, - LyrBlock, - NUM_LAYERS -}; /* scene layers */ +#include "monitor.h" typedef struct { /* Must keep this field first */ @@ -32,7 +20,14 @@ typedef struct { struct wl_listener surface_commit; } LayerSurface; -/* ===== Function Declarations ===== */ +/* ===== Event Handlers ===== */ +static void commitlayersurfacenotify(struct wl_listener *listener, void *data); +static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); +static void destroylayersurfacenotify(struct wl_listener *listener, void *data); +// createlayersurface uses the (commit|unmap|destroy)layersurfacenotify callbacks static void createlayersurface(struct wl_listener *listener, void *data); +void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + #endif /* CRYWL_LAYERS_H */ diff --git a/src/lib/macros.h b/src/lib/macros.h deleted file mode 100644 index a2d7e88..0000000 --- a/src/lib/macros.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef CRYWL_MACROS_H -#define CRYWL_MACROS_H - -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) -#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags])) -#define LENGTH(X) (sizeof X / sizeof X[0]) -#define END(A) ((A) + LENGTH(A)) -#define TAGMASK ((1u << TAGCOUNT) - 1) -#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) -#define LISTEN_STATIC(E, H) do { struct wl_listener *_l = ecalloc(1, sizeof(*_l)); _l->notify = (H); wl_signal_add((E), _l); } while (0) - -#endif /* CRYWL_MACROS_H */ diff --git a/src/lib/monitor.c b/src/lib/monitor.c index 18537d5..f65ac3b 100644 --- a/src/lib/monitor.c +++ b/src/lib/monitor.c @@ -1,4 +1,33 @@ -#include "lib/monitor.h" +#include "monitor.h" +#include "clientutil.h" + +void applyrules(Client *c) { + /* rule matching */ + const char *appid, *title; + uint32_t newtags = 0; + int i; + const Rule *r; + Monitor *mon = selmon, *m; + + appid = client_get_appid(c); + title = client_get_title(c); + + for (r = rules; r < END(rules); r++) { + if ((!r->title || strstr(title, r->title)) && + (!r->id || strstr(appid, r->id))) { + c->isfloating = r->isfloating; + newtags |= r->tags; + i = 0; + wl_list_for_each(m, &mons, link) { + if (r->monitor == i++) + mon = m; + } + } + } + + c->isfloating |= client_is_float_type(c); + setmon(c, mon, newtags); +} void arrange(Monitor *m) { Client *c; diff --git a/src/lib/monitor.h b/src/lib/monitor.h index 41327a3..0ac7041 100644 --- a/src/lib/monitor.h +++ b/src/lib/monitor.h @@ -1,7 +1,7 @@ #ifndef CRYWL_MONITOR_H #define CRYWL_MONITOR_H -#include "lib/client.h" +#include "client.h" // client.h contains a forward declaration of Monitor typedef struct { @@ -51,33 +51,31 @@ typedef struct { int monitor; } Rule; - -/* ===== Fucntion Declarations ===== */ -static void arrange(Monitor *m); -static void arrangelayer(Monitor *m, struct wl_list *list, - struct wlr_box *usable_area, int exclusive); -static void arrangelayers(Monitor *m); -static void cleanupmon(struct wl_listener *listener, void *data); -static void closemon(Monitor *m); -static void createmon(struct wl_listener *listener, void *data); -static Monitor *dirtomon(enum wlr_direction dir); -static void focusmon(const Arg *arg); -static void focusstack(const Arg *arg); -static Client *focustop(Monitor *m); -static void gpureset(struct wl_listener *listener, void *data); -static void incnmaster(const Arg *arg); -static void monocle(Monitor *m); -static void rendermon(struct wl_listener *listener, void *data); -static void requestmonstate(struct wl_listener *listener, void *data); -static void setlayout(const Arg *arg); -static void setmfact(const Arg *arg); -static void setmon(Client *c, Monitor *m, uint32_t newtags); -static void tag(const Arg *arg); -static void tagmon(const Arg *arg); -static void tile(Monitor *m); -static void updatemons(struct wl_listener *listener, void *data); -static Monitor *xytomon(double x, double y); - - +/* ===== Function Declarations ===== */ +void applyrules(Client *c); +void arrange(Monitor *m); +void arrangelayer(Monitor *m, struct wl_list *list, + struct wlr_box *usable_area, int exclusive); +void arrangelayers(Monitor *m); +void cleanupmon(struct wl_listener *listener, void *data); +void closemon(Monitor *m); +void createmon(struct wl_listener *listener, void *data); +Monitor *dirtomon(enum wlr_direction dir); +void focusmon(const Arg *arg); +void focusstack(const Arg *arg); +Client *focustop(Monitor *m); +void gpureset(struct wl_listener *listener, void *data); +void incnmaster(const Arg *arg); +void monocle(Monitor *m); +void rendermon(struct wl_listener *listener, void *data); +void requestmonstate(struct wl_listener *listener, void *data); +void setlayout(const Arg *arg); +void setmfact(const Arg *arg); +void setmon(Client *c, Monitor *m, uint32_t newtags); +void tag(const Arg *arg); +void tagmon(const Arg *arg); +void tile(Monitor *m); +void updatemons(struct wl_listener *listener, void *data); +Monitor *xytomon(double x, double y); #endif /* CRYWL_MONITOR_H */ diff --git a/src/lib/notify.c b/src/lib/notify.c index cd86f57..d22ac84 100644 --- a/src/lib/notify.c +++ b/src/lib/notify.c @@ -1,54 +1,3 @@ -void axisnotify(struct wl_listener *listener, void *data) { - /* This event is forwarded by the cursor when a pointer emits an axis event, - * for example when you move the scroll wheel. */ - struct wlr_pointer_axis_event *event = data; - wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); - /* TODO: allow usage of scroll wheel for mousebindings, it can be implemented - * by checking the event's orientation and the delta of the event */ - /* Notify the client with pointer focus of the axis event. */ - wlr_seat_pointer_notify_axis(seat, event->time_msec, event->orientation, - event->delta, event->delta_discrete, - event->source, event->relative_direction); -} - -void commitlayersurfacenotify(struct wl_listener *listener, void *data) { - LayerSurface *l = wl_container_of(listener, l, surface_commit); - struct wlr_layer_surface_v1 *layer_surface = l->layer_surface; - struct wlr_scene_tree *scene_layer = - layers[layermap[layer_surface->current.layer]]; - struct wlr_layer_surface_v1_state old_state; - - if (l->layer_surface->initial_commit) { - client_set_scale(layer_surface->surface, l->mon->wlr_output->scale); - - /* Temporarily set the layer's current state to pending - * so that we can easily arrange it */ - old_state = l->layer_surface->current; - l->layer_surface->current = l->layer_surface->pending; - arrangelayers(l->mon); - l->layer_surface->current = old_state; - return; - } - - if (layer_surface->current.committed == 0 && - l->mapped == layer_surface->surface->mapped) - return; - l->mapped = layer_surface->surface->mapped; - - if (scene_layer != l->scene->node.parent) { - wlr_scene_node_reparent(&l->scene->node, scene_layer); - wl_list_remove(&l->link); - wl_list_insert(&l->mon->layers[layer_surface->current.layer], &l->link); - wlr_scene_node_reparent( - &l->popups->node, - (layer_surface->current.layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP - ? layers[LyrTop] - : scene_layer)); - } - - arrangelayers(l->mon); -} - void commitnotify(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, commit); @@ -101,18 +50,6 @@ void createnotify(struct wl_listener *listener, void *data) { LISTEN(&toplevel->events.set_title, &c->set_title, updatetitle); } -void destroylayersurfacenotify(struct wl_listener *listener, void *data) { - LayerSurface *l = wl_container_of(listener, l, destroy); - - wl_list_remove(&l->link); - wl_list_remove(&l->destroy.link); - wl_list_remove(&l->unmap.link); - wl_list_remove(&l->surface_commit.link); - wlr_scene_node_destroy(&l->scene->node); - wlr_scene_node_destroy(&l->popups->node); - free(l); -} - void destroynotify(struct wl_listener *listener, void *data) { /* Called when the xdg_toplevel is destroyed. */ Client *c = wl_container_of(listener, c, destroy); @@ -316,20 +253,6 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx, pointerfocus(c, surface, sx, sy, time); } -void unmaplayersurfacenotify(struct wl_listener *listener, void *data) { - LayerSurface *l = wl_container_of(listener, l, unmap); - - l->mapped = 0; - wlr_scene_node_set_enabled(&l->scene->node, 0); - if (l == exclusive_focus) - exclusive_focus = NULL; - if (l->layer_surface->output && (l->mon = l->layer_surface->output->data)) - arrangelayers(l->mon); - if (l->layer_surface->surface == seat->keyboard_state.focused_surface) - focusclient(focustop(selmon), 1); - motionnotify(0, NULL, 0, 0, 0, 0); -} - void unmapnotify(struct wl_listener *listener, void *data) { /* Called when the surface is unmapped, and should no longer be shown. */ Client *c = wl_container_of(listener, c, unmap); diff --git a/src/lib/notify.h b/src/lib/notify.h index 64050fe..bf8b5ab 100644 --- a/src/lib/notify.h +++ b/src/lib/notify.h @@ -2,11 +2,8 @@ #define CRYWL_NOTIFY_H /* ===== Function Declarations ===== */ -static void axisnotify(struct wl_listener *listener, void *data); -static void commitlayersurfacenotify(struct wl_listener *listener, void *data); static void commitnotify(struct wl_listener *listener, void *data); static void createnotify(struct wl_listener *listener, void *data); -static void destroylayersurfacenotify(struct wl_listener *listener, void *data); static void destroynotify(struct wl_listener *listener, void *data); static void fullscreennotify(struct wl_listener *listener, void *data); static void mapnotify(struct wl_listener *listener, void *data); @@ -14,7 +11,6 @@ static void maximizenotify(struct wl_listener *listener, void *data); static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx, double sy, double sx_unaccel, double sy_unaccel); -static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); static void unmapnotify(struct wl_listener *listener, void *data); #endif /* CRYWL_NOTIFY_H */ diff --git a/src/listeners/decoration.h b/src/listeners/decoration.h new file mode 100644 index 0000000..fe4d827 --- /dev/null +++ b/src/listeners/decoration.h @@ -0,0 +1,18 @@ +#ifndef CRYWM_LSTN_DECORATION_H +#define CRYWM_LSTN_DECORATION_H + +#include "../lib/decoration.h" + +static void createdecoration(struct wl_listener *listener, void *data) { + struct wlr_xdg_toplevel_decoration_v1 *deco = data; + Client *c = deco->toplevel->base->data; + c->decoration = deco; + + LISTEN(&deco->events.request_mode, &c->set_decoration_mode, + requestdecorationmode); + LISTEN(&deco->events.destroy, &c->destroy_decoration, destroydecoration); + + requestdecorationmode(&c->set_decoration_mode, deco); +} + +#endif /* CRYWM_LSTN_DECORATION_H */ diff --git a/src/lib/drag.c b/src/listeners/drag.h similarity index 61% rename from src/lib/drag.c rename to src/listeners/drag.h index 5f96e60..980c0e7 100644 --- a/src/lib/drag.c +++ b/src/listeners/drag.h @@ -1,4 +1,11 @@ -void destroydragicon(struct wl_listener *listener, void *data) { +#ifndef CRYWL_LSTN_DRAG_H +#define CRYWL_LSTN_DRAG_H + +#include "../lib/clientutil.h" +#include "../lib/notify.h" + +/* Helper for the startdrag() listener */ +static void destroydragicon(struct wl_listener *listener, void *data) { /* Focus enter isn't sent during drag, so refocus the focused node. */ focusclient(focustop(selmon), 1); motionnotify(0, NULL, 0, 0, 0, 0); @@ -6,7 +13,9 @@ void destroydragicon(struct wl_listener *listener, void *data) { free(listener); } -void requeststartdrag(struct wl_listener *listener, void *data) { +/* ===== LISTENERS ===== */ + +static void requeststartdrag(struct wl_listener *listener, void *data) { struct wlr_seat_request_start_drag_event *event = data; if (wlr_seat_validate_pointer_grab_serial(seat, event->origin, event->serial)) @@ -15,7 +24,7 @@ void requeststartdrag(struct wl_listener *listener, void *data) { wlr_data_source_destroy(event->drag->source); } -void startdrag(struct wl_listener *listener, void *data) { +static void startdrag(struct wl_listener *listener, void *data) { struct wlr_drag *drag = data; if (!drag->icon) return; @@ -24,3 +33,4 @@ void startdrag(struct wl_listener *listener, void *data) { LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon); } +#endif /* CRYWL_LSTN_DRAG_H */ diff --git a/src/listeners/input.h b/src/listeners/input.h new file mode 100644 index 0000000..ead9b34 --- /dev/null +++ b/src/listeners/input.h @@ -0,0 +1,169 @@ +#ifndef CRYWL_LSTN_INPUT_H +#define CRYWL_LSTN_INPUT_H + +#include "../lib/clientutil.h" +#include "../lib/input.h" +#include "../lib/cursor.h" +#include "../lib/notify.h" + +static inline void axisnotify(struct wl_listener *listener, void *data) { + /* This event is forwarded by the cursor when a pointer emits an axis event, + * for example when you move the scroll wheel. */ + struct wlr_pointer_axis_event *event = data; + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + /* TODO: allow usage of scroll wheel for mousebindings, it can be implemented + * by checking the event's orientation and the delta of the event */ + /* Notify the client with pointer focus of the axis event. */ + wlr_seat_pointer_notify_axis(seat, event->time_msec, event->orientation, + event->delta, event->delta_discrete, + event->source, event->relative_direction); +} + +static inline void motionabsolute(struct wl_listener *listener, void *data) { + /* This event is forwarded by the cursor when a pointer emits an _absolute_ + * motion event, from 0..1 on each axis. This happens, for example, when + * wlroots is running under a Wayland window rather than KMS+DRM, and you + * move the mouse over the window. You could enter the window from any edge, + * so we have to warp the mouse there. Also, some hardware emits these events. + */ + struct wlr_pointer_motion_absolute_event *event = data; + double lx, ly, dx, dy; + + if (!event->time_msec) /* this is 0 with virtual pointers */ + wlr_cursor_warp_absolute(cursor, &event->pointer->base, event->x, event->y); + + wlr_cursor_absolute_to_layout_coords(cursor, &event->pointer->base, event->x, + event->y, &lx, &ly); + dx = lx - cursor->x; + dy = ly - cursor->y; + motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy); +} + +static inline void motionrelative(struct wl_listener *listener, void *data) { + /* This event is forwarded by the cursor when a pointer emits a _relative_ + * pointer motion event (i.e. a delta) */ + struct wlr_pointer_motion_event *event = data; + /* The cursor doesn't move unless we tell it to. The cursor automatically + * handles constraining the motion to the output layout, as well as any + * special configuration applied for the specific input device which + * generated the event. You can pass NULL for the device if you want to move + * the cursor around without any input. */ + motionnotify(event->time_msec, &event->pointer->base, event->delta_x, + event->delta_y, event->unaccel_dx, event->unaccel_dy); +} + +static inline void virtualkeyboard(struct wl_listener *listener, void *data) { + struct wlr_virtual_keyboard_v1 *kb = data; + /* virtual keyboards shouldn't share keyboard group */ + KeyboardGroup *group = createkeyboardgroup(); + /* Set the keymap to match the group keymap */ + wlr_keyboard_set_keymap(&kb->keyboard, group->wlr_group->keyboard.keymap); + LISTEN(&kb->keyboard.base.events.destroy, &group->destroy, + destroykeyboardgroup); + + /* Add the new keyboard to the group */ + wlr_keyboard_group_add_keyboard(group->wlr_group, &kb->keyboard); +} + +static inline void virtualpointer(struct wl_listener *listener, void *data) { + struct wlr_virtual_pointer_v1_new_pointer_event *event = data; + struct wlr_input_device *device = &event->new_pointer->pointer.base; + + wlr_cursor_attach_input_device(cursor, device); + if (event->suggested_output) + wlr_cursor_map_input_to_output(cursor, device, event->suggested_output); +} + + +static inline void buttonpress(struct wl_listener *listener, void *data) { + struct wlr_pointer_button_event *event = data; + struct wlr_keyboard *keyboard; + uint32_t mods; + Client *c; + const Button *b; + + wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + + switch (event->state) { + case WL_POINTER_BUTTON_STATE_PRESSED: + cursor_mode = CurPressed; + selmon = xytomon(cursor->x, cursor->y); + if (locked) + break; + + /* Change focus if the button was _pressed_ over a client */ + xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL); + if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) + focusclient(c, 1); + + keyboard = wlr_seat_get_keyboard(seat); + mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0; + for (b = buttons; b < END(buttons); b++) { + if (CLEANMASK(mods) == CLEANMASK(b->mod) && event->button == b->button && + b->func) { + b->func(&b->arg); + return; + } + } + break; + case WL_POINTER_BUTTON_STATE_RELEASED: + /* If you released any buttons, we exit interactive move/resize mode. */ + /* TODO: should reset to the pointer focus's current setcursor */ + if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) { + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); + cursor_mode = CurNormal; + /* Drop the window off on its new monitor */ + selmon = xytomon(cursor->x, cursor->y); + setmon(grabc, selmon, 0); + grabc = NULL; + return; + } + cursor_mode = CurNormal; + break; + } + /* If the event wasn't handled by the compositor, notify the client with + * pointer focus that a button press has occurred */ + wlr_seat_pointer_notify_button(seat, event->time_msec, event->button, + event->state); +} + +static inline void cursorframe(struct wl_listener *listener, void *data) { + /* This event is forwarded by the cursor when a pointer emits a frame + * event. Frame events are sent after regular pointer events to group + * multiple events together. For instance, two axis events may happen at the + * same time, in which case a frame event won't be sent in between. */ + /* Notify the client with pointer focus of the frame event. */ + wlr_seat_pointer_notify_frame(seat); +} + +static inline void setcursor(struct wl_listener *listener, void *data) { + /* This event is raised by the seat when a client provides a cursor image */ + struct wlr_seat_pointer_request_set_cursor_event *event = data; + /* If we're "grabbing" the cursor, don't use the client's image, we will + * restore it after "grabbing" sending a leave event, followed by a enter + * event, which will result in the client requesting set the cursor surface */ + if (cursor_mode != CurNormal && cursor_mode != CurPressed) + return; + /* This can be sent by any client, so we check to make sure this one + * actually has pointer focus first. If so, we can tell the cursor to + * use the provided surface as the cursor image. It will set the + * hardware cursor on the output that it's currently on and continue to + * do so as the cursor moves between outputs. */ + if (event->seat_client == seat->pointer_state.focused_client) + wlr_cursor_set_surface(cursor, event->surface, event->hotspot_x, + event->hotspot_y); +} + +static inline void setcursorshape(struct wl_listener *listener, void *data) { + struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data; + if (cursor_mode != CurNormal && cursor_mode != CurPressed) + return; + /* This can be sent by any client, so we check to make sure this one + * actually has pointer focus first. If so, we can tell the cursor to + * use the provided cursor shape. */ + if (event->seat_client == seat->pointer_state.focused_client) + wlr_cursor_set_xcursor(cursor, cursor_mgr, + wlr_cursor_shape_v1_name(event->shape)); +} + +#endif /* CRYWL_LSTN_INPUT_H */ diff --git a/src/listeners/listeners.h b/src/listeners/listeners.h new file mode 100644 index 0000000..96f7e61 --- /dev/null +++ b/src/listeners/listeners.h @@ -0,0 +1,23 @@ +#ifndef CRYWL_LSTN_ALL_H +#define CRYWL_LSTN_ALL_H + +#include "input.h" +#include "decoration.h" +#include "drag.h" + +static struct wl_listener cursor_button = {.notify = buttonpress}; +static struct wl_listener cursor_frame = {.notify = cursorframe}; +static struct wl_listener request_cursor = {.notify = setcursor}; +static struct wl_listener request_set_cursor_shape = {.notify = setcursorshape}; + +static struct wl_listener cursor_axis = {.notify = axisnotify}; +static struct wl_listener cursor_motion = {.notify = motionrelative}; +static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute}; +static struct wl_listener new_virtual_keyboard = {.notify = virtualkeyboard}; +static struct wl_listener new_virtual_pointer = {.notify = virtualpointer}; + +static struct wl_listener new_xdg_decoration = {.notify = createdecoration}; + +static struct wl_listener start_drag = {.notify = startdrag}; + +#endif /*CRYWL_LSTN_ALL_H*/ diff --git a/src/main.c b/src/main.c index 615e962..7d60559 100644 --- a/src/main.c +++ b/src/main.c @@ -69,64 +69,9 @@ #endif #include "util.h" -#include "lib/layers.h" - -/* variables */ -static int locked; -static void *exclusive_focus; -static struct wl_event_loop *event_loop; -static struct wlr_backend *backend; -static struct wlr_scene *scene; -static struct wlr_scene_tree *layers[NUM_LAYERS]; -static struct wlr_scene_tree *drag_icon; -/* Map from ZWLR_LAYER_SHELL_* constants to Lyr* enum */ -static const int layermap[] = {LyrBg, LyrBottom, LyrTop, LyrOverlay}; -static struct wlr_renderer *drw; -static struct wlr_allocator *alloc; -static struct wlr_compositor *compositor; -static struct wlr_session *session; - -static struct wlr_xdg_shell *xdg_shell; -static struct wlr_xdg_activation_v1 *activation; -static struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr; -static struct wl_list clients; /* tiling order */ -static struct wl_list fstack; /* focus order */ -static struct wlr_idle_notifier_v1 *idle_notifier; -static struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; -static struct wlr_layer_shell_v1 *layer_shell; -static struct wlr_output_manager_v1 *output_mgr; -static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; -static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; -static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; -static struct wlr_output_power_manager_v1 *power_mgr; - -static struct wlr_pointer_constraints_v1 *pointer_constraints; -static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr; -static struct wlr_pointer_constraint_v1 *active_constraint; - -static struct wlr_cursor *cursor; -static struct wlr_xcursor_manager *cursor_mgr; - -static struct wlr_scene_rect *root_bg; -static struct wlr_session_lock_manager_v1 *session_lock_mgr; -static struct wlr_scene_rect *locked_bg; -static struct wlr_session_lock_v1 *cur_lock; - -static struct wlr_seat *seat; -static KeyboardGroup *kb_group; -static unsigned int cursor_mode; -static Client *grabc; -static int grabcx, grabcy; /* client-relative */ - -static struct wlr_output_layout *output_layout; -static struct wlr_box sgeom; -static struct wl_list mons; -static Monitor *selmon; /* global event handlers */ static struct wl_listener cursor_axis = {.notify = axisnotify}; -static struct wl_listener cursor_button = {.notify = buttonpress}; -static struct wl_listener cursor_frame = {.notify = cursorframe}; static struct wl_listener cursor_motion = {.notify = motionrelative}; static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute}; static struct wl_listener gpu_reset = {.notify = gpureset}; @@ -140,27 +85,20 @@ static struct wl_listener new_pointer_constraint = { static struct wl_listener new_output = {.notify = createmon}; static struct wl_listener new_xdg_toplevel = {.notify = createnotify}; static struct wl_listener new_xdg_popup = {.notify = createpopup}; -static struct wl_listener new_xdg_decoration = {.notify = createdecoration}; static struct wl_listener new_layer_surface = {.notify = createlayersurface}; static struct wl_listener output_mgr_apply = {.notify = outputmgrapply}; static struct wl_listener output_mgr_test = {.notify = outputmgrtest}; static struct wl_listener output_power_mgr_set_mode = {.notify = powermgrsetmode}; static struct wl_listener request_activate = {.notify = urgent}; -static struct wl_listener request_cursor = {.notify = setcursor}; static struct wl_listener request_set_psel = {.notify = setpsel}; static struct wl_listener request_set_sel = {.notify = setsel}; -static struct wl_listener request_set_cursor_shape = {.notify = setcursorshape}; static struct wl_listener request_start_drag = {.notify = requeststartdrag}; -static struct wl_listener start_drag = {.notify = startdrag}; static struct wl_listener new_session_lock = {.notify = locksession}; /* configuration, allows nested code to access above variables */ #include "config.h" -/* attempt to encapsulate suck into one file */ -#include "client.h" - /* function implementations */ int main(int argc, char *argv[]) { char *startup_cmd = NULL; diff --git a/src/shared.c b/src/shared.c new file mode 100644 index 0000000..b8fe0a7 --- /dev/null +++ b/src/shared.c @@ -0,0 +1,53 @@ +#define IGNORE_EXTERNS +#include "shared.h" + +/* variables */ +int locked; +void *exclusive_focus; +struct wl_event_loop *event_loop; +struct wlr_backend *backend; +struct wlr_scene *scene; +struct wlr_scene_tree *layers[NUM_LAYERS]; +struct wlr_scene_tree *drag_icon; +/* Map from ZWLR_LAYER_SHELL_* constants to Lyr* enum */ +const int layermap[] = {LyrBg, LyrBottom, LyrTop, LyrOverlay}; +struct wlr_renderer *drw; +struct wlr_allocator *alloc; +struct wlr_compositor *compositor; +struct wlr_session *session; + +struct wlr_xdg_shell *xdg_shell; +struct wlr_xdg_activation_v1 *activation; +struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr; +struct wl_list clients; /* tiling order */ +struct wl_list fstack; /* focus order */ +struct wlr_idle_notifier_v1 *idle_notifier; +struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; +struct wlr_layer_shell_v1 *layer_shell; +struct wlr_output_manager_v1 *output_mgr; +struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; +struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; +struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; +struct wlr_output_power_manager_v1 *power_mgr; + +struct wlr_pointer_constraints_v1 *pointer_constraints; +struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr; +struct wlr_pointer_constraint_v1 *active_constraint; + +struct wlr_cursor *cursor; +struct wlr_xcursor_manager *cursor_mgr; + +struct wlr_scene_rect *root_bg; +struct wlr_session_lock_manager_v1 *session_lock_mgr; +struct wlr_scene_rect *locked_bg; +struct wlr_session_lock_v1 *cur_lock; + +struct wlr_seat *seat; +unsigned int cursor_mode; +Client *grabc; +int grabcx, grabcy; /* client-relative */ + +struct wlr_output_layout *output_layout; +struct wlr_box sgeom; +struct wl_list mons; +Monitor *selmon; diff --git a/src/shared.h b/src/shared.h new file mode 100644 index 0000000..584ce26 --- /dev/null +++ b/src/shared.h @@ -0,0 +1,67 @@ +#ifndef CRYWL_SHARED_H +#define CRYWL_SHARED_H + +enum { + LyrBg, + LyrBottom, + LyrTile, + LyrFloat, + LyrTop, + LyrFS, + LyrOverlay, + LyrBlock, + NUM_LAYERS +}; /* scene layers */ + +#ifndef IGNORE_EXTERNS +/* variables */ +extern int locked; +extern void *exclusive_focus; +extern struct wl_event_loop *event_loop; +extern struct wlr_backend *backend; +extern struct wlr_scene *scene; +extern struct wlr_scene_tree *layers[NUM_LAYERS]; +extern struct wlr_scene_tree *drag_icon; +/* Map from ZWLR_LAYER_SHELL_* constants to Lyr* enum */ +extern const int layermap[]; +extern struct wlr_renderer *drw; +extern struct wlr_allocator *alloc; +extern struct wlr_compositor *compositor; +extern struct wlr_session *session; + +extern struct wlr_xdg_shell *xdg_shell; +extern struct wlr_xdg_activation_v1 *activation; +extern struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr; +extern struct wl_list clients; /* tiling order */ +extern struct wl_list fstack; /* focus order */ +extern struct wlr_idle_notifier_v1 *idle_notifier; +extern struct wlr_idle_inhibit_manager_v1 *idle_inhibit_mgr; +extern struct wlr_layer_shell_v1 *layer_shell; +extern struct wlr_output_manager_v1 *output_mgr; +extern struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr; +extern struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr; +extern struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr; +extern struct wlr_output_power_manager_v1 *power_mgr; + +extern struct wlr_pointer_constraints_v1 *pointer_constraints; +extern struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr; + +extern struct wlr_xcursor_manager *cursor_mgr; + +extern struct wlr_scene_rect *root_bg; +extern struct wlr_session_lock_manager_v1 *session_lock_mgr; +extern struct wlr_scene_rect *locked_bg; +extern struct wlr_session_lock_v1 *cur_lock; + +extern struct wlr_seat *seat; +extern unsigned int cursor_mode; +extern Client *grabc; +extern int grabcx, grabcy; /* client-relative */ + +extern struct wlr_output_layout *output_layout; +extern struct wlr_box sgeom; +extern struct wl_list mons; +extern Monitor *selmon; +#endif /* IGNORE_EXTERNS */ + +#endif /* CRYWL_SHARED_H */ diff --git a/src/wayland.h b/src/wayland.h new file mode 100644 index 0000000..514002e --- /dev/null +++ b/src/wayland.h @@ -0,0 +1,63 @@ +#ifndef CRYWL_WL_LINK +#define CRYWL_WL_LINK + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef XWAYLAND +#include +#include +#include +#endif /* XWAYLAND */ + +#endif /* CRYWL_WL_LINK */ +