Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libtk/unix/tkUnixEvent.c
1811 views
1
/*
2
* tkUnixEvent.c --
3
*
4
* This file implements an event source for X displays for the
5
* UNIX version of Tk.
6
*
7
* Copyright (c) 1995 Sun Microsystems, Inc.
8
*
9
* See the file "license.terms" for information on usage and redistribution
10
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
*
12
* SCCS: @(#) tkUnixEvent.c 1.5 96/02/15 18:55:30
13
*/
14
15
#include "tkInt.h"
16
#include "tkUnixInt.h"
17
#include <signal.h>
18
19
/*
20
* Prototypes for procedures that are referenced only in this file:
21
*/
22
23
static void DisplayCheckProc _ANSI_ARGS_((ClientData clientData,
24
int flags));
25
static void DisplaySetupProc _ANSI_ARGS_((ClientData clientData,
26
int flags));
27
28
/*
29
*----------------------------------------------------------------------
30
*
31
* DisplaySetupProc --
32
*
33
* This procedure is part of the event source for UNIX X displays.
34
* It is invoked by Tcl_DoOneEvent before it calls select to check
35
* for events on all displays.
36
*
37
* Results:
38
* None.
39
*
40
* Side effects:
41
* Tells the notifier which files should be waited for.
42
*
43
*----------------------------------------------------------------------
44
*/
45
46
static void
47
DisplaySetupProc(clientData, flags)
48
ClientData clientData; /* Not used. */
49
int flags; /* Flags passed to Tk_DoOneEvent:
50
* if it doesn't include
51
* TCL_WINDOW_EVENTS then we do
52
* nothing. */
53
{
54
TkDisplay *dispPtr;
55
static Tcl_Time dontBlock = {0, 0};
56
57
if (!(flags & TCL_WINDOW_EVENTS)) {
58
return;
59
}
60
61
for (dispPtr = tkDisplayList; dispPtr != NULL; dispPtr = dispPtr->nextPtr) {
62
Tcl_File handle;
63
XFlush(dispPtr->display);
64
if (XQLength(dispPtr->display) > 0) {
65
Tcl_SetMaxBlockTime(&dontBlock);
66
}
67
handle = Tcl_GetFile(
68
(ClientData)ConnectionNumber(dispPtr->display), TCL_UNIX_FD);
69
Tcl_WatchFile(handle, TCL_READABLE);
70
}
71
}
72
73
/*
74
*----------------------------------------------------------------------
75
*
76
* DisplayCheckProc --
77
*
78
* This procedure is the second part of the "event source" for
79
* X displays. It is invoked by Tcl_DoOneEvent after it calls
80
* select (or whatever it uses to wait for events).
81
*
82
* Results:
83
* None.
84
*
85
* Side effects:
86
* Makes entries on the Tcl event queue for all the events available
87
* from all the displays.
88
*
89
*----------------------------------------------------------------------
90
*/
91
92
static void
93
DisplayCheckProc(clientData, flags)
94
ClientData clientData; /* Not used. */
95
int flags; /* Flags passed to Tk_DoOneEvent:
96
* if it doesn't include
97
* TCL_WINDOW_EVENTS then we do
98
* nothing. */
99
{
100
TkDisplay *dispPtr;
101
XEvent event;
102
int numFound;
103
104
if (!(flags & TCL_WINDOW_EVENTS)) {
105
return;
106
}
107
108
for (dispPtr = tkDisplayList; dispPtr != NULL; dispPtr = dispPtr->nextPtr) {
109
Tcl_File handle;
110
/*
111
* Note: we should not need to do a flush of the output queues before
112
* calling XEventsQueued because it was done by DisplaySetupProc.
113
*/
114
115
handle = Tcl_GetFile(
116
(ClientData) ConnectionNumber(dispPtr->display), TCL_UNIX_FD);
117
if (Tcl_FileReady(handle, TCL_READABLE) != 0) {
118
numFound = XEventsQueued(dispPtr->display, QueuedAfterReading);
119
if (numFound == 0) {
120
121
/*
122
* Things are very tricky if there aren't any events readable
123
* at this point (after all, there was supposedly data
124
* available on the connection). A couple of things could
125
* have occurred:
126
*
127
* One possibility is that there were only error events in the
128
* input from the server. If this happens, we should return
129
* (we don't want to go to sleep in XNextEvent below, since
130
* this would block out other sources of input to the
131
* process).
132
*
133
* Another possibility is that our connection to the server
134
* has been closed. This will not necessarily be detected in
135
* XEventsQueued (!!), so if we just return then there will be
136
* an infinite loop. To detect such an error, generate a NoOp
137
* protocol request to exercise the connection to the server,
138
* then return. However, must disable SIGPIPE while sending
139
* the request, or else the process will die from the signal
140
* and won't invoke the X error function to print a nice (?!)
141
* message.
142
*/
143
144
void (*oldHandler)();
145
146
oldHandler = (void (*)()) signal(SIGPIPE, SIG_IGN);
147
XNoOp(dispPtr->display);
148
XFlush(dispPtr->display);
149
(void) signal(SIGPIPE, oldHandler);
150
}
151
} else {
152
numFound = XQLength(dispPtr->display);
153
}
154
155
/*
156
* Transfer events from the X event queue to the Tk event queue.
157
*/
158
159
while (numFound > 0) {
160
XNextEvent(dispPtr->display, &event);
161
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
162
numFound--;
163
}
164
}
165
}
166
167
/*
168
*----------------------------------------------------------------------
169
*
170
* TkCreateXEventSource --
171
*
172
* This procedure is called during Tk initialization to create
173
* the event source for X Window events.
174
*
175
* Results:
176
* None.
177
*
178
* Side effects:
179
* A new event source is created.
180
*
181
*----------------------------------------------------------------------
182
*/
183
184
void
185
TkCreateXEventSource()
186
{
187
static int initialized = 0;
188
189
if (!initialized) {
190
Tcl_CreateEventSource(DisplaySetupProc, DisplayCheckProc,
191
(ClientData) NULL);
192
initialized = 1;
193
}
194
}
195
196