mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Simplified text input handling, fixes hotkeys on windows with text input
This commit is contained in:
		| @@ -96,7 +96,7 @@ void CInGameConsole::print(const std::string & txt) | |||||||
|  |  | ||||||
| 		auto splitText = CMessage::breakText(txt, maxWidth, FONT_MEDIUM); | 		auto splitText = CMessage::breakText(txt, maxWidth, FONT_MEDIUM); | ||||||
|  |  | ||||||
| 		for (auto const & entry : splitText) | 		for(const auto & entry : splitText) | ||||||
| 			texts.push_back({entry, 0}); | 			texts.push_back({entry, 0}); | ||||||
|  |  | ||||||
| 		while(texts.size() > maxDisplayedTexts) | 		while(texts.size() > maxDisplayedTexts) | ||||||
| @@ -107,23 +107,43 @@ void CInGameConsole::print(const std::string & txt) | |||||||
| 	CCS->soundh->playSound("CHAT"); | 	CCS->soundh->playSound("CHAT"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool CInGameConsole::captureThisKey(EShortcut key) | ||||||
|  | { | ||||||
|  | 	if (enteredText.empty()) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	switch (key) | ||||||
|  | 	{ | ||||||
|  | 		case EShortcut::GLOBAL_ACCEPT: | ||||||
|  | 		case EShortcut::GLOBAL_CANCEL: | ||||||
|  | 		case EShortcut::GAME_ACTIVATE_CONSOLE: | ||||||
|  | 		case EShortcut::GLOBAL_BACKSPACE: | ||||||
|  | 		case EShortcut::MOVE_UP: | ||||||
|  | 		case EShortcut::MOVE_DOWN: | ||||||
|  | 			return true; | ||||||
|  |  | ||||||
|  | 		default: | ||||||
|  | 			return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| void CInGameConsole::keyPressed (EShortcut key) | void CInGameConsole::keyPressed (EShortcut key) | ||||||
| { | { | ||||||
| 	if (LOCPLINT->cingconsole != this) | 	if (LOCPLINT->cingconsole != this) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	if(!captureAllKeys && key != EShortcut::GAME_ACTIVATE_CONSOLE) | 	if(enteredText.empty() && key != EShortcut::GAME_ACTIVATE_CONSOLE) | ||||||
| 		return; //because user is not entering any text | 		return; //because user is not entering any text | ||||||
|  |  | ||||||
| 	switch(key) | 	switch(key) | ||||||
| 	{ | 	{ | ||||||
| 	case EShortcut::GLOBAL_CANCEL: | 	case EShortcut::GLOBAL_CANCEL: | ||||||
| 		if(captureAllKeys) | 		if(!enteredText.empty()) | ||||||
| 			endEnteringText(false); | 			endEnteringText(false); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 	case EShortcut::GAME_ACTIVATE_CONSOLE: | 	case EShortcut::GAME_ACTIVATE_CONSOLE: | ||||||
| 		if(captureAllKeys) | 		if(!enteredText.empty()) | ||||||
| 			endEnteringText(false); | 			endEnteringText(false); | ||||||
| 		else | 		else | ||||||
| 			startEnteringText(); | 			startEnteringText(); | ||||||
| @@ -131,7 +151,7 @@ void CInGameConsole::keyPressed (EShortcut key) | |||||||
|  |  | ||||||
| 	case EShortcut::GLOBAL_ACCEPT: | 	case EShortcut::GLOBAL_ACCEPT: | ||||||
| 		{ | 		{ | ||||||
| 			if(!enteredText.empty() && captureAllKeys) | 			if(!enteredText.empty()) | ||||||
| 			{ | 			{ | ||||||
| 				bool anyTextExceptCaret = enteredText.size() > 1; | 				bool anyTextExceptCaret = enteredText.size() > 1; | ||||||
| 				endEnteringText(anyTextExceptCaret); | 				endEnteringText(anyTextExceptCaret); | ||||||
| @@ -191,8 +211,9 @@ void CInGameConsole::textInputed(const std::string & inputtedText) | |||||||
| 	if (LOCPLINT->cingconsole != this) | 	if (LOCPLINT->cingconsole != this) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	if(!captureAllKeys || enteredText.empty()) | 	if(enteredText.empty()) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	enteredText.resize(enteredText.size()-1); | 	enteredText.resize(enteredText.size()-1); | ||||||
|  |  | ||||||
| 	enteredText += inputtedText; | 	enteredText += inputtedText; | ||||||
| @@ -211,14 +232,10 @@ void CInGameConsole::startEnteringText() | |||||||
| 	if (!isActive()) | 	if (!isActive()) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	if (captureAllKeys) |  | ||||||
| 		return; |  | ||||||
|  |  | ||||||
| 	assert(currentStatusBar.expired());//effectively, nullptr check | 	assert(currentStatusBar.expired());//effectively, nullptr check | ||||||
|  |  | ||||||
| 	currentStatusBar = GH.statusbar(); | 	currentStatusBar = GH.statusbar(); | ||||||
|  |  | ||||||
| 	captureAllKeys = true; |  | ||||||
| 	enteredText = "_"; | 	enteredText = "_"; | ||||||
|  |  | ||||||
| 	GH.statusbar()->setEnteringMode(true); | 	GH.statusbar()->setEnteringMode(true); | ||||||
| @@ -227,7 +244,6 @@ void CInGameConsole::startEnteringText() | |||||||
|  |  | ||||||
| void CInGameConsole::endEnteringText(bool processEnteredText) | void CInGameConsole::endEnteringText(bool processEnteredText) | ||||||
| { | { | ||||||
| 	captureAllKeys = false; |  | ||||||
| 	prevEntDisp = -1; | 	prevEntDisp = -1; | ||||||
| 	if(processEnteredText) | 	if(processEnteredText) | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
| @@ -50,6 +50,7 @@ public: | |||||||
| 	void keyPressed(EShortcut key) override; | 	void keyPressed(EShortcut key) override; | ||||||
| 	void textInputed(const std::string & enteredText) override; | 	void textInputed(const std::string & enteredText) override; | ||||||
| 	void textEdited(const std::string & enteredText) override; | 	void textEdited(const std::string & enteredText) override; | ||||||
|  | 	bool captureThisKey(EShortcut key) override; | ||||||
|  |  | ||||||
| 	void startEnteringText(); | 	void startEnteringText(); | ||||||
| 	void endEnteringText(bool processEnteredText); | 	void endEnteringText(bool processEnteredText); | ||||||
|   | |||||||
| @@ -33,6 +33,12 @@ void InputSourceKeyboard::handleEventKeyDown(const SDL_KeyboardEvent & key) | |||||||
| 	if(key.repeat != 0) | 	if(key.repeat != 0) | ||||||
| 		return; // ignore periodic event resends | 		return; // ignore periodic event resends | ||||||
|  |  | ||||||
|  | 	if (SDL_IsTextInputActive() == SDL_TRUE) | ||||||
|  | 	{ | ||||||
|  | 		if (key.keysym.sym >= ' ' && key.keysym.sym < 0x80) | ||||||
|  | 			return; // printable character - will be handled as text input | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	assert(key.state == SDL_PRESSED); | 	assert(key.state == SDL_PRESSED); | ||||||
|  |  | ||||||
| 	if(key.keysym.sym >= SDLK_F1 && key.keysym.sym <= SDLK_F15 && settings["session"]["spectate"].Bool()) | 	if(key.keysym.sym >= SDLK_F1 && key.keysym.sym <= SDLK_F15 && settings["session"]["spectate"].Bool()) | ||||||
| @@ -77,6 +83,12 @@ void InputSourceKeyboard::handleEventKeyUp(const SDL_KeyboardEvent & key) | |||||||
| 	if(key.repeat != 0) | 	if(key.repeat != 0) | ||||||
| 		return; // ignore periodic event resends | 		return; // ignore periodic event resends | ||||||
|  |  | ||||||
|  | 	if (SDL_IsTextInputActive() == SDL_TRUE) | ||||||
|  | 	{ | ||||||
|  | 		if (key.keysym.sym >= ' ' && key.keysym.sym < 0x80) | ||||||
|  | 			return; // printable character - will be handled as text input | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	assert(key.state == SDL_RELEASED); | 	assert(key.state == SDL_RELEASED); | ||||||
|  |  | ||||||
| 	auto shortcutsVector = GH.shortcuts().translateKeycode(key.keysym.sym); | 	auto shortcutsVector = GH.shortcuts().translateKeycode(key.keysym.sym); | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ | |||||||
|  |  | ||||||
| #include "CGuiHandler.h" | #include "CGuiHandler.h" | ||||||
| #include "WindowHandler.h" | #include "WindowHandler.h" | ||||||
|  | #include "EventDispatcher.h" | ||||||
| #include "Shortcut.h" | #include "Shortcut.h" | ||||||
| #include "../render/Canvas.h" | #include "../render/Canvas.h" | ||||||
| #include "../windows/CMessage.h" | #include "../windows/CMessage.h" | ||||||
| @@ -22,7 +23,6 @@ CIntObject::CIntObject(int used_, Point pos_): | |||||||
| 	parent(parent_m), | 	parent(parent_m), | ||||||
| 	redrawParent(false), | 	redrawParent(false), | ||||||
| 	inputEnabled(true), | 	inputEnabled(true), | ||||||
| 	captureAllKeys(false), |  | ||||||
| 	used(used_), | 	used(used_), | ||||||
| 	recActions(GH.defActionsDef), | 	recActions(GH.defActionsDef), | ||||||
| 	defActions(GH.defActionsDef), | 	defActions(GH.defActionsDef), | ||||||
| @@ -37,6 +37,8 @@ CIntObject::~CIntObject() | |||||||
| 	if(isActive()) | 	if(isActive()) | ||||||
| 		deactivate(); | 		deactivate(); | ||||||
|  |  | ||||||
|  | 	GH.events().assertElementInactive(this); | ||||||
|  |  | ||||||
| 	while(!children.empty()) | 	while(!children.empty()) | ||||||
| 	{ | 	{ | ||||||
| 		if((defActions & DISPOSE) && (children.front()->recActions & DISPOSE)) | 		if((defActions & DISPOSE) && (children.front()->recActions & DISPOSE)) | ||||||
| @@ -148,15 +150,15 @@ void CIntObject::setInputEnabled(bool on) | |||||||
|  |  | ||||||
| 	inputEnabled = on; | 	inputEnabled = on; | ||||||
|  |  | ||||||
| 	if (!isActive()) | 	if (isActive()) | ||||||
| 		return; | 	{ | ||||||
|  | 		assert((used & GENERAL) == 0); | ||||||
|  |  | ||||||
| 	assert((used & GENERAL) == 0); | 		if (on) | ||||||
|  | 			activateEvents(used); | ||||||
| 	if (on) | 		else | ||||||
| 		activateEvents(used); | 			deactivateEvents(used); | ||||||
| 	else | 	} | ||||||
| 		deactivateEvents(used); |  | ||||||
|  |  | ||||||
| 	for(auto & elem : children) | 	for(auto & elem : children) | ||||||
| 		elem->setInputEnabled(on); | 		elem->setInputEnabled(on); | ||||||
| @@ -207,6 +209,9 @@ void CIntObject::addChild(CIntObject * child, bool adjustPosition) | |||||||
| 	if(adjustPosition) | 	if(adjustPosition) | ||||||
| 		child->moveBy(pos.topLeft(), adjustPosition); | 		child->moveBy(pos.topLeft(), adjustPosition); | ||||||
|  |  | ||||||
|  | 	if (inputEnabled != child->inputEnabled) | ||||||
|  | 		child->setInputEnabled(inputEnabled); | ||||||
|  |  | ||||||
| 	if (!isActive() && child->isActive()) | 	if (!isActive() && child->isActive()) | ||||||
| 		child->deactivate(); | 		child->deactivate(); | ||||||
| 	if (isActive()&& !child->isActive()) | 	if (isActive()&& !child->isActive()) | ||||||
| @@ -292,7 +297,7 @@ const Rect & CIntObject::center(const Point & p, bool propagate) | |||||||
|  |  | ||||||
| bool CIntObject::captureThisKey(EShortcut key) | bool CIntObject::captureThisKey(EShortcut key) | ||||||
| { | { | ||||||
| 	return captureAllKeys; | 	return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| CKeyShortcut::CKeyShortcut() | CKeyShortcut::CKeyShortcut() | ||||||
|   | |||||||
| @@ -62,10 +62,8 @@ public: | |||||||
| 	CIntObject(int used=0, Point offset=Point()); | 	CIntObject(int used=0, Point offset=Point()); | ||||||
| 	virtual ~CIntObject(); | 	virtual ~CIntObject(); | ||||||
|  |  | ||||||
| 	//keyboard handling | 	/// allows capturing key input so it will be delivered only to this element | ||||||
| 	bool captureAllKeys; //if true, only this object should get info about pressed keys | 	bool captureThisKey(EShortcut key) override; | ||||||
|  |  | ||||||
| 	bool captureThisKey(EShortcut key) override; //allows refining captureAllKeys against specific events (eg. don't capture ENTER) |  | ||||||
|  |  | ||||||
| 	void addUsedEvents(ui16 newActions); | 	void addUsedEvents(ui16 newActions); | ||||||
| 	void removeUsedEvents(ui16 newActions); | 	void removeUsedEvents(ui16 newActions); | ||||||
|   | |||||||
| @@ -310,7 +310,6 @@ CChatBox::CChatBox(const Rect & rect) | |||||||
| { | { | ||||||
| 	OBJ_CONSTRUCTION; | 	OBJ_CONSTRUCTION; | ||||||
| 	pos += rect.topLeft(); | 	pos += rect.topLeft(); | ||||||
| 	captureAllKeys = true; |  | ||||||
| 	setRedrawParent(true); | 	setRedrawParent(true); | ||||||
|  |  | ||||||
| 	const int height = static_cast<int>(graphics->fonts[FONT_SMALL]->getLineHeight()); | 	const int height = static_cast<int>(graphics->fonts[FONT_SMALL]->getLineHeight()); | ||||||
|   | |||||||
| @@ -495,7 +495,6 @@ CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(c | |||||||
| 	setRedrawParent(true); | 	setRedrawParent(true); | ||||||
| 	pos.h = Pos.h; | 	pos.h = Pos.h; | ||||||
| 	pos.w = Pos.w; | 	pos.w = Pos.w; | ||||||
| 	captureAllKeys = true; |  | ||||||
| 	background.reset(); | 	background.reset(); | ||||||
| 	addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT); | 	addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT); | ||||||
|  |  | ||||||
| @@ -511,7 +510,6 @@ CTextInput::CTextInput(const Rect & Pos, const Point & bgOffset, const std::stri | |||||||
| 	pos.h = Pos.h; | 	pos.h = Pos.h; | ||||||
| 	pos.w = Pos.w; | 	pos.w = Pos.w; | ||||||
|  |  | ||||||
| 	captureAllKeys = true; |  | ||||||
| 	OBJ_CONSTRUCTION; | 	OBJ_CONSTRUCTION; | ||||||
| 	background = std::make_shared<CPicture>(bgName, bgOffset.x, bgOffset.y); | 	background = std::make_shared<CPicture>(bgName, bgOffset.x, bgOffset.y); | ||||||
| 	addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT); | 	addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT); | ||||||
| @@ -525,7 +523,6 @@ CTextInput::CTextInput(const Rect & Pos, std::shared_ptr<IImage> srf) | |||||||
| 	:CFocusable(std::make_shared<CKeyboardFocusListener>(this)) | 	:CFocusable(std::make_shared<CKeyboardFocusListener>(this)) | ||||||
| { | { | ||||||
| 	pos += Pos.topLeft(); | 	pos += Pos.topLeft(); | ||||||
| 	captureAllKeys = true; |  | ||||||
| 	OBJ_CONSTRUCTION; | 	OBJ_CONSTRUCTION; | ||||||
| 	background = std::make_shared<CPicture>(srf, Pos); | 	background = std::make_shared<CPicture>(srf, Pos); | ||||||
| 	pos.w = background->pos.w; | 	pos.w = background->pos.w; | ||||||
| @@ -620,17 +617,6 @@ void CTextInput::setText(const std::string & nText, bool callCb) | |||||||
| 		cb(text); | 		cb(text); | ||||||
| } | } | ||||||
|  |  | ||||||
| bool CTextInput::captureThisKey(EShortcut key) |  | ||||||
| { |  | ||||||
| 	if(key == EShortcut::GLOBAL_RETURN) |  | ||||||
| 		return false; |  | ||||||
|  |  | ||||||
| 	if (!focus) |  | ||||||
| 		return false; |  | ||||||
|  |  | ||||||
| 	return true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void CTextInput::textInputed(const std::string & enteredText) | void CTextInput::textInputed(const std::string & enteredText) | ||||||
| { | { | ||||||
| 	if(!focus) | 	if(!focus) | ||||||
|   | |||||||
| @@ -227,7 +227,7 @@ public: | |||||||
| 	void clickLeft(tribool down, bool previousState) override; | 	void clickLeft(tribool down, bool previousState) override; | ||||||
| 	void keyPressed(EShortcut key) override; | 	void keyPressed(EShortcut key) override; | ||||||
|  |  | ||||||
| 	bool captureThisKey(EShortcut key) override; | 	//bool captureThisKey(EShortcut key) override; | ||||||
|  |  | ||||||
| 	void textInputed(const std::string & enteredText) override; | 	void textInputed(const std::string & enteredText) override; | ||||||
| 	void textEdited(const std::string & enteredText) override; | 	void textEdited(const std::string & enteredText) override; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user