Modifying dwl.c to warp cursor in dwl, Wayland Compositor
The Wayland compositor called dwl is written in C in line with suckless philosophy. dwl is a compact, hackable compositor for Wayland based on wlroots. It is intended to fill the same space in the Wayland world that dwm does in X11, primarily in terms of functionality, and secondarily in terms of philosophy.
To add cursorwarp function in dwl, the best way is inserting snippet of codes in focusclient and focusmon functions.
The following snippets of codes goes into focusclient and focusclient functions respectively.
/* cursorwarp - msh added for simple cursorwarp */
if (c && cursor_mode == CurNormal && (cursor->x < c->geom.x ||
cursor->x > c->geom.x + c->geom.width ||
cursor->y < c->geom.y ||
cursor->y > c->geom.y + c->geom.height)) {
wlr_cursor_warp_closest(cursor,
NULL,
c->geom.x + c->geom.width / 2.0,
c->geom.y + c->geom.height / 2.0);
}
/* cursorwarp - msh added the following wlr_cursor_warp_closest */
if (!focustop(selmon)) {
wlr_cursor_warp_closest(cursor, NULL,
selmon->m.x + selmon->m.width / 2.0,
selmon->m.y + selmon->m.height / 2.0);
}
See the following codes of focusclient and focusclient functions.
void focusclient(Client *c, int lift) { /* Copied from wlroots/types/wlr_keyboard_group.c */ struct keyboard_group_device { struct wlr_keyboard *keyboard; struct wl_listener key; struct wl_listener modifiers; struct wl_listener keymap; struct wl_listener repeat_info; struct wl_listener destroy; struct wl_list link; // wlr_keyboard_group.devices }; struct wlr_surface *old = seat->keyboard_state.focused_surface; int unused_lx, unused_ly, old_client_type; Client *old_c = NULL; LayerSurface *old_l = NULL; struct keyboard_group_device *device; struct wlr_keyboard *kb = wlr_seat_get_keyboard(seat); struct wlr_keyboard_group *group = kb ? wlr_keyboard_group_from_wlr_keyboard(kb) : NULL; if (locked) return; /* Raise client in stacking order if requested */ if (c && lift) wlr_scene_node_raise_to_top(&c->scene->node); if (c && client_surface(c) == old) return; if ((old_client_type = toplevel_from_wlr_surface(old, &old_c, &old_l)) == XDGShell) { struct wlr_xdg_popup *popup, *tmp; wl_list_for_each_safe(popup, tmp, &old_c->surface.xdg->popups, link) wlr_xdg_popup_destroy(popup); } /* cursorwarp - msh added for simple cursorwarp */ if (c && cursor_mode == CurNormal && (cursor->x < c->geom.x || cursor->x > c->geom.x + c->geom.width || cursor->y < c->geom.y || cursor->y > c->geom.y + c->geom.height)) { wlr_cursor_warp_closest(cursor, NULL, c->geom.x + c->geom.width / 2.0, c->geom.y + c->geom.height / 2.0); } /* Put the new client atop the focus stack and select its monitor */ if (c && !client_is_unmanaged(c)) { wl_list_remove(&c->flink); wl_list_insert(&fstack, &c->flink); selmon = c->mon; c->isurgent = 0; client_restack_surface(c); /* Don't change border color if there is an exclusive focus or we are * handling a drag operation */ if (!exclusive_focus && !seat->drag) client_set_border_color(c, focuscolor); } /* Deactivate old client if focus is changing */ if (old && (!c || client_surface(c) != old)) { /* If an overlay is focused, don't focus or activate the client, * but only update its position in fstack to render its border with focuscolor * and focus it after the overlay is closed. */ if (old_client_type == LayerShell && wlr_scene_node_coords( &old_l->scene->node, &unused_lx, &unused_ly) && old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { return; } else if (old_c && old_c == exclusive_focus && client_wants_focus(old_c)) { return; /* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg * and probably other clients */ } else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) { client_set_border_color(old_c, bordercolor); client_activate_surface(old, 0); } } printstatus(); /* Update keyboard layout */ if (group) { // Update the first real device, because kb or group->kb is not a real // keyboard and its effective layout gets overwritten device = wl_container_of(group->devices.next, device, link); wlr_keyboard_notify_modifiers(device->keyboard, device->keyboard->modifiers.depressed, device->keyboard->modifiers.latched, device->keyboard->modifiers.locked, c ? c->kblayout_idx : 0 ); } if (!c) { /* With no client, all we have left is to clear focus */ wlr_seat_keyboard_notify_clear_focus(seat); return; } /* Change cursor surface */ motionnotify(0, NULL, 0, 0, 0, 0); /* Have a client, so focus its top-level wlr_surface */ client_notify_enter(client_surface(c), kb); /* Activate the new client */ client_activate_surface(client_surface(c), 1); } void focusmon(const Arg *arg) { int i = 0, nmons = wl_list_length(&mons); if (nmons) { do /* don't switch to disabled mons */ selmon = dirtomon(arg->i); while (!selmon->wlr_output->enabled && i++ < nmons); } /* cursorwarp - msh added the following wlr_cursor_warp_closest */ if (!focustop(selmon)) { wlr_cursor_warp_closest(cursor, NULL, selmon->m.x + selmon->m.width / 2.0, selmon->m.y + selmon->m.height / 2.0); } focusclient(focustop(selmon), 1); }
Comments
Post a Comment