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