如何将小部件作为 client_data 传递给 Xt/Motif 信号处理程序?
How do I pass a widget as client_data to a Xt/Motif signal handler?
我希望 Motif 应用程序在接收到 SIGUSR1 信号时重新绘制绘图区小部件。
我已经使用 X11R6 中的 Xt 功能配置了信号:
/* CONFIGURE READ SIGNAL, TRAPS SIGUSR1 TO FORCE APPLICATION READ DATA FILE */
signal(SIGUSR1, signal_usr1_handler);
signal_id = XtAppAddSignal (app, read_data, (XtPointer)chart_area);
其中 signal_usr1_handler
是 OS Unix 处理程序,read_data
是 Xt 信号处理程序。
对于 Xt 信号处理程序,我试图传递小部件 chart_area
,它是一个绘图区小部件。
这些是处理程序:
/* SIGNAL HANDLER */
void signal_usr1_handler() {
printf("SIGUSR1 RECEIVED\n");
XtNoticeSignal(signal_id);
}
/* READ DATA XT SIGNAL HANDLER */
void read_data(XtPointer client_data, XtSignalId *id) {
posx += 5;
printf("XT HANDLES SIGUSR1\n");
XmDrawingAreaCallbackStruct da_struct;
da_struct.reason = XmCR_EXPOSE;
da_struct.event = (XEvent *) NULL;
da_struct.window = XtWindow((Widget)client_data);
XtCallCallbacks((Widget)client_data, XmNexposeCallback, (XtPointer) &da_struct);
}
应用程序恰好在执行 XtCallCallbacks
函数时引发 Segmentation fault (core dumped)
。
这是完整的源代码:
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include <Xm/Xm.h>
#include <Xm/DrawingA.h>
#include <Xm/Label.h>
/* FUNCTION DECLARATIONS */
void draw_chart(Widget widget, XtPointer client_data, XtPointer call_data);
void signal_usr1_handler();
void read_data(XtPointer client_data, XtSignalId *id);
/* XT SIGNAL ID */
XtSignalId signal_id; /* Signal ID used to receive data read via SIGUSR1 */
int main(int argc, char *argv[]) {
/* WIDGETS */
XtAppContext app; /* Application Context */
Widget toplevel; /* Top Level Button */
Widget chart_area; /* Drawing Area Widget to draw the chart */
/* DRAWING AREA RELATED */
XGCValues gcv;
GC gc;
/* RESOURCE VALUE ARRAYS/COUNT */
Arg al[10];
int ac;
/* INITIALIZE TOP LEVEL WINDOW */
XtSetLanguageProc(NULL, NULL, NULL);
toplevel = XtVaOpenApplication(
&app, argv[0], NULL, 0, &argc, argv, NULL, sessionShellWidgetClass,
XmNwidth, 400, XmNheight, 300, NULL
);
/* CREATE AND MANAGE DRAWING CANVAS WIDGET */
ac=0;
chart_area = XmCreateDrawingArea(toplevel, "chart_area", al, ac);
/* CREATE GRAPHICS CONTEXT */
gcv.foreground = WhitePixelOfScreen(XtScreen(chart_area));
gcv.background = BlackPixelOfScreen(XtScreen(chart_area));
gc = XCreateGC (
XtDisplay(chart_area),
RootWindowOfScreen(XtScreen(chart_area)),
(GCForeground | GCBackground),
&gcv);
/* ASSIGN GRAPHICS CONTEXT */
XtVaSetValues(chart_area, XmNuserData, gc, NULL);
/* ASSIGN CALLBACKS AND MANAGE WIDGET */
XtAddCallback(chart_area, XmNexposeCallback, draw_chart, NULL);
XtManageChild(chart_area);
/* CONFIGURE READ SIGNAL, TRAPS SIGUSR1 TO FORCE APPLICATION READ DATA FILE */
signal(SIGUSR1, signal_usr1_handler);
signal_id = XtAppAddSignal (app, read_data, (XtPointer)chart_area);
/* REALIZE TOPLEVEL WINDOW AND LAUNCH APPLICATION LOOP */
XtRealizeWidget(toplevel);
XtAppMainLoop(app);
return 0;
}
void draw_chart(Widget widget, XtPointer client_data, XtPointer call_data) {
XmDrawingAreaCallbackStruct *cbs = (XmDrawingAreaCallbackStruct *) call_data;
XEvent *event = cbs->event;
Display *dpy = event->xany.display;
GC gc;
/* DRAW LINE */
if(cbs->reason == XmCR_EXPOSE || cbs->reason == XmCR_ACTIVATE) {
XtVaGetValues(widget, XmNuserData, &gc, NULL);
XDrawLine(dpy, cbs->window, gc, 10, 10, posx, 200);
}
}
/* SIGNAL HANDLER */
void signal_usr1_handler() {
printf("SIGUSR1 RECEIVED\n");
XtNoticeSignal(signal_id);
}
/* READ DATA XT SIGNAL HANDLER */
void read_data(XtPointer client_data, XtSignalId *id) {
/* ... READ DATA AND PROCESSING GOES HERE ... */
posx += 5;
printf("XT HANDLES SIGUSR1\n");
XmDrawingAreaCallbackStruct da_struct;
da_struct.reason = XmCR_EXPOSE;
da_struct.event = (XEvent *) NULL;
da_struct.window = XtWindow((Widget)client_data);
/* XtCallCallbacks((Widget)client_data, XmNexposeCallback, (XtPointer) &da_struct); */
}
以下原因导致崩溃:
显示 *dpy = 事件->xany.display;
因为事件被设置为 NULL。
此外,您可能需要通过传递其地址并接收 XmUserData 作为
来处理 gc
GC *gc;
然后使用*gc,
我希望 Motif 应用程序在接收到 SIGUSR1 信号时重新绘制绘图区小部件。
我已经使用 X11R6 中的 Xt 功能配置了信号:
/* CONFIGURE READ SIGNAL, TRAPS SIGUSR1 TO FORCE APPLICATION READ DATA FILE */
signal(SIGUSR1, signal_usr1_handler);
signal_id = XtAppAddSignal (app, read_data, (XtPointer)chart_area);
其中 signal_usr1_handler
是 OS Unix 处理程序,read_data
是 Xt 信号处理程序。
对于 Xt 信号处理程序,我试图传递小部件 chart_area
,它是一个绘图区小部件。
这些是处理程序:
/* SIGNAL HANDLER */
void signal_usr1_handler() {
printf("SIGUSR1 RECEIVED\n");
XtNoticeSignal(signal_id);
}
/* READ DATA XT SIGNAL HANDLER */
void read_data(XtPointer client_data, XtSignalId *id) {
posx += 5;
printf("XT HANDLES SIGUSR1\n");
XmDrawingAreaCallbackStruct da_struct;
da_struct.reason = XmCR_EXPOSE;
da_struct.event = (XEvent *) NULL;
da_struct.window = XtWindow((Widget)client_data);
XtCallCallbacks((Widget)client_data, XmNexposeCallback, (XtPointer) &da_struct);
}
应用程序恰好在执行 XtCallCallbacks
函数时引发 Segmentation fault (core dumped)
。
这是完整的源代码:
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include <Xm/Xm.h>
#include <Xm/DrawingA.h>
#include <Xm/Label.h>
/* FUNCTION DECLARATIONS */
void draw_chart(Widget widget, XtPointer client_data, XtPointer call_data);
void signal_usr1_handler();
void read_data(XtPointer client_data, XtSignalId *id);
/* XT SIGNAL ID */
XtSignalId signal_id; /* Signal ID used to receive data read via SIGUSR1 */
int main(int argc, char *argv[]) {
/* WIDGETS */
XtAppContext app; /* Application Context */
Widget toplevel; /* Top Level Button */
Widget chart_area; /* Drawing Area Widget to draw the chart */
/* DRAWING AREA RELATED */
XGCValues gcv;
GC gc;
/* RESOURCE VALUE ARRAYS/COUNT */
Arg al[10];
int ac;
/* INITIALIZE TOP LEVEL WINDOW */
XtSetLanguageProc(NULL, NULL, NULL);
toplevel = XtVaOpenApplication(
&app, argv[0], NULL, 0, &argc, argv, NULL, sessionShellWidgetClass,
XmNwidth, 400, XmNheight, 300, NULL
);
/* CREATE AND MANAGE DRAWING CANVAS WIDGET */
ac=0;
chart_area = XmCreateDrawingArea(toplevel, "chart_area", al, ac);
/* CREATE GRAPHICS CONTEXT */
gcv.foreground = WhitePixelOfScreen(XtScreen(chart_area));
gcv.background = BlackPixelOfScreen(XtScreen(chart_area));
gc = XCreateGC (
XtDisplay(chart_area),
RootWindowOfScreen(XtScreen(chart_area)),
(GCForeground | GCBackground),
&gcv);
/* ASSIGN GRAPHICS CONTEXT */
XtVaSetValues(chart_area, XmNuserData, gc, NULL);
/* ASSIGN CALLBACKS AND MANAGE WIDGET */
XtAddCallback(chart_area, XmNexposeCallback, draw_chart, NULL);
XtManageChild(chart_area);
/* CONFIGURE READ SIGNAL, TRAPS SIGUSR1 TO FORCE APPLICATION READ DATA FILE */
signal(SIGUSR1, signal_usr1_handler);
signal_id = XtAppAddSignal (app, read_data, (XtPointer)chart_area);
/* REALIZE TOPLEVEL WINDOW AND LAUNCH APPLICATION LOOP */
XtRealizeWidget(toplevel);
XtAppMainLoop(app);
return 0;
}
void draw_chart(Widget widget, XtPointer client_data, XtPointer call_data) {
XmDrawingAreaCallbackStruct *cbs = (XmDrawingAreaCallbackStruct *) call_data;
XEvent *event = cbs->event;
Display *dpy = event->xany.display;
GC gc;
/* DRAW LINE */
if(cbs->reason == XmCR_EXPOSE || cbs->reason == XmCR_ACTIVATE) {
XtVaGetValues(widget, XmNuserData, &gc, NULL);
XDrawLine(dpy, cbs->window, gc, 10, 10, posx, 200);
}
}
/* SIGNAL HANDLER */
void signal_usr1_handler() {
printf("SIGUSR1 RECEIVED\n");
XtNoticeSignal(signal_id);
}
/* READ DATA XT SIGNAL HANDLER */
void read_data(XtPointer client_data, XtSignalId *id) {
/* ... READ DATA AND PROCESSING GOES HERE ... */
posx += 5;
printf("XT HANDLES SIGUSR1\n");
XmDrawingAreaCallbackStruct da_struct;
da_struct.reason = XmCR_EXPOSE;
da_struct.event = (XEvent *) NULL;
da_struct.window = XtWindow((Widget)client_data);
/* XtCallCallbacks((Widget)client_data, XmNexposeCallback, (XtPointer) &da_struct); */
}
以下原因导致崩溃:
显示 *dpy = 事件->xany.display;
因为事件被设置为 NULL。
此外,您可能需要通过传递其地址并接收 XmUserData 作为
来处理 gcGC *gc;
然后使用*gc,