z-index system for wayland
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
fixes clicks penetrating to widgets behind one another and allows MwLLRaiseImpl to be implemented
This commit is contained in:
parent
af472c625c
commit
e1824cffa0
3 changed files with 122 additions and 106 deletions
|
|
@ -341,6 +341,9 @@ struct _MwLLWayland {
|
||||||
|
|
||||||
MwBool is_toplevel;
|
MwBool is_toplevel;
|
||||||
|
|
||||||
|
/* Stacking order among sibling sublevels. Higher values are drawn on top and get the pointer first. */
|
||||||
|
MwI32 z_index;
|
||||||
|
|
||||||
MwBool is_clipping;
|
MwBool is_clipping;
|
||||||
MwRect clip;
|
MwRect clip;
|
||||||
|
|
||||||
|
|
@ -505,6 +508,11 @@ void MwLLWaylandClipboardRead(wl_clipboard_device_context_t* ctx, int clipboard_
|
||||||
/* Flush Wayland events */
|
/* Flush Wayland events */
|
||||||
void MwLLWaylandFlush(MwLL handle);
|
void MwLLWaylandFlush(MwLL handle);
|
||||||
|
|
||||||
|
/* Get the sublevel children of a widget ordered from lowest to highest z-index (ties keep creation order). Free the result with arrfree. */
|
||||||
|
MwLL* MwLLWaylandSublevelsByZIndex(MwLL handle);
|
||||||
|
/* Set a sublevel's z-index and schedule a redraw so the new stacking order is shown. */
|
||||||
|
void MwLLWaylandSetZIndex(MwLL handle, MwI32 z_index);
|
||||||
|
|
||||||
/* recursively dispatch the key event to focused widgets. */
|
/* recursively dispatch the key event to focused widgets. */
|
||||||
void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down);
|
void MwLLRecursiveKeyDispatch(MwLL self, int* k, MwBool down);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -721,33 +721,6 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void recursive_dispatch_mouse_down(MwLL handle, MwMouse* p) {
|
|
||||||
MwWidget h = (MwWidget)handle->common.internal;
|
|
||||||
MwLLDispatch(handle, down, p);
|
|
||||||
if(h) {
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < arrlen(h->children); i++) {
|
|
||||||
MwLLDispatch(h->children[i]->lowlevel, down, p);
|
|
||||||
if(arrlen(h->children[i]->children) > 0) {
|
|
||||||
recursive_dispatch_mouse_down(h->children[i]->lowlevel, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
static void recursive_dispatch_mouse_up(MwLL handle, MwMouse* p) {
|
|
||||||
MwWidget h = (MwWidget)handle->common.internal;
|
|
||||||
MwLLDispatch(handle, up, p);
|
|
||||||
if(h) {
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < arrlen(h->children); i++) {
|
|
||||||
MwLLDispatch(h->children[i]->lowlevel, up, p);
|
|
||||||
if(arrlen(h->children[i]->children) > 0) {
|
|
||||||
recursive_dispatch_mouse_up(h->children[i]->lowlevel, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos) {
|
static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwPoint* _relative_mouse_pos, MwPoint* _absolute_pos) {
|
||||||
MwLL topmost_parent = child;
|
MwLL topmost_parent = child;
|
||||||
MwPoint point;
|
MwPoint point;
|
||||||
|
|
@ -761,9 +734,7 @@ static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwP
|
||||||
if(topmost_parent) {
|
if(topmost_parent) {
|
||||||
/* if the topmost parent is a popup/subwindow then its x/y is irrelevant to us. */
|
/* if the topmost parent is a popup/subwindow then its x/y is irrelevant to us. */
|
||||||
if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP && topmost_parent->wayland.type != MwLL_WAYLAND_TOPLEVEL) {
|
if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP && topmost_parent->wayland.type != MwLL_WAYLAND_TOPLEVEL) {
|
||||||
if(topmost_parent->wayland.x > 0)
|
|
||||||
absolute_pos.x += topmost_parent->wayland.x;
|
absolute_pos.x += topmost_parent->wayland.x;
|
||||||
if(topmost_parent->wayland.y > 0)
|
|
||||||
absolute_pos.y += topmost_parent->wayland.y;
|
absolute_pos.y += topmost_parent->wayland.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -783,22 +754,42 @@ static MwBool hit_detect(MwLL child, MwLL* _topmost_parent, MwPoint* _point, MwP
|
||||||
point.y >= absolute_pos.y && point.y <= absolute_pos.y + child->wayland.wh;
|
point.y >= absolute_pos.y && point.y <= absolute_pos.y + child->wayland.wh;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) {
|
/* deepest, topmost-z sublevel under the pointer, or self if none */
|
||||||
switch(state) {
|
static MwLL find_target(MwLL self, MwPoint* local) {
|
||||||
case WL_POINTER_BUTTON_STATE_PRESSED:
|
MwLL* children = MwLLWaylandSublevelsByZIndex(self);
|
||||||
MwLLDispatch(self, down, &p);
|
MwLL target = self;
|
||||||
break;
|
int i;
|
||||||
case WL_POINTER_BUTTON_STATE_RELEASED:
|
for(i = arrlen(children) - 1; i >= 0; i--) {
|
||||||
MwLLDispatch(self, up, &p);
|
MwLL tp;
|
||||||
|
MwPoint pt, rel, abs;
|
||||||
|
if(hit_detect(children[i], &tp, &pt, &rel, &abs)) {
|
||||||
|
*local = rel;
|
||||||
|
target = find_target(children[i], local);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
arrfree(children);
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
if(self->common.internal) {
|
static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) {
|
||||||
MwWidget w = self->common.internal;
|
MwLL target = find_target(self, &p.point);
|
||||||
|
|
||||||
|
switch(state) {
|
||||||
|
case WL_POINTER_BUTTON_STATE_PRESSED:
|
||||||
|
MwLLDispatch(target, down, &p);
|
||||||
|
break;
|
||||||
|
case WL_POINTER_BUTTON_STATE_RELEASED:
|
||||||
|
MwLLDispatch(target, up, &p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
/* walk from the top of the stack down so that only the highest z-index sublevel under the pointer gets the click */
|
||||||
|
MwLL* children = MwLLWaylandSublevelsByZIndex(self);
|
||||||
int i, n;
|
int i, n;
|
||||||
for(i = 0; i < arrlen(w->children); i++) {
|
for(i = arrlen(children) - 1; i >= 0; i--) {
|
||||||
if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) {
|
MwLL child = children[i];
|
||||||
MwLL child = w->children[i]->lowlevel;
|
|
||||||
MwLL topmost_parent = child;
|
MwLL topmost_parent = child;
|
||||||
MwPoint point;
|
MwPoint point;
|
||||||
MwPoint relative_mouse_pos;
|
MwPoint relative_mouse_pos;
|
||||||
|
|
@ -827,9 +818,10 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mouse_dispatch(child, p, state);
|
mouse_dispatch(child, p, state);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
arrfree(children);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,17 +13,48 @@ MwBool MwWaylandVulkan = MwFALSE;
|
||||||
|
|
||||||
MwBool MwWaylandCairoOnly = MwFALSE;
|
MwBool MwWaylandCairoOnly = MwFALSE;
|
||||||
|
|
||||||
void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)) {
|
MwLL* MwLLWaylandSublevelsByZIndex(MwLL handle) {
|
||||||
|
MwLL* r = NULL;
|
||||||
if(handle->common.internal) {
|
if(handle->common.internal) {
|
||||||
MwWidget w = handle->common.internal;
|
MwWidget w = handle->common.internal;
|
||||||
int i;
|
int i, j;
|
||||||
for(i = 0; i < arrlen(w->children); i++) {
|
for(i = 0; i < arrlen(w->children); i++) {
|
||||||
if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) {
|
|
||||||
MwLL child = w->children[i]->lowlevel;
|
MwLL child = w->children[i]->lowlevel;
|
||||||
func(handle, child);
|
if(child->wayland.type != MwLL_WAYLAND_SUBLEVEL) continue;
|
||||||
|
|
||||||
|
/* insertion sort, stable so that equal z-indexes keep their creation order */
|
||||||
|
arrput(r, child);
|
||||||
|
for(j = arrlen(r) - 1; j > 0 && r[j - 1]->wayland.z_index > child->wayland.z_index; j--) {
|
||||||
|
r[j] = r[j - 1];
|
||||||
|
}
|
||||||
|
r[j] = child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MwLLWaylandSetZIndex(MwLL handle, MwI32 z_index) {
|
||||||
|
MwLL root = handle;
|
||||||
|
|
||||||
|
if(handle->wayland.z_index == z_index) return;
|
||||||
|
handle->wayland.z_index = z_index;
|
||||||
|
|
||||||
|
/* sublevels are composited by their root, so that's what needs to redraw */
|
||||||
|
while(root->wayland.type == MwLL_WAYLAND_SUBLEVEL && root->wayland.parent) {
|
||||||
|
root = root->wayland.parent;
|
||||||
|
}
|
||||||
|
root->wayland.do_cascading_draw = MwTRUE;
|
||||||
|
root->wayland.events_pending = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterate over the sublevel children of a widget, from the bottom of the stack to the top */
|
||||||
|
void MwLLWaylandChildrenIterate(MwLL handle, void (*func)(MwLL handle, MwLL child)) {
|
||||||
|
MwLL* children = MwLLWaylandSublevelsByZIndex(handle);
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < arrlen(children); i++) {
|
||||||
|
func(handle, children[i]);
|
||||||
|
}
|
||||||
|
arrfree(children);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int event_loop(MwLL handle);
|
static int event_loop(MwLL handle);
|
||||||
|
|
@ -813,35 +844,21 @@ static void clip(MwLL handle) {
|
||||||
cy = 0;
|
cy = 0;
|
||||||
mx = toplevel->wayland.ww;
|
mx = toplevel->wayland.ww;
|
||||||
my = toplevel->wayland.wh;
|
my = toplevel->wayland.wh;
|
||||||
// ws is traversed result
|
/* ws is traversed result */
|
||||||
// ws[ws.length - 1] is ignored bc it's toplevel
|
/* ws[arrlen(ws) - 1] is the toplevel, which is the origin */
|
||||||
for(i = arrlen(ws) - 2; i >= 0; i--) {
|
for(i = arrlen(ws) - 2; i >= 0; i--) {
|
||||||
int j;
|
|
||||||
int l = 0;
|
|
||||||
|
|
||||||
x += ws[i]->wayland.x;
|
x += ws[i]->wayland.x;
|
||||||
y += ws[i]->wayland.y;
|
y += ws[i]->wayland.y;
|
||||||
|
|
||||||
for(j = i - 1; j >= 0; j--) {
|
cx = MAX(cx, x);
|
||||||
if(ws[j]->wayland.x > cx) l = 1;
|
cy = MAX(cy, y);
|
||||||
if(ws[j]->wayland.y > cy) l = 1;
|
mx = MIN(mx, x + (int)ws[i]->wayland.ww);
|
||||||
if(l) break;
|
my = MIN(my, y + (int)ws[i]->wayland.wh);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!l) {
|
|
||||||
cx = MAX(cx, ws[i]->wayland.x);
|
|
||||||
cy = MAX(cy, ws[i]->wayland.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
mx = MIN(mx, x + ws[i]->wayland.ww);
|
|
||||||
my = MIN(my, y + ws[i]->wayland.wh);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mx < cx) mx = cx;
|
|
||||||
if(my < cy) my = cy;
|
|
||||||
|
|
||||||
arrfree(ws);
|
arrfree(ws);
|
||||||
|
|
||||||
|
/* fully hidden, clip to an empty rectangle */
|
||||||
if(mx < cx) mx = cx;
|
if(mx < cx) mx = cx;
|
||||||
if(my < cy) my = cy;
|
if(my < cy) my = cy;
|
||||||
|
|
||||||
|
|
@ -1937,21 +1954,20 @@ static MwBool MwLLDoModernImpl(MwLL handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MwLLRaiseImpl(MwLL handle) {
|
static void MwLLRaiseImpl(MwLL handle) {
|
||||||
(void)handle;
|
MwLL* siblings;
|
||||||
/*
|
int n;
|
||||||
|
|
||||||
if(handle->wayland.type == MwLL_WAYLAND_SUBLEVEL) {
|
if(handle->wayland.type != MwLL_WAYLAND_SUBLEVEL || !handle->wayland.parent) {
|
||||||
MwLL topmost_parent = handle;
|
return;
|
||||||
int children_num;
|
|
||||||
while(topmost_parent->wayland.parent) topmost_parent = topmost_parent->wayland.parent;
|
|
||||||
children_num = arrlen(((MwWidget)topmost_parent->common.internal)->children);
|
|
||||||
|
|
||||||
if(children_num > 1) {
|
|
||||||
printf("%d\n", children_num);
|
|
||||||
MwWidget last_child = ((MwWidget)topmost_parent->common.internal)->children[children_num - 1];
|
|
||||||
wl_subsurface_place_above(handle->wayland.sublevel->subsurface, last_child->lowlevel->wayland.framebuffer.surface);
|
|
||||||
}
|
}
|
||||||
}*/
|
|
||||||
|
/* put it one above whichever sibling is currently on top */
|
||||||
|
siblings = MwLLWaylandSublevelsByZIndex(handle->wayland.parent);
|
||||||
|
n = arrlen(siblings);
|
||||||
|
if(n > 0 && siblings[n - 1] != handle) {
|
||||||
|
MwLLWaylandSetZIndex(handle, siblings[n - 1]->wayland.z_index + 1);
|
||||||
|
}
|
||||||
|
arrfree(siblings);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MwLLClipImpl(MwLL handle, MwRect* rect) {
|
static void MwLLClipImpl(MwLL handle, MwRect* rect) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue