Browse Source

Merge pull request #2310 from IvanSavenko/left_click_refactor

Left click input refactor
Ivan Savenko 2 years ago
parent
commit
9ef959a7f8
65 changed files with 381 additions and 422 deletions
  1. 2 1
      client/CPlayerInterface.cpp
  2. 8 11
      client/adventureMap/CInfoBar.cpp
  3. 2 2
      client/adventureMap/CInfoBar.h
  4. 10 13
      client/adventureMap/CList.cpp
  5. 2 2
      client/adventureMap/CList.h
  6. 3 4
      client/adventureMap/CMinimap.cpp
  7. 2 2
      client/adventureMap/CMinimap.h
  8. 6 9
      client/battle/BattleFieldController.cpp
  9. 2 2
      client/battle/BattleFieldController.h
  10. 2 2
      client/gui/CIntObject.cpp
  11. 0 1
      client/gui/CIntObject.h
  12. 20 17
      client/gui/EventDispatcher.cpp
  13. 1 1
      client/gui/EventDispatcher.h
  14. 12 9
      client/gui/EventsReceiver.h
  15. 4 8
      client/lobby/CBonusSelection.cpp
  16. 2 2
      client/lobby/CBonusSelection.h
  17. 1 1
      client/lobby/CSelectionBase.cpp
  18. 1 1
      client/lobby/CSelectionBase.h
  19. 1 1
      client/lobby/OptionsTab.cpp
  20. 1 1
      client/lobby/OptionsTab.h
  21. 17 10
      client/lobby/RandomMapTab.cpp
  22. 4 2
      client/lobby/RandomMapTab.h
  23. 13 15
      client/lobby/SelectionTab.cpp
  24. 2 2
      client/lobby/SelectionTab.h
  25. 3 6
      client/mainmenu/CCampaignScreen.cpp
  26. 1 1
      client/mainmenu/CCampaignScreen.h
  27. 2 2
      client/mainmenu/CPrologEpilogVideo.cpp
  28. 1 1
      client/mainmenu/CPrologEpilogVideo.h
  29. 2 2
      client/mainmenu/CreditsScreen.cpp
  30. 1 1
      client/mainmenu/CreditsScreen.h
  31. 4 10
      client/mapView/MapViewActions.cpp
  32. 2 2
      client/mapView/MapViewActions.h
  33. 61 33
      client/widgets/Buttons.cpp
  34. 8 3
      client/widgets/Buttons.h
  35. 6 14
      client/widgets/CArtifactHolder.cpp
  36. 4 5
      client/widgets/CArtifactHolder.h
  37. 4 7
      client/widgets/CComponent.cpp
  38. 2 2
      client/widgets/CComponent.h
  39. 2 5
      client/widgets/CGarrisonInt.cpp
  40. 2 2
      client/widgets/CGarrisonInt.h
  41. 2 2
      client/widgets/CWindowWithArtifacts.cpp
  42. 12 17
      client/widgets/MiscWidgets.cpp
  43. 6 6
      client/widgets/MiscWidgets.h
  44. 5 5
      client/widgets/Slider.cpp
  45. 1 1
      client/widgets/Slider.h
  46. 5 8
      client/widgets/TextControls.cpp
  47. 2 2
      client/widgets/TextControls.h
  48. 41 49
      client/windows/CCastleInterface.cpp
  49. 12 12
      client/windows/CCastleInterface.h
  50. 2 3
      client/windows/CCreatureWindow.cpp
  51. 1 1
      client/windows/CCreatureWindow.h
  52. 10 13
      client/windows/CHeroWindow.cpp
  53. 2 2
      client/windows/CHeroWindow.h
  54. 7 18
      client/windows/CKingdomInterface.cpp
  55. 2 5
      client/windows/CKingdomInterface.h
  56. 4 6
      client/windows/CQuestLog.cpp
  57. 3 3
      client/windows/CQuestLog.h
  58. 6 7
      client/windows/CSpellWindow.cpp
  59. 4 4
      client/windows/CSpellWindow.h
  60. 2 6
      client/windows/CTradeWindow.cpp
  61. 2 2
      client/windows/CTradeWindow.h
  62. 1 1
      client/windows/CreaturePurchaseCard.cpp
  63. 1 1
      client/windows/CreaturePurchaseCard.h
  64. 16 24
      client/windows/GUIClasses.cpp
  65. 9 9
      client/windows/GUIClasses.h

+ 2 - 1
client/CPlayerInterface.cpp

@@ -1100,7 +1100,8 @@ void CPlayerInterface::showBlockingDialog( const std::string &text, const std::v
 		if (pom.size() > 1)
 			charperline = 50;
 		GH.windows().createAndPushWindow<CSelWindow>(text, playerID, charperline, intComps, pom, askID);
-		intComps[0]->clickLeft(true, false);
+		intComps[0]->clickPressed(GH.getCursorPosition());
+		intComps[0]->clickReleased(GH.getCursorPosition());
 	}
 }
 

+ 8 - 11
client/adventureMap/CInfoBar.cpp

@@ -271,20 +271,17 @@ void CInfoBar::tick(uint32_t msPassed)
 	}
 }
 
-void CInfoBar::clickLeft(tribool down, bool previousState)
+void CInfoBar::clickReleased(const Point & cursorPosition)
 {
-	if(down)
-	{
-		if(state == HERO || state == TOWN)
-			showGameStatus();
-		else if(state == GAME)
-			showDate();
-		else
-			popComponents(true);
-	}
+	if(state == HERO || state == TOWN)
+		showGameStatus();
+	else if(state == GAME)
+		showDate();
+	else
+		popComponents(true);
 }
 
-void CInfoBar::showPopupWindow()
+void CInfoBar::showPopupWindow(const Point & cursorPosition)
 {
 	CRClickPopup::createAndPush(CGI->generaltexth->allTexts[109]);
 }

+ 2 - 2
client/adventureMap/CInfoBar.h

@@ -154,8 +154,8 @@ private:
 
 	void tick(uint32_t msPassed) override;
 
-	void clickLeft(tribool down, bool previousState) override;
-	void showPopupWindow() override;
+	void clickReleased(const Point & cursorPosition) override;
+	void showPopupWindow(const Point & cursorPosition) override;
 	void hover(bool on) override;
 
 	void playNewDaySound();

+ 10 - 13
client/adventureMap/CList.cpp

@@ -40,25 +40,22 @@ CList::CListItem::CListItem(CList * Parent)
 
 CList::CListItem::~CListItem() = default;
 
-void CList::CListItem::showPopupWindow()
+void CList::CListItem::showPopupWindow(const Point & cursorPosition)
 {
 	showTooltip();
 }
 
-void CList::CListItem::clickLeft(tribool down, bool previousState)
+void CList::CListItem::clickPressed(const Point & cursorPosition)
 {
-	if(down == true)
+	//second click on already selected item
+	if(parent->selected == this->shared_from_this())
 	{
-		//second click on already selected item
-		if(parent->selected == this->shared_from_this())
-		{
-			open();
-		}
-		else
-		{
-			//first click - switch selection
-			parent->select(this->shared_from_this());
-		}
+		open();
+	}
+	else
+	{
+		//first click - switch selection
+		parent->select(this->shared_from_this());
 	}
 }
 

+ 2 - 2
client/adventureMap/CList.h

@@ -35,8 +35,8 @@ protected:
 		CListItem(CList * parent);
 		~CListItem();
 
-		void showPopupWindow() override;
-		void clickLeft(tribool down, bool previousState) override;
+		void showPopupWindow(const Point & cursorPosition) override;
+		void clickPressed(const Point & cursorPosition) override;
 		void hover(bool on) override;
 		void onSelect(bool on);
 

+ 3 - 4
client/adventureMap/CMinimap.cpp

@@ -143,13 +143,12 @@ void CMinimap::gesturePanning(const Point & initialPosition, const Point & curre
 		moveAdvMapSelection(currentPosition);
 }
 
-void CMinimap::clickLeft(tribool down, bool previousState)
+void CMinimap::clickPressed(const Point & cursorPosition)
 {
-	if(down)
-		moveAdvMapSelection(GH.getCursorPosition());
+	moveAdvMapSelection(cursorPosition);
 }
 
-void CMinimap::showPopupWindow()
+void CMinimap::showPopupWindow(const Point & cursorPosition)
 {
 	CRClickPopup::createAndPush(CGI->generaltexth->zelp[291].second);
 }

+ 2 - 2
client/adventureMap/CMinimap.h

@@ -44,8 +44,8 @@ class CMinimap : public CIntObject
 	int level;
 
 	void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
-	void clickLeft(tribool down, bool previousState) override;
-	void showPopupWindow() override;
+	void clickPressed(const Point & cursorPosition) override;
+	void showPopupWindow(const Point & cursorPosition) override;
 	void hover(bool on) override;
 	void mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) override;
 

+ 6 - 9
client/battle/BattleFieldController.cpp

@@ -184,7 +184,7 @@ void BattleFieldController::createHeroes()
 void BattleFieldController::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
 {
 	if (!on && pos.isInside(finalPosition))
-		clickLeft(false, false);
+		clickPressed(finalPosition);
 }
 
 void BattleFieldController::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance)
@@ -213,18 +213,15 @@ void BattleFieldController::mouseMoved(const Point & cursorPosition, const Point
 		owner.actionsController->onHoverEnded();
 }
 
-void BattleFieldController::clickLeft(tribool down, bool previousState)
+void BattleFieldController::clickPressed(const Point & cursorPosition)
 {
-	if(!down)
-	{
-		BattleHex selectedHex = getHoveredHex();
+	BattleHex selectedHex = getHoveredHex();
 
-		if (selectedHex != BattleHex::INVALID)
-			owner.actionsController->onHexLeftClicked(selectedHex);
-	}
+	if (selectedHex != BattleHex::INVALID)
+		owner.actionsController->onHexLeftClicked(selectedHex);
 }
 
