1use alloc::vec;
38use alloc::vec::Vec;
39
40use crate::consts::*;
41use crate::keys::*;
42use crate::list::{anim_decay, anim_steps};
43use crate::value::part_id;
44use crate::{Sp, Ui};
45
46const NAT_W: i32 = 320;
47const NAT_H: i32 = 240;
48const EST_DIP: i32 = 40;
49const WHEEL_DIP: i32 = 48;
50const REVEAL_TRIES: u8 = 8;
51
52#[derive(Clone, Default)]
56pub(crate) struct Rows {
57 h: Vec<i32>,
59 sum: Vec<i64>,
61 cnt: Vec<i32>,
62 pub(crate) est: i32,
64 pub(crate) top: usize,
66 pub(crate) off: i32,
67}
68
69fn val(v: i32) -> (i64, i32) {
70 if v == 0 { (0, 0) } else { (v.unsigned_abs() as i64, 1) }
71}
72
73impl Rows {
74 pub(crate) fn len(&self) -> usize {
75 self.h.len()
76 }
77
78 fn est(&self) -> i64 {
79 self.est.max(1) as i64
80 }
81
82 fn rebuild(&mut self) {
83 let n = self.h.len();
84 self.sum = vec![0; n + 1];
85 self.cnt = vec![0; n + 1];
86 for i in 1..=n {
87 let (s, c) = val(self.h[i - 1]);
88 self.sum[i] += s;
89 self.cnt[i] += c;
90 let j = i + (i & i.wrapping_neg());
91 if j <= n {
92 self.sum[j] += self.sum[i];
93 self.cnt[j] += self.cnt[i];
94 }
95 }
96 }
97
98 fn add(&mut self, i: usize, ds: i64, dc: i32) {
99 let mut k = i + 1;
100 while k < self.sum.len() {
101 self.sum[k] += ds;
102 self.cnt[k] += dc;
103 k += k & k.wrapping_neg();
104 }
105 }
106
107 fn put(&mut self, i: usize, v: i32) -> bool {
108 let Some(&old) = self.h.get(i) else { return false };
109 if old == v {
110 return false;
111 }
112 let (s0, c0) = val(old);
113 let (s1, c1) = val(v);
114 self.h[i] = v;
115 self.add(i, s1 - s0, c1 - c0);
116 true
117 }
118
119 pub(crate) fn resize(&mut self, n: usize) {
121 if n == self.h.len() && self.sum.len() == n + 1 {
122 return;
123 }
124 self.h.resize(n, 0);
125 self.rebuild();
126 if self.top >= n {
127 self.top = n.saturating_sub(1);
128 self.off = 0;
129 }
130 }
131
132 pub(crate) fn height(&self, i: usize) -> i32 {
134 match self.h.get(i) {
135 Some(&v) if v != 0 => v.abs(),
136 _ => self.est.max(1),
137 }
138 }
139
140 pub(crate) fn known(&self, i: usize) -> bool {
142 self.h.get(i).is_some_and(|&v| v > 0)
143 }
144
145 pub(crate) fn set(&mut self, i: usize, h: i32) -> bool {
147 self.put(i, h.max(1))
148 }
149
150 pub(crate) fn guess(&mut self, i: usize, h: i32) {
152 if self.h.get(i).is_some_and(|&v| v <= 0) {
153 self.put(i, -h.max(1));
154 }
155 }
156
157 pub(crate) fn forget(&mut self, i: usize) {
159 self.put(i, 0);
160 }
161
162 pub(crate) fn forget_all(&mut self) {
164 self.h.iter_mut().for_each(|v| *v = 0);
165 self.rebuild();
166 }
167
168 pub(crate) fn mean(&self) -> Option<i32> {
170 let n = self.h.len();
171 let (mut s, mut c, mut k) = (0i64, 0i64, n);
172 while k > 0 {
173 s += self.sum[k];
174 c += self.cnt[k] as i64;
175 k &= k - 1;
176 }
177 (c > 0).then(|| (s / c).clamp(1, i32::MAX as i64) as i32)
178 }
179
180 pub(crate) fn prefix(&self, i: usize) -> i64 {
182 let i = i.min(self.h.len());
183 let (mut s, mut c, mut k) = (0i64, 0i64, i);
184 while k > 0 {
185 s += self.sum[k];
186 c += self.cnt[k] as i64;
187 k &= k - 1;
188 }
189 s + (i as i64 - c) * self.est()
190 }
191
192 pub(crate) fn total(&self) -> i64 {
194 self.prefix(self.h.len())
195 }
196
197 pub(crate) fn find(&self, y: i64) -> (usize, i32) {
199 let n = self.h.len();
200 if n == 0 {
201 return (0, 0);
202 }
203 let est = self.est();
204 let (mut pos, mut rem) = (0usize, y.max(0));
205 let mut step = 1usize << (usize::BITS - 1 - n.leading_zeros());
206 while step > 0 {
207 let k = pos + step;
208 if k <= n {
209 let v = self.sum[k] + (step as i64 - self.cnt[k] as i64) * est;
210 if v <= rem {
211 pos = k;
212 rem -= v;
213 }
214 }
215 step >>= 1;
216 }
217 if pos >= n { (n - 1, self.height(n - 1)) } else { (pos, rem.min(i32::MAX as i64) as i32) }
218 }
219
220 pub(crate) fn pos(&self) -> i64 {
222 self.prefix(self.top) + self.off as i64
223 }
224
225 pub(crate) fn set_pos(&mut self, y: i64) {
226 let (t, o) = self.find(y);
227 self.top = t;
228 self.off = o;
229 }
230
231 pub(crate) fn clamp(&mut self, view: i32) {
233 if self.h.is_empty() {
234 self.top = 0;
235 self.off = 0;
236 return;
237 }
238 let n = self.h.len();
239 if self.top >= n {
240 self.top = n - 1;
241 self.off = 0;
242 }
243 while self.off >= self.height(self.top) && self.top + 1 < n {
246 self.off -= self.height(self.top);
247 self.top += 1;
248 }
249 while self.off < 0 && self.top > 0 {
250 self.top -= 1;
251 self.off += self.height(self.top);
252 }
253 self.off = self.off.clamp(0, self.height(self.top) - 1);
254 let max = (self.total() - view as i64).max(0);
255 if self.pos() > max {
256 self.set_pos(max);
257 }
258 }
259
260 pub(crate) fn insert(&mut self, at: usize, n: usize) {
262 let at = at.min(self.h.len());
263 self.h.splice(at..at, core::iter::repeat_n(0, n));
264 self.rebuild();
265 if at <= self.top && self.h.len() > n {
266 self.top += n;
267 }
268 }
269
270 pub(crate) fn remove(&mut self, at: usize, n: usize) {
273 let at = at.min(self.h.len());
274 let end = at.saturating_add(n).min(self.h.len());
275 self.h.drain(at..end);
276 self.rebuild();
277 if self.top >= end {
278 self.top -= end - at;
279 } else if self.top >= at {
280 self.top = at;
281 self.off = 0;
282 }
283 if self.top >= self.h.len() {
284 self.top = self.h.len().saturating_sub(1);
285 self.off = 0;
286 }
287 }
288
289 pub(crate) fn reveal(&mut self, i: usize, view: i32) {
291 if i >= self.h.len() {
292 return;
293 }
294 let y = self.prefix(i) - self.pos();
295 let h = self.height(i) as i64;
296 if y < 0 || h >= view as i64 {
297 self.top = i;
298 self.off = 0;
299 } else if y + h > view as i64 {
300 let p = self.prefix(i) + h - view as i64;
301 self.set_pos(p);
302 }
303 }
304}
305
306#[derive(Clone)]
310pub struct VListState {
311 pub sel: i32,
313 pub estimate: i32,
316 rows: Rows,
317 given: Vec<i32>,
319 key: (i32, i32, u32),
321 pending: i32,
323 t0: i32,
324 reveal: Option<(usize, u8)>,
325 sb_y: i32,
327 sb_pos: i32,
328}
329
330impl Default for VListState {
331 fn default() -> VListState {
332 VListState::new()
333 }
334}
335
336impl VListState {
337 pub fn new() -> VListState {
339 let rows = Rows { est: EST_DIP, ..Rows::default() };
340 VListState { sel: -1, estimate: 0, rows, given: Vec::new(), key: (0, 0, 0), pending: 0, t0: 0, reveal: None, sb_y: i32::MIN, sb_pos: 0 }
341 }
342
343 fn dpi(&self) -> i32 {
344 if self.key.0 > 0 { self.key.0 } else { 96 }
345 }
346
347 pub fn set_height(&mut self, i: usize, dip: i32) {
349 if self.given.len() <= i {
350 if dip <= 0 {
351 return;
352 }
353 self.given.resize(i + 1, 0);
354 }
355 self.given[i] = dip.max(0);
356 if i < self.rows.len() {
357 if dip > 0 {
358 let px = crate::layout::dp_at(dip, self.dpi()).max(1);
359 self.rows.set(i, px);
360 } else {
361 self.rows.forget(i);
362 }
363 }
364 }
365
366 pub fn invalidate(&mut self, i: usize) {
368 if self.given.get(i).is_none_or(|&g| g == 0) {
369 self.rows.forget(i);
370 }
371 }
372
373 pub fn invalidate_all(&mut self) {
375 self.rows.forget_all();
376 self.key.1 = -1;
377 }
378
379 pub fn insert(&mut self, at: usize, n: usize) {
382 self.rows.insert(at, n);
383 if self.given.len() > at {
384 self.given.splice(at..at, core::iter::repeat_n(0, n));
385 }
386 if self.sel >= 0 && self.sel as usize >= at {
387 self.sel += n as i32;
388 }
389 }
390
391 pub fn remove(&mut self, at: usize, n: usize) {
393 self.rows.remove(at, n);
394 if self.given.len() > at {
395 let end = at.saturating_add(n).min(self.given.len());
396 self.given.drain(at..end);
397 }
398 if self.sel >= 0 {
399 let s = self.sel as usize;
400 if s >= at.saturating_add(n) {
401 self.sel -= n as i32;
402 } else if s >= at {
403 self.sel = -1;
404 }
405 }
406 }
407
408 pub fn reveal(&mut self, i: usize) {
410 self.reveal = Some((i, 0));
411 }
412
413 pub fn scroll_to(&mut self, i: usize) {
415 self.rows.top = i;
416 self.rows.off = 0;
417 self.pending = 0;
418 self.reveal = None;
419 }
420
421 pub fn first_visible(&self) -> (usize, i32) {
423 (self.rows.top, self.rows.off)
424 }
425
426 pub fn row_height(&self, i: usize) -> i32 {
428 self.rows.height(i)
429 }
430
431 pub fn row_known(&self, i: usize) -> bool {
433 self.rows.known(i)
434 }
435
436 pub fn set_count(&mut self, n: usize) {
438 self.rows.resize(n);
439 for (i, &g) in self.given.iter().enumerate().take(n) {
440 if g > 0 {
441 let px = crate::layout::dp_at(g, self.dpi()).max(1);
442 self.rows.set(i, px);
443 }
444 }
445 }
446
447 pub fn scroll_pos(&self) -> i64 {
450 self.rows.pos()
451 }
452
453 pub fn set_scroll_pos(&mut self, px: i64) {
455 self.rows.set_pos(px);
456 self.pending = 0;
457 self.reveal = None;
458 }
459
460 pub fn total_height(&self) -> i64 {
462 self.rows.total()
463 }
464}
465
466struct Open {
470 id: u32,
471 st: VListState,
472 count: usize,
473 rect: [i32; 4],
474 rx: i32,
476 rw: i32,
477 y: i32,
479 next: usize,
480 cur: usize,
481 cur_y: i32,
482 vev: u32,
483 ev: u32,
484 old: i32,
485 kdbl: bool,
486 changed: bool,
487 hit0: usize,
488 layer: u32,
489 shown: Option<(i32, i32)>,
491 copy: bool,
493}
494
495#[derive(Default)]
497pub(crate) struct S {
498 open: Vec<Open>,
499}
500
501impl Ui {
502 #[cfg_attr(jfgui_dev, track_caller)]
505 pub fn vlist_begin(&mut self, id: u32, st: &mut VListState, count: usize) -> (usize, usize) {
506 let _src = self.src_scope();
507 let mut s = core::mem::take(st);
508 let r = self.place(self.dp(NAT_W), self.dp(NAT_H));
509 let sbw = self.style.scrollbar_thickness(self);
510 let view = r[3].max(1);
511 let key = (self.wp.rt.dpi, r[2], self.layout_scale());
513 if key != s.key {
514 let dpi_changed = key.0 != s.key.0;
515 s.key = key;
516 s.rows.forget_all();
517 if dpi_changed || s.rows.len() != count {
518 s.rows.resize(count);
519 }
520 for (i, &g) in s.given.iter().enumerate() {
521 if g > 0 && i < count {
522 s.rows.set(i, self.dp(g).max(1));
523 }
524 }
525 }
526 if s.rows.len() != count {
527 s.rows.resize(count);
528 for (i, &g) in s.given.iter().enumerate().take(count) {
529 if g > 0 {
530 s.rows.set(i, self.dp(g).max(1));
531 }
532 }
533 }
534 if s.sel >= count as i32 {
535 s.sel = count as i32 - 1;
536 }
537 s.rows.est = if s.estimate > 0 { self.dp(s.estimate) } else { s.rows.mean().unwrap_or(self.dp(EST_DIP)) }.max(1);
538 self.wp.ctx.last_rect = r;
540 let vev = self.behave(id, HB_FOCUS | HB_OWNKEYS);
541 let old = s.sel;
542 let mut kdbl = false;
543 if vev & EV_FOCUS != 0 && count > 0 {
544 kdbl = self.vl_keys(&mut s, count, view);
545 }
546 if s.pending != 0 {
548 let p0 = s.pending;
549 if self.anim_off {
550 s.pending = 0;
551 } else {
552 let steps = anim_steps(self.now_ms, &mut s.t0);
553 s.pending = anim_decay(p0, 0, steps);
554 }
555 let moved = p0 - s.pending;
556 let p = s.rows.pos() + moved as i64;
557 s.rows.set_pos(p);
558 if s.pending != 0 {
559 self.animating = true;
560 }
561 }
562 let (_, pan) = self.pan_take(id);
564 if pan != 0 {
565 s.pending = 0;
566 s.reveal = None;
567 let p = s.rows.pos() + pan as i64;
568 s.rows.set_pos(p);
569 }
570 if let Some((i, _)) = s.reveal {
571 s.rows.reveal(i, view);
572 }
573 s.rows.clamp(view);
574 let first = s.rows.top.min(count);
575 let mut end = first;
576 let mut y = r[1] - s.rows.off;
577 while end < count && y < r[1] + view {
578 y += s.rows.height(end);
579 end += 1;
580 }
581 self.clip_push(r[0], r[1], r[2], r[3]);
582 let copy = s.rows.total() > view as i64;
584 if copy {
585 self.scroll_copy_begin(id, r[0] as i64, r[1] as i64 - s.rows.pos());
586 }
587 let c = &self.wp.ctx;
588 let (hit0, layer) = (c.hits[c.hit_cur].len(), c.cmd_layer_ui);
589 let rw = (r[2] - sbw).max(1);
590 let y0 = r[1] - s.rows.off;
591 self.m.vlist.open.push(Open {
592 id,
593 st: s,
594 count,
595 rect: r,
596 rx: r[0],
597 rw,
598 y: y0,
599 next: first,
600 cur: usize::MAX,
601 cur_y: 0,
602 vev,
603 ev: 0,
604 old,
605 kdbl,
606 changed: false,
607 hit0,
608 layer,
609 shown: None,
610 copy,
611 });
612 (first, end)
613 }
614
615 fn vl_keys(&mut self, s: &mut VListState, count: usize, view: i32) -> bool {
617 let n = count as i64;
618 let cur = s.sel as i64;
619 let start = if cur < 0 { s.rows.top as i64 } else { cur };
620 let page = |s: &VListState, from: i64, down: bool| -> i64 {
622 let (mut i, mut acc) = (from, 0i64);
623 loop {
624 let next = if down { i + 1 } else { i - 1 };
625 if next < 0 || next >= n {
626 return i;
627 }
628 acc += s.rows.height(next as usize) as i64;
629 if acc > view as i64 {
630 return if i == from { next } else { i };
631 }
632 i = next;
633 }
634 };
635 let mut new = None;
636 if self.key(VK_UP) {
637 new = Some(if cur < 0 { start } else { cur - 1 });
638 }
639 if self.key(VK_DOWN) {
640 new = Some(if cur < 0 { start } else { cur + 1 });
641 }
642 if self.key(VK_HOME) {
643 new = Some(0);
644 }
645 if self.key(VK_END) {
646 new = Some(n - 1);
647 }
648 if self.key(VK_PRIOR) {
649 new = Some(page(s, start, false));
650 }
651 if self.key(VK_NEXT) {
652 new = Some(page(s, start, true));
653 }
654 let enter = cur >= 0 && self.key(VK_RETURN);
655 if let Some(v) = new {
656 let v = v.clamp(0, n - 1);
657 if v != cur {
658 s.sel = v as i32;
659 self.repass();
660 }
661 s.reveal = Some((v as usize, 0));
662 self.wp.ctx.focus_visible = true;
663 }
664 if enter {
665 s.reveal = Some((cur as usize, 0));
666 self.repass();
667 }
668 enter
669 }
670
671 #[cfg_attr(jfgui_dev, track_caller)]
673 pub fn vlist_item_begin(&mut self, i: usize) -> u32 {
674 let _src = self.src_scope();
675 let Some(mut o) = self.m.vlist.open.pop() else {
676 self.warn("ui_vlist_item_begin outside a vlist");
677 return 0;
678 };
679 if o.next < i {
681 for k in o.next..i.min(o.count) {
682 o.y += o.st.rows.height(k);
683 }
684 }
685 o.next = i + 1;
686 let h = o.st.rows.height(i);
687 let rid = o.id.wrapping_add(1).wrapping_add(i as u32);
688 let rect = [o.rx, o.y, o.rw, h];
689 self.wp.ctx.last_rect = rect;
690 let ev0 = self.behave(rid, 0);
691 let mut ev = ev0;
692 let c = &mut self.wp.ctx;
693 if c.active == rid && c.pressed & (1 << BTN_LEFT) != 0 {
694 c.focus = o.id;
695 c.focus_visible = false;
696 }
697 if ev & EV_ACT != 0 && o.st.sel != i as i32 {
698 o.st.sel = i as i32;
699 o.ev |= EV_ACT;
700 self.repass();
701 }
702 let selected = o.st.sel == i as i32;
703 if selected && core::mem::take(&mut o.kdbl) {
704 ev |= EV_DOUBLE;
705 }
706 if ev & EV_DOUBLE != 0 {
707 o.ev |= EV_DOUBLE;
708 }
709 let fl = if o.vev & EV_FOCUS != 0 && self.wp.ctx.focus_visible { 2 } else { 0 };
710 let disabled = self.wp.ctx.last_state == SS_DISABLED as u32;
711 let mut sp = Sp { ev, value: selected as i32, value2: disabled as i32, flags: fl, ..Sp::default() };
712 sp.place(rect);
713 let st = self.style;
714 st.list_row(self, &sp);
715 if selected {
716 self.wp.ctx.last_state |= SS_SELECTED as u32;
717 }
718 self.sem(K_LISTITEM, rid, None, i as i32);
719 let given = o.st.given.get(i).copied().unwrap_or(0) > 0;
721 let px = self.dp(8);
722 self.next_rect_px(o.rx + px, o.y, (o.rw - px * 2).max(1), if given { h } else { 0 });
723 o.cur = i;
724 o.cur_y = o.y;
725 self.m.vlist.open.push(o);
726 self.box_begin(rid | 0xC000_0000, BOX_V | if given { BOX_FIXED } else { 0 } | pad(4), 4);
727 ev0 | (ev & EV_DOUBLE)
728 }
729
730 #[cfg_attr(jfgui_dev, track_caller)]
732 pub fn vlist_item_end(&mut self) {
733 let _src = self.src_scope();
734 self.box_end();
735 let Some(mut o) = self.m.vlist.open.pop() else {
736 return;
737 };
738 let i = o.cur;
739 if i < o.count {
740 let rid = o.id.wrapping_add(1).wrapping_add(i as u32);
741 let given = o.st.given.get(i).copied().unwrap_or(0) > 0;
742 if !given {
743 let mh = self.slot(rid | 0xC000_0000).meash.max(1);
744 if o.st.rows.set(i, mh) {
745 o.changed = true;
746 }
747 }
748 let h = o.st.rows.height(i);
749 if o.st.reveal.is_some_and(|r| r.0 == i) {
750 o.shown = Some((o.cur_y - o.rect[1], h));
751 }
752 o.y = o.cur_y + h;
753 }
754 o.cur = usize::MAX;
755 self.m.vlist.open.push(o);
756 }
757
758 pub fn vlist_sel(&self) -> i32 {
760 self.m.vlist.open.last().map_or(-1, |o| o.st.sel)
761 }
762
763 #[cfg_attr(jfgui_dev, track_caller)]
765 pub fn vlist_end(&mut self, st: &mut VListState) -> u32 {
766 let _src = self.src_scope();
767 let Some(mut o) = self.m.vlist.open.pop() else {
768 return 0;
769 };
770 if o.copy {
771 self.scroll_copy_end();
772 }
773 self.clip_pop();
774 let r = o.rect;
775 let view = r[3].max(1);
776 let s = &mut o.st;
777 if let Some((i, tries)) = s.reveal {
779 let done = match o.shown {
780 Some((y, h)) => (y >= 0 && y + h <= view) || (y == 0 && h >= view) || !o.changed,
781 None => false,
782 };
783 if done || tries >= REVEAL_TRIES || i >= o.count {
784 s.reveal = None;
785 } else {
786 s.reveal = Some((i, tries + 1));
787 self.repass();
788 }
789 }
790 if o.changed {
792 self.repass();
793 }
794 let total = s.rows.total().min(i32::MAX as i64) as i32;
796 if total > view {
797 let sbw = self.style.scrollbar_thickness(self);
798 let sid = part_id(o.id, 1);
802 let c = &self.wp.ctx;
803 let (my, press) = (c.my, c.pressed & (1 << BTN_LEFT) != 0);
804 let held = c.active == sid && c.mbtn & (1 << BTN_LEFT) != 0;
805 let mut pos = if held && !press && my == s.sb_y { s.sb_pos } else { s.rows.pos().min(i32::MAX as i64) as i32 };
806 self.next_rect_px(r[0] + r[2] - sbw, r[1], sbw, r[3]);
807 let ev = self.scrollbar(sid, &mut pos, total, view, true);
808 if ev & EV_ACT != 0 && (press || my != o.st.sb_y) {
809 o.st.rows.set_pos(pos as i64);
810 o.st.pending = 0;
811 o.st.reveal = None;
812 self.repass();
813 }
814 o.st.sb_y = my;
815 o.st.sb_pos = pos;
816 }
817 let s = &mut o.st;
818 let c = &self.wp.ctx;
820 let wy = c.wheel_y;
821 let hot = c.hot;
822 let over = hot != 0 && c.hits[c.hit_cur].get(o.hit0..).is_some_and(|v| v.iter().any(|h| h.id == hot && h.layer as u32 == o.layer));
823 if (over || o.vev & EV_HOVER != 0) && wy != 0 {
824 let step = self.dp(WHEEL_DIP);
825 let d = wy.wrapping_neg().wrapping_mul(step) / 120;
826 let p = s.rows.pos() + (s.pending + d) as i64;
827 let max = (s.rows.total() - view as i64).max(0);
828 if (d < 0 && s.rows.pos() > 0) || (d > 0 && s.rows.pos() < max) || p.clamp(0, max) != s.rows.pos() {
829 if s.pending == 0 {
830 s.t0 = self.now_ms as i32;
831 }
832 s.pending += d;
833 self.wp.ctx.wheel_y = 0;
834 s.reveal = None;
835 if self.anim_off {
836 self.repass();
837 } else {
838 self.animating = true;
839 }
840 }
841 }
842 let max = (s.rows.total() - view as i64).clamp(0, i32::MAX as i64) as i32;
844 let pos = s.rows.pos().clamp(0, i32::MAX as i64) as i32;
845 self.pan_push(o.id, o.hit0, o.layer as u8, true, super::touch::AX_V, [0, pos], [0, max]);
846 let s = &mut o.st;
847 if o.vev & EV_FOCUS != 0 && self.wp.ctx.focus_visible && s.sel < 0 {
849 let st = self.style;
850 st.focus_rect(self, r[0], r[1], r[2], r[3]);
851 }
852 let mut stt = 0;
853 if o.vev & EV_HOVER != 0 {
854 stt |= SS_HOVER as u32;
855 }
856 if o.vev & EV_FOCUS != 0 {
857 stt |= SS_FOCUSED as u32;
858 }
859 self.wp.ctx.last_rect = r;
860 self.wp.ctx.last_state = stt;
861 let sel = s.sel;
862 self.sem(K_LIST, o.id, None, sel).max = o.count as i32;
863 let mut ev = o.ev | (o.vev & (EV_FOCUS | EV_HOVER));
864 if sel != o.old {
865 ev |= EV_ACT;
866 }
867 if o.kdbl {
868 ev |= EV_DOUBLE; }
870 *st = o.st;
871 self.wp.ctx.last_rect = r;
872 ev
873 }
874}