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 of
9 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
10 */
11
12 #include "tkInt.h"
13
14 #ifndef _WIN32
15 #include "tkUnixInt.h"
16 #endif
17
18 /*
19 * The following structure is used to pass information to ScrollRestrictProc
20 * from TkScrollWindow.
21 */
22
23 typedef struct ScrollInfo {
24 int done; /* Flag is 0 until filtering is done. */
25 Display *display; /* Display to filter. */
26 Window window; /* Window to filter. */
27 TkRegion region; /* Region into which damage is accumulated. */
28 int dx, dy; /* Amount by which window was shifted. */
29 } ScrollInfo;
30
31 /*
32 * Forward declarations for functions declared later in this file:
33 */
34
35 static Tk_RestrictProc ScrollRestrictProc;
36
37 /*
38 *----------------------------------------------------------------------
39 *
40 * TkScrollWindow --
41 *
42 * Scroll a rectangle of the specified window and accumulate damage
43 * information in the specified Region.
44 *
45 * Results:
46 * Returns 0 if no damage additional damage was generated. Sets damageRgn
47 * to contain the damaged areas and returns 1 if GraphicsExpose events
48 * were detected.
49 *
50 * Side effects:
51 * Scrolls the bits in the window and enters the event loop looking for
52 * damage events.
53 *
54 *----------------------------------------------------------------------
55 */
56
57 int
TkScrollWindow(Tk_Window tkwin,GC gc,int x,int y,int width,int height,int dx,int dy,TkRegion damageRgn)58 TkScrollWindow(
59 Tk_Window tkwin, /* The window to be scrolled. */
60 GC gc, /* GC for window to be scrolled. */
61 int x, int y, int width, int height,
62 /* Position rectangle to be scrolled. */
63 int dx, int dy, /* Distance rectangle should be moved. */
64 TkRegion damageRgn) /* Region to accumulate damage in. */
65 {
66 Tk_RestrictProc *prevProc;
67 ClientData prevArg;
68 ScrollInfo info;
69
70 XCopyArea(Tk_Display(tkwin), Tk_WindowId(tkwin), Tk_WindowId(tkwin), gc,
71 x, y, (unsigned) width, (unsigned) height, x+dx, y+dy);
72
73 info.done = 0;
74 info.window = Tk_WindowId(tkwin);
75 info.display = Tk_Display(tkwin);
76 info.region = damageRgn;
77 info.dx = dx;
78 info.dy = dy;
79
80 /*
81 * Sync the event stream so all of the expose events will be on the Tk
82 * event queue before we start filtering. This avoids busy waiting while
83 * we filter events.
84 */
85
86 TkpSync(info.display);
87 prevProc = Tk_RestrictEvents(ScrollRestrictProc, &info, &prevArg);
88 while (!info.done) {
89 Tcl_ServiceEvent(TCL_WINDOW_EVENTS);
90 }
91 Tk_RestrictEvents(prevProc, prevArg, &prevArg);
92
93 if (XEmptyRegion((Region) damageRgn)) {
94 return 0;
95 } else {
96 return 1;
97 }
98 }
99
100 /*
101 *----------------------------------------------------------------------
102 *
103 * ScrollRestrictProc --
104 *
105 * A Tk_RestrictProc used by TkScrollWindow to gather up Expose
106 * information into a single damage region. It accumulates damage events
107 * on the specified window until a NoExpose or the last GraphicsExpose
108 * event is detected.
109 *
110 * Results:
111 * None.
112 *
113 * Side effects:
114 * Discards Expose events after accumulating damage information
115 * for a particular window.
116 *
117 *----------------------------------------------------------------------
118 */
119
120 static Tk_RestrictAction
ScrollRestrictProc(ClientData arg,XEvent * eventPtr)121 ScrollRestrictProc(
122 ClientData arg,
123 XEvent *eventPtr)
124 {
125 ScrollInfo *info = (ScrollInfo *) arg;
126 XRectangle rect;
127
128 /*
129 * Defer events which aren't for the specified window.
130 */
131
132 if (info->done || (eventPtr->xany.display != info->display)
133 || (eventPtr->xany.window != info->window)) {
134 return TK_DEFER_EVENT;
135 }
136
137 if (eventPtr->type == NoExpose) {
138 info->done = 1;
139 } else if (eventPtr->type == GraphicsExpose) {
140 rect.x = eventPtr->xgraphicsexpose.x;
141 rect.y = eventPtr->xgraphicsexpose.y;
142 rect.width = eventPtr->xgraphicsexpose.width;
143 rect.height = eventPtr->xgraphicsexpose.height;
144 XUnionRectWithRegion(&rect, (Region) info->region,
145 (Region) info->region);
146
147 if (eventPtr->xgraphicsexpose.count == 0) {
148 info->done = 1;
149 }
150 } else if (eventPtr->type == Expose) {
151 /*
152 * This case is tricky. This event was already queued before the
153 * XCopyArea was issued. If this area overlaps the area being copied,
154 * then some of the copied area may be invalid. The easiest way to
155 * handle this case is to mark both the original area and the shifted
156 * area as damaged.
157 */
158
159 rect.x = eventPtr->xexpose.x;
160 rect.y = eventPtr->xexpose.y;
161 rect.width = eventPtr->xexpose.width;
162 rect.height = eventPtr->xexpose.height;
163 XUnionRectWithRegion(&rect, (Region) info->region,
164 (Region) info->region);
165 rect.x += info->dx;
166 rect.y += info->dy;
167 XUnionRectWithRegion(&rect, (Region) info->region,
168 (Region) info->region);
169 } else {
170 return TK_DEFER_EVENT;
171 }
172 return TK_DISCARD_EVENT;
173 }
174
175 /*
176 *----------------------------------------------------------------------
177 *
178 * TkpDrawHighlightBorder --
179 *
180 * This function draws a rectangular ring around the outside of a widget
181 * to indicate that it has received the input focus.
182 *
183 * On Unix, we just draw the simple inset ring. On other sytems, e.g. the
184 * Mac, the focus ring is a little more complicated, so we need this
185 * abstraction.
186 *
187 * Results:
188 * None.
189 *
190 * Side effects:
191 * A rectangle "width" pixels wide is drawn in "drawable", corresponding
192 * to the outer area of "tkwin".
193 *
194 *----------------------------------------------------------------------
195 */
196
197 void
TkpDrawHighlightBorder(Tk_Window tkwin,GC fgGC,GC bgGC,int highlightWidth,Drawable drawable)198 TkpDrawHighlightBorder(
199 Tk_Window tkwin,
200 GC fgGC,
201 GC bgGC,
202 int highlightWidth,
203 Drawable drawable)
204 {
205 TkDrawInsetFocusHighlight(tkwin, fgGC, highlightWidth, drawable, 0);
206 }
207
208 /*
209 *----------------------------------------------------------------------
210 *
211 * TkpDrawFrame --
212 *
213 * This function draws the rectangular frame area.
214 *
215 * Results:
216 * None.
217 *
218 * Side effects:
219 * Draws inside the tkwin area.
220 *
221 *----------------------------------------------------------------------
222 */
223
224 void
TkpDrawFrame(Tk_Window tkwin,Tk_3DBorder border,int highlightWidth,int borderWidth,int relief)225 TkpDrawFrame(
226 Tk_Window tkwin,
227 Tk_3DBorder border,
228 int highlightWidth,
229 int borderWidth,
230 int relief)
231 {
232 Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, highlightWidth,
233 highlightWidth, Tk_Width(tkwin) - 2*highlightWidth,
234 Tk_Height(tkwin) - 2*highlightWidth, borderWidth, relief);
235 }
236
237 /*
238 * Local Variables:
239 * mode: c
240 * c-basic-offset: 4
241 * fill-column: 78
242 * End:
243 */
244