-void BattleFieldController::showPopupWindow()
+void BattleFieldController::showPopupWindow(const Point & cursorPosition)
 {
 	BattleHex selectedHex = getHoveredHex();
 

+ 2 - 2
client/battle/BattleFieldController.h

@@ -100,8 +100,8 @@ class BattleFieldController : public CIntObject
 	void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
 	void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
 	void mouseMoved(const Point & cursorPosition, const Point & lastUpdateDistance) override;
-	void clickLeft(tribool down, bool previousState) override;
-	void showPopupWindow() override;
+	void clickPressed(const Point & cursorPosition) override;
+	void showPopupWindow(const Point & cursorPosition) override;
 	void activate() override;
 
 	void showAll(Canvas & to) override;

+ 2 - 2
client/gui/CIntObject.cpp

@@ -313,7 +313,7 @@ void CKeyShortcut::keyPressed(EShortcut key)
 	if( assignedKey == key && assignedKey != EShortcut::NONE && !shortcutPressed)
 	{
 		shortcutPressed = true;
-		clickLeft(true, false);
+		clickPressed(GH.getCursorPosition());
 	}
 }
 
@@ -322,7 +322,7 @@ void CKeyShortcut::keyReleased(EShortcut key)
 	if( assignedKey == key && assignedKey != EShortcut::NONE && shortcutPressed)
 	{
 		shortcutPressed = false;
-		clickLeft(false, true);
+		clickReleased(GH.getCursorPosition());
 	}
 }
 

+ 0 - 1
client/gui/CIntObject.h

@@ -62,7 +62,6 @@ public:
 	CIntObject(int used=0, Point offset=Point());
 	virtual ~CIntObject();
 
-	/// allows capturing key input so it will be delivered only to this element
 	bool captureThisKey(EShortcut key) override;
 
 	void addUsedEvents(ui16 newActions);

+ 20 - 17
client/gui/EventDispatcher.cpp

@@ -128,23 +128,23 @@ void EventDispatcher::dispatchMouseDoubleClick(const Point & position)
 
 		if(i->receiveEvent(position, AEventsReceiver::DOUBLECLICK))
 		{
-			i->clickDouble();
+			i->clickDouble(position);
 			doubleClicked = true;
 		}
 	}
 
 	if(!doubleClicked)
-		handleLeftButtonClick(true);
+		handleLeftButtonClick(position, true);
 }
 
 void EventDispatcher::dispatchMouseLeftButtonPressed(const Point & position)
 {
-	handleLeftButtonClick(true);
+	handleLeftButtonClick(position, true);
 }
 
 void EventDispatcher::dispatchMouseLeftButtonReleased(const Point & position)
 {
-	handleLeftButtonClick(false);
+	handleLeftButtonClick(position, false);
 }
 
 void EventDispatcher::dispatchShowPopup(const Point & position)
@@ -155,10 +155,10 @@ void EventDispatcher::dispatchShowPopup(const Point & position)
 		if(!vstd::contains(rclickable, i))
 			continue;
 
-		if( !i->receiveEvent(GH.getCursorPosition(), AEventsReceiver::LCLICK))
+		if( !i->receiveEvent(position, AEventsReceiver::LCLICK))
 			continue;
 
-		i->showPopupWindow();
+		i->showPopupWindow(position);
 	}
 }
 
@@ -170,7 +170,7 @@ void EventDispatcher::dispatchClosePopup(const Point & position)
 	assert(!GH.windows().isTopWindowPopup());
 }
 
-void EventDispatcher::handleLeftButtonClick(bool isPressed)
+void EventDispatcher::handleLeftButtonClick(const Point & position, bool isPressed)
 {
 	auto hlp = lclickable;
 	for(auto & i : hlp)
@@ -178,20 +178,23 @@ void EventDispatcher::handleLeftButtonClick(bool isPressed)
 		if(!vstd::contains(lclickable, i))
 			continue;
 
-		auto prev = i->isMouseLeftButtonPressed();
-
-		if(!isPressed)
-			i->mouseClickedState = isPressed;
-
-		if( i->receiveEvent(GH.getCursorPosition(), AEventsReceiver::LCLICK))
+		if( i->receiveEvent(position, AEventsReceiver::LCLICK))
 		{
 			if(isPressed)
-				i->mouseClickedState = isPressed;
-			i->clickLeft(isPressed, prev);
+				i->clickPressed(position);
+
+			if (i->mouseClickedState && !isPressed)
+				i->clickReleased(position);
+
+			i->mouseClickedState = isPressed;
 		}
-		else if(!isPressed)
+		else
 		{
-			i->clickLeft(boost::logic::indeterminate, prev);
+			if(i->mouseClickedState && !isPressed)
+			{
+				i->mouseClickedState = isPressed;
+				i->clickCancel(position);
+			}
 		}
 	}
 }

+ 1 - 1
client/gui/EventDispatcher.h

@@ -35,7 +35,7 @@ class EventDispatcher
 	EventReceiversList textInterested;
 	EventReceiversList panningInterested;
 
-	void handleLeftButtonClick(bool isPressed);
+	void handleLeftButtonClick(const Point & position, bool isPressed);
 
 
 	template<typename Functor>

+ 12 - 9
client/gui/EventsReceiver.h

@@ -15,7 +15,6 @@ VCMI_LIB_NAMESPACE_END
 
 class EventDispatcher;
 enum class EShortcut;
-using boost::logic::tribool;
 
 /// Class that is capable of subscribing and receiving input events
 /// Acts as base class for all UI elements
@@ -34,9 +33,18 @@ protected:
 	/// Deactivates particular events for this UI element. Uses unnamed enum from this class
 	void deactivateEvents(ui16 what);
 
-	virtual void clickLeft(tribool down, bool previousState) {}
-	virtual void showPopupWindow() {}
-	virtual void clickDouble() {}
+	/// allows capturing key input so it will be delivered only to this element
+	virtual bool captureThisKey(EShortcut key) = 0;
+
+	/// If true, event of selected type in selected position will be processed by this element
+	virtual bool receiveEvent(const Point & position, int eventType) const= 0;
+
+public:
+	virtual void clickPressed(const Point & cursorPosition) {}
+	virtual void clickReleased(const Point & cursorPosition) {}
+	virtual void clickCancel(const Point & cursorPosition) {}
+	virtual void showPopupWindow(const Point & cursorPosition) {}
+	virtual void clickDouble(const Point & cursorPosition) {}
 
 	/// Called when user pans screen by specified distance
 	virtual void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) {}
@@ -62,11 +70,6 @@ protected:
 
 	virtual void tick(uint32_t msPassed) {}
 
-	virtual bool captureThisKey(EShortcut key) = 0;
-
-	/// If true, event of selected type in selected position will be processed by this element
-	virtual bool receiveEvent(const Point & position, int eventType) const= 0;
-
 public:
 	AEventsReceiver();
 	virtual ~AEventsReceiver() = default;

+ 4 - 8
client/lobby/CBonusSelection.cpp

@@ -499,23 +499,19 @@ void CBonusSelection::CRegion::updateState()
 	}
 }
 
-void CBonusSelection::CRegion::clickLeft(tribool down, bool previousState)
+void CBonusSelection::CRegion::clickReleased(const Point & cursorPosition)
 {
-	//select if selectable & clicked inside our graphic
-	if(indeterminate(down))
-		return;
-
-	if(!down && selectable && !graphicsNotSelected->getSurface()->isTransparent(GH.getCursorPosition() - pos.topLeft()))
+	if(selectable && !graphicsNotSelected->getSurface()->isTransparent(cursorPosition - pos.topLeft()))
 	{
 		CSH->setCampaignMap(idOfMapAndRegion);
 	}
 }
 
-void CBonusSelection::CRegion::showPopupWindow()
+void CBonusSelection::CRegion::showPopupWindow(const Point & cursorPosition)
 {
 	// FIXME: For some reason "down" is only ever contain indeterminate_value
 	auto text = CSH->si->campState->scenario(idOfMapAndRegion).regionText;
-	if(!graphicsNotSelected->getSurface()->isTransparent(GH.getCursorPosition() - pos.topLeft()) && text.size())
+	if(!graphicsNotSelected->getSurface()->isTransparent(cursorPosition - pos.topLeft()) && text.size())
 	{
 		CRClickPopup::createAndPush(text);
 	}

+ 2 - 2
client/lobby/CBonusSelection.h

@@ -47,8 +47,8 @@ public:
 	public:
 		CRegion(CampaignScenarioID id, bool accessible, bool selectable, const CampaignRegions & campDsc);
 		void updateState();
-		void clickLeft(tribool down, bool previousState) override;
-		void showPopupWindow() override;
+		void clickReleased(const Point & cursorPosition) override;
+		void showPopupWindow(const Point & cursorPosition) override;
 	};
 
 	void createBonusesIcons();

+ 1 - 1
client/lobby/CSelectionBase.cpp

@@ -377,7 +377,7 @@ void CFlagBox::recreate()
 	}
 }
 
-void CFlagBox::showPopupWindow()
+void CFlagBox::showPopupWindow(const Point & cursorPosition)
 {
 	if(SEL->getMapInfo())
 		GH.windows().createAndPushWindow<CFlagBoxTooltipBox>(iconsTeamFlags);

+ 1 - 1
client/lobby/CSelectionBase.h

@@ -135,7 +135,7 @@ class CFlagBox : public CIntObject
 public:
 	CFlagBox(const Rect & rect);
 	void recreate();
-	void showPopupWindow() override;
+	void showPopupWindow(const Point & cursorPosition) override;
 	void showTeamsPopup();
 
 	class CFlagBoxTooltipBox : public CWindowObject

+ 1 - 1
client/lobby/OptionsTab.cpp

@@ -432,7 +432,7 @@ void OptionsTab::SelectedBox::update()
 	subtitle->setText(getName());
 }
 
