XmDrawingArea 输入回调未命中事件

XmDrawingArea input callback misses events

我正在尝试追踪一个看起来像是 Motif 绘图区域中缺少事件的问题。

如果我在绘图区域内点击鼠标按钮 1,我将获得 ButtonPress 和 ButtonRelease 事件,但随后我将停止获得 Ctrl 和 Shift 键的按键事件(其他键似乎正常)。 在这种状态下,如果我按下另一个键(比如 ESC),我将获得 ESC 键的 KeyPress 和 KeyRelease,然后我也开始获得 Ctrl 和 Shift 的按键事件(不是我错过的那些 - 只是任何新的按键)

再次按下按钮,Ctrl/Shift再次“消失”。单击鼠标按钮 3 Ctrl/Shift 返回。

按住 Ctrl 键并单击按钮 1(然后松开 Ctrl),我得到了 KeyPress 和 ButtonRelease,然后是 KeyRelease。 (没有 ButtonPress)

这一切有什么解释吗?我看到它在 Windows 上使用 eXceed 和本地 X 服务器(通过 x2go)。我在 Linux 和 Solaris 客户端上都看到了它。

编辑:我的实际应用程序有一个“自定义”事件循环(只是抓取一个事件,可选择记录它然后分派)。我看到 X11 事件循环可以看到丢失的事件,但它们没有进入绘图区域输入 CB。

#include <stdio.h>
#include <Xm/Xm.h>
#include <Xm/DrawingA.h>

void inputCb(Widget w, XtPointer client, XtPointer call)
{
    char *type;
    char data[16] = {0};
    
    XmDrawingAreaCallbackStruct *cbs = (XmDrawingAreaCallbackStruct *) call;

    switch(cbs->event->type)
    {
        case ButtonPress:
            type="ButtonPress";
            break;
        case ButtonRelease:
            type="ButtonRelease";
            break;
        case KeyPress:
            type="KeyPress";
            break;
        case KeyRelease:
            type="KeyRelease";
            break;
        default:
            type="Other";
            sprintf(data, " (%d)", cbs->event->type);
            break;
    }
    printf("%s%s\n", type, data);
}

int
main(int argc, char *argv[])
{
  XtAppContext appContext;
  Widget toplevel, drawingArea;

  toplevel = XtVaAppInitialize(&appContext, "drawingArea", NULL, 0,
                   &argc, argv, NULL, NULL);
  drawingArea= XtVaCreateManagedWidget("drawingArea", xmDrawingAreaWidgetClass, toplevel,
    NULL);

  XtAddCallback(drawingArea, XmNinputCallback, inputCb, (XtPointer)0);
  XtRealizeWidget(toplevel);
  XtAppMainLoop(appContext);
  return 0;
}

我仍然不确定为什么输入回调会错过一些事件。可能是 Motif 版本的差异。

我的解决方法是根本不使用输入回调,而是使用获取 Button Press/Release + Key Press/Release 事件的事件处理程序。 在事件处理程序中,我创建了一个虚拟 CB 结构,因此我可以像事件来自 CB

一样调用我的客户端代码
 XtAddEventHandler(drawArea,
        ButtonPressMask|ButtonReleaseMask|KeyPressMask|KeyReleaseMask,
        False, (XtEventHandler)inputEH, (XtPointer)0);


static void inputEH(Widget     w,
                 XtPointer     clientData,
                 XEvent*       event,
                 Boolean*      continueToDispatch)
{
    // Create a dummy call_data so it looks like we've come from the InputCB
    //
    XmAnyCallbackStruct call_data;
    call_data.reason = XmCR_INPUT;
    call_data.event = event;

    client_code_that_expects_certain_args(w, clientData, &call_data);
}