diff options
| author | Johannes Herman <johannes.herman@gmail.com> | 2025-07-29 19:35:59 +0200 |
|---|---|---|
| committer | Johannes Herman <johannes.herman@gmail.com> | 2025-07-29 19:35:59 +0200 |
| commit | 5f7c6f8d08f336c5d18e67c145319a70abe4f61c (patch) | |
| tree | 738c9268d81ffa4fc497d831c7919cf56fee8d17 /dwl.c | |
| parent | 41977d8f791305f91059c1754450682fd5099d95 (diff) | |
sticky and unclutter
Diffstat (limited to 'dwl.c')
| -rw-r--r-- | dwl.c | 114 |
1 files changed, 104 insertions, 10 deletions
@@ -73,7 +73,11 @@ #define MAX(A, B) ((A) > (B) ? (A) : (B)) #define MIN(A, B) ((A) < (B) ? (A) : (B)) #define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS) -#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]) && !(C)->swallowedby) + +#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((((C)->tags & (M)->tagset[(M)->seltags]) && !(C)->swallowedby) || C->issticky)) + +// #define VISIBLEON(C, M) ((M) && (C)->mon == (M) && (((C)->tags & (M)->tagset[(M)->seltags]) || C->issticky)) + #define LENGTH(X) (sizeof X / sizeof X[0]) #define END(A) ((A) + LENGTH(A)) #define TAGMASK ((1u << TAGCOUNT) - 1) @@ -141,7 +145,7 @@ struct Client { #endif unsigned int bw; uint32_t tags; - int isfloating, isurgent, isfullscreen; + int isfloating, isurgent, isfullscreen, issticky; int isterm, noswallow; uint32_t resize; /* configure serial of a pending resize */ pid_t pid; @@ -300,6 +304,8 @@ static void focusstack(const Arg *arg); static Client *focustop(Monitor *m); static void fullscreennotify(struct wl_listener *listener, void *data); static void gpureset(struct wl_listener *listener, void *data); +static void handlecursoractivity(void); +static int hidecursor(void *data); static void handlesig(int signo); static void incnmaster(const Arg *arg); static void inputdevice(struct wl_listener *listener, void *data); @@ -336,6 +342,7 @@ static void setcursor(struct wl_listener *listener, void *data); static void setcursorshape(struct wl_listener *listener, void *data); static void setfloating(Client *c, int floating); static void setfullscreen(Client *c, int fullscreen); +static void setsticky(Client *c, int sticky); static void setgamma(struct wl_listener *listener, void *data); static void setlayout(const Arg *arg); static void setmfact(const Arg *arg); @@ -352,6 +359,7 @@ static void tagmon(const Arg *arg); static Client *termforwin(Client *c); static void tile(Monitor *m); static void togglefloating(const Arg *arg); +static void togglesticky(const Arg *arg); static void togglefullscreen(const Arg *arg); static void toggleswallow(const Arg *arg); static void toggleautoswallow(const Arg *arg); @@ -411,6 +419,14 @@ static struct wlr_pointer_constraint_v1 *active_constraint; static struct wlr_cursor *cursor; static struct wlr_xcursor_manager *cursor_mgr; +static struct wl_event_source *hide_source; +static bool cursor_hidden = false; +static struct { + enum wp_cursor_shape_device_v1_shape shape; + struct wlr_surface *surface; + int hotspot_x; + int hotspot_y; +} last_cursor; static struct wlr_scene_rect *root_bg; static struct wlr_session_lock_manager_v1 *session_lock_mgr; @@ -631,6 +647,7 @@ buttonpress(struct wl_listener *listener, void *data) const Button *b; wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + handlecursoractivity(); switch (event->state) { case WL_POINTER_BUTTON_STATE_PRESSED: @@ -1494,6 +1511,18 @@ focustop(Monitor *m) return NULL; } + +Client * +focustopnotsticky(Monitor *m) +{ + Client *c; + wl_list_for_each(c, &fstack, flink) { + if (VISIBLEON(c, m) && (!c->issticky || !c->isfloating || c->isfullscreen)) + return c; + } + return NULL; +} + void fullscreennotify(struct wl_listener *listener, void *data) { @@ -1547,6 +1576,32 @@ handlesig(int signo) } void +handlecursoractivity(void) +{ + wl_event_source_timer_update(hide_source, cursor_timeout * 1000); + + if (!cursor_hidden) + return; + + cursor_hidden = false; + + if (last_cursor.shape) + wlr_cursor_set_xcursor(cursor, cursor_mgr, + wlr_cursor_shape_v1_name(last_cursor.shape)); + else + wlr_cursor_set_surface(cursor, last_cursor.surface, + last_cursor.hotspot_x, last_cursor.hotspot_y); +} + +int +hidecursor(void *data) +{ + wlr_cursor_unset_image(cursor); + cursor_hidden = true; + return 1; +} + +void incnmaster(const Arg *arg) { if (!arg || !selmon) @@ -1885,6 +1940,7 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d wlr_cursor_move(cursor, device, dx, dy); wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); + handlecursoractivity(); /* Update selmon (even while dragging a window) */ if (sloppyfocus) @@ -1909,7 +1965,7 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d /* If there's no client surface under the cursor, set the cursor image to a * default. This is what makes the cursor image appear when you move it * off of a client or over its border. */ - if (!surface && !seat->drag) + if (!surface && !seat->drag && !cursor_hidden) wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); pointerfocus(c, surface, sx, sy, time); @@ -2307,6 +2363,7 @@ run(char *startup_cmd) * monitor when displayed here */ wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y); wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); + handlecursoractivity(); /* Run the Wayland event loop. This does not return until you exit the * compositor. Starting the backend rigged up all of the necessary event @@ -2330,9 +2387,16 @@ setcursor(struct wl_listener *listener, void *data) * use the provided surface as the cursor image. It will set the * hardware cursor on the output that it's currently on and continue to * do so as the cursor moves between outputs. */ - if (event->seat_client == seat->pointer_state.focused_client) - wlr_cursor_set_surface(cursor, event->surface, - event->hotspot_x, event->hotspot_y); + if (event->seat_client == seat->pointer_state.focused_client) { + last_cursor.shape = 0; + last_cursor.surface = event->surface; + last_cursor.hotspot_x = event->hotspot_x; + last_cursor.hotspot_y = event->hotspot_y; + + if (!cursor_hidden) + wlr_cursor_set_surface(cursor, event->surface, + event->hotspot_x, event->hotspot_y); + } } void @@ -2344,9 +2408,14 @@ setcursorshape(struct wl_listener *listener, void *data) /* This can be sent by any client, so we check to make sure this one is * actually has pointer focus first. If so, we can tell the cursor to * use the provided cursor shape. */ - if (event->seat_client == seat->pointer_state.focused_client) - wlr_cursor_set_xcursor(cursor, cursor_mgr, - wlr_cursor_shape_v1_name(event->shape)); + if (event->seat_client == seat->pointer_state.focused_client) { + last_cursor.shape = event->shape; + last_cursor.surface = NULL; + + if (!cursor_hidden) + wlr_cursor_set_xcursor(cursor, cursor_mgr, + wlr_cursor_shape_v1_name(event->shape)); + } } void @@ -2401,6 +2470,17 @@ setgamma(struct wl_listener *listener, void *data) } void +setsticky(Client *c, int sticky) +{ + if(sticky && !c->issticky) { + c->issticky = 1; + } else if(!sticky && c->issticky) { + c->issticky = 0; + arrange(c->mon); + } +} + +void setlayout(const Arg *arg) { if (!selmon) @@ -2623,6 +2703,9 @@ setup(void) relative_pointer_mgr = wlr_relative_pointer_manager_v1_create(dpy); + hide_source = wl_event_loop_add_timer(wl_display_get_event_loop(dpy), + hidecursor, cursor); + /* * Creates a cursor, which is a wlroots utility for tracking the cursor * image shown on screen. @@ -3030,6 +3113,16 @@ toggleautoswallow(const Arg *arg) } void +togglesticky(const Arg *arg) +{ + Client *c = focustop(selmon); + if(!c) + return; + + setsticky(c, !c->issticky); +} + +void toggletag(const Arg *arg) { uint32_t newtags; @@ -3249,7 +3342,7 @@ view(const Arg *arg) selmon->seltags ^= 1; /* toggle sel tagset */ if (arg->ui & TAGMASK) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - focusclient(focustop(selmon), 1); + focusclient(focustopnotsticky(selmon), 1); arrange(selmon); printstatus(); } @@ -3277,6 +3370,7 @@ virtualpointer(struct wl_listener *listener, void *data) wlr_cursor_attach_input_device(cursor, device); if (event->suggested_output) wlr_cursor_map_input_to_output(cursor, device, event->suggested_output); + handlecursoractivity(); } Monitor * |
