|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ E T ┃
Length: 10098 (0x2772) Types: TextFile Names: »Event.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─ ⟦526ad3590⟧ »EUUGD11/gnu-31mar87/X.V10.R4.tar.Z« └─⟦2109abc41⟧ └─ ⟦this⟧ »./X.V10R4/Toolkit/DECToolkit/src/Event.c«
/* * $Source: /u1/X/DECToolkit/src/RCS/Event.c,v $ * $Header: Event.c,v 1.1 86/12/17 09:01:19 swick Exp $ */ #ifndef lint static char *rcsid_Event_c = "$Header: Event.c,v 1.1 86/12/17 09:01:19 swick Exp $"; #endif lint #ifndef lint static char *sccsid = "@(#)Event.c 1.10 12/11/86"; #endif lint /* * COPYRIGHT 1986 * DIGITAL EQUIPMENT CORPORATION * MAYNARD, MASSACHUSETTS * ALL RIGHTS RESERVED. * * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. * * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS, * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT * SET FORTH ABOVE. * * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting documentation, * and that the name of Digital Equipment Corporation not be used in advertising * or publicity pertaining to distribution of the software without specific, * written prior permission. */ /* File: Event.c */ #include <X/Xlib.h> #include "Toolkit.h" /* * General Comment: * This file contains much code that compensates for deficiencies * under X10. For example, it synthesizes the ResizeWindow event * and mungs with the ordering of ExposeWindow events. Massive * changes to this file (mostly lobotomies) will be required when * porting this code to X11. Performance under X11 should be much * faster (and the code should be easier to read!). --mjg */ /* Private Definitions */ #define GRABEVENTS (KeyPressed | KeyReleased | ButtonPressed | \ ButtonReleased | MouseMoved) typedef struct _ProcRec { int (*proc)(); int mask; caddr_t data; struct _ProcRec *next; } ProcRec, *ProcPtr; typedef struct _EventRec { Window window; int width, height; /* Size of window, last we knew. */ int needsexpose; /* Whether we need to expose this window. */ struct _EventRec *nextexpose; ProcPtr firstproc; int totalmask; short disableautograb; } EventRec, *EventPtr; extern char *Tmalloc(); static TEntryType eventContext; static int initialized = FALSE; EventPtr FirstExpose = 0; EventRec GlobalCtx; static TEntryType autograbContext; static int AutoGrab,GrabOn; static Window GrabWindow; /* Private Routines */ static int Initialize() { eventContext = UniqueEntryType(); autograbContext = UniqueEntryType(); initialized = TRUE; GlobalCtx.firstproc = NULL; GlobalCtx.window = 0; SaveEntry(0, eventContext, &GlobalCtx); } static EventPtr EventPtrFromWindow(w) { EventPtr result; if (FindEntry(w, eventContext, &result) == ERRNONE) return(result); return(0); } /* * Delete the event handler reference in the dispatcher for this window. */ static ResetXEventDispatch(w) Window w; { EventPtr ctx; ProcPtr p, p2; ctx = EventPtrFromWindow(w); if (!ctx) return(ERRNOTFOUND); if (ctx->needsexpose) ctx->needsexpose = 2; /* Cause it to be freed later. */ else { for (p=ctx->firstproc ; p != NULL ; p2 = p->next, free(p), p = p2) /* NULL */; free(ctx); } return(DeleteEntry(w, eventContext)); } static int CallProc(ctx, event) EventPtr ctx; XEvent *event; { EventPtr first; ProcPtr p; int type, result; int finalresult = NOENTRY; type = event->type; /* * The following hack gets around the problem of * no "ResizeWindow" event under X10. */ if (type == ResizeWindow) /* HACK %%% */ type = ExposeWindow; /* HACK %%% */ for (first = &GlobalCtx; first != NULL; first = (first == ctx) ? NULL : ctx) { for (p = first->firstproc; p != NULL; p = p->next) { if (type & p->mask || ((type & MouseMoved) && (p->mask & (LeftDownMotion | MiddleDownMotion | RightDownMotion)))) { result = p->proc(event, p->data); if (finalresult != PROCESSED) finalresult = result; } } } return(finalresult); } /* Public routines */ /* * Dispatch an event to the appropriate subwindow. * Return a value indicating how the event was handled. * Note that all of the hair in this procedure is due to * limitations in X10 that will be fixed in X11. */ int TDispatchXEvent(event) XEvent *event; { EventPtr ctx; int error; int result; if (event->type == ButtonPressed) { error = FindEntry(event->window, autograbContext, &AutoGrab); if (error == ERRNOTFOUND) AutoGrab = FALSE; GrabWindow = event->window; } if ((GrabOn || AutoGrab) && ((event->type & GRABEVENTS))) { XKeyOrButtonEvent * ev = (XKeyOrButtonEvent *) event; ev->window = GrabWindow; XInterpretLocator(GrabWindow, &(ev->x), &(ev->y), &(ev->subwindow), ev->location); } if (event->type == ButtonReleased) AutoGrab = FALSE; error = FindEntry(event->window, eventContext, &ctx); if (error != ERRNONE) result = NOENTRY; else { if (event->type == ExposeWindow && event->subwindow == 0) { XExposeWindowEvent *ev = (XExposeWindowEvent *) event; if (ctx->width != ev->width || ctx->height != ev->height) { ev->type = ResizeWindow; CallProc(ctx, ev); ctx->width = ev->width; ctx->height = ev->height; } if (!ctx->needsexpose) { ctx->needsexpose = TRUE; ctx->nextexpose = FirstExpose; FirstExpose = ctx; } result = PROCESSED; } else result = CallProc(ctx, event); } if (FirstExpose && QLength() == 0) { XExposeWindowEvent ev; XSync(0); while (FirstExpose && QLength() == 0) { ev.type = ExposeWindow; ev.window = FirstExpose->window; ev.detail = 0; ev.width = FirstExpose->width; ev.height = FirstExpose->height; ev.subwindow = 0; ev.x = ev.y = 0; if (FirstExpose->needsexpose == 2) { ctx = FirstExpose; FirstExpose = FirstExpose->nextexpose; free(ctx); } else { CallProc(FirstExpose, &ev); FirstExpose->needsexpose = FALSE; FirstExpose = FirstExpose->nextexpose; } } } return(result); } /* * Register an event handler "proc" for window "w" with the * event dispatcher for "eventmask" events. * Note that re-registering the same window and handler with * a new event mask OVERWRITES the previous eventmask for that * window/handler combination. */ int TSetXEventDispatch(w, proc, eventmask, data) Window w; int (*proc)(); int eventmask; caddr_t data; { EventPtr ctx; ProcPtr p, p2; int totalmask; if (initialized == FALSE) Initialize(); ctx = EventPtrFromWindow(w); if (ctx == 0) { ctx = (EventPtr)Tmalloc(sizeof(EventRec)); ctx->window = w; ctx->width = 0; ctx->height = 0; ctx->needsexpose = FALSE; SaveEntry(w, eventContext, ctx); ctx->firstproc = NULL; ctx->totalmask = 0; ctx->disableautograb = FALSE; } totalmask = 0; p2 = NULL; p = ctx->firstproc; while (p != NULL && p->proc != proc) { totalmask |= p->mask; p2 = p; p = p->next; } if (p == NULL) { if (eventmask == 0) return; p = (ProcPtr)Tmalloc(sizeof(ProcRec)); p->next = ctx->firstproc; ctx->firstproc = p; p->proc = proc; } if (eventmask) { p->mask = eventmask; p->data = data; } else { if (p2) p2->next = p->next; else ctx->firstproc = p->next; p2 = p; p = p->next; free(p2); } totalmask |= eventmask; for (; p != NULL; p = p->next) totalmask |= p->mask; if (totalmask != ctx->totalmask) { ctx->totalmask = totalmask; if (ctx->window) { if ((totalmask & ButtonPressed) && (totalmask & ButtonReleased) && (!(ctx->disableautograb))) SaveEntry(w, autograbContext, TRUE); else DeleteEntry(w, autograbContext); XSelectInput(w, totalmask); } } } /* * Arrange to have the given procedure called whenever ANY event happens * that matches the given mask. */ TSetNotify(proc, mask, data) int (*proc)(); int mask; caddr_t data; { TSetXEventDispatch(0, proc, mask, data); } TDisableAutoGrab(w) Window w; { EventPtr ctx; ctx = EventPtrFromWindow(w); if (ctx) { ctx->disableautograb = TRUE; DeleteEntry(w, autograbContext); } } TEnableAutoGrab(w) Window w; { EventPtr ctx; ctx = EventPtrFromWindow(w); if (ctx) { ctx->disableautograb = FALSE; if ((ctx->totalmask & ButtonPressed) && (ctx->totalmask & ButtonReleased)) SaveEntry(w, autograbContext, TRUE); } } TDestroyWindow(window) Window window; { if (GrabWindow == window) AutoGrab = GrabOn = FALSE; ResetXEventDispatch(window); TClearGeometryRequest(window); DeleteEntry(window, autograbContext); XDestroyWindow(window); } TGrabMouse(w, cursor, mask) Window w; Cursor cursor; int mask; { GrabOn = TRUE; GrabWindow = w; XGrabMouse(w, cursor, mask); } TUngrabMouse() { GrabOn = FALSE; XUngrabMouse(); }