Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 33 additions & 24 deletions extras/videoDrivers/SDL2/VideoSDL2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ struct SDLMemoryDeleter

template<typename T>
using SDL_memory = std::unique_ptr<T, SDLMemoryDeleter<T>>;

void setSpecialKeys(KeyEvent& ke, const SDL_Keymod mod)
{
ke.ctrl = (mod & KMOD_CTRL);
ke.shift = (mod & KMOD_SHIFT);
ke.alt = (mod & KMOD_ALT);
}
void setSpecialKeys(KeyEvent& ke)
{
setSpecialKeys(ke, SDL_GetModState());
}
} // namespace

IVideoDriver* CreateVideoInstance(VideoDriverLoaderInterface* CallBack)
Expand Down Expand Up @@ -251,12 +262,8 @@ void VideoSDL2::HandlePaste()
if(!text || *text == '\0') // empty string indicates error
PrintError(text ? SDL_GetError() : "Paste failed.");

KeyEvent ke = {KeyType::Char, 0, false, false, false};
for(const char32_t c : s25util::utf8to32(text.get()))
{
ke.c = static_cast<unsigned>(c);
CallBack->Msg_KeyDown(ke);
}
CallBack->Msg_KeyDown(KeyEvent(c));
}

void VideoSDL2::DestroyScreen()
Expand Down Expand Up @@ -301,7 +308,7 @@ bool VideoSDL2::MessageLoop()