-void OptionsTab::SelectedBox::showPopupWindow()
+void OptionsTab::SelectedBox::showPopupWindow(const Point & cursorPosition)
 {
 	// cases when we do not need to display a message
 	if(settings.castle == -2 && CPlayerSettingsHelper::type == TOWN)

+ 1 - 1
client/lobby/OptionsTab.h

@@ -101,7 +101,7 @@ public:
 		std::shared_ptr<CLabel> subtitle;
 
 		SelectedBox(Point position, PlayerSettings & settings, SelType type);
-		void showPopupWindow() override;
+		void showPopupWindow(const Point & cursorPosition) override;
 		void scrollBy(int distance) override;
 
 		void update();

+ 17 - 10
client/lobby/RandomMapTab.cpp

@@ -406,18 +406,17 @@ void TemplatesDropBox::ListItem::hover(bool on)
 	redraw();
 }
 
-void TemplatesDropBox::ListItem::clickLeft(tribool down, bool previousState)
+void TemplatesDropBox::ListItem::clickPressed(const Point & cursorPosition)
 {
-	if(down && isHovered())
-	{
+	if(isHovered())
 		dropBox.setTemplate(item);
-	}
-	else 
-	{
-		dropBox.clickLeft(true, true);
-	}
 }
 
+void TemplatesDropBox::ListItem::clickReleased(const Point & cursorPosition)
+{
+	dropBox.clickPressed(cursorPosition);
+	dropBox.clickReleased(cursorPosition);
+}
 
 TemplatesDropBox::TemplatesDropBox(RandomMapTab & randomMapTab, int3 size):
 	InterfaceObjectConfigurable(LCLICK | HOVER),
@@ -471,9 +470,17 @@ void TemplatesDropBox::sliderMove(int slidPos)
 	redraw();
 }
 
-void TemplatesDropBox::clickLeft(tribool down, bool previousState)
+bool TemplatesDropBox::receiveEvent(const Point & position, int eventType) const
+{
+	if (eventType == LCLICK)
+		return true; // we want drop box to close when clicking outside drop box borders
+
+	return CIntObject::receiveEvent(position, eventType);
+}
+
+void TemplatesDropBox::clickPressed(const Point & cursorPosition)
 {
-	if (!pos.isInside(GH.getCursorPosition()))
+	if (!pos.isInside(cursorPosition))
 	{
 		assert(GH.windows().isTopWindow(this));
 		GH.windows().popWindows(1);

+ 4 - 2
client/lobby/RandomMapTab.h

@@ -62,7 +62,8 @@ class TemplatesDropBox : public InterfaceObjectConfigurable
 		void updateItem(int index, const CRmgTemplate * item = nullptr);
 		
 		void hover(bool on) override;
-		void clickLeft(tribool down, bool previousState) override;
+		void clickPressed(const Point & cursorPosition) override;
+		void clickReleased(const Point & cursorPosition) override;
 	};
 	
 	friend struct ListItem;
@@ -70,7 +71,8 @@ class TemplatesDropBox : public InterfaceObjectConfigurable
 public:
 	TemplatesDropBox(RandomMapTab & randomMapTab, int3 size);
 	
-	void clickLeft(tribool down, bool previousState) override;
+	bool receiveEvent(const Point & position, int eventType) const override;
+	void clickPressed(const Point & cursorPosition) override;
 	void setTemplate(const CRmgTemplate *);
 	
 private:

+ 13 - 15
client/lobby/SelectionTab.cpp

@@ -270,22 +270,20 @@ void SelectionTab::toggleMode()
 	redraw();
 }
 
-void SelectionTab::clickLeft(tribool down, bool previousState)
+void SelectionTab::clickReleased(const Point & cursorPosition)
 {
-	if(down)
-	{
-		int line = getLine();
+	int line = getLine();
 
-		if(line != -1)
-		{
-			select(line);
-		}
+	if(line != -1)
+	{
+		select(line);
+	}
 #ifdef VCMI_IOS
-		// focus input field if clicked inside it
-		else if(inputName && inputName->isActive() && inputNameRect.isInside(GH.getCursorPosition()))
-			inputName->giveFocus();
+	// focus input field if clicked inside it
+	else if(inputName && inputName->isActive() && inputNameRect.isInside(cursorPosition))
+		inputName->giveFocus();
 #endif
-	}
+
 }
 
 void SelectionTab::keyPressed(EShortcut key)
@@ -317,12 +315,12 @@ void SelectionTab::keyPressed(EShortcut key)
 	select((int)selectionPos - slider->getValue() + moveBy);
 }
 
-void SelectionTab::clickDouble()
+void SelectionTab::clickDouble(const Point & cursorPosition)
 {
 	if(getLine() != -1) //double clicked scenarios list
 	{
-		(static_cast<CLobbyScreen *>(parent))->buttonStart->clickLeft(true, false);
-		(static_cast<CLobbyScreen *>(parent))->buttonStart->clickLeft(false, true);
+		(static_cast<CLobbyScreen *>(parent))->buttonStart->clickPressed(cursorPosition);
+		(static_cast<CLobbyScreen *>(parent))->buttonStart->clickReleased(cursorPosition);
 	}
 }
 

+ 2 - 2
client/lobby/SelectionTab.h

@@ -65,9 +65,9 @@ public:
 	SelectionTab(ESelectionScreen Type);
 	void toggleMode();
 
-	void clickLeft(tribool down, bool previousState) override;
+	void clickReleased(const Point & cursorPosition) override;
 	void keyPressed(EShortcut key) override;
-	void clickDouble() override;
+	void clickDouble(const Point & cursorPosition) override;
 	bool receiveEvent(const Point & position, int eventType) const override;
 
 	void filter(int size, bool selectFirst = false); //0 - all

+ 3 - 6
client/mainmenu/CCampaignScreen.cpp

@@ -141,13 +141,10 @@ void CCampaignScreen::CCampaignButton::show(Canvas & to)
 	}
 }
 
-void CCampaignScreen::CCampaignButton::clickLeft(tribool down, bool previousState)
+void CCampaignScreen::CCampaignButton::clickReleased(const Point & cursorPosition)
 {
-	if(down)
-	{
-		CCS->videoh->close();
-		CMainMenu::openCampaignLobby(campFile);
-	}
+	CCS->videoh->close();
+	CMainMenu::openCampaignLobby(campFile);
 }
 
 void CCampaignScreen::CCampaignButton::hover(bool on)

+ 1 - 1
client/mainmenu/CCampaignScreen.h

@@ -40,7 +40,7 @@ private:
 		std::string video; // the resource name of the video
 		std::string hoverText;
 
-		void clickLeft(tribool down, bool previousState) override;
+		void clickReleased(const Point & cursorPosition) override;
 		void hover(bool on) override;
 
 	public:

+ 2 - 2
client/mainmenu/CPrologEpilogVideo.cpp

@@ -52,10 +52,10 @@ void CPrologEpilogVideo::show(Canvas & to)
 		text->showAll(to); // blit text over video, if needed
 
 	if(text->textSize.y + 100 < positionCounter / 5)
-		clickLeft(false, false);
+		clickPressed(GH.getCursorPosition());
 }
 
-void CPrologEpilogVideo::clickLeft(tribool down, bool previousState)
+void CPrologEpilogVideo::clickPressed(const Point & cursorPosition)
 {
 	close();
 	CCS->soundh->stopSound(voiceSoundHandle);

+ 1 - 1
client/mainmenu/CPrologEpilogVideo.h

@@ -26,6 +26,6 @@ class CPrologEpilogVideo : public CWindowObject
 public:
 	CPrologEpilogVideo(CampaignScenarioPrologEpilog _spe, std::function<void()> callback);
 
-	void clickLeft(tribool down, bool previousState) override;
+	void clickPressed(const Point & cursorPosition) override;
 	void show(Canvas & to) override;
 };

+ 2 - 2
client/mainmenu/CreditsScreen.cpp

@@ -43,10 +43,10 @@ void CreditsScreen::show(Canvas & to)
 
 	//end of credits, close this screen
 	if(credits->textSize.y + 600 < positionCounter / 2)
-		clickLeft(false, false);
+		clickPressed(GH.getCursorPosition());
 }
 
-void CreditsScreen::clickLeft(tribool down, bool previousState)
+void CreditsScreen::clickPressed(const Point & cursorPosition)
 {
 	CTabbedInt * menu = dynamic_cast<CTabbedInt *>(parent);
 	assert(menu);

+ 1 - 1
client/mainmenu/CreditsScreen.h

@@ -21,5 +21,5 @@ class CreditsScreen : public CIntObject
 public:
 	CreditsScreen(Rect rect);
 	void show(Canvas & to) override;
-	void clickLeft(tribool down, bool previousState) override;
+	void clickPressed(const Point & cursorPosition) override;
 };

+ 4 - 10
client/mapView/MapViewActions.cpp

@@ -41,23 +41,17 @@ void MapViewActions::setContext(const std::shared_ptr<IMapRendererContext> & con
 	this->context = context;
 }
 
-void MapViewActions::clickLeft(tribool down, bool previousState)
+void MapViewActions::clickPressed(const Point & cursorPosition)
 {
-	if(indeterminate(down))
-		return;
-
-	if(down == false)
-		return;
-
-	int3 tile = model->getTileAtPoint(GH.getCursorPosition() - pos.topLeft());
+	int3 tile = model->getTileAtPoint(cursorPosition - pos.topLeft());
 
 	if(context->isInMap(tile))
 		adventureInt->onTileLeftClicked(tile);
 }
 
