static void dir_focus(ClientWin *cw, match_func match, dist_func func) { float diff = 0.0; ClientWin *candidate = NULL; dlist *iter, *candidates; candidates = dlist_first(dlist_find_all(cw->mainwin->cod, (dlist_match_func)match, &cw->mini)); if(! candidates) return; for(iter = dlist_first(candidates); iter; iter = iter->next) { ClientWin *win = (ClientWin *)iter->data; float distance = func(&cw->mini, &win->mini); if(! candidate || distance < diff) { candidate = win; diff = distance; } } XWarpPointer(candidate->mainwin->ps->dpy, None, candidate->mini.window, 0, 0, 0, 0, candidate->mini.width / 2, candidate->mini.height / 2); XSetInputFocus(candidate->mainwin->ps->dpy, candidate->mini.window, RevertToParent, CurrentTime); dlist_free(candidates); }
static dlist * do_layout(MainWin *mw, dlist *clients, Window focus, Window leader) { unsigned long desktop = wm_get_current_desktop(mw->dpy); unsigned int width, height; float factor; int xoff, yoff; dlist *iter, *tmp; /* Update the client table, pick the ones we want and sort them */ clients = update_clients(mw, clients, 0); if(mw->cod) dlist_free(mw->cod); tmp = dlist_first(dlist_find_all(clients, (dlist_match_func)clientwin_validate_func, &desktop)); if(leader != None) { mw->cod = dlist_first(dlist_find_all(tmp, clientwin_check_group_leader_func, (void*)&leader)); dlist_free(tmp); } else mw->cod = tmp; if(! mw->cod) return clients; dlist_sort(mw->cod, clientwin_sort_func, 0); /* Move the mini windows around */ layout_run(mw, mw->cod, &width, &height); factor = (float)(mw->width - 100) / width; if(factor * height > mw->height - 100) factor = (float)(mw->height - 100) / height; xoff = (mw->width - (float)width * factor) / 2; yoff = (mw->height - (float)height * factor) / 2; mainwin_transform(mw, factor); for(iter = mw->cod; iter; iter = iter->next) clientwin_move((ClientWin*)iter->data, factor, xoff, yoff); /* Get the currently focused window and select which mini-window to focus */ iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)focus); if(! iter) iter = mw->cod; mw->focus = (ClientWin*)iter->data; mw->focus->focused = 1; /* Map the client windows */ for(iter = mw->cod; iter; iter = iter->next) clientwin_map((ClientWin*)iter->data); XWarpPointer(mw->dpy, None, mw->focus->mini.window, 0, 0, 0, 0, mw->focus->mini.width / 2, mw->focus->mini.height / 2); return clients; }
static dlist * update_clients(MainWin *mw, dlist *clients, Bool *touched) { dlist *stack, *iter; stack = dlist_first(wm_get_stack(mw->dpy)); iter = clients = dlist_first(clients); if(touched) *touched = False; /* Terminate clients that are no longer managed */ while(iter) { ClientWin *cw = (ClientWin *)iter->data; if(! dlist_find_data(stack, (void *)cw->client.window)) { dlist *tmp = iter->next; clientwin_destroy((ClientWin *)iter->data, True); clients = dlist_remove(iter); iter = tmp; if(touched) *touched = True; continue; } clientwin_update(cw); iter = iter->next; } /* Add new clients */ for(iter = dlist_first(stack); iter; iter = iter->next) { ClientWin *cw = (ClientWin*)dlist_find(clients, clientwin_cmp_func, iter->data); if(! cw && (Window)iter->data != mw->window) { cw = clientwin_create(mw, (Window)iter->data); if(! cw) continue; clients = dlist_add(clients, cw); clientwin_update(cw); if(touched) *touched = True; } } dlist_free(stack); return clients; }
dlist * dlist_find_data(dlist *l, void *data) { for(l = dlist_first(l); l; l = l->next) if(l->data == data) break; return l; }
dlist * dlist_find(dlist *l, dlist_match_func func, void *data) { for(l = dlist_first(l); l; l = l->next) if(func(l, data)) break; return l; }
int dlist_same(dlist *l1, dlist *l2) { l1 = dlist_first(l1); while(l1) { if(l1 == l2) return 1; l1 = l1->next; } return 0; }
dlist * dlist_nth(dlist *l, unsigned int n) { unsigned int i = 0; l = dlist_first(l); while(l && i != n) { i++; l = l->next; } return l; }
void msgque_flush() { pts_t pts = (pts_t)pthread_getspecific(g_msg_que_key); if(pts){ struct dnode *dln = dlist_first(&pts->per_thread_que); while(dln && dln != &pts->per_thread_que.tail){ ptq_t ptq = (ptq_t)dln; ptq->write_que.flag = 1;_flush_local(ptq);ptq->write_que.flag = 0; dln = dln->next; } } }
void dlist_free_data(dlist *l) { l = dlist_first(l); while(l) { if(l->data) free(l->data); l->data = 0; l = l->next; } }
static dlist * update_clients(MainWin *mw, dlist *clients) { dlist *stack, *iter; stack = dlist_first(wm_get_stack(mw->dpy)); iter = clients = dlist_first(clients); while(iter) { ClientWin *cw = (ClientWin *)iter->data; if(! dlist_find_data(stack, (void *)cw->client.window)) { dlist *tmp = iter->next; clientwin_destroy((ClientWin *)iter->data); clients = dlist_remove(iter); iter = tmp; continue; } clientwin_update(cw); iter = iter->next; } for(iter = dlist_first(stack); iter; iter = iter->next) { ClientWin *cw = (ClientWin*)dlist_find(clients, clientwin_cmp_func, iter->data); if(! cw) { cw = clientwin_create(mw, (Window)iter->data); if(! cw) continue; clients = dlist_add(clients, cw); clientwin_update(cw); } } dlist_free(stack); return clients; }
dlist * dlist_prepend(dlist *l, void *d) { dlist *new_elem; l = dlist_first(l); new_elem = malloc(sizeof(dlist)); new_elem->prev = 0; new_elem->next = l; new_elem->data = d; if(l) l->prev = new_elem; return new_elem; }
unsigned int dlist_len(dlist *l) { unsigned int n = 0; l = dlist_first(l); while(l) { n++; l = l->next; } return n; }
dlist * dlist_dup(dlist *l) { dlist *n = 0; l = dlist_first(l); while(l) { n = dlist_add(n, l->data); l = l->next; } return n; }
dlist * dlist_free(dlist *l) { l = dlist_first(l); while(l) { dlist *c = l; l = l->next; free(c); } return 0; }
dlist * dlist_find_all(dlist *l, dlist_match_func match, void *data) { dlist *n = 0; l = dlist_first(l); while(l) { if(match(l, data)) n = dlist_add(n, l->data); l = l->next; } return n; }
void dlist_reverse(dlist *l) { dlist *iter1 = dlist_first(l), *iter2 = dlist_last(l); while(iter1 != iter2) { dlist_swap(iter1, iter2); if(iter1->next == iter2) break; iter1 = iter1->next; iter2 = iter2->prev; } }
dlist * dlist_free_with_func(dlist *l, dlist_free_func func) { l = dlist_first(l); while(l) { dlist *c = l; if(l->data) func(l->data); l = l->next; free(c); } return 0; }
dlist * dlist_free_with_data(dlist *l) { l = dlist_first(l); while(l) { dlist *c = l; if(l->data) free(l->data); l = l->next; free(c); } return 0; }
const char * config_get(dlist *config, const char *section, const char *key, const char *def) { ConfigEntry needle; dlist *iter; needle.section = (char *)section; needle.key = (char *)key; iter = dlist_find(dlist_first(config), (dlist_match_func)entry_find_func, &needle); if(! iter) return def; return ((ConfigEntry*)iter->data)->value; }
void dlist_sort(dlist *l, dlist_cmp_func cmp, void *data) { dlist *start = dlist_first(l); while(start) { dlist *iter = start; start = 0; while(iter) { if(iter->next && cmp(iter, iter->next, data) == 1) { dlist_swap(iter, iter->next); if(! start) start = iter->prev; } iter = iter->next; } } }
static void* heart_beat_routine(void *arg){ while(1){ mutex_lock(g_heart_beat->mtx); struct dnode *dn = dlist_first(&g_heart_beat->thread_structs); if(dn){ while(dn != &g_heart_beat->thread_structs.tail) { pts_t pts =(pts_t)dn; pthread_kill(pts->thread_id,SIGUSR1); dn = dn->next; } } mutex_unlock(g_heart_beat->mtx); usleep(msgque_flush_time*1000); } return NULL; }
static dlist * entry_set(dlist *config, const char *section, char *key, char *value) { dlist *iter = dlist_first(config); ConfigEntry *entry; for(; iter; iter = iter->next) { entry = (ConfigEntry *)iter->data; if(! strcasecmp(entry->section, section) && ! strcasecmp(entry->key, key)) { free(key); free(entry->value); entry->value = value; return config; } } entry = entry_new(section, key, value); return dlist_add(config, entry); }
void heart_beat_signal_handler(int sig) { //block_sigusr1(); pts_t pts = (pts_t)pthread_getspecific(g_msg_que_key); if(pts){ struct dnode *dln = dlist_first(&pts->per_thread_que); while(dln && dln != &pts->per_thread_que.tail){ ptq_t ptq = (ptq_t)dln; if(ptq->write_que.flag == 0){ _flush_local(ptq); }else{ ptq->write_que.flag = 2; } dln = dln->next; } } //unblock_sigusr1(); }
static dlist * skippy_run(MainWin *mw, dlist *clients, Window focus, Window leader, Bool all_xin) { XEvent ev; int die = 0; Bool refocus = False; int last_rendered; /* Update the main window's geometry (and Xinerama info if applicable) */ mainwin_update(mw); #ifdef XINERAMA if(all_xin) mw->xin_active = 0; #else /* ! XINERAMA */ if(all_xin); #endif /* XINERAMA */ /* Map the main window and run our event loop */ if(mw->lazy_trans) { mainwin_map(mw); XFlush(mw->dpy); } clients = do_layout(mw, clients, focus, leader); if(! mw->cod) return clients; /* Map the main window and run our event loop */ if(! mw->lazy_trans) mainwin_map(mw); last_rendered = time_in_millis(); while(! die) { int i, j, now, timeout; int move_x = -1, move_y = -1; struct pollfd r_fd; XFlush(mw->dpy); r_fd.fd = ConnectionNumber(mw->dpy); r_fd.events = POLLIN; if(mw->poll_time > 0) timeout = MAX(0, mw->poll_time + last_rendered - time_in_millis()); else timeout = -1; i = poll(&r_fd, 1, timeout); now = time_in_millis(); if(now >= last_rendered + mw->poll_time) { REDUCE(if( ((ClientWin*)iter->data)->damaged ) clientwin_repair(iter->data), mw->cod); last_rendered = now; } i = XPending(mw->dpy); for(j = 0; j < i; ++j) { XNextEvent(mw->dpy, &ev); if (ev.type == MotionNotify) { move_x = ev.xmotion.x_root; move_y = ev.xmotion.y_root; } else if(ev.type == DestroyNotify || ev.type == UnmapNotify) { dlist *iter = dlist_find(clients, clientwin_cmp_func, (void *)ev.xany.window); if(iter) { ClientWin *cw = (ClientWin *)iter->data; clients = dlist_first(dlist_remove(iter)); iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)ev.xany.window); if(iter) mw->cod = dlist_first(dlist_remove(iter)); clientwin_destroy(cw, True); if(! mw->cod) { die = 1; break; } } } else if (mw->poll_time >= 0 && ev.type == mw->damage_event_base + XDamageNotify) { XDamageNotifyEvent *d_ev = (XDamageNotifyEvent *)&ev; dlist *iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)d_ev->drawable); if(iter) { if(mw->poll_time == 0) clientwin_repair((ClientWin *)iter->data); else ((ClientWin *)iter->data)->damaged = True; } } else if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_q) { DIE_NOW = 1; die = 1; break; } else if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_escape) { refocus = True; die = 1; break; } else if(ev.xany.window == mw->window) die = mainwin_handle(mw, &ev); else if(ev.type == PropertyNotify) { if(ev.xproperty.atom == ESETROOT_PMAP_ID || ev.xproperty.atom == _XROOTPMAP_ID) { mainwin_update_background(mw); REDUCE(clientwin_render((ClientWin *)iter->data), mw->cod); } } else if(mw->tooltip && ev.xany.window == mw->tooltip->window) tooltip_handle(mw->tooltip, &ev); else { dlist *iter; for(iter = mw->cod; iter; iter = iter->next) { ClientWin *cw = (ClientWin *)iter->data; if(cw->mini.window == ev.xany.window) { die = clientwin_handle(cw, &ev); if(die) break; } } if(die) break; } } if(mw->tooltip && move_x != -1) tooltip_move(mw->tooltip, move_x + 20, move_y + 20); }
static dlist * skippy_run(MainWin *mw, dlist *clients, int force, Window focus, Window leader, Bool all_xin) { unsigned int width, height, tree_count, u; float factor; int xoff, yoff; XEvent ev; int die = 0; dlist *iter, *tmp; Window dummy_w, *tree_windows; CARD32 desktop = wm_get_current_desktop(mw->dpy); Bool refocus = False; /* Update the main window's geometry (and Xinerama info if applicable) */ mainwin_update(mw); #ifdef XINERAMA if(all_xin) mw->xin_active = 0; #else /* ! XINERAMA */ if(all_xin); #endif /* XINERAMA */ /* Update the client table, pick the ones we want and sort them */ clients = update_clients(mw, clients); tmp = dlist_first(dlist_find_all(clients, (dlist_match_func)clientwin_validate_func, &desktop)); if(leader != None) { mw->cod = dlist_first(dlist_find_all(tmp, clientwin_check_group_leader_func, (void*)&leader)); dlist_free(tmp); } else mw->cod = tmp; if(! mw->cod) return clients; dlist_sort(mw->cod, clientwin_sort_func, 0); /* Move the mini windows around */ layout_run(mw, mw->cod, &width, &height); factor = (float)(mw->width - 100) / width; if(factor * height > mw->height - 100) factor = (float)(mw->height - 100) / height; xoff = (mw->width - (float)width * factor) / 2; yoff = (mw->height - (float)height * factor) / 2; for(iter = mw->cod; iter; iter = iter->next) clientwin_move((ClientWin*)iter->data, factor, xoff, yoff); /* Get the currently focused window and select which mini-window to focus */ iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)focus); if(! iter) iter = mw->cod; mw->focus = (ClientWin*)iter->data; mw->focus->focused = 1; /* Save the stacking tree */ XQueryTree(mw->dpy, mw->root, &dummy_w, &dummy_w, &tree_windows, &tree_count); mw->stack_touched = False; /* Map the client windows */ for(iter = mw->cod; iter; iter = iter->next) clientwin_map((ClientWin*)iter->data, force); XWarpPointer(mw->dpy, None, mw->focus->mini.window, 0, 0, 0, 0, mw->focus->mini.width / 2, mw->focus->mini.height / 2); /* Restore the stacking order (using XRestackWindows seems like a bad idea) */ if(mw->stack_touched) for(u = 0; u < tree_count; ++u) XRaiseWindow(mw->dpy, tree_windows[u]); XFree(tree_windows); /* Map the main window and run our event loop */ mainwin_map(mw); while(! die) { XNextEvent(mw->dpy, &ev); if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_q) { DIE_NOW = 1; break; } else if(ev.type == DestroyNotify || ev.type == UnmapNotify) { dlist *iter = dlist_find(clients, clientwin_cmp_func, (void *)ev.xany.window); if(iter) { ClientWin *cw = (ClientWin *)iter->data; clients = dlist_first(dlist_remove(iter)); iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)ev.xany.window); if(iter) mw->cod = dlist_first(dlist_remove(iter)); clientwin_destroy(cw); if(! mw->cod) { die = 1; break; } } } else if(ev.xany.window == mw->window) die = mainwin_handle(mw, &ev); else if(ev.type == PropertyNotify && (ev.xproperty.atom == ESETROOT_PMAP_ID || ev.xproperty.atom == _XROOTPMAP_ID)) mainwin_update_background(mw); else if(mw->tooltip && ev.xany.window == mw->tooltip->window) tooltip_handle(mw->tooltip, &ev); else if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_escape) { refocus = True; break; } else { dlist *iter; for(iter = mw->cod; iter; iter = iter->next) { ClientWin *cw = (ClientWin *)iter->data; if(cw->mini.window == ev.xany.window) { die = clientwin_handle(cw, &ev); break; } } } } /* Unmap the main window and clean up */ mainwin_unmap(mw); XFlush(mw->dpy); REDUCE(clientwin_unmap((ClientWin*)iter->data), mw->cod); dlist_free(mw->cod); mw->cod = 0; if(die == 2) DIE_NOW = 1; if(refocus) XSetInputFocus(mw->dpy, focus, RevertToPointerRoot, CurrentTime); return clients; }