Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 104 additions & 10 deletions cm-window.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

#include <stdio.h>
#include <stdlib.h>

#include <X11/Xatom.h>

Expand All @@ -12,6 +13,109 @@

win *list;

/* Simple open-addressing hash table: Window -> win* */
static win **win_hash = NULL;
static unsigned int win_hash_size = 0;
static unsigned int win_hash_count = 0;
static unsigned int win_hash_tombstones = 0;

#define HASH_INITIAL_SIZE 256
#define HASH_LOAD_FACTOR(num, den) ((num) >= ((den) * 3 / 4))

static unsigned int hash_window(Window id) {
return (unsigned int)id;
}

static Bool win_hash_resize(void) {
unsigned int new_size = win_hash_size ? win_hash_size * 2 : HASH_INITIAL_SIZE;
win **new_hash = calloc(new_size, sizeof(win*));
if (!new_hash) return False;
for (unsigned int i = 0; i < win_hash_size; i++) {
win *w = win_hash[i];
if (w && w != (win*)1) {
unsigned int idx = hash_window(w->id) & (new_size - 1);
while (new_hash[idx]) {
idx = (idx + 1) & (new_size - 1);
}
new_hash[idx] = w;
}
}
free(win_hash);
win_hash = new_hash;
win_hash_size = new_size;
win_hash_tombstones = 0;
return True;
}

void win_hash_insert(win *w) {
if (HASH_LOAD_FACTOR(win_hash_count + 1, win_hash_size)
|| win_hash_tombstones > win_hash_count) {
if (!win_hash_resize()) {
/* OOM: table may still have ~25% free slots because resize triggers at 75%.
* Insertion will proceed, but guard against infinite loops below. */
}
}
unsigned int idx = hash_window(w->id) & (win_hash_size - 1);
unsigned int probes = 0;
while (win_hash[idx] && win_hash[idx] != (win*)1) {
if (win_hash[idx]->id == w->id) {
win_hash[idx] = w; // replace
return;
}
idx = (idx + 1) & (win_hash_size - 1);
if (unlikely(++probes >= win_hash_size)) {
/* Table is completely full of live entries. This should never happen
* because resize triggers at 75%, but guard against pathological OOM. */
return;
}
}
win_hash[idx] = w;
win_hash_count++;
}

void win_hash_remove(Window id) {
if (!win_hash_size) return;
unsigned int idx = hash_window(id) & (win_hash_size - 1);
while (win_hash[idx]) {
if (win_hash[idx] != (win*)1 && win_hash[idx]->id == id) {
win_hash[idx] = (win*)1; // tombstone
win_hash_count--;
win_hash_tombstones++;
return;
}
idx = (idx + 1) & (win_hash_size - 1);
}
}

win* win_hash_lookup(Window id) {
if (!win_hash_size) return NULL;
unsigned int idx = hash_window(id) & (win_hash_size - 1);
while (win_hash[idx]) {
if (win_hash[idx] != (win*)1 && win_hash[idx]->id == id && !win_hash[idx]->destroyed) {
return win_hash[idx];
}
idx = (idx + 1) & (win_hash_size - 1);
}
return NULL;
}

win* find_win_any_state(Window id) {
if (!win_hash_size) return NULL;
unsigned int idx = hash_window(id) & (win_hash_size - 1);
while (win_hash[idx]) {
if (win_hash[idx] != (win*)1 && win_hash[idx]->id == id) {
return win_hash[idx];
}
idx = (idx + 1) & (win_hash_size - 1);
}
return NULL;
}

win* find_win(Window id) {
return win_hash_lookup(id);
}