-void MapViewActions::showPopupWindow()
+void MapViewActions::showPopupWindow(const Point & cursorPosition)
 {
-	int3 tile = model->getTileAtPoint(GH.getCursorPosition() - pos.topLeft());
+	int3 tile = model->getTileAtPoint(cursorPosition - pos.topLeft());
 
 	if(context->isInMap(tile))
 		adventureInt->onTileRightClicked(tile);

+ 2 - 2
client/mapView/MapViewActions.h

@@ -31,8 +31,8 @@ public:
 
 	void setContext(const std::shared_ptr<IMapRendererContext> & context);
 
-	void clickLeft(tribool down, bool previousState) override;
-	void showPopupWindow() override;
+	void clickPressed(const Point & cursorPosition) override;
+	void showPopupWindow(const Point & cursorPosition) override;
 	void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
 	void gesturePinch(const Point & centerPosition, double lastUpdateFactor) override;
 	void hover(bool on) override;

+ 61 - 33
client/widgets/Buttons.cpp

@@ -167,39 +167,48 @@ void CButton::onButtonClicked()
 	callback();
 }
 
-void CButton::clickLeft(tribool down, bool previousState)
+void CButton::clickPressed(const Point & cursorPosition)
 {
 	if(isBlocked())
 		return;
 
-	if (down)
+	if (getState() != PRESSED)
 	{
-		if (getState() != PRESSED)
-		{
-			if (!soundDisabled)
-				CCS->soundh->playSound(soundBase::button);
-			setState(PRESSED);
-
-			if (actOnDown)
-				onButtonClicked();
-		}
+		if (!soundDisabled)
+			CCS->soundh->playSound(soundBase::button);
+		setState(PRESSED);
+
+		if (actOnDown)
+			onButtonClicked();
 	}
-	else
+}
+
+void CButton::clickReleased(const Point & cursorPosition)
+{
+	if (getState() == PRESSED)
 	{
-		if (getState() == PRESSED)
-		{
-			if(hoverable && isHovered())
-				setState(HIGHLIGHTED);
-			else
-				setState(NORMAL);
-
-			if (!actOnDown && previousState && (down == false))
-				onButtonClicked();
-		}
+		if(hoverable && isHovered())
+			setState(HIGHLIGHTED);
+		else
+			setState(NORMAL);
+
+		if (!actOnDown)
+			onButtonClicked();
+	}
+}
+
+void CButton::clickCancel(const Point & cursorPosition)
+{
+	if (getState() == PRESSED)
+	{
+		if(hoverable && isHovered())
+			setState(HIGHLIGHTED);
+		else
+			setState(NORMAL);
 	}
 }
 
-void CButton::showPopupWindow()
+void CButton::showPopupWindow(const Point & cursorPosition)
 {
 	if(helpBox.size()) //there is no point to show window with nothing inside...
 		CRClickPopup::createAndPush(helpBox);
@@ -382,7 +391,7 @@ void CToggleButton::setEnabled(bool enabled)
 	setState(enabled ? NORMAL : BLOCKED);
 }
 
-void CToggleButton::clickLeft(tribool down, bool previousState)
+void CToggleButton::clickPressed(const Point & cursorPosition)
 {
 	// force refresh
 	hover(false);
@@ -391,22 +400,41 @@ void CToggleButton::clickLeft(tribool down, bool previousState)
 	if(isBlocked())
 		return;
 
-	if (down && canActivate())
+	if (canActivate())
 	{
 		CCS->soundh->playSound(soundBase::button);
 		setState(PRESSED);
 	}
+}
 
-	if(previousState)//mouse up
+void CToggleButton::clickReleased(const Point & cursorPosition)
+{
+	// force refresh
+	hover(false);
+	hover(true);
+
+	if(isBlocked())
+		return;
+
+	if (getState() == PRESSED && canActivate())
 	{
-		if(down == false && getState() == PRESSED && canActivate())
-		{
-			onButtonClicked();
-			setSelected(!selected);
-		}
-		else
-			doSelect(selected); // restore
+		onButtonClicked();
+		setSelected(!selected);
 	}
+	else
+		doSelect(selected); // restore
+}
+
+void CToggleButton::clickCancel(const Point & cursorPosition)
+{
+	// force refresh
+	hover(false);
+	hover(true);
+
+	if(isBlocked())
+		return;
+
+	doSelect(selected);
 }
 
 void CToggleGroup::addCallback(std::function<void(int)> callback)

+ 8 - 3
client/widgets/Buttons.h

@@ -102,8 +102,10 @@ public:
 	void setPlayerColor(PlayerColor player);
 
 	/// CIntObject overrides
-	void showPopupWindow() override;
-	void clickLeft(tribool down, bool previousState) override;
+	void showPopupWindow(const Point & cursorPosition) override;
+	void clickPressed(const Point & cursorPosition) override;
+	void clickReleased(const Point & cursorPosition) override;
+	void clickCancel(const Point & cursorPosition) override;
 	void hover (bool on) override;
 	void showAll(Canvas & to) override;
 
@@ -154,7 +156,10 @@ class CToggleButton : public CButton, public CToggleBase
 public:
 	CToggleButton(Point position, const std::string &defName, const std::pair<std::string, std::string> &help,
 				  CFunctionList<void(bool)> Callback = 0, EShortcut key = {}, bool playerColoredButton = false );
-	void clickLeft(tribool down, bool previousState) override;
+
+	void clickPressed(const Point & cursorPosition) override;
+	void clickReleased(const Point & cursorPosition) override;
+	void clickCancel(const Point & cursorPosition) override;
 
 	// bring overrides into scope
 	//using CButton::addCallback;

+ 6 - 14
client/widgets/CArtifactHolder.cpp

@@ -67,11 +67,6 @@ CArtPlace::CArtPlace(Point position, const CArtifactInstance * Art)
 	pos.w = pos.h = 44;
 }
 
-void CArtPlace::clickLeft(tribool down, bool previousState)
-{
-	LRClickableAreaWTextComp::clickLeft(down, previousState);
-}
-
 const CArtifactInstance * CArtPlace::getArt()
 {
 	return ourArt;
@@ -121,16 +116,16 @@ void CCommanderArtPlace::returnArtToHeroCallback()
 	}
 }
 
-void CCommanderArtPlace::clickLeft(tribool down, bool previousState)
+void CCommanderArtPlace::clickPressed(const Point & cursorPosition)
 {
-	if(ourArt && text.size() && down)
+	if(ourArt && text.size())
 		LOCPLINT->showYesNoDialog(CGI->generaltexth->translate("vcmi.commanderWindow.artifactMessage"), [this]() { returnArtToHeroCallback(); }, []() {});
 }
 
-void CCommanderArtPlace::showPopupWindow()
+void CCommanderArtPlace::showPopupWindow(const Point & cursorPosition)
 {
 	if(ourArt && text.size())
-		CArtPlace::showPopupWindow();
+		CArtPlace::showPopupWindow(cursorPosition);
 }
 
 void CCommanderArtPlace::setArtifact(const CArtifactInstance * art)
@@ -183,16 +178,13 @@ bool CHeroArtPlace::isMarked() const
 	return marked;
 }
 
-void CHeroArtPlace::clickLeft(tribool down, bool previousState)
+void CHeroArtPlace::clickPressed(const Point & cursorPosition)
 {
-	if(down || !previousState)
-		return;
-
 	if(leftClickCallback)
 		leftClickCallback(*this);
 }
 
-void CHeroArtPlace::showPopupWindow()
+void CHeroArtPlace::showPopupWindow(const Point & cursorPosition)
 {
 	if(rightClickCallback)
 		rightClickCallback(*this);

+ 4 - 5
client/widgets/CArtifactHolder.h

@@ -41,7 +41,6 @@ protected:
 
 public:
 	CArtPlace(Point position, const CArtifactInstance * Art = nullptr);
-	void clickLeft(tribool down, bool previousState) override;
 	const CArtifactInstance * getArt();
 
 	virtual void setArtifact(const CArtifactInstance * art)=0;
@@ -58,8 +57,8 @@ protected:
 
 public:
 	CCommanderArtPlace(Point position, const CGHeroInstance * commanderOwner, ArtifactPosition artSlot, const CArtifactInstance * Art = nullptr);
-	void clickLeft(tribool down, bool previousState) override;
-	void showPopupWindow() override;
+	void clickPressed(const Point & cursorPosition) override;
+	void showPopupWindow(const Point & cursorPosition) override;
 	void setArtifact(const CArtifactInstance * art) override;
 };
 
@@ -77,8 +76,8 @@ public:
 	bool isLocked();
 	void selectSlot(bool on);
 	bool isMarked() const;
-	void clickLeft(tribool down, bool previousState) override;
-	void showPopupWindow() override;
+	void clickPressed(const Point & cursorPosition) override;
+	void showPopupWindow(const Point & cursorPosition) override;
 	void showAll(Canvas & to) override;
 	void setArtifact(const CArtifactInstance * art) override;
 	void addCombinedArtInfo(std::map<const CArtifact*, int> & arts);

+ 4 - 7
client/widgets/CComponent.cpp

@@ -255,19 +255,16 @@ void CComponent::setSurface(std::string defName, int imgPos)
 	image = std::make_shared<CAnimImage>(defName, imgPos);
 }
 
-void CComponent::showPopupWindow()
+void CComponent::showPopupWindow(const Point & cursorPosition)
 {
 	if(!getDescription().empty())
 		CRClickPopup::createAndPush(getDescription());
 }
 
-void CSelectableComponent::clickLeft(tribool down, bool previousState)
+void CSelectableComponent::clickPressed(const Point & cursorPosition)
 {
-	if (down)
-	{
-		if(onSelect)
-			onSelect();
-	}
+	if(onSelect)
+		onSelect();
 }
 
 void CSelectableComponent::init()

+ 2 - 2
client/widgets/CComponent.h

@@ -65,7 +65,7 @@ public:
 	CComponent(Etype Type, int Subtype, int Val = 0, ESize imageSize=large, EFonts font = FONT_SMALL);
 	CComponent(const Component &c, ESize imageSize=large, EFonts font = FONT_SMALL);
 
-	void showPopupWindow() override; //call-in
+	void showPopupWindow(const Point & cursorPosition) override; //call-in
 };
 
 /// component that can be selected or deselected
