aboutsummaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/guiChatConsole.cpp148
-rw-r--r--src/gui/guiChatConsole.h11
2 files changed, 158 insertions, 1 deletions
diff --git a/src/gui/guiChatConsole.cpp b/src/gui/guiChatConsole.cpp
index a4e91fe78..fd92cf298 100644
--- a/src/gui/guiChatConsole.cpp
+++ b/src/gui/guiChatConsole.cpp
@@ -90,6 +90,19 @@ GUIChatConsole::GUIChatConsole(
// set default cursor options
setCursor(true, true, 2.0, 0.1);
+
+ m_cache_clickable_chat_weblinks = g_settings->getBool("clickable_chat_weblinks");
+ if(m_cache_clickable_chat_weblinks)
+ {
+ std::string ctrlkeystoparse = g_settings->get("chat_weblink_ctrl_keys");
+ if(setupChatClickCtrlKeys(ctrlkeystoparse) == 0)
+ {
+ // if fail then try again w hardcoded string
+ g_logger.log(LL_WARNING, "Failed to parse chat_weblink_ctrl_keys. Using hardcoded default.");
+ ctrlkeystoparse = "KEY_CONTROL,KEY_LCONTROL,KEY_RCONTROL";
+ setupChatClickCtrlKeys(ctrlkeystoparse);
+ }
+ }
}
GUIChatConsole::~GUIChatConsole()
@@ -404,9 +417,24 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
{
ChatPrompt &prompt = m_chat_backend->getPrompt();
+ static bool isctrldown; // track this for mouse event
- if(event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown)
+ if(event.EventType == EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
{
+ // CTRL up
+ if(isInCtrlKeys(event.KeyInput.Key))
+ {
+ isctrldown = false;
+ }
+ }
+ else if(event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown)
+ {
+ // CTRL down
+ if(isInCtrlKeys(event.KeyInput.Key))
+ {
+ isctrldown = true;
+ }
+
// Key input
if (KeyPress(event.KeyInput) == getKeySetting("keymap_console")) {
closeConsole();
@@ -618,6 +646,18 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
s32 rows = myround(-3.0 * event.MouseInput.Wheel);
m_chat_backend->scroll(rows);
}
+ // Middle click opens weblink, if enabled in config
+ else if(m_cache_clickable_chat_weblinks && (
+ event.MouseInput.Event == EMIE_MMOUSE_PRESSED_DOWN ||
+ (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN && isctrldown)
+ ))
+ {
+ // because console prompt and hardcoded margins
+ if(event.MouseInput.Y / m_fontsize.Y < (m_height / m_fontsize.Y) - 1 )
+ {
+ middleClick(event.MouseInput.X / m_fontsize.X, event.MouseInput.Y / m_fontsize.Y);
+ }
+ }
}
return Parent ? Parent->OnEvent(event) : false;
@@ -633,3 +673,109 @@ void GUIChatConsole::setVisible(bool visible)
}
}
+// Return how many "ctrl" keycodes successfully found in string, or 0 on fail
+int GUIChatConsole::setupChatClickCtrlKeys(std::string inputline)
+{
+ m_cache_chat_weblink_ctrl_keys.clear();
+
+ irr::EKEY_CODE kc;
+ std::string stemp;
+ size_t startpos = 0, endpos = 0;
+ while(startpos < inputline.size())
+ {
+ // Foreach delimited string,
+ endpos = inputline.find(',', startpos);
+ endpos = std::min(endpos, inputline.find(' ', startpos));
+ // Ignore space/comma
+ if(endpos == startpos)
+ {
+ ++endpos;
+ }
+ // Ignore consecutive space/comma
+ else if(endpos - startpos > 1)
+ {
+ // If valid keycode, add it to cached list
+ stemp = inputline.substr(startpos, endpos - startpos);
+ kc = keyname_to_keycode_safemode(stemp.c_str());
+ if(kc != irr::KEY_KEY_CODES_COUNT)
+ {
+ m_cache_chat_weblink_ctrl_keys.push_back(kc);
+ }
+ else
+ {
+ stemp = "Ignoring unknown keycode '" + stemp + "' for chat_weblink_ctrl_keys, check your conf";
+ g_logger.log(LL_WARNING, stemp);
+ }
+ }
+ startpos = endpos;
+ }
+
+ return m_cache_chat_weblink_ctrl_keys.size();
+}
+
+bool GUIChatConsole::isInCtrlKeys(const irr::EKEY_CODE& kc)
+{
+ // To avoid including <algorithm>
+ for(size_t i=0; i<m_cache_chat_weblink_ctrl_keys.size(); ++i)
+ {
+ if(m_cache_chat_weblink_ctrl_keys.at(i) == kc)
+ return true;
+ }
+ return false;
+}
+
+void GUIChatConsole::middleClick(s32 col, s32 row)
+{
+ // Prevent accidental rapid clicking
+ static u32 oldtime = 0;
+ // seriously..
+ u32 newtime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
+
+ // 0.6 seconds should suffice
+ if(newtime - oldtime < 600)
+ return;
+ oldtime = newtime;
+
+ const std::vector<ChatFormattedFragment> & frags = m_chat_backend->getConsoleBuffer().getFormattedLine(row).fragments;
+ std::string weblink = ""; // from frag meta
+
+ // Identify targetted fragment, if exists
+ int ind = frags.size() - 1;
+ while(u32(col - 1) < frags[ind].column)
+ {
+ --ind;
+ }
+ if(ind > -1)
+ {
+ weblink = frags[ind].meta;
+ }
+
+ // Debug help
+ std::string ws;
+ ws = "Middleclick: (" + std::to_string(col) + ',' + std::to_string(row) + ')' + " frags:";
+ for(u32 i=0;i<frags.size();++i)
+ {
+ if(ind == int(i))
+ ws += '*';
+ ws += std::to_string(frags.at(i).column) + '('
+ + std::to_string(frags.at(i).text.size()) + "),";
+ }
+ g_logger.log(LL_VERBOSE, ws);
+
+ // User notification
+ std::string mesg;
+ if(weblink.size() != 0)
+ {
+ mesg = " * ";
+ if(porting::open_url(weblink))
+ {
+ mesg += gettext("Opening webpage");
+ }
+ else
+ {
+ mesg += gettext("Failed to open webpage");
+ }
+ mesg += " '" + weblink + "'";
+ m_chat_backend->addUnparsedMessage(utf8_to_wide(mesg));
+ }
+}
diff --git a/src/gui/guiChatConsole.h b/src/gui/guiChatConsole.h
index 896342ab0..169fb7eb7 100644
--- a/src/gui/guiChatConsole.h
+++ b/src/gui/guiChatConsole.h
@@ -82,6 +82,12 @@ private:
void drawText();
void drawPrompt();
+ // Clickable weblink stuff
+ int setupChatClickCtrlKeys(std::string inputline);
+ bool isInCtrlKeys(const irr::EKEY_CODE& kc);
+ // If clicked fragment has a web url, send it to the system default web browser
+ void middleClick(s32 col, s32 row);
+
private:
ChatBackend* m_chat_backend;
Client* m_client;
@@ -124,4 +130,9 @@ private:
// font
gui::IGUIFont *m_font = nullptr;
v2u32 m_fontsize;
+
+ // Enable clickable chat weblinks
+ bool m_cache_clickable_chat_weblinks;
+ // Set of "control" keys for weblink mouseclicks
+ std::vector<irr::EKEY_CODE> m_cache_chat_weblink_ctrl_keys;
};