Open6
ImGuiでショートカットキーを使ってofSystemSaveDialogを使ったときの不具合[Mac]
ピン留めされたアイテム
ImGui側で修正されたっぽい
Issueたってたのね。
環境
macOS 10.15.5
OpenGL 4.1
openFrameworks 0.11.0
ofxImGui 330e1425a8
現象
bool IsKeyDown(int key_index, ImGuiKeyModFlags mod)
{
auto &&io = ImGui::GetIO();
return io.KeysDown[key_index] && io.KeyMods == mod;
}
if(IsKeyDown('S', ImGuiKeyModFlags_Super | ImGuiKeyModFlags_Shift)) {
auto result = ofSystemSaveDialog("", "Save as");
if(result.bSuccess) {
...
}
}
こんな感じでダイアログを開くと、閉じた直後にimgui.cpp#7557にあるio.KeyModsのSanityCheckに失敗する。
const ImGuiKeyModFlags expected_key_mod_flags = GetMergedKeyModFlags();
IM_ASSERT(g.IO.KeyMods == expected_key_mod_flags && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
デバッガで値をみたところ、以下だった。
-
GetMergedKeyModFlags()
の結果は0 -
g.IO.KeyMods
は10 (=ImGuiKeyModFlags_Super | ImGuiKeyModFlags_Shift
)
GetMergedKeyModFlags()
が集計しているフラグはofxImGui/src/EngineGLFW.cpp
にあるEngineGLFW::onKeyReleasedで下ろされている。
そのタイミングをみてみると、ダイアログが開くときっぽい。
どうやらGLFWなのかmacOSなのか何かの動作で、OpenGL的にはここでキーを放したことになるらしい。
時系列で現象をみると
-
NewFrame()
でIO.KeyMods
がGetMergedKeyModFlags()
によって設定される - ダイアログが開き、
IO.KeyMods
はそのままでフラグ側だけが変更される -
ErrorCheckEndFrameSanityChecks()
でミスマッチがみつかる
ということになる。
こんな感じでキーのキャッシュをして、ダイアログ前後で保存して戻すと、次以降のフレームでも(Releaseイベントが呼ばれないので)押されっぱなしになって失敗。
auto &io = ImGui::GetIO();
bool key_cache[512];
auto storeKeyCache = [&]() {
memcpy(key_cache, io.KeysDown, sizeof(io.KeysDown));
};
auto restoreKeyCache = [&]() {
memcpy(io.KeysDown, key_cache, sizeof(io.KeysDown));
io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL];
io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT];
io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT];
io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER];
};
これをダイアログ直後に呼んで解決した。
(#include "imgui_internal.h"
が必要)
auto sanitizeKeyMods = [&]() {
ImGui::GetIO().KeyMods = ImGui::GetMergedKeyModFlags();
};