@@ -79,7 +79,7 @@ public:
 	void showAll(Canvas & to) override;
 	void select(bool on);
 
-	void clickLeft(tribool down, bool previousState) override; //call-in
+	void clickPressed(const Point & cursorPosition) override; //call-in
 	CSelectableComponent(Etype Type, int Sub, int Val, ESize imageSize=large, std::function<void()> OnSelect = nullptr);
 	CSelectableComponent(const Component & c, std::function<void()> OnSelect = nullptr);
 };

+ 2 - 5
client/widgets/CGarrisonInt.cpp

@@ -285,7 +285,7 @@ bool CGarrisonSlot::mustForceReselection() const
 	return false;
 }
 
-void CGarrisonSlot::showPopupWindow()
+void CGarrisonSlot::showPopupWindow(const Point & cursorPosition)
 {
 	if(creature)
 	{
@@ -293,10 +293,8 @@ void CGarrisonSlot::showPopupWindow()
 	}
 }
 
-void CGarrisonSlot::clickLeft(tribool down, bool previousState)
+void CGarrisonSlot::clickPressed(const Point & cursorPosition)
 {
-	if(down)
-	{
 		bool refr = false;
 		const CGarrisonSlot * selection = owner->getSelection();
 
@@ -349,7 +347,6 @@ void CGarrisonSlot::clickLeft(tribool down, bool previousState)
 			hover(false);
 			hover(true);
 		}
-	}
 }
 
 void CGarrisonSlot::update()

+ 2 - 2
client/widgets/CGarrisonInt.h

@@ -58,8 +58,8 @@ public:
 	bool our() const;
 	SlotID getSlot() const { return ID; }
 	bool ally() const;
-	void showPopupWindow() override;
-	void clickLeft(tribool down, bool previousState) override;
+	void showPopupWindow(const Point & cursorPosition) override;
+	void clickPressed(const Point & cursorPosition) override;
 	void update();
 	CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, EGarrisonType Upg=EGarrisonType::UP, const CStackInstance * creature_ = nullptr);
 

+ 2 - 2
client/widgets/CWindowWithArtifacts.cpp

@@ -200,7 +200,7 @@ void CWindowWithArtifacts::rightClickArtPlaceHero(CArtifactsOfHeroBase & artsIns
 						return;
 					}
 					if(artPlace.text.size())
-						artPlace.LRClickableAreaWTextComp::showPopupWindow();
+						artPlace.LRClickableAreaWTextComp::showPopupWindow(GH.getCursorPosition());
 				}
 			}
 			// Altar window, Market window right click handler
@@ -209,7 +209,7 @@ void CWindowWithArtifacts::rightClickArtPlaceHero(CArtifactsOfHeroBase & artsIns
 				std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroMarket>>)
 			{
 				if(artPlace.getArt() && artPlace.text.size())
-					artPlace.LRClickableAreaWTextComp::showPopupWindow();
+					artPlace.LRClickableAreaWTextComp::showPopupWindow(GH.getCursorPosition());
 			}
 		}, artSetWeak.value());
 }

+ 12 - 17
client/widgets/MiscWidgets.cpp

@@ -50,14 +50,12 @@ CHoverableArea::~CHoverableArea()
 {
 }
 
-void LRClickableAreaWText::clickLeft(tribool down, bool previousState)
+void LRClickableAreaWText::clickPressed(const Point & cursorPosition)
 {
-	if(!down && previousState && !text.empty())
-	{
+	if(!text.empty())
 		LOCPLINT->showInfoDialog(text);
-	}
 }
-void LRClickableAreaWText::showPopupWindow()
+void LRClickableAreaWText::showPopupWindow(const Point & cursorPosition)
 {
 	if (!text.empty())
 		CRClickPopup::createAndPush(text);
@@ -85,13 +83,10 @@ void LRClickableAreaWText::init()
 	addUsedEvents(LCLICK | SHOW_POPUP | HOVER);
 }
 
-void LRClickableAreaWTextComp::clickLeft(tribool down, bool previousState)
+void LRClickableAreaWTextComp::clickPressed(const Point & cursorPosition)
 {
-	if((!down) && previousState)
-	{
-		std::vector<std::shared_ptr<CComponent>> comp(1, createComponent());
-		LOCPLINT->showInfoDialog(text, comp);
-	}
+	std::vector<std::shared_ptr<CComponent>> comp(1, createComponent());
+	LOCPLINT->showInfoDialog(text, comp);
 }
 
 LRClickableAreaWTextComp::LRClickableAreaWTextComp(const Rect &Pos, int BaseType)
@@ -108,7 +103,7 @@ std::shared_ptr<CComponent> LRClickableAreaWTextComp::createComponent() const
 		return std::shared_ptr<CComponent>();
 }
 
-void LRClickableAreaWTextComp::showPopupWindow()
+void LRClickableAreaWTextComp::showPopupWindow(const Point & cursorPosition)
 {
 	if(auto comp = createComponent())
 	{
@@ -116,7 +111,7 @@ void LRClickableAreaWTextComp::showPopupWindow()
 		return;
 	}
 
-	LRClickableAreaWText::showPopupWindow(); //only if with-component variant not occurred
+	LRClickableAreaWText::showPopupWindow(cursorPosition); //only if with-component variant not occurred
 }
 
 CHeroArea::CHeroArea(int x, int y, const CGHeroInstance * _hero)
@@ -134,9 +129,9 @@ CHeroArea::CHeroArea(int x, int y, const CGHeroInstance * _hero)
 		portrait = std::make_shared<CAnimImage>("PortraitsLarge", hero->portrait);
 }
 
-void CHeroArea::clickLeft(tribool down, bool previousState)
+void CHeroArea::clickPressed(const Point & cursorPosition)
 {
-	if(hero && (!down) && previousState)
+	if(hero)
 		LOCPLINT->openHeroWindow(hero);
 }
 
@@ -148,9 +143,9 @@ void CHeroArea::hover(bool on)
 		GH.statusbar()->clear();
 }
 
-void LRClickableAreaOpenTown::clickLeft(tribool down, bool previousState)
+void LRClickableAreaOpenTown::clickPressed(const Point & cursorPosition)
 {
-	if(town && (!down) && previousState)
+	if(town)
 	{
 		LOCPLINT->openTownWindow(town);
 		if ( type == 2 )

+ 6 - 6
client/widgets/MiscWidgets.h

@@ -48,8 +48,8 @@ public:
 	virtual ~LRClickableAreaWText();
 	void init();
 
-	virtual void clickLeft(tribool down, bool previousState) override;
-	virtual void showPopupWindow() override;
+	void clickPressed(const Point & cursorPosition) override;
+	void showPopupWindow(const Point & cursorPosition) override;
 };
 
 /// base class for hero/town/garrison tooltips
@@ -135,7 +135,7 @@ class CHeroArea: public CIntObject
 public:
 	CHeroArea(int x, int y, const CGHeroInstance * _hero);
 
-	void clickLeft(tribool down, bool previousState) override;
+	void clickPressed(const Point & cursorPosition) override;
 	void hover(bool on) override;
 };
 
@@ -146,8 +146,8 @@ public:
 	int type;
 	int baseType;
 	int bonusValue;
-	virtual void clickLeft(tribool down, bool previousState) override;
-	virtual void showPopupWindow() override;
+	void clickPressed(const Point & cursorPosition) override;
+	void showPopupWindow(const Point & cursorPosition) override;
 
 	LRClickableAreaWTextComp(const Rect &Pos = Rect(0,0,0,0), int BaseType = -1);
 	std::shared_ptr<CComponent> createComponent() const;
@@ -158,7 +158,7 @@ class LRClickableAreaOpenTown: public LRClickableAreaWTextComp
 {
 public:
 	const CGTownInstance * town;
-	void clickLeft(tribool down, bool previousState) override;
+	void clickPressed(const Point & cursorPosition) override;
 	LRClickableAreaOpenTown(const Rect & Pos, const CGTownInstance * Town);
 };
 

+ 5 - 5
client/widgets/Slider.cpp

@@ -121,20 +121,20 @@ void CSlider::scrollTo(int to)
 	moved(to);
 }
 
-void CSlider::clickLeft(tribool down, bool previousState)
+void CSlider::clickPressed(const Point & cursorPosition)
 {
-	if(down && !slider->isBlocked())
+	if(!slider->isBlocked())
 	{
 		double pw = 0;
 		double rw = 0;
 		if(getOrientation() == Orientation::HORIZONTAL)
 		{
-			pw = GH.getCursorPosition().x-pos.x-25;
+			pw = cursorPosition.x-pos.x-25;
 			rw = pw / static_cast<double>(pos.w - 48);
 		}
 		else
 		{
-			pw = GH.getCursorPosition().y-pos.y-24;
+			pw = cursorPosition.y-pos.y-24;
 			rw = pw / (pos.h-48);
 		}
 
@@ -142,7 +142,7 @@ void CSlider::clickLeft(tribool down, bool previousState)
 		if (!vstd::iswithin(rw, 0, 1))
 			return;
 
-		slider->clickLeft(true, slider->isMouseLeftButtonPressed());
+		slider->clickPressed(cursorPosition);
 		scrollTo((int)(rw * positions  +  0.5));
 		return;
 	}

+ 1 - 1
client/widgets/Slider.h

@@ -69,7 +69,7 @@ public:
 
 	bool receiveEvent(const Point & position, int eventType) const override;
 	void keyPressed(EShortcut key) override;
-	void clickLeft(tribool down, bool previousState) override;
+	void clickPressed(const Point & cursorPosition) override;
 	void mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) override;
 	void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
 	void showAll(Canvas & to) override;

+ 5 - 8
client/widgets/TextControls.cpp

@@ -446,13 +446,10 @@ void CGStatusBar::show(Canvas & to)
 	showAll(to);
 }
 
