diff --git a/src/netxs/apps/tile.hpp b/src/netxs/apps/tile.hpp index db62c5dfb3..0da1f7e329 100644 --- a/src/netxs/apps/tile.hpp +++ b/src/netxs/apps/tile.hpp @@ -244,7 +244,7 @@ namespace netxs::app::tile boss.remove(applet_ptr); applet.moveto(dot_00); world_ptr->bell::signal(tier::request, vtm::events::handoff, what); // Attach to the world. - pro::focus::set(applet_ptr, gear_id_list, solo::off, true); // Refocus. + pro::focus::set(applet_ptr, gear.id, solo::on, true); boss.base::riseup(tier::release, e2::form::proceed::quit::one, true); // Destroy placeholder. if (auto new_parent_ptr = applet.parent()) { @@ -510,7 +510,8 @@ namespace netxs::app::tile if (boss.count() == 1) // Only empty pane/slot available. { highlight(boss, faux); - pro::focus::off(boss.back()); // Unset focus from node_veer if it is focused. + // Solo focus will be set in pro::d_n_d::proceed. + //pro::focus::off(boss.back()); // Unset focus from node_veer if it is focused. auto app = app_window(what); boss.attach(app); app->bell::signal(tier::anycast, e2::form::upon::started); diff --git a/src/netxs/desktopio/application.hpp b/src/netxs/desktopio/application.hpp index 9431a1579c..1c21b7ec5c 100644 --- a/src/netxs/desktopio/application.hpp +++ b/src/netxs/desktopio/application.hpp @@ -24,7 +24,7 @@ namespace netxs::app namespace netxs::app::shared { - static const auto version = "v0.9.99.60"; + static const auto version = "v0.9.99.61"; static const auto repository = "https://github.com/directvt/vtm"; static const auto usr_config = "~/.config/vtm/settings.xml"s; static const auto sys_config = "/etc/vtm/settings.xml"s; diff --git a/src/netxs/desktopio/controls.hpp b/src/netxs/desktopio/controls.hpp index b9904fc9ef..76d60987f4 100644 --- a/src/netxs/desktopio/controls.hpp +++ b/src/netxs/desktopio/controls.hpp @@ -1373,17 +1373,13 @@ namespace netxs::ui pro::focus::off(item_ptr, gear_id_list); } // pro::focus: Defocus all gears and clear chains (optionally remove_default route from parent) and return deleted active gear id's. - static auto cut(sptr item_ptr, bool remove_default = faux) + static auto cut(sptr item_ptr) { auto lock = item_ptr->bell::sync(); - auto gear_id_list = hids::events::focus::cut.param(); + auto gear_id_list = item_ptr->base::riseup(tier::request, e2::form::state::keybd::enlist); if (auto parent = item_ptr->parent()) { - parent->base::riseup(tier::request, hids::events::focus::cut, gear_id_list); - if (remove_default) - { - parent->base::riseup(tier::request, hids::events::focus::dry, { .item = item_ptr }); - } + parent->base::riseup(tier::request, hids::events::focus::cut, { .item = item_ptr }); } return gear_id_list; } @@ -1662,15 +1658,16 @@ namespace netxs::ui } else //if (!first_step) { + auto focusable = node_type == mode::focused || node_type == mode::focusable; + auto last_step = chain.next.size() > 1 || focusable; chain.foreach([&](auto& nexthop, auto& status) { if (nexthop == seed.item) { - status = state::idle; + status = last_step ? state::dead : state::idle; } }); - auto focusable = node_type == mode::focused || node_type == mode::focusable; - if (chain.next.size() > 1 || focusable) // Stop unfocusing on hub or focusable. + if (last_step) // Stop unfocusing on hub or focusable. { boss.bell::expire(tier::preview); // Don't let the hall send the event to the gate. return; @@ -1709,33 +1706,22 @@ namespace netxs::ui } }; // pro::focus: Drop all downlinks (toward inside) from the boss and unfocus boss. Return dropped active gears. - boss.LISTEN(tier::request, hids::events::focus::cut, gear_id_list, memo) + boss.LISTEN(tier::request, hids::events::focus::cut, seed, memo) { + seed.treeid = treeid; + seed.digest = ++digest; for (auto& [gear_id, chain] : gears) { - auto live = faux; - chain.foreach([&, gear_id = gear_id](auto& nexthop, auto& status) // Drop all downlinks (toward inside) from the boss. //todo Apple clang can't capture gear_id in lambda + chain.next.remove_if([&, gear_id = gear_id](auto& next) // Drop all downlinks (toward inside) from the boss. //todo Apple clang can't capture gear_id by ref. { - if (gear_id && status == state::live) + auto match = next.next_wptr.lock() == seed.item; + if (match && gear_id && next.status == state::live) { - live = true; - nexthop->bell::signal(tier::release, hids::events::focus::set::off, { .gear_id = gear_id }); + seed.gear_id = gear_id; + seed.item->bell::signal(tier::release, hids::events::focus::set::off, seed); } - nexthop = {}; + return match; }); - if (gear_id) - { - boss.bell::signal(tier::preview, hids::events::focus::set::off, { .gear_id = gear_id }); // The cutting object is changing its host along with focus. - if (live) gear_id_list.push_back(gear_id); // Backup dropped active gears. - } - } - }; - // pro::focus: . - boss.LISTEN(tier::request, hids::events::focus::dry, seed, memo) - { - for (auto& [gear_id, chain] : gears) - { - chain.next.remove_if([&](auto& next){ return next.next_wptr.lock() == seed.item; }); } }; // pro::focus: Switch all foci from the prev_ptr to the next_ptr (which must have a pro::focus on board). diff --git a/src/netxs/desktopio/input.hpp b/src/netxs/desktopio/input.hpp index e8219e1f32..c10bd3efa0 100644 --- a/src/netxs/desktopio/input.hpp +++ b/src/netxs/desktopio/input.hpp @@ -156,9 +156,8 @@ namespace netxs::events::userland }; SUBSET_XS( focus ) { - EVENT_XS( dry, input::foci ), // request: Remove the reference to the specified applet. EVENT_XS( hop, input::foci ), // request: Switch focus branch to seed.item. - EVENT_XS( cut, ui::gear_id_list_t ), // request: Unfocus and delete downstream (to inside) focus route. + EVENT_XS( cut, input::foci ), // request: Unfocus and delete downstream (to inside) focus route. EVENT_XS( add, input::foci ), // request: Initiate focus setting toward outside (used by gui and dtvt). EVENT_XS( rem, input::foci ), // request: Initiate focus unsetting toward outside (used by gui and dtvt). EVENT_XS( dup, input::foci ), // request: Make a focus tree copy from default. diff --git a/src/vtm.hpp b/src/vtm.hpp index 5200de3eb7..e3bf4b1de1 100644 --- a/src/vtm.hpp +++ b/src/vtm.hpp @@ -122,7 +122,7 @@ namespace netxs::app::vtm void follow(vtm::link& new_what, dent pads = {}) { what = new_what; - auto gear_id_list = pro::focus::cut(what.applet, true); + auto gear_id_list = pro::focus::cut(what.applet); auto window_ptr = new_what.applet; saved = nexthop; nexthop = new_what.applet; @@ -640,7 +640,7 @@ namespace netxs::app::vtm fp2d coord; wptr cover; - void proceed(bool keep) + void proceed(bool keep, hids& gear) { drags = faux; boss.bell::signal(tier::anycast, e2::form::prop::lucidity, 0xFF); // Make target opaque. @@ -656,7 +656,7 @@ namespace netxs::app::vtm auto gear_id_list = pro::focus::cut(what.applet); what.applet->base::detach(); dest.bell::signal(tier::release, vtm::events::d_n_d::drop, what); // Pass core. - pro::focus::set(what.applet, gear_id_list, solo::off, true); // Re set focus. + pro::focus::set(what.applet, gear.id, solo::on, true); // Set unique focus. boss.base::detach(); // The object kills itself. } } @@ -686,21 +686,21 @@ namespace netxs::app::vtm boss.LISTEN(tier::release, hids::events::mouse::button::drag::pull::any, gear, memo) { if (!drags) return; - if (gear.meta(hids::anyMod)) proceed(faux); + if (gear.meta(hids::anyMod)) proceed(faux, gear); else coord = gear.coord - gear.delta.get(); }; boss.LISTEN(tier::release, hids::events::mouse::button::drag::stop::any, gear, memo) { if (!drags) return; - if (gear.meta(hids::anyMod)) proceed(faux); - else proceed(true); + if (gear.meta(hids::anyMod)) proceed(faux, gear); + else proceed(true, gear); gear.setfree(); }; boss.LISTEN(tier::release, hids::events::mouse::button::drag::cancel::any, gear, memo) { if (!drags) return; - if (gear.meta(hids::anyMod)) proceed(faux); - else proceed(true); + if (gear.meta(hids::anyMod)) proceed(faux, gear); + else proceed(true, gear); gear.setfree(); }; boss.LISTEN(tier::release, e2::render::background::prerender, parent_canvas, memo) @@ -781,18 +781,20 @@ namespace netxs::app::vtm } }; //todo mimic pro::focus - LISTEN(tier::request, hids::events::focus::cut, gear_id_list, tokens, (treeid = datetime::uniqueid(), digest = ui64{})) + LISTEN(tier::request, hids::events::focus::cut, seed, tokens, (treeid = datetime::uniqueid(), digest = ui64{})) { if (align.what.applet) { + seed.treeid = treeid; + seed.digest = ++digest; for (auto& [ext_gear_id, gear_ptr] : input.gears) { if (ext_gear_id && !gear_ptr->keybd_disabled) // Ignore default and halted gears. { if (auto gear_id = gear_ptr->id) { - gear_id_list.push_back(gear_id); - align.what.applet->bell::signal(tier::release, hids::events::focus::set::off, { .gear_id = gear_id, .treeid = treeid, .digest = ++digest }); + seed.gear_id = gear_id; + align.what.applet->bell::signal(tier::release, hids::events::focus::set::off, seed); } } } @@ -1814,7 +1816,7 @@ namespace netxs::app::vtm if (gear.args_ptr) { auto arg = gear.args_ptr->empty() ? -1 : (si32)xml::take_or(gear.args_ptr->front(), faux); - items.foreach(gear, [&](auto window_ptr) + items.foreach(gear, [&](auto& window_ptr) { auto zorder = arg == 0 ? zpos::plain : arg == 1 ? zpos::topmost @@ -1826,7 +1828,7 @@ namespace netxs::app::vtm } void close_focused_windows(hids& gear) { - items.foreach(gear, [&](auto window_ptr) + items.foreach(gear, [&](auto& window_ptr) { bell::enqueue(window_ptr, [](auto& boss) // Keep the focus tree intact while processing key events. { @@ -1837,7 +1839,7 @@ namespace netxs::app::vtm } void minimize_focused_windows(hids& gear) { - items.foreach(gear, [&](auto window_ptr) + items.foreach(gear, [&](auto& window_ptr) { bell::enqueue(window_ptr, [gear_id = gear.id](auto& boss) // Keep the focus tree intact while processing key events. { @@ -1852,7 +1854,7 @@ namespace netxs::app::vtm } void maximize_focused_windows(hids& gear) { - items.foreach(gear, [&](auto window_ptr) + items.foreach(gear, [&](auto& window_ptr) { bell::enqueue(window_ptr, [gear_id = gear.id](auto& boss) // Keep the focus tree intact while processing key events. { @@ -1867,7 +1869,7 @@ namespace netxs::app::vtm } void fullscreen_first_focused_window(hids& gear) { - items.foreach(gear, [&](auto window_ptr) + items.foreach(gear, [&](auto& window_ptr) { bell::enqueue(window_ptr, [gear_id = gear.id](auto& boss) // Keep the focus tree intact while processing key events. { @@ -1885,7 +1887,7 @@ namespace netxs::app::vtm { auto warp = gear.get_args_or(dent{}); auto focused_window_list = std::vector{}; - items.foreach(gear, [&](auto window_ptr) + items.foreach(gear, [&](auto& window_ptr) { focused_window_list.push_back(window_ptr); gear.set_handled(); @@ -1993,11 +1995,12 @@ namespace netxs::app::vtm }; LISTEN(tier::release, vtm::events::gate::restore, what) { - auto gear_id_list = pro::focus::cut(what.applet); - what.applet->base::detach(); + auto window_ptr = what.applet; + auto gear_id_list = pro::focus::cut(window_ptr); + window_ptr->base::detach(); auto& cfg = dbase.menu[what.menuid]; - branch(what.menuid, what.applet, !cfg.hidden); - pro::focus::set(what.applet, gear_id_list, solo::on, true); + branch(what.menuid, window_ptr, !cfg.hidden); + pro::focus::set(window_ptr, gear_id_list, solo::on, true); }; LISTEN(tier::request, vtm::events::apptype, what) { @@ -2172,7 +2175,7 @@ namespace netxs::app::vtm gear.owner.bell::signal(tier::release, hids::events::keybd::key::post, gear); } }; - //todo mimic pro::focus + //todo mimic pro::focus (hall has no parent) LISTEN(tier::preview, hids::events::focus::set::any, seed) // Forward focus events to the gate for sending it to the outside. { if (seed.gear_id) diff --git a/src/vtm.xml b/src/vtm.xml index 8270ce8935..eb52cb9335 100644 --- a/src/vtm.xml +++ b/src/vtm.xml @@ -493,7 +493,7 @@ R"==( - +