/*ARGSUSED*/ void Tk_SetTSOrigin( Tk_Window tkwin, GC gc, int x, int y) { while (!Tk_TopWinHierarchy(tkwin)) { x -= Tk_X(tkwin) + Tk_Changes(tkwin)->border_width; y -= Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width; tkwin = Tk_Parent(tkwin); } XSetTSOrigin(Tk_Display(tkwin), gc, x, y); }
static void RecomputePlacement( ClientData clientData) /* Pointer to Master record. */ { register Master *masterPtr = clientData; register Slave *slavePtr; int x, y, width, height, tmp; int masterWidth, masterHeight, masterX, masterY; double x1, y1, x2, y2; int abort; /* May get set to non-zero to abort this * placement operation. */ masterPtr->flags &= ~PARENT_RECONFIG_PENDING; /* * Abort any nested call to RecomputePlacement for this window, since * we'll do everything necessary here, and set up so this call can be * aborted if necessary. */ if (masterPtr->abortPtr != NULL) { *masterPtr->abortPtr = 1; } masterPtr->abortPtr = &abort; abort = 0; Tcl_Preserve(masterPtr); /* * Iterate over all the slaves for the master. Each slave's geometry can * be computed independently of the other slaves. Changes to the window's * structure could cause almost anything to happen, including deleting the * parent or child. If this happens, we'll be told to abort. */ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort; slavePtr = slavePtr->nextPtr) { /* * Step 1: compute size and borderwidth of master, taking into account * desired border mode. */ masterX = masterY = 0; masterWidth = Tk_Width(masterPtr->tkwin); masterHeight = Tk_Height(masterPtr->tkwin); if (slavePtr->borderMode == BM_INSIDE) { masterX = Tk_InternalBorderLeft(masterPtr->tkwin); masterY = Tk_InternalBorderTop(masterPtr->tkwin); masterWidth -= masterX + Tk_InternalBorderRight(masterPtr->tkwin); masterHeight -= masterY + Tk_InternalBorderBottom(masterPtr->tkwin); } else if (slavePtr->borderMode == BM_OUTSIDE) { masterX = masterY = -Tk_Changes(masterPtr->tkwin)->border_width; masterWidth -= 2 * masterX; masterHeight -= 2 * masterY; } /* * Step 2: compute size of slave (outside dimensions including border) * and location of anchor point within master. */ x1 = slavePtr->x + masterX + (slavePtr->relX*masterWidth); x = (int) (x1 + ((x1 > 0) ? 0.5 : -0.5)); y1 = slavePtr->y + masterY + (slavePtr->relY*masterHeight); y = (int) (y1 + ((y1 > 0) ? 0.5 : -0.5)); if (slavePtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH)) { width = 0; if (slavePtr->flags & CHILD_WIDTH) { width += slavePtr->width; } if (slavePtr->flags & CHILD_REL_WIDTH) { /* * The code below is a bit tricky. In order to round correctly * when both relX and relWidth are specified, compute the * location of the right edge and round that, then compute * width. If we compute the width and round it, rounding * errors in relX and relWidth accumulate. */ x2 = x1 + (slavePtr->relWidth*masterWidth); tmp = (int) (x2 + ((x2 > 0) ? 0.5 : -0.5)); width += tmp - x; } } else { width = Tk_ReqWidth(slavePtr->tkwin) + 2*Tk_Changes(slavePtr->tkwin)->border_width; } if (slavePtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT)) { height = 0; if (slavePtr->flags & CHILD_HEIGHT) { height += slavePtr->height; } if (slavePtr->flags & CHILD_REL_HEIGHT) { /* * See note above for rounding errors in width computation. */ y2 = y1 + (slavePtr->relHeight*masterHeight); tmp = (int) (y2 + ((y2 > 0) ? 0.5 : -0.5)); height += tmp - y; } } else { height = Tk_ReqHeight(slavePtr->tkwin) + 2*Tk_Changes(slavePtr->tkwin)->border_width; } /* * Step 3: adjust the x and y positions so that the desired anchor * point on the slave appears at that position. Also adjust for the * border mode and master's border. */ switch (slavePtr->anchor) { case TK_ANCHOR_N: x -= width/2; break; case TK_ANCHOR_NE: x -= width; break; case TK_ANCHOR_E: x -= width; y -= height/2; break; case TK_ANCHOR_SE: x -= width; y -= height; break; case TK_ANCHOR_S: x -= width/2; y -= height; break; case TK_ANCHOR_SW: y -= height; break; case TK_ANCHOR_W: y -= height/2; break; case TK_ANCHOR_NW: break; case TK_ANCHOR_CENTER: x -= width/2; y -= height/2; break; } /* * Step 4: adjust width and height again to reflect inside dimensions * of window rather than outside. Also make sure that the width and * height aren't zero. */ width -= 2*Tk_Changes(slavePtr->tkwin)->border_width; height -= 2*Tk_Changes(slavePtr->tkwin)->border_width; if (width <= 0) { width = 1; } if (height <= 0) { height = 1; } /* * Step 5: reconfigure the window and map it if needed. If the slave * is a child of the master, we do this ourselves. If the slave isn't * a child of the master, let Tk_MaintainGeometry do the work (it will * re-adjust things as relevant windows map, unmap, and move). */ if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) { if ((x != Tk_X(slavePtr->tkwin)) || (y != Tk_Y(slavePtr->tkwin)) || (width != Tk_Width(slavePtr->tkwin)) || (height != Tk_Height(slavePtr->tkwin))) { Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height); } if (abort) { break; } /* * Don't map the slave unless the master is mapped: the slave will * get mapped later, when the master is mapped. */ if (Tk_IsMapped(masterPtr->tkwin)) { Tk_MapWindow(slavePtr->tkwin); } } else { if ((width <= 0) || (height <= 0)) { Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin); Tk_UnmapWindow(slavePtr->tkwin); } else { Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin, x, y, width, height); } } } masterPtr->abortPtr = NULL; Tcl_Release(masterPtr); }
static Busy * CreateBusy( Tcl_Interp *interp, /* Interpreter to report error to */ Tk_Window tkRef) /* Window hosting the busy window */ { Busy *busyPtr; int length, x, y; const char *fmt; char *name; Tk_Window tkBusy, tkChild, tkParent; Window parent; Tk_FakeWin *winPtr; busyPtr = (Busy *) ckalloc(sizeof(Busy)); x = y = 0; length = strlen(Tk_Name(tkRef)); name = ckalloc(length + 6); if (Tk_IsTopLevel(tkRef)) { fmt = "_Busy"; /* Child */ tkParent = tkRef; } else { Tk_Window tkwin; fmt = "%s_Busy"; /* Sibling */ tkParent = Tk_Parent(tkRef); for (tkwin = tkRef; (tkwin != NULL) && !Tk_IsTopLevel(tkwin); tkwin = Tk_Parent(tkwin)) { if (tkwin == tkParent) { break; } x += Tk_X(tkwin) + Tk_Changes(tkwin)->border_width; y += Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width; } } for (tkChild = FirstChild(tkParent); tkChild != NULL; tkChild = NextChild(tkChild)) { Tk_MakeWindowExist(tkChild); } sprintf(name, fmt, Tk_Name(tkRef)); tkBusy = Tk_CreateWindow(interp, tkParent, name, NULL); ckfree(name); if (tkBusy == NULL) { return NULL; } Tk_MakeWindowExist(tkRef); busyPtr->display = Tk_Display(tkRef); busyPtr->interp = interp; busyPtr->tkRef = tkRef; busyPtr->tkParent = tkParent; busyPtr->tkBusy = tkBusy; busyPtr->width = Tk_Width(tkRef); busyPtr->height = Tk_Height(tkRef); busyPtr->x = Tk_X(tkRef); busyPtr->y = Tk_Y(tkRef); busyPtr->cursor = None; Tk_SetClass(tkBusy, "Busy"); busyPtr->optionTable = Tk_CreateOptionTable(interp, busyOptionSpecs); if (Tk_InitOptions(interp, (char *) busyPtr, busyPtr->optionTable, tkBusy) != TCL_OK) { Tk_DestroyWindow(tkBusy); return NULL; } SetWindowInstanceData(tkBusy, busyPtr); winPtr = (Tk_FakeWin *) tkRef; TkpCreateBusy(winPtr, tkRef, &parent, tkParent, busyPtr); MakeTransparentWindowExist(tkBusy, parent); Tk_MoveResizeWindow(tkBusy, x, y, busyPtr->width, busyPtr->height); /* * Only worry if the busy window is destroyed. */ Tk_CreateEventHandler(tkBusy, StructureNotifyMask, BusyEventProc, busyPtr); /* * Indicate that the busy window's geometry is being managed. This will * also notify us if the busy window is ever packed. */ Tk_ManageGeometry(tkBusy, &busyMgrInfo, busyPtr); if (busyPtr->cursor != None) { Tk_DefineCursor(tkBusy, busyPtr->cursor); } /* * Track the reference window to see if it is resized or destroyed. */ Tk_CreateEventHandler(tkRef, StructureNotifyMask, RefWinEventProc, busyPtr); return busyPtr; }
static void RefWinEventProc( ClientData clientData, /* Busy window record */ register XEvent *eventPtr) /* Event which triggered call to routine */ { register Busy *busyPtr = clientData; switch (eventPtr->type) { case ReparentNotify: case DestroyNotify: /* * Arrange for the busy structure to be removed at a proper time. */ Tcl_EventuallyFree(busyPtr, DestroyBusy); break; case ConfigureNotify: if ((busyPtr->width != Tk_Width(busyPtr->tkRef)) || (busyPtr->height != Tk_Height(busyPtr->tkRef)) || (busyPtr->x != Tk_X(busyPtr->tkRef)) || (busyPtr->y != Tk_Y(busyPtr->tkRef))) { int x, y; busyPtr->width = Tk_Width(busyPtr->tkRef); busyPtr->height = Tk_Height(busyPtr->tkRef); busyPtr->x = Tk_X(busyPtr->tkRef); busyPtr->y = Tk_Y(busyPtr->tkRef); x = y = 0; if (busyPtr->tkParent != busyPtr->tkRef) { Tk_Window tkwin; for (tkwin = busyPtr->tkRef; (tkwin != NULL) && (!Tk_IsTopLevel(tkwin)); tkwin = Tk_Parent(tkwin)) { if (tkwin == busyPtr->tkParent) { break; } x += Tk_X(tkwin) + Tk_Changes(tkwin)->border_width; y += Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width; } } if (busyPtr->tkBusy != NULL) { Tk_MoveResizeWindow(busyPtr->tkBusy, x, y, busyPtr->width, busyPtr->height); TkpShowBusyWindow(busyPtr); } } break; case MapNotify: if (busyPtr->tkParent != busyPtr->tkRef) { TkpShowBusyWindow(busyPtr); } break; case UnmapNotify: if (busyPtr->tkParent != busyPtr->tkRef) { TkpHideBusyWindow(busyPtr); } break; } }