SPE-2564: FIx of shortcuts on Mac, including cmd+m and cmd+q

This commit is contained in:
David Kocik 2024-12-09 13:10:42 +01:00 committed by Lukas Matena
parent 189d728b3f
commit 1848bb9396
3 changed files with 151 additions and 77 deletions

View File

@ -56,7 +56,7 @@ void ConnectRequestHandler::handle_message(const std::string& message)
}
if (action_string.empty()) {
BOOST_LOG_TRIVIAL(error) << "Recieved invalid message from _prusaConnect (missing action). Message: " << message;
BOOST_LOG_TRIVIAL(error) << "Received invalid message from _prusaConnect (missing action). Message: " << message;
return;
}
assert(m_actions.find(action_string) != m_actions.end()); // this assert means there is a action that has no handling.

View File

@ -592,69 +592,20 @@ void WebViewPanel::sys_color_changed()
#endif
}
void WebViewPanel::on_app_quit_event(const std::string& message_data)
{
// MacOS only suplement for cmd+Q
wxGetApp().Exit();
}
void WebViewPanel::on_app_minimize_event(const std::string& message_data)
{
// MacOS only suplement for cmd+M
wxGetApp().mainframe->Iconize(true);
}
void WebViewPanel::define_css()
{
if (m_styles_defined) {
return;
}
m_styles_defined = true;
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__;
std::string script = R"(
// loading overlay
var style = document.createElement('style');
style.innerHTML = `
body {}
.slic3r-loading-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(127 127 127 / 50%);
z-index: 50;
display: flex;
align-items: center;
justify-content: center;
}
.slic3r-loading-anim {
width: 60px;
aspect-ratio: 4;
--_g: no-repeat radial-gradient(circle closest-side,#000 90%,#0000);
background:
var(--_g) 0% 50%,
var(--_g) 50% 50%,
var(--_g) 100% 50%;
background-size: calc(100%/3) 100%;
animation: slic3r-loading-anim 1s infinite linear;
}
@keyframes slic3r-loading-anim {
33%{background-size:calc(100%/3) 0% ,calc(100%/3) 100%,calc(100%/3) 100%}
50%{background-size:calc(100%/3) 100%,calc(100%/3) 0% ,calc(100%/3) 100%}
66%{background-size:calc(100%/3) 100%,calc(100%/3) 100%,calc(100%/3) 0% }
}
document.head.appendChild(style);
)";
//#ifdef __APPLE__
#if defined(__APPLE__)
// WebView on Windows does read keyboard shortcuts
// Thus doing f.e. Reload twice would make the oparation to fail
script += R"(
(function() {
const listenerKey = 'custom-click-listener';
if (!document[listenerKey]) {
document.addEventListener('keydown', function (event) {
if (event.key === 'F5' || (event.ctrlKey && event.key === 'r') || (event.metaKey && event.key === 'r')) {
window.ExternalApp.postMessage(JSON.stringify({ event: 'reloadHomePage', fromKeyboard: 1}));
}
});
document[listenerKey] = true;
}
})();
)";
#endif // __APPLE__
run_script(script);
assert(false);
}
ConnectWebViewPanel::ConnectWebViewPanel(wxWindow* parent)
@ -663,6 +614,11 @@ ConnectWebViewPanel::ConnectWebViewPanel(wxWindow* parent)
auto* plater = wxGetApp().plater();
plater->Bind(EVT_UA_LOGGEDOUT, &ConnectWebViewPanel::on_user_logged_out, this);
plater->Bind(EVT_UA_ID_USER_SUCCESS, &ConnectWebViewPanel::on_user_token, this);
m_actions["appQuit"] = std::bind(&WebViewPanel::on_app_quit_event, this, std::placeholders::_1);
m_actions["appMinimize"] = std::bind(&WebViewPanel::on_app_minimize_event, this, std::placeholders::_1);
m_actions["reloadHomePage"] = std::bind(&ConnectWebViewPanel::on_reload_event, this, std::placeholders::_1);
}
void ConnectWebViewPanel::late_create()
@ -976,9 +932,41 @@ void ConnectWebViewPanel::on_connect_action_print(const std::string& message_dat
assert(false);
}
void ConnectWebViewPanel::define_css()
{
if (m_styles_defined) {
return;
}
m_styles_defined = true;
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__;
#if defined(__APPLE__)
// WebView on Windows does read keyboard shortcuts
// Thus doing f.e. Reload twice would make the oparation to fail
std::string script = R"(
document.addEventListener('keydown', function (event) {
if (event.key === 'F5' || (event.ctrlKey && event.key === 'r') || (event.metaKey && event.key === 'r')) {
window.webkit.messageHandlers._prusaSlicer.postMessage(JSON.stringify({ action: 'reloadHomePage', fromKeyboard: 1}));
}
if (event.metaKey && event.key === 'q') {
window.webkit.messageHandlers._prusaSlicer.postMessage(JSON.stringify({ action: 'appQuit'}));
}
if (event.metaKey && event.key === 'm') {
window.webkit.messageHandlers._prusaSlicer.postMessage(JSON.stringify({ action: 'appMinimize'}));
}
});
)";
run_script(script);
#endif // defined(__APPLE__)
}
PrinterWebViewPanel::PrinterWebViewPanel(wxWindow* parent, const wxString& default_url)
: WebViewPanel(parent, default_url, {"ExternalApp"}, "other_loading", "other_error", false)
{
m_events["reloadHomePage"] = std::bind(&PrinterWebViewPanel::on_reload_event, this, std::placeholders::_1);
m_events["appQuit"] = std::bind(&WebViewPanel::on_app_quit_event, this, std::placeholders::_1);
m_events["appMinimize"] = std::bind(&WebViewPanel::on_app_minimize_event, this, std::placeholders::_1);
}
void PrinterWebViewPanel::on_navigation_request(wxWebViewEvent &evt)
@ -1025,8 +1013,35 @@ void PrinterWebViewPanel::on_loaded(wxWebViewEvent& evt)
}
void PrinterWebViewPanel::on_script_message(wxWebViewEvent& evt)
{
// Only reload messages are being sent now.
load_default_url();
BOOST_LOG_TRIVIAL(debug) << "received message from Physical printer page: " << evt.GetString();
handle_message(into_u8(evt.GetString()));
}
void PrinterWebViewPanel::handle_message(const std::string& message)
{
std::string event_string;
try {
std::stringstream ss(message);
pt::ptree ptree;
pt::read_json(ss, ptree);
if (const auto action = ptree.get_optional<std::string>("event"); action) {
event_string = *action;
}
}
catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Could not parse printables message. " << e.what();
return;
}
if (event_string.empty()) {
BOOST_LOG_TRIVIAL(error) << "Received invalid message from printables (missing event). Message: " << message;
return;
}
assert(m_events.find(event_string) != m_events.end()); // this assert means there is an event that has no handling.
if (m_events.find(event_string) != m_events.end()) {
m_events[event_string](message);
}
}
void PrinterWebViewPanel::send_api_key()
@ -1070,19 +1085,67 @@ void PrinterWebViewPanel::send_credentials()
setup_webview_with_credentials(m_browser, m_usr, m_psk);
}
void PrinterWebViewPanel::define_css()
{
if (m_styles_defined) {
return;
}
m_styles_defined = true;
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__;
#if defined(__APPLE__)
// WebView on Windows does read keyboard shortcuts
// Thus doing f.e. Reload twice would make the oparation to fail
std::string script = R"(
document.addEventListener('keydown', function (event) {
if (event.key === 'F5' || (event.ctrlKey && event.key === 'r') || (event.metaKey && event.key === 'r')) {
window.webkit.messageHandlers.ExternalApp.postMessage(JSON.stringify({ event: 'reloadHomePage', fromKeyboard: 1}));
}
if (event.metaKey && event.key === 'q') {
window.webkit.messageHandlers.ExternalApp.postMessage(JSON.stringify({ event: 'appQuit'}));
}
if (event.metaKey && event.key === 'm') {
window.webkit.messageHandlers.ExternalApp.postMessage(JSON.stringify({ event: 'appMinimize'}));
}
});
)";
run_script(script);
#endif // defined(__APPLE__)
}
void PrinterWebViewPanel::on_reload_event(const std::string& message_data)
{
// Event from our error page button or keyboard shortcut
m_styles_defined = false;
try {
std::stringstream ss(message_data);
pt::ptree ptree;
pt::read_json(ss, ptree);
if (const auto keyboard = ptree.get_optional<bool>("fromKeyboard"); keyboard && *keyboard) {
do_reload();
} else {
// On error page do load of default url.
load_default_url();
}
} catch (const std::exception &e) {
BOOST_LOG_TRIVIAL(error) << "Could not parse message. " << e.what();
return;
}
}
PrintablesWebViewPanel::PrintablesWebViewPanel(wxWindow* parent)
: WebViewPanel(parent, GUI::from_u8(Utils::ServiceConfig::instance().printables_url()), { "ExternalApp" }, "other_loading", "other_error", false)
{
m_events["accessTokenExpired"] = std::bind(&PrintablesWebViewPanel::on_printables_event_access_token_expired, this, std::placeholders::_1);
m_events["reloadHomePage"] = std::bind(&PrintablesWebViewPanel::on_reload_event, this, std::placeholders::_1);
m_events["printGcode"] = std::bind(&PrintablesWebViewPanel::on_printables_event_print_gcode, this, std::placeholders::_1);
m_events["downloadFile"] = std::bind(&PrintablesWebViewPanel::on_printables_event_download_file, this, std::placeholders::_1);
m_events["sliceFile"] = std::bind(&PrintablesWebViewPanel::on_printables_event_slice_file, this, std::placeholders::_1);
m_events["requiredLogin"] = std::bind(&PrintablesWebViewPanel::on_printables_event_required_login, this, std::placeholders::_1);
m_events["openExternalUrl"] = std::bind(&PrintablesWebViewPanel::on_printables_event_open_url, this, std::placeholders::_1);
m_events["reloadHomePage"] = std::bind(&PrintablesWebViewPanel::on_reload_event, this, std::placeholders::_1);
m_events["appQuit"] = std::bind(&WebViewPanel::on_app_quit_event, this, std::placeholders::_1);
m_events["appMinimize"] = std::bind(&WebViewPanel::on_app_minimize_event, this, std::placeholders::_1);
}
void PrintablesWebViewPanel::handle_message(const std::string& message)
@ -1613,17 +1676,17 @@ void PrintablesWebViewPanel::define_css()
// WebView on Windows does read keyboard shortcuts
// Thus doing f.e. Reload twice would make the oparation to fail
script += R"(
(function() {
const listenerKey = 'custom-click-listener';
if (!document[listenerKey]) {
document.addEventListener('keydown', function (event) {
if (event.key === 'F5' || (event.ctrlKey && event.key === 'r') || (event.metaKey && event.key === 'r')) {
window.ExternalApp.postMessage(JSON.stringify({ event: 'reloadHomePage', fromKeyboard: 1}));
}
});
document[listenerKey] = true;
document.addEventListener('keydown', function (event) {
if (event.key === 'F5' || (event.ctrlKey && event.key === 'r') || (event.metaKey && event.key === 'r')) {
window.ExternalApp.postMessage(JSON.stringify({ event: 'reloadHomePage', fromKeyboard: 1}));
}
})();
if (event.metaKey && event.key === 'q') {
window.ExternalApp.postMessage(JSON.stringify({ event: 'appQuit'}));
}
if (event.metaKey && event.key === 'm') {
window.ExternalApp.postMessage(JSON.stringify({ event: 'appMinimize'}));
}
});
)";
#endif // defined(__APPLE__)
run_script(script);

View File

@ -74,11 +74,14 @@ public:
void set_load_default_url_on_next_error(bool val) { m_load_default_url_on_next_error = val; }
void on_app_quit_event(const std::string& message_data);
void on_app_minimize_event(const std::string& message_data);
protected:
virtual void late_create();
virtual void define_css();
virtual void on_page_will_load();
wxWebView* m_browser { nullptr };
bool m_load_default_url { false };
@ -144,6 +147,7 @@ protected:
void on_reload_event(const std::string& message_data) override;
void on_connect_action_close_dialog(const std::string& message_data) override {assert(false);}
void on_user_token(UserAccountSuccessEvent& e);
void define_css() override;
private:
static wxString get_login_script(bool refresh);
static wxString get_logout_script();
@ -172,11 +176,18 @@ public:
m_psk = psk;
}
void clear() { m_api_key.clear(); m_usr.clear(); m_psk.clear(); m_api_key_sent = false; }
void on_reload_event(const std::string& message_data);
protected:
void define_css() override;
private:
std::string m_api_key;
std::string m_usr;
std::string m_psk;
bool m_api_key_sent {false};
void handle_message(const std::string& message);
std::map<std::string, std::function<void(const std::string&)>> m_events;
};
class PrintablesWebViewPanel : public WebViewPanel