-void CGStatusBar::clickLeft(tribool down, bool previousState)
+void CGStatusBar::clickPressed(const Point & cursorPosition)
 {
-	if(!down)
-	{
-		if(LOCPLINT && LOCPLINT->cingconsole->isActive())
-			LOCPLINT->cingconsole->startEnteringText();
-	}
+	if(LOCPLINT && LOCPLINT->cingconsole->isActive())
+		LOCPLINT->cingconsole->startEnteringText();
 }
 
 void CGStatusBar::activate()
@@ -561,9 +558,9 @@ std::string CTextInput::visibleText()
 	return focus ? text + newText + "_" : text;
 }
 
-void CTextInput::clickLeft(tribool down, bool previousState)
+void CTextInput::clickPressed(const Point & cursorPosition)
 {
-	if(down && !focus)
+	if(!focus)
 		giveFocus();
 }
 

+ 2 - 2
client/widgets/TextControls.h

@@ -138,7 +138,7 @@ class CGStatusBar : public CLabel, public std::enable_shared_from_this<CGStatusB
 protected:
 	Point getBorderSize() override;
 
-	void clickLeft(tribool down, bool previousState) override;
+	void clickPressed(const Point & cursorPosition) override;
 
 public:
 	~CGStatusBar();
@@ -224,7 +224,7 @@ public:
 	CTextInput(const Rect & Pos, const Point & bgOffset, const std::string & bgName, const CFunctionList<void(const std::string &)> & CB);
 	CTextInput(const Rect & Pos, std::shared_ptr<IImage> srf);
 
-	void clickLeft(tribool down, bool previousState) override;
+	void clickPressed(const Point & cursorPosition) override;
 	void keyPressed(EShortcut key) override;
 
 	//bool captureThisKey(EShortcut key) override;

+ 41 - 49
client/windows/CCastleInterface.cpp

@@ -134,16 +134,16 @@ void CBuildingRect::hover(bool on)
 	}
 }
 
-void CBuildingRect::clickLeft(tribool down, bool previousState)
+void CBuildingRect::clickPressed(const Point & cursorPosition)
 {
-	if(previousState && getBuilding() && area && !down && (parent->selectedBuilding==this))
+	if(getBuilding() && area && (parent->selectedBuilding==this))
 	{
 		auto building = getBuilding();
 		parent->buildingClicked(building->bid, building->subId, building->upgrade);
 	}
 }
 
-void CBuildingRect::showPopupWindow()
+void CBuildingRect::showPopupWindow(const Point & cursorPosition)
 {
 	if((!area) || (this!=parent->selectedBuilding) || getBuilding() == nullptr)
 		return;
@@ -377,37 +377,35 @@ void CHeroGSlot::hover(bool on)
 		GH.statusbar()->write(temp);
 }
 
-void CHeroGSlot::clickLeft(tribool down, bool previousState)
+void CHeroGSlot::clickPressed(const Point & cursorPosition)
 {
 	std::shared_ptr<CHeroGSlot> other = upg ? owner->garrisonedHero : owner->visitingHero;
-	if(!down)
-	{
-		owner->garr->setSplittingMode(false);
-		owner->garr->selectSlot(nullptr);
 
-		if(hero && isSelected())
-		{
-			setHighlight(false);
-			LOCPLINT->openHeroWindow(hero);
-		}
-		else if(other->hero && other->isSelected())
-		{
-			owner->swapArmies();
-		}
-		else if(hero)
-		{
-			setHighlight(true);
-			owner->garr->selectSlot(nullptr);
-			redraw();
-		}
+	owner->garr->setSplittingMode(false);
+	owner->garr->selectSlot(nullptr);
 
-		//refresh statusbar
-		hover(false);
-		hover(true);
+	if(hero && isSelected())
+	{
+		setHighlight(false);
+		LOCPLINT->openHeroWindow(hero);
+	}
+	else if(other->hero && other->isSelected())
+	{
+		owner->swapArmies();
 	}
+	else if(hero)
+	{
+		setHighlight(true);
+		owner->garr->selectSlot(nullptr);
+		redraw();
+	}
+
+	//refresh statusbar
+	hover(false);
+	hover(true);
 }
 
-void CHeroGSlot::showPopupWindow()
+void CHeroGSlot::showPopupWindow(const Point & cursorPosition)
 {
 	if(hero)
 	{
@@ -1057,17 +1055,14 @@ void CCreaInfo::hover(bool on)
 	}
 }
 
-void CCreaInfo::clickLeft(tribool down, bool previousState)
+void CCreaInfo::clickPressed(const Point & cursorPosition)
 {
-	if(previousState && (!down))
+	int offset = LOCPLINT->castleInt? (-87) : 0;
+	auto recruitCb = [=](CreatureID id, int count)
 	{
-		int offset = LOCPLINT->castleInt? (-87) : 0;
-		auto recruitCb = [=](CreatureID id, int count)
-		{
-			LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, level);
-		};
-		GH.windows().createAndPushWindow<CRecruitmentWindow>(town, level, town, recruitCb, offset);
-	}
+		LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, level);
+	};
+	GH.windows().createAndPushWindow<CRecruitmentWindow>(town, level, town, recruitCb, offset);
 }
 
 std::string CCreaInfo::genGrowthText()
@@ -1081,7 +1076,7 @@ std::string CCreaInfo::genGrowthText()
 	return descr;
 }
 
-void CCreaInfo::showPopupWindow()
+void CCreaInfo::showPopupWindow(const Point & cursorPosition)
 {
 	if (showAvailable)
 		GH.windows().createAndPushWindow<CDwellingInfoBox>(GH.screenDimensions().x / 2, GH.screenDimensions().y / 2, town, level);
@@ -1133,7 +1128,7 @@ void CTownInfo::hover(bool on)
 	}
 }
 
-void CTownInfo::showPopupWindow()
+void CTownInfo::showPopupWindow(const Point & cursorPosition)
 {
 	if(building)
 	{
@@ -1379,13 +1374,12 @@ void CHallInterface::CBuildingBox::hover(bool on)
 	}
 }
 
-void CHallInterface::CBuildingBox::clickLeft(tribool down, bool previousState)
+void CHallInterface::CBuildingBox::clickPressed(const Point & cursorPosition)
 {
-	if(previousState && (!down))
-		GH.windows().createAndPushWindow<CBuildWindow>(town,building,state,0);
+	GH.windows().createAndPushWindow<CBuildWindow>(town,building,state,0);
 }
 
-void CHallInterface::CBuildingBox::showPopupWindow()
+void CHallInterface::CBuildingBox::showPopupWindow(const Point & cursorPosition)
 {
 	GH.windows().createAndPushWindow<CBuildWindow>(town,building,state,1);
 }
@@ -1740,10 +1734,9 @@ void CFortScreen::RecruitArea::creaturesChangedEventHandler()
 	}
 }
 
-void CFortScreen::RecruitArea::clickLeft(tribool down, bool previousState)
+void CFortScreen::RecruitArea::clickPressed(const Point & cursorPosition)
 {
-	if(!down && previousState)
-		LOCPLINT->castleInt->builds->enterDwelling(level);
+	LOCPLINT->castleInt->builds->enterDwelling(level);
 }
 
 CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner,std::string imagem)
@@ -1796,13 +1789,12 @@ CMageGuildScreen::Scroll::Scroll(Point position, const CSpell *Spell)
 	pos = image->pos;
 }
 
-void CMageGuildScreen::Scroll::clickLeft(tribool down, bool previousState)
+void CMageGuildScreen::Scroll::clickPressed(const Point & cursorPosition)
 {
-	if(down)
-		LOCPLINT->showInfoDialog(spell->getDescriptionTranslated(0), std::make_shared<CComponent>(CComponent::spell, spell->id));
+	LOCPLINT->showInfoDialog(spell->getDescriptionTranslated(0), std::make_shared<CComponent>(CComponent::spell, spell->id));
 }
 
-void CMageGuildScreen::Scroll::showPopupWindow()
+void CMageGuildScreen::Scroll::showPopupWindow(const Point & cursorPosition)
 {
 	CRClickPopup::createAndPush(spell->getDescriptionTranslated(0), std::make_shared<CComponent>(CComponent::spell, spell->id));
 }

+ 12 - 12
client/windows/CCastleInterface.h

@@ -66,8 +66,8 @@ public:
 	CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, const CStructure *Str);
 	bool operator<(const CBuildingRect & p2) const;
 	void hover(bool on) override;
-	void clickLeft(tribool down, bool previousState) override;
-	void showPopupWindow() override;
+	void clickPressed(const Point & cursorPosition) override;
+	void showPopupWindow(const Point & cursorPosition) override;
 	void mouseMoved (const Point & cursorPosition, const Point & lastUpdateDistance) override;
 	bool receiveEvent(const Point & position, int eventType) const override;
 	void tick(uint32_t msPassed) override;
@@ -112,8 +112,8 @@ public:
 	void set(const CGHeroInstance * newHero);
 
 	void hover (bool on) override;
-	void clickLeft(tribool down, bool previousState) override;
-	void showPopupWindow() override;
+	void clickPressed(const Point & cursorPosition) override;
+	void showPopupWindow(const Point & cursorPosition) override;
 	void deactivate() override;
 };
 
@@ -192,8 +192,8 @@ public:
 
 	void update();
 	void hover(bool on) override;
-	void clickLeft(tribool down, bool previousState) override;
-	void showPopupWindow() override;
+	void clickPressed(const Point & cursorPosition) override;
+	void showPopupWindow(const Point & cursorPosition) override;
 	bool getShowAvailable();
 };
 
@@ -208,7 +208,7 @@ public:
 	CTownInfo(int posX, int posY, const CGTownInstance * town, bool townHall);
 
 	void hover(bool on) override;
-	void showPopupWindow() override;
+	void showPopupWindow(const Point & cursorPosition) override;
 };
 
 /// Class which manages the castle window
@@ -274,8 +274,8 @@ class CHallInterface : public CStatusbarWindow
 	public:
 		CBuildingBox(int x, int y, const CGTownInstance * Town, const CBuilding * Building);
 		void hover(bool on) override;
