Expand Up
@@ -41,6 +41,10 @@ inline u32 clamp_u8(s32 value)
return (u32) MYMIN (MYMAX (value, 0 ), 255 );
}
inline bool isInCtrlKeys (const irr::EKEY_CODE& kc)
{
return kc == KEY_LCONTROL || kc == KEY_RCONTROL || kc == KEY_CONTROL;
}
GUIChatConsole::GUIChatConsole (
gui::IGUIEnvironment* env,
Expand Down
Expand Up
@@ -91,6 +95,10 @@ GUIChatConsole::GUIChatConsole(
// set default cursor options
setCursor (true , true , 2.0 , 0.1 );
// track ctrl keys for mouse event
m_is_ctrl_down = false ;
m_cache_clickable_chat_weblinks = g_settings->getBool (" clickable_chat_weblinks" );
}
GUIChatConsole::~GUIChatConsole ()
Expand Down
Expand Up
@@ -405,8 +413,21 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
ChatPrompt &prompt = m_chat_backend->getPrompt ();
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 ))
{
m_is_ctrl_down = false ;
}
}
else if (event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput .PressedDown )
{
// CTRL down
if (isInCtrlKeys (event.KeyInput .Key )) {
m_is_ctrl_down = true ;
}
// Key input
if (KeyPress (event.KeyInput ) == getKeySetting (" keymap_console" )) {
closeConsole ();
Expand Down
Expand Up
@@ -613,11 +634,24 @@ bool GUIChatConsole::OnEvent(const SEvent& event)
}
else if (event.EventType == EET_MOUSE_INPUT_EVENT)
{
if (event.MouseInput .Event == EMIE_MOUSE_WHEEL)
if (event.MouseInput .Event == EMIE_MOUSE_WHEEL)
{
s32 rows = myround (-3.0 * event.MouseInput .Wheel );
m_chat_backend->scroll (rows);
}
// Middle click or ctrl-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 && m_is_ctrl_down)
))
{
// If clicked within console output region
if (event.MouseInput .Y / m_fontsize.Y < (m_height / m_fontsize.Y ) - 1 )
{
// Translate pixel position to font position
middleClick (event.MouseInput .X / m_fontsize.X , event.MouseInput .Y / m_fontsize.Y );
}
}
}
#if (IRRLICHT_VERSION_MT_REVISION >= 2)
else if (event.EventType == EET_STRING_INPUT_EVENT)
Expand All
@@ -640,3 +674,63 @@ void GUIChatConsole::setVisible(bool visible)
}
}
void GUIChatConsole::middleClick (s32 col, s32 row)
{
// Prevent accidental rapid clicking
static u64 s_oldtime = 0 ;
u64 newtime = porting::getTimeMs ();
// 0.6 seconds should suffice
if (newtime - s_oldtime < 600 )
return ;
s_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 indx = frags.size () - 1 ;
if (indx < 0 ) {
// Invalid row, frags is empty
return ;
}
// Scan from right to left, offset by 1 font space because left margin
while (indx > -1 && (u32)col < frags[indx].column + 1 ) {
--indx;
}
if (indx > -1 ) {
weblink = frags[indx].weblink ;
// Note if(indx < 0) then a frag somehow had a corrupt column field
}
/*
// Debug help. Please keep this in case adjustments are made later.
std::string ws;
ws = "Middleclick: (" + std::to_string(col) + ',' + std::to_string(row) + ')' + " frags:";
// show all frags <position>(<length>) for the clicked row
for (u32 i=0;i<frags.size();++i) {
if (indx == int(i))
// tag the actual clicked frag
ws += '*';
ws += std::to_string(frags.at(i).column) + '('
+ std::to_string(frags.at(i).text.size()) + "),";
}
actionstream << ws << std::endl;
*/
// User notification
if (weblink.size () != 0 ) {
std::ostringstream msg;
msg << " * " ;
if (porting::open_url (weblink)) {
msg << gettext (" Opening webpage" );
}
else {
msg << gettext (" Failed to open webpage" );
}
msg << " '" << weblink << " '" ;
msg.flush ();
m_chat_backend->addUnparsedMessage (utf8_to_wide (msg.str ()));
}
}