[英]wxWidgets wxGetKeyState() and Wayland issue
我遇到了 Wayland 的wxGetKeyState()
問題。 讓我解釋一下:在我的一些應用程序中,我添加了一個測試,用於在我的應用程序頂部 wxFrame window 的 ctor 中按下 Shift 鍵。 如果在啟動期間按下 Shift 鍵,我會運行與我的應用程序相關的診斷代碼。 在我使用 Wayland 顯示服務器切換到 Ubuntu 22.04 之前,這一直工作得很好。 如果我使用 X.org 顯示服務器在 Ubuntu 22.04 中運行我的應用程序,一切都會按預期運行。 順便說一句,我使用的是 wxWidgets 3.2.0。
要測試這個可能的錯誤,只需將這幾行代碼添加到頂部 wxFrame ctor 的末尾。
MyFrame::MyFrame()
{
...
if (wxGetKeyState(WXK_SHIFT))
{
wxMessageBox("Hello there");
}
}
有沒有人遇到過這個問題? 有已知的解決方法嗎?
問候,鮑勃
編輯:當我運行最小的應用程序(如下所示)時,我看到了 X 和 Wayland 的這些結果。
Output 在 X 中按住 shift 鍵啟動應用程序時。
18:40:25: Debug: from CTOR: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
18:40:25: Debug: from idle: 1
在 X 下, wxGetKeyState()
的行為符合預期。 它在停止之前經歷了 16 個空閑周期,同時一直顯示正確的值。
現在,這是 output 在 Waylan 中按住 shift 鍵啟動應用程序時。
18:32:43: Debug: from CTOR: 0
18:32:43: Debug: from idle: 0
18:32:43: Debug: from idle: 0
18:32:43: Debug: from idle: 0
18:32:43: Debug: from idle: 1
在 Wayland 下,ctor 的測試失敗,需要 3 個空閑周期才能報告正確的值。 我希望這個測試有助於識別和解決這個問題。
最小測試程序:
#include <wx/wx.h>
class MyApp: public wxApp
{
public:
virtual bool OnInit();
};
class MyFrame: public wxFrame
{
public:
MyFrame();
void on_idle(wxIdleEvent& event);
};
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
MyFrame* wnd = new MyFrame();
wnd->Show();
return true;
}
MyFrame::MyFrame() : wxFrame(NULL, wxID_ANY, "minimal")
{
Bind(wxEVT_IDLE, &MyFrame::on_idle, this);
wxLogDebug("from CTOR: %d", wxGetKeyState(WXK_SHIFT));
}
void MyFrame::on_idle(wxIdleEvent& event)
{
wxLogDebug("from idle: %d", wxGetKeyState(WXK_SHIFT));
}
這應該可以工作,我剛剛在鍵盤示例中添加了這個 function 的演示,它對我來說在 X 和 Wayland 上的行為都符合預期,包括在啟動時按下相應鍵時在狀態欄中顯示“Shift”樣本。
查看代碼,Wayland 支持需要 GTK 3.4 或更高版本,但您絕對應該在 Ubuntu 22.04 下擁有這個(實際上是更新的版本),所以我不知道為什么它不起作用。 如果您在鍵盤示例中也發現了問題,請嘗試自己調試,即檢查wxGetKeyStateGTK()
function 內部發生的情況。
我針對 Wayland/wxGetKeyState() 問題實施了一個臨時解決方案。 下面的 function get_key_state_hack()
提供與wxGetKeyState()
相同的功能,但有以下注意事項:
此 function 的使用僅在針對 Linux/Wayland 時才有意義。 它在任何其他情況下都沒有提供任何優勢。 wxGetKeyState()
開始與 Wayland 一起正常工作的那一天,您將不再需要這個 function。 正如 VZ 所建議的,問題似乎出在 GDK 上。
這個 function 僅在程序啟動期間有用,因為在幾個空閑事件周期wxGetKeyState()
工作正常。
此 function 將阻塞幾個空閑事件周期。 在我的情況下這不是問題,因為我將它用作一次性測試來檢測在程序啟動期間是否按住 Shift 鍵,並且一旦用戶移動鼠標或觸摸鍵盤,就會出現大量空閑事件。
#include <wx/evtloop.h>
bool get_key_state_hack(wxKeyCode key)
{
int count = 5;
bool pressed = false;
wxEventLoop loop;
auto on_idle = [&](wxIdleEvent& event)
{
bool keydown = wxGetKeyState(key);
if (keydown || (--count < 1))
{
pressed = keydown;
loop.Exit();
}
};
wxTheApp->Bind(wxEVT_IDLE, on_idle);
loop.Run();
wxTheApp->Unbind(wxEVT_IDLE, on_idle);
return pressed;
}
By the way, I decided to use a lambda function as event handler to keep all the code nicely packed in a single C++ function.
我希望這個 function 對遇到這個問題的人有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.