forked from 0ad/0ad
Implement keyDown event
Change HotkeyPress event to be non-repeating (HotkeyDown to replace the repeating case) Fix shiftlag Make toggle hotkeys only respond to the first SDL event. Many iterations of review by: elexis Test done by: Imarok Comments By: vladislav, Stan Reviewed By: wraitii Fixes: #5055 Differential Revision: https://code.wildfiregames.com/D1398 This was SVN commit r23701.
This commit is contained in:
parent
892f97743b
commit
5cfce692e7
@ -12,7 +12,7 @@ class OverlayCounter
|
||||
registerConfigChangeHandler(this.onConfigChange.bind(this));
|
||||
|
||||
if (this.Hotkey)
|
||||
Engine.SetGlobalHotkey(this.Hotkey, this.toggle.bind(this));
|
||||
Engine.SetGlobalHotkey(this.Hotkey, "Press", this.toggle.bind(this));
|
||||
}
|
||||
|
||||
onConfigChange(changes)
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<object>
|
||||
<object hotkey="tab.next">
|
||||
<action on="Press">selectNextTab(1);</action>
|
||||
<action on="KeyDown">selectNextTab(1);</action>
|
||||
</object>
|
||||
|
||||
<object hotkey="tab.prev">
|
||||
<action on="Press">selectNextTab(-1);</action>
|
||||
<action on="KeyDown">selectNextTab(-1);</action>
|
||||
</object>
|
||||
|
||||
<object name="tabButtons" type="image">
|
||||
|
@ -15,8 +15,8 @@ class CivInfoButton
|
||||
"hotkey_structree": colorizeHotkey("%(hotkey)s", "structree")
|
||||
});
|
||||
|
||||
Engine.SetGlobalHotkey("structree", this.openPage.bind(this, "page_structree.xml"));
|
||||
Engine.SetGlobalHotkey("civinfo", this.openPage.bind(this, "page_civinfo.xml"));
|
||||
Engine.SetGlobalHotkey("structree", "Press", this.openPage.bind(this, "page_structree.xml"));
|
||||
Engine.SetGlobalHotkey("civinfo", "Press", this.openPage.bind(this, "page_civinfo.xml"));
|
||||
}
|
||||
|
||||
onPress()
|
||||
|
@ -16,7 +16,7 @@ class GameSettingTabs
|
||||
colorizeHotkey("\n" + this.HotkeyUpTooltip, this.ConfigNameHotkeyUp);
|
||||
|
||||
setupWindow.registerLoadHandler(this.onLoad.bind(this));
|
||||
Engine.SetGlobalHotkey("cancel", selectPanel);
|
||||
Engine.SetGlobalHotkey("cancel", "Press", selectPanel);
|
||||
}
|
||||
|
||||
registerTabsResizeHandler(handler)
|
||||
|
@ -29,7 +29,7 @@ class LeaderboardPage
|
||||
openPage()
|
||||
{
|
||||
this.leaderboardPage.hidden = false;
|
||||
Engine.SetGlobalHotkey("cancel", this.onPressClose.bind(this));
|
||||
Engine.SetGlobalHotkey("cancel", "Press", this.onPressClose.bind(this));
|
||||
Engine.SendGetBoardList();
|
||||
|
||||
let playerName = this.leaderboardList.selectedPlayer();
|
||||
|
@ -17,10 +17,10 @@ class QuitButton
|
||||
|
||||
if (dialog)
|
||||
{
|
||||
Engine.SetGlobalHotkey("lobby", onPress);
|
||||
Engine.SetGlobalHotkey("cancel", onPress);
|
||||
Engine.SetGlobalHotkey("lobby", "Press", onPress);
|
||||
Engine.SetGlobalHotkey("cancel", "Press", onPress);
|
||||
|
||||
let cancelHotkey = Engine.SetGlobalHotkey.bind(Engine, "cancel", onPress);
|
||||
let cancelHotkey = Engine.SetGlobalHotkey.bind(Engine, "cancel", "Press", onPress);
|
||||
leaderboardPage.registerClosePageHandler(cancelHotkey);
|
||||
profilePage.registerClosePageHandler(cancelHotkey);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class ProfilePage
|
||||
openPage()
|
||||
{
|
||||
this.profilePage.hidden = false;
|
||||
Engine.SetGlobalHotkey("cancel", this.onPressClose.bind(this));
|
||||
Engine.SetGlobalHotkey("cancel", "Press", this.onPressClose.bind(this));
|
||||
}
|
||||
|
||||
onPressLookup()
|
||||
|
@ -85,7 +85,7 @@ class MainMenuItemHandler
|
||||
{
|
||||
let item = menuItems[i];
|
||||
if (item.onPress && item.hotkey)
|
||||
Engine.SetGlobalHotkey(item.hotkey, () => {
|
||||
Engine.SetGlobalHotkey(item.hotkey, "Press", () => {
|
||||
this.closeSubmenu();
|
||||
item.onPress();
|
||||
});
|
||||
|
@ -12,7 +12,7 @@ class RangeOverlayManager
|
||||
for (let type of this.Types)
|
||||
{
|
||||
this.setEnabled(type, this.isEnabled(type));
|
||||
Engine.SetGlobalHotkey(type.hotkey, this.toggle.bind(this, type));
|
||||
Engine.SetGlobalHotkey(type.hotkey, "Press", this.toggle.bind(this, type));
|
||||
}
|
||||
|
||||
registerConfigChangeHandler(this.onConfigChange.bind(this));
|
||||
|
@ -40,9 +40,9 @@ class Chat
|
||||
registerPlayerAssignmentsChangeHandler(updater);
|
||||
playerViewControl.registerViewedPlayerChangeHandler(updater);
|
||||
|
||||
Engine.SetGlobalHotkey("chat", this.openPage.bind(this));
|
||||
Engine.SetGlobalHotkey("privatechat", this.openPage.bind(this));
|
||||
Engine.SetGlobalHotkey("teamchat", () => { this.openPage(g_IsObserver ? "/observers" : "/allies"); });
|
||||
Engine.SetGlobalHotkey("chat", "Press", this.openPage.bind(this));
|
||||
Engine.SetGlobalHotkey("privatechat", "Press", this.openPage.bind(this));
|
||||
Engine.SetGlobalHotkey("teamchat", "Press", () => { this.openPage(g_IsObserver ? "/observers" : "/allies"); });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,7 +81,7 @@ class Chat
|
||||
submitChat(text, command = "")
|
||||
{
|
||||
if (command.startsWith("/msg "))
|
||||
Engine.SetGlobalHotkey("privatechat", () => { this.openPage(command); });
|
||||
Engine.SetGlobalHotkey("privatechat", "Press", () => { this.openPage(command); });
|
||||
|
||||
let msg = command ? command + " " + text : text;
|
||||
|
||||
|
@ -32,19 +32,19 @@
|
||||
</object>
|
||||
|
||||
<object hotkey="session.kill">
|
||||
<action on="Press">performCommand(g_Selection.toList().map(ent => GetEntityState(ent)), "delete");</action>
|
||||
<action on="KeyDown">performCommand(g_Selection.toList().map(ent => GetEntityState(ent)), "delete");</action>
|
||||
</object>
|
||||
|
||||
<object hotkey="session.unload">
|
||||
<action on="Press">unloadAll();</action>
|
||||
<action on="KeyDown">unloadAll();</action>
|
||||
</object>
|
||||
|
||||
<object hotkey="session.stop">
|
||||
<action on="Press">stopUnits(g_Selection.toList());</action>
|
||||
<action on="KeyDown">stopUnits(g_Selection.toList());</action>
|
||||
</object>
|
||||
|
||||
<object hotkey="session.backtowork">
|
||||
<action on="Press">backToWork();</action>
|
||||
<action on="KeyDown">backToWork();</action>
|
||||
</object>
|
||||
|
||||
<object hotkey="session.batchtrain">
|
||||
@ -54,15 +54,15 @@
|
||||
|
||||
<!-- Find idle warrior - TODO: Potentially move this to own UI button? -->
|
||||
<object hotkey="selection.idlewarrior">
|
||||
<action on="Press">findIdleUnit(g_MilitaryTypes);</action>
|
||||
<action on="KeyDown">findIdleUnit(g_MilitaryTypes);</action>
|
||||
</object>
|
||||
|
||||
<object hotkey="selection.idleunit">
|
||||
<action on="Press">findIdleUnit(["!Domestic"]);</action>
|
||||
<action on="KeyDown">findIdleUnit(["!Domestic"]);</action>
|
||||
</object>
|
||||
|
||||
<object hotkey="selection.cancel">
|
||||
<action on="Press">clearSelection();</action>
|
||||
<action on="KeyDown">clearSelection();</action>
|
||||
</object>
|
||||
|
||||
<object hotkey="session.showstatusbars">
|
||||
|
@ -2,36 +2,36 @@
|
||||
<object>
|
||||
<!-- queue first unit in the training queue -->
|
||||
<object hotkey="session.queueunit.1">
|
||||
<action on="Press">addTrainingByPosition(0);</action>
|
||||
<action on="KeyDown">addTrainingByPosition(0);</action>
|
||||
</object>
|
||||
|
||||
<!-- queue 2nd unit in the training queue -->
|
||||
<object hotkey="session.queueunit.2">
|
||||
<action on="Press">addTrainingByPosition(1);</action>
|
||||
<action on="KeyDown">addTrainingByPosition(1);</action>
|
||||
</object>
|
||||
|
||||
<!-- queue 3rd unit in the training queue -->
|
||||
<object hotkey="session.queueunit.3">
|
||||
<action on="Press">addTrainingByPosition(2);</action>
|
||||
<action on="KeyDown">addTrainingByPosition(2);</action>
|
||||
</object>
|
||||
|
||||
<!-- queue 4th unit in the training queue -->
|
||||
<object hotkey="session.queueunit.4">
|
||||
<action on="Press">addTrainingByPosition(3);</action>
|
||||
<action on="KeyDown">addTrainingByPosition(3);</action>
|
||||
</object>
|
||||
|
||||
<!-- queue 5th unit in the training queue -->
|
||||
<object hotkey="session.queueunit.5">
|
||||
<action on="Press">addTrainingByPosition(4);</action>
|
||||
<action on="KeyDown">addTrainingByPosition(4);</action>
|
||||
</object>
|
||||
|
||||
<!-- queue 6th unit in the training queue -->
|
||||
<object hotkey="session.queueunit.6">
|
||||
<action on="Press">addTrainingByPosition(5);</action>
|
||||
<action on="KeyDown">addTrainingByPosition(5);</action>
|
||||
</object>
|
||||
|
||||
<!-- queue 7th unit in the training queue -->
|
||||
<object hotkey="session.queueunit.7">
|
||||
<action on="Press">addTrainingByPosition(6);</action>
|
||||
<action on="KeyDown">addTrainingByPosition(6);</action>
|
||||
</object>
|
||||
</object>
|
||||
|
@ -6,7 +6,8 @@ class MiniMapIdleWorkerButton
|
||||
constructor(playerViewControl, idleClasses)
|
||||
{
|
||||
this.idleWorkerButton = Engine.GetGUIObjectByName("idleWorkerButton");
|
||||
this.idleWorkerButton.onPress = this.onPress.bind(this);
|
||||
this.idleWorkerButton.onKeyDown = this.onKeyDown.bind(this);
|
||||
this.idleWorkerButton.onMouseLeftPress = this.onKeyDown.bind(this);
|
||||
this.idleClasses = idleClasses;
|
||||
|
||||
registerHotkeyChangeHandler(this.onHotkeyChange.bind(this));
|
||||
@ -30,7 +31,7 @@ class MiniMapIdleWorkerButton
|
||||
});
|
||||
}
|
||||
|
||||
onPress()
|
||||
onKeyDown()
|
||||
{
|
||||
findIdleUnit(this.idleClasses);
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ class CivIcon
|
||||
playerViewControl.registerViewedPlayerChangeHandler(this.rebuild.bind(this));
|
||||
registerHotkeyChangeHandler(this.rebuild.bind(this));
|
||||
|
||||
Engine.SetGlobalHotkey("civinfo", () => this.openPage("page_civinfo.xml"));
|
||||
Engine.SetGlobalHotkey("structree", () => this.openPage("page_structree.xml"));
|
||||
Engine.SetGlobalHotkey("structree", "Press", this.openPage.bind(this, "page_structree.xml"));
|
||||
Engine.SetGlobalHotkey("civinfo", "Press", this.openPage.bind(this, "page_civinfo.xml"));
|
||||
}
|
||||
|
||||
onPress()
|
||||
|
@ -17,11 +17,11 @@
|
||||
</object>
|
||||
|
||||
<object hotkey="tab.next">
|
||||
<action on="Press">selectNextTab(1);</action>
|
||||
<action on="KeyDown">selectNextTab(1);</action>
|
||||
</object>
|
||||
|
||||
<object hotkey="tab.prev">
|
||||
<action on="Press">selectNextTab(-1);</action>
|
||||
<action on="KeyDown">selectNextTab(-1);</action>
|
||||
</object>
|
||||
|
||||
<object type="image" sprite="ModernFade" name="fadeImage"/>
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -640,7 +640,19 @@ InReaction CCameraController::HandleEvent(const SDL_Event_* ev)
|
||||
{
|
||||
switch (ev->ev.type)
|
||||
{
|
||||
case SDL_HOTKEYPRESS:
|
||||
{
|
||||
std::string hotkey = static_cast<const char*>(ev->ev.user.data1);
|
||||
if (hotkey == "camera.reset")
|
||||
{
|
||||
ResetCameraAngleZoom();
|
||||
return IN_HANDLED;
|
||||
}
|
||||
return IN_PASS;
|
||||
}
|
||||
|
||||
case SDL_HOTKEYDOWN:
|
||||
{
|
||||
std::string hotkey = static_cast<const char*>(ev->ev.user.data1);
|
||||
|
||||
// Mouse wheel must be treated using events instead of polling,
|
||||
@ -698,11 +710,8 @@ InReaction CCameraController::HandleEvent(const SDL_Event_* ev)
|
||||
m_ViewZoomSpeed /= m_ViewZoomSpeedModifier;
|
||||
return IN_HANDLED;
|
||||
}
|
||||
else if (hotkey == "camera.reset")
|
||||
{
|
||||
ResetCameraAngleZoom();
|
||||
return IN_HANDLED;
|
||||
}
|
||||
return IN_PASS;
|
||||
}
|
||||
}
|
||||
|
||||
return IN_PASS;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -378,10 +378,9 @@ InReaction CGameView::HandleEvent(const SDL_Event_* ev)
|
||||
{
|
||||
switch(ev->ev.type)
|
||||
{
|
||||
|
||||
case SDL_HOTKEYDOWN:
|
||||
case SDL_HOTKEYPRESS:
|
||||
{
|
||||
std::string hotkey = static_cast<const char*>(ev->ev.user.data1);
|
||||
|
||||
if (hotkey == "wireframe")
|
||||
{
|
||||
if (g_XmppClient && g_rankedGame == true)
|
||||
@ -407,6 +406,7 @@ InReaction CGameView::HandleEvent(const SDL_Event_* ev)
|
||||
return IN_HANDLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m->CameraController->HandleEvent(ev);
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ const u32 MAX_OBJECT_DEPTH = 100; // Max number of nesting for GUI includes. Use
|
||||
const CStr CGUI::EventNameLoad = "Load";
|
||||
const CStr CGUI::EventNameTick = "Tick";
|
||||
const CStr CGUI::EventNamePress = "Press";
|
||||
const CStr CGUI::EventNameKeyDown = "KeyDown";
|
||||
const CStr CGUI::EventNameRelease = "Release";
|
||||
const CStr CGUI::EventNameMouseRightPress = "MouseRightPress";
|
||||
const CStr CGUI::EventNameMouseLeftPress = "MouseLeftPress";
|
||||
@ -86,11 +87,13 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev)
|
||||
{
|
||||
InReaction ret = IN_PASS;
|
||||
|
||||
if (ev->ev.type == SDL_HOTKEYDOWN || ev->ev.type == SDL_HOTKEYUP)
|
||||
if (ev->ev.type == SDL_HOTKEYDOWN || ev->ev.type == SDL_HOTKEYPRESS || ev->ev.type == SDL_HOTKEYUP)
|
||||
{
|
||||
const char* hotkey = static_cast<const char*>(ev->ev.user.data1);
|
||||
|
||||
if (m_GlobalHotkeys.find(hotkey) != m_GlobalHotkeys.end() && ev->ev.type == SDL_HOTKEYDOWN)
|
||||
const CStr& eventName = ev->ev.type == SDL_HOTKEYPRESS ? EventNamePress : ev->ev.type == SDL_HOTKEYDOWN ? EventNameKeyDown : EventNameRelease;
|
||||
|
||||
if (m_GlobalHotkeys.find(hotkey) != m_GlobalHotkeys.end() && m_GlobalHotkeys[hotkey].find(eventName) != m_GlobalHotkeys[hotkey].end())
|
||||
{
|
||||
ret = IN_HANDLED;
|
||||
|
||||
@ -98,15 +101,17 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev)
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedObject globalObj(cx, &GetGlobalObject().toObject());
|
||||
JS::RootedValue result(cx);
|
||||
JS_CallFunctionValue(cx, globalObj, m_GlobalHotkeys[hotkey], JS::HandleValueArray::empty(), &result);
|
||||
JS_CallFunctionValue(cx, globalObj, m_GlobalHotkeys[hotkey][eventName], JS::HandleValueArray::empty(), &result);
|
||||
}
|
||||
|
||||
std::map<CStr, std::vector<IGUIObject*> >::iterator it = m_HotkeyObjects.find(hotkey);
|
||||
if (it != m_HotkeyObjects.end())
|
||||
for (IGUIObject* const& obj : it->second)
|
||||
{
|
||||
if (ev->ev.type == SDL_HOTKEYDOWN)
|
||||
if (ev->ev.type == SDL_HOTKEYPRESS)
|
||||
ret = obj->SendEvent(GUIM_PRESSED, EventNamePress);
|
||||
else if (ev->ev.type == SDL_HOTKEYDOWN)
|
||||
ret = obj->SendEvent(GUIM_KEYDOWN, EventNameKeyDown);
|
||||
else
|
||||
ret = obj->SendEvent(GUIM_RELEASED, EventNameRelease);
|
||||
}
|
||||
@ -400,7 +405,7 @@ void CGUI::UnsetObjectHotkey(IGUIObject* pObject, const CStr& hotkeyTag)
|
||||
assignment.end());
|
||||
}
|
||||
|
||||
void CGUI::SetGlobalHotkey(const CStr& hotkeyTag, JS::HandleValue function)
|
||||
void CGUI::SetGlobalHotkey(const CStr& hotkeyTag, const CStr& eventName, JS::HandleValue function)
|
||||
{
|
||||
JSContext* cx = m_ScriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
@ -411,19 +416,33 @@ void CGUI::SetGlobalHotkey(const CStr& hotkeyTag, JS::HandleValue function)
|
||||
return;
|
||||
}
|
||||
|
||||
// Only support "Press", "Keydown" and "Release" events.
|
||||
if (eventName != EventNamePress && eventName != EventNameKeyDown && eventName != EventNameRelease)
|
||||
{
|
||||
JS_ReportError(cx, "Cannot assign a function to an unsupported event!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!function.isObject() || !JS_ObjectIsFunction(cx, &function.toObject()))
|
||||
{
|
||||
JS_ReportError(cx, "Cannot assign non-function value to global hotkey '%s'", hotkeyTag.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
UnsetGlobalHotkey(hotkeyTag);
|
||||
m_GlobalHotkeys[hotkeyTag].init(cx, function);
|
||||
UnsetGlobalHotkey(hotkeyTag, eventName);
|
||||
m_GlobalHotkeys[hotkeyTag][eventName].init(cx, function);
|
||||
}
|
||||
|
||||
void CGUI::UnsetGlobalHotkey(const CStr& hotkeyTag)
|
||||
void CGUI::UnsetGlobalHotkey(const CStr& hotkeyTag, const CStr& eventName)
|
||||
{
|
||||
m_GlobalHotkeys.erase(hotkeyTag);
|
||||
std::map<CStr, std::map<CStr, JS::PersistentRootedValue>>::iterator it = m_GlobalHotkeys.find(hotkeyTag);
|
||||
if (it == m_GlobalHotkeys.end())
|
||||
return;
|
||||
|
||||
m_GlobalHotkeys[hotkeyTag].erase(eventName);
|
||||
|
||||
if (m_GlobalHotkeys.count(hotkeyTag) == 0)
|
||||
m_GlobalHotkeys.erase(it);
|
||||
}
|
||||
|
||||
const SGUIScrollBarStyle* CGUI::GetScrollBarStyle(const CStr& style) const
|
||||
|
@ -136,8 +136,8 @@ public:
|
||||
/**
|
||||
* Allows the JS side to add or remove global hotkeys.
|
||||
*/
|
||||
void SetGlobalHotkey(const CStr& hotkeyTag, JS::HandleValue function);
|
||||
void UnsetGlobalHotkey(const CStr& hotkeyTag);
|
||||
void SetGlobalHotkey(const CStr& hotkeyTag, const CStr& eventName, JS::HandleValue function);
|
||||
void UnsetGlobalHotkey(const CStr& hotkeyTag, const CStr& eventName);
|
||||
|
||||
/**
|
||||
* Return the object which is an ancestor of every other GUI object.
|
||||
@ -606,10 +606,11 @@ private:
|
||||
std::map<CStr, std::vector<IGUIObject*> > m_HotkeyObjects;
|
||||
|
||||
/**
|
||||
* Map from hotkey names to functions that are triggered if the hotkey is pressed.
|
||||
* Contrary to object hotkeys, this allows for only one global function per hotkey name.
|
||||
* Map from hotkey names to maps of eventNames to functions that are triggered
|
||||
* when the hotkey goes through the event. Contrary to object hotkeys, this
|
||||
* allows for only one global function per hotkey name per event type.
|
||||
*/
|
||||
std::map<CStr, JS::PersistentRootedValue> m_GlobalHotkeys;
|
||||
std::map<CStr, std::map<CStr, JS::PersistentRootedValue>> m_GlobalHotkeys;
|
||||
|
||||
/**
|
||||
* XML and JS can subscribe handlers to events identified by these names.
|
||||
@ -619,6 +620,7 @@ private:
|
||||
static const CStr EventNameLoad;
|
||||
static const CStr EventNameTick;
|
||||
static const CStr EventNamePress;
|
||||
static const CStr EventNameKeyDown;
|
||||
static const CStr EventNameRelease;
|
||||
static const CStr EventNameMouseRightPress;
|
||||
static const CStr EventNameMouseLeftPress;
|
||||
|
@ -43,6 +43,7 @@ enum EGUIMessageType
|
||||
GUIM_MOUSE_WHEEL_DOWN,
|
||||
GUIM_SETTINGS_UPDATED, // SGUIMessage.m_Value = name of setting
|
||||
GUIM_PRESSED,
|
||||
GUIM_KEYDOWN,
|
||||
GUIM_RELEASED,
|
||||
GUIM_DOUBLE_PRESSED,
|
||||
GUIM_MOUSE_MOTION,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -61,16 +61,16 @@ JS::Value JSI_GUIManager::GetGUIObjectByName(ScriptInterface::CxPrivate* pCxPriv
|
||||
return JS::ObjectValue(*guiObj->GetJSObject());
|
||||
}
|
||||
|
||||
void JSI_GUIManager::SetGlobalHotkey(ScriptInterface::CxPrivate* pCxPrivate, const std::string& hotkeyTag, JS::HandleValue function)
|
||||
void JSI_GUIManager::SetGlobalHotkey(ScriptInterface::CxPrivate* pCxPrivate, const std::string& hotkeyTag, const std::string& eventName, JS::HandleValue function)
|
||||
{
|
||||
CGUI* guiPage = static_cast<CGUI*>(pCxPrivate->pCBData);
|
||||
guiPage->SetGlobalHotkey(hotkeyTag, function);
|
||||
guiPage->SetGlobalHotkey(hotkeyTag, eventName, function);
|
||||
}
|
||||
|
||||
void JSI_GUIManager::UnsetGlobalHotkey(ScriptInterface::CxPrivate* pCxPrivate, const std::string& hotkeyTag)
|
||||
void JSI_GUIManager::UnsetGlobalHotkey(ScriptInterface::CxPrivate* pCxPrivate, const std::string& hotkeyTag, const std::string& eventName)
|
||||
{
|
||||
CGUI* guiPage = static_cast<CGUI*>(pCxPrivate->pCBData);
|
||||
guiPage->UnsetGlobalHotkey(hotkeyTag);
|
||||
guiPage->UnsetGlobalHotkey(hotkeyTag, eventName);
|
||||
}
|
||||
|
||||
std::wstring JSI_GUIManager::SetCursor(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::wstring& name)
|
||||
@ -99,8 +99,8 @@ void JSI_GUIManager::RegisterScriptFunctions(const ScriptInterface& scriptInterf
|
||||
{
|
||||
scriptInterface.RegisterFunction<void, std::wstring, JS::HandleValue, JS::HandleValue, &PushGuiPage>("PushGuiPage");
|
||||
scriptInterface.RegisterFunction<void, std::wstring, JS::HandleValue, &SwitchGuiPage>("SwitchGuiPage");
|
||||
scriptInterface.RegisterFunction<void, std::string, JS::HandleValue, &SetGlobalHotkey>("SetGlobalHotkey");
|
||||
scriptInterface.RegisterFunction<void, std::string, &UnsetGlobalHotkey>("UnsetGlobalHotkey");
|
||||
scriptInterface.RegisterFunction<void, std::string, std::string, JS::HandleValue, &SetGlobalHotkey>("SetGlobalHotkey");
|
||||
scriptInterface.RegisterFunction<void, std::string, std::string, &UnsetGlobalHotkey>("UnsetGlobalHotkey");
|
||||
scriptInterface.RegisterFunction<void, JS::HandleValue, &PopGuiPage>("PopGuiPage");
|
||||
scriptInterface.RegisterFunction<JS::Value, std::string, &GetGUIObjectByName>("GetGUIObjectByName");
|
||||
scriptInterface.RegisterFunction<std::wstring, std::wstring, &SetCursor>("SetCursor");
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -27,8 +27,8 @@ namespace JSI_GUIManager
|
||||
void SwitchGuiPage(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& name, JS::HandleValue initData);
|
||||
void PopGuiPage(ScriptInterface::CxPrivate* pCxPrivate, JS::HandleValue args);
|
||||
JS::Value GetGUIObjectByName(ScriptInterface::CxPrivate* pCxPrivate, const std::string& name);
|
||||
void SetGlobalHotkey(ScriptInterface::CxPrivate* pCxPrivate, const std::string& hotkeyTag, JS::HandleValue function);
|
||||
void UnsetGlobalHotkey(ScriptInterface::CxPrivate* pCxPrivate, const std::string& hotkeyTag);
|
||||
void SetGlobalHotkey(ScriptInterface::CxPrivate* pCxPrivate, const std::string& hotkeyTag, const std::string& eventName, JS::HandleValue function);
|
||||
void UnsetGlobalHotkey(ScriptInterface::CxPrivate* pCxPrivate, const std::string& hotkeyTag, const std::string& eventName);
|
||||
std::wstring SetCursor(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& name);
|
||||
void ResetCursor(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
bool TemplateExists(ScriptInterface::CxPrivate* pCxPrivate, const std::string& templateName);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -74,6 +74,7 @@ public:
|
||||
SDL_Event_ hotkeyNotification;
|
||||
hotkeyNotification.ev.type = SDL_KEYDOWN;
|
||||
hotkeyNotification.ev.key.keysym.sym = SDLK_a;
|
||||
hotkeyNotification.ev.key.repeat = 0;
|
||||
|
||||
// Init input and poll the event.
|
||||
InitInput();
|
||||
@ -100,6 +101,22 @@ public:
|
||||
ScriptInterface::FromJSVal(pcx, js_hotkey_pressed_value, hotkey_pressed_value);
|
||||
TS_ASSERT_EQUALS(hotkey_pressed_value, true);
|
||||
|
||||
// We are listening to KeyDown events, so repeat shouldn't matter.
|
||||
hotkeyNotification.ev.key.repeat = 1;
|
||||
in_push_priority_event(&hotkeyNotification);
|
||||
while (in_poll_event(&ev))
|
||||
in_dispatch_event(&ev);
|
||||
|
||||
hotkey_pressed_value = false;
|
||||
pageScriptInterface.GetProperty(global, "state_before", &js_hotkey_pressed_value);
|
||||
ScriptInterface::FromJSVal(pcx, js_hotkey_pressed_value, hotkey_pressed_value);
|
||||
TS_ASSERT_EQUALS(hotkey_pressed_value, true);
|
||||
|
||||
hotkey_pressed_value = false;
|
||||
pageScriptInterface.GetProperty(global, "state_after", &js_hotkey_pressed_value);
|
||||
ScriptInterface::FromJSVal(pcx, js_hotkey_pressed_value, hotkey_pressed_value);
|
||||
TS_ASSERT_EQUALS(hotkey_pressed_value, true);
|
||||
|
||||
hotkeyNotification.ev.type = SDL_KEYUP;
|
||||
in_push_priority_event(&hotkeyNotification);
|
||||
while (in_poll_event(&ev))
|
||||
|
@ -171,7 +171,7 @@ static InReaction MainInputHandler(const SDL_Event_* ev)
|
||||
QuitEngine();
|
||||
break;
|
||||
|
||||
case SDL_HOTKEYDOWN:
|
||||
case SDL_HOTKEYPRESS:
|
||||
std::string hotkey = static_cast<const char*>(ev->ev.user.data1);
|
||||
if (hotkey == "exit")
|
||||
{
|
||||
|
@ -637,7 +637,7 @@ InReaction conInputHandler(const SDL_Event_* ev)
|
||||
if (!g_Console)
|
||||
return IN_PASS;
|
||||
|
||||
if ((int)ev->ev.type == SDL_HOTKEYDOWN)
|
||||
if (static_cast<int>(ev->ev.type) == SDL_HOTKEYPRESS)
|
||||
{
|
||||
std::string hotkey = static_cast<const char*>(ev->ev.user.data1);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -154,7 +154,7 @@ bool isNegated(const SKey& key)
|
||||
|
||||
InReaction HotkeyStateChange(const SDL_Event_* ev)
|
||||
{
|
||||
if (ev->ev.type == SDL_HOTKEYDOWN)
|
||||
if (ev->ev.type == SDL_HOTKEYPRESS)
|
||||
g_HotkeyStatus[static_cast<const char*>(ev->ev.user.data1)] = true;
|
||||
else if (ev->ev.type == SDL_HOTKEYUP)
|
||||
g_HotkeyStatus[static_cast<const char*>(ev->ev.user.data1)] = false;
|
||||
@ -216,6 +216,9 @@ InReaction HotkeyInputHandler(const SDL_Event_* ev)
|
||||
|
||||
SDL_Event_ phantom;
|
||||
phantom.ev.type = ((ev->ev.type == SDL_KEYDOWN) || (ev->ev.type == SDL_MOUSEBUTTONDOWN)) ? SDL_KEYDOWN : SDL_KEYUP;
|
||||
if (phantom.ev.type == SDL_KEYDOWN)
|
||||
phantom.ev.key.repeat = ev->ev.type == SDL_KEYDOWN ? ev->ev.key.repeat : 0;
|
||||
|
||||
if ((keycode == SDLK_LSHIFT) || (keycode == SDLK_RSHIFT))
|
||||
{
|
||||
phantom.ev.key.keysym.sym = (SDL_Keycode)UNIFIED_SHIFT;
|
||||
@ -259,7 +262,7 @@ InReaction HotkeyInputHandler(const SDL_Event_* ev)
|
||||
|
||||
// To avoid this, set the modifier keys for /all/ events this key would trigger
|
||||
// (Ctrl, for example, is both group-save and bookmark-save)
|
||||
// but only send a HotkeyDown event for the event with bindings most precisely
|
||||
// but only send a HotkeyPress/HotkeyDown event for the event with bindings most precisely
|
||||
// matching the conditions (i.e. the event with the highest number of auxiliary
|
||||
// keys, providing they're all down)
|
||||
|
||||
@ -306,10 +309,22 @@ InReaction HotkeyInputHandler(const SDL_Event_* ev)
|
||||
|
||||
for (size_t i = 0; i < closestMapNames.size(); ++i)
|
||||
{
|
||||
SDL_Event_ hotkeyNotification;
|
||||
hotkeyNotification.ev.type = SDL_HOTKEYDOWN;
|
||||
hotkeyNotification.ev.user.data1 = const_cast<char*>(closestMapNames[i]);
|
||||
in_push_priority_event(&hotkeyNotification);
|
||||
// Send a KeyPress event when a key is pressed initially and on mouseButton and mouseWheel events.
|
||||
if (ev->ev.type != SDL_KEYDOWN || ev->ev.key.repeat == 0)
|
||||
{
|
||||
SDL_Event_ hotkeyPressNotification;
|
||||
hotkeyPressNotification.ev.type = SDL_HOTKEYPRESS;
|
||||
hotkeyPressNotification.ev.user.data1 = const_cast<char*>(closestMapNames[i]);
|
||||
in_push_priority_event(&hotkeyPressNotification);
|
||||
}
|
||||
|
||||
// Send a HotkeyDown event on every key, mouseButton and mouseWheel event.
|
||||
// For keys the event is repeated depending on hardware and OS configured interval.
|
||||
// On linux, modifier keys (shift, alt, ctrl) are not repeated, see https://github.com/SFML/SFML/issues/122.
|
||||
SDL_Event_ hotkeyDownNotification;
|
||||
hotkeyDownNotification.ev.type = SDL_HOTKEYDOWN;
|
||||
hotkeyDownNotification.ev.user.data1 = const_cast<char*>(closestMapNames[i]);
|
||||
in_push_priority_event(&hotkeyDownNotification);
|
||||
}
|
||||
|
||||
// -- KEYUP SECTION --
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -25,9 +25,10 @@
|
||||
* Hotkeys consist of a name (an arbitrary string), and a key mapping.
|
||||
* The names and mappings are loaded from the config system (any
|
||||
* config setting with the name prefix "hotkey.").
|
||||
* When a hotkey is pressed or released, SDL_HOTKEYDOWN and SDL_HOTKEYUP
|
||||
* events are triggered, with the hotkey name stored in ev.user.data1
|
||||
* as a const char*.
|
||||
* When a hotkey is pressed one SDL_HOTKEYPRESS is triggered. While the key is
|
||||
* kept down repeated SDL_HOTKEYDOWN events are triggered at an interval
|
||||
* determined by the OS. When a hotkey is released an SDL_HOTKEYUP event is
|
||||
* triggered. All with the hotkey name stored in ev.user.data1 as a const char*.
|
||||
*/
|
||||
|
||||
#include "CStr.h"
|
||||
@ -38,8 +39,9 @@
|
||||
// required for our HOTKEY event type definition. this is OK since
|
||||
// hotkey.h is not included from any headers.
|
||||
|
||||
const int SDL_HOTKEYDOWN = SDL_USEREVENT;
|
||||
const int SDL_HOTKEYUP = SDL_USEREVENT + 1;
|
||||
const uint SDL_HOTKEYPRESS = SDL_USEREVENT;
|
||||
const uint SDL_HOTKEYDOWN = SDL_USEREVENT + 1;
|
||||
const uint SDL_HOTKEYUP = SDL_USEREVENT + 2;
|
||||
|
||||
extern void LoadHotkeys();
|
||||
extern void UnloadHotkeys();
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -336,7 +336,7 @@ InReaction CProfileViewer::Input(const SDL_Event_* ev)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_HOTKEYDOWN:
|
||||
case SDL_HOTKEYPRESS:
|
||||
std::string hotkey = static_cast<const char*>(ev->ev.user.data1);
|
||||
|
||||
if( hotkey == "profile.toggle" )
|
||||
|
Loading…
Reference in New Issue
Block a user