wayland: Phase 68 — placement.c: safe overlap calculation without frame
Guard all frame->core and frame->workspace dereferences in placement.c
against NULL frame pointers (Wayland windows have no WFrameWindow):
- calcSumOfCoveredAreas: skip windows without frame (no stacking level
or geometry available via frame; Wayland window client geometry is
tracked separately in wwin->client.* and wwin->frame_x/y).
- window_overlaps: add early-return path for frameless windows that uses
wwin->client.{width,height} and wwin->frame_x/y for the overlap test,
bypassing the frame->core stacking level check.
- getPlaceOrigin (icon-placement helper): guard frame->workspace reads
for WCLASS_MINIWINDOW and WCLASS_WINDOW parent types using logical-OR
with the wwin->workspace fallback.
Together these prevent NULL dereferences when smart/auto/cascade
placement iterates the managed-window list and encounters Wayland
windows alongside X11 windows.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e60dff8ffd
commit
2c55725bb6
|
|
@ -62,7 +62,9 @@ iconPosition(WCoreWindow *wcore, int sx1, int sy1, int sx2, int sy2,
|
|||
|
||||
ok = 1;
|
||||
} else if (wcore->descriptor.parent_type == WCLASS_MINIWINDOW &&
|
||||
(((WIcon *) parent)->owner->frame->workspace == workspace
|
||||
((!((WIcon *) parent)->owner->frame ||
|
||||
((WIcon *) parent)->owner->frame->workspace == workspace ||
|
||||
((WIcon *) parent)->owner->workspace == workspace)
|
||||
|| IS_OMNIPRESENT(((WIcon *) parent)->owner)
|
||||
|| wPreferences.sticky_icons)
|
||||
&& ((WIcon *) parent)->mapped) {
|
||||
|
|
@ -73,7 +75,10 @@ iconPosition(WCoreWindow *wcore, int sx1, int sy1, int sx2, int sy2,
|
|||
ok = 1;
|
||||
} else if (wcore->descriptor.parent_type == WCLASS_WINDOW
|
||||
&& ((WWindow *) parent)->flags.icon_moved
|
||||
&& (((WWindow *) parent)->frame->workspace == workspace || IS_OMNIPRESENT((WWindow *) parent)
|
||||
&& ((!((WWindow *) parent)->frame ||
|
||||
((WWindow *) parent)->frame->workspace == workspace ||
|
||||
((WWindow *) parent)->workspace == workspace)
|
||||
|| IS_OMNIPRESENT((WWindow *) parent)
|
||||
|| wPreferences.sticky_icons)) {
|
||||
*retX = ((WWindow *) parent)->icon_x;
|
||||
*retY = ((WWindow *) parent)->icon_y;
|
||||
|
|
@ -268,6 +273,11 @@ static int calcSumOfCoveredAreas(WWindow *wwin, int x, int y, int w, int h)
|
|||
test_window = test_window->prev;
|
||||
|
||||
for (; test_window != NULL; test_window = test_window->next) {
|
||||
/* Phase 68: Wayland windows have no frame; skip them in the
|
||||
* overlap calculation (their geometry is tracked in client.* but
|
||||
* they have no X11 stacking level — treat as zero obstruction). */
|
||||
if (!test_window->frame)
|
||||
continue;
|
||||
if (test_window->frame->core->stacking->window_level < WMNormalLevel) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -277,8 +287,12 @@ static int calcSumOfCoveredAreas(WWindow *wwin, int x, int y, int w, int h)
|
|||
tx = test_window->frame_x;
|
||||
ty = test_window->frame_y;
|
||||
|
||||
/* Phase 68: guard frame->workspace with wwin->workspace fallback */
|
||||
int tw_workspace = test_window->workspace;
|
||||
if (test_window->frame)
|
||||
tw_workspace = test_window->frame->workspace;
|
||||
if (test_window->flags.mapped || (test_window->flags.shaded &&
|
||||
test_window->frame->workspace == wwin->screen_ptr->current_workspace &&
|
||||
tw_workspace == wwin->screen_ptr->current_workspace &&
|
||||
!(test_window->flags.miniaturized || test_window->flags.hidden))) {
|
||||
sum_isect += calcIntersectionArea(tx, ty, tw, th, x, y, w, h);
|
||||
}
|
||||
|
|
@ -308,6 +322,19 @@ window_overlaps(WWindow *win, int x, int y, int w, int h, Bool ignore_sunken)
|
|||
{
|
||||
int tw, th, tx, ty;
|
||||
|
||||
/* Phase 68: Wayland windows have no frame; use client geometry. */
|
||||
if (!win->frame) {
|
||||
tw = win->client.width;
|
||||
th = win->client.height;
|
||||
tx = win->frame_x;
|
||||
ty = win->frame_y;
|
||||
if ((tx < (x + w)) && ((tx + tw) > x) &&
|
||||
(ty < (y + h)) && ((ty + th) > y) &&
|
||||
win->flags.mapped)
|
||||
return True;
|
||||
return False;
|
||||
}
|
||||
|
||||
if (ignore_sunken &&
|
||||
win->frame->core->stacking->window_level < WMNormalLevel) {
|
||||
return False;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@
|
|||
# 25. (Phase 67) WWindow.workspace added; wWorkspaceForceChange uses it as
|
||||
# fallback when frame==NULL so workspace switching is safe in Wayland
|
||||
# (build-only check — workspace switch requires keyboard shortcuts).
|
||||
# 26. (Phase 68) placement.c guards: calcSumOfCoveredAreas/window_overlaps
|
||||
# skip frameless (Wayland) windows safely; frame->workspace accesses
|
||||
# in icon-placement helpers use wwin->workspace fallback.
|
||||
#
|
||||
# This test grows as wl_backend vtable slots are implemented.
|
||||
#
|
||||
|
|
|
|||
Loading…
Reference in New Issue