@@ -1735,6 +1735,71 @@ namespace netxs::ui
17351735 }
17361736 };
17371737
1738+ // pro: Keyboard events.
1739+ class keybd
1740+ : public skill
1741+ {
1742+ using skill::boss,
1743+ skill::memo;
1744+
1745+ std::unordered_map<id_t , time> last_key; // keybd: .
1746+ si64 instance_id; // keybd: .
1747+
1748+ public:
1749+ static void forward_release (base& boss, hids& gear)
1750+ {
1751+ auto parent_ptr = boss.base ::This ();
1752+ while ((!gear.handled || gear.keystat == input::key::released) && parent_ptr) // Always pass released key events. Stop on gear.timecod > last_key[gear.id] in pro::keybd (gear.handled).
1753+ {
1754+ parent_ptr->base ::signal (tier::release, input::events::keybd::post , gear);
1755+ parent_ptr = parent_ptr->base ::parent ();
1756+ }
1757+ }
1758+
1759+ keybd (base&&) = delete ;
1760+ keybd (base& boss)
1761+ : skill{ boss },
1762+ instance_id{ datetime::now ().time_since_epoch ().count () }
1763+ {
1764+ boss.LISTEN (tier::general, input::events::die, gear, memo)
1765+ {
1766+ last_key.erase (gear.id );
1767+ };
1768+ boss.LISTEN (tier::release, input::events::keybd::any, gear, memo)
1769+ {
1770+ gear.shared_event = gear.touched && gear.touched != instance_id;
1771+ auto & timecod = last_key[gear.id ];
1772+ if (gear.timecod > timecod)
1773+ {
1774+ timecod = gear.timecod ;
1775+ if (gear.payload == input::keybd::type::keypress && gear.keystat != input::key::interrupted)
1776+ {
1777+ if (!gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdrelease, boss.indexer .anykey_event );
1778+ if (!gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdrelease, gear.vkevent );
1779+ if (!gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdrelease, gear.chevent );
1780+ if (!gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdrelease, gear.scevent );
1781+ }
1782+ }
1783+ else
1784+ {
1785+ gear.set_handled (faux); // faux: Set handled for keybd only.
1786+ gear.keystat = input::key::interrupted; // Forward gear.keystat == input::key::released only once.
1787+ }
1788+ };
1789+ boss.LISTEN (tier::preview, input::events::keybd::any, gear, memo)
1790+ {
1791+ gear.shared_event = gear.touched && gear.touched != instance_id;
1792+ if (gear.payload == input::keybd::type::keypress)
1793+ {
1794+ if (!gear.touched && !gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdpreview, gear.vkevent );
1795+ if (!gear.touched && !gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdpreview, gear.chevent );
1796+ if (!gear.touched && !gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdpreview, gear.scevent );
1797+ if (!gear.touched && !gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdpreview, boss.indexer .anykey_event );
1798+ }
1799+ };
1800+ }
1801+ };
1802+
17381803 // pro: Text input focus tree.
17391804 class focus
17401805 : public skill
@@ -2138,15 +2203,28 @@ namespace netxs::ui
21382203 {
21392204 auto sent = faux;
21402205 auto & chain = get_chain (gear.id );
2206+ auto in_keystat = gear.keystat ;
2207+ auto ou_keystat = gear.keystat ;
2208+ auto in_handled = gear.handled ;
2209+ auto ou_handled = gear.handled ;
21412210 chain.foreach ([&](auto & nexthop, auto & status)
21422211 {
21432212 if (status == state::live)
21442213 {
21452214 sent = true ;
2215+ gear.handled = in_handled; // Split handled state.
2216+ gear.keystat = in_keystat; // Split keystat state.
21462217 nexthop.base ::signal (tier::preview, input::events::keybd::post , gear);
2218+ ou_handled |= gear.handled ; // Combine handled state.
2219+ if (gear.keystat == input::key::interrupted)
2220+ {
2221+ ou_keystat = gear.keystat ;
2222+ }
21472223 }
21482224 });
2149- if (!sent && node_type != mode::relay) // Send key::post event back. The relays themselves will later send it back.
2225+ gear.handled = ou_handled;
2226+ gear.keystat = ou_keystat;
2227+ if (!sent && node_type != mode::relay) // Send key::post event back. The relays themselves will send it back later.
21502228 {
21512229 if constexpr (debugmode)
21522230 {
@@ -2156,12 +2234,7 @@ namespace netxs::ui
21562234 // auto i = 0;
21572235 // }
21582236 }
2159- auto parent_ptr = boss.base ::This ();
2160- while ((!gear.handled || gear.keystat == input::key::released) && parent_ptr) // Always pass released key events.
2161- {
2162- parent_ptr->base ::signal (tier::release, input::events::keybd::post , gear);
2163- parent_ptr = parent_ptr->base ::parent ();
2164- }
2237+ pro::keybd::forward_release (boss, gear);
21652238 }
21662239 };
21672240 // all tier::previews going to outside (upstream)
@@ -2591,60 +2664,6 @@ namespace netxs::ui
25912664 }
25922665 };
25932666
2594- // pro: Keyboard events.
2595- class keybd
2596- : public skill
2597- {
2598- using skill::boss,
2599- skill::memo;
2600-
2601- std::unordered_map<id_t , time> last_key; // keybd: .
2602- si64 instance_id; // keybd: .
2603-
2604- public:
2605- keybd (base&&) = delete ;
2606- keybd (base& boss)
2607- : skill{ boss },
2608- instance_id{ datetime::now ().time_since_epoch ().count () }
2609- {
2610- boss.LISTEN (tier::general, input::events::die, gear, memo)
2611- {
2612- last_key.erase (gear.id );
2613- };
2614- boss.LISTEN (tier::release, input::events::keybd::any, gear, memo)
2615- {
2616- gear.shared_event = gear.touched && gear.touched != instance_id;
2617- auto & timecod = last_key[gear.id ];
2618- if (gear.timecod > timecod)
2619- {
2620- timecod = gear.timecod ;
2621- if (gear.payload == input::keybd::type::keypress)
2622- {
2623- if (!gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdrelease, boss.indexer .anykey_event );
2624- if (!gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdrelease, gear.vkevent );
2625- if (!gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdrelease, gear.chevent );
2626- if (!gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdrelease, gear.scevent );
2627- }
2628- }
2629- else
2630- {
2631- gear.set_handled (faux); // faux: Set handled for keybd only.
2632- }
2633- };
2634- boss.LISTEN (tier::preview, input::events::keybd::any, gear, memo)
2635- {
2636- gear.shared_event = gear.touched && gear.touched != instance_id;
2637- if (gear.payload == input::keybd::type::keypress)
2638- {
2639- if (!gear.touched && !gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdpreview, gear.vkevent );
2640- if (!gear.touched && !gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdpreview, gear.chevent );
2641- if (!gear.touched && !gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdpreview, gear.scevent );
2642- if (!gear.touched && !gear.handled ) input::bindings::dispatch (boss, instance_id, gear, tier::keybdpreview, boss.indexer .anykey_event );
2643- }
2644- };
2645- }
2646- };
2647-
26482667 // pro: Glow gradient filter.
26492668 class grade
26502669 : public skill
0 commit comments