-		void clickLeft(tribool down, bool previousState) override;
-		void showPopupWindow() override;
+		void clickPressed(const Point & cursorPosition) override;
+		void showPopupWindow(const Point & cursorPosition) override;
 	};
 	const CGTownInstance * town;
 
@@ -346,7 +346,7 @@ class CFortScreen : public CStatusbarWindow
 
 		void creaturesChangedEventHandler();
 		void hover(bool on) override;
-		void clickLeft(tribool down, bool previousState) override;
+		void clickPressed(const Point & cursorPosition) override;
 	};
 	std::shared_ptr<CLabel> title;
 	std::vector<std::shared_ptr<RecruitArea>> recAreas;
@@ -371,8 +371,8 @@ class CMageGuildScreen : public CStatusbarWindow
 
 	public:
 		Scroll(Point position, const CSpell *Spell);
-		void clickLeft(tribool down, bool previousState) override;
-		void showPopupWindow() override;
+		void clickPressed(const Point & cursorPosition) override;
+		void showPopupWindow(const Point & cursorPosition) override;
 		void hover(bool on) override;
 	};
 	std::shared_ptr<CPicture> window;

+ 2 - 3
client/windows/CCreatureWindow.cpp

@@ -114,10 +114,9 @@ void CCommanderSkillIcon::setObject(std::shared_ptr<CIntObject> newObject)
 	redraw();
 }
 
-void CCommanderSkillIcon::clickLeft(tribool down, bool previousState)
+void CCommanderSkillIcon::clickPressed(const Point & cursorPosition)
 {
-	if(down)
-		callback();
+	callback();
 }
 
 static std::string skillToFile(int skill, int level, bool selected)

+ 1 - 1
client/windows/CCreatureWindow.h

@@ -37,7 +37,7 @@ public:
 
 	std::function<void()> callback;
 
-	void clickLeft(tribool down, bool previousState) override;
+	void clickPressed(const Point & cursorPosition) override;
 
 	void setObject(std::shared_ptr<CIntObject> object);
 };

+ 10 - 13
client/windows/CHeroWindow.cpp

@@ -85,21 +85,18 @@ CHeroWithMaybePickedArtifact::CHeroWithMaybePickedArtifact(CWindowWithArtifacts
 {
 }
 
-void CHeroSwitcher::clickLeft(tribool down, bool previousState)
+void CHeroSwitcher::clickPressed(const Point & cursorPosition)
 {
-	if(!down)
+	//TODO: do not recreate window
+	if (false)
 	{
-		//TODO: do not recreate window
-		if (false)
-		{
-			owner->update(hero, true);
-		}
-		else
-		{
-			const CGHeroInstance * buf = hero;
-			GH.windows().popWindows(1);
-			GH.windows().createAndPushWindow<CHeroWindow>(buf);
-		}
+		owner->update(hero, true);
+	}
+	else
+	{
+		const CGHeroInstance * buf = hero;
+		GH.windows().popWindows(1);
+		GH.windows().createAndPushWindow<CHeroWindow>(buf);
 	}
 }
 

+ 2 - 2
client/windows/CHeroWindow.h

@@ -41,7 +41,7 @@ class CHeroSwitcher : public CIntObject
 	std::shared_ptr<CAnimImage> image;
 	CHeroWindow * owner;
 public:
-	void clickLeft(tribool down, bool previousState) override;
+	void clickPressed(const Point & cursorPosition) override;
 
 	CHeroSwitcher(CHeroWindow * owner_, Point pos_, const CGHeroInstance * hero_);
 };
@@ -127,6 +127,6 @@ public:
 	void updateGarrisons() override;
 
 	//friends
-	friend void CHeroArtPlace::clickLeft(tribool down, bool previousState);
+	friend void CHeroArtPlace::clickPressed(const Point & cursorPosition);
 	friend class CPlayerInterface;
 };

+ 7 - 18
client/windows/CKingdomInterface.cpp

@@ -90,7 +90,7 @@ InfoBox::InfoBox(Point position, InfoPos Pos, InfoSize Size, std::shared_ptr<IIn
 
 InfoBox::~InfoBox() = default;
 
-void InfoBox::showPopupWindow()
+void InfoBox::showPopupWindow(const Point & cursorPosition)
 {
 	std::shared_ptr<CComponent> comp;
 	std::string text;
@@ -101,26 +101,15 @@ void InfoBox::showPopupWindow()
 		CRClickPopup::createAndPush(text);
 }
 
-void InfoBox::clickLeft(tribool down, bool previousState)
-{
-	if((!down) && previousState)
-	{
-		std::shared_ptr<CComponent> comp;
-		std::string text;
-		data->prepareMessage(text, comp);
-
-		if(comp)
-			LOCPLINT->showInfoDialog(text, CInfoWindow::TCompsInfo(1, comp));
-	}
-}
-
-//TODO?
-/*
-void InfoBox::update()
+void InfoBox::clickPressed(const Point & cursorPosition)
 {
+	std::shared_ptr<CComponent> comp;
+	std::string text;
+	data->prepareMessage(text, comp);
 
+	if(comp)
+		LOCPLINT->showInfoDialog(text, CInfoWindow::TCompsInfo(1, comp));
 }
-*/
 
 IInfoBoxData::IInfoBoxData(InfoType Type)
 	: type(Type)

+ 2 - 5
client/windows/CKingdomInterface.h

@@ -73,11 +73,8 @@ public:
 	InfoBox(Point position, InfoPos Pos, InfoSize Size, std::shared_ptr<IInfoBoxData> Data);
 	~InfoBox();
 
-	void showPopupWindow() override;
-	void clickLeft(tribool down, bool previousState) override;
-
-	//Update object if data may have changed
-	//void update();
+	void showPopupWindow(const Point & cursorPosition) override;
+	void clickPressed(const Point & cursorPosition) override;
 };
 
 class IInfoBoxData

+ 4 - 6
client/windows/CQuestLog.cpp

@@ -39,10 +39,9 @@ VCMI_LIB_NAMESPACE_END
 
 class CAdvmapInterface;
 
-void CQuestLabel::clickLeft(tribool down, bool previousState)
+void CQuestLabel::clickPressed(const Point & cursorPosition)
 {
-	if (down)
-		callback();
+	callback();
 }
 
 void CQuestLabel::showAll(Canvas & to)
@@ -56,10 +55,9 @@ CQuestIcon::CQuestIcon (const std::string &defname, int index, int x, int y) :
 	addUsedEvents(LCLICK);
 }
 
-void CQuestIcon::clickLeft(tribool down, bool previousState)
+void CQuestIcon::clickPressed(const Point & cursorPosition)
 {
-	if (down)
-		callback();
+	callback();
 }
 
 void CQuestIcon::showAll(Canvas & to)

+ 3 - 3
client/windows/CQuestLog.h

@@ -45,7 +45,7 @@ public:
 
 	CQuestLabel(Rect position, EFonts Font = FONT_SMALL, ETextAlignment Align = ETextAlignment::TOPLEFT, const SDL_Color &Color = Colors::WHITE, const std::string &Text =  "")
 		: CMultiLineLabel (position, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE, Text){};
-	void clickLeft(tribool down, bool previousState) override;
+	void clickPressed(const Point & cursorPosition) override;
 	void showAll(Canvas & to) override;
 };
 
@@ -56,7 +56,7 @@ public:
 
 	CQuestIcon(const std::string &defname, int index, int x=0, int y=0);
 
-	void clickLeft(tribool down, bool previousState) override;
+	void clickPressed(const Point & cursorPosition) override;
 	void showAll(Canvas & to) override;
 };
 
@@ -64,7 +64,7 @@ class CQuestMinimap : public CMinimap
 {
 	std::vector<std::shared_ptr<CQuestIcon>> icons;
 
-	void clickLeft(tribool down, bool previousState) override{}; //minimap ignores clicking on its surface
+	void clickPressed(const Point & cursorPosition) override{}; //minimap ignores clicking on its surface
 	void iconClicked();
 	void mouseDragged(const Point & cursorPosition, const Point & lastUpdateDistance) override{};
 

+ 6 - 7
client/windows/CSpellWindow.cpp

@@ -51,13 +51,12 @@ CSpellWindow::InteractiveArea::InteractiveArea(const Rect & myRect, std::functio
 	owner = _owner;
 }
 
-void CSpellWindow::InteractiveArea::clickLeft(tribool down, bool previousState)
+void CSpellWindow::InteractiveArea::clickPressed(const Point & cursorPosition)
 {
-	if(!down)
-		onLeft();
+	onLeft();
 }
 
-void CSpellWindow::InteractiveArea::showPopupWindow()
+void CSpellWindow::InteractiveArea::showPopupWindow(const Point & cursorPosition)
 {
 	CRClickPopup::createAndPush(helpText);
 }
@@ -472,9 +471,9 @@ CSpellWindow::SpellArea::SpellArea(Rect pos, CSpellWindow * owner)
 
 CSpellWindow::SpellArea::~SpellArea() = default;
 
-void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
+void CSpellWindow::SpellArea::clickPressed(const Point & cursorPosition)
 {
-	if(mySpell && !down)
+	if(mySpell)
 	{
 		auto spellCost = owner->myInt->cb->getSpellCost(mySpell, owner->myHero);
 		if(spellCost > owner->myHero->mana) //insufficient mana
@@ -540,7 +539,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
 	}
 }
 
-void CSpellWindow::SpellArea::showPopupWindow()
+void CSpellWindow::SpellArea::showPopupWindow(const Point & cursorPosition)
 {
 	if(mySpell)
 	{

+ 4 - 4
client/windows/CSpellWindow.h

@@ -44,8 +44,8 @@ class CSpellWindow : public CWindowObject
 		~SpellArea();
 		void setSpell(const CSpell * spell);
 
-		void clickLeft(tribool down, bool previousState) override;
-		void showPopupWindow() override;
+		void clickPressed(const Point & cursorPosition) override;
+		void showPopupWindow(const Point & cursorPosition) override;
 		void hover(bool on) override;
 	};
 
@@ -57,8 +57,8 @@ class CSpellWindow : public CWindowObject
 		std::string hoverText;
 		std::string helpText;
 	public:
-		void clickLeft(tribool down, bool previousState) override;
-		void showPopupWindow() override;
+		void clickPressed(const Point & cursorPosition) override;
+		void showPopupWindow(const Point & cursorPosition) override;
 		void hover(bool on) override;
 
 		InteractiveArea(const Rect &myRect, std::function<void()> funcL, int helpTextId, CSpellWindow * _owner);

+ 2 - 6
client/windows/CTradeWindow.cpp

@@ -171,13 +171,10 @@ void CTradeWindow::CTradeableItem::showAll(Canvas & to)
 	to.drawText(pos.topLeft() + posToSubCenter, FONT_SMALL, Colors::WHITE, ETextAlignment::CENTER, subtitle);
 }
 
-void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
+void CTradeWindow::CTradeableItem::clickPressed(const Point & cursorPosition)
 {
 	CTradeWindow *mw = dynamic_cast<CTradeWindow *>(parent);
 	assert(mw);
-	if(down)
-	{
-
 		if(type == ARTIFACT_PLACEHOLDER)
 		{
 			CAltarWindow *aw = static_cast<CAltarWindow *>(mw);
@@ -221,7 +218,6 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
 				return;
 		}
 		mw->selectionChanged(left);
-	}
 }
 
 void CTradeWindow::CTradeableItem::showAllAt(const Point &dstPos, const std::string &customSub, Canvas & to)
@@ -262,7 +258,7 @@ void CTradeWindow::CTradeableItem::hover(bool on)
 	}
 }
 