typedef struct _AtomArr {
Atom *atoms;
unsigned long n_items;
Expand Down Expand Up @@ -69,16 +173,6 @@ static bool win_has_atom(Window window, Atom atom){
}


win* find_win(Window id) {
win *w;
for (w = list; w; w = w->next) {
if (w->id == id && !w->destroyed)
return w;
}
return NULL;
}


win* find_win_any_parent(Window w) {
Window root, parent;
Window *children;
Expand Down
4 changes: 4 additions & 0 deletions cm-window.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,12 @@ typedef struct _win {
extern win *list;

win* find_win(Window id);
win* find_win_any_state(Window id);
win* find_win_any_parent(Window w);

void win_hash_insert(win *w);
void win_hash_remove(Window id);

bool win_state_is_hidden(Window window);
bool win_is_client(Window window);
void win_register_client_events(Window window);
91 changes: 50 additions & 41 deletions fastcompmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1673,6 +1673,9 @@ win_suggest_opacity(win* w, bool* is_userdefined){

static void
add_win(Display *dpy, Window id, Window prev) {
win *existing = find_win_any_state(id);
if (unlikely(existing)) return;

win *new = calloc(1, sizeof(win));
win **p;

Expand Down Expand Up @@ -1745,6 +1748,8 @@ add_win(Display *dpy, Window id, Window prev) {
new->next = *p;
*p = new;

win_hash_insert(new);

if (new->a.map_state == IsViewable) {
new->window_type = determine_wintype(dpy, id, id);
new->opacity = win_suggest_opacity(new, &new->userdefined_opacity);
Expand Down Expand Up @@ -1886,61 +1891,65 @@ circulate_win(Display *dpy, XCirculateEvent *ce) {
}

static void
finish_destroy_win(Display *dpy, Window id) {
win **prev, *w;
finish_destroy_win(Display *dpy, win *w) {
win **prev;

if (!w || !w->destroyed) return;

finish_unmap_win(dpy, w);
win_hash_remove(w->id);

for (prev = &list; (w = *prev); prev = &w->next) {
if (w->id == id && w->destroyed) {
finish_unmap_win(dpy, w);
for (prev = &list; *prev; prev = &(*prev)->next) {
if ((*prev) == w) {
*prev = w->next;
break;
}
}

if (w->alpha_pict) {
XRenderFreePicture(dpy, w->alpha_pict);
w->alpha_pict = None;
}
if (w->alpha_pict) {
XRenderFreePicture(dpy, w->alpha_pict);
w->alpha_pict = None;
}

if (w->alpha_border_pict) {
XRenderFreePicture(dpy, w->alpha_border_pict);
w->alpha_border_pict = None;
}
if (w->alpha_border_pict) {
XRenderFreePicture(dpy, w->alpha_border_pict);
w->alpha_border_pict = None;
}

if (w->shadow_pict) {
XRenderFreePicture(dpy, w->shadow_pict);
w->shadow_pict = None;
}
if (w->shadow_pict) {
XRenderFreePicture(dpy, w->shadow_pict);
w->shadow_pict = None;
}

/* fix leak, from freedesktop repo */
if (w->shadow) {
XRenderFreePicture (dpy, w->shadow);
w->shadow = None;
}
/* fix leak, from freedesktop repo */
if (w->shadow) {
XRenderFreePicture (dpy, w->shadow);
w->shadow = None;
}

if (w->damage != None) {
set_ignore(dpy, NextRequest(dpy));
XDamageDestroy(dpy, w->damage);
w->damage = None;
}
if (w->damage != None) {
set_ignore(dpy, NextRequest(dpy));
XDamageDestroy(dpy, w->damage);
w->damage = None;
}

cleanup_fade(dpy, w);
cleanup_fade(dpy, w);

if (w->border_clip) {
XFixesDestroyRegion(dpy, w->border_clip);
w->border_clip = None;
}
if(w->extents){
XFixesDestroyRegion(dpy, w->extents);
w->extents = None;
}
free(w);
break;
}
if (w->border_clip) {
XFixesDestroyRegion(dpy, w->border_clip);
w->border_clip = None;
}
if(w->extents){
XFixesDestroyRegion(dpy, w->extents);
w->extents = None;
}
free(w);
}

#if HAS_NAME_WINDOW_PIXMAP
static void
destroy_callback(Display *dpy, win *w) {
finish_destroy_win(dpy, w->id);
finish_destroy_win(dpy, w);
}
#endif

Expand All @@ -1960,7 +1969,7 @@ destroy_win(Display *dpy, Window id, Bool fade) {
} else
#endif
{
finish_destroy_win(dpy, id);
finish_destroy_win(dpy, w);
}
}

Expand Down