1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +02:00

Android: make keyboard appear and disappear only on demand

This commit is contained in:
Andrii Danylchenko 2022-05-07 12:56:34 +03:00 committed by Andrii Danylchenko
parent 6da233c387
commit 2710d1df50
3 changed files with 155 additions and 93 deletions

View File

@ -268,10 +268,14 @@ void SelectionTab::clickLeft(tribool down, bool previousState)
if(down) if(down)
{ {
int line = getLine(); int line = getLine();
if(line != -1) if(line != -1)
{
select(line); select(line);
} }
} }
}
void SelectionTab::keyPressed(const SDL_KeyboardEvent & key) void SelectionTab::keyPressed(const SDL_KeyboardEvent & key)
{ {
if(key.state != SDL_PRESSED) if(key.state != SDL_PRESSED)

View File

@ -175,15 +175,15 @@ void CTextContainer::blitLine(SDL_Surface *to, Rect destRect, std::string what)
where.x += (int)f->getStringWidth(toPrint); where.x += (int)f->getStringWidth(toPrint);
} }
currDelimeter++; currDelimeter++;
} } while(begin++ != std::string::npos);
while (begin++ != std::string::npos);
} }
CTextContainer::CTextContainer(EAlignment alignment, EFonts font, SDL_Color color) : CTextContainer::CTextContainer(EAlignment alignment, EFonts font, SDL_Color color) :
alignment(alignment), alignment(alignment),
font(font), font(font),
color(color) color(color)
{} {
}
void CMultiLineLabel::showAll(SDL_Surface * to) void CMultiLineLabel::showAll(SDL_Surface * to)
{ {
@ -410,33 +410,41 @@ void CGStatusBar::lock(bool shouldLock)
CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB) CTextInput::CTextInput(const Rect & Pos, EFonts font, const CFunctionList<void(const std::string &)> & CB)
: CLabel(Pos.x, Pos.y, font, CENTER), : CLabel(Pos.x, Pos.y, font, CENTER),
cb(CB) cb(CB),
CFocusable(std::make_shared<CKeyboardFocusListener>(this))
{ {
type |= REDRAW_PARENT; type |= REDRAW_PARENT;
focus = false;
pos.h = Pos.h; pos.h = Pos.h;
pos.w = Pos.w; pos.w = Pos.w;
captureAllKeys = true; captureAllKeys = true;
background.reset(); background.reset();
addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT); addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT);
#ifndef VCMI_ANDROID
giveFocus(); giveFocus();
#endif
} }
CTextInput::CTextInput(const Rect & Pos, const Point & bgOffset, const std::string & bgName, const CFunctionList<void(const std::string &)> & CB) CTextInput::CTextInput(const Rect & Pos, const Point & bgOffset, const std::string & bgName, const CFunctionList<void(const std::string &)> & CB)
:cb(CB) :cb(CB), CFocusable(std::make_shared<CKeyboardFocusListener>(this))
{ {
focus = false;
pos += Pos; pos += Pos;
pos.h = Pos.h;
pos.w = Pos.w;
captureAllKeys = true; 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);
#ifndef VCMI_ANDROID
giveFocus(); giveFocus();
#endif
} }
CTextInput::CTextInput(const Rect & Pos, SDL_Surface * srf) CTextInput::CTextInput(const Rect & Pos, SDL_Surface * srf)
:CFocusable(std::make_shared<CKeyboardFocusListener>(this))
{ {
focus = false;
pos += Pos; pos += Pos;
captureAllKeys = true; captureAllKeys = true;
OBJ_CONSTRUCTION; OBJ_CONSTRUCTION;
@ -450,22 +458,35 @@ CTextInput::CTextInput(const Rect & Pos, SDL_Surface * srf)
pos.h = background->pos.h; pos.h = background->pos.h;
background->pos = pos; background->pos = pos;
addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT); addUsedEvents(LCLICK | KEYBOARD | TEXTINPUT);
giveFocus();
}
void CTextInput::focusGot() #ifndef VCMI_ANDROID
{ giveFocus();
CSDL_Ext::startTextInput(&pos);
#ifdef VCMI_ANDROID
notifyAndroidTextInputChanged(text);
#endif #endif
} }
void CTextInput::focusLost() std::atomic<int> CKeyboardFocusListener::usageIndex(0);
CKeyboardFocusListener::CKeyboardFocusListener(CTextInput * textInput)
:textInput(textInput)
{
}
void CKeyboardFocusListener::focusGot()
{
CSDL_Ext::startTextInput(&textInput->pos);
#ifdef VCMI_ANDROID
textInput->notifyAndroidTextInputChanged(textInput->text);
#endif
usageIndex++;
}
void CKeyboardFocusListener::focusLost()
{
if(0 == --usageIndex)
{ {
CSDL_Ext::stopTextInput(); CSDL_Ext::stopTextInput();
} }
}
std::string CTextInput::visibleText() std::string CTextInput::visibleText()
{ {
@ -641,6 +662,12 @@ void CTextInput::notifyAndroidTextInputChanged(std::string & text)
#endif //VCMI_ANDROID #endif //VCMI_ANDROID
CFocusable::CFocusable() CFocusable::CFocusable()
:CFocusable(std::make_shared<IFocusListener>())
{
}
CFocusable::CFocusable(std::shared_ptr<IFocusListener> focusListener)
: focusListener(focusListener)
{ {
focus = false; focus = false;
focusables.push_back(this); focusables.push_back(this);
@ -648,24 +675,30 @@ CFocusable::CFocusable()
CFocusable::~CFocusable() CFocusable::~CFocusable()
{ {
if(inputWithFocus == this) if(hasFocus())
{ {
focusLost();
inputWithFocus = nullptr; inputWithFocus = nullptr;
focusListener->focusLost();
} }
focusables -= this; focusables -= this;
} }
bool CFocusable::hasFocus() const
{
return inputWithFocus == this;
}
void CFocusable::giveFocus() void CFocusable::giveFocus()
{ {
focus = true; focus = true;
focusGot(); focusListener->focusGot();
redraw(); redraw();
if(inputWithFocus) if(inputWithFocus)
{ {
inputWithFocus->focus = false; inputWithFocus->focus = false;
inputWithFocus->focusListener->focusLost();
inputWithFocus->redraw(); inputWithFocus->redraw();
} }

View File

@ -140,24 +140,50 @@ public:
void lock(bool shouldLock); //If true, current text cannot be changed until lock(false) is called void lock(bool shouldLock); //If true, current text cannot be changed until lock(false) is called
}; };
class CFocusable;
class IFocusListener
{
public:
virtual void focusGot() {};
virtual void focusLost() {};
virtual ~IFocusListener() = default;
};
/// UIElement which can get input focus /// UIElement which can get input focus
class CFocusable : public virtual CIntObject class CFocusable : public virtual CIntObject
{ {
protected: private:
virtual void focusGot(){}; std::shared_ptr<IFocusListener> focusListener;
virtual void focusLost(){};
public: public:
bool focus; //only one focusable control can have focus at one moment bool focus; //only one focusable control can have focus at one moment
void giveFocus(); //captures focus void giveFocus(); //captures focus
void moveFocus(); //moves focus to next active control (may be used for tab switching) void moveFocus(); //moves focus to next active control (may be used for tab switching)
bool hasFocus() const;
static std::list<CFocusable *> focusables; //all existing objs static std::list<CFocusable *> focusables; //all existing objs
static CFocusable * inputWithFocus; //who has focus now static CFocusable * inputWithFocus; //who has focus now
CFocusable(); CFocusable();
CFocusable(std::shared_ptr<IFocusListener> focusListener);
~CFocusable(); ~CFocusable();
}; };
class CTextInput;
class CKeyboardFocusListener : public IFocusListener
{
private:
static std::atomic<int> usageIndex;
CTextInput * textInput;
public:
CKeyboardFocusListener(CTextInput * textInput);
void focusGot() override;
void focusLost() override;
};
/// Text input box where players can enter text /// Text input box where players can enter text
class CTextInput : public CLabel, public CFocusable class CTextInput : public CLabel, public CFocusable
{ {
@ -165,9 +191,6 @@ class CTextInput : public CLabel, public CFocusable
protected: protected:
std::string visibleText() override; std::string visibleText() override;
void focusGot() override;
void focusLost() override;
#ifdef VCMI_ANDROID #ifdef VCMI_ANDROID
void notifyAndroidTextInputChanged(std::string & text); void notifyAndroidTextInputChanged(std::string & text);
#endif #endif
@ -192,4 +215,6 @@ public:
//Filter that will allow only input of numbers in range min-max (min-max are allowed) //Filter that will allow only input of numbers in range min-max (min-max are allowed)
//min-max should be set via something like std::bind //min-max should be set via something like std::bind
static void numberFilter(std::string & text, const std::string & oldText, int minValue, int maxValue); static void numberFilter(std::string & text, const std::string & oldText, int minValue, int maxValue);
friend class CKeyboardFocusListener;
}; };