Skip to content

Convert window list to doubly-linked and fix restack prev pointer bug - #46

Open
jEsuSdA wants to merge 1 commit into
tycho-kirchner:masterfrom
jEsuSdA:fix/doubly-linked-list-restack-prev
Open

Convert window list to doubly-linked and fix restack prev pointer bug#46
jEsuSdA wants to merge 1 commit into
tycho-kirchner:masterfrom
jEsuSdA:fix/doubly-linked-list-restack-prev

Conversation

@jEsuSdA

@jEsuSdA jEsuSdA commented Jul 2, 2026

Copy link
Copy Markdown

Summary

Converts the window list from singly-linked to doubly-linked, eliminating O(n) scans in restack_win() and finish_destroy_win(). Also fixes a subtle bug that could cause grey screen regions when restacking windows.

Problem

The window list is currently singly-linked. Both restack_win() and finish_destroy_win() must scan the entire list to find the previous element:

  • restack_win() scans twice (unhook + rehook)
  • finish_destroy_win() scans once per destroyed window

Additionally, restack_win() has a subtle bug when inserting at the end of the list: the previous pointer of the former last node is not updated correctly, which can corrupt the list head pointer. When finish_destroy_win() later frees a window at the end, paint_all() may traverse an empty list and paint nothing → grey screen.

Solution

Add a prev pointer to the win struct and maintain it correctly:

  • add_win(): sets prev when inserting at the head or after another window
  • restack_win(): unhooks and rehooks using prev directly, no linear scan. Tracks new_pred during the rehook loop to correctly set prev when inserting at the end
  • finish_destroy_win(): uses prev pointer to unlink in O(1) instead of scanning from the head

Changes

  • cm-window.h — adds struct _win *prev field
  • fastcompmgr.c — updates add_win(), restack_win(), finish_destroy_win()

Scope

  • make clean && make produces zero warnings, zero errors

Impact

  • restack_win() and finish_destroy_win() are now O(1) instead of O(n)
  • Fixes grey screen bug caused by list head corruption during restack

Currently the window list is singly-linked, so restack_win() and
finish_destroy_win() must scan the entire list to find the previous
element. This is O(n) for both operations.

Add a prev pointer to the win struct and maintain it correctly:

- add_win(): sets prev when inserting at the head or after another window
- restack_win(): unhooks and rehooks using prev directly, no linear scan

This also fixes a subtle bug in restack_win(): when inserting at the
end of the list (new_above not found), the old code could leave the
prev pointer inconsistent, causing finish_destroy_win() to corrupt the
list head and paint_all() to traverse an empty list, resulting in a
grey screen.

finish_destroy_win() now uses the prev pointer to unlink in O(1)
instead of scanning from the head each time.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant