mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 10:46:25 +00:00
sculpt: refine keyboard entry of new depot URL
This patch includes the system dialog in the global keyboard focus handling, supports hovering of the "Edit" and "Add" buttons, allows the use of the enter key to finish URL editing, and triggers a re-scan of depot users after adding a new one. Issue #4820
This commit is contained in:
parent
937ddd012b
commit
43d51c4499
@ -22,18 +22,21 @@
|
|||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <view/network_dialog.h>
|
#include <view/network_dialog.h>
|
||||||
#include <view/panel_dialog.h>
|
#include <view/panel_dialog.h>
|
||||||
|
#include <view/system_dialog.h>
|
||||||
|
|
||||||
namespace Sculpt { struct Keyboard_focus; }
|
namespace Sculpt { struct Keyboard_focus; }
|
||||||
|
|
||||||
struct Sculpt::Keyboard_focus
|
struct Sculpt::Keyboard_focus
|
||||||
{
|
{
|
||||||
enum Target { INITIAL, WPA_PASSPHRASE, WM } target { INITIAL };
|
enum Target { INITIAL, WPA_PASSPHRASE, SYSTEM_DIALOG, WM } target { INITIAL };
|
||||||
|
|
||||||
Expanding_reporter _focus_reporter;
|
Expanding_reporter _focus_reporter;
|
||||||
|
|
||||||
Network_dialog const &_network_dialog;
|
Network_dialog const &_network_dialog;
|
||||||
Wpa_passphrase &_wpa_passphrase;
|
Wpa_passphrase &_wpa_passphrase;
|
||||||
Panel_dialog::State const &_panel;
|
Panel_dialog::State const &_panel;
|
||||||
|
System_dialog const &_system_dialog;
|
||||||
|
bool const &_system_visible;
|
||||||
|
|
||||||
void update()
|
void update()
|
||||||
{
|
{
|
||||||
@ -44,6 +47,9 @@ struct Sculpt::Keyboard_focus
|
|||||||
if (_panel.network_visible() && _network_dialog.need_keyboard_focus_for_passphrase())
|
if (_panel.network_visible() && _network_dialog.need_keyboard_focus_for_passphrase())
|
||||||
target = WPA_PASSPHRASE;
|
target = WPA_PASSPHRASE;
|
||||||
|
|
||||||
|
if (_system_dialog.keyboard_needed() && _system_visible)
|
||||||
|
target = SYSTEM_DIALOG;
|
||||||
|
|
||||||
if (orig_target == target)
|
if (orig_target == target)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -54,6 +60,7 @@ struct Sculpt::Keyboard_focus
|
|||||||
switch (target) {
|
switch (target) {
|
||||||
|
|
||||||
case WPA_PASSPHRASE:
|
case WPA_PASSPHRASE:
|
||||||
|
case SYSTEM_DIALOG:
|
||||||
xml.attribute("label", "manager -> input");
|
xml.attribute("label", "manager -> input");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -68,12 +75,16 @@ struct Sculpt::Keyboard_focus
|
|||||||
Keyboard_focus(Env &env,
|
Keyboard_focus(Env &env,
|
||||||
Network_dialog const &network_dialog,
|
Network_dialog const &network_dialog,
|
||||||
Wpa_passphrase &wpa_passphrase,
|
Wpa_passphrase &wpa_passphrase,
|
||||||
Panel_dialog::State const &panel)
|
Panel_dialog::State const &panel,
|
||||||
|
System_dialog const &system_dialog,
|
||||||
|
bool const &system_visible)
|
||||||
:
|
:
|
||||||
_focus_reporter(env, "focus", "focus"),
|
_focus_reporter(env, "focus", "focus"),
|
||||||
_network_dialog(network_dialog),
|
_network_dialog(network_dialog),
|
||||||
_wpa_passphrase(wpa_passphrase),
|
_wpa_passphrase(wpa_passphrase),
|
||||||
_panel(panel)
|
_panel(panel),
|
||||||
|
_system_dialog(system_dialog),
|
||||||
|
_system_visible(system_visible)
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
@ -672,7 +672,8 @@ struct Sculpt::Main : Input_event_handler,
|
|||||||
_try_handle_click();
|
_try_handle_click();
|
||||||
}
|
}
|
||||||
|
|
||||||
Keyboard_focus _keyboard_focus { _env, _network.dialog, _network.wpa_passphrase, *this };
|
Keyboard_focus _keyboard_focus { _env, _network.dialog, _network.wpa_passphrase,
|
||||||
|
*this, _system_dialog, _system_visible };
|
||||||
|
|
||||||
Constructible<Input::Seq_number> _clicked_seq_number { };
|
Constructible<Input::Seq_number> _clicked_seq_number { };
|
||||||
Constructible<Input::Seq_number> _clacked_seq_number { };
|
Constructible<Input::Seq_number> _clacked_seq_number { };
|
||||||
@ -784,11 +785,34 @@ struct Sculpt::Main : Input_event_handler,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _keyboard_input_consumed_by_sculpt_manager() const
|
||||||
|
{
|
||||||
|
return (_keyboard_focus.target == Keyboard_focus::WPA_PASSPHRASE)
|
||||||
|
|| (_system_visible && _system_dialog.keyboard_needed());
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Keyboard_focus_guard
|
||||||
|
{
|
||||||
|
Main &_main;
|
||||||
|
|
||||||
|
bool const _orig = _main._keyboard_input_consumed_by_sculpt_manager();
|
||||||
|
|
||||||
|
Keyboard_focus_guard(Main &main) : _main(main) { }
|
||||||
|
|
||||||
|
~Keyboard_focus_guard()
|
||||||
|
{
|
||||||
|
if (_orig != _main._keyboard_input_consumed_by_sculpt_manager())
|
||||||
|
_main._keyboard_focus.update();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Menu_view::Hover_update_handler interface
|
* Menu_view::Hover_update_handler interface
|
||||||
*/
|
*/
|
||||||
void menu_view_hover_updated() override
|
void menu_view_hover_updated() override
|
||||||
{
|
{
|
||||||
|
Keyboard_focus_guard focus_guard { *this };
|
||||||
|
|
||||||
if (_clicked_seq_number.constructed())
|
if (_clicked_seq_number.constructed())
|
||||||
_try_handle_click();
|
_try_handle_click();
|
||||||
|
|
||||||
@ -803,6 +827,8 @@ struct Sculpt::Main : Input_event_handler,
|
|||||||
{
|
{
|
||||||
bool need_generate_dialog = false;
|
bool need_generate_dialog = false;
|
||||||
|
|
||||||
|
Keyboard_focus_guard focus_guard { *this };
|
||||||
|
|
||||||
if (ev.key_press(Input::BTN_LEFT) || ev.touch()) {
|
if (ev.key_press(Input::BTN_LEFT) || ev.touch()) {
|
||||||
_clicked_seq_number.construct(_global_input_seq_number);
|
_clicked_seq_number.construct(_global_input_seq_number);
|
||||||
_try_handle_click();
|
_try_handle_click();
|
||||||
@ -822,9 +848,6 @@ struct Sculpt::Main : Input_event_handler,
|
|||||||
need_generate_dialog = true;
|
need_generate_dialog = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ev.press())
|
|
||||||
_keyboard_focus.update();
|
|
||||||
|
|
||||||
if (need_generate_dialog)
|
if (need_generate_dialog)
|
||||||
generate_dialog();
|
generate_dialog();
|
||||||
}
|
}
|
||||||
@ -1710,6 +1733,7 @@ void Sculpt::Main::_handle_window_layout()
|
|||||||
|
|
||||||
/* define window-manager focus */
|
/* define window-manager focus */
|
||||||
_wm_focus.generate([&] (Xml_generator &xml) {
|
_wm_focus.generate([&] (Xml_generator &xml) {
|
||||||
|
|
||||||
_window_list.xml().for_each_sub_node("window", [&] (Xml_node win) {
|
_window_list.xml().for_each_sub_node("window", [&] (Xml_node win) {
|
||||||
Label const label = win.attribute_value("label", Label());
|
Label const label = win.attribute_value("label", Label());
|
||||||
|
|
||||||
@ -1988,6 +2012,10 @@ void Sculpt::Main::_handle_runtime_state()
|
|||||||
if (_index_update_queue.download_count != orig_download_count)
|
if (_index_update_queue.download_count != orig_download_count)
|
||||||
_deploy.update_installation();
|
_deploy.update_installation();
|
||||||
|
|
||||||
|
/* update depot-user selection after adding new depot URL */
|
||||||
|
if (_system_visible)
|
||||||
|
trigger_depot_query();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The removal of an index file may have completed, re-query index
|
* The removal of an index file may have completed, re-query index
|
||||||
* files to reflect this change at the depot selection menu.
|
* files to reflect this change at the depot selection menu.
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#ifndef _MODEL__DOWNLOAD_QUEUE_H_
|
#ifndef _MODEL__DOWNLOAD_QUEUE_H_
|
||||||
#define _MODEL__DOWNLOAD_QUEUE_H_
|
#define _MODEL__DOWNLOAD_QUEUE_H_
|
||||||
|
|
||||||
|
#include <depot/archive.h>
|
||||||
#include <base/registry.h>
|
#include <base/registry.h>
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#define _MODEL__INDEX_UPDATE_QUEUE_H_
|
#define _MODEL__INDEX_UPDATE_QUEUE_H_
|
||||||
|
|
||||||
#include <model/download_queue.h>
|
#include <model/download_queue.h>
|
||||||
|
#include <model/file_operation_queue.h>
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
namespace Sculpt { struct Index_update_queue; }
|
namespace Sculpt { struct Index_update_queue; }
|
||||||
|
@ -49,6 +49,8 @@ struct Sculpt::Depot_users_dialog
|
|||||||
|
|
||||||
bool _unfolded = false;
|
bool _unfolded = false;
|
||||||
|
|
||||||
|
bool _selected_user_exists = false;
|
||||||
|
|
||||||
Hoverable_item _user { };
|
Hoverable_item _user { };
|
||||||
Hoverable_item _button { };
|
Hoverable_item _button { };
|
||||||
|
|
||||||
@ -124,8 +126,9 @@ struct Sculpt::Depot_users_dialog
|
|||||||
bool const selected = (name == _selected);
|
bool const selected = (name == _selected);
|
||||||
Url const url = _url(user);
|
Url const url = _url(user);
|
||||||
Url const label = Depot_url::from_string(url).valid() ? url : Url(name);
|
Url const label = Depot_url::from_string(url).valid() ? url : Url(name);
|
||||||
|
bool const show_all = _unfolded || !_selected_user_exists;
|
||||||
|
|
||||||
if (!selected && !_unfolded)
|
if (!selected && !show_all)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_gen_item(xml, name,
|
_gen_item(xml, name,
|
||||||
@ -133,7 +136,7 @@ struct Sculpt::Depot_users_dialog
|
|||||||
[&] /* right */ { }
|
[&] /* right */ { }
|
||||||
);
|
);
|
||||||
|
|
||||||
if (_unfolded && !last)
|
if (show_all && !last)
|
||||||
_gen_vspacer(xml, String<64>("below ", name).string());
|
_gen_vspacer(xml, String<64>("below ", name).string());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +176,9 @@ struct Sculpt::Depot_users_dialog
|
|||||||
gen_named_node(xml, "button", "add", [&] {
|
gen_named_node(xml, "button", "add", [&] {
|
||||||
if (!url_valid)
|
if (!url_valid)
|
||||||
xml.attribute("style", "unimportant");
|
xml.attribute("style", "unimportant");
|
||||||
|
else
|
||||||
|
_button.gen_hovered_attr(xml, "add");
|
||||||
|
|
||||||
xml.node("label", [&] {
|
xml.node("label", [&] {
|
||||||
if (!url_valid)
|
if (!url_valid)
|
||||||
xml.attribute("style", "unimportant");
|
xml.attribute("style", "unimportant");
|
||||||
@ -180,6 +186,7 @@ struct Sculpt::Depot_users_dialog
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
gen_named_node(xml, "button", "edit", [&] {
|
gen_named_node(xml, "button", "edit", [&] {
|
||||||
|
_button.gen_hovered_attr(xml, "edit");
|
||||||
xml.node("label", [&] {
|
xml.node("label", [&] {
|
||||||
xml.attribute("text", "Edit"); }); });
|
xml.attribute("text", "Edit"); }); });
|
||||||
}
|
}
|
||||||
@ -208,12 +215,12 @@ struct Sculpt::Depot_users_dialog
|
|||||||
bool const last = (--remain_count == 0);
|
bool const last = (--remain_count == 0);
|
||||||
_gen_entry(xml, user, last); });
|
_gen_entry(xml, user, last); });
|
||||||
|
|
||||||
if (_unfolded)
|
if (_unfolded || !_selected_user_exists)
|
||||||
_gen_add_entry(xml, depot_users);
|
_gen_add_entry(xml, depot_users);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!_unfolded && !known_pubkey) {
|
if (!_unfolded && !known_pubkey && _selected_user_exists) {
|
||||||
gen_named_node(xml, "button", "pubkey warning", [&] {
|
gen_named_node(xml, "button", "pubkey warning", [&] {
|
||||||
xml.attribute("style", "invisible");
|
xml.attribute("style", "invisible");
|
||||||
xml.node("label", [&] {
|
xml.node("label", [&] {
|
||||||
@ -240,7 +247,7 @@ struct Sculpt::Depot_users_dialog
|
|||||||
|
|
||||||
void generate(Xml_generator &xml) const { _gen_selection(xml); }
|
void generate(Xml_generator &xml) const { _gen_selection(xml); }
|
||||||
|
|
||||||
bool unfolded() const { return _unfolded; }
|
bool unfolded() const { return _unfolded || !_selected_user_exists; }
|
||||||
|
|
||||||
struct User_properties
|
struct User_properties
|
||||||
{
|
{
|
||||||
@ -280,6 +287,7 @@ struct Sculpt::Depot_users_dialog
|
|||||||
_selected = user;
|
_selected = user;
|
||||||
select_fn(user);
|
select_fn(user);
|
||||||
_unfolded = false;
|
_unfolded = false;
|
||||||
|
_selected_user_exists = true;
|
||||||
_url_edit_field = _orig_edit_url;
|
_url_edit_field = _orig_edit_url;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -324,6 +332,19 @@ struct Sculpt::Depot_users_dialog
|
|||||||
if (c.value == ' ' || c.value == '"')
|
if (c.value == ' ' || c.value == '"')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* respond to enter key */
|
||||||
|
if (c.value == 10) {
|
||||||
|
Depot_url const depot_url = _depot_url(_depot_users.xml());
|
||||||
|
if (depot_url.valid()) {
|
||||||
|
_action.add_depot_url(depot_url);
|
||||||
|
_selected = depot_url.user;
|
||||||
|
_selected_user_exists = true;
|
||||||
|
_unfolded = false;
|
||||||
|
_url_edit_field = _orig_edit_url;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_url_edit_field.apply(c);
|
_url_edit_field.apply(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,16 +356,11 @@ struct Sculpt::Depot_users_dialog
|
|||||||
* If the selected depot user does not exist in the depot, show
|
* If the selected depot user does not exist in the depot, show
|
||||||
* list of available users.
|
* list of available users.
|
||||||
*/
|
*/
|
||||||
bool selected_user_exists = false;
|
_selected_user_exists = false;
|
||||||
|
|
||||||
_depot_users.xml().for_each_sub_node([&] (Xml_node const &user) {
|
_depot_users.xml().for_each_sub_node([&] (Xml_node const &user) {
|
||||||
if (_selected == user.attribute_value("name", User()))
|
if (_selected == user.attribute_value("name", User()))
|
||||||
selected_user_exists = true; });
|
_selected_user_exists = true; });
|
||||||
|
|
||||||
if (!selected_user_exists) {
|
|
||||||
_selected = _default_user;
|
|
||||||
_unfolded = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user