簡體   English   中英

wxWidgets wxGetKeyState() 和 Wayland 問題

[英]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()相同的功能,但有以下注意事項:

  1. 此 function 的使用僅在針對 Linux/Wayland 時才有意義。 它在任何其他情況下都沒有提供任何優勢。 wxGetKeyState()開始與 Wayland 一起正常工作的那一天,您將不再需要這個 function。 正如 VZ 所建議的,問題似乎出在 GDK 上。

  2. 這個 function 僅在程序啟動期間有用,因為在幾個空閑事件周期wxGetKeyState()工作正常。

  3. 此 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM