Files
cpython-source-deps/unix/tkUnixDraw.c
2017-09-04 14:25:47 -05:00

245 lines
6.3 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 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:
*/