|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)Event.c 1.7 2/25/87";
3: #endif lint
4:
5: /*
6: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
7: *
8: * All Rights Reserved
9: *
10: * Permission to use, copy, modify, and distribute this software and its
11: * documentation for any purpose and without fee is hereby granted,
12: * provided that the above copyright notice appear in all copies and that
13: * both that copyright notice and this permission notice appear in
14: * supporting documentation, and that the name of Digital Equipment
15: * Corporation not be used in advertising or publicity pertaining to
16: * distribution of the software without specific, written prior permission.
17: *
18: *
19: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
20: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
21: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
22: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
25: * SOFTWARE.
26: */
27:
28: #include "Xlib.h"
29: #include "Intrinsic.h"
30: #include "Xutil.h"
31:
32: /* Private Definitions */
33:
34: typedef struct _ProcRec {
35: XtEventHandler proc;
36: unsigned long mask;
37: caddr_t data;
38: struct _ProcRec *next;
39: } ProcRec, *ProcPtr;
40:
41: typedef struct {
42: Display *dpy;
43: Window window;
44: ProcPtr firstproc;
45: unsigned long totalmask;
46: Boolean master; /* True if this window is a child of root. */
47: } EventRec, *EventPtr;
48:
49: static XContext eventContext;
50: static Boolean initialized = FALSE;
51:
52: /* Private Routines */
53:
54: void EventInitialize()
55: {
56: if (initialized)
57: return;
58: initialized = TRUE;
59:
60: eventContext = XUniqueContext();
61: }
62:
63: static EventPtr EventPtrFromWindow(dpy, w)
64: Display *dpy;
65: Window w;
66: {
67: EventPtr result;
68: if (XFindContext(dpy, w, eventContext, (caddr_t *)&result) != XCNOENT)
69: return(result);
70: return(0);
71: }
72:
73: /*
74: * Delete the event handler reference in the dispatcher for this window.
75: */
76: static void ResetEventHandler(dpy, w)
77: Display *dpy;
78: Window w;
79: {
80: register EventPtr ctx;
81: register ProcPtr p, p2;
82:
83: ctx = EventPtrFromWindow(dpy, w);
84: if (!ctx)
85: return;
86: p = ctx->firstproc;
87: while (p != NULL) {
88: p2 = p->next;
89: XtFree((char *) p);
90: p = p2;
91: }
92: XtFree((char *)ctx);
93:
94: (void) XDeleteContext(dpy, w, eventContext);
95: return;
96: }
97:
98: static XtEventReturnCode CallProc(ctx, event)
99: EventPtr ctx;
100: XEvent *event;
101: {
102: register EventPtr evp;
103: EventPtr first;
104: register ProcPtr p;
105: register int nprocs, i;
106: XtEventHandler procs[100]; /* We need to copy the procs into this */
107: /* local storage before calling any of */
108: /* them, because one of the calls */
109: /* could cause the ctx record to be */
110: /* destroyed! */
111: caddr_t data[100];
112: unsigned long kinds;
113: XtEventReturnCode result;
114: XtEventReturnCode finalresult = XteventNoHandler;
115:
116: static unsigned long masks[] = {
117: 0, /* No such event. */
118: StructureNotifyMask, /* MessageEvent (Faked by toolkit). */
119: KeyPressMask, /* KeyPress */
120: KeyReleaseMask, /* KeyRelease */
121: ButtonPressMask, /* ButtonPress */
122: ButtonReleaseMask, /* ButtonRelease */
123: PointerMotionMask | PointerMotionHintMask | Button1MotionMask |
124: Button2MotionMask | Button3MotionMask | Button4MotionMask |
125: Button5MotionMask | ButtonMotionMask,
126: /* MotionNotify */
127: EnterWindowMask, /* EnterNotify */
128: LeaveWindowMask, /* LeaveNotify */
129: FocusChangeMask, /* FocusIn */
130: FocusChangeMask, /* FocusOut */
131: KeymapStateMask, /* KeymapNotify */
132: ExposureMask, /* Expose */
133: ExposureMask, /* GraphicsExpose */
134: ExposureMask, /* NoExpose */
135: VisibilityChangeMask, /* VisibilityNotify */
136: 0, /* CreateNotify */
137: StructureNotifyMask, /* DestroyNotify */
138: StructureNotifyMask, /* UnmapNotify */
139: StructureNotifyMask, /* MapNotify */
140: 0, /* MapRequest */
141: StructureNotifyMask, /* ReparentNotify */
142: StructureNotifyMask, /* ConfigureNotify */
143: 0, /* ConfigureRequest */
144: StructureNotifyMask, /* GravityNotify */
145: 0, /* ResizeRequest */
146: StructureNotifyMask, /* CirculateNotify */
147: 0, /* CirculateRequest */
148: PropertyChangeMask, /* PropertyNotify */
149: StructureNotifyMask, /* SelectionClear */
150: StructureNotifyMask, /* SelectionRequest */
151: StructureNotifyMask, /* SelectionNotify */
152: ColormapChangeMask, /* ColormapNotify */
153: StructureNotifyMask, /* ClientMessage */
154: StructureNotifyMask /* MappingNotify */
155: };
156:
157: if (event->type >= LASTEvent) return(finalresult);
158:
159: kinds = masks[event->type];
160:
161: nprocs = 0;
162: if (XFindContext(event->xany.display, (Window) 0,
163: eventContext, (caddr_t *)&first))
164: first = ctx;
165: for (evp = first; evp != NULL; evp = (evp == ctx) ? NULL : ctx) {
166: for (p = evp->firstproc; p != NULL; p = p->next) {
167: if (kinds & p->mask) {
168: procs[nprocs] = p->proc;
169: data[nprocs++] = p->data;
170: }
171: }
172: }
173: for (i=0 ; i<nprocs ; i++) {
174: result = (*(procs[i]))(event, data[i]);
175: if (finalresult != XteventHandled)
176: finalresult = result;
177: }
178: return(finalresult);
179: }
180:
181:
182: /* Public routines */
183:
184: /*
185: * Dispatch an event to the appropriate subwindow.
186: * Return a value indicating how the event was handled.
187: */
188: XtEventReturnCode XtDispatchEvent(event)
189: XEvent *event;
190: {
191: EventPtr ctx;
192:
193: if (XFindContext(event->xany.display, event->xany.window,
194: eventContext, (caddr_t *)&ctx) != 0)
195: return XteventNoHandler;
196: else
197: return CallProc(ctx, event);
198: }
199:
200: /*
201: * Register an event handler "proc" for window "w" with the
202: * event dispatcher for "eventMask" events.
203: * Note that re-registering the same window and handler with
204: * a new event mask OVERWRITES the previous eventMask for that
205: * window/handler combination.
206: */
207: void XtSetEventHandler(dpy, w, proc, eventMask, data)
208: Display *dpy;
209: Window w;
210: XtEventHandler proc;
211: unsigned long eventMask;
212: caddr_t data;
213: {
214: register EventPtr ctx;
215: register ProcPtr p, p2;
216: register unsigned long totalmask;
217:
218: ctx = EventPtrFromWindow(dpy, w);
219: if (ctx == NULL) {
220: ctx = (EventPtr)XtMalloc(sizeof(EventRec));
221: ctx->dpy = dpy;
222: ctx->window = w;
223: (void) XSaveContext(dpy, w, eventContext, (caddr_t)ctx);
224: ctx->firstproc = NULL;
225: ctx->totalmask = 0;
226: ctx->master = FALSE;
227: }
228: totalmask = 0;
229: p2 = NULL;
230: p = ctx->firstproc;
231: while (p != NULL && p->proc != proc) {
232: totalmask |= p->mask;
233: p2 = p;
234: p = p->next;
235: }
236: if (p == NULL) {
237: if (eventMask == 0)
238: return;
239: p = (ProcPtr)XtMalloc(sizeof(ProcRec));
240: p->next = ctx->firstproc;
241: ctx->firstproc = p;
242: p->proc = proc;
243: }
244: if (eventMask) {
245: p->mask = eventMask;
246: p->data = data;
247: }
248: else {
249: if (p2)
250: p2->next = p->next;
251: else
252: ctx->firstproc = p->next;
253: p2 = p;
254: p = p->next;
255: XtFree((char *)p2);
256: }
257: totalmask |= eventMask;
258: for (; p != NULL; p = p->next)
259: totalmask |= p->mask;
260: if (totalmask != ctx->totalmask) {
261: ctx->totalmask = totalmask;
262: if (ctx->window) {
263: if (!ctx->master) totalmask &= ~StructureNotifyMask;
264: XSelectInput(dpy, w, totalmask);
265: }
266: }
267: }
268:
269: void XtDeleteEventHandler(dpy, w, proc)
270: Display *dpy;
271: Window w;
272: XtEventHandler proc;
273: {
274: XtSetEventHandler(dpy, w, (XtEventHandler) proc, (unsigned long) 0, (caddr_t) NULL);
275: }
276:
277: /*
278: * Make the given window be treated as a "master" window; that is, one that
279: * is not a child of some other widget.
280: */
281:
282: void XtMakeMaster(dpy, w)
283: Display *dpy;
284: Window w;
285: {
286: EventPtr ctx;
287: XWMHints *hints;
288:
289: ctx = EventPtrFromWindow(dpy, w);
290: if (ctx == NULL) {
291: ctx = (EventPtr)XtMalloc(sizeof(EventRec));
292: ctx->window = w;
293: (void) XSaveContext(dpy, w, eventContext, (caddr_t)ctx);
294: ctx->firstproc = NULL;
295: ctx->totalmask = 0;
296: } else XSelectInput(dpy, w, ctx->totalmask);
297: ctx->master = TRUE;
298: /* ||| Maybe the following stuff doesn't belong here. It's just trying
299: to tell the window manager that we handle our own focus. -TW %%% */
300: hints = XGetWMHints(dpy, w);
301: if (hints == NULL) {
302: hints = (XWMHints *) XtMalloc(sizeof(XWMHints));
303: hints->flags = 0;
304: }
305: hints->flags |= InputHint;
306: hints->input = FALSE;
307: XSetWMHints(dpy, w, hints);
308: XtFree(hints);
309: }
310:
311: /*
312: * Arrange to have the given procedure called whenever ANY event happens
313: * that matches the given mask.
314: */
315: void XtSetGlobalEventHandler(dpy, proc, eventMask, data)
316: Display *dpy;
317: XtEventHandler proc;
318: unsigned long eventMask;
319: caddr_t data;
320: {
321: XtSetEventHandler(dpy, (Window) 0, (XtEventHandler) proc, eventMask, data);
322: }
323:
324: void XtClearEventHandlers(dpy, window)
325: Display *dpy;
326: Window window;
327: {
328: ResetEventHandler(dpy, window);
329: (void) XtClearGeometryHandler(dpy, window);
330: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.