Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
wlroots-based Wayland compositor with virtual outputs and physical cursor continuity.
Originally forked from dwl.

`LOC: 7442 total, 2878 vwl.c`
`LOC: 7494 total, 2878 vwl.c`

## Features

Expand Down
69 changes: 64 additions & 5 deletions share.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <wlr/interfaces/wlr_output.h>
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/util/box.h>
#include <wlr/util/log.h>

#include "vwl.h"
Expand All @@ -19,6 +21,12 @@ static struct vwl_vout_image_capture_source_manager_v1 *vout_capture_mgr;
static struct wl_event_loop *share_event_loop;
static struct wlr_allocator *share_allocator;
static struct wlr_renderer *share_renderer;
static struct share_cursor {
struct wlr_buffer *buffer;
int32_t hotspot_x;
int32_t hotspot_y;
Client *last_hovered;
} share_cursor;

static bool ensureimagesource(Client *c);
static bool ensurevoutimagesource(VirtualOutput *vout);
Expand Down Expand Up @@ -55,6 +63,7 @@ static struct wl_listener foreign_toplevel_capture_request = {

static size_t last_vout_capture_num;

static void loadcursorimage(struct wlr_xcursor_manager *mgr);
static struct wlr_box voutcapturebox(VirtualOutput *vout);
static void sourceupdateconstraints(struct vout_image_source *source, const struct wlr_output_state *state);
static void rendersource(struct vout_image_source *source);
Expand Down Expand Up @@ -134,7 +143,7 @@ voutcapturebox(VirtualOutput *vout)
{
if (!vout || !vout->mon)
return (struct wlr_box){0};
if (vout->layout_geom.width > 0 && vout->layout_geom.height > 0)
if (!wlr_box_empty(&vout->layout_geom))
return vout->layout_geom;
return vout->mon->window_area;
}
Expand All @@ -155,12 +164,18 @@ share_create_capture_scene(Client *c)
goto fail;
if (!wlr_scene_surface_create(c->image_capture_tree, client_surface(c)))
goto fail;
return true;
} else {
c->image_capture_tree = wlr_scene_xdg_surface_create(&c->image_capture_scene->tree, c->surface.xdg);
if (!c->image_capture_tree)
goto fail;
}

c->image_capture_tree = wlr_scene_xdg_surface_create(&c->image_capture_scene->tree, c->surface.xdg);
if (!c->image_capture_tree)
goto fail;
loadcursorimage(cursor_mgr);
if (share_cursor.buffer) {
c->image_capture_cursor = wlr_scene_buffer_create(&c->image_capture_scene->tree, share_cursor.buffer);
if (c->image_capture_cursor)
wlr_scene_node_set_enabled(&c->image_capture_cursor->node, false);
}

return true;

Expand Down Expand Up @@ -197,6 +212,7 @@ share_destroy_capture_scene(Client *c)
wlr_scene_node_destroy(&c->image_capture_scene->tree.node);
c->image_capture_scene = NULL;
c->image_capture_tree = NULL;
c->image_capture_cursor = NULL;
}

void
Expand All @@ -205,6 +221,9 @@ share_destroy(Client *c)
if (!c)
return;

if (share_cursor.last_hovered == c)
share_cursor.last_hovered = NULL;

if (c->image_capture_source) {
wl_list_remove(&c->image_capture_source_destroy.link);
wl_list_init(&c->image_capture_source_destroy.link);
Expand Down Expand Up @@ -239,6 +258,46 @@ share_update_title(Client *c)
wlr_ext_foreign_toplevel_handle_v1_update_state(c->ext_foreign_toplevel, &state);
}

void
share_update_capture_cursors(double lx, double ly, Client *hovered)
{
if (hovered && (!hovered->image_capture_cursor || !share_is_captured(hovered)))
hovered = NULL;

if (!share_cursor.last_hovered && !hovered)
return;

if (share_cursor.last_hovered && share_cursor.last_hovered != hovered)
wlr_scene_node_set_enabled(&share_cursor.last_hovered->image_capture_cursor->node, false);

share_cursor.last_hovered = hovered;

if (!hovered)
return;

wlr_scene_node_set_position(&hovered->image_capture_cursor->node,
(int)(lx - hovered->geom.x - share_cursor.hotspot_x + hovered->bw),
(int)(ly - hovered->geom.y - share_cursor.hotspot_y + hovered->bw));
wlr_scene_node_set_enabled(&hovered->image_capture_cursor->node, true);
}

static void
loadcursorimage(struct wlr_xcursor_manager *mgr)
{
struct wlr_xcursor *xcursor;
struct wlr_xcursor_image *image;

if (!mgr || share_cursor.buffer)
return;
xcursor = wlr_xcursor_manager_get_xcursor(mgr, "default", 1);
if (!xcursor || xcursor->image_count == 0)
return;
image = xcursor->images[0];
share_cursor.buffer = wlr_xcursor_image_get_buffer(image);
share_cursor.hotspot_x = (int32_t)image->hotspot_x;
share_cursor.hotspot_y = (int32_t)image->hotspot_y;
}

