diff --git a/CHANGELOG.md b/CHANGELOG.md index 78fa6a4f9..533db09ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * util:random\_bytes(len) added for CSPRNG byte string * target_input long messages are now marked as multipart * convey tui/tpack state in resize events + * target\_anchorhint added for informing clients about positioning and hierarchy ## Core * respect border attribute in text rasteriser diff --git a/doc/target_anchorhint.lua b/doc/target_anchorhint.lua new file mode 100644 index 000000000..f8e84b86e --- /dev/null +++ b/doc/target_anchorhint.lua @@ -0,0 +1,38 @@ +-- target_anchorhint +-- @short: Inform a target about its coordinates relative to a reference +-- @inargs: vid:tgt, int:type=ANCHORHINT_SEGMENT, int:parent, int:x, int:y, int:z +-- @inargs: vid:tgt, int:type=ANCHORHINT_EXTERNAL, int:parent, int:x, int:y, int:z +-- @inargs: vid:tgt, int:type=ANCHORHINT_PROXY, vid:src, int:parent, int:x, int:y, int:z +-- @inargs: vid:tgt, int:type=ANCHORHINT_PROXY_EXTERNAL, int:src, int:parent, int:x, int:y, int:z +-- @outargs: +-- @longdescr: While ref:target_displayhint can be used to provide additional +-- information about how a client will be presented, it does not carry +-- information about how it will be positioned within some reference frame. +-- This is not as useful since clients can already hint in the other direction +-- through viewport events. +-- +-- The major exceptions are when one client is bridging to other windowing +-- systems (ANCHORHINT_PROXY, ANCHORHINT_PROXY_EXTERNAL), +-- acting as a window manager for nested/embedded subsegments (ANCHORHINT_SEGMENT) +-- or as an out-of-process external window manager (ANCHORHINT_PROXY). +-- *x* and *y* refers to the resolved upper-left corner position of the target, +-- and *z* the stacking or composition order. +-- +-- In such cases target_anchorhint can be used. The type indicates which +-- reference objects that could be provided. If the type contains EXTERNAL the +-- *src* and *parent* arguments will be treated as an opaque externally +-- provided identifier, as with ref:target_displayhint and received through the +-- segment_request and viewport events. +-- +-- The non-external types will have *src* and *parent* verified as valid +-- frameservers and the VIDs substitued for the respective cookie identifier +-- (see ref:launch_target). If these point to an invalid vid or ones without +-- TYPE_FRAMESERVER the event will fail silent and be discarded. +-- +-- @group: targetcontrol +-- @cfunction: targetdisphint +-- @related: target_displayhint, launch_target +function main() +#ifdef MAIN +#endif +end diff --git a/src/engine/arcan_lua.c b/src/engine/arcan_lua.c index 88f534680..47e27d351 100644 --- a/src/engine/arcan_lua.c +++ b/src/engine/arcan_lua.c @@ -196,6 +196,22 @@ typedef int acoord; #define CONST_TRUST_TRANSITIVE 13 #endif +#ifndef CONST_ANCHORHINT_SEGMENT +#define CONST_ANCHORHINT_SEGMENT 10 +#endif + +#ifndef CONST_ANCHORHINT_EXTERNAL +#define CONST_ANCHORHINT_EXTERNAL 11 +#endif + +#ifndef CONST_ANCHORHINT_PROXY +#define CONST_ANCHORHINT_PROXY 12 +#endif + +#ifndef CONST_ANCHORHINT_PROXY_EXTERNAL +#define CONST_ANCHORHINT_PROXY_EXTERNAL 13 +#endif + /* * disable support for all builtin frameservers * which removes most (launch_target and target_alloc remain) @@ -234,6 +250,10 @@ static const int RENDERFMT_RETAIN_ALPHA = RENDERTARGET_RETAIN_ALPHA; static const int DEVICE_INDIRECT = CONST_DEVICE_INDIRECT; static const int DEVICE_DIRECT = CONST_DEVICE_DIRECT; static const int DEVICE_LOST = CONST_DEVICE_LOST; +static const int ANCHORHINT_SEGMENT = CONST_ANCHORHINT_SEGMENT; +static const int ANCHORHINT_EXTERNAL = CONST_ANCHORHINT_EXTERNAL; +static const int ANCHORHINT_PROXY = CONST_ANCHORHINT_PROXY; +static const int ANCHORHINT_PROXY_EXTERNAL = CONST_ANCHORHINT_PROXY_EXTERNAL; #define DBHANDLE arcan_db_get_shared(NULL) @@ -1083,12 +1103,12 @@ static int loadimageasynch(lua_State* ctx) static int imageloaded(lua_State* ctx) { - LUA_TRACE("imageloaded"); + LUA_TRACE("image_loaded"); arcan_vobject* vobj; luaL_checkvid(ctx, 1, &vobj); lua_pushnumber(ctx, vobj->feed.state.tag == ARCAN_TAG_IMAGE); - LUA_ETRACE("load_image_asynch", NULL, 1); + LUA_ETRACE("image_loaded", NULL, 1); } static int moveimage(lua_State* ctx) @@ -4221,8 +4241,10 @@ void arcan_lwa_subseg_ev( case TARGET_COMMAND_PAUSE: case TARGET_COMMAND_UNPAUSE: case TARGET_COMMAND_GRAPHMODE: -/* handled in platform */ - case TARGET_COMMAND_RESET: + case TARGET_COMMAND_ANCHORHINT: /* should probably feed back to know position, + but unclear if _lwa applications should rely + on that */ + case TARGET_COMMAND_RESET: /* handled in platform */ case TARGET_COMMAND_SEEKCONTENT: /* scrolling */ case TARGET_COMMAND_COREOPT: /* dynamic key-value */ case TARGET_COMMAND_SEEKTIME: /* scrolling? */ @@ -7815,6 +7837,71 @@ static int targetdisphint(lua_State* ctx) LUA_ETRACE("target_displayhint", NULL, 2); } +static unsigned int get_vid_token(lua_State* ctx, int ind) +{ + arcan_vobject* vobj; + arcan_vobj_id parent = luaL_checkvid(ctx, ind, &vobj); + if (vobj->feed.state.tag != ARCAN_TAG_FRAMESERV){ + arcan_fatal("target_anchorhint(vid, ANCHORHINT_SEGMENT, " + ">parent<, ...) not connected to a frameserver"); + } + arcan_frameserver* fsrv = vobj->feed.state.ptr; + return fsrv->cookie; +} + +static int targetanchor(lua_State* ctx) +{ + + LUA_TRACE("target_anchorhint"); + arcan_event ev = { + .category = EVENT_TARGET, + .tgt.kind = TARGET_COMMAND_ANCHORHINT + }; + + arcan_vobject* vobj; + arcan_vobj_id vid = luaL_checkvid(ctx, 1, &vobj); + + if (vobj->feed.state.tag != ARCAN_TAG_FRAMESERV){ + arcan_fatal("target_anchorhint(>vid<, ...) not connected to a frameserver"); + } + + int type = luaL_checknumber(ctx, 2); + bool swap_token = false; + bool want_source = false; + int coord_ofs = 4; + + switch (type){ + case CONST_ANCHORHINT_SEGMENT: + ev.tgt.ioevs[4].uiv = get_vid_token(ctx, 3); + break; + case CONST_ANCHORHINT_PROXY: + ev.tgt.ioevs[3].uiv = get_vid_token(ctx, 3); + ev.tgt.ioevs[4].uiv = get_vid_token(ctx, 4); + break; + case CONST_ANCHORHINT_EXTERNAL: + ev.tgt.ioevs[4].uiv = luaL_checknumber(ctx, 3); + ev.tgt.ioevs[5].iv = 1; + coord_ofs = 5; + break; + case CONST_ANCHORHINT_PROXY_EXTERNAL: + ev.tgt.ioevs[3].uiv = luaL_checknumber(ctx, 3); + ev.tgt.ioevs[4].uiv = luaL_checknumber(ctx, 4); + ev.tgt.ioevs[5].iv = 1; + coord_ofs = 5; + break; + default: + arcan_fatal("target_anchorhint(vid, >type<, ..) invalid type value"); + break; + } + + ev.tgt.ioevs[0].uiv = luaL_checknumber(ctx, coord_ofs + 0); + ev.tgt.ioevs[1].uiv = luaL_checknumber(ctx, coord_ofs + 1); + ev.tgt.ioevs[2].uiv = luaL_optnumber(ctx, coord_ofs + 2, 0); + + tgtevent(vid, ev); + LUA_ETRACE("target_anchorhint", NULL, 0); +} + static int targetgraph(lua_State* ctx) { LUA_TRACE("target_graphmode"); @@ -12159,6 +12246,10 @@ void arcan_lua_pushglobalconsts(lua_State* ctx){ {"DEVICE_INDIRECT", DEVICE_INDIRECT}, {"DEVICE_DIRECT", DEVICE_DIRECT}, {"DEVICE_LOST", DEVICE_LOST}, +{"ANCHORHINT_SEGMENT", ANCHORHINT_SEGMENT}, +{"ANCHORHINT_EXTERNAL", ANCHORHINT_EXTERNAL}, +{"ANCHORHINT_PROXY", ANCHORHINT_PROXY}, +{"ANCHORHINT_PROXY_EXTERNAL", ANCHORHINT_PROXY_EXTERNAL}, {"RENDERTARGET_NOSCALE", RENDERTARGET_NOSCALE}, {"RENDERTARGET_SCALE", RENDERTARGET_SCALE}, {"RENDERTARGET_NODETACH", RENDERTARGET_NODETACH}, diff --git a/src/shmif/arcan_shmif_event.h b/src/shmif/arcan_shmif_event.h index 212b10a75..634dd6b6a 100644 --- a/src/shmif/arcan_shmif_event.h +++ b/src/shmif/arcan_shmif_event.h @@ -661,6 +661,7 @@ enum ARCAN_TARGET_COMMAND { * [2].iv : rel_z * [3].uiv : source * [4].uiv : parent + * [5].iv : extns (!0) * * Most clients should not rely or depend on these events. They are mainly * provided to bridge other windowing systems, for pseudo-window management of @@ -672,6 +673,9 @@ enum ARCAN_TARGET_COMMAND { * The Z value may be used to carry stacking or draw order, e.g. < 0 the source * is below the parent (drawn before), with > 0 is above the parent (drawn * after). + * + * If extns is set (!0) the values of source and parent refers to previously + * provded extids from viewport and segment requests rather than segment token. */ TARGET_COMMAND_ANCHORHINT, diff --git a/src/wayland/wlimpl/surf.c b/src/wayland/wlimpl/surf.c index ce4d6b419..c7e0926a9 100644 --- a/src/wayland/wlimpl/surf.c +++ b/src/wayland/wlimpl/surf.c @@ -118,6 +118,18 @@ static void surf_damage(struct wl_client* cl, w *= surf->scale; h *= surf->scale; + if (x < 0) + x = 0; + + if (y < 0) + y = 0; + + if (w < 0) + w = surf->acon.w; + + if (h < 0) + h = surf->acon.h; + trace(TRACE_SURF,"%s:(%"PRIxPTR") @x,y+w,h(%d+%d, %d+%d)", surf->tracetag, (uintptr_t)res, (int)x, (int)w, (int)y, (int)h);