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