OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / tk8.6.12 / unix / tkUnixDraw.c
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 \f
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
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 \f
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
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 \f
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
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 \f
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
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 \f
237 /*
238  * Local Variables:
239  * mode: c
240  * c-basic-offset: 4
241  * fill-column: 78
242  * End:
243  */