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);
}
我正在尝试追踪一个看起来像是 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);
}