diff --git a/configure.ac b/configure.ac index 8d588408..53d65671 100644 --- a/configure.ac +++ b/configure.ac @@ -246,7 +246,7 @@ for try in 1 2; do echo "*** trying without -lgmodule" glib_modules= fi - AM_PATH_GLIB_2_0(2.16.0,,, $glib_modules) + AM_PATH_GLIB_2_0(2.28.0,,, $glib_modules) if test "$GLIB_LIBS"; then if test $glib_modules = gmodule; then AC_DEFINE(HAVE_GMODULE) diff --git a/src/fe-common/core/fe-windows.c b/src/fe-common/core/fe-windows.c index 46c1593b..0afa2914 100644 --- a/src/fe-common/core/fe-windows.c +++ b/src/fe-common/core/fe-windows.c @@ -35,30 +35,83 @@ GSList *windows; /* first in the list is the active window, next is the last active, etc. */ +GSequence *windows_seq; WINDOW_REC *active_win; static int daytag; static int daycheck; /* 0 = don't check, 1 = time is 00:00, check, 2 = time is 00:00, already checked */ +static int window_refnum_lookup(WINDOW_REC *window, void *refnum_p) +{ + int refnum = GPOINTER_TO_INT(refnum_p); + return window->refnum == refnum ? 0 : window->refnum < refnum ? -1 : 1; +} + +static GSequenceIter *windows_seq_begin(void) +{ + return g_sequence_get_begin_iter(windows_seq); +} + +static GSequenceIter *windows_seq_end(void) +{ + return g_sequence_get_end_iter(windows_seq); +} + +static GSequenceIter *windows_seq_insert(WINDOW_REC *rec) +{ + return g_sequence_insert_sorted(windows_seq, rec, (GCompareDataFunc)window_refnum_cmp, NULL); +} + +static GSequenceIter *windows_seq_refnum_lookup(int refnum) +{ + return g_sequence_lookup(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); +} + +static void windows_seq_changed(GSequenceIter *iter) +{ + g_sequence_sort_changed(iter, (GCompareDataFunc)window_refnum_cmp, NULL); +} + +static GSequenceIter *windows_seq_window_lookup(WINDOW_REC *rec) +{ + return g_sequence_lookup(windows_seq, rec, (GCompareDataFunc)window_refnum_cmp, NULL); +} + +/* search to the numerically right iterator of refnum */ +static GSequenceIter *windows_seq_refnum_search_right(int refnum) +{ + return g_sequence_search(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); +} + +/* we want to find the numerically left iterator of refnum, so we + search the right of the previous refnum. but we need to figure out + the case where the iterator is already at the beginning, i.e + iter->refnum >= refnum */ +static GSequenceIter *windows_seq_refnum_search_left(int refnum) +{ + GSequenceIter *iter = windows_seq_refnum_search_right(refnum - 1); + return iter == windows_seq_begin() ? NULL : g_sequence_iter_prev(iter); +} + static int window_get_new_refnum(void) { WINDOW_REC *win; - GSList *tmp; + GSequenceIter *iter, *end; int refnum; refnum = 1; - tmp = windows; - while (tmp != NULL) { - win = tmp->data; + iter = windows_seq_begin(); + end = windows_seq_end(); - if (refnum != win->refnum) { - tmp = tmp->next; - continue; - } + while (iter != end) { + win = g_sequence_get(iter); + + if (refnum != win->refnum) + return refnum; refnum++; - tmp = windows; + iter = g_sequence_iter_next(iter); } return refnum; @@ -73,6 +126,7 @@ WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic) rec->level = settings_get_level("window_default_level"); windows = g_slist_prepend(windows, rec); + windows_seq_insert(rec); signal_emit("window created", 2, rec, GINT_TO_POINTER(automatic)); if (item != NULL) window_item_add(rec, item, automatic); @@ -84,6 +138,19 @@ WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic) return rec; } +static void window_set_refnum0(WINDOW_REC *window, int refnum) +{ + int old_refnum; + + g_return_if_fail(window != NULL); + g_return_if_fail(refnum >= 1); + if (window->refnum == refnum) return; + + old_refnum = window->refnum; + window->refnum = refnum; + signal_emit("window refnum changed", 2, window, GINT_TO_POINTER(old_refnum)); +} + /* removed_refnum was removed from the windows list, pack the windows so there won't be any holes. If there is any holes after removed_refnum, leave the windows behind it alone. */ @@ -91,23 +158,37 @@ static void windows_pack(int removed_refnum) { WINDOW_REC *window; int refnum; + GSequenceIter *iter, *end; - for (refnum = removed_refnum+1;; refnum++) { - window = window_find_refnum(refnum); - if (window == NULL || window->sticky_refnum) + refnum = removed_refnum + 1; + end = windows_seq_end(); + iter = windows_seq_refnum_lookup(refnum); + if (iter == NULL) return; + + while (iter != end) { + window = g_sequence_get(iter); + + if (window == NULL || window->sticky_refnum || window->refnum != refnum) break; - window_set_refnum(window, refnum-1); + window_set_refnum0(window, refnum - 1); + windows_seq_changed(iter); + + refnum++; + iter = g_sequence_iter_next(iter); } } void window_destroy(WINDOW_REC *window) { + GSequenceIter *iter; g_return_if_fail(window != NULL); if (window->destroying) return; window->destroying = TRUE; windows = g_slist_remove(windows, window); + iter = windows_seq_window_lookup(window); + if (iter != NULL) g_sequence_remove(iter); if (active_win == window) { active_win = NULL; /* it's corrupted */ @@ -189,26 +270,32 @@ void window_change_server(WINDOW_REC *window, void *server) void window_set_refnum(WINDOW_REC *window, int refnum) { - GSList *tmp; + GSequenceIter *other_iter, *window_iter; int old_refnum; g_return_if_fail(window != NULL); g_return_if_fail(refnum >= 1); if (window->refnum == refnum) return; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; + other_iter = windows_seq_refnum_lookup(refnum); + window_iter = windows_seq_refnum_lookup(window->refnum); - if (rec->refnum == refnum) { - rec->refnum = window->refnum; - signal_emit("window refnum changed", 2, rec, GINT_TO_POINTER(refnum)); - break; - } + if (other_iter != NULL) { + WINDOW_REC *rec = g_sequence_get(other_iter); + + rec->refnum = window->refnum; + signal_emit("window refnum changed", 2, rec, GINT_TO_POINTER(refnum)); } old_refnum = window->refnum; window->refnum = refnum; signal_emit("window refnum changed", 2, window, GINT_TO_POINTER(old_refnum)); + + if (window_iter != NULL && other_iter != NULL) { + g_sequence_swap(other_iter, window_iter); + } else { + windows_seq_changed(window_iter); + } } void window_set_name(WINDOW_REC *window, const char *name) @@ -346,13 +433,13 @@ WINDOW_REC *window_find_closest(void *server, const char *name, int level) WINDOW_REC *window_find_refnum(int refnum) { - GSList *tmp; + GSequenceIter *iter; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; + iter = windows_seq_refnum_lookup(refnum); + if (iter != NULL) { + WINDOW_REC *rec = g_sequence_get(iter); - if (rec->refnum == refnum) - return rec; + return rec; } return NULL; @@ -400,71 +487,86 @@ WINDOW_REC *window_find_item(SERVER_REC *server, const char *name) int window_refnum_prev(int refnum, int wrap) { - GSList *tmp; - int prev, max; + WINDOW_REC *rec; + GSequenceIter *iter, *end; - max = prev = -1; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; + iter = windows_seq_refnum_search_left(refnum); + end = windows_seq_end(); - if (rec->refnum < refnum && (prev == -1 || rec->refnum > prev)) - prev = rec->refnum; - if (wrap && (max == -1 || rec->refnum > max)) - max = rec->refnum; + if (iter != NULL) { + rec = g_sequence_get(iter); + return rec->refnum; } - return prev != -1 ? prev : max; + if (wrap) { + iter = g_sequence_iter_prev(end); + if (iter != end) { + rec = g_sequence_get(iter); + return rec->refnum; + } + } + + return -1; } int window_refnum_next(int refnum, int wrap) { - GSList *tmp; - int min, next; + WINDOW_REC *rec; + GSequenceIter *iter, *end; - min = next = -1; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; + iter = windows_seq_refnum_search_right(refnum); + end = windows_seq_end(); - if (rec->refnum > refnum && (next == -1 || rec->refnum < next)) - next = rec->refnum; - if (wrap && (min == -1 || rec->refnum < min)) - min = rec->refnum; + if (iter != end) { + rec = g_sequence_get(iter); + return rec->refnum; } - return next != -1 ? next : min; + if (wrap) { + iter = windows_seq_begin(); + if (iter != end) { + rec = g_sequence_get(iter); + return rec->refnum; + } + } + + return -1; } int windows_refnum_last(void) { - GSList *tmp; - int max; + WINDOW_REC *rec; + GSequenceIter *end, *iter; - max = -1; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; - - if (rec->refnum > max) - max = rec->refnum; + end = windows_seq_end(); + iter = g_sequence_iter_prev(end); + if (iter != end) { + rec = g_sequence_get(iter); + return rec->refnum; } - return max; + return -1; } int window_refnum_cmp(WINDOW_REC *w1, WINDOW_REC *w2) { - return w1->refnum < w2->refnum ? -1 : 1; + return w1 == w2 ? 0 : w1->refnum < w2->refnum ? -1 : 1; } GSList *windows_get_sorted(void) { - GSList *tmp, *sorted; + GSequenceIter *iter, *begin; + GSList *sorted; sorted = NULL; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; + iter = windows_seq_end(); + begin = windows_seq_begin(); - sorted = g_slist_insert_sorted(sorted, rec, (GCompareFunc) - window_refnum_cmp); + while (iter != begin) { + iter = g_sequence_iter_prev(iter); + WINDOW_REC *rec = g_sequence_get(iter); + + sorted = g_slist_prepend(sorted, rec); } return sorted; @@ -709,6 +811,7 @@ static void read_settings(void) void windows_init(void) { active_win = NULL; + windows_seq = g_sequence_new(NULL); daycheck = 0; daytag = -1; settings_add_bool("lookandfeel", "window_auto_change", FALSE); settings_add_bool("lookandfeel", "windows_auto_renumber", TRUE); @@ -733,4 +836,6 @@ void windows_deinit(void) signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected); signal_remove("server connect failed", (SIGNAL_FUNC) sig_server_disconnected); signal_remove("setup changed", (SIGNAL_FUNC) read_settings); + g_sequence_free(windows_seq); + windows_seq = NULL; } diff --git a/src/fe-text/statusbar-items.c b/src/fe-text/statusbar-items.c index 0db4f63a..de4499b4 100644 --- a/src/fe-text/statusbar-items.c +++ b/src/fe-text/statusbar-items.c @@ -143,16 +143,34 @@ static char *get_activity_list(MAIN_WINDOW_REC *window, int normal, int hilight) static void item_act(SBAR_ITEM_REC *item, int get_size_only) { char *actlist; + int max_size; - actlist = get_activity_list(item->bar->parent_window, TRUE, TRUE); - if (actlist == NULL) { - if (get_size_only) + if (get_size_only) { + if (activity_list == NULL) item->min_size = item->max_size = 0; + /* Skip activity calculation on regular trigger, only + set dirty */ return; } - statusbar_item_default_handler(item, get_size_only, + actlist = get_activity_list(item->bar->parent_window, TRUE, TRUE); + if (actlist == NULL) { + return; + } + + max_size = item->max_size; + statusbar_item_default_handler(item, TRUE, NULL, actlist, FALSE); + statusbar_item_default_handler(item, FALSE, + NULL, actlist, FALSE); + if (max_size != item->max_size) { + /* Due to above hack of skipping the calculation, we + need to manually trigger the redraw process now or + we won't see the item */ + item->bar->dirty = item->dirty = TRUE; + statusbar_redraw(item->bar, TRUE); + statusbar_redraw_dirty(); + } g_free_not_null(actlist); }