Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libtk/unix/tkUnixDraw.c
1811 views
1
/*
2
* tkUnixDraw.c --
3
*
4
* This file contains X specific drawing routines.
5
*
6
* Copyright (c) 1995 Sun Microsystems, Inc.
7
*
8
* See the file "license.terms" for information on usage and redistribution
9
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10
*
11
* SCCS: @(#) tkUnixDraw.c 1.7 96/02/15 18:55:26
12
*/
13
14
#include "tkInt.h"
15
16
/*
17
* The following structure is used to pass information to
18
* ScrollRestrictProc from TkScrollWindow.
19
*/
20
21
typedef struct ScrollInfo {
22
int done; /* Flag is 0 until filtering is done. */
23
Display *display; /* Display to filter. */
24
Window window; /* Window to filter. */
25
TkRegion region; /* Region into which damage is accumulated. */
26
int dx, dy; /* Amount by which window was shifted. */
27
} ScrollInfo;
28
29
/*
30
* Forward declarations for procedures declared later in this file:
31
*/
32
33
static Tk_RestrictAction ScrollRestrictProc _ANSI_ARGS_((
34
ClientData arg, XEvent *eventPtr));
35
36
/*
37
*----------------------------------------------------------------------
38
*
39
* TkScrollWindow --
40
*
41
* Scroll a rectangle of the specified window and accumulate
42
* damage information in the specified Region.
43
*
44
* Results:
45
* Returns 0 if no damage additional damage was generated. Sets
46
* damageRgn to contain the damaged areas and returns 1 if
47
* GraphicsExpose events were detected.
48
*
49
* Side effects:
50
* Scrolls the bits in the window and enters the event loop
51
* looking for damage events.
52
*
53
*----------------------------------------------------------------------
54
*/
55
56
int
57
TkScrollWindow(tkwin, gc, x, y, width, height, dx, dy, damageRgn)
58
Tk_Window tkwin; /* The window to be scrolled. */
59
GC gc; /* GC for window to be scrolled. */
60
int x, y, width, height; /* Position rectangle to be scrolled. */
61
int dx, dy; /* Distance rectangle should be moved. */
62
TkRegion damageRgn; /* Region to accumulate damage in. */
63
{
64
Tk_RestrictProc *oldProc;
65
ClientData oldArg, dummy;
66
ScrollInfo info;
67
68
XCopyArea(Tk_Display(tkwin), Tk_WindowId(tkwin), Tk_WindowId(tkwin), gc,
69
x, y, (unsigned int) width, (unsigned int) height, x + dx, y + dy);
70
71
info.done = 0;
72
info.window = Tk_WindowId(tkwin);
73
info.display = Tk_Display(tkwin);
74
info.region = damageRgn;
75
info.dx = dx;
76
info.dy = dy;
77
78
/*
79
* Sync the event stream so all of the expose events will be on the
80
* X event queue before we start filtering. This avoids busy waiting
81
* while we filter events.
82
*/
83
84
XSync(info.display, False);
85
oldProc = Tk_RestrictEvents(ScrollRestrictProc, (ClientData) &info,
86
&oldArg);
87
while (!info.done) {
88
Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT);
89
}
90
Tk_RestrictEvents(oldProc, oldArg, &dummy);
91
92
return XEmptyRegion((Region) damageRgn) ? 0 : 1;
93
}
94
95
/*
96
*----------------------------------------------------------------------
97
*
98
* ScrollRestrictProc --
99
*
100
* A Tk_RestrictProc used by TkScrollWindow to gather up Expose
101
* information into a single damage region. It accumulates damage
102
* events on the specified window until a NoExpose or the last
103
* GraphicsExpose event is detected.
104
*
105
* Results:
106
* None.
107
*
108
* Side effects:
109
* Discards Expose events after accumulating damage information
110
* for a particular window.
111
*
112
*----------------------------------------------------------------------
113
*/
114
115
static Tk_RestrictAction
116
ScrollRestrictProc(arg, eventPtr)
117
ClientData arg;
118
XEvent *eventPtr;
119
{
120
ScrollInfo *info = (ScrollInfo *) arg;
121
XRectangle rect;
122
123
/*
124
* Defer events which aren't for the specified window.
125
*/
126
127
if (info->done || (eventPtr->xany.display != info->display)
128
|| (eventPtr->xany.window != info->window)) {
129
return TK_DEFER_EVENT;
130
}
131
132
if (eventPtr->type == NoExpose) {
133
info->done = 1;
134
} else if (eventPtr->type == GraphicsExpose) {
135
rect.x = eventPtr->xgraphicsexpose.x;
136
rect.y = eventPtr->xgraphicsexpose.y;
137
rect.width = eventPtr->xgraphicsexpose.width;
138
rect.height = eventPtr->xgraphicsexpose.height;
139
XUnionRectWithRegion(&rect, (Region) info->region,
140
(Region) info->region);
141
142
if (eventPtr->xgraphicsexpose.count == 0) {
143
info->done = 1;
144
}
145
} else if (eventPtr->type == Expose) {
146
147
/*
148
* This case is tricky. This event was already queued before
149
* the XCopyArea was issued. If this area overlaps the area
150
* being copied, then some of the copied area may be invalid.
151
* The easiest way to handle this case is to mark both the
152
* original area and the shifted area as damaged.
153
*/
154
155
rect.x = eventPtr->xexpose.x;
156
rect.y = eventPtr->xexpose.y;
157
rect.width = eventPtr->xexpose.width;
158
rect.height = eventPtr->xexpose.height;
159
XUnionRectWithRegion(&rect, (Region) info->region,
160
(Region) info->region);
161
rect.x += info->dx;
162
rect.y += info->dy;
163
XUnionRectWithRegion(&rect, (Region) info->region,
164
(Region) info->region);
165
} else {
166
return TK_DEFER_EVENT;
167
}
168
return TK_DISCARD_EVENT;
169
}
170
171
172