AmendHub

Download:

jcs

/

wallops

/

amendments

/

105

chatter: Fix background window updates

For some reason doing TEPinScroll in a TE of a background window, in
a background tab, does not honor the clip region and draws where it's
not supposed to. Handle this by setting a flag so when we switch to
that window and tab, we'll scroll it down before updating it.
 
Also ditch the tab bar shadow and just use the per-window shadow to
do all drawing. Add a reference counter to it so all callers don't
need to figure out if they're down the chain from an update that has
already called use_shadow.

jcs made amendment 105 2 months ago
--- chatter.c Fri Sep 13 17:51:11 2024 +++ chatter.c Mon Sep 16 09:24:57 2024 @@ -30,6 +30,7 @@ static Handle scrp_rec_h = NULL; static Pattern tab_bar_pattern; static Rect zerorect = { 0, 0, 0, 0 }; +static BitMap shadow_cur_bits; void chatter_layout(struct chatter *chatter, bool init, Rect *init_bounds); void chatter_draw_tab_bar(struct chatter *chatter); @@ -348,10 +349,12 @@ chatter_focus_tab(struct chatter *chatter, struct chat RgnHandle clip; Rect r; + if (chatter->current_tab && chatter->current_tab == tab) + return; + + chatter_use_shadow(chatter); + if (chatter->current_tab) { - if (chatter->current_tab == tab) - return; - /* * Doing the HideControl takes out the top line of our tab bar, * so clip to just above it @@ -389,6 +392,12 @@ chatter_focus_tab(struct chatter *chatter, struct chat chatter->current_tab = tab; + if (tab->need_downscroll) { + chatter_autoscroll(chatter, tab->messages_te, + tab->messages_scroller); + tab->need_downscroll = false; + } + HLock(tab->messages_te); EraseRect(&(*(tab->messages_te))->viewRect); TEActivate(tab->messages_te); @@ -412,6 +421,7 @@ chatter_focus_tab(struct chatter *chatter, struct chat DrawControls(chatter->win); chatter_draw_tab_bar(chatter); + chatter_reveal_shadow(chatter); if (chatter->focusable) chatter_update_menu(chatter->focusable); @@ -460,8 +470,6 @@ chatter_close(struct focusable *focusable) } } - if (chatter->tab_bar.baseAddr) - xfree(&chatter->tab_bar.baseAddr); if (chatter->shadow.baseAddr) xfree(&chatter->shadow.baseAddr); @@ -541,6 +549,9 @@ chatter_idle(struct focusable *focusable, EventRecord chatter_draw_tab_bar(chatter); chatter_update_titlebar(chatter); } + + if (chatter->shadow_refcnt != 0) + panic("shadow refcnt %d", chatter->shadow_refcnt); } void @@ -621,21 +632,6 @@ chatter_draw_tab_bar(struct chatter *chatter) static const char no_connection[] = "Disconnected"; struct chatter_tab *tab; - cur_bits = thePort->portBits; - - if (chatter->tab_bar.baseAddr == 0) { - width = chatter->win->portRect.right - chatter->win->portRect.left; - chatter->tab_bar.rowBytes = (((width - 1) / 16) + 1) * 2; - chatter->tab_bar.baseAddr = xmalloczero( - (long)chatter->tab_bar.rowBytes * TAB_BAR_HEIGHT); - if (chatter->tab_bar.baseAddr == NULL) - panic("malloc(%ld) failed: out of memory", - (long)chatter->tab_bar.rowBytes * TAB_BAR_HEIGHT); - SetRect(&chatter->tab_bar.bounds, 0, 0, width, TAB_BAR_HEIGHT); - } - - SetPortBits(&chatter->tab_bar); - TextFont(geneva); TextSize(9); @@ -645,11 +641,13 @@ chatter_draw_tab_bar(struct chatter *chatter) chatter->ntabs; if (tab_width > MAX_TAB_WIDTH) tab_width = MAX_TAB_WIDTH; - - r.top = 0; - r.bottom = TAB_BAR_HEIGHT; + + HLock(chatter->input_te); r.left = 0; r.right = chatter->win->portRect.right - chatter->win->portRect.left; + r.bottom = (*(chatter->input_te))->viewRect.top; + r.top = r.bottom - TAB_BAR_HEIGHT; + HUnlock(chatter->input_te); FillRect(&r, tab_bar_pattern); r.left--; @@ -725,22 +723,6 @@ chatter_draw_tab_bar(struct chatter *chatter) TextSize(10); TextFace(0); - SetPortBits(&cur_bits); - - HLock(chatter->input_te); - r = chatter->tab_bar.bounds; - r.bottom = (*(chatter->input_te))->viewRect.top; - r.top += r.bottom - TAB_BAR_HEIGHT; - HUnlock(chatter->input_te); - - SLIST_FOREACH(tab, &chatter->tabs_list, list) { - tab->label_rect.top += r.top; - tab->label_rect.bottom += r.top; - } - - CopyBits(&chatter->tab_bar, &thePort->portBits, - &chatter->tab_bar.bounds, &r, srcCopy, nil); - chatter_draw_grow_icon(chatter); } @@ -857,9 +839,7 @@ chatter_mouse_down(struct focusable *focusable, EventR SLIST_FOREACH(ttab, &chatter->tabs_list, list) { if (PtInRect(p, &ttab->label_rect)) { - chatter_use_shadow(chatter); chatter_focus_tab(chatter, ttab); - chatter_reveal_shadow(chatter); return; } } @@ -912,10 +892,6 @@ chatter_resize(struct focusable *focusable, EventRecor SizeWindow(focusable->win, width, height, true); EraseRect(&chatter->win->portRect); - /* chatter_draw_tab_bar will recreate this to the new size */ - if (chatter->tab_bar.baseAddr) - xfree(&chatter->tab_bar.baseAddr); - /* update each tab that isn't the current one */ savergn = NewRgn(); GetClip(savergn); @@ -1108,6 +1084,7 @@ chatter_printf(struct chatter *chatter, struct irc_con StScrpRec *scrp_rec; ScrpSTElement *scrp_ele, *prev_scrp_ele; RgnHandle savergn; + GrafPtr old_port; va_list argptr; size_t len, n, buf_out_len, in_this_style; time_t now = Time; @@ -1258,18 +1235,29 @@ no_overflow: HUnlock(scrp_rec_h); HUnlock(tab->messages_te); - chatter_autoscroll(chatter, tab->messages_te, tab->messages_scroller); - - if (chatter->current_tab == tab) + if (chatter->current_tab == tab && chatter->win == FrontWindow()) + chatter_autoscroll(chatter, tab->messages_te, + tab->messages_scroller); + else + tab->need_downscroll = true; + + if (chatter->current_tab == tab) { tab->have_activity = false; - else { + } else { /* resume normal drawing */ SetClip(savergn); DisposeRgn(savergn); if (!had_activity) { tab->have_activity = true; - chatter_draw_tab_bar(chatter); + if (chatter->win == FrontWindow()) { + chatter_draw_tab_bar(chatter); + } else { + GetPort(&old_port); + SetPort(chatter->win); + InvalRect(&chatter->win->portRect); + SetPort(old_port); + } } } @@ -1462,24 +1450,29 @@ chatter_remove_from_nick_list(struct chatter *chatter, LDelRow(1, pos, tab->nick_list); } -static BitMap shadow_cur_bits; - void chatter_use_shadow(struct chatter *chatter) { + if (++chatter->shadow_refcnt != 1) + return; + shadow_cur_bits = thePort->portBits; SetRect(&chatter->shadow.bounds, 0, 0, chatter->win->portRect.right - chatter->win->portRect.left, chatter->win->portRect.bottom - chatter->win->portRect.top); SetPortBits(&chatter->shadow); + CopyBits(&chatter->win->portBits, &chatter->shadow, + &chatter->shadow.bounds, &chatter->shadow.bounds, srcCopy, nil); } void chatter_reveal_shadow(struct chatter *chatter) { + if (--chatter->shadow_refcnt != 0) + return; + SetPortBits(&shadow_cur_bits); - CopyBits(&chatter->shadow, &chatter->win->portBits, &chatter->shadow.bounds, &chatter->shadow.bounds, srcCopy, nil); ValidRect(&chatter->win->portRect); --- chatter.h Fri Sep 13 17:30:22 2024 +++ chatter.h Mon Sep 16 09:16:13 2024 @@ -80,6 +80,7 @@ struct chatter_tab { ListHandle nick_list; Rect label_rect; bool have_activity; + bool need_downscroll; }; SLIST_HEAD(chatter_tabs_head, chatter_tab); @@ -88,11 +89,11 @@ struct chatter { WindowPtr win; BitMap shadow; Rect shadow_bounds; + short shadow_refcnt; TEHandle input_te; char input[IRC_MAX_MSG_SIZE]; bool quitting; bool need_tab_bar_redraw; - BitMap tab_bar; short ntabs; struct chatter_tabs_head tabs_list; struct chatter_tab *current_tab;