From a2c7f17dc401befa8f9125cbdda4ec3e59ebe671 Mon Sep 17 00:00:00 2001 From: Dmitry Sapozhnikov <11535558+o-sdn-o@users.noreply.github.com> Date: Sun, 10 Nov 2024 16:34:36 +0500 Subject: [PATCH 1/6] Drop pro::focus::flip --- src/netxs/apps/desk.hpp | 8 ++++---- src/netxs/apps/tile.hpp | 31 ++++++++++++++--------------- src/netxs/desktopio/console.hpp | 2 +- src/netxs/desktopio/controls.hpp | 23 ++++++++++----------- src/netxs/desktopio/input.hpp | 1 - src/netxs/desktopio/terminal.hpp | 17 ++++++++-------- src/vtm.hpp | 34 +++++++++++++++----------------- 7 files changed, 54 insertions(+), 62 deletions(-) diff --git a/src/netxs/apps/desk.hpp b/src/netxs/apps/desk.hpp index 092e554b0d..60e1b84adf 100644 --- a/src/netxs/apps/desk.hpp +++ b/src/netxs/apps/desk.hpp @@ -131,7 +131,7 @@ namespace netxs::app::desk { window.bell::signal(tier::release, e2::form::size::minimize, gear); } - else pro::focus::set(data_src, gear.id, pro::focus::solo::on, pro::focus::flip::off); + else pro::focus::set(data_src, gear.id, pro::focus::solo::on); } else // Jump to window. { @@ -159,7 +159,7 @@ namespace netxs::app::desk { window.bell::signal(tier::release, e2::form::size::minimize, gear); } - pro::focus::set(data_src, gear.id, pro::focus::solo::off, pro::focus::flip::off); + pro::focus::set(data_src, gear.id, pro::focus::solo::off); } gear.dismiss(true); // Suppress double click. } @@ -174,7 +174,7 @@ namespace netxs::app::desk { window.bell::signal(tier::release, e2::form::size::minimize, gear); } - else pro::focus::set(data_src, gear.id, pro::focus::solo::on, pro::focus::flip::off); + else pro::focus::set(data_src, gear.id, pro::focus::solo::on); gear.dismiss(); } } @@ -421,7 +421,7 @@ namespace netxs::app::desk boss.LISTEN(tier::release, events::ui::focus::any, gear, window.tracker) { auto deed = boss.bell::protos(tier::release); - if (deed == events::ui::focus::set.id) pro::focus::set(window.This(), gear.id, pro::focus::solo::off, pro::focus::flip::off); + if (deed == events::ui::focus::set.id) pro::focus::set(window.This(), gear.id, pro::focus::solo::off); else if (deed == events::ui::focus::off.id) pro::focus::off(window.This(), gear.id); }; }); diff --git a/src/netxs/apps/tile.hpp b/src/netxs/apps/tile.hpp index b973fcf8a5..6f94fe073d 100644 --- a/src/netxs/apps/tile.hpp +++ b/src/netxs/apps/tile.hpp @@ -278,7 +278,7 @@ namespace netxs::app::tile { auto gear_id_list = pro::focus::get(parent_ptr); // Expropriate all foci. world_ptr->bell::signal(tier::request, vtm::events::handoff, what); // Attach to the world. - pro::focus::set(what.applet, gear_id_list, pro::focus::solo::off, pro::focus::flip::off, true); // Refocus. + pro::focus::set(what.applet, gear_id_list, pro::focus::solo::off, true); // Refocus. master.base::riseup(tier::release, e2::form::proceed::quit::one, true); // Destroy placeholder. } @@ -292,11 +292,11 @@ namespace netxs::app::tile }; boss.LISTEN(tier::release, hids::events::mouse::button::click::right, gear) { - pro::focus::set(boss.This(), gear.id, pro::focus::solo::on, pro::focus::flip::off); + pro::focus::set(boss.This(), gear.id, pro::focus::solo::on); }; boss.LISTEN(tier::release, hids::events::mouse::button::click::middle, gear) { - pro::focus::set(boss.This(), gear.id, pro::focus::solo::on, pro::focus::flip::off); + pro::focus::set(boss.This(), gear.id, pro::focus::solo::on); }; boss.LISTEN(tier::release, e2::form::upon::vtree::attached, parent) { @@ -483,8 +483,7 @@ namespace netxs::app::tile if (ratio == min_ratio) { node->set_ratio(saved_ratio); - pro::focus::set(boss.This(), gear.id, gear.meta(hids::anyCtrl) ? pro::focus::solo::off - : pro::focus::solo::on, pro::focus::flip::off, true); + pro::focus::set(boss.This(), gear.id, gear.meta(hids::anyCtrl) ? pro::focus::solo::off : pro::focus::solo::on, true); } else { @@ -525,7 +524,7 @@ namespace netxs::app::tile auto app = app_window(what); boss.attach(app); app->bell::signal(tier::anycast, e2::form::upon::started); - pro::focus::set(what.applet, gear_id_list, pro::focus::solo::mix, pro::focus::flip::off, true); + pro::focus::set(what.applet, gear_id_list, pro::focus::solo::mix, true); } }; boss.LISTEN(tier::release, e2::form::proceed::swap, item_ptr) @@ -543,7 +542,7 @@ namespace netxs::app::tile boss.attach(item_ptr); } else item_ptr = boss.This(); - pro::focus::set(boss.back(), gear_id_list, pro::focus::solo::off, pro::focus::flip::off); + pro::focus::set(boss.back(), gear_id_list, pro::focus::solo::off); } else { @@ -564,7 +563,7 @@ namespace netxs::app::tile { auto gear_id_list = pro::focus::get(boss.This()); item_ptr = boss.pop_back(); - pro::focus::set(boss.back(), gear_id_list, pro::focus::solo::off, pro::focus::flip::off); + pro::focus::set(boss.back(), gear_id_list, pro::focus::solo::off); } else { @@ -591,7 +590,7 @@ namespace netxs::app::tile boss.LISTEN(tier::anycast, app::tile::events::ui::select, gear) { auto item_ptr = boss.back(); - if (item_ptr->base::kind() != base::node) pro::focus::set(item_ptr, gear.id, pro::focus::solo::off, pro::focus::flip::off); + if (item_ptr->base::kind() != base::node) pro::focus::set(item_ptr, gear.id, pro::focus::solo::off); else pro::focus::off(item_ptr, gear.id); // Exclude grips. }; boss.LISTEN(tier::preview, e2::form::size::enlarge::any, gear, -, (oneoff = subs{})) @@ -622,7 +621,7 @@ namespace netxs::app::tile }; auto just_copy = fullscreen_item; boss.base::riseup(tier::release, e2::form::proceed::attach, fullscreen_item); - pro::focus::set(just_copy, gear_id_list, pro::focus::solo::off, pro::focus::flip::off); // Handover all foci. + pro::focus::set(just_copy, gear_id_list, pro::focus::solo::off); // Handover all foci. boss.base::reflow(); } } @@ -650,8 +649,8 @@ namespace netxs::app::tile auto slot_1 = newnode->attach(slot::_1, empty_1->branch(curitem)); auto slot_2 = newnode->attach(slot::_2, empty_2); boss.attach(newnode); - pro::focus::set(slot_1->back(), gear_id, pro::focus::solo::off, pro::focus::flip::off); // Handover all foci. - pro::focus::set(slot_2->back(), gear_id, pro::focus::solo::off, pro::focus::flip::off); + pro::focus::set(slot_1->back(), gear_id, pro::focus::solo::off); // Handover all foci. + pro::focus::set(slot_2->back(), gear_id, pro::focus::solo::off); } }; boss.LISTEN(tier::anycast, e2::form::proceed::quit::any, fast) @@ -674,7 +673,7 @@ namespace netxs::app::tile { auto gear_id_list = pro::focus::get(boss.This()); auto deleted_item = boss.pop_back(); // Throw away. - pro::focus::set(boss.back(), gear_id_list, pro::focus::solo::off, pro::focus::flip::off); + pro::focus::set(boss.back(), gear_id_list, pro::focus::solo::off); } else if (boss.count() == 1) // Remove empty slot, reorganize. { @@ -718,7 +717,7 @@ namespace netxs::app::tile { gear_id_list.push_back(gear.id); } - pro::focus::set(app, gear_id_list, pro::focus::solo::off, pro::focus::flip::off); + pro::focus::set(app, gear_id_list, pro::focus::solo::off); }; boss.LISTEN(tier::release, events::backup, empty_slot_list) { @@ -964,8 +963,8 @@ namespace netxs::app::tile auto gear_id_list = pro::focus::get(boss.This()); // Seize all foci. auto item_ptr = boss.pop_back(); item_ptr->bell::signal(tier::release, e2::form::size::restore, item_ptr); - pro::focus::set(boss.back(), foci_list, pro::focus::solo::off, pro::focus::flip::off, true); // Restore saved foci. - pro::focus::set(item_ptr, gear_id_list, pro::focus::solo::off, pro::focus::flip::off); // Apply item's foci. + pro::focus::set(boss.back(), foci_list, pro::focus::solo::off, true); // Restore saved foci. + pro::focus::set(item_ptr, gear_id_list, pro::focus::solo::off); // Apply item's foci. foci_list.clear(); } diff --git a/src/netxs/desktopio/console.hpp b/src/netxs/desktopio/console.hpp index e7ebaae5b3..3436a0a98f 100644 --- a/src/netxs/desktopio/console.hpp +++ b/src/netxs/desktopio/console.hpp @@ -1145,7 +1145,7 @@ namespace netxs::ui //if (auto target = local ? applet : base::parent()) if (auto target = nexthop.lock()) { - pro::focus::set(target, gear.id, pro::focus::solo::off, pro::focus::flip::off, true); + pro::focus::set(target, gear.id, pro::focus::solo::off, true); } oneoff_focus.reset(); }; diff --git a/src/netxs/desktopio/controls.hpp b/src/netxs/desktopio/controls.hpp index d46c836832..6b1f9b55f8 100644 --- a/src/netxs/desktopio/controls.hpp +++ b/src/netxs/desktopio/controls.hpp @@ -1247,15 +1247,14 @@ namespace netxs::ui public: enum class mode { hub, focusable, focused, active }; enum class solo { off, on, mix }; - enum class flip { off = faux, on = true }; friend auto operator == (si32 l, solo r) { return l == static_cast>(r); } template - static void set(sptr item_ptr, T&& gear_id, solo s, flip f, bool skip = faux) + static void set(sptr item_ptr, T&& gear_id, solo s, bool skip = faux) { auto fire = [&](auto id) { - auto seed = item_ptr->base::riseup(tier::preview, hids::events::keybd::focus::set, { .id = id, .solo = (si32)s, .flip = (bool)f, .skip = skip }); + auto seed = item_ptr->base::riseup(tier::preview, hids::events::keybd::focus::set, { .id = id, .solo = (si32)s, .skip = skip }); //if constexpr (debugmode) log(prompt::foci, "Focus set gear:", seed.id, " item:", item_ptr->id); }; if constexpr (std::is_same_v>) fire(gear_id); @@ -1308,7 +1307,7 @@ namespace netxs::ui { auto seed = parent->base::riseup(tier::release, hids::events::keybd::focus::hop, { .what = src_ptr, .item = dst_ptr }); auto gear_id_list = pro::focus::off(src_ptr); - pro::focus::set(dst_ptr, gear_id_list, pro::focus::solo::off, pro::focus::flip::off); + pro::focus::set(dst_ptr, gear_id_list, pro::focus::solo::off); } } static auto test(base& item, input::hids& gear) @@ -1327,7 +1326,7 @@ namespace netxs::ui { boss.LISTEN(tier::anycast, e2::form::upon::started, parent_ptr, memo, (m)) { - pro::focus::set(boss.This(), id_t{}, solo::off, flip::off, m == mode::active ? true : faux); + pro::focus::set(boss.This(), id_t{}, solo::off, m == mode::active ? true : faux); }; } boss.LISTEN(tier::request, e2::form::state::keybd::check, state, memo) @@ -1342,8 +1341,12 @@ namespace netxs::ui // Set unique focus on left click. Set group focus on Ctrl+LeftClick. boss.LISTEN(tier::release, hids::events::mouse::button::click::left, gear, memo) { - if (gear.meta(hids::anyCtrl)) pro::focus::set(boss.This(), gear.id, solo::off, flip::on ); - else pro::focus::set(boss.This(), gear.id, solo::on, flip::off); + if (gear.meta(hids::anyCtrl)) + { + if (pro::focus::test(boss, gear)) pro::focus::off(boss.This(), gear.id); + else pro::focus::set(boss.This(), gear.id, solo::off); + } + else pro::focus::set(boss.This(), gear.id, solo::on); gear.dismiss(); }; // Subscribe on keybd events. @@ -1477,12 +1480,6 @@ namespace netxs::ui { if (route.active) { - if (seed.flip) // Focus flip-off is always a truncation of the maximum path without branches. - { - if (focusable) route.focused = faux; - boss.bell::signal(tier::preview, hids::events::keybd::focus::off, seed); - return; - } if (seed.solo != solo::on) // Group focus. { route.focused = focusable; diff --git a/src/netxs/desktopio/input.hpp b/src/netxs/desktopio/input.hpp index b602e10b28..31ffe03b11 100644 --- a/src/netxs/desktopio/input.hpp +++ b/src/netxs/desktopio/input.hpp @@ -813,7 +813,6 @@ namespace netxs::input { id_t id{}; // foci: Gear id. si32 solo{}; // foci: Exclusive focus request. - bool flip{}; // foci: Toggle focus request. bool skip{}; // foci: Ignore focusable object, just activate it. sptr what{}; // foci: Replacement item. sptr item{}; // foci: Next focused item. diff --git a/src/netxs/desktopio/terminal.hpp b/src/netxs/desktopio/terminal.hpp index bcec6df0b0..ff87265b44 100644 --- a/src/netxs/desktopio/terminal.hpp +++ b/src/netxs/desktopio/terminal.hpp @@ -338,7 +338,7 @@ namespace netxs::ui auto gear_test = owner.base::riseup(tier::request, e2::form::state::keybd::find, { gear.id, 0 }); if (gear_test.second == 0) { - pro::focus::set(owner.This(), gear.id, pro::focus::solo::off, pro::focus::flip::off); + pro::focus::set(owner.This(), gear.id, pro::focus::solo::off); } owner.base::riseup(tier::preview, e2::form::layout::expose); } @@ -348,8 +348,8 @@ namespace netxs::ui auto gear_test = owner.base::riseup(tier::request, e2::form::state::keybd::find, { gear.id, 0 }); if (gear_test.second == 0) { - pro::focus::set(owner.This(), gear.id, gear.meta(hids::anyCtrl) ? pro::focus::solo::off - : pro::focus::solo::on, pro::focus::flip::on); + if (pro::focus::test(owner, gear)) pro::focus::off(owner.This(), gear.id); + else pro::focus::set(owner.This(), gear.id, gear.meta(hids::anyCtrl) ? pro::focus::solo::off : pro::focus::solo::on); } owner.base::riseup(tier::preview, e2::form::layout::expose); } @@ -7134,7 +7134,7 @@ namespace netxs::ui auto data = get_clipboard_text(gear); if (data.size()) { - pro::focus::set(this->This(), gear.id, pro::focus::solo::off, pro::focus::flip::off); + pro::focus::set(this->This(), gear.id, pro::focus::solo::off); _paste(data); return true; } @@ -7142,9 +7142,8 @@ namespace netxs::ui } auto _copy(hids& gear, text const& data) { - auto form = selmod == mime::disabled ? mime::textonly - : selmod; - pro::focus::set(this->This(), gear.id, pro::focus::solo::off, pro::focus::flip::off); + auto form = selmod == mime::disabled ? mime::textonly : selmod; + pro::focus::set(this->This(), gear.id, pro::focus::solo::off); gear.set_clipboard(target->panel, data, form); } auto copy(hids& gear) @@ -7187,7 +7186,7 @@ namespace netxs::ui auto gear_test = base::riseup(tier::request, e2::form::state::keybd::find, { gear.id, 0 }); if (!gear_test.second) // Set exclusive focus on right click. { - pro::focus::set(This(), gear.id, pro::focus::solo::on, pro::focus::flip::off); + pro::focus::set(This(), gear.id, pro::focus::solo::on); } if ((selection_active() && copy(gear)) || (selection_passed() && paste(gear))) @@ -7209,7 +7208,7 @@ namespace netxs::ui } if (utf8.size()) { - pro::focus::set(this->This(), gear.id, pro::focus::solo::off, pro::focus::flip::off); + pro::focus::set(this->This(), gear.id, pro::focus::solo::off); follow[axis::X] = true; if (bpmode) { diff --git a/src/vtm.hpp b/src/vtm.hpp index f9efffe447..7d436622cd 100644 --- a/src/vtm.hpp +++ b/src/vtm.hpp @@ -175,7 +175,7 @@ namespace netxs::app::vtm window_ptr->bell::signal(tier::release, e2::form::upon::vtree::attached, boss.base::This()); window_ptr->bell::signal(tier::anycast, vtm::events::attached, boss.base::This()); - pro::focus::set(window_ptr, gear_id_list, pro::focus::solo::on, pro::focus::flip::off, true); // Refocus. + pro::focus::set(window_ptr, gear_id_list, pro::focus::solo::on, true); // Refocus. } void unbind(type restore = type::full) { @@ -213,7 +213,7 @@ namespace netxs::app::vtm } } what.applet.reset(); - pro::focus::set(window_ptr, gear_id_list, pro::focus::solo::on, pro::focus::flip::off, true); // Refocus. + pro::focus::set(window_ptr, gear_id_list, pro::focus::solo::on, true); // Refocus. } }; @@ -337,7 +337,7 @@ namespace netxs::app::vtm auto coord = gear.coord + area.coor; if (!area.hittest(coord)) { - pro::focus::set(boss.This(), gear.id, pro::focus::solo::on, pro::focus::flip::off); + pro::focus::set(boss.This(), gear.id, pro::focus::solo::on); appear(coord); } gear.dismiss(); @@ -752,7 +752,7 @@ namespace netxs::app::vtm if (true /*...*/) //todo lookup taskbar kb shortcuts { //... - //pro::focus::set(applet, gear.id, pro::focus::solo::on, pro::focus::flip::off); + //pro::focus::set(applet, gear.id, pro::focus::solo::on); } else @@ -891,7 +891,7 @@ namespace netxs::app::vtm auto& window = *window_ptr; window.bell::signal(tier::release, e2::form::layout::selected, gear); if (!maximized) jump_to(window); - pro::focus::set(window_ptr, gear.id, pro::focus::solo::on, pro::focus::flip::off); + pro::focus::set(window_ptr, gear.id, pro::focus::solo::on); } //gear.dismiss(); this->bell::expire(tier::preview); //todo temp @@ -1296,8 +1296,7 @@ namespace netxs::app::vtm if (boss.hidden) // Restore if it is hidden. { boss.hidden = faux; - pro::focus::set(This, gear.id, gear.meta(hids::anyCtrl) ? pro::focus::solo::off - : pro::focus::solo::on, pro::focus::flip::off, true); + pro::focus::set(This, gear.id, gear.meta(hids::anyCtrl) ? pro::focus::solo::off : pro::focus::solo::on, true); } else // Hide if visible and refocus. { @@ -1327,7 +1326,7 @@ namespace netxs::app::vtm while (window != This && ((gearid && gearid != gear.owner.id) || (hidden == true || !viewport.hittest(window->center())))); if (window != This) { - pro::focus::set(window, gear.id, pro::focus::solo::on, pro::focus::flip::off); + pro::focus::set(window, gear.id, pro::focus::solo::on); This.reset(); } } @@ -1366,11 +1365,11 @@ namespace netxs::app::vtm }; boss.LISTEN(tier::release, hids::events::mouse::button::click::right, gear) { - pro::focus::set(boss.This(), gear.id, pro::focus::solo::on, pro::focus::flip::off); + pro::focus::set(boss.This(), gear.id, pro::focus::solo::on); }; boss.LISTEN(tier::release, hids::events::mouse::button::click::middle, gear) { - pro::focus::set(boss.This(), gear.id, pro::focus::solo::on, pro::focus::flip::off); + pro::focus::set(boss.This(), gear.id, pro::focus::solo::on); }; boss.LISTEN(tier::release, e2::form::proceed::quit::any, fast) { @@ -1413,7 +1412,7 @@ namespace netxs::app::vtm what.applet = window_ptr; boss.bell::enqueue(boss.This(), [&](auto& /*boss*/) { - pro::focus::set(boss.This(), gear.id, pro::focus::solo::on, pro::focus::flip::off, true); // Refocus to demultifocus. + pro::focus::set(boss.This(), gear.id, pro::focus::solo::on, true); // Refocus to demultifocus. }); window_ptr->base::riseup(tier::request, e2::form::prop::ui::header, what.header); window_ptr->base::riseup(tier::request, e2::form::prop::ui::footer, what.footer); @@ -1466,7 +1465,7 @@ namespace netxs::app::vtm else { boss.base::riseup(tier::preview, e2::form::layout::expose); // Multiple windows coubld be maximized at the same time. - pro::focus::set(window_ptr, gear.id, pro::focus::solo::on, pro::focus::flip::off, true); + pro::focus::set(window_ptr, gear.id, pro::focus::solo::on, true); auto owner_id = gear.owner.id; saved_area = boss.base::area(); saved_area.coor -= viewport.coor; @@ -1930,7 +1929,7 @@ namespace netxs::app::vtm what.square.size = winsize ? winsize : viewport.size * 3 / 4; if (auto window = create(what)) { - pro::focus::set(window, gear.id, pro::focus::solo::on, pro::focus::flip::off); + pro::focus::set(window, gear.id, pro::focus::solo::on); window->bell::signal(tier::anycast, e2::form::upon::created, gear); // Tile should change the menu item. if (appbase.winform == shared::win::state::maximized) window->bell::signal(tier::preview, e2::form::size::enlarge::maximize, gear); else if (appbase.winform == shared::win::state::minimized) window->bell::signal(tier::preview, e2::form::size::minimize, gear); @@ -1944,7 +1943,7 @@ namespace netxs::app::vtm what.square.size = winsize; if (auto window = create(what)) { - pro::focus::set(window, id_t{}, pro::focus::solo::on, pro::focus::flip::off); + pro::focus::set(window, id_t{}, pro::focus::solo::on); yield = utf::concat(window->id); } } @@ -1970,7 +1969,7 @@ namespace netxs::app::vtm //{ // log(prompt::hall, "Objects count: ", items.size()); //}; - pro::focus::set(window, gear.id, pro::focus::solo::on, pro::focus::flip::off); + pro::focus::set(window, gear.id, pro::focus::solo::on); window->bell::signal(tier::anycast, e2::form::upon::created, gear); // Tile should change the menu item. auto& cfg = dbase.menu[what.menuid]; if (cfg.winform == shared::win::state::maximized) window->bell::signal(tier::preview, e2::form::size::enlarge::maximize, gear); @@ -2141,8 +2140,7 @@ namespace netxs::app::vtm auto count = 0; for (auto& window_ptr : foci) { - pro::focus::set(window_ptr, id_t{}, count++ ? pro::focus::solo::off // Reset all foci on the first item. - : pro::focus::solo::on, pro::focus::flip::off); + pro::focus::set(window_ptr, id_t{}, count++ ? pro::focus::solo::off : pro::focus::solo::on); // Reset all foci on the first item. } if constexpr (debugmode) { @@ -2228,7 +2226,7 @@ namespace netxs::app::vtm { auto owner_id = last_ptr->bell::signal(tier::request, e2::form::state::maximized); if (owner_id && owner_id != gear_ptr->owner.id) continue; - pro::focus::set(last_ptr, gear_id, pro::focus::solo::off, pro::focus::flip::off); + pro::focus::set(last_ptr, gear_id, pro::focus::solo::off); } } } From 284e380f23f6e19ff674fbdace6ab4d82f374ae1 Mon Sep 17 00:00:00 2001 From: Dmitry Sapozhnikov <11535558+o-sdn-o@users.noreply.github.com> Date: Sun, 10 Nov 2024 20:22:49 +0500 Subject: [PATCH 2/6] #86 WIP: Rename DropIfRepeats to DropAutoRepeat --- doc/apps.md | 2 +- doc/settings.md | 16 ++++++++-------- src/netxs/desktopio/application.hpp | 10 +++++----- src/netxs/desktopio/controls.hpp | 4 ++-- src/netxs/desktopio/input.hpp | 9 +++++---- src/vtm.xml | 14 +++++++------- 6 files changed, 28 insertions(+), 27 deletions(-) diff --git a/doc/apps.md b/doc/apps.md index bd7d6f69bd..dd23f20422 100644 --- a/doc/apps.md +++ b/doc/apps.md @@ -161,7 +161,7 @@ The list of hotkey actions is slightly different from the list of window menu ac Value | Unique for hotkeys | Default Hotkey | Description -----------------------------|--------------------|------------------------------|------------ Drop | | | Drop all events for the specified key combination. No further processing. -DropIfRepeats | | | Drop `Key Repeat` events for the specified key combination. This binding should be specified before the main action for the key combination. +DropAutoRepeat | | | Drop `Key Repeat` events for the specified key combination. This binding should be specified before the main action for the key combination. ToggleExclusiveKeybd | x | `Ctrl-Alt`, `Alt-Ctrl` | Toggle exclusive keyboard mode. In exclusive mode, all keyboard events are ignored by higher levels. TerminalFindNext | | `Alt+RightArrow` | Highlight next match of selected text fragment. Clipboard content is used if no active selection. TerminalFindPrev | | `Alt+LeftArrow` | Highlight previous match of selected text fragment. Clipboard content is used if no active selection. diff --git a/doc/settings.md b/doc/settings.md index b566a4b5bc..bc36840b71 100644 --- a/doc/settings.md +++ b/doc/settings.md @@ -345,7 +345,7 @@ Configuration record | Interpretation Action | Default key combination | Available at layer | Description -------------------------------|--------------------------|---------------------|------------ `Drop` | | All layers | Drop all events for the specified key combination. No further processing. -`DropIfRepeats` | | All layers | Drop `Key Repeat` events for the specified key combination. This binding should be specified before the main action for the key combination. +`DropAutoRepeat` | | All layers | Drop `Key Repeat` events for the specified key combination. This binding should be specified before the main action for the key combination. `ToggleDebugOverlay` | | TUI matrix | Toggle debug overlay. `ToggleExclusiveKeybd` | `Ctrl-Alt`, `Alt-Ctrl` | Application | Toggle exclusive keyboard mode. In exclusive mode, all keyboard events are ignored by higher layers. Exclusive keyboard mode is automatically disabled when refocusing. `IncreaseCellHeight` | `CapsLock+UpArrow` | Native GUI window | Increase the text cell height by one pixel. @@ -793,15 +793,15 @@ Notes - + - + - + - + - + @@ -826,9 +826,9 @@ Notes - + - + diff --git a/src/netxs/desktopio/application.hpp b/src/netxs/desktopio/application.hpp index 305aedf06d..56b73554aa 100644 --- a/src/netxs/desktopio/application.hpp +++ b/src/netxs/desktopio/application.hpp @@ -130,7 +130,7 @@ namespace netxs::app::shared { if (std::exchange(*esc_pressed, faux) != *esc_pressed) boss.bell::signal(tier::anycast, e2::form::state::keybd::command::close, *esc_pressed); }); - keybd.template bind( "Esc", "DropIfRepeats"); + keybd.template bind( "Esc", "DropAutoRepeat"); keybd.template bind( "Esc", "WindowClosePreview"); keybd.template bind("-Esc", "WindowClose"); keybd.template bind( "Any", "CancelWindowClose"); @@ -151,13 +151,13 @@ namespace netxs::app::shared keybd.bind("DownArrow" , "ScrollLineDown" ); keybd.bind("LeftArrow" , "ScrollCharLeft" ); keybd.bind("RightArrow", "ScrollCharRight" ); - keybd.bind("Home" , "DropIfRepeats" ); + keybd.bind("Home" , "DropAutoRepeat" ); keybd.bind("Home" , "ScrollTop" ); - keybd.bind("End" , "DropIfRepeats" ); + keybd.bind("End" , "DropAutoRepeat" ); keybd.bind("End" , "ScrollEnd" ); - keybd.bind("F11" , "DropIfRepeats" ); + keybd.bind("F11" , "DropAutoRepeat" ); keybd.bind("F11" , "ToggleMaximize" ); - keybd.bind("F12" , "DropIfRepeats" ); + keybd.bind("F12" , "DropAutoRepeat" ); keybd.bind("F12" , "ToggleFullscreen" ); keybd.bind("Ctrl-Alt" , "ToggleExclusiveKeybd"); keybd.bind("Alt-Ctrl" , "ToggleExclusiveKeybd"); diff --git a/src/netxs/desktopio/controls.hpp b/src/netxs/desktopio/controls.hpp index 6b1f9b55f8..e1fd777ecc 100644 --- a/src/netxs/desktopio/controls.hpp +++ b/src/netxs/desktopio/controls.hpp @@ -1921,8 +1921,8 @@ namespace netxs::ui if (!gear.handled) _dispatch(gear, input::key::kmap::any_key); } }; - proc("Drop", [](hids& gear){ gear.set_handled(); }); - proc("DropIfRepeats", [](hids& gear){ if (gear.keystat == input::key::repeated) gear.set_handled(); }); + proc("Drop", [](hids& gear){ gear.set_handled(); }); + proc("DropAutoRepeat", [](hids& gear){ if (gear.keystat == input::key::repeated) gear.set_handled(); }); } template diff --git a/src/netxs/desktopio/input.hpp b/src/netxs/desktopio/input.hpp index 31ffe03b11..01808fb842 100644 --- a/src/netxs/desktopio/input.hpp +++ b/src/netxs/desktopio/input.hpp @@ -1447,6 +1447,7 @@ namespace netxs::input NumLock = 1 << 12, // ⇭ Num Lock CapsLock = 1 << 13, // ⇪ Caps Lock ScrlLock = 1 << 14, // ⇳ Scroll Lock (⤓) + HkeyMode = 1 << 28, // Alternate hotkey mode AltGr = LAlt | LCtrl, anyCtrl = LCtrl | RCtrl, anyAlt = LAlt | RAlt, @@ -1732,7 +1733,7 @@ namespace netxs::input static constexpr auto mask = netxs::events::level_mask(hids::events::mouse::button::any.id); static constexpr auto base = mask & hids::events::mouse::button::any.id; alive = true; - hids::ctlstat = new_ctlstate; + keybd::ctlstat = new_ctlstate; mouse::coord = new_coord; mouse::click = new_click; mouse::whlfp = new_whlfp; @@ -1743,7 +1744,7 @@ namespace netxs::input mouse::load_button_state(new_button_state); } - auto meta(si32 ctl_key = -1) { return hids::ctlstat & ctl_key; } + auto meta(si32 ctl_key = -1) { return keybd::ctlstat & ctl_key; } // hids: Stop handeling this event. void dismiss(bool set_nodbl = faux) @@ -1776,7 +1777,7 @@ namespace netxs::input } #endif disabled = faux; - hids::ctlstat = m.ctlstat; + keybd::ctlstat = m.ctlstat; mouse::update(m, idmap); } void take(syskeybd& k) @@ -1990,7 +1991,7 @@ namespace netxs::input if (keystat != input::key::released) { - auto s = hids::ctlstat; + auto s = keybd::ctlstat; auto v = keybd::keycode & -2; // Generic keys only auto c = keybd::cluster.empty() ? 0 : keybd::cluster.front(); diff --git a/src/vtm.xml b/src/vtm.xml index e423d3442a..575f833764 100644 --- a/src/vtm.xml +++ b/src/vtm.xml @@ -380,15 +380,15 @@ R"==( - + - + - + - + - + @@ -413,9 +413,9 @@ R"==( - + - + From 30c2e15c6747689fc40e93a9c50540ea6c75674d Mon Sep 17 00:00:00 2001 From: Dmitry Sapozhnikov <11535558+o-sdn-o@users.noreply.github.com> Date: Mon, 11 Nov 2024 14:14:01 +0500 Subject: [PATCH 3/6] #86 WIP: Change 'Exclusive Keyboard Mode' to 'Alternate Keyboard Mode' (mode=0 or 1) --- doc/apps.md | 26 +++++--- doc/settings.md | 32 ++++++---- doc/user-interface.md | 50 ++++++++++++---- src/netxs/apps.hpp | 18 ++---- src/netxs/desktopio/application.hpp | 69 +++++++++++---------- src/netxs/desktopio/baseui.hpp | 1 + src/netxs/desktopio/console.hpp | 15 ++--- src/netxs/desktopio/controls.hpp | 44 +++++++++----- src/netxs/desktopio/directvt.hpp | 2 + src/netxs/desktopio/gui.hpp | 64 ++++++++++++++------ src/netxs/desktopio/input.hpp | 93 +++++++++-------------------- src/netxs/desktopio/system.hpp | 43 ++++++++++++- src/netxs/desktopio/terminal.hpp | 84 ++++++++++++++------------ src/vtm.xml | 14 +++-- 14 files changed, 326 insertions(+), 229 deletions(-) diff --git a/doc/apps.md b/doc/apps.md index dd23f20422..a53092ac79 100644 --- a/doc/apps.md +++ b/doc/apps.md @@ -160,9 +160,9 @@ The list of hotkey actions is slightly different from the list of window menu ac Value | Unique for hotkeys | Default Hotkey | Description -----------------------------|--------------------|------------------------------|------------ -Drop | | | Drop all events for the specified key combination. No further processing. -DropAutoRepeat | | | Drop `Key Repeat` events for the specified key combination. This binding should be specified before the main action for the key combination. -ToggleExclusiveKeybd | x | `Ctrl-Alt`, `Alt-Ctrl` | Toggle exclusive keyboard mode. In exclusive mode, all keyboard events are ignored by higher levels. +Drop | x | | Drop all events for the specified key combination. No further processing. +DropAutoRepeat | x | | Drop `Key Repeat` events for the specified key combination. This binding should be specified before the main action for the key combination. +ToggleHotkeyMode | x | `Ctrl-Alt`, `Alt-Ctrl` | Toggle hotkey mode between mode=0 (deafult) and mode=1. TerminalFindNext | | `Alt+RightArrow` | Highlight next match of selected text fragment. Clipboard content is used if no active selection. TerminalFindPrev | | `Alt+LeftArrow` | Highlight previous match of selected text fragment. Clipboard content is used if no active selection. TerminalViewportOnePageUp | x | `Shift+Ctrl+PageUp` | Scroll one page up. @@ -303,11 +303,23 @@ TerminalSelectionOneShot | | - + + + + + + + + + + + + + @@ -333,10 +345,8 @@ TerminalSelectionOneShot | | - - - - + + ``` diff --git a/doc/settings.md b/doc/settings.md index bc36840b71..841f275079 100644 --- a/doc/settings.md +++ b/doc/settings.md @@ -303,13 +303,14 @@ Application `app_name` | `` | Application layer key bi The syntax for defining key combination bindings is: ```xml - + ``` Tag | Value ---------|-------- `key` | The text string containing the key combination. `action` | The action name. +`mode` | Hotkey mode for which mapping is being done (mode=0 by default). Either `mode=0` or `mode=1` are allowed. The following joiners are allowed for combining keys: @@ -333,12 +334,13 @@ The required key combination sequence can be generated on the Info page, accessi #### Interpretation -Configuration record | Interpretation --------------------------------------------|----------------- -`` | Append existing bindings using an indirect reference (the `NameOfAction` variable without quotes). -`` | Append existing bindings with the directly specified command "NameOfAction". -`` | Remove all existing bindings for the specified key combination "Key+Chord". -`` | Do nothing. +Configuration record | Interpretation +--------------------------------------------------|----------------- +`` | Append existing bindings using an indirect reference (the `NameOfAction` variable without quotes). +`` | Append existing bindings with the directly specified command "NameOfAction". +`` | Append existing bindings for mode=1. +`` | Remove all existing bindings for the specified key combination "Key+Chord". +`` | Do nothing. #### Available actions @@ -347,7 +349,7 @@ Action | Default key combination | Available at layer `Drop` | | All layers | Drop all events for the specified key combination. No further processing. `DropAutoRepeat` | | All layers | Drop `Key Repeat` events for the specified key combination. This binding should be specified before the main action for the key combination. `ToggleDebugOverlay` | | TUI matrix | Toggle debug overlay. -`ToggleExclusiveKeybd` | `Ctrl-Alt`, `Alt-Ctrl` | Application | Toggle exclusive keyboard mode. In exclusive mode, all keyboard events are ignored by higher layers. Exclusive keyboard mode is automatically disabled when refocusing. +`ToggleHotkeyMode` | `Ctrl-Alt`, `Alt-Ctrl` | TUI matrix | Toggle hotkey mode between mode=0 (deafult) and mode=1. `IncreaseCellHeight` | `CapsLock+UpArrow` | Native GUI window | Increase the text cell height by one pixel. `DecreaseCellHeight` | `CapsLock+DownArrow` | Native GUI window | Decrease the text cell height by one pixel. `ResetCellHeight` | `Ctrl+Key0` | Native GUI window | Reset text cell height. @@ -790,7 +792,7 @@ Notes - + @@ -804,9 +806,13 @@ Notes - + - + + + + + @@ -820,6 +826,8 @@ Notes + + @@ -847,8 +855,6 @@ Notes - - diff --git a/doc/user-interface.md b/doc/user-interface.md index d29b4b1f45..e3a1a3175c 100644 --- a/doc/user-interface.md +++ b/doc/user-interface.md @@ -24,19 +24,19 @@ - Ctrl-Alt ² - Toggle exclusive keyboard mode + Ctrl-Alt ¹ + Toggle alternate keyboard mode - F10 ² + F10 ¹ Disconnect all users and shutdown if there are no apps running - Shift+F7 ² + Shift+F7 ¹ Leave current session - Ctrl+PageUp/PageDown ² + Ctrl+PageUp/PageDown ¹ Switch focus between running apps @@ -161,24 +161,24 @@ GUI window Resizing grips - Window 1px-height row (in fullscreen mode)¹ + Window 1px-height row (in fullscreen mode)² - Alt+Enter ² + Alt+Enter ¹ Toggle fullscreen mode - Ctrl+CapsLock ² + Ctrl+CapsLock ¹ Toggle antialiasing mode - CapsLock+UpArrow/DownArrow ² + CapsLock+UpArrow/DownArrow ¹ Scale cell size - CapsLock+0 ² + CapsLock+0 ¹ Reset cell size @@ -214,5 +214,31 @@ -¹ — In fullscreen mode, the GUI window reserves a 1px high area at the top for forwarding mouse events. -² — Key bindings can be customized using the settings. \ No newline at end of file +## Built-in Terminal + + + + + + + + + + + + + + + + + + + + + +
Hotkey ¹ Default action
Alt+RightArrow Highlight next match of selected text fragment. Clipboard content is used if no active selection.
Alt+LeftArrow Highlight previous match of selected text fragment. Clipboard content is used if no active selection.
Shift+Ctrl+PageUp Scroll one page up.
Shift+Ctrl+PageDown Scroll one page down.
Shift+Alt+LeftArrow Scroll one page to the left.
Shift+Alt+RightArrow Scroll one page to the right.
Shift+Ctrl+UpArrow Scroll one line up.
Shift+Ctrl+DownArrow Scroll one line down.
Shift+Ctrl+LeftArrow Scroll one cell to the left.
Shift+Ctrl+RightArrow Scroll one cell to the right.
Shift+Ctrl+Home Don't repeat the Scroll to the scrollback top.
Shift+Ctrl+Home Scroll to the scrollback top.
Shift+Ctrl+End Don't repeat the Scroll to the scrollback bottom (reset viewport position).
Shift+Ctrl+End Scroll to the scrollback bottom (reset viewport position).
+ +--- + +¹ — Key bindings can be customized using settings. +² — In fullscreen mode, the GUI window reserves a 1px high area at the top for forwarding mouse events. \ No newline at end of file diff --git a/src/netxs/apps.hpp b/src/netxs/apps.hpp index 74ef10e9c3..9beeed28f6 100644 --- a/src/netxs/apps.hpp +++ b/src/netxs/apps.hpp @@ -615,31 +615,22 @@ namespace netxs::app::shared ->template plugin() ->template plugin(); auto state_block = title_grid_state->attach(ui::fork::ctor()); - auto state_label = state_block->attach(slot::_1, ui::item::ctor("Exclusive keyboard mode:")->setpad({ 2, 1, 0, 0 })); + auto state_label = state_block->attach(slot::_1, ui::item::ctor("Alternate keyboard mode:")->setpad({ 2, 1, 0, 0 })); auto state_state = state_block->attach(slot::_2, ui::item::ctor(ansi::bgc(reddk).fgx(0).add("█off "))) ->setpad({ 1, 1, 0, 0 }) ->active() ->shader(cell::shaders::xlight, e2::form::state::hover) ->invoke([&](auto& boss) { - auto state_ptr = ptr::shared(faux); - auto& state = *state_ptr; - auto& window_inst = *window; - window->LISTEN(tier::release, hids::events::keybd::focus::exclusive, seed, boss.tracker, (state_ptr)) + window->LISTEN(tier::release, e2::form::state::keybd::hotkey, state, boss.tracker) { - state = !!seed.item; boss.set(state ? ansi::bgc(greendk).fgc(whitelt).add(" on █") : ansi::bgc(reddk).fgx(0) .add("█off ")); boss.base::reflow(); }; - window->LISTEN(tier::release, e2::form::state::keybd::focus::off, gear_id, boss.tracker) // Call gear's subscription - { - if (state) window_inst.bell::signal(tier::preview, hids::events::keybd::focus::exclusive, {}); // to reset exclusive mode. - }; boss.LISTEN(tier::release, hids::events::mouse::button::click::left, gear) { - state ? gear.set_exclusive() - : gear.set_exclusive(window_inst.This()); + gear.set_hotkey_mode(gear.meta(hids::HotkeyMode) ? 0 : hids::HotkeyMode); gear.dismiss_dblclick(); }; }); @@ -760,7 +751,8 @@ namespace netxs::app::shared { if (gear.keystat != input::key::repeated) (*update_ptr)(items_inst, gear, true); }); - keybd.template bind( "Any", "UpdateChordPreview"); + keybd.template bind( "Any", "UpdateChordPreview", 0); + keybd.template bind( "Any", "UpdateChordPreview", 1); }); inside->attach(slot::_2, ui::post::ctor()) ->limits({ -1, 1 }) diff --git a/src/netxs/desktopio/application.hpp b/src/netxs/desktopio/application.hpp index 56b73554aa..b78a4764e8 100644 --- a/src/netxs/desktopio/application.hpp +++ b/src/netxs/desktopio/application.hpp @@ -116,7 +116,7 @@ namespace netxs::app::shared auto esc_pressed = ptr::shared(faux); keybd.proc("WindowClose", [&, esc_pressed](hids& gear) { - if (!gear.is_exclusive() && *esc_pressed) + if (*esc_pressed) { boss.bell::signal(tier::anycast, e2::form::proceed::quit::one, true); gear.set_handled(true); @@ -130,37 +130,40 @@ namespace netxs::app::shared { if (std::exchange(*esc_pressed, faux) != *esc_pressed) boss.bell::signal(tier::anycast, e2::form::state::keybd::command::close, *esc_pressed); }); - keybd.template bind( "Esc", "DropAutoRepeat"); - keybd.template bind( "Esc", "WindowClosePreview"); - keybd.template bind("-Esc", "WindowClose"); - keybd.template bind( "Any", "CancelWindowClose"); - keybd.proc("ScrollPageUp" , [&](hids& gear){ if (!gear.is_exclusive()) { scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::bypage::y, { .vector = { 0, 1 }}); } }); - keybd.proc("ScrollPageDown" , [&](hids& gear){ if (!gear.is_exclusive()) { scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::bypage::y, { .vector = { 0,-1 }}); } }); - keybd.proc("ScrollLineUp" , [&](hids& gear){ if (!gear.is_exclusive()) { scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::bystep::y, { .vector = { 0, 3 }}); } }); - keybd.proc("ScrollLineDown" , [&](hids& gear){ if (!gear.is_exclusive()) { scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::bystep::y, { .vector = { 0,-3 }}); } }); - keybd.proc("ScrollCharLeft" , [&](hids& gear){ if (!gear.is_exclusive()) { scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::bystep::x, { .vector = { 3, 0 }}); } }); - keybd.proc("ScrollCharRight" , [&](hids& gear){ if (!gear.is_exclusive()) { scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::bystep::x, { .vector = {-3, 0 }}); } }); - keybd.proc("ScrollTop" , [&](hids& gear){ if (!gear.is_exclusive()) { scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::to_top::y); } }); - keybd.proc("ScrollEnd" , [&](hids& gear){ if (!gear.is_exclusive()) { scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::to_end::y); } }); - keybd.proc("ToggleMaximize" , [&](hids& gear){ if (!gear.is_exclusive()) { scroll_inst.bell::enqueue(boss.This(), [&](auto& /*boss*/){ scroll_inst.base::riseup(tier::preview, e2::form::size::enlarge::maximize, gear); }); }}); // Refocus-related operations require execution outside of keyboard events. - keybd.proc("ToggleFullscreen" , [&](hids& gear){ if (!gear.is_exclusive()) { scroll_inst.bell::enqueue(boss.This(), [&](auto& /*boss*/){ scroll_inst.base::riseup(tier::preview, e2::form::size::enlarge::fullscreen, gear); }); }}); - keybd.proc("ToggleExclusiveKeybd", [&](hids& gear){ if (!gear.is_exclusive()) gear.set_exclusive(boss.This()); else gear.set_exclusive(); }); - keybd.bind("PageUp" , "ScrollPageUp" ); - keybd.bind("PageDown" , "ScrollPageDown" ); - keybd.bind("UpArrow" , "ScrollLineUp" ); - keybd.bind("DownArrow" , "ScrollLineDown" ); - keybd.bind("LeftArrow" , "ScrollCharLeft" ); - keybd.bind("RightArrow", "ScrollCharRight" ); - keybd.bind("Home" , "DropAutoRepeat" ); - keybd.bind("Home" , "ScrollTop" ); - keybd.bind("End" , "DropAutoRepeat" ); - keybd.bind("End" , "ScrollEnd" ); - keybd.bind("F11" , "DropAutoRepeat" ); - keybd.bind("F11" , "ToggleMaximize" ); - keybd.bind("F12" , "DropAutoRepeat" ); - keybd.bind("F12" , "ToggleFullscreen" ); - keybd.bind("Ctrl-Alt" , "ToggleExclusiveKeybd"); - keybd.bind("Alt-Ctrl" , "ToggleExclusiveKeybd"); + keybd.proc("ScrollPageUp" , [&](hids& /*gear*/){ scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::bypage::y, { .vector = { 0, 1 }}); }); + keybd.proc("ScrollPageDown" , [&](hids& /*gear*/){ scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::bypage::y, { .vector = { 0,-1 }}); }); + keybd.proc("ScrollLineUp" , [&](hids& /*gear*/){ scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::bystep::y, { .vector = { 0, 3 }}); }); + keybd.proc("ScrollLineDown" , [&](hids& /*gear*/){ scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::bystep::y, { .vector = { 0,-3 }}); }); + keybd.proc("ScrollCharLeft" , [&](hids& /*gear*/){ scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::bystep::x, { .vector = { 3, 0 }}); }); + keybd.proc("ScrollCharRight" , [&](hids& /*gear*/){ scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::bystep::x, { .vector = {-3, 0 }}); }); + keybd.proc("ScrollTop" , [&](hids& /*gear*/){ scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::to_top::y); }); + keybd.proc("ScrollEnd" , [&](hids& /*gear*/){ scroll_inst.base::riseup(tier::preview, e2::form::upon::scroll::to_end::y); }); + //todo use sptr for gear when enqueueing (dangling reference) + keybd.proc("ToggleMaximize" , [&](hids& gear){ scroll_inst.bell::enqueue(boss.This(), [&](auto& /*boss*/){ scroll_inst.base::riseup(tier::preview, e2::form::size::enlarge::maximize, gear); }); }); // Refocus-related operations require execution outside of keyboard eves. + keybd.proc("ToggleFullscreen", [&](hids& gear){ scroll_inst.bell::enqueue(boss.This(), [&](auto& /*boss*/){ scroll_inst.base::riseup(tier::preview, e2::form::size::enlarge::fullscreen, gear); }); }); + auto binding = [&](auto mode) + { + keybd.template bind( "Esc", "DropAutoRepeat" , mode); + keybd.template bind( "Esc", "WindowClosePreview", mode); + keybd.template bind("-Esc", "WindowClose" , mode); + keybd.template bind( "Any", "CancelWindowClose" , mode); + keybd.bind("PageUp" , "ScrollPageUp" , mode); + keybd.bind("PageDown" , "ScrollPageDown" , mode); + keybd.bind("UpArrow" , "ScrollLineUp" , mode); + keybd.bind("DownArrow" , "ScrollLineDown" , mode); + keybd.bind("LeftArrow" , "ScrollCharLeft" , mode); + keybd.bind("RightArrow", "ScrollCharRight" , mode); + keybd.bind("Home" , "DropAutoRepeat" , mode); + keybd.bind("Home" , "ScrollTop" , mode); + keybd.bind("End" , "DropAutoRepeat" , mode); + keybd.bind("End" , "ScrollEnd" , mode); + keybd.bind("F11" , "DropAutoRepeat" , mode); + keybd.bind("F11" , "ToggleMaximize" , mode); + keybd.bind("F12" , "DropAutoRepeat" , mode); + keybd.bind("F12" , "ToggleFullscreen", mode); + }; + binding(0); + binding(1); }; using builder_t = std::function; @@ -680,7 +683,7 @@ namespace netxs::app::shared //todo implement 'fonts/font/file' - font file path/url gui_config.fontlist.push_back(f->take_value()); } - auto keybinds = config.list("/config/gui/hotkeys/key"); + auto keybinds = config.list("/config/hotkeys/gui/key"); for (auto keybind_ptr : keybinds) { auto& keybind = *keybind_ptr; diff --git a/src/netxs/desktopio/baseui.hpp b/src/netxs/desktopio/baseui.hpp index 97a55f5acb..ffce934c1d 100644 --- a/src/netxs/desktopio/baseui.hpp +++ b/src/netxs/desktopio/baseui.hpp @@ -451,6 +451,7 @@ namespace netxs::events::userland EVENT_XS( find , ui::focus_test_t ), // request: Check the focus. EVENT_XS( next , ui::focus_test_t ), // request: Next hop count. EVENT_XS( check , bool ), // anycast: Check any focus. + EVENT_XS( hotkey , si32 ), // release: Hotkeymode. GROUP_XS( focus , const id_t ), // release: Has any keybd focus. GROUP_XS( command , si32 ), // release: Hotkey command preview. diff --git a/src/netxs/desktopio/console.hpp b/src/netxs/desktopio/console.hpp index 3436a0a98f..91ca680f45 100644 --- a/src/netxs/desktopio/console.hpp +++ b/src/netxs/desktopio/console.hpp @@ -1135,6 +1135,7 @@ namespace netxs::ui //auto simple = config.take("/config/simple", faux); // DirectVT Gateway console case. config.set("/config/simple", faux); keybd.proc("ToggleDebugOverlay", [&](hids& gear){ gear.set_handled(); debug ? debug.stop() : debug.start(); }); + keybd.proc("ToggleHotkeyMode", [&](hids& gear){ gear.set_handled(); gear.set_hotkey_mode(gear.meta(hids::HotkeyMode) ? 0 : hids::HotkeyMode); }); keybd.load(config, "/config/hotkeys/tui/key"); base::root(true); @@ -1201,6 +1202,12 @@ namespace netxs::ui } //if constexpr (debugmode) log(prompt::foci, text(--seed.deep * 4, ' '), "----------------gate"); }; + LISTEN(tier::preview, hids::events::keybd::mode, gear, tokens) + { + auto [ext_gear_id, gear_ptr] = input.get_foreign_gear_id(gear.id); + if (!gear_ptr) return; + conio.hotkey_mode.send(canal, ext_gear_id, gear.meta(hids::HotkeyMode)); + }; LISTEN(tier::preview, hids::events::keybd::focus::cut, seed, tokens) { if (direct) @@ -1238,15 +1245,9 @@ namespace netxs::ui }; if (direct) // Forward unhandled events outside. { - LISTEN(tier::release, hids::events::keybd::focus::exclusive, seed) // Request exclusive mode. - { - auto [ext_gear_id, gear_ptr] = input.get_foreign_gear_id(seed.id); - if (!gear_ptr) return; - conio.focus_set.send(canal, ext_gear_id, seed.item ? -1 : -2); // -1: set, -2: reset. - }; LISTEN(tier::release, hids::events::keybd::key::any, gear) // Return back unhandled keybd events. { - if (gear && !gear.handled && ptr::is_empty(gear.exclusive_wptr)) // Do not return events in exclusive mode. + if (gear && !gear.handled) { auto [ext_gear_id, gear_ptr] = input.get_foreign_gear_id(gear.id); if (gear_ptr) diff --git a/src/netxs/desktopio/controls.hpp b/src/netxs/desktopio/controls.hpp index e1fd777ecc..0b718595fd 100644 --- a/src/netxs/desktopio/controls.hpp +++ b/src/netxs/desktopio/controls.hpp @@ -1350,10 +1350,22 @@ namespace netxs::ui gear.dismiss(); }; // Subscribe on keybd events. + auto hotkey_mode_ptr = ptr::shared(0); + auto& hotkey_mode = *hotkey_mode_ptr; + boss.LISTEN(tier::request, e2::form::state::keybd::hotkey, m, memo, (hotkey_mode_ptr)) + { + m = hotkey_mode; + }; boss.LISTEN(tier::preview, hids::events::keybd::key::post, gear, memo) // preview: Run after any. { //if constexpr (debugmode) log(prompt::foci, "KeyEvent: gear:", gear.id, " hub:", boss.id, " gears.size:", gears.size()); if (!gear) return; + if (gear.payload == input::keybd::type::keypress + && std::exchange(hotkey_mode, gear.meta(hids::HotkeyMode)) != hotkey_mode) // Notify if hotkey mode has changed. + { + auto m = hotkey_mode >> 28; //std::countr_zero(hids::HotkeyMode); //todo MSVC doesn't get it + boss.bell::signal(tier::release, e2::form::state::keybd::hotkey, m); + } auto& route = get_route(gear.id); if (route.active) { @@ -1830,8 +1842,8 @@ namespace netxs::ui using skill::boss, skill::memo; - std::unordered_map, qiew::hash, qiew::equal> handlers_preview; - std::unordered_map, qiew::hash, qiew::equal> handlers_release; + std::array, qiew::hash, qiew::equal>, 2> handlers_preview; + std::array, qiew::hash, qiew::equal>, 2> handlers_release; std::unordered_map api_map; auto _get_chords(qiew chord_str) @@ -1848,9 +1860,11 @@ namespace netxs::ui } } template - auto _set(qiew chord_str, sptr handler_ptr) + auto _set(qiew chord_str, sptr handler_ptr, si32 mode) { - auto& handlers = Tier == tier::release ? handlers_release : handlers_preview; + //todo unify + auto hmode = mode ? 1 : 0; + auto& handlers = Tier == tier::release ? handlers_release[hmode] : handlers_preview[hmode]; if (auto chords = _get_chords(chord_str)) { for (auto& chord : chords.value()) @@ -1862,9 +1876,10 @@ namespace netxs::ui else return faux; } template - auto _reset(qiew chord_str) + auto _reset(qiew chord_str, si32 mode) { - auto& handlers = Tier == tier::release ? handlers_release : handlers_preview; + auto hmode = mode ? 1 : 0; + auto& handlers = Tier == tier::release ? handlers_release[hmode] : handlers_preview[hmode]; if (auto chords = _get_chords(chord_str)) { for (auto& chord : chords.value()) @@ -1878,7 +1893,8 @@ namespace netxs::ui template void _dispatch(hids& gear, qiew chord) { - auto& handlers = Tier == tier::release ? handlers_release : handlers_preview; + auto hmode = gear.meta(hids::HotkeyMode) ? 1 : 0; + auto& handlers = Tier == tier::release ? handlers_release[hmode] : handlers_preview[hmode]; auto iter = handlers.find(chord); if (iter != handlers.end()) { @@ -1941,27 +1957,22 @@ namespace netxs::ui api_map[name] = ptr::shared(std::move(proc)); } template - auto bind(qiew chord_str, qiew proc_name) + auto bind(qiew chord_str, qiew proc_name, si32 mode = 0) { if (!chord_str) return; if (proc_name) { if (auto iter = api_map.find(proc_name); iter != api_map.end()) { - _set(chord_str, iter->second); + _set(chord_str, iter->second, mode); } else log("%%Action '%proc%' not found", prompt::user, proc_name); } else { - _reset(chord_str); + _reset(chord_str, mode); } } - auto wipe() - { - handlers_release.clear(); - handlers_preview.clear(); - } template auto load(xmls& config, qiew path) { @@ -1973,7 +1984,8 @@ namespace netxs::ui { auto chord = keybind.take_value(); auto action = keybind.take("action", ""s); - bind(chord, action); + auto mode = keybind.take("mode", 0); + bind(chord, action, mode); } } } diff --git a/src/netxs/desktopio/directvt.hpp b/src/netxs/desktopio/directvt.hpp index f7610671e3..8bef73fdd8 100644 --- a/src/netxs/desktopio/directvt.hpp +++ b/src/netxs/desktopio/directvt.hpp @@ -863,6 +863,7 @@ namespace netxs::directvt (fp2d, click)) STRUCT_macro(focus_cut, (id_t, gear_id)) STRUCT_macro(focus_set, (id_t, gear_id) (si32, solo)) + STRUCT_macro(hotkey_mode, (id_t, gear_id) (si32, mode)) STRUCT_macro(fullscrn, (id_t, gear_id)) STRUCT_macro(maximize, (id_t, gear_id)) STRUCT_macro(header, (id_t, window_id) (text, utf8)) @@ -1414,6 +1415,7 @@ namespace netxs::directvt X(jgc_list ) /* List of jumbo GC. */\ X(focus_cut ) /* Request to focus cut. */\ X(focus_set ) /* Request to focus set. */\ + X(hotkey_mode ) /* Request hotkey mode to set. */\ X(fullscrn ) /* Notify/Request to fullscreen. */\ X(maximize ) /* Request to maximize window. */\ X(header ) /* Set window title. */\ diff --git a/src/netxs/desktopio/gui.hpp b/src/netxs/desktopio/gui.hpp index 168509e792..4a6c4044ac 100644 --- a/src/netxs/desktopio/gui.hpp +++ b/src/netxs/desktopio/gui.hpp @@ -1807,21 +1807,24 @@ namespace netxs::gui void handle(s11n::xs::focus_set lock) { auto& item = lock.thing; - if (item.solo < 0) // Exclusive keyboard mode: -1: set, -2: reset. + if (owner.mfocus.focused()) // We are the focus tree endpoint. Signal back the focus set up. { - gears->set_exclusive(item.solo == -1 ? owner.This() : netxs::sptr{}); // Exclusive mode will be reset automatically when focus is changed. + auto seed = owner.bell::signal(tier::release, hids::events::keybd::focus::bus::on, { .id = item.gear_id, .solo = item.solo, .item = owner.This() }); } - else + else owner.window_post_command(ipc::take_focus); + if (item.solo == ui::pro::focus::solo::on) // Set solo focus. { - if (owner.mfocus.focused()) // We are the focus tree endpoint. Signal back the focus set up. - { - auto seed = owner.bell::signal(tier::release, hids::events::keybd::focus::bus::on, { .id = item.gear_id, .solo = item.solo, .item = owner.This() }); - } - else owner.window_post_command(ipc::take_focus); - if (item.solo == ui::pro::focus::solo::on) // Set solo focus. - { - owner.window_post_command(ipc::solo_focus); - } + owner.window_post_command(ipc::solo_focus); + } + } + void handle(s11n::xs::hotkey_mode lock) + { + auto& k = lock.thing; + auto guard = owner.sync(); + if (auto gear_ptr = owner.bell::getref(k.gear_id)) + { + owner.hotkey = k.mode; + owner.window_post_command(ipc::sync_state); } } void handle(s11n::xs::syskeybd lock) @@ -1964,6 +1967,7 @@ namespace netxs::gui regs fields; // winbase: Text input field list. evnt stream; // winbase: DirectVT event proxy. kmap chords; // winbase: Pressed key table (key chord). + si32 hotkey; // winbase: Alternate hotkey mode. winbase(auth& indexer, std::list& font_names, si32 cell_height, bool antialiasing, span blink_rate, twod grip_cell, std::list>& hotkeys) : base{ indexer }, @@ -1994,7 +1998,8 @@ namespace netxs::gui heldby{ 0x0 }, whlacc{ 0.f }, wdelta{ 24.f }, - stream{ *this, *os::dtvt::client } + stream{ *this, *os::dtvt::client }, + hotkey{ 0 } { wkeybd.proc("IncreaseCellHeight" , [&](hids& gear){ gear.set_handled(); IncreaseCellHeight(1.f); }); wkeybd.proc("DecreaseCellHeight" , [&](hids& gear){ gear.set_handled(); IncreaseCellHeight(-1.f);}); @@ -2004,7 +2009,8 @@ namespace netxs::gui wkeybd.proc("RollFontsBackward" , [&](hids& gear){ gear.set_handled(); RollFontList(feed::rev); }); wkeybd.proc("RollFontsForward" , [&](hids& gear){ gear.set_handled(); RollFontList(feed::fwd); }); wkeybd.proc("_ResetWheelAccumulator", [&](hids& /*gear*/){ whlacc = {}; }); - wkeybd.bind("-Ctrl", "_ResetWheelAccumulator"); + wkeybd.bind("-Ctrl", "_ResetWheelAccumulator", 0); + wkeybd.bind("-Ctrl", "_ResetWheelAccumulator", 1); for (auto& [chord, action] : hotkeys) wkeybd.bind(chord, action); } @@ -2845,12 +2851,36 @@ namespace netxs::gui { keybd_send_block(block); // Send multifocus events. } - return gear.is_exclusive() || wkeybd.filter(gear); + return wkeybd.filter(gear); }); } void keybd_send_state(si32 virtcod = {}, si32 keystat = {}, si32 scancod = {}, bool extflag = {}, view cluster = {}, bool synth = faux) { - auto state = 0; + if (auto hotkey_mode_changed = virtcod == 0 && (keymod ^ hotkey) & input::hids::HotkeyMode) // Send empty key to update hotkey mode state. + { + auto& gear = *stream.gears; + netxs::set_flag(keymod, hotkey); + netxs::set_flag(gear.ctlstat, hotkey); + auto temp = syskeybd{}; //todo same code in system.hpp:4918 + std::swap(temp.vkchord, gear.vkchord); + std::swap(temp.scchord, gear.scchord); + std::swap(temp.chchord, gear.chchord); + std::swap(temp.cluster, gear.cluster); + std::swap(temp.keystat, gear.keystat); + gear.virtcod = 0; + gear.scancod = 0; + gear.keycode = 0; + gear.payload = input::keybd::type::keypress; + stream_keybd(gear); + std::swap(temp.vkchord, gear.vkchord); + std::swap(temp.scchord, gear.scchord); + std::swap(temp.chchord, gear.chchord); + std::swap(temp.cluster, gear.cluster); + std::swap(temp.keystat, gear.keystat); + return; + } + + auto state = hotkey; auto cs = 0; if (extflag) cs |= input::key::ExtendedKey; if (synth) @@ -3067,7 +3097,7 @@ namespace netxs::gui stream.m.ctlstat = keymod; keybd.syncto(gear); gear.gear_id = gear.bell::id; // Restore gear id. - if (gear.is_exclusive() || wkeybd.filter(gear)) + if (wkeybd.filter(gear)) { stream.keybd(gear); } diff --git a/src/netxs/desktopio/input.hpp b/src/netxs/desktopio/input.hpp index 01808fb842..f00e0de670 100644 --- a/src/netxs/desktopio/input.hpp +++ b/src/netxs/desktopio/input.hpp @@ -34,19 +34,10 @@ namespace netxs::events::userland EVENT_XS( enter, input::hids ), // inform the form about the mouse hover. EVENT_XS( leave, input::hids ), // inform the form about leaving the mouse. }; - //SUBSET_XS( keybd ) - //{ - // EVENT_XS( got , input::hids ), - // EVENT_XS( lost, input::hids ), - //}; - //SUBSET_XS( focus ) - //{ - // EVENT_XS( got , input::hids ), - // EVENT_XS( lost, input::hids ), - //}; }; SUBSET_XS( keybd ) { + EVENT_XS( mode , input::hids ), GROUP_XS( key , input::hids ), GROUP_XS( control, input::hids ), GROUP_XS( state , input::hids ), @@ -56,6 +47,7 @@ namespace netxs::events::userland { EVENT_XS( post, input::hids ), }; + //todo revise SUBSET_XS( control ) { GROUP_XS( up , input::hids ), @@ -80,6 +72,7 @@ namespace netxs::events::userland EVENT_XS( shift_left , input::hids ), }; }; + //todo revise SUBSET_XS( state ) { GROUP_XS( on , input::hids ), @@ -110,7 +103,6 @@ namespace netxs::events::userland EVENT_XS( cut, input::foci ), // Cut mono focus branch. EVENT_XS( dry, input::foci ), // Remove the reference to the specified applet. EVENT_XS( hop, input::foci ), // Change next hop destination. args: pair. - EVENT_XS( exclusive, input::foci ), // preview/release: Request exclusive keyboard mode. GROUP_XS( bus, input::foci ), SUBSET_XS( bus ) @@ -1436,25 +1428,25 @@ namespace netxs::input enum modifiers { - LCtrl = 1 << 0, // Left ⌃ Ctrl - RCtrl = 1 << 1, // Right ⌃ Ctrl - LAlt = 1 << 2, // Left ⎇ Alt, Left ⌥ Option - RAlt = 1 << 3, // Right ⎇ Alt, Right ⌥ Option, ⇮ AltGr - LShift = 1 << 4, // Left ⇧ Shift - RShift = 1 << 5, // Right ⇧ Shift - LWin = 1 << 6, // Left ⊞ Win, ◆ Meta, ⌘ Cmd (Apple key), ❖ Super - RWin = 1 << 7, // Right ⊞ Win, ◆ Meta, ⌘ Cmd (Apple key), ❖ Super - NumLock = 1 << 12, // ⇭ Num Lock - CapsLock = 1 << 13, // ⇪ Caps Lock - ScrlLock = 1 << 14, // ⇳ Scroll Lock (⤓) - HkeyMode = 1 << 28, // Alternate hotkey mode - AltGr = LAlt | LCtrl, - anyCtrl = LCtrl | RCtrl, - anyAlt = LAlt | RAlt, - anyShift = LShift | RShift, - anyAltGr = anyAlt | anyCtrl, - anyWin = LWin | RWin, - anyMod = anyAlt | anyCtrl | anyShift | anyWin, + LCtrl = 1 << 0, // Left ⌃ Ctrl + RCtrl = 1 << 1, // Right ⌃ Ctrl + LAlt = 1 << 2, // Left ⎇ Alt, Left ⌥ Option + RAlt = 1 << 3, // Right ⎇ Alt, Right ⌥ Option, ⇮ AltGr + LShift = 1 << 4, // Left ⇧ Shift + RShift = 1 << 5, // Right ⇧ Shift + LWin = 1 << 6, // Left ⊞ Win, ◆ Meta, ⌘ Cmd (Apple key), ❖ Super + RWin = 1 << 7, // Right ⊞ Win, ◆ Meta, ⌘ Cmd (Apple key), ❖ Super + NumLock = 1 << 12, // ⇭ Num Lock + CapsLock = 1 << 13, // ⇪ Caps Lock + ScrlLock = 1 << 14, // ⇳ Scroll Lock (⤓) + HotkeyMode = 1 << 28, // Alternate hotkey mode + AltGr = LAlt | LCtrl, + anyCtrl = LCtrl | RCtrl, + anyAlt = LAlt | RAlt, + anyShift = LShift | RShift, + anyAltGr = anyAlt | anyCtrl, + anyWin = LWin | RWin, + anyMod = anyAlt | anyCtrl | anyShift | anyWin, }; static auto build_alone_key() @@ -1574,9 +1566,6 @@ namespace netxs::input id_t user_index; // hids: User/Device image/icon index. kmap other_key; // hids: Dynamic key-vt mapping. - wptr exclusive_wptr; // hids: Exclusive keyboard owner. - hook exclusive_memo; // hids: Exclusive keyboard owner reset. - template hids(auth& indexer, T& props, base& owner, core const& idmap) : bell{ indexer }, @@ -1610,27 +1599,6 @@ namespace netxs::input return alive; } - void set_exclusive(sptr kb_owner = {}) - { - //todo make it crossprocess - auto prev = exclusive_wptr.lock(); - if (kb_owner != prev) - { - exclusive_wptr = kb_owner; - exclusive_memo.reset(); - if (prev) prev->bell::signal(tier::release, hids::events::keybd::focus::exclusive, {}); // Trigger to reset exclusive mode. - if (kb_owner) - { - kb_owner->bell::signal(tier::release, hids::events::keybd::focus::exclusive, { .id = bell::id, .item = kb_owner }); // Notify requestee. - kb_owner->LISTEN(tier::preview, hids::events::keybd::focus::exclusive, seed, exclusive_memo) // Reset exclusive mode on requestee focus change (requestee calls signal(tier::preview, hids::events::keybd::focus::exclusive)). - { - set_exclusive(); - }; - } - owner.bell::signal(tier::release, hids::events::keybd::focus::exclusive, { .id = bell::id, .item = kb_owner }); // Forward outside (crossprocess). - } - } - auto tooltip_enabled(time const& now) { return !mouse::m_sys.buttons @@ -1760,6 +1728,13 @@ namespace netxs::input { handled = b; } + void set_hotkey_mode(si32 mode) + { + auto temp = keybd::ctlstat; + netxs::set_flag(keybd::ctlstat, mode); + owner.bell::signal(tier::preview, hids::events::keybd::mode, *this); + keybd::ctlstat = temp; + } void take(sysmouse& m) { @@ -1956,19 +1931,9 @@ namespace netxs::input if (m_sav.changed != m_sys.changed) m_sav = m_sys; return !alive; } - auto is_exclusive() - { - return !ptr::is_empty(exclusive_wptr); - } void fire_keybd() { alive = true; - if (is_exclusive()) - if (auto target = exclusive_wptr.lock()) - { - target->bell::signal(tier::preview, hids::events::keybd::key::post, *this); - return; - } owner.bell::signal(tier::preview, hids::events::keybd::key::post, *this); } void fire_focus() diff --git a/src/netxs/desktopio/system.hpp b/src/netxs/desktopio/system.hpp index 6c66f1ca11..3a49a6b234 100644 --- a/src/netxs/desktopio/system.hpp +++ b/src/netxs/desktopio/system.hpp @@ -4840,6 +4840,8 @@ namespace netxs::os { struct adapter : s11n { + si32 hotkey = 0; + void direct(s11n::xs::bitmap_vt16 /*lock*/, view& data) { io::send(data); } void direct(s11n::xs::bitmap_vt256 /*lock*/, view& data) { io::send(data); } void direct(s11n::xs::bitmap_vtrgb /*lock*/, view& data) { io::send(data); } @@ -4907,6 +4909,29 @@ namespace netxs::os { s11n::recycle_cliprequest(dtvt::client, lock); } + void handle(s11n::xs::hotkey_mode lock) + { + auto& k = lock.thing; + hotkey = k.mode; + auto item = s11n::syskeybd.freeze(); + netxs::set_flag(item.thing.ctlstat, hotkey); + auto temp = input::syskeybd{}; //todo same code in gui.hpp:2860 + std::swap(temp.vkchord, item.thing.vkchord); + std::swap(temp.scchord, item.thing.scchord); + std::swap(temp.chchord, item.thing.chchord); + std::swap(temp.cluster, item.thing.cluster); + std::swap(temp.keystat, item.thing.keystat); + item.thing.virtcod = 0; + item.thing.scancod = 0; + item.thing.keycode = 0; + item.thing.payload = input::keybd::type::keypress; + item.thing.sendby(dtvt::client); + std::swap(temp.vkchord, item.thing.vkchord); + std::swap(temp.scchord, item.thing.scchord); + std::swap(temp.chchord, item.thing.chchord); + std::swap(temp.cluster, item.thing.cluster); + std::swap(temp.keystat, item.thing.keystat); + } adapter() : s11n{ *this } @@ -6047,8 +6072,22 @@ namespace netxs::os auto alarm = fire{}; auto alive = flag{ true }; - auto keybd = [&](auto& data){ if (alive) proxy.syskeybd.send(intio, data); }; - auto mouse = [&](auto& data){ if (alive) proxy.sysmouse.send(intio, data); }; + auto keybd = [&](auto& data) + { + if (alive) + { + netxs::set_flag(data.ctlstat, proxy.hotkey); // Inject alternate hotkey mode. + proxy.syskeybd.send(intio, data); + } + }; + auto mouse = [&](auto& data) + { + if (alive) + { + netxs::set_flag(data.ctlstat, proxy.hotkey); // Inject alternate hotkey mode. + proxy.sysmouse.send(intio, data); + } + }; auto winsz = [&](auto& data){ if (alive) proxy.syswinsz.send(intio, data); }; auto focus = [&](auto& data){ if (alive) proxy.sysfocus.send(intio, data); }; auto close = [&](auto& data){ if (alive.exchange(faux)) proxy.sysclose.send(intio, data); }; diff --git a/src/netxs/desktopio/terminal.hpp b/src/netxs/desktopio/terminal.hpp index ff87265b44..3ec03f2890 100644 --- a/src/netxs/desktopio/terminal.hpp +++ b/src/netxs/desktopio/terminal.hpp @@ -7716,36 +7716,36 @@ namespace netxs::ui publish_property(ui::term::events::search::status, [&](auto& v){ v = target->selection_button(); }); selection_selmod(config.def_selmod); - chords.proc("TerminalFindPrev", [&](hids& gear){ gear.set_handled(); selection_search(gear, feed::rev); }); - chords.proc("TerminalFindNext", [&](hids& gear){ gear.set_handled(); selection_search(gear, feed::fwd); }); - chords.proc("TerminalViewportOnePageLeft", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bypage::x, { .vector = { 1, 0 }}); }); - chords.proc("TerminalViewportOnePageRight", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bypage::x, { .vector = {-1, 0 }}); }); - chords.proc("TerminalViewportOneCharLeft", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bystep::x, { .vector = { 1, 0 }}); }); - chords.proc("TerminalViewportOneCharRight", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bystep::x, { .vector = {-1, 0 }}); }); - chords.proc("TerminalViewportOneCharUp", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bystep::y, { .vector = { 0, 1 }}); }); - chords.proc("TerminalViewportOneCharDown", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bystep::y, { .vector = { 0,-1 }}); }); - chords.proc("TerminalViewportOnePageUp", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bypage::y, { .vector = { 0, 1 }}); }); - chords.proc("TerminalViewportOnePageDown", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bypage::y, { .vector = { 0,-1 }}); }); - chords.proc("TerminalViewportTop", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::to_top::y); }); - chords.proc("TerminalViewportEnd", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::to_end::y); }); - chords.proc("TerminalSelectionCancel", [&](hids& gear){ if (!selection_active()) return; gear.set_handled(); exec_cmd(commands::ui::deselect); }); - chords.proc("TerminalToggleCwdSync", [&](hids& gear){ gear.set_handled(); base::riseup(tier::preview, ui::term::events::toggle::cwdsync, true); }); - chords.proc("TerminalToggleWrapMode", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::togglewrp); }); - chords.proc("TerminalQuit", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::sighup); }); - chords.proc("TerminalRestart", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::restart); }); - chords.proc("TerminalToggleFullscreen", [&](hids& gear){ gear.set_handled(); bell::enqueue(This(), [&](auto& /*boss*/){ base::riseup(tier::preview, e2::form::size::enlarge::fullscreen, gear); }); }); // Refocus-related operations require execution outside of keyboard events. - chords.proc("TerminalToggleMaximize", [&](hids& gear){ gear.set_handled(); bell::enqueue(This(), [&](auto& /*boss*/){ base::riseup(tier::preview, e2::form::size::enlarge::maximize, gear); }); }); - chords.proc("TerminalUndo", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::undo); }); - chords.proc("TerminalRedo", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::redo); }); - chords.proc("TerminalClipboardPaste", [&](hids& gear){ gear.set_handled(); paste(gear); }); - chords.proc("TerminalClipboardWipe", [&](hids& gear){ gear.set_handled(); gear.clear_clipboard(); }); - chords.proc("TerminalSwitchCopyMode", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::togglesel); }); - chords.proc("TerminalSelectionCopy", [&](hids& gear){ gear.set_handled(); copy(gear); }); - chords.proc("TerminalToggleSelectionMode", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::toggleselalt); }); - chords.proc("TerminalSelectionOneShot", [&](hids& gear){ gear.set_handled(); set_oneshot(mime::textonly); }); - chords.proc("TerminalViewportCopy", [&](hids& gear){ gear.set_handled(); prnscrn(gear); }); - chords.proc("TerminalToggleStdioLog", [&](hids& gear){ gear.set_handled(); set_log(!io_log); ondata(); }); - chords.proc("ToggleExclusiveKeybd", [&](hids& gear){ if (!gear.is_exclusive()) gear.set_exclusive(This()); else gear.set_exclusive(); }); + chords.proc("TerminalFindPrev", [&](hids& gear){ gear.set_handled(); selection_search(gear, feed::rev); }); + chords.proc("TerminalFindNext", [&](hids& gear){ gear.set_handled(); selection_search(gear, feed::fwd); }); + chords.proc("TerminalViewportOnePageLeft", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bypage::x, { .vector = { 1, 0 }}); }); + chords.proc("TerminalViewportOnePageRight", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bypage::x, { .vector = {-1, 0 }}); }); + chords.proc("TerminalViewportOneCharLeft", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bystep::x, { .vector = { 1, 0 }}); }); + chords.proc("TerminalViewportOneCharRight", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bystep::x, { .vector = {-1, 0 }}); }); + chords.proc("TerminalViewportOneCharUp", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bystep::y, { .vector = { 0, 1 }}); }); + chords.proc("TerminalViewportOneCharDown", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bystep::y, { .vector = { 0,-1 }}); }); + chords.proc("TerminalViewportOnePageUp", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bypage::y, { .vector = { 0, 1 }}); }); + chords.proc("TerminalViewportOnePageDown", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::bypage::y, { .vector = { 0,-1 }}); }); + chords.proc("TerminalViewportTop", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::to_top::y); }); + chords.proc("TerminalViewportEnd", [&](hids& gear){ if (target != &normal) return; gear.set_handled(); base::riseup(tier::preview, e2::form::upon::scroll::to_end::y); }); + chords.proc("TerminalSelectionCancel", [&](hids& gear){ if (!selection_active()) return; gear.set_handled(); exec_cmd(commands::ui::deselect); }); + chords.proc("TerminalToggleCwdSync", [&](hids& gear){ gear.set_handled(); base::riseup(tier::preview, ui::term::events::toggle::cwdsync, true); }); + chords.proc("TerminalToggleWrapMode", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::togglewrp); }); + chords.proc("TerminalQuit", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::sighup); }); + chords.proc("TerminalRestart", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::restart); }); + //todo use wptr for gear when enqueueing + chords.proc("TerminalToggleFullscreen", [&](hids& gear){ gear.set_handled(); bell::enqueue(This(), [&](auto& /*boss*/){ base::riseup(tier::preview, e2::form::size::enlarge::fullscreen, gear); }); }); // Refocus-related operations require execution outside of keyboard events. + chords.proc("TerminalToggleMaximize", [&](hids& gear){ gear.set_handled(); bell::enqueue(This(), [&](auto& /*boss*/){ base::riseup(tier::preview, e2::form::size::enlarge::maximize, gear); }); }); + chords.proc("TerminalUndo", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::undo); }); + chords.proc("TerminalRedo", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::redo); }); + chords.proc("TerminalClipboardPaste", [&](hids& gear){ gear.set_handled(); paste(gear); }); + chords.proc("TerminalClipboardWipe", [&](hids& gear){ gear.set_handled(); gear.clear_clipboard(); }); + chords.proc("TerminalSwitchCopyMode", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::togglesel); }); + chords.proc("TerminalSelectionCopy", [&](hids& gear){ gear.set_handled(); copy(gear); }); + chords.proc("TerminalToggleSelectionMode", [&](hids& gear){ gear.set_handled(); exec_cmd(commands::ui::toggleselalt); }); + chords.proc("TerminalSelectionOneShot", [&](hids& gear){ gear.set_handled(); set_oneshot(mime::textonly); }); + chords.proc("TerminalViewportCopy", [&](hids& gear){ gear.set_handled(); prnscrn(gear); }); + chords.proc("TerminalToggleStdioLog", [&](hids& gear){ gear.set_handled(); set_log(!io_log); ondata(); }); chords.load(xml_config, "/config/hotkeys/term/key"); LISTEN(tier::general, e2::timer::tick, timestamp) // Update before world rendering. @@ -8038,14 +8038,19 @@ namespace netxs::ui if (auto gear_ptr = owner.bell::getref(k.gear_id)) if (auto parent_ptr = owner.base::parent()) { - if (k.solo < 0) // Exclusive keyboard mode: -1: set, -2: reset. - { - gear_ptr->set_exclusive(k.solo == -1 ? owner.This() : sptr{}); // Exclusive mode will be reset automatically when focus is changed. - } - else - { - auto seed = parent_ptr->base::riseup(tier::preview, hids::events::keybd::focus::set, { .id = k.gear_id, .solo = k.solo, .item = owner.This() }); - } + auto seed = parent_ptr->base::riseup(tier::preview, hids::events::keybd::focus::set, { .id = k.gear_id, .solo = k.solo, .item = owner.This() }); + } + } + } + void handle(s11n::xs::hotkey_mode lock) + { + auto& k = lock.thing; + if (owner.active) + { + auto guard = owner.sync(); + if (auto gear_ptr = owner.bell::getref(k.gear_id)) + { + gear_ptr->set_hotkey_mode(k.mode); } } } @@ -8060,7 +8065,7 @@ namespace netxs::ui { auto& gear = *gear_ptr; //todo should we use temp gear object here? - gear.alive = true; + gear.alive = true; k.syncto(gear); do { @@ -8226,6 +8231,7 @@ namespace netxs::ui owner.base::riseup(tier::preview, e2::form::prop::cwd, path); }); } + evnt(dtvt& owner) : s11n{ *this, owner.id }, input_fields_handler{ owner }, diff --git a/src/vtm.xml b/src/vtm.xml index 575f833764..68e1499914 100644 --- a/src/vtm.xml +++ b/src/vtm.xml @@ -377,7 +377,7 @@ R"==( - + @@ -391,9 +391,13 @@ R"==( - + - + + + + + @@ -407,6 +411,8 @@ R"==( + + @@ -434,8 +440,6 @@ R"==( - - )==" \ No newline at end of file From c1d9ac1239b7ce668b80d25fa8919cd1de2cd3c1 Mon Sep 17 00:00:00 2001 From: Dmitry Sapozhnikov <11535558+o-sdn-o@users.noreply.github.com> Date: Mon, 11 Nov 2024 14:14:43 +0500 Subject: [PATCH 4/6] v0.9.99.44 --- src/netxs/desktopio/application.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/netxs/desktopio/application.hpp b/src/netxs/desktopio/application.hpp index b78a4764e8..ea77d5def2 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.43"; + static const auto version = "v0.9.99.44"; 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; From b6e587ce3f7f72ad962caa624ddad0428c959ee8 Mon Sep 17 00:00:00 2001 From: Dmitry Sapozhnikov <11535558+o-sdn-o@users.noreply.github.com> Date: Mon, 11 Nov 2024 14:27:48 +0500 Subject: [PATCH 5/6] Fix gcc complaints --- src/netxs/desktopio/gui.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/netxs/desktopio/gui.hpp b/src/netxs/desktopio/gui.hpp index 4a6c4044ac..3a98aa98c6 100644 --- a/src/netxs/desktopio/gui.hpp +++ b/src/netxs/desktopio/gui.hpp @@ -2856,7 +2856,7 @@ namespace netxs::gui } void keybd_send_state(si32 virtcod = {}, si32 keystat = {}, si32 scancod = {}, bool extflag = {}, view cluster = {}, bool synth = faux) { - if (auto hotkey_mode_changed = virtcod == 0 && (keymod ^ hotkey) & input::hids::HotkeyMode) // Send empty key to update hotkey mode state. + if (virtcod == 0 && (keymod ^ hotkey) & input::hids::HotkeyMode) // Send empty key to update hotkey mode state if it is changed. { auto& gear = *stream.gears; netxs::set_flag(keymod, hotkey); From ad85902458f9b4e3a4ffd0facb7b1f22afc979af Mon Sep 17 00:00:00 2001 From: Dmitry Sapozhnikov <11535558+o-sdn-o@users.noreply.github.com> Date: Mon, 11 Nov 2024 14:30:18 +0500 Subject: [PATCH 6/6] Minor edits --- src/vtm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vtm.xml b/src/vtm.xml index 68e1499914..04688c5e75 100644 --- a/src/vtm.xml +++ b/src/vtm.xml @@ -376,7 +376,7 @@ R"==( - +