Import Tk 8.6.6 (as of svn r86089)
This commit is contained in:
243
unix/tkUnixDraw.c
Normal file
243
unix/tkUnixDraw.c
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#ifndef _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_RestrictProc ScrollRestrictProc;
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* 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 *prevProc;
|
||||
ClientData prevArg;
|
||||
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);
|
||||
prevProc = Tk_RestrictEvents(ScrollRestrictProc, &info, &prevArg);
|
||||
while (!info.done) {
|
||||
Tcl_ServiceEvent(TCL_WINDOW_EVENTS);
|
||||
}
|
||||
Tk_RestrictEvents(prevProc, prevArg, &prevArg);
|
||||
|
||||
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:
|
||||
*/
|
||||
Reference in New Issue
Block a user