|
|
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 - metrics - 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();
}