static void
sourceupdateconstraints(struct vout_image_source *source, const struct wlr_output_state *state)
{
Expand Down
1 change: 1 addition & 0 deletions share.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ typedef struct Client Client;
void share_init(struct wl_display *display, struct wl_event_loop *loop, struct wlr_allocator *allocator,
struct wlr_renderer *renderer);
void share_cleanuplisteners(void);
void share_update_capture_cursors(double lx, double ly, Client *hovered);
bool share_create_capture_scene(Client *c);
void share_create_toplevel(Client *c);
void share_destroy_capture_scene(Client *c);
Expand Down
18 changes: 9 additions & 9 deletions vwl.c
Original file line number Diff line number Diff line change
Expand Up @@ -954,7 +954,7 @@ placefloating(Client *c)
if (!c || !c->mon || !client_surface(c)->mapped)
return;
vout = CLIENT_VOUT(c);
if (vout && vout->layout_geom.width > 0 && vout->layout_geom.height > 0)
if (vout && !wlr_box_empty(&vout->layout_geom))
area = vout->layout_geom;
else
area = c->mon->window_area;
Expand Down Expand Up @@ -1224,8 +1224,7 @@ focusclient(Client *c, int lift)
if (selvout && selvout->lt[selvout->sellt] && selvout->lt[selvout->sellt]->arrange == tabbed) {
struct wlr_box area;
tabbed_mon = selvout->mon;
area = (selvout->layout_geom.width && selvout->layout_geom.height) ? selvout->layout_geom
: selvout->mon->window_area;
area = !wlr_box_empty(&selvout->layout_geom) ? selvout->layout_geom : selvout->mon->window_area;
tabhdr_update(selvout->mon, selvout, area, focustoptiledvout(selvout));
}
c->isurgent = 0;
Expand Down Expand Up @@ -1418,7 +1417,7 @@ tabmove(const Arg *arg)

{
struct wlr_box area;
area = (vout->layout_geom.width && vout->layout_geom.height) ? vout->layout_geom : selmon->window_area;
area = !wlr_box_empty(&vout->layout_geom) ? vout->layout_geom : selmon->window_area;
tabhdr_update(selmon, vout, area, sel);
}
focusclient(sel, 1);
Expand Down Expand Up @@ -1691,6 +1690,7 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
hover.vout = hover_vout;
hover.ws = hover_vout ? hover_vout->ws : NULL;
xytonode(cursor->x, cursor->y, NULL, &hover.client, NULL, NULL, NULL);
share_update_capture_cursors(cursor->x, cursor->y, hover.client);

cursorsync();

Expand Down Expand Up @@ -1792,7 +1792,7 @@ resize(Client *c, struct wlr_box geo, int interact)
if (!c->mon || !client_surface(c)->mapped)
return;

limit = (vout && vout->layout_geom.width && vout->layout_geom.height) ? vout->layout_geom : c->mon->window_area;
limit = (vout && !wlr_box_empty(&vout->layout_geom)) ? vout->layout_geom : c->mon->window_area;
bbox = interact ? &sgeom : &limit;

client_set_bounds(c, geo.width, geo.height);
Expand Down Expand Up @@ -1929,7 +1929,7 @@ setfullscreen(Client *c, int fullscreen)
else
wlr_scene_node_reparent(&c->scene->node, layers[LyrTop]);
target = c->mon->monitor_area;
if (c->fullscreen_mode == FS_VIRTUAL && vout && vout->layout_geom.width && vout->layout_geom.height) {
if (c->fullscreen_mode == FS_VIRTUAL && vout && !wlr_box_empty(&vout->layout_geom)) {
target = vout->layout_geom;
if (vout->lt[vout->sellt] && vout->lt[vout->sellt]->arrange == tabbed) {
int header = tabhdr_header_height();
Expand Down Expand Up @@ -2386,7 +2386,7 @@ tabbed(Monitor *m)

if (!vout)
return;
area = (vout->layout_geom.width && vout->layout_geom.height) ? vout->layout_geom : m->window_area;
area = !wlr_box_empty(&vout->layout_geom) ? vout->layout_geom : m->window_area;
active = focustoptiledvout(vout);
header_height = tabhdr_header_height();

Expand Down Expand Up @@ -2440,7 +2440,7 @@ tile(Monitor *m)

if (!vout)
return;
area = (vout->layout_geom.width && vout->layout_geom.height) ? vout->layout_geom : m->window_area;
area = !wlr_box_empty(&vout->layout_geom) ? vout->layout_geom : m->window_area;

wl_list_for_each(c, &clients, link)
if (CLIENT_VOUT(c) == vout && VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
Expand Down Expand Up @@ -2956,7 +2956,7 @@ voutat(Monitor *m, double lx, double ly)
if (!m)
return NULL;
wl_list_for_each(vout, &m->vouts, link) {
if (vout->layout_geom.width <= 0 || vout->layout_geom.height <= 0)
if (wlr_box_empty(&vout->layout_geom))
continue;
if (lx >= vout->layout_geom.x && lx < vout->layout_geom.x + vout->layout_geom.width &&
ly >= vout->layout_geom.y && ly < vout->layout_geom.y + vout->layout_geom.height)
Expand Down
1 change: 1 addition & 0 deletions vwl.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ struct Client {
struct wlr_scene_tree *scene_surface;
struct wlr_scene *image_capture_scene;
struct wlr_scene_tree *image_capture_tree;
struct wlr_scene_buffer *image_capture_cursor;
struct wlr_ext_foreign_toplevel_handle_v1 *ext_foreign_toplevel;
struct wlr_ext_image_capture_source_v1 *image_capture_source;
struct wl_list link;
Expand Down
Loading