case SDL_KEYDOWN:
{
KeyEvent ke = {KeyType::Invalid, 0, false, false, false};
KeyEvent ke;

switch(ev.key.keysym.sym)
{
Expand Down Expand Up @@ -337,29 +344,32 @@ bool VideoSDL2::MessageLoop()
break;
}

if(ke.kt == KeyType::Invalid)
break;

/// Strg, Alt, usw gedrückt?
if(ev.key.keysym.mod & KMOD_CTRL)
ke.ctrl = true;
if(ev.key.keysym.mod & KMOD_SHIFT)
ke.shift = true;
if(ev.key.keysym.mod & KMOD_ALT)
ke.alt = true;
setSpecialKeys(ke, SDL_Keymod(ev.key.keysym.mod));

CallBack->Msg_KeyDown(ke);
if(ke.kt != KeyType::Invalid)
CallBack->Msg_KeyDown(ke);
else if(ke.alt || ke.ctrl)
{
// Handle shortcuts (CTRL+x, ALT+y)
// but not possible combinations (ALT+0054)
const SDL_Keycode keycode = ev.key.keysym.sym;
if(keycode >= 'a' && keycode <= 'z')
{
ke.kt = KeyType::Char;
ke.c = static_cast<char32_t>(keycode);
CallBack->Msg_KeyDown(ke);
}
}
}
break;
case SDL_TEXTINPUT:
{
const std::u32string text = s25util::utf8to32(ev.text.text);
SDL_Keymod mod = SDL_GetModState();
KeyEvent ke = {KeyType::Char, 0, (mod & KMOD_CTRL) != 0, (mod & KMOD_SHIFT) != 0,
(mod & KMOD_ALT) != 0};
KeyEvent ke(0);
setSpecialKeys(ke);
for(char32_t c : text)
{
ke.c = static_cast<unsigned>(c);
ke.c = c;
CallBack->Msg_KeyDown(ke);
}
break;
Expand Down Expand Up @@ -458,9 +468,8 @@ void VideoSDL2::SetMousePos(Position pos)

KeyEvent VideoSDL2::GetModKeyState() const
{
const SDL_Keymod modifiers = SDL_GetModState();
const KeyEvent ke = {KeyType::Invalid, 0, ((modifiers & KMOD_CTRL) != 0), ((modifiers & KMOD_SHIFT) != 0),
((modifiers & KMOD_ALT) != 0)};
KeyEvent ke;
setSpecialKeys(ke);
return ke;
}

Expand Down
27 changes: 20 additions & 7 deletions extras/videoDrivers/WinAPI/WinAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
#include <limits>
#include <winuser.h>

namespace {
void setSpecialKeys(KeyEvent& ke, LPARAM lParam)
{
ke.ctrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
ke.shift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
ke.alt = (HIWORD(lParam) & KF_ALTDOWN) != 0;
}
} // namespace

/**
* Zeiger auf die aktuelle Instanz.
*/
Expand Down Expand Up @@ -519,15 +528,17 @@ void VideoWinAPI::OnWMChar(unsigned c, bool disablepaste, LPARAM lParam)
if(c == ' ')
return;

KeyEvent ke = {KeyType::Char, c, (GetKeyState(VK_CONTROL) & 0x8000) != 0, (GetKeyState(VK_SHIFT) & 0x8000) != 0,
(lParam & KF_ALTDOWN) != 0};
KeyEvent ke(c);
setSpecialKeys(ke, lParam);

if(c == 'V' || c == 'v' || c == 0x16)
if(!disablepaste && ke.ctrl != 0)
{
if(!disablepaste && ke.ctrl)
{
OnWMPaste();
return;
}
}

CallBack->Msg_KeyDown(ke);
}
Expand All @@ -539,8 +550,8 @@ void VideoWinAPI::OnWMChar(unsigned c, bool disablepaste, LPARAM lParam)
*/
void VideoWinAPI::OnWMKeyDown(unsigned c, LPARAM lParam)
{
KeyEvent ke = {KeyType::Invalid, 0, (GetKeyState(VK_CONTROL) & 0x8000) != 0, (GetKeyState(VK_SHIFT) & 0x8000) != 0,
(lParam & KF_ALTDOWN) != 0};
KeyEvent ke;
setSpecialKeys(ke, lParam);

switch(c)
{
Expand Down Expand Up @@ -710,8 +721,10 @@ LRESULT CALLBACK VideoWinAPI::WindowProc(HWND window, UINT msg, WPARAM wParam, L
*/
KeyEvent VideoWinAPI::GetModKeyState() const
{
const KeyEvent ke = {KeyType::Invalid, 0, (GetKeyState(VK_CONTROL) & 0x8000) != 0,
(GetKeyState(VK_SHIFT) & 0x8000) != 0, (GetKeyState(VK_MENU) & 0x8000) != 0};
KeyEvent ke;
ke.ctrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
ke.shift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
ke.alt = (GetKeyState(VK_MENU) & 0x8000) != 0;
return ke;
}

Expand Down
10 changes: 7 additions & 3 deletions libs/driver/include/driver/KeyEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ enum class KeyType
/// TastatureventStruktur
struct KeyEvent
{
KeyType kt;
unsigned c;
bool ctrl, shift, alt;
constexpr KeyEvent() = default;
constexpr explicit KeyEvent(char32_t c) : kt(KeyType::Char), c(c) {}
constexpr explicit KeyEvent(KeyType kt) : kt(kt) {}

KeyType kt = KeyType::Invalid;
char32_t c = 0;
bool ctrl = false, shift = false, alt = false;
};
28 changes: 16 additions & 12 deletions libs/s25main/CheatCommandTracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ void CheatCommandTracker::onKeyEvent(const KeyEvent& ke)
if(!cheats_.areCheatsAllowed())
return;

if(checkSpecialKeyEvent(ke))
lastChars_.clear();
else
if(ke.kt == KeyType::Char)
onCharKeyEvent(ke);
else
{
onSpecialKeyEvent(ke);
lastChars_.clear();
}
}

void CheatCommandTracker::onChatCommand(const std::string& cmd)
Expand All @@ -38,25 +41,26 @@ void CheatCommandTracker::onChatCommand(const std::string& cmd)
cheats_.toggleAllBuildingsEnabled();
}

bool CheatCommandTracker::checkSpecialKeyEvent(const KeyEvent& ke)
void CheatCommandTracker::onSpecialKeyEvent(const KeyEvent& ke)
{
if(ke.kt == KeyType::Char)
return false;

switch(ke.kt)
{
case KeyType::F7: cheats_.toggleAllVisible(); break;
case KeyType::F10: cheats_.toggleHumanAIPlayer(); break;
default: break;
}

return true;
}

void CheatCommandTracker::onCharKeyEvent(const KeyEvent& ke)
{
lastChars_.push_back(ke.c);
// Handle only ASCII chars
if(ke.c > 0x7F)
lastChars_.clear();
else
{
lastChars_.push_back(static_cast<char>(ke.c));

if(lastChars_ == enableCheatsStr)
cheats_.toggleCheatMode();
if(lastChars_ == enableCheatsStr)
cheats_.toggleCheatMode();
}
}
2 changes: 1 addition & 1 deletion libs/s25main/CheatCommandTracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class CheatCommandTracker
void onChatCommand(const std::string& cmd);

private:
bool checkSpecialKeyEvent(const KeyEvent& ke);
void onSpecialKeyEvent(const KeyEvent& ke);
void onCharKeyEvent(const KeyEvent& ke);

Cheats& cheats_;
Expand Down
3 changes: 1 addition & 2 deletions libs/s25main/drivers/VideoDriverWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,7 @@ KeyEvent VideoDriverWrapper::GetModKeyState() const
{
if(videodriver)
return videodriver->GetModKeyState();
const KeyEvent ke = {KeyType::Invalid, 0, false, false, false};
return ke;
return KeyEvent();
}

void VideoDriverWrapper::SwapBuffers()
Expand Down
14 changes: 7 additions & 7 deletions tests/s25Main/UI/testControls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ BOOST_FIXTURE_TEST_CASE(EditShowsCorrectChars, uiHelper::Fixture)
mc.ldown = true;
edt2.Msg_LeftDown(mc);
edt2.Msg_PaintAfter();
edt2.Msg_KeyDown(KeyEvent{KeyType::Char, c, false, false, false});
edt2.Msg_KeyDown(KeyEvent(c));
// Remove chars from front until in size
auto itFirst = curChars.begin();
while(font->getWidth(curText) > allowedWidth)
Expand All @@ -188,12 +188,12 @@ BOOST_FIXTURE_TEST_CASE(EditShowsCorrectChars, uiHelper::Fixture)
int moveOffset = rttr::test::randomValue<int>(-curCursorPos - 1,
curChars.size() - curCursorPos + 1); //+-1 to check for "overrun"
for(; moveOffset < 0; ++moveOffset, --curCursorPos)
edt.Msg_KeyDown(KeyEvent{KeyType::Left, 0, false, false, false});
edt.Msg_KeyDown(KeyEvent(KeyType::Left));
for(; moveOffset > 0; --moveOffset, ++curCursorPos)
edt.Msg_KeyDown(KeyEvent{KeyType::Right, 0, false, false, false});
edt.Msg_KeyDown(KeyEvent(KeyType::Right));
curCursorPos = helpers::clamp(curCursorPos, 0, static_cast<int>(curChars.size()));
// Erase one char (currently only good way to check where the cursor is
edt.Msg_KeyDown(KeyEvent{KeyType::Backspace, 0, false, false, false});
edt.Msg_KeyDown(KeyEvent(KeyType::Backspace));
if(curCursorPos > 0)
{
curChars.erase(curChars.begin() + --curCursorPos);
Expand All @@ -219,18 +219,18 @@ BOOST_FIXTURE_TEST_CASE(EditShowsCorrectChars, uiHelper::Fixture)
do
{
BOOST_TEST_REQUIRE(txt->GetText() == txtWithoutFirst);
edt.Msg_KeyDown(KeyEvent{KeyType::Left, 0, false, false, false});
edt.Msg_KeyDown(KeyEvent(KeyType::Left));
--curCursorPos;
} while(curCursorPos > 5);
while(curCursorPos-- >= 0)
{
BOOST_TEST_REQUIRE(txt->GetText() == curText); // Trailing chars are removed by font rendering
edt.Msg_KeyDown(KeyEvent{KeyType::Left, 0, false, false, false});
edt.Msg_KeyDown(KeyEvent(KeyType::Left));
}
// Moving fully right shows txt again
curCursorPos = 0;
while(static_cast<unsigned>(curCursorPos++) < curChars.size())
edt.Msg_KeyDown(KeyEvent{KeyType::Right, 0, false, false, false});
edt.Msg_KeyDown(KeyEvent(KeyType::Right));
BOOST_TEST_REQUIRE(txt->GetText() == txtWithoutFirst);
}

Expand Down
17 changes: 9 additions & 8 deletions tests/s25Main/UI/testWindowManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ BOOST_FIXTURE_TEST_CASE(ModalWindowPlacement, uiHelper::Fixture)
MOCK_EXPECT(curWnd->DrawContent); // Ignore all draw calls
}
// Way outside any window, should still be handled
KeyEvent ke{KeyType::Char, 'a', false, false, false};
const KeyEvent ke('a');
for(TestIngameWnd* curWnd : expectedOrder)
{
REQUIRE_WINDOW_ACTIVE(curWnd);
Expand All @@ -381,7 +381,7 @@ BOOST_FIXTURE_TEST_CASE(EscClosesWindow, uiHelper::Fixture)
{
auto* wnd = &WINDOWMANAGER.Show(std::make_unique<TestIngameWnd>(CGI_HELP));
BOOST_TEST_REQUIRE(WINDOWMANAGER.GetTopMostWindow() == wnd);
KeyEvent evEsc{KeyType::Escape, 0, false, false, false};
const KeyEvent evEsc(KeyType::Escape);
WINDOWMANAGER.Msg_KeyDown(evEsc);
WINDOWMANAGER.Draw();
BOOST_TEST_REQUIRE(WINDOWMANAGER.GetTopMostWindow() == nullptr);
Expand Down Expand Up @@ -479,8 +479,9 @@ BOOST_FIXTURE_TEST_CASE(RightclickClosesWindow, uiHelper::Fixture)

BOOST_FIXTURE_TEST_CASE(PinnedWindows, uiHelper::Fixture)
{
constexpr KeyEvent evEsc{KeyType::Escape, 0, false, false, false};
constexpr KeyEvent evAltW{KeyType::Char, 'w', false, false, true};
constexpr KeyEvent evEsc(KeyType::Escape);
KeyEvent evAltW('w');
evAltW.alt = true;

BOOST_TEST_CONTEXT("Pinned windows ignore escape key")
{
Expand Down Expand Up @@ -610,8 +611,7 @@ BOOST_FIXTURE_TEST_CASE(TestTransmitSettingsAdapter, uiHelper::Fixture)
wnd = &WINDOWMANAGER.Show(std::make_unique<MockSettingsWnd>(CGI_TOOLS));
BOOST_TEST_REQUIRE(WINDOWMANAGER.GetTopMostWindow() == wnd);
MOCK_EXPECT(wnd->TransmitSettings).once();
KeyEvent ev{KeyType::Escape, 0, false, false, false};
WINDOWMANAGER.Msg_KeyDown(ev);
WINDOWMANAGER.Msg_KeyDown(KeyEvent(KeyType::Escape));
WINDOWMANAGER.Draw();
BOOST_TEST(MockSettingsWnd::activeWnds == 0);
BOOST_TEST(WINDOWMANAGER.GetTopMostWindow() == nullptr);
Expand All @@ -621,8 +621,9 @@ BOOST_FIXTURE_TEST_CASE(TestTransmitSettingsAdapter, uiHelper::Fixture)
wnd = &WINDOWMANAGER.Show(std::make_unique<MockSettingsWnd>(CGI_TOOLS));
BOOST_TEST_REQUIRE(WINDOWMANAGER.GetTopMostWindow() == wnd);
MOCK_EXPECT(wnd->TransmitSettings).once();
KeyEvent ev{KeyType::Escape, 'w', false, false, true};
WINDOWMANAGER.Msg_KeyDown(ev);
KeyEvent ke('w');
ke.alt = true;
WINDOWMANAGER.Msg_KeyDown(ke);
WINDOWMANAGER.Draw();
BOOST_TEST(MockSettingsWnd::activeWnds == 0);
BOOST_TEST(WINDOWMANAGER.GetTopMostWindow() == nullptr);
Expand Down
11 changes: 4 additions & 7 deletions tests/s25Main/integration/testCheatCommandTracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,10 @@ struct CheatCommandTrackerFixture : WorldFixture<CreateEmptyWorld, T_numPlayers>
Cheats cheats_{this->world};
CheatCommandTracker tracker_{cheats_};

KeyEvent makeKeyEvent(unsigned c) { return {KeyType::Char, c, false, false, false}; }
KeyEvent makeKeyEvent(KeyType kt) { return {kt, 0, false, false, false}; }

void trackString(const std::string& str)
{
for(char c : str)
tracker_.onKeyEvent(makeKeyEvent(c));
for(char32_t c : str)
tracker_.onKeyEvent(KeyEvent(c));
}
};
using CheatCommandTrackerFixture1P = CheatCommandTrackerFixture<1>;
Expand Down Expand Up @@ -55,7 +52,7 @@ BOOST_FIXTURE_TEST_CASE(CheatModeIsNotTurnedOn_IfTheCheatStringIsWrong, CheatCom
BOOST_TEST_REQUIRE(cheats_.isCheatModeOn() == false);

trackString("win");
tracker_.onKeyEvent(makeKeyEvent(KeyType::F10)); // interrupted by another key type
tracker_.onKeyEvent(KeyEvent(KeyType::F10)); // interrupted by another key type
trackString("ter");
BOOST_TEST_REQUIRE(cheats_.isCheatModeOn() == false);

Expand All @@ -78,7 +75,7 @@ BOOST_FIXTURE_TEST_CASE(CheatModeIsTurnedOn_WhenTheFirstCharacterIsRepeated, Che
BOOST_FIXTURE_TEST_CASE(CheatModeIsTurnedOn_EvenWhenWrongInputsWereProvidedBefore, CheatCommandTrackerFixture1P)
{
trackString("www");
auto ke = makeKeyEvent('1');
KeyEvent ke('1');
ke.alt = true;
tracker_.onKeyEvent(ke);
trackString("interwitter");
Expand Down
Loading