-void CTradeWindow::CTradeableItem::showPopupWindow()
+void CTradeWindow::CTradeableItem::showPopupWindow(const Point & cursorPosition)
 {
 	switch(type)
 	{

+ 2 - 2
client/windows/CTradeWindow.h

@@ -56,10 +56,10 @@ public:
 
 		void showAllAt(const Point & dstPos, const std::string & customSub, Canvas & to);
 
-		void showPopupWindow() override;
+		void showPopupWindow(const Point & cursorPosition) override;
 		void hover(bool on) override;
 		void showAll(Canvas & to) override;
-		void clickLeft(tribool down, bool previousState) override;
+		void clickPressed(const Point & cursorPosition) override;
 		std::string getName(int number = -1) const;
 		CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial);
 	};

+ 1 - 1
client/windows/CreaturePurchaseCard.cpp

@@ -123,7 +123,7 @@ CreaturePurchaseCard::CCreatureClickArea::CCreatureClickArea(const Point & posit
 	pos.h = CREATURE_HEIGHT;
 }
 
-void CreaturePurchaseCard::CCreatureClickArea::showPopupWindow()
+void CreaturePurchaseCard::CCreatureClickArea::showPopupWindow(const Point & cursorPosition)
 {
 	GH.windows().createAndPushWindow<CStackWindow>(creatureOnTheCard, true);
 }

+ 1 - 1
client/windows/CreaturePurchaseCard.h

@@ -49,7 +49,7 @@ private:
 	{
 	public:
 		CCreatureClickArea(const Point & pos, const std::shared_ptr<CCreaturePic> creaturePic, const CCreature * creatureOnTheCard);
-		void showPopupWindow() override;
+		void showPopupWindow(const Point & cursorPosition) override;
 		const CCreature * creatureOnTheCard;
 
 		// These are obtained by guessing and checking. I'm not sure how the other numbers

+ 16 - 24
client/windows/GUIClasses.cpp

@@ -96,13 +96,12 @@ void CRecruitmentWindow::CCreatureCard::select(bool on)
 	redraw();
 }
 
-void CRecruitmentWindow::CCreatureCard::clickLeft(tribool down, bool previousState)
+void CRecruitmentWindow::CCreatureCard::clickPressed(const Point & cursorPosition)
 {
-	if(down)
-		parent->select(this->shared_from_this());
+	parent->select(this->shared_from_this());
 }
 
-void CRecruitmentWindow::CCreatureCard::showPopupWindow()
+void CRecruitmentWindow::CCreatureCard::showPopupWindow(const Point & cursorPosition)
 {
 	GH.windows().createAndPushWindow<CStackWindow>(creature, true);
 }
@@ -552,13 +551,13 @@ void CTavernWindow::show(Canvas & to)
 	CCS->videoh->update(pos.x+70, pos.y+56, to.getInternalSurface(), true, false);
 }
 
-void CTavernWindow::HeroPortrait::clickLeft(tribool down, bool previousState)
+void CTavernWindow::HeroPortrait::clickPressed(const Point & cursorPosition)
 {
-	if(h && previousState && !down)
+	if(h)
 		*_sel = _id;
 }
 
-void CTavernWindow::HeroPortrait::showPopupWindow()
+void CTavernWindow::HeroPortrait::showPopupWindow(const Point & cursorPosition)
 {
 	if(h)
 		GH.windows().createAndPushWindow<CRClickPopupInt>(std::make_shared<CHeroWindow>(h));
@@ -1150,13 +1149,10 @@ void CTransformerWindow::CItem::move()
 	left = !left;
 }
 
-void CTransformerWindow::CItem::clickLeft(tribool down, bool previousState)
+void CTransformerWindow::CItem::clickPressed(const Point & cursorPosition)
 {
-	if(previousState && (!down))
-	{
-		move();
-		parent->redraw();
-	}
+	move();
+	parent->redraw();
 }
 
 void CTransformerWindow::CItem::update()
@@ -1258,16 +1254,13 @@ CUniversityWindow::CItem::CItem(CUniversityWindow * _parent, int _ID, int X, int
 	pos.w = icon->pos.w;
 }
 
-void CUniversityWindow::CItem::clickLeft(tribool down, bool previousState)
+void CUniversityWindow::CItem::clickPressed(const Point & cursorPosition)
 {
-	if(previousState && (!down))
-	{
-		if(state() == 2)
-			GH.windows().createAndPushWindow<CUnivConfirmWindow>(parent, ID, LOCPLINT->cb->getResourceAmount(EGameResID::GOLD) >= 2000);
-	}
+	if(state() == 2)
+		GH.windows().createAndPushWindow<CUnivConfirmWindow>(parent, ID, LOCPLINT->cb->getResourceAmount(EGameResID::GOLD) >= 2000);
 }
 
-void CUniversityWindow::CItem::showPopupWindow()
+void CUniversityWindow::CItem::showPopupWindow(const Point & cursorPosition)
 {
 	CRClickPopup::createAndPush(CGI->skillh->getByIndex(ID)->getDescriptionTranslated(1), std::make_shared<CComponent>(CComponent::secskill, ID, 1));
 }
@@ -1792,13 +1785,12 @@ void CObjectListWindow::CItem::select(bool on)
 	redraw();//???
 }
 
-void CObjectListWindow::CItem::clickLeft(tribool down, bool previousState)
+void CObjectListWindow::CItem::clickPressed(const Point & cursorPosition)
 {
-	if( previousState && !down)
-		parent->changeSelection(index);
+	parent->changeSelection(index);
 }
 
-void CObjectListWindow::CItem::clickDouble()
+void CObjectListWindow::CItem::clickDouble(const Point & cursorPosition)
 {
 	parent->elementSelected();
 }

+ 9 - 9
client/windows/GUIClasses.h

@@ -59,8 +59,8 @@ class CRecruitmentWindow : public CStatusbarWindow
 
 		CCreatureCard(CRecruitmentWindow * window, const CCreature * crea, int totalAmount);
 
-		void clickLeft(tribool down, bool previousState) override;
-		void showPopupWindow() override;
+		void clickPressed(const Point & cursorPosition) override;
+		void showPopupWindow(const Point & cursorPosition) override;
 		void showAll(Canvas & to) override;
 	};
 
@@ -161,8 +161,8 @@ class CObjectListWindow : public CWindowObject
 		CItem(CObjectListWindow * parent, size_t id, std::string text);
 
 		void select(bool on);
-		void clickLeft(tribool down, bool previousState) override;
-		void clickDouble() override;
+		void clickPressed(const Point & cursorPosition) override;
+		void clickDouble(const Point & cursorPosition) override;
 	};
 
 	std::function<void(int)> onSelect;//called when OK button is pressed, returns id of selected item.
@@ -205,8 +205,8 @@ public:
 		std::string description; // "XXX is a level Y ZZZ with N artifacts"
 		const CGHeroInstance * h;
 
-		void clickLeft(tribool down, bool previousState) override;
-		void showPopupWindow() override;
+		void clickPressed(const Point & cursorPosition) override;
+		void showPopupWindow(const Point & cursorPosition) override;
 		void hover (bool on) override;
 		HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H);
 
@@ -376,7 +376,7 @@ class CTransformerWindow : public CStatusbarWindow, public CGarrisonHolder
 		std::shared_ptr<CLabel> count;
 
 		void move();
-		void clickLeft(tribool down, bool previousState) override;
+		void clickPressed(const Point & cursorPosition) override;
 		void update();
 		CItem(CTransformerWindow * parent, int size, int id);
 	};
@@ -417,8 +417,8 @@ class CUniversityWindow : public CStatusbarWindow
 		CUniversityWindow * parent;
 
 		void showAll(Canvas & to) override;
-		void clickLeft(tribool down, bool previousState) override;
-		void showPopupWindow() override;
+		void clickPressed(const Point & cursorPosition) override;
+		void showPopupWindow(const Point & cursorPosition) override;
 		void hover(bool on) override;
 		int state();//0=can't learn, 1=learned, 2=can learn
 		CItem(CUniversityWindow * _parent, int _ID, int X, int Y);