4 * This file contains X specific drawing routines.
6 * Copyright (c) 1995 Sun Microsystems, Inc.
8 * See the file "license.terms" for information on usage and redistribution of
9 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 #include "tkUnixInt.h"
19 * The following structure is used to pass information to ScrollRestrictProc
20 * from TkScrollWindow.
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. */
32 * Forward declarations for functions declared later in this file:
35 static Tk_RestrictProc ScrollRestrictProc;
38 *----------------------------------------------------------------------
42 * Scroll a rectangle of the specified window and accumulate damage
43 * information in the specified Region.
46 * Returns 0 if no damage additional damage was generated. Sets damageRgn
47 * to contain the damaged areas and returns 1 if GraphicsExpose events
51 * Scrolls the bits in the window and enters the event loop looking for
54 *----------------------------------------------------------------------
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. */
66 Tk_RestrictProc *prevProc;
70 XCopyArea(Tk_Display(tkwin), Tk_WindowId(tkwin), Tk_WindowId(tkwin), gc,
71 x, y, (unsigned) width, (unsigned) height, x+dx, y+dy);
74 info.window = Tk_WindowId(tkwin);
75 info.display = Tk_Display(tkwin);
76 info.region = damageRgn;
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
86 TkpSync(info.display);
87 prevProc = Tk_RestrictEvents(ScrollRestrictProc, &info, &prevArg);
89 Tcl_ServiceEvent(TCL_WINDOW_EVENTS);
91 Tk_RestrictEvents(prevProc, prevArg, &prevArg);
93 if (XEmptyRegion((Region) damageRgn)) {
101 *----------------------------------------------------------------------
103 * ScrollRestrictProc --
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
114 * Discards Expose events after accumulating damage information
115 * for a particular window.
117 *----------------------------------------------------------------------
120 static Tk_RestrictAction
125 ScrollInfo *info = (ScrollInfo *) arg;
129 * Defer events which aren't for the specified window.
132 if (info->done || (eventPtr->xany.display != info->display)
133 || (eventPtr->xany.window != info->window)) {
134 return TK_DEFER_EVENT;
137 if (eventPtr->type == NoExpose) {
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);
147 if (eventPtr->xgraphicsexpose.count == 0) {
150 } else if (eventPtr->type == Expose) {
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
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);
167 XUnionRectWithRegion(&rect, (Region) info->region,
168 (Region) info->region);
170 return TK_DEFER_EVENT;
172 return TK_DISCARD_EVENT;
176 *----------------------------------------------------------------------
178 * TkpDrawHighlightBorder --
180 * This function draws a rectangular ring around the outside of a widget
181 * to indicate that it has received the input focus.
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
191 * A rectangle "width" pixels wide is drawn in "drawable", corresponding
192 * to the outer area of "tkwin".
194 *----------------------------------------------------------------------
198 TkpDrawHighlightBorder(
205 TkDrawInsetFocusHighlight(tkwin, fgGC, highlightWidth, drawable, 0);
209 *----------------------------------------------------------------------
213 * This function draws the rectangular frame area.
219 * Draws inside the tkwin area.
221 *----------------------------------------------------------------------
232 Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, highlightWidth,
233 highlightWidth, Tk_Width(tkwin) - 2*highlightWidth,
234 Tk_Height(tkwin) - 2*highlightWidth, borderWidth, relief);