diff --git a/src/lib/client.c b/src/lib/client.c index 25245e8..e78915e 100644 --- a/src/lib/client.c +++ b/src/lib/client.c @@ -1,3 +1,7 @@ +#include +#include + + #include "client.h" void applybounds(Client *c, struct wlr_box *bbox) { @@ -225,20 +229,6 @@ void updatetitle(struct wl_listener *listener, void *data) { printstatus(); } -void urgent(struct wl_listener *listener, void *data) { - struct wlr_xdg_activation_v1_request_activate_event *event = data; - Client *c = NULL; - toplevel_from_wlr_surface(event->surface, &c, NULL); - if (!c || c == focustop(selmon)) - return; - - c->isurgent = 1; - printstatus(); - - if (client_surface(c)->mapped) - client_set_border_color(c, urgentcolor); -} - void view(const Arg *arg) { if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) return; diff --git a/src/lib/client.h b/src/lib/client.h index 8b5beff..47b1127 100644 --- a/src/lib/client.h +++ b/src/lib/client.h @@ -7,7 +7,8 @@ #ifndef CRYWL_CLIENT_H #define CRYWL_CLIENT_H -#include "../wayland.h" +#include + #include "../util.h" enum { XDGShell, LayerShell, X11 }; /* client types */ @@ -61,14 +62,11 @@ 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); diff --git a/src/lib/crywl.c b/src/lib/crywl.c index 0cd387c..ca83e21 100644 --- a/src/lib/crywl.c +++ b/src/lib/crywl.c @@ -305,42 +305,6 @@ void handlesig(int signo) { quit(NULL); } -void printstatus(void) { - Monitor *m = NULL; - Client *c; - uint32_t occ, urg, sel; - - wl_list_for_each(m, &mons, link) { - occ = urg = 0; - wl_list_for_each(c, &clients, link) { - if (c->mon != m) - continue; - occ |= c->tags; - if (c->isurgent) - urg |= c->tags; - } - if ((c = focustop(m))) { - printf("%s title %s\n", m->wlr_output->name, client_get_title(c)); - printf("%s appid %s\n", m->wlr_output->name, client_get_appid(c)); - printf("%s fullscreen %d\n", m->wlr_output->name, c->isfullscreen); - printf("%s floating %d\n", m->wlr_output->name, c->isfloating); - sel = c->tags; - } else { - printf("%s title \n", m->wlr_output->name); - printf("%s appid \n", m->wlr_output->name); - printf("%s fullscreen \n", m->wlr_output->name); - printf("%s floating \n", m->wlr_output->name); - sel = 0; - } - - printf("%s selmon %u\n", m->wlr_output->name, m == selmon); - printf("%s tags %" PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32 "\n", - m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg); - printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol); - } - fflush(stdout); -} - void run(char *startup_cmd) { /* Add a Unix socket to the Wayland display. */ const char *socket = wl_display_add_socket_auto(dpy); diff --git a/src/lib/cursor.c b/src/lib/cursor.c index fad876b..0ae09cb 100644 --- a/src/lib/cursor.c +++ b/src/lib/cursor.c @@ -1,5 +1,7 @@ #include +#include + #include "cursor.h" #include "clientutil.h" diff --git a/src/lib/idle.c b/src/lib/idle.c index 580518f..8ca9a1f 100644 --- a/src/lib/idle.c +++ b/src/lib/idle.c @@ -1,3 +1,10 @@ +#include + +#include +#include +#include +#include + void checkidleinhibitor(struct wlr_surface *exclude) { int inhibited = 0, unused_lx, unused_ly; struct wlr_idle_inhibitor_v1 *inhibitor; @@ -17,13 +24,7 @@ void checkidleinhibitor(struct wlr_surface *exclude) { wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited); } -void createidleinhibitor(struct wl_listener *listener, void *data) { - struct wlr_idle_inhibitor_v1 *idle_inhibitor = data; - LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor); - - checkidleinhibitor(NULL); -} - +/* Helper listener used by `listeners/idle.h:createidleinhibitor` */ void destroyidleinhibitor(struct wl_listener *listener, void *data) { /* `data` is the wlr_surface of the idle inhibitor being destroyed, * at this point the idle inhibitor is still in the list of the manager */ diff --git a/src/lib/idle.h b/src/lib/idle.h index 0ad1995..1b5023c 100644 --- a/src/lib/idle.h +++ b/src/lib/idle.h @@ -1,9 +1,11 @@ #ifndef CRYWL_IDLE_H #define CRYWL_IDLE_H +#include +#include + /* ===== Function Declarations ===== */ -static void checkidleinhibitor(struct wlr_surface *exclude); -static void createidleinhibitor(struct wl_listener *listener, void *data); -static void destroyidleinhibitor(struct wl_listener *listener, void *data); +void checkidleinhibitor(struct wlr_surface *exclude); +void destroyidleinhibitor(struct wl_listener *listener, void *data); #endif /* CRYWL_IDLE_H */ diff --git a/src/lib/input.c b/src/lib/input.c index 71b2684..be6a083 100644 --- a/src/lib/input.c +++ b/src/lib/input.c @@ -65,14 +65,6 @@ void createpointer(struct wlr_pointer *pointer) { wlr_cursor_attach_input_device(cursor, &pointer->base); } -void createpointerconstraint(struct wl_listener *listener, void *data) { - PointerConstraint *pointer_constraint = - ecalloc(1, sizeof(*pointer_constraint)); - pointer_constraint->constraint = data; - LISTEN(&pointer_constraint->constraint->events.destroy, - &pointer_constraint->destroy, destroypointerconstraint); -} - KeyboardGroup *createkeyboardgroup(void) { KeyboardGroup *group = ecalloc(1, sizeof(*group)); struct xkb_context *context; @@ -134,34 +126,6 @@ void destroykeyboardgroup(struct wl_listener *listener, void *data) { free(group); } -void inputdevice(struct wl_listener *listener, void *data) { - /* This event is raised by the backend when a new input device becomes - * available. */ - struct wlr_input_device *device = data; - uint32_t caps; - - switch (device->type) { - case WLR_INPUT_DEVICE_KEYBOARD: - createkeyboard(wlr_keyboard_from_input_device(device)); - break; - case WLR_INPUT_DEVICE_POINTER: - createpointer(wlr_pointer_from_input_device(device)); - break; - default: - /* TODO handle other input device types */ - break; - } - - /* We need to let the wlr_seat know what our capabilities are, which is - * communiciated to the client. In dwl we always have a cursor, even if - * there are no pointer devices, so we always include that capability. */ - /* TODO do we actually require a cursor? */ - caps = WL_SEAT_CAPABILITY_POINTER; - if (!wl_list_empty(&kb_group->wlr_group->devices)) - caps |= WL_SEAT_CAPABILITY_KEYBOARD; - wlr_seat_set_capabilities(seat, caps); -} - int keybinding(uint32_t mods, xkb_keysym_t sym) { /* * Here we handle compositor keybindings. This is when the compositor is diff --git a/src/lib/input.h b/src/lib/input.h index 9c76b55..3ba7332 100644 --- a/src/lib/input.h +++ b/src/lib/input.h @@ -40,18 +40,12 @@ 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 createkeyboard(struct wlr_keyboard *keyboard); static KeyboardGroup *createkeyboardgroup(void); static void createpointer(struct wlr_pointer *pointer); -static void createpointerconstraint(struct wl_listener *listener, void *data); static void destroypointerconstraint(struct wl_listener *listener, void *data); static void destroykeyboardgroup(struct wl_listener *listener, void *data); -static void inputdevice(struct wl_listener *listener, void *data); 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); diff --git a/src/lib/layers.c b/src/lib/layers.c index 1f4308d..89d1ceb 100644 --- a/src/lib/layers.c +++ b/src/lib/layers.c @@ -1,4 +1,9 @@ +#include +#include + #include "layers.h" +#include "notify.h" +#include "clientutil.h" void commitlayersurfacenotify(struct wl_listener *listener, void *data) { LayerSurface *l = wl_container_of(listener, l, surface_commit); @@ -64,43 +69,6 @@ void destroylayersurfacenotify(struct wl_listener *listener, void *data) { free(l); } -/* Binds commitlayersurfacenotify, unmaplayersurfacenotify, destroylayersurfacenotify - */ -void createlayersurface(struct wl_listener *listener, void *data) { - struct wlr_layer_surface_v1 *layer_surface = data; - LayerSurface *l; - struct wlr_surface *surface = layer_surface->surface; - struct wlr_scene_tree *scene_layer = - layers[layermap[layer_surface->pending.layer]]; - - if (!layer_surface->output && - !(layer_surface->output = selmon ? selmon->wlr_output : NULL)) { - wlr_layer_surface_v1_destroy(layer_surface); - return; - } - - l = layer_surface->data = ecalloc(1, sizeof(*l)); - l->type = LayerShell; - LISTEN(&surface->events.commit, &l->surface_commit, commitlayersurfacenotify); - LISTEN(&surface->events.unmap, &l->unmap, unmaplayersurfacenotify); - LISTEN(&layer_surface->events.destroy, &l->destroy, - destroylayersurfacenotify); - - l->layer_surface = layer_surface; - l->mon = layer_surface->output->data; - l->scene_layer = - wlr_scene_layer_surface_v1_create(scene_layer, layer_surface); - l->scene = l->scene_layer->tree; - l->popups = surface->data = wlr_scene_tree_create( - layer_surface->current.layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP - ? layers[LyrTop] - : scene_layer); - l->scene->node.data = l->popups->node.data = l; - - 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; diff --git a/src/lib/layers.h b/src/lib/layers.h index b829a21..afddfce 100644 --- a/src/lib/layers.h +++ b/src/lib/layers.h @@ -24,8 +24,6 @@ typedef struct { 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); diff --git a/src/lib/lock.c b/src/lib/lock.c index b2ee98e..16333eb 100644 --- a/src/lib/lock.c +++ b/src/lib/lock.c @@ -1,3 +1,15 @@ +#include + +#include +#include +#include +#include + +#include "clientutil.h" +#include "lock.h" +#include "monitor.h" +#include "notify.h" + void createlocksurface(struct wl_listener *listener, void *data) { SessionLock *lock = wl_container_of(listener, lock, new_surface); struct wlr_session_lock_surface_v1 *lock_surface = data; @@ -61,29 +73,6 @@ void destroysessionlock(struct wl_listener *listener, void *data) { destroylock(lock, 0); } -void locksession(struct wl_listener *listener, void *data) { - struct wlr_session_lock_v1 *session_lock = data; - SessionLock *lock; - wlr_scene_node_set_enabled(&locked_bg->node, 1); - if (cur_lock) { - wlr_session_lock_v1_destroy(session_lock); - return; - } - lock = session_lock->data = ecalloc(1, sizeof(*lock)); - focusclient(NULL, 0); - - lock->scene = wlr_scene_tree_create(layers[LyrBlock]); - cur_lock = lock->lock = session_lock; - locked = 1; - - LISTEN(&session_lock->events.new_surface, &lock->new_surface, - createlocksurface); - LISTEN(&session_lock->events.destroy, &lock->destroy, destroysessionlock); - LISTEN(&session_lock->events.unlock, &lock->unlock, unlocksession); - - wlr_session_lock_v1_send_locked(session_lock); -} - void unlocksession(struct wl_listener *listener, void *data) { SessionLock *lock = wl_container_of(listener, lock, unlock); destroylock(lock, 1); diff --git a/src/lib/lock.h b/src/lib/lock.h index 9407bae..5adc9f6 100644 --- a/src/lib/lock.h +++ b/src/lib/lock.h @@ -1,6 +1,8 @@ #ifndef CRYWL_LOCK_H #define CRYWL_LOCK_H +#include + typedef struct { struct wlr_scene_tree *scene; @@ -15,7 +17,6 @@ static void createlocksurface(struct wl_listener *listener, void *data); static void destroylock(SessionLock *lock, int unlocked); static void destroylocksurface(struct wl_listener *listener, void *data); static void destroysessionlock(struct wl_listener *listener, void *data); -static void locksession(struct wl_listener *listener, void *data); static void unlocksession(struct wl_listener *listener, void *data); #endif /* CRYWL_LOCK_H */ diff --git a/src/lib/logging.c b/src/lib/logging.c new file mode 100644 index 0000000..3e3daf4 --- /dev/null +++ b/src/lib/logging.c @@ -0,0 +1,44 @@ +#include + +#include +#include + +#include "monitor.h" +#include "clientutil.h" + +void printstatus(void) { + Monitor *m = NULL; + Client *c; + uint32_t occ, urg, sel; + + wl_list_for_each(m, &mons, link) { + occ = urg = 0; + wl_list_for_each(c, &clients, link) { + if (c->mon != m) + continue; + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; + } + if ((c = focustop(m))) { + printf("%s title %s\n", m->wlr_output->name, client_get_title(c)); + printf("%s appid %s\n", m->wlr_output->name, client_get_appid(c)); + printf("%s fullscreen %d\n", m->wlr_output->name, c->isfullscreen); + printf("%s floating %d\n", m->wlr_output->name, c->isfloating); + sel = c->tags; + } else { + printf("%s title \n", m->wlr_output->name); + printf("%s appid \n", m->wlr_output->name); + printf("%s fullscreen \n", m->wlr_output->name); + printf("%s floating \n", m->wlr_output->name); + sel = 0; + } + + printf("%s selmon %u\n", m->wlr_output->name, m == selmon); + printf("%s tags %" PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32 "\n", + m->wlr_output->name, occ, m->tagset[m->seltags], sel, urg); + printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol); + } + fflush(stdout); +} + diff --git a/src/lib/logging.h b/src/lib/logging.h new file mode 100644 index 0000000..fabcc97 --- /dev/null +++ b/src/lib/logging.h @@ -0,0 +1,8 @@ +#ifndef CRYWL_LOGGING_H +#define CRYWL_LOGGING_H + +/* ===== Functional Declarations ===== */ +static void printstatus(void); + +#endif /* CRYWL_LOGGING_H */ + diff --git a/src/lib/mgrs.h b/src/lib/mgrs.h deleted file mode 100644 index 3b28625..0000000 --- a/src/lib/mgrs.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef CRYWL_MGRS_H -#define CRYWL_MGRS_H - -/* ===== Function Declarations ===== */ -static void outputmgrapply(struct wl_listener *listener, void *data); -static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, - int test); -static void outputmgrtest(struct wl_listener *listener, void *data); -static void powermgrsetmode(struct wl_listener *listener, void *data); - -#endif /* CRYWL_MGRS_H */ diff --git a/src/lib/monitor.c b/src/lib/monitor.c index f65ac3b..336f255 100644 --- a/src/lib/monitor.c +++ b/src/lib/monitor.c @@ -1,3 +1,7 @@ +#include + +#include + #include "monitor.h" #include "clientutil.h" @@ -184,84 +188,6 @@ void closemon(Monitor *m) { printstatus(); } -void createmon(struct wl_listener *listener, void *data) { - /* This event is raised by the backend when a new output (aka a display or - * monitor) becomes available. */ - struct wlr_output *wlr_output = data; - const MonitorRule *r; - size_t i; - struct wlr_output_state state; - Monitor *m; - - if (!wlr_output_init_render(wlr_output, alloc, drw)) - return; - - m = wlr_output->data = ecalloc(1, sizeof(*m)); - m->wlr_output = wlr_output; - - for (i = 0; i < LENGTH(m->layers); i++) - wl_list_init(&m->layers[i]); - - wlr_output_state_init(&state); - /* Initialize monitor state using configured rules */ - m->tagset[0] = m->tagset[1] = 1; - for (r = monrules; r < END(monrules); r++) { - if (!r->name || strstr(wlr_output->name, r->name)) { - m->m.x = r->x; - m->m.y = r->y; - m->mfact = r->mfact; - m->nmaster = r->nmaster; - m->lt[0] = r->lt; - m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]]; - strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); - wlr_output_state_set_scale(&state, r->scale); - wlr_output_state_set_transform(&state, r->rr); - break; - } - } - - /* The mode is a tuple of (width, height, refresh rate), and each - * monitor supports only a specific set of modes. We just pick the - * monitor's preferred mode; a more sophisticated compositor would let - * the user configure it. */ - wlr_output_state_set_mode(&state, wlr_output_preferred_mode(wlr_output)); - - /* Set up event listeners */ - LISTEN(&wlr_output->events.frame, &m->frame, rendermon); - LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon); - LISTEN(&wlr_output->events.request_state, &m->request_state, requestmonstate); - - wlr_output_state_set_enabled(&state, 1); - wlr_output_commit_state(wlr_output, &state); - wlr_output_state_finish(&state); - - wl_list_insert(&mons, &m->link); - printstatus(); - - /* The xdg-protocol specifies: - * - * If the fullscreened surface is not opaque, the compositor must make - * sure that other screen content not part of the same surface tree (made - * up of subsurfaces, popups or similarly coupled surfaces) are not - * visible below the fullscreened surface. - * - */ - /* updatemons() will resize and set correct position */ - m->fullscreen_bg = wlr_scene_rect_create(layers[LyrFS], 0, 0, fullscreen_bg); - wlr_scene_node_set_enabled(&m->fullscreen_bg->node, 0); - - /* Adds this to the output layout in the order it was configured. - * - * The output layout utility automatically adds a wl_output global to the - * display, which Wayland clients can see to find out information about the - * output (such as DPI, scale factor, manufacturer, etc). - */ - m->scene_output = wlr_scene_output_create(scene, wlr_output); - if (m->m.x == -1 && m->m.y == -1) - wlr_output_layout_add_auto(output_layout, wlr_output); - else - wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y); -} Monitor *dirtomon(enum wlr_direction dir) { struct wlr_output *next; @@ -323,29 +249,6 @@ Client *focustop(Monitor *m) { return NULL; } -void gpureset(struct wl_listener *listener, void *data) { - struct wlr_renderer *old_drw = drw; - struct wlr_allocator *old_alloc = alloc; - struct Monitor *m; - if (!(drw = wlr_renderer_autocreate(backend))) - die("couldn't recreate renderer"); - - if (!(alloc = wlr_allocator_autocreate(backend, drw))) - die("couldn't recreate allocator"); - - wl_list_remove(&gpu_reset.link); - wl_signal_add(&drw->events.lost, &gpu_reset); - - wlr_compositor_set_renderer(compositor, drw); - - wl_list_for_each(m, &mons, link) { - wlr_output_init_render(m->wlr_output, alloc, drw); - } - - wlr_allocator_destroy(old_alloc); - wlr_renderer_destroy(old_drw); -} - void incnmaster(const Arg *arg) { if (!arg || !selmon) return; @@ -394,12 +297,6 @@ skip: wlr_output_state_finish(&pending); } -void requestmonstate(struct wl_listener *listener, void *data) { - struct wlr_output_event_request_state *event = data; - wlr_output_commit_state(event->output, event->state); - updatemons(NULL, NULL); -} - void setlayout(const Arg *arg) { if (!selmon) return; @@ -506,113 +403,6 @@ void tile(Monitor *m) { } } -void updatemons(struct wl_listener *listener, void *data) { - /* - * Called whenever the output layout changes: adding or removing a - * monitor, changing an output's mode or position, etc. This is where - * the change officially happens and we update geometry, window - * positions, focus, and the stored configuration in wlroots' - * output-manager implementation. - */ - struct wlr_output_configuration_v1 *config = - wlr_output_configuration_v1_create(); - Client *c; - struct wlr_output_configuration_head_v1 *config_head; - Monitor *m; - - /* First remove from the layout the disabled monitors */ - wl_list_for_each(m, &mons, link) { - if (m->wlr_output->enabled || m->asleep) - continue; - config_head = - wlr_output_configuration_head_v1_create(config, m->wlr_output); - config_head->state.enabled = 0; - /* Remove this output from the layout to avoid cursor enter inside it */ - wlr_output_layout_remove(output_layout, m->wlr_output); - closemon(m); - m->m = m->w = (struct wlr_box){0}; - } - /* Insert outputs that need to */ - wl_list_for_each(m, &mons, link) { - if (m->wlr_output->enabled && - !wlr_output_layout_get(output_layout, m->wlr_output)) - wlr_output_layout_add_auto(output_layout, m->wlr_output); - } - - /* Now that we update the output layout we can get its box */ - wlr_output_layout_get_box(output_layout, NULL, &sgeom); - - wlr_scene_node_set_position(&root_bg->node, sgeom.x, sgeom.y); - wlr_scene_rect_set_size(root_bg, sgeom.width, sgeom.height); - - /* Make sure the clients are hidden when dwl is locked */ - wlr_scene_node_set_position(&locked_bg->node, sgeom.x, sgeom.y); - wlr_scene_rect_set_size(locked_bg, sgeom.width, sgeom.height); - - wl_list_for_each(m, &mons, link) { - if (!m->wlr_output->enabled) - continue; - config_head = - wlr_output_configuration_head_v1_create(config, m->wlr_output); - - /* Get the effective monitor geometry to use for surfaces */ - wlr_output_layout_get_box(output_layout, m->wlr_output, &m->m); - m->w = m->m; - wlr_scene_output_set_position(m->scene_output, m->m.x, m->m.y); - - wlr_scene_node_set_position(&m->fullscreen_bg->node, m->m.x, m->m.y); - wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height); - - if (m->lock_surface) { - struct wlr_scene_tree *scene_tree = m->lock_surface->surface->data; - wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y); - wlr_session_lock_surface_v1_configure(m->lock_surface, m->m.width, - m->m.height); - } - - /* Calculate the effective monitor geometry to use for clients */ - arrangelayers(m); - /* Don't move clients to the left output when plugging monitors */ - arrange(m); - /* make sure fullscreen clients have the right size */ - if ((c = focustop(m)) && c->isfullscreen) - resize(c, m->m, 0); - - /* Try to re-set the gamma LUT when updating monitors, - * it's only really needed when enabling a disabled output, but meh. */ - m->gamma_lut_changed = 1; - - config_head->state.x = m->m.x; - config_head->state.y = m->m.y; - - if (!selmon) { - selmon = m; - } - } - - if (selmon && selmon->wlr_output->enabled) { - wl_list_for_each(c, &clients, link) { - if (!c->mon && client_surface(c)->mapped) - setmon(c, selmon, c->tags); - } - focusclient(focustop(selmon), 1); - if (selmon->lock_surface) { - client_notify_enter(selmon->lock_surface->surface, - wlr_seat_get_keyboard(seat)); - client_activate_surface(selmon->lock_surface->surface, 1); - } - } - - /* FIXME: figure out why the cursor image is at 0,0 after turning all - * the monitors on. - * Move the cursor image where it used to be. It does not generate a - * wl_pointer.motion event for the clients, it's only the image what it's - * at the wrong position after all. */ - wlr_cursor_move(cursor, NULL, 0, 0); - - wlr_output_manager_v1_set_configuration(output_mgr, config); -} - Monitor *xytomon(double x, double y) { struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y); return o ? o->data : NULL; diff --git a/src/lib/monitor.h b/src/lib/monitor.h index 0ac7041..41ceb59 100644 --- a/src/lib/monitor.h +++ b/src/lib/monitor.h @@ -59,23 +59,19 @@ void arrangelayer(Monitor *m, struct wl_list *list, 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 d22ac84..9428e54 100644 --- a/src/lib/notify.c +++ b/src/lib/notify.c @@ -29,27 +29,6 @@ void commitnotify(struct wl_listener *listener, void *data) { c->resize = 0; } -void createnotify(struct wl_listener *listener, void *data) { - /* This event is raised when a client creates a new toplevel (application - * window). */ - struct wlr_xdg_toplevel *toplevel = data; - Client *c = NULL; - - /* Allocate a Client for this surface */ - c = toplevel->base->data = ecalloc(1, sizeof(*c)); - c->surface.xdg = toplevel->base; - c->bw = borderpx; - - LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); - LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); - LISTEN(&toplevel->base->surface->events.unmap, &c->unmap, unmapnotify); - LISTEN(&toplevel->events.destroy, &c->destroy, destroynotify); - LISTEN(&toplevel->events.request_fullscreen, &c->fullscreen, - fullscreennotify); - LISTEN(&toplevel->events.request_maximize, &c->maximize, maximizenotify); - LISTEN(&toplevel->events.set_title, &c->set_title, updatetitle); -} - void destroynotify(struct wl_listener *listener, void *data) { /* Called when the xdg_toplevel is destroyed. */ Client *c = wl_container_of(listener, c, destroy); diff --git a/src/lib/notify.h b/src/lib/notify.h index bf8b5ab..d1c3a81 100644 --- a/src/lib/notify.h +++ b/src/lib/notify.h @@ -3,7 +3,6 @@ /* ===== Function Declarations ===== */ static void commitnotify(struct wl_listener *listener, void *data); -static void createnotify(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); diff --git a/src/lib/popup.h b/src/lib/popup.h deleted file mode 100644 index 2d17d5e..0000000 --- a/src/lib/popup.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CRYWL_POPUP_H -#define CRYWL_POPUP_H - -/* ===== Function Declarations ===== */ -static void commitpopup(struct wl_listener *listener, void *data); -static void createpopup(struct wl_listener *listener, void *data); - -#endif /* CRYWL_POPUP_H */ diff --git a/src/listeners/client.h b/src/listeners/client.h new file mode 100644 index 0000000..2b9da35 --- /dev/null +++ b/src/listeners/client.h @@ -0,0 +1,44 @@ +#ifndef CRYWL_LSTN_CLIENT_H +#define CRYWL_LSTN_CLIENT_H + +#include +#include +#include +#include +#include + +#include "../lib/clientutil.h" + +/* This event is raised by the seat when a client wants to set the selection, + * usually when the user copies something. wlroots allows compositors to + * ignore such requests if they so choose, but in dwl we always honor them + */ +static void setpsel(struct wl_listener *listener, void *data) { + struct wlr_seat_request_set_primary_selection_event *event = data; + wlr_seat_set_primary_selection(seat, event->source, event->serial); +} + +/* This event is raised by the seat when a client wants to set the selection, + * usually when the user copies something. wlroots allows compositors to + * ignore such requests if they so choose, but in dwl we always honor them + */ +static void setsel(struct wl_listener *listener, void *data) { + struct wlr_seat_request_set_selection_event *event = data; + wlr_seat_set_selection(seat, event->source, event->serial); +} + +static void urgent(struct wl_listener *listener, void *data) { + struct wlr_xdg_activation_v1_request_activate_event *event = data; + Client *c = NULL; + toplevel_from_wlr_surface(event->surface, &c, NULL); + if (!c || c == focustop(selmon)) + return; + + c->isurgent = 1; + printstatus(); + + if (client_surface(c)->mapped) + client_set_border_color(c, urgentcolor); +} + +#endif /* CRYWL_LSTN_CLIENT_H */ diff --git a/src/listeners/idle.h b/src/listeners/idle.h new file mode 100644 index 0000000..805ff39 --- /dev/null +++ b/src/listeners/idle.h @@ -0,0 +1,16 @@ +#ifndef CRYWL_LSTN_IDLE_H +#define CRYWL_LSTN_IDLE_H + +#include + +#include "../util.h" +#include "../lib/idle.h" + +static void createidleinhibitor(struct wl_listener *listener, void *data) { + struct wlr_idle_inhibitor_v1 *idle_inhibitor = data; + LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor); + + checkidleinhibitor(NULL); +} + +#endif /* CRYWL_LSTN_IDLE_H */ diff --git a/src/listeners/input.h b/src/listeners/input.h index ead9b34..57add42 100644 --- a/src/listeners/input.h +++ b/src/listeners/input.h @@ -6,7 +6,7 @@ #include "../lib/cursor.h" #include "../lib/notify.h" -static inline void axisnotify(struct wl_listener *listener, void *data) { +static 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; @@ -19,7 +19,7 @@ static inline void axisnotify(struct wl_listener *listener, void *data) { event->source, event->relative_direction); } -static inline void motionabsolute(struct wl_listener *listener, void *data) { +static 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 @@ -39,7 +39,7 @@ static inline void motionabsolute(struct wl_listener *listener, void *data) { motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy); } -static inline void motionrelative(struct wl_listener *listener, void *data) { +static 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; @@ -52,7 +52,7 @@ static inline void motionrelative(struct wl_listener *listener, void *data) { event->delta_y, event->unaccel_dx, event->unaccel_dy); } -static inline void virtualkeyboard(struct wl_listener *listener, void *data) { +static 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(); @@ -65,7 +65,7 @@ static inline void virtualkeyboard(struct wl_listener *listener, void *data) { wlr_keyboard_group_add_keyboard(group->wlr_group, &kb->keyboard); } -static inline void virtualpointer(struct wl_listener *listener, void *data) { +static 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; @@ -74,8 +74,16 @@ static inline void virtualpointer(struct wl_listener *listener, void *data) { wlr_cursor_map_input_to_output(cursor, device, event->suggested_output); } +static void createpointerconstraint(struct wl_listener *listener, void *data) { + PointerConstraint *pointer_constraint = + ecalloc(1, sizeof(*pointer_constraint)); + pointer_constraint->constraint = data; + LISTEN(&pointer_constraint->constraint->events.destroy, + &pointer_constraint->destroy, destroypointerconstraint); +} -static inline void buttonpress(struct wl_listener *listener, void *data) { + +static void buttonpress(struct wl_listener *listener, void *data) { struct wlr_pointer_button_event *event = data; struct wlr_keyboard *keyboard; uint32_t mods; @@ -127,7 +135,7 @@ static inline void buttonpress(struct wl_listener *listener, void *data) { event->state); } -static inline void cursorframe(struct wl_listener *listener, void *data) { +static 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 @@ -136,7 +144,7 @@ static inline void cursorframe(struct wl_listener *listener, void *data) { wlr_seat_pointer_notify_frame(seat); } -static inline void setcursor(struct wl_listener *listener, void *data) { +static 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 @@ -154,7 +162,7 @@ static inline void setcursor(struct wl_listener *listener, void *data) { event->hotspot_y); } -static inline void setcursorshape(struct wl_listener *listener, void *data) { +static 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; @@ -166,4 +174,33 @@ static inline void setcursorshape(struct wl_listener *listener, void *data) { wlr_cursor_shape_v1_name(event->shape)); } + +static void inputdevice(struct wl_listener *listener, void *data) { + /* This event is raised by the backend when a new input device becomes + * available. */ + struct wlr_input_device *device = data; + uint32_t caps; + + switch (device->type) { + case WLR_INPUT_DEVICE_KEYBOARD: + createkeyboard(wlr_keyboard_from_input_device(device)); + break; + case WLR_INPUT_DEVICE_POINTER: + createpointer(wlr_pointer_from_input_device(device)); + break; + default: + /* TODO handle other input device types */ + break; + } + + /* We need to let the wlr_seat know what our capabilities are, which is + * communiciated to the client. In dwl we always have a cursor, even if + * there are no pointer devices, so we always include that capability. */ + /* TODO do we actually require a cursor? */ + caps = WL_SEAT_CAPABILITY_POINTER; + if (!wl_list_empty(&kb_group->wlr_group->devices)) + caps |= WL_SEAT_CAPABILITY_KEYBOARD; + wlr_seat_set_capabilities(seat, caps); +} + #endif /* CRYWL_LSTN_INPUT_H */ diff --git a/src/listeners/layer.h b/src/listeners/layer.h new file mode 100644 index 0000000..56476a0 --- /dev/null +++ b/src/listeners/layer.h @@ -0,0 +1,49 @@ +#ifndef CRYWL_LSTN_LAYER_H +#define CRYWL_LSTN_LAYER_H + +#include +#include +#include + +#include "../lib/layers.h" + +/* Binds commitlayersurfacenotify, unmaplayersurfacenotify, + * destroylayersurfacenotify. createlayersurface() uses the + * (commit|unmap|destroy)layersurfacenotify callbacks. + */ +static void createlayersurface(struct wl_listener *listener, void *data) { + struct wlr_layer_surface_v1 *layer_surface = data; + LayerSurface *l; + struct wlr_surface *surface = layer_surface->surface; + struct wlr_scene_tree *scene_layer = + layers[layermap[layer_surface->pending.layer]]; + + if (!layer_surface->output && + !(layer_surface->output = selmon ? selmon->wlr_output : NULL)) { + wlr_layer_surface_v1_destroy(layer_surface); + return; + } + + l = layer_surface->data = ecalloc(1, sizeof(*l)); + l->type = LayerShell; + LISTEN(&surface->events.commit, &l->surface_commit, commitlayersurfacenotify); + LISTEN(&surface->events.unmap, &l->unmap, unmaplayersurfacenotify); + LISTEN(&layer_surface->events.destroy, &l->destroy, + destroylayersurfacenotify); + + l->layer_surface = layer_surface; + l->mon = layer_surface->output->data; + l->scene_layer = + wlr_scene_layer_surface_v1_create(scene_layer, layer_surface); + l->scene = l->scene_layer->tree; + l->popups = surface->data = wlr_scene_tree_create( + layer_surface->current.layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP + ? layers[LyrTop] + : scene_layer); + l->scene->node.data = l->popups->node.data = l; + + wl_list_insert(&l->mon->layers[layer_surface->pending.layer], &l->link); + wlr_surface_send_enter(surface, layer_surface->output); +} + +#endif /* CRYWL_LSTN_LAYER_H */ diff --git a/src/listeners/listeners.h b/src/listeners/listeners.h index 96f7e61..c977cdf 100644 --- a/src/listeners/listeners.h +++ b/src/listeners/listeners.h @@ -1,9 +1,19 @@ #ifndef CRYWL_LSTN_ALL_H #define CRYWL_LSTN_ALL_H -#include "input.h" +#include "client.h" #include "decoration.h" #include "drag.h" +#include "idle.h" +#include "input.h" +#include "layer.h" +#include "lock.h" +#include "mgrs.h" +#include "monitor.h" +#include "notify.h" +#include "popup.h" + +static struct wl_listener new_xdg_toplevel = {.notify = createnotify}; static struct wl_listener cursor_button = {.notify = buttonpress}; static struct wl_listener cursor_frame = {.notify = cursorframe}; @@ -13,11 +23,38 @@ 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_input_device = {.notify = inputdevice}; static struct wl_listener new_virtual_keyboard = {.notify = virtualkeyboard}; static struct wl_listener new_virtual_pointer = {.notify = virtualpointer}; +static struct wl_listener new_pointer_constraint = { + .notify = createpointerconstraint}; static struct wl_listener new_xdg_decoration = {.notify = createdecoration}; +static struct wl_listener request_start_drag = {.notify = requeststartdrag}; static struct wl_listener start_drag = {.notify = startdrag}; -#endif /*CRYWL_LSTN_ALL_H*/ +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 new_session_lock = {.notify = locksession}; + +static struct wl_listener new_xdg_popup = {.notify = createpopup}; + +static struct wl_listener new_idle_inhibitor = {.notify = createidleinhibitor}; + +static struct wl_listener request_set_psel = {.notify = setpsel}; +static struct wl_listener request_set_sel = {.notify = setsel}; + +static struct wl_listener gpu_reset = {.notify = gpureset}; + +static struct wl_listener layout_change = {.notify = updatemons}; +static struct wl_listener new_output = {.notify = createmon}; + +static struct wl_listener new_layer_surface = {.notify = createlayersurface}; + +static struct wl_listener request_activate = {.notify = urgent}; + +#endif /* CRYWL_LSTN_ALL_H */ diff --git a/src/listeners/lock.h b/src/listeners/lock.h new file mode 100644 index 0000000..d20b9da --- /dev/null +++ b/src/listeners/lock.h @@ -0,0 +1,33 @@ +#ifndef CRYWL_LSTN_LOCK_H +#define CRYWL_LSTN_LOCK_H + +#include +#include + +#include "../lib/lock.h" +#include "../lib/clientutil.h" + +static void locksession(struct wl_listener *listener, void *data) { + struct wlr_session_lock_v1 *session_lock = data; + SessionLock *lock; + wlr_scene_node_set_enabled(&locked_bg->node, 1); + if (cur_lock) { + wlr_session_lock_v1_destroy(session_lock); + return; + } + lock = session_lock->data = ecalloc(1, sizeof(*lock)); + focusclient(NULL, 0); + + lock->scene = wlr_scene_tree_create(layers[LyrBlock]); + cur_lock = lock->lock = session_lock; + locked = 1; + + LISTEN(&session_lock->events.new_surface, &lock->new_surface, + createlocksurface); + LISTEN(&session_lock->events.destroy, &lock->destroy, destroysessionlock); + LISTEN(&session_lock->events.unlock, &lock->unlock, unlocksession); + + wlr_session_lock_v1_send_locked(session_lock); +} + +#endif /* CRYWL_LSTN_LOCK_H */ diff --git a/src/lib/mgrs.c b/src/listeners/mgrs.h similarity index 82% rename from src/lib/mgrs.c rename to src/listeners/mgrs.h index d6ab877..0b9501b 100644 --- a/src/lib/mgrs.c +++ b/src/listeners/mgrs.h @@ -1,10 +1,15 @@ -void outputmgrapply(struct wl_listener *listener, void *data) { - struct wlr_output_configuration_v1 *config = data; - outputmgrapplyortest(config, 0); -} +#ifndef CRYWL_LSTN_MGRS_H +#define CRYWL_LSTN_MGRS_H -void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, - int test) { +#include +#include +#include +#include + +#include "../lib/monitor.h" + +static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, + int test) { /* * Called when a client such as wlr-randr requests a change in output * configuration. This is only one way that the layout can be changed, @@ -66,12 +71,17 @@ void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, updatemons(NULL, NULL); } -void outputmgrtest(struct wl_listener *listener, void *data) { +static void outputmgrapply(struct wl_listener *listener, void *data) { + struct wlr_output_configuration_v1 *config = data; + outputmgrapplyortest(config, 0); +} + +static void outputmgrtest(struct wl_listener *listener, void *data) { struct wlr_output_configuration_v1 *config = data; outputmgrapplyortest(config, 1); } -void powermgrsetmode(struct wl_listener *listener, void *data) { +static void powermgrsetmode(struct wl_listener *listener, void *data) { struct wlr_output_power_v1_set_mode_event *event = data; struct wlr_output_state state = {0}; Monitor *m = event->output->data; @@ -86,3 +96,5 @@ void powermgrsetmode(struct wl_listener *listener, void *data) { m->asleep = !event->mode; updatemons(NULL, NULL); } + +#endif /* CRYWL_LSTN_MGRS_H */ diff --git a/src/listeners/monitor.h b/src/listeners/monitor.h new file mode 100644 index 0000000..00fb36b --- /dev/null +++ b/src/listeners/monitor.h @@ -0,0 +1,230 @@ +#ifndef CRYWL_LSTN_MONITOR_H +#define CRYWL_LSTN_MONITOR_H + +#include +#include +#include +#include +#include +#include +#include + +#include "../lib/monitor.h" + +static void gpureset(struct wl_listener *listener, void *data) { + struct wlr_renderer *old_drw = drw; + struct wlr_allocator *old_alloc = alloc; + struct Monitor *m; + if (!(drw = wlr_renderer_autocreate(backend))) + die("couldn't recreate renderer"); + + if (!(alloc = wlr_allocator_autocreate(backend, drw))) + die("couldn't recreate allocator"); + + wl_list_remove(&gpu_reset.link); + wl_signal_add(&drw->events.lost, &gpu_reset); + + wlr_compositor_set_renderer(compositor, drw); + + wl_list_for_each(m, &mons, link) { + wlr_output_init_render(m->wlr_output, alloc, drw); + } + + wlr_allocator_destroy(old_alloc); + wlr_renderer_destroy(old_drw); +} + +/* + * Called whenever the output layout changes: adding or removing a + * monitor, changing an output's mode or position, etc. This is where + * the change officially happens and we update geometry, window + * positions, focus, and the stored configuration in wlroots' + * output-manager implementation. + */ +static void updatemons(struct wl_listener *listener, void *data) { + struct wlr_output_configuration_v1 *config = + wlr_output_configuration_v1_create(); + Client *c; + struct wlr_output_configuration_head_v1 *config_head; + Monitor *m; + + /* First remove from the layout the disabled monitors */ + wl_list_for_each(m, &mons, link) { + if (m->wlr_output->enabled || m->asleep) + continue; + config_head = + wlr_output_configuration_head_v1_create(config, m->wlr_output); + config_head->state.enabled = 0; + /* Remove this output from the layout to avoid cursor enter inside it */ + wlr_output_layout_remove(output_layout, m->wlr_output); + closemon(m); + m->m = m->w = (struct wlr_box){0}; + } + /* Insert outputs that need to */ + wl_list_for_each(m, &mons, link) { + if (m->wlr_output->enabled && + !wlr_output_layout_get(output_layout, m->wlr_output)) + wlr_output_layout_add_auto(output_layout, m->wlr_output); + } + + /* Now that we update the output layout we can get its box */ + wlr_output_layout_get_box(output_layout, NULL, &sgeom); + + wlr_scene_node_set_position(&root_bg->node, sgeom.x, sgeom.y); + wlr_scene_rect_set_size(root_bg, sgeom.width, sgeom.height); + + /* Make sure the clients are hidden when dwl is locked */ + wlr_scene_node_set_position(&locked_bg->node, sgeom.x, sgeom.y); + wlr_scene_rect_set_size(locked_bg, sgeom.width, sgeom.height); + + wl_list_for_each(m, &mons, link) { + if (!m->wlr_output->enabled) + continue; + config_head = + wlr_output_configuration_head_v1_create(config, m->wlr_output); + + /* Get the effective monitor geometry to use for surfaces */ + wlr_output_layout_get_box(output_layout, m->wlr_output, &m->m); + m->w = m->m; + wlr_scene_output_set_position(m->scene_output, m->m.x, m->m.y); + + wlr_scene_node_set_position(&m->fullscreen_bg->node, m->m.x, m->m.y); + wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height); + + if (m->lock_surface) { + struct wlr_scene_tree *scene_tree = m->lock_surface->surface->data; + wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y); + wlr_session_lock_surface_v1_configure(m->lock_surface, m->m.width, + m->m.height); + } + + /* Calculate the effective monitor geometry to use for clients */ + arrangelayers(m); + /* Don't move clients to the left output when plugging monitors */ + arrange(m); + /* make sure fullscreen clients have the right size */ + if ((c = focustop(m)) && c->isfullscreen) + resize(c, m->m, 0); + + /* Try to re-set the gamma LUT when updating monitors, + * it's only really needed when enabling a disabled output, but meh. */ + m->gamma_lut_changed = 1; + + config_head->state.x = m->m.x; + config_head->state.y = m->m.y; + + if (!selmon) { + selmon = m; + } + } + + if (selmon && selmon->wlr_output->enabled) { + wl_list_for_each(c, &clients, link) { + if (!c->mon && client_surface(c)->mapped) + setmon(c, selmon, c->tags); + } + focusclient(focustop(selmon), 1); + if (selmon->lock_surface) { + client_notify_enter(selmon->lock_surface->surface, + wlr_seat_get_keyboard(seat)); + client_activate_surface(selmon->lock_surface->surface, 1); + } + } + + /* FIXME: figure out why the cursor image is at 0,0 after turning all + * the monitors on. + * Move the cursor image where it used to be. It does not generate a + * wl_pointer.motion event for the clients, it's only the image what it's + * at the wrong position after all. */ + wlr_cursor_move(cursor, NULL, 0, 0); + + wlr_output_manager_v1_set_configuration(output_mgr, config); +} + +/* Helper listener for listeners/monitor.h:createmon() */ +static void requestmonstate(struct wl_listener *listener, void *data) { + struct wlr_output_event_request_state *event = data; + wlr_output_commit_state(event->output, event->state); + updatemons(NULL, NULL); +} + +/* This event is raised by the backend when a new output (aka a display or + * monitor) becomes available. */ +static void createmon(struct wl_listener *listener, void *data) { + struct wlr_output *wlr_output = data; + const MonitorRule *r; + size_t i; + struct wlr_output_state state; + Monitor *m; + + if (!wlr_output_init_render(wlr_output, alloc, drw)) + return; + + m = wlr_output->data = ecalloc(1, sizeof(*m)); + m->wlr_output = wlr_output; + + for (i = 0; i < LENGTH(m->layers); i++) + wl_list_init(&m->layers[i]); + + wlr_output_state_init(&state); + /* Initialize monitor state using configured rules */ + m->tagset[0] = m->tagset[1] = 1; + for (r = monrules; r < END(monrules); r++) { + if (!r->name || strstr(wlr_output->name, r->name)) { + m->m.x = r->x; + m->m.y = r->y; + m->mfact = r->mfact; + m->nmaster = r->nmaster; + m->lt[0] = r->lt; + m->lt[1] = &layouts[LENGTH(layouts) > 1 && r->lt != &layouts[1]]; + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, LENGTH(m->ltsymbol)); + wlr_output_state_set_scale(&state, r->scale); + wlr_output_state_set_transform(&state, r->rr); + break; + } + } + + /* The mode is a tuple of (width, height, refresh rate), and each + * monitor supports only a specific set of modes. We just pick the + * monitor's preferred mode; a more sophisticated compositor would let + * the user configure it. */ + wlr_output_state_set_mode(&state, wlr_output_preferred_mode(wlr_output)); + + /* Set up event listeners */ + LISTEN(&wlr_output->events.frame, &m->frame, rendermon); + LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon); + LISTEN(&wlr_output->events.request_state, &m->request_state, requestmonstate); + + wlr_output_state_set_enabled(&state, 1); + wlr_output_commit_state(wlr_output, &state); + wlr_output_state_finish(&state); + + wl_list_insert(&mons, &m->link); + printstatus(); + + /* The xdg-protocol specifies: + * + * If the fullscreened surface is not opaque, the compositor must make + * sure that other screen content not part of the same surface tree (made + * up of subsurfaces, popups or similarly coupled surfaces) are not + * visible below the fullscreened surface. + * + */ + /* updatemons() will resize and set correct position */ + m->fullscreen_bg = wlr_scene_rect_create(layers[LyrFS], 0, 0, fullscreen_bg); + wlr_scene_node_set_enabled(&m->fullscreen_bg->node, 0); + + /* Adds this to the output layout in the order it was configured. + * + * The output layout utility automatically adds a wl_output global to the + * display, which Wayland clients can see to find out information about the + * output (such as DPI, scale factor, manufacturer, etc). + */ + m->scene_output = wlr_scene_output_create(scene, wlr_output); + if (m->m.x == -1 && m->m.y == -1) + wlr_output_layout_add_auto(output_layout, wlr_output); + else + wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y); +} + +#endif /* CRYWL_LSTN_MONITOR_H */ diff --git a/src/listeners/notify.h b/src/listeners/notify.h new file mode 100644 index 0000000..968f217 --- /dev/null +++ b/src/listeners/notify.h @@ -0,0 +1,29 @@ +#ifndef CRYWL_LSTN_NOTIFY_H +#define CRYWL_LSTN_NOTIFY_H + +#include + +#include "../lib/client.h" + +/* This event is raised when a client creates a new toplevel (application + * window). */ +static void createnotify(struct wl_listener *listener, void *data) { + struct wlr_xdg_toplevel *toplevel = data; + Client *c = NULL; + + /* Allocate a Client for this surface */ + c = toplevel->base->data = ecalloc(1, sizeof(*c)); + c->surface.xdg = toplevel->base; + c->bw = borderpx; + + LISTEN(&toplevel->base->surface->events.commit, &c->commit, commitnotify); + LISTEN(&toplevel->base->surface->events.map, &c->map, mapnotify); + LISTEN(&toplevel->base->surface->events.unmap, &c->unmap, unmapnotify); + LISTEN(&toplevel->events.destroy, &c->destroy, destroynotify); + LISTEN(&toplevel->events.request_fullscreen, &c->fullscreen, + fullscreennotify); + LISTEN(&toplevel->events.request_maximize, &c->maximize, maximizenotify); + LISTEN(&toplevel->events.set_title, &c->set_title, updatetitle); +} + +#endif CRYWL_LSTN_NOTIFY_H diff --git a/src/lib/popup.c b/src/listeners/popup.h similarity index 63% rename from src/lib/popup.c rename to src/listeners/popup.h index cffb6f3..407fc23 100644 --- a/src/lib/popup.c +++ b/src/listeners/popup.h @@ -1,4 +1,16 @@ -void commitpopup(struct wl_listener *listener, void *data) { +#ifndef CRYWL_LSTN_POPUP_H +#define CRYWL_LSTN_POPUP_H + +#include + +#include +#include + +#include "../lib/layers.h" +#include "../lib/clientutil.h" + +/* Helper listener for listeners/popup.h:createpopup() */ +static void commitpopup(struct wl_listener *listener, void *data) { struct wlr_surface *surface = data; struct wlr_xdg_popup *popup = wlr_xdg_popup_try_from_wlr_surface(surface); LayerSurface *l = NULL; @@ -26,9 +38,11 @@ void commitpopup(struct wl_listener *listener, void *data) { free(listener); } -void createpopup(struct wl_listener *listener, void *data) { - /* This event is raised when a client (either xdg-shell or layer-shell) - * creates a new popup. */ +/* This event is raised when a client (either xdg-shell or layer-shell) creates a new popup. */ +static void createpopup(struct wl_listener *listener, void *data) { struct wlr_xdg_popup *popup = data; LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup); } + +#endif /* CRYWL_LSTN_POPUP_H */ + diff --git a/src/main.c b/src/main.c index 7d60559..477c0ac 100644 --- a/src/main.c +++ b/src/main.c @@ -71,30 +71,8 @@ #include "util.h" /* global event handlers */ -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 gpu_reset = {.notify = gpureset}; -static struct wl_listener layout_change = {.notify = updatemons}; -static struct wl_listener new_idle_inhibitor = {.notify = createidleinhibitor}; -static struct wl_listener new_input_device = {.notify = inputdevice}; -static struct wl_listener new_virtual_keyboard = {.notify = virtualkeyboard}; -static struct wl_listener new_virtual_pointer = {.notify = virtualpointer}; -static struct wl_listener new_pointer_constraint = { - .notify = createpointerconstraint}; -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_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_set_psel = {.notify = setpsel}; -static struct wl_listener request_set_sel = {.notify = setsel}; -static struct wl_listener request_start_drag = {.notify = requeststartdrag}; -static struct wl_listener new_session_lock = {.notify = locksession}; /* configuration, allows nested code to access above variables */ #include "config.h"