REFACTOR (wl_listeners isolated)
This commit is contained in:
parent
ab3942d3b5
commit
b92eb285c0
31 changed files with 620 additions and 473 deletions
|
|
@ -1,3 +1,7 @@
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||||
|
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
|
||||||
void applybounds(Client *c, struct wlr_box *bbox) {
|
void applybounds(Client *c, struct wlr_box *bbox) {
|
||||||
|
|
@ -225,20 +229,6 @@ void updatetitle(struct wl_listener *listener, void *data) {
|
||||||
printstatus();
|
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) {
|
void view(const Arg *arg) {
|
||||||
if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
|
if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
#ifndef CRYWL_CLIENT_H
|
#ifndef CRYWL_CLIENT_H
|
||||||
#define CRYWL_CLIENT_H
|
#define CRYWL_CLIENT_H
|
||||||
|
|
||||||
#include "../wayland.h"
|
#include <wlr/util/box.h>
|
||||||
|
|
||||||
#include "../util.h"
|
#include "../util.h"
|
||||||
|
|
||||||
enum { XDGShell, LayerShell, X11 }; /* client types */
|
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 resize(Client *c, struct wlr_box geo, int interact);
|
||||||
void setfloating(Client *c, int floating);
|
void setfloating(Client *c, int floating);
|
||||||
void setfullscreen(Client *c, int fullscreen);
|
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 togglefloating(const Arg *arg);
|
||||||
void togglefullscreen(const Arg *arg);
|
void togglefullscreen(const Arg *arg);
|
||||||
void toggletag(const Arg *arg);
|
void toggletag(const Arg *arg);
|
||||||
void toggleview(const Arg *arg);
|
void toggleview(const Arg *arg);
|
||||||
void updatetitle(struct wl_listener *listener, void *data);
|
void updatetitle(struct wl_listener *listener, void *data);
|
||||||
void urgent(struct wl_listener *listener, void *data);
|
|
||||||
void view(const Arg *arg);
|
void view(const Arg *arg);
|
||||||
void zoom(const Arg *arg);
|
void zoom(const Arg *arg);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -305,42 +305,6 @@ void handlesig(int signo) {
|
||||||
quit(NULL);
|
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) {
|
void run(char *startup_cmd) {
|
||||||
/* Add a Unix socket to the Wayland display. */
|
/* Add a Unix socket to the Wayland display. */
|
||||||
const char *socket = wl_display_add_socket_auto(dpy);
|
const char *socket = wl_display_add_socket_auto(dpy);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <wlr/types/wlr_cursor.h>
|
||||||
|
|
||||||
#include "cursor.h"
|
#include "cursor.h"
|
||||||
#include "clientutil.h"
|
#include "clientutil.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <wlr/types/wlr_compositor.h>
|
||||||
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||||
|
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
||||||
|
|
||||||
void checkidleinhibitor(struct wlr_surface *exclude) {
|
void checkidleinhibitor(struct wlr_surface *exclude) {
|
||||||
int inhibited = 0, unused_lx, unused_ly;
|
int inhibited = 0, unused_lx, unused_ly;
|
||||||
struct wlr_idle_inhibitor_v1 *inhibitor;
|
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);
|
wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createidleinhibitor(struct wl_listener *listener, void *data) {
|
/* Helper listener used by `listeners/idle.h:createidleinhibitor` */
|
||||||
struct wlr_idle_inhibitor_v1 *idle_inhibitor = data;
|
|
||||||
LISTEN_STATIC(&idle_inhibitor->events.destroy, destroyidleinhibitor);
|
|
||||||
|
|
||||||
checkidleinhibitor(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroyidleinhibitor(struct wl_listener *listener, void *data) {
|
void destroyidleinhibitor(struct wl_listener *listener, void *data) {
|
||||||
/* `data` is the wlr_surface of the idle inhibitor being destroyed,
|
/* `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 */
|
* at this point the idle inhibitor is still in the list of the manager */
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
#ifndef CRYWL_IDLE_H
|
#ifndef CRYWL_IDLE_H
|
||||||
#define CRYWL_IDLE_H
|
#define CRYWL_IDLE_H
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||||
|
|
||||||
/* ===== Function Declarations ===== */
|
/* ===== Function Declarations ===== */
|
||||||
static void checkidleinhibitor(struct wlr_surface *exclude);
|
void checkidleinhibitor(struct wlr_surface *exclude);
|
||||||
static void createidleinhibitor(struct wl_listener *listener, void *data);
|
void destroyidleinhibitor(struct wl_listener *listener, void *data);
|
||||||
static void destroyidleinhibitor(struct wl_listener *listener, void *data);
|
|
||||||
|
|
||||||
#endif /* CRYWL_IDLE_H */
|
#endif /* CRYWL_IDLE_H */
|
||||||
|
|
|
||||||
|
|
@ -65,14 +65,6 @@ void createpointer(struct wlr_pointer *pointer) {
|
||||||
wlr_cursor_attach_input_device(cursor, &pointer->base);
|
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 *createkeyboardgroup(void) {
|
||||||
KeyboardGroup *group = ecalloc(1, sizeof(*group));
|
KeyboardGroup *group = ecalloc(1, sizeof(*group));
|
||||||
struct xkb_context *context;
|
struct xkb_context *context;
|
||||||
|
|
@ -134,34 +126,6 @@ void destroykeyboardgroup(struct wl_listener *listener, void *data) {
|
||||||
free(group);
|
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) {
|
int keybinding(uint32_t mods, xkb_keysym_t sym) {
|
||||||
/*
|
/*
|
||||||
* Here we handle compositor keybindings. This is when the compositor is
|
* Here we handle compositor keybindings. This is when the compositor is
|
||||||
|
|
|
||||||
|
|
@ -40,18 +40,12 @@ typedef struct {
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
} PointerConstraint;
|
} PointerConstraint;
|
||||||
|
|
||||||
/* ===== Event Handlers ===== */
|
|
||||||
static void virtualkeyboard(struct wl_listener *listener, void *data);
|
|
||||||
static void virtualpointer(struct wl_listener *listener, void *data);
|
|
||||||
|
|
||||||
/* ===== Function Declarations ===== */
|
/* ===== Function Declarations ===== */
|
||||||
static void createkeyboard(struct wlr_keyboard *keyboard);
|
static void createkeyboard(struct wlr_keyboard *keyboard);
|
||||||
static KeyboardGroup *createkeyboardgroup(void);
|
static KeyboardGroup *createkeyboardgroup(void);
|
||||||
static void createpointer(struct wlr_pointer *pointer);
|
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 destroypointerconstraint(struct wl_listener *listener, void *data);
|
||||||
static void destroykeyboardgroup(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 int keybinding(uint32_t mods, xkb_keysym_t sym);
|
||||||
static void keypress(struct wl_listener *listener, void *data);
|
static void keypress(struct wl_listener *listener, void *data);
|
||||||
static void keypressmod(struct wl_listener *listener, void *data);
|
static void keypressmod(struct wl_listener *listener, void *data);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||||
|
|
||||||
#include "layers.h"
|
#include "layers.h"
|
||||||
|
#include "notify.h"
|
||||||
|
#include "clientutil.h"
|
||||||
|
|
||||||
void commitlayersurfacenotify(struct wl_listener *listener, void *data) {
|
void commitlayersurfacenotify(struct wl_listener *listener, void *data) {
|
||||||
LayerSurface *l = wl_container_of(listener, l, surface_commit);
|
LayerSurface *l = wl_container_of(listener, l, surface_commit);
|
||||||
|
|
@ -64,43 +69,6 @@ void destroylayersurfacenotify(struct wl_listener *listener, void *data) {
|
||||||
free(l);
|
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,
|
void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc,
|
||||||
LayerSurface **pl, double *nx, double *ny) {
|
LayerSurface **pl, double *nx, double *ny) {
|
||||||
struct wlr_scene_node *node, *pnode;
|
struct wlr_scene_node *node, *pnode;
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@ typedef struct {
|
||||||
static void commitlayersurfacenotify(struct wl_listener *listener, void *data);
|
static void commitlayersurfacenotify(struct wl_listener *listener, void *data);
|
||||||
static void unmaplayersurfacenotify(struct wl_listener *listener, void *data);
|
static void unmaplayersurfacenotify(struct wl_listener *listener, void *data);
|
||||||
static void destroylayersurfacenotify(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,
|
void xytonode(double x, double y, struct wlr_surface **psurface,
|
||||||
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,15 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <wlr/types/wlr_output.h>
|
||||||
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
#include <wlr/types/wlr_seat.h>
|
||||||
|
#include <wlr/types/wlr_session_lock_v1.h>
|
||||||
|
|
||||||
|
#include "clientutil.h"
|
||||||
|
#include "lock.h"
|
||||||
|
#include "monitor.h"
|
||||||
|
#include "notify.h"
|
||||||
|
|
||||||
void createlocksurface(struct wl_listener *listener, void *data) {
|
void createlocksurface(struct wl_listener *listener, void *data) {
|
||||||
SessionLock *lock = wl_container_of(listener, lock, new_surface);
|
SessionLock *lock = wl_container_of(listener, lock, new_surface);
|
||||||
struct wlr_session_lock_surface_v1 *lock_surface = data;
|
struct wlr_session_lock_surface_v1 *lock_surface = data;
|
||||||
|
|
@ -61,29 +73,6 @@ void destroysessionlock(struct wl_listener *listener, void *data) {
|
||||||
destroylock(lock, 0);
|
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) {
|
void unlocksession(struct wl_listener *listener, void *data) {
|
||||||
SessionLock *lock = wl_container_of(listener, lock, unlock);
|
SessionLock *lock = wl_container_of(listener, lock, unlock);
|
||||||
destroylock(lock, 1);
|
destroylock(lock, 1);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef CRYWL_LOCK_H
|
#ifndef CRYWL_LOCK_H
|
||||||
#define CRYWL_LOCK_H
|
#define CRYWL_LOCK_H
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct wlr_scene_tree *scene;
|
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 destroylock(SessionLock *lock, int unlocked);
|
||||||
static void destroylocksurface(struct wl_listener *listener, void *data);
|
static void destroylocksurface(struct wl_listener *listener, void *data);
|
||||||
static void destroysessionlock(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);
|
static void unlocksession(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
#endif /* CRYWL_LOCK_H */
|
#endif /* CRYWL_LOCK_H */
|
||||||
|
|
|
||||||
44
src/lib/logging.c
Normal file
44
src/lib/logging.c
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
#include <wlr/types/wlr_output.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
8
src/lib/logging.h
Normal file
8
src/lib/logging.h
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef CRYWL_LOGGING_H
|
||||||
|
#define CRYWL_LOGGING_H
|
||||||
|
|
||||||
|
/* ===== Functional Declarations ===== */
|
||||||
|
static void printstatus(void);
|
||||||
|
|
||||||
|
#endif /* CRYWL_LOGGING_H */
|
||||||
|
|
||||||
|
|
@ -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 */
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
|
||||||
#include "monitor.h"
|
#include "monitor.h"
|
||||||
#include "clientutil.h"
|
#include "clientutil.h"
|
||||||
|
|
||||||
|
|
@ -184,84 +188,6 @@ void closemon(Monitor *m) {
|
||||||
printstatus();
|
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) {
|
Monitor *dirtomon(enum wlr_direction dir) {
|
||||||
struct wlr_output *next;
|
struct wlr_output *next;
|
||||||
|
|
@ -323,29 +249,6 @@ Client *focustop(Monitor *m) {
|
||||||
return NULL;
|
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) {
|
void incnmaster(const Arg *arg) {
|
||||||
if (!arg || !selmon)
|
if (!arg || !selmon)
|
||||||
return;
|
return;
|
||||||
|
|
@ -394,12 +297,6 @@ skip:
|
||||||
wlr_output_state_finish(&pending);
|
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) {
|
void setlayout(const Arg *arg) {
|
||||||
if (!selmon)
|
if (!selmon)
|
||||||
return;
|
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) {
|
Monitor *xytomon(double x, double y) {
|
||||||
struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y);
|
struct wlr_output *o = wlr_output_layout_output_at(output_layout, x, y);
|
||||||
return o ? o->data : NULL;
|
return o ? o->data : NULL;
|
||||||
|
|
|
||||||
|
|
@ -59,23 +59,19 @@ void arrangelayer(Monitor *m, struct wl_list *list,
|
||||||
void arrangelayers(Monitor *m);
|
void arrangelayers(Monitor *m);
|
||||||
void cleanupmon(struct wl_listener *listener, void *data);
|
void cleanupmon(struct wl_listener *listener, void *data);
|
||||||
void closemon(Monitor *m);
|
void closemon(Monitor *m);
|
||||||
void createmon(struct wl_listener *listener, void *data);
|
|
||||||
Monitor *dirtomon(enum wlr_direction dir);
|
Monitor *dirtomon(enum wlr_direction dir);
|
||||||
void focusmon(const Arg *arg);
|
void focusmon(const Arg *arg);
|
||||||
void focusstack(const Arg *arg);
|
void focusstack(const Arg *arg);
|
||||||
Client *focustop(Monitor *m);
|
Client *focustop(Monitor *m);
|
||||||
void gpureset(struct wl_listener *listener, void *data);
|
|
||||||
void incnmaster(const Arg *arg);
|
void incnmaster(const Arg *arg);
|
||||||
void monocle(Monitor *m);
|
void monocle(Monitor *m);
|
||||||
void rendermon(struct wl_listener *listener, void *data);
|
void rendermon(struct wl_listener *listener, void *data);
|
||||||
void requestmonstate(struct wl_listener *listener, void *data);
|
|
||||||
void setlayout(const Arg *arg);
|
void setlayout(const Arg *arg);
|
||||||
void setmfact(const Arg *arg);
|
void setmfact(const Arg *arg);
|
||||||
void setmon(Client *c, Monitor *m, uint32_t newtags);
|
void setmon(Client *c, Monitor *m, uint32_t newtags);
|
||||||
void tag(const Arg *arg);
|
void tag(const Arg *arg);
|
||||||
void tagmon(const Arg *arg);
|
void tagmon(const Arg *arg);
|
||||||
void tile(Monitor *m);
|
void tile(Monitor *m);
|
||||||
void updatemons(struct wl_listener *listener, void *data);
|
|
||||||
Monitor *xytomon(double x, double y);
|
Monitor *xytomon(double x, double y);
|
||||||
|
|
||||||
#endif /* CRYWL_MONITOR_H */
|
#endif /* CRYWL_MONITOR_H */
|
||||||
|
|
|
||||||
|
|
@ -29,27 +29,6 @@ void commitnotify(struct wl_listener *listener, void *data) {
|
||||||
c->resize = 0;
|
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) {
|
void destroynotify(struct wl_listener *listener, void *data) {
|
||||||
/* Called when the xdg_toplevel is destroyed. */
|
/* Called when the xdg_toplevel is destroyed. */
|
||||||
Client *c = wl_container_of(listener, c, destroy);
|
Client *c = wl_container_of(listener, c, destroy);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
/* ===== Function Declarations ===== */
|
/* ===== Function Declarations ===== */
|
||||||
static void commitnotify(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 destroynotify(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 fullscreennotify(struct wl_listener *listener, void *data);
|
||||||
static void mapnotify(struct wl_listener *listener, void *data);
|
static void mapnotify(struct wl_listener *listener, void *data);
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
|
||||||
44
src/listeners/client.h
Normal file
44
src/listeners/client.h
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef CRYWL_LSTN_CLIENT_H
|
||||||
|
#define CRYWL_LSTN_CLIENT_H
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
#include <wlr/types/wlr_data_device.h>
|
||||||
|
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||||
|
#include <wlr/types/wlr_primary_selection.h>
|
||||||
|
#include <wlr/types/wlr_xdg_activation_v1.h>
|
||||||
|
|
||||||
|
#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 */
|
||||||
16
src/listeners/idle.h
Normal file
16
src/listeners/idle.h
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef CRYWL_LSTN_IDLE_H
|
||||||
|
#define CRYWL_LSTN_IDLE_H
|
||||||
|
|
||||||
|
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include "../lib/cursor.h"
|
#include "../lib/cursor.h"
|
||||||
#include "../lib/notify.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,
|
/* This event is forwarded by the cursor when a pointer emits an axis event,
|
||||||
* for example when you move the scroll wheel. */
|
* for example when you move the scroll wheel. */
|
||||||
struct wlr_pointer_axis_event *event = data;
|
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);
|
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_
|
/* 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
|
* 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
|
* 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);
|
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_
|
/* This event is forwarded by the cursor when a pointer emits a _relative_
|
||||||
* pointer motion event (i.e. a delta) */
|
* pointer motion event (i.e. a delta) */
|
||||||
struct wlr_pointer_motion_event *event = data;
|
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);
|
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;
|
struct wlr_virtual_keyboard_v1 *kb = data;
|
||||||
/* virtual keyboards shouldn't share keyboard group */
|
/* virtual keyboards shouldn't share keyboard group */
|
||||||
KeyboardGroup *group = createkeyboardgroup();
|
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);
|
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_virtual_pointer_v1_new_pointer_event *event = data;
|
||||||
struct wlr_input_device *device = &event->new_pointer->pointer.base;
|
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);
|
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_pointer_button_event *event = data;
|
||||||
struct wlr_keyboard *keyboard;
|
struct wlr_keyboard *keyboard;
|
||||||
uint32_t mods;
|
uint32_t mods;
|
||||||
|
|
@ -127,7 +135,7 @@ static inline void buttonpress(struct wl_listener *listener, void *data) {
|
||||||
event->state);
|
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
|
/* This event is forwarded by the cursor when a pointer emits a frame
|
||||||
* event. Frame events are sent after regular pointer events to group
|
* event. Frame events are sent after regular pointer events to group
|
||||||
* multiple events together. For instance, two axis events may happen at the
|
* 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);
|
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 */
|
/* This event is raised by the seat when a client provides a cursor image */
|
||||||
struct wlr_seat_pointer_request_set_cursor_event *event = data;
|
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
|
/* 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);
|
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;
|
struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data;
|
||||||
if (cursor_mode != CurNormal && cursor_mode != CurPressed)
|
if (cursor_mode != CurNormal && cursor_mode != CurPressed)
|
||||||
return;
|
return;
|
||||||
|
|
@ -166,4 +174,33 @@ static inline void setcursorshape(struct wl_listener *listener, void *data) {
|
||||||
wlr_cursor_shape_v1_name(event->shape));
|
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 */
|
#endif /* CRYWL_LSTN_INPUT_H */
|
||||||
|
|
|
||||||
49
src/listeners/layer.h
Normal file
49
src/listeners/layer.h
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef CRYWL_LSTN_LAYER_H
|
||||||
|
#define CRYWL_LSTN_LAYER_H
|
||||||
|
|
||||||
|
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||||
|
#include <wlr/types/wlr_output.h>
|
||||||
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
|
@ -1,9 +1,19 @@
|
||||||
#ifndef CRYWL_LSTN_ALL_H
|
#ifndef CRYWL_LSTN_ALL_H
|
||||||
#define CRYWL_LSTN_ALL_H
|
#define CRYWL_LSTN_ALL_H
|
||||||
|
|
||||||
#include "input.h"
|
#include "client.h"
|
||||||
#include "decoration.h"
|
#include "decoration.h"
|
||||||
#include "drag.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_button = {.notify = buttonpress};
|
||||||
static struct wl_listener cursor_frame = {.notify = cursorframe};
|
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_axis = {.notify = axisnotify};
|
||||||
static struct wl_listener cursor_motion = {.notify = motionrelative};
|
static struct wl_listener cursor_motion = {.notify = motionrelative};
|
||||||
static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute};
|
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_keyboard = {.notify = virtualkeyboard};
|
||||||
static struct wl_listener new_virtual_pointer = {.notify = virtualpointer};
|
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 new_xdg_decoration = {.notify = createdecoration};
|
||||||
|
|
||||||
|
static struct wl_listener request_start_drag = {.notify = requeststartdrag};
|
||||||
static struct wl_listener start_drag = {.notify = startdrag};
|
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 */
|
||||||
|
|
|
||||||
33
src/listeners/lock.h
Normal file
33
src/listeners/lock.h
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef CRYWL_LSTN_LOCK_H
|
||||||
|
#define CRYWL_LSTN_LOCK_H
|
||||||
|
|
||||||
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
#include <wlr/types/wlr_session_lock_v1.h>
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
void outputmgrapply(struct wl_listener *listener, void *data) {
|
#ifndef CRYWL_LSTN_MGRS_H
|
||||||
struct wlr_output_configuration_v1 *config = data;
|
#define CRYWL_LSTN_MGRS_H
|
||||||
outputmgrapplyortest(config, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void outputmgrapplyortest(struct wlr_output_configuration_v1 *config,
|
#include <wlr/types/wlr_output.h>
|
||||||
int test) {
|
#include <wlr/types/wlr_output_layout.h>
|
||||||
|
#include <wlr/types/wlr_output_management_v1.h>
|
||||||
|
#include <wlr/types/wlr_output_power_management_v1.h>
|
||||||
|
|
||||||
|
#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
|
* 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,
|
* 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);
|
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;
|
struct wlr_output_configuration_v1 *config = data;
|
||||||
outputmgrapplyortest(config, 1);
|
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_power_v1_set_mode_event *event = data;
|
||||||
struct wlr_output_state state = {0};
|
struct wlr_output_state state = {0};
|
||||||
Monitor *m = event->output->data;
|
Monitor *m = event->output->data;
|
||||||
|
|
@ -86,3 +96,5 @@ void powermgrsetmode(struct wl_listener *listener, void *data) {
|
||||||
m->asleep = !event->mode;
|
m->asleep = !event->mode;
|
||||||
updatemons(NULL, NULL);
|
updatemons(NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CRYWL_LSTN_MGRS_H */
|
||||||
230
src/listeners/monitor.h
Normal file
230
src/listeners/monitor.h
Normal file
|
|
@ -0,0 +1,230 @@
|
||||||
|
#ifndef CRYWL_LSTN_MONITOR_H
|
||||||
|
#define CRYWL_LSTN_MONITOR_H
|
||||||
|
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
#include <wlr/render/allocator.h>
|
||||||
|
#include <wlr/render/wlr_renderer.h>
|
||||||
|
#include <wlr/types/wlr_compositor.h>
|
||||||
|
#include <wlr/types/wlr_output.h>
|
||||||
|
#include <wlr/types/wlr_output_layout.h>
|
||||||
|
#include <wlr/types/wlr_output_management_v1.h>
|
||||||
|
|
||||||
|
#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 */
|
||||||
29
src/listeners/notify.h
Normal file
29
src/listeners/notify.h
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef CRYWL_LSTN_NOTIFY_H
|
||||||
|
#define CRYWL_LSTN_NOTIFY_H
|
||||||
|
|
||||||
|
#include <wlr/types/wlr_xdg_shell.h>
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
@ -1,4 +1,16 @@
|
||||||
void commitpopup(struct wl_listener *listener, void *data) {
|
#ifndef CRYWL_LSTN_POPUP_H
|
||||||
|
#define CRYWL_LSTN_POPUP_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
#include <wlr/types/wlr_xdg_decoration_v1.h>
|
||||||
|
|
||||||
|
#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_surface *surface = data;
|
||||||
struct wlr_xdg_popup *popup = wlr_xdg_popup_try_from_wlr_surface(surface);
|
struct wlr_xdg_popup *popup = wlr_xdg_popup_try_from_wlr_surface(surface);
|
||||||
LayerSurface *l = NULL;
|
LayerSurface *l = NULL;
|
||||||
|
|
@ -26,9 +38,11 @@ void commitpopup(struct wl_listener *listener, void *data) {
|
||||||
free(listener);
|
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)
|
static void createpopup(struct wl_listener *listener, void *data) {
|
||||||
* creates a new popup. */
|
|
||||||
struct wlr_xdg_popup *popup = data;
|
struct wlr_xdg_popup *popup = data;
|
||||||
LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup);
|
LISTEN_STATIC(&popup->base->surface->events.commit, commitpopup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CRYWL_LSTN_POPUP_H */
|
||||||
|
|
||||||
22
src/main.c
22
src/main.c
|
|
@ -71,30 +71,8 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
/* global event handlers */
|
/* 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_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_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 */
|
/* configuration, allows nested code to access above variables */
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue