wayland: Phase 69 — WIN_WORKSPACE macro; safe workspace reads without frame
Add WIN_WORKSPACE(w) macro to window.h that returns frame->workspace
when the window has a frame (X11 path) or wwin->workspace when it does
not (Wayland path, set in Phase 67).
Replace all unsafe frame->workspace reads with WIN_WORKSPACE() in:
- window.c: wWindowObscuresWindow (workspace comparison + geometry),
wWindowFocusPrev/Next (same-workspace filter),
wWindowSaveState (state serialization)
- session.c: session save (workspace name lookup)
- switchmenu.c: all five switch-menu workspace comparisons/lookups
Also guard wWindowObscuresWindow's frame->core width/height reads with
a ternary that falls back to client.{width,height} for frameless windows.
This eliminates the last class of NULL frame->workspace dereferences
reachable from workspace-switch, focus-cycle, session-save, and
switch-menu code paths.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2c55725bb6
commit
36aa1c5725
|
|
@ -219,7 +219,7 @@ static WMPropList *makeWindowState(WWindow * wwin, WApplication * wapp)
|
|||
|
||||
name = WMCreatePLString(buffer);
|
||||
cmd = WMCreatePLString(command);
|
||||
workspace = WMCreatePLString(scr->workspaces[wwin->frame->workspace]->name);
|
||||
workspace = WMCreatePLString(scr->workspaces[WIN_WORKSPACE(wwin)]->name);
|
||||
|
||||
shaded = wwin->flags.shaded ? sYes : sNo;
|
||||
miniaturized = wwin->flags.miniaturized ? sYes : sNo;
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ static int menuIndexForWindow(WMenu * menu, WWindow * wwin, int old_pos)
|
|||
move_down = 1;
|
||||
|
||||
if (IS_OMNIPRESENT(tw) || (tw != wwin &&
|
||||
tw->frame->workspace >= wwin->frame->workspace))
|
||||
WIN_WORKSPACE(tw) >= WIN_WORKSPACE(wwin)))
|
||||
return idx - move_down;
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +219,7 @@ void UpdateSwitchMenu(WScreen * scr, WWindow * wwin, int action)
|
|||
snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH, "[*]");
|
||||
else
|
||||
snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH, "[%s]",
|
||||
scr->workspaces[wwin->frame->workspace]->name);
|
||||
scr->workspaces[WIN_WORKSPACE(wwin)]->name);
|
||||
|
||||
if (wwin->flags.hidden) {
|
||||
entry->flags.indicator_type = MI_HIDDEN;
|
||||
|
|
@ -277,7 +277,7 @@ void UpdateSwitchMenu(WScreen * scr, WWindow * wwin, int action)
|
|||
} else {
|
||||
snprintf(entry->rtext, MAX_WORKSPACENAME_WIDTH,
|
||||
"[%s]",
|
||||
scr->workspaces[wwin->frame->workspace]->name);
|
||||
scr->workspaces[WIN_WORKSPACE(wwin)]->name);
|
||||
}
|
||||
|
||||
rt = entry->rtext;
|
||||
|
|
@ -350,12 +350,12 @@ static void UpdateSwitchMenuWorkspace(WScreen *scr, int workspace)
|
|||
for (i = 0; i < menu->entry_no; i++) {
|
||||
wwin = (WWindow *) menu->entries[i]->clientdata;
|
||||
|
||||
if (wwin->frame->workspace == workspace && !IS_OMNIPRESENT(wwin)) {
|
||||
if (WIN_WORKSPACE(wwin) == workspace && !IS_OMNIPRESENT(wwin)) {
|
||||
if (IS_OMNIPRESENT(wwin))
|
||||
snprintf(menu->entries[i]->rtext, MAX_WORKSPACENAME_WIDTH, "[*]");
|
||||
else
|
||||
snprintf(menu->entries[i]->rtext, MAX_WORKSPACENAME_WIDTH, "[%s]",
|
||||
scr->workspaces[wwin->frame->workspace]->name);
|
||||
scr->workspaces[WIN_WORKSPACE(wwin)]->name);
|
||||
menu->flags.realized = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
17
src/window.c
17
src/window.c
|
|
@ -445,13 +445,14 @@ Bool wWindowObscuresWindow(WWindow *wwin, WWindow *obscured)
|
|||
{
|
||||
int w1, h1, w2, h2;
|
||||
|
||||
w1 = wwin->frame->core->width;
|
||||
h1 = wwin->frame->core->height;
|
||||
w2 = obscured->frame->core->width;
|
||||
h2 = obscured->frame->core->height;
|
||||
/* Phase 69: Wayland windows have no frame; use client geometry. */
|
||||
w1 = wwin->frame ? (int)wwin->frame->core->width : (int)wwin->client.width;
|
||||
h1 = wwin->frame ? (int)wwin->frame->core->height : (int)wwin->client.height;
|
||||
w2 = obscured->frame ? (int)obscured->frame->core->width : (int)obscured->client.width;
|
||||
h2 = obscured->frame ? (int)obscured->frame->core->height : (int)obscured->client.height;
|
||||
|
||||
if (!IS_OMNIPRESENT(wwin) && !IS_OMNIPRESENT(obscured)
|
||||
&& wwin->frame->workspace != obscured->frame->workspace)
|
||||
&& WIN_WORKSPACE(wwin) != WIN_WORKSPACE(obscured))
|
||||
return False;
|
||||
|
||||
if (wwin->frame_x + w1 < obscured->frame_x
|
||||
|
|
@ -1704,7 +1705,7 @@ void wWindowFocusPrev(WWindow *wwin, Bool inSameWorkspace)
|
|||
tmp = tmp->prev;
|
||||
|
||||
if (inSameWorkspace)
|
||||
while (tmp && (tmp->frame->workspace != wwin->frame->workspace))
|
||||
while (tmp && (WIN_WORKSPACE(tmp) != WIN_WORKSPACE(wwin)))
|
||||
tmp = tmp->next;
|
||||
|
||||
wWindowSingleFocus(tmp);
|
||||
|
|
@ -1719,7 +1720,7 @@ void wWindowFocusNext(WWindow *wwin, Bool inSameWorkspace)
|
|||
|
||||
tmp = wwin->prev;
|
||||
if (inSameWorkspace)
|
||||
while (tmp && (tmp->frame->workspace != wwin->frame->workspace))
|
||||
while (tmp && (WIN_WORKSPACE(tmp) != WIN_WORKSPACE(wwin)))
|
||||
tmp = tmp->prev;
|
||||
|
||||
wWindowSingleFocus(tmp);
|
||||
|
|
@ -2239,7 +2240,7 @@ void wWindowSaveState(WWindow *wwin)
|
|||
int i;
|
||||
|
||||
memset(data, 0, sizeof(long) * 10);
|
||||
data[0] = wwin->frame->workspace;
|
||||
data[0] = WIN_WORKSPACE(wwin);
|
||||
data[1] = wwin->flags.miniaturized;
|
||||
data[2] = wwin->flags.shaded;
|
||||
data[3] = wwin->flags.hidden;
|
||||
|
|
|
|||
|
|
@ -307,6 +307,10 @@ typedef struct WWindow {
|
|||
#define IS_RESIZABLE(w) (!(WFLAGP((w), no_resizable) || (w)->flags.fullscreen))
|
||||
#define IS_OMNIPRESENT(w) ((w)->flags.omnipresent | WFLAGP(w, omnipresent))
|
||||
#define WINDOW_LEVEL(w) ((w)->frame->core->stacking->window_level)
|
||||
/* Phase 69: safe workspace read for windows that may have no frame (Wayland).
|
||||
* frame->workspace is the authoritative slot for X11 windows; wwin->workspace
|
||||
* is the fallback set in wManageWindow for Wayland windows. */
|
||||
#define WIN_WORKSPACE(w) ((w)->frame ? (w)->frame->workspace : (w)->workspace)
|
||||
|
||||
/*
|
||||
* Changes to this must update wWindowSaveState/getSavedState
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@
|
|||
# 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.
|
||||
# 27. (Phase 69) WIN_WORKSPACE(w) macro added; frame->workspace reads in
|
||||
# wWindowFocusPrev/Next, wWindowObscuresWindow, wWindowSaveState,
|
||||
# session.c, and switchmenu.c replaced with the macro.
|
||||
#
|
||||
# This test grows as wl_backend vtable slots are implemented.
|
||||
#
|
||||
|
|
|
|||
Loading…
Reference in New Issue