1 /*
2 * tkCanvWind.c --
3 *
4 * This file implements window items for canvas widgets.
5 *
6 * Copyright (c) 1992-1994 The Regents of the University of California.
7 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
8 *
9 * See the file "license.terms" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 *
12 * SCCS: @(#) tkCanvWind.c 1.26 96/09/06 08:41:52
13 */
14
15 #include "tkInt.h"
16 #include "tkCanvas.h"
17
18 /*
19 * The structure below defines the record for each window item.
20 */
21
22 typedef struct WindowItem {
23 Tk_Item header; /* Generic stuff that's the same for all
24 * types. MUST BE FIRST IN STRUCTURE. */
25 double x, y; /* Coordinates of positioning point for
26 * window. */
27 Tk_Window tkwin; /* Window associated with item. NULL means
28 * window has been destroyed. */
29 int width; /* Width to use for window (<= 0 means use
30 * window's requested width). */
31 int height; /* Width to use for window (<= 0 means use
32 * window's requested width). */
33 Tk_Anchor anchor; /* Where to anchor window relative to
34 * (x,y). */
35 Tk_Canvas canvas; /* Canvas containing this item. */
36 } WindowItem;
37
38 /*
39 * Information used for parsing configuration specs:
40 */
41
42 static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
43 Tk_CanvasTagsPrintProc, (ClientData) NULL
44 };
45
46 static Tk_ConfigSpec configSpecs[] = {
47 {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
48 "center", Tk_Offset(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
49 {TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL,
50 "0", Tk_Offset(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT},
51 {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
52 (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
53 {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
54 "0", Tk_Offset(WindowItem, width), TK_CONFIG_DONT_SET_DEFAULT},
55 {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL,
56 (char *) NULL, Tk_Offset(WindowItem, tkwin), TK_CONFIG_NULL_OK},
57 {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
58 (char *) NULL, 0, 0}
59 };
60
61 /*
62 * Prototypes for procedures defined in this file:
63 */
64
65 static void ComputeWindowBbox _ANSI_ARGS_((Tk_Canvas canvas,
66 WindowItem *winItemPtr));
67 static int ConfigureWinItem _ANSI_ARGS_((Tcl_Interp *interp,
68 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
69 char **argv, int flags));
70 static int CreateWinItem _ANSI_ARGS_((Tcl_Interp *interp,
71 Tk_Canvas canvas, struct Tk_Item *itemPtr,
72 int argc, char **argv));
73 static void DeleteWinItem _ANSI_ARGS_((Tk_Canvas canvas,
74 Tk_Item *itemPtr, Display *display));
75 static void DisplayWinItem _ANSI_ARGS_((Tk_Canvas canvas,
76 Tk_Item *itemPtr, Display *display, Drawable dst,
77 int x, int y, int width, int height));
78 static void ScaleWinItem _ANSI_ARGS_((Tk_Canvas canvas,
79 Tk_Item *itemPtr, double originX, double originY,
80 double scaleX, double scaleY));
81 static void TranslateWinItem _ANSI_ARGS_((Tk_Canvas canvas,
82 Tk_Item *itemPtr, double deltaX, double deltaY));
83 static int WinItemCoords _ANSI_ARGS_((Tcl_Interp *interp,
84 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
85 char **argv));
86 static void WinItemLostSlaveProc _ANSI_ARGS_((
87 ClientData clientData, Tk_Window tkwin));
88 static void WinItemRequestProc _ANSI_ARGS_((ClientData clientData,
89 Tk_Window tkwin));
90 static void WinItemStructureProc _ANSI_ARGS_((
91 ClientData clientData, XEvent *eventPtr));
92 static int WinItemToArea _ANSI_ARGS_((Tk_Canvas canvas,
93 Tk_Item *itemPtr, double *rectPtr));
94 static double WinItemToPoint _ANSI_ARGS_((Tk_Canvas canvas,
95 Tk_Item *itemPtr, double *pointPtr));
96
97 /*
98 * The structure below defines the window item type by means of procedures
99 * that can be invoked by generic item code.
100 */
101
102 Tk_ItemType tkWindowType = {
103 "window", /* name */
104 sizeof(WindowItem), /* itemSize */
105 CreateWinItem, /* createProc */
106 configSpecs, /* configSpecs */
107 ConfigureWinItem, /* configureProc */
108 WinItemCoords, /* coordProc */
109 DeleteWinItem, /* deleteProc */
110 DisplayWinItem, /* displayProc */
111 1, /* alwaysRedraw */
112 WinItemToPoint, /* pointProc */
113 WinItemToArea, /* areaProc */
114 (Tk_ItemPostscriptProc *) NULL, /* postscriptProc */
115 ScaleWinItem, /* scaleProc */
116 TranslateWinItem, /* translateProc */
117 (Tk_ItemIndexProc *) NULL, /* indexProc */
118 (Tk_ItemCursorProc *) NULL, /* cursorProc */
119 (Tk_ItemSelectionProc *) NULL, /* selectionProc */
120 (Tk_ItemInsertProc *) NULL, /* insertProc */
121 (Tk_ItemDCharsProc *) NULL, /* dTextProc */
122 (Tk_ItemType *) NULL /* nextPtr */
123 };
124
125
126 /*
127 * The structure below defines the official type record for the
128 * placer:
129 */
130
131 static Tk_GeomMgr canvasGeomType = {
132 "canvas", /* name */
133 WinItemRequestProc, /* requestProc */
134 WinItemLostSlaveProc, /* lostSlaveProc */
135 };
136
137 /*
138 *--------------------------------------------------------------
139 *
140 * CreateWinItem --
141 *
142 * This procedure is invoked to create a new window
143 * item in a canvas.
144 *
145 * Results:
146 * A standard Tcl return value. If an error occurred in
147 * creating the item, then an error message is left in
148 * interp->result; in this case itemPtr is
149 * left uninitialized, so it can be safely freed by the
150 * caller.
151 *
152 * Side effects:
153 * A new window item is created.
154 *
155 *--------------------------------------------------------------
156 */
157
158 static int
CreateWinItem(interp,canvas,itemPtr,argc,argv)159 CreateWinItem(interp, canvas, itemPtr, argc, argv)
160 Tcl_Interp *interp; /* Interpreter for error reporting. */
161 Tk_Canvas canvas; /* Canvas to hold new item. */
162 Tk_Item *itemPtr; /* Record to hold new item; header
163 * has been initialized by caller. */
164 int argc; /* Number of arguments in argv. */
165 char **argv; /* Arguments describing rectangle. */
166 {
167 WindowItem *winItemPtr = (WindowItem *) itemPtr;
168
169 if (argc < 2) {
170 Tcl_AppendResult(interp, "wrong # args: should be \"",
171 Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
172 itemPtr->typePtr->name, " x y ?options?\"",
173 (char *) NULL);
174 return TCL_ERROR;
175 }
176
177 /*
178 * Initialize item's record.
179 */
180
181 winItemPtr->tkwin = NULL;
182 winItemPtr->width = 0;
183 winItemPtr->height = 0;
184 winItemPtr->anchor = TK_ANCHOR_CENTER;
185 winItemPtr->canvas = canvas;
186
187 /*
188 * Process the arguments to fill in the item record.
189 */
190
191 if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &winItemPtr->x) != TCL_OK)
192 || (Tk_CanvasGetCoord(interp, canvas, argv[1],
193 &winItemPtr->y) != TCL_OK)) {
194 return TCL_ERROR;
195 }
196
197 if (ConfigureWinItem(interp, canvas, itemPtr, argc-2, argv+2, 0)
198 != TCL_OK) {
199 DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
200 return TCL_ERROR;
201 }
202 return TCL_OK;
203 }
204
205 /*
206 *--------------------------------------------------------------
207 *
208 * WinItemCoords --
209 *
210 * This procedure is invoked to process the "coords" widget
211 * command on window items. See the user documentation for
212 * details on what it does.
213 *
214 * Results:
215 * Returns TCL_OK or TCL_ERROR, and sets interp->result.
216 *
217 * Side effects:
218 * The coordinates for the given item may be changed.
219 *
220 *--------------------------------------------------------------
221 */
222
223 static int
WinItemCoords(interp,canvas,itemPtr,argc,argv)224 WinItemCoords(interp, canvas, itemPtr, argc, argv)
225 Tcl_Interp *interp; /* Used for error reporting. */
226 Tk_Canvas canvas; /* Canvas containing item. */
227 Tk_Item *itemPtr; /* Item whose coordinates are to be
228 * read or modified. */
229 int argc; /* Number of coordinates supplied in
230 * argv. */
231 char **argv; /* Array of coordinates: x1, y1,
232 * x2, y2, ... */
233 {
234 WindowItem *winItemPtr = (WindowItem *) itemPtr;
235 char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE];
236
237 if (argc == 0) {
238 Tcl_PrintDouble(interp, winItemPtr->x, x);
239 Tcl_PrintDouble(interp, winItemPtr->y, y);
240 Tcl_AppendResult(interp, x, " ", y, (char *) NULL);
241 } else if (argc == 2) {
242 if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &winItemPtr->x)
243 != TCL_OK) || (Tk_CanvasGetCoord(interp, canvas, argv[1],
244 &winItemPtr->y) != TCL_OK)) {
245 return TCL_ERROR;
246 }
247 ComputeWindowBbox(canvas, winItemPtr);
248 } else {
249 sprintf(interp->result,
250 "wrong # coordinates: expected 0 or 2, got %d", argc);
251 return TCL_ERROR;
252 }
253 return TCL_OK;
254 }
255
256 /*
257 *--------------------------------------------------------------
258 *
259 * ConfigureWinItem --
260 *
261 * This procedure is invoked to configure various aspects
262 * of a window item, such as its anchor position.
263 *
264 * Results:
265 * A standard Tcl result code. If an error occurs, then
266 * an error message is left in interp->result.
267 *
268 * Side effects:
269 * Configuration information may be set for itemPtr.
270 *
271 *--------------------------------------------------------------
272 */
273
274 static int
ConfigureWinItem(interp,canvas,itemPtr,argc,argv,flags)275 ConfigureWinItem(interp, canvas, itemPtr, argc, argv, flags)
276 Tcl_Interp *interp; /* Used for error reporting. */
277 Tk_Canvas canvas; /* Canvas containing itemPtr. */
278 Tk_Item *itemPtr; /* Window item to reconfigure. */
279 int argc; /* Number of elements in argv. */
280 char **argv; /* Arguments describing things to configure. */
281 int flags; /* Flags to pass to Tk_ConfigureWidget. */
282 {
283 WindowItem *winItemPtr = (WindowItem *) itemPtr;
284 Tk_Window oldWindow;
285 Tk_Window canvasTkwin;
286
287 oldWindow = winItemPtr->tkwin;
288 canvasTkwin = Tk_CanvasTkwin(canvas);
289 if (Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, argc, argv,
290 (char *) winItemPtr, flags) != TCL_OK) {
291 return TCL_ERROR;
292 }
293
294 /*
295 * A few of the options require additional processing.
296 */
297
298 if (oldWindow != winItemPtr->tkwin) {
299 if (oldWindow != NULL) {
300 Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
301 WinItemStructureProc, (ClientData) winItemPtr);
302 Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL,
303 (ClientData) NULL);
304 Tk_UnmaintainGeometry(oldWindow, canvasTkwin);
305 Tk_UnmapWindow(oldWindow);
306 }
307 if (winItemPtr->tkwin != NULL) {
308 Tk_Window ancestor, parent;
309
310 /*
311 * Make sure that the canvas is either the parent of the
312 * window associated with the item or a descendant of that
313 * parent. Also, don't allow a top-level window to be
314 * managed inside a canvas.
315 */
316
317 parent = Tk_Parent(winItemPtr->tkwin);
318 for (ancestor = canvasTkwin; ;
319 ancestor = Tk_Parent(ancestor)) {
320 if (ancestor == parent) {
321 break;
322 }
323 if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_LEVEL) {
324 badWindow:
325 Tcl_AppendResult(interp, "can't use ",
326 Tk_PathName(winItemPtr->tkwin),
327 " in a window item of this canvas", (char *) NULL);
328 winItemPtr->tkwin = NULL;
329 return TCL_ERROR;
330 }
331 }
332 if (((Tk_FakeWin *) (winItemPtr->tkwin))->flags & TK_TOP_LEVEL) {
333 goto badWindow;
334 }
335 if (winItemPtr->tkwin == canvasTkwin) {
336 goto badWindow;
337 }
338 Tk_CreateEventHandler(winItemPtr->tkwin, StructureNotifyMask,
339 WinItemStructureProc, (ClientData) winItemPtr);
340 Tk_ManageGeometry(winItemPtr->tkwin, &canvasGeomType,
341 (ClientData) winItemPtr);
342 }
343 }
344
345 ComputeWindowBbox(canvas, winItemPtr);
346
347 return TCL_OK;
348 }
349
350 /*
351 *--------------------------------------------------------------
352 *
353 * DeleteWinItem --
354 *
355 * This procedure is called to clean up the data structure
356 * associated with a window item.
357 *
358 * Results:
359 * None.
360 *
361 * Side effects:
362 * Resources associated with itemPtr are released.
363 *
364 *--------------------------------------------------------------
365 */
366
367 static void
DeleteWinItem(canvas,itemPtr,display)368 DeleteWinItem(canvas, itemPtr, display)
369 Tk_Canvas canvas; /* Overall info about widget. */
370 Tk_Item *itemPtr; /* Item that is being deleted. */
371 Display *display; /* Display containing window for
372 * canvas. */
373 {
374 WindowItem *winItemPtr = (WindowItem *) itemPtr;
375 Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
376
377 if (winItemPtr->tkwin != NULL) {
378 Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
379 WinItemStructureProc, (ClientData) winItemPtr);
380 Tk_ManageGeometry(winItemPtr->tkwin, (Tk_GeomMgr *) NULL,
381 (ClientData) NULL);
382 if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
383 Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
384 }
385 Tk_UnmapWindow(winItemPtr->tkwin);
386 }
387 }
388
389 /*
390 *--------------------------------------------------------------
391 *
392 * ComputeWindowBbox --
393 *
394 * This procedure is invoked to compute the bounding box of
395 * all the pixels that may be drawn as part of a window item.
396 * This procedure is where the child window's placement is
397 * computed.
398 *
399 * Results:
400 * None.
401 *
402 * Side effects:
403 * The fields x1, y1, x2, and y2 are updated in the header
404 * for itemPtr.
405 *
406 *--------------------------------------------------------------
407 */
408
409 static void
ComputeWindowBbox(canvas,winItemPtr)410 ComputeWindowBbox(canvas, winItemPtr)
411 Tk_Canvas canvas; /* Canvas that contains item. */
412 WindowItem *winItemPtr; /* Item whose bbox is to be
413 * recomputed. */
414 {
415 int width, height, x, y;
416
417 x = winItemPtr->x + ((winItemPtr->x >= 0) ? 0.5 : - 0.5);
418 y = winItemPtr->y + ((winItemPtr->y >= 0) ? 0.5 : - 0.5);
419
420 if (winItemPtr->tkwin == NULL) {
421 winItemPtr->header.x1 = winItemPtr->header.x2 = x;
422 winItemPtr->header.y1 = winItemPtr->header.y2 = y;
423 return;
424 }
425
426 /*
427 * Compute dimensions of window.
428 */
429
430 width = winItemPtr->width;
431 if (width <= 0) {
432 width = Tk_ReqWidth(winItemPtr->tkwin);
433 if (width <= 0) {
434 width = 1;
435 }
436 }
437 height = winItemPtr->height;
438 if (height <= 0) {
439 height = Tk_ReqHeight(winItemPtr->tkwin);
440 if (height <= 0) {
441 height = 1;
442 }
443 }
444
445 /*
446 * Compute location of window, using anchor information.
447 */
448
449 switch (winItemPtr->anchor) {
450 case TK_ANCHOR_N:
451 x -= width/2;
452 break;
453 case TK_ANCHOR_NE:
454 x -= width;
455 break;
456 case TK_ANCHOR_E:
457 x -= width;
458 y -= height/2;
459 break;
460 case TK_ANCHOR_SE:
461 x -= width;
462 y -= height;
463 break;
464 case TK_ANCHOR_S:
465 x -= width/2;
466 y -= height;
467 break;
468 case TK_ANCHOR_SW:
469 y -= height;
470 break;
471 case TK_ANCHOR_W:
472 y -= height/2;
473 break;
474 case TK_ANCHOR_NW:
475 break;
476 case TK_ANCHOR_CENTER:
477 x -= width/2;
478 y -= height/2;
479 break;
480 }
481
482 /*
483 * Store the information in the item header.
484 */
485
486 winItemPtr->header.x1 = x;
487 winItemPtr->header.y1 = y;
488 winItemPtr->header.x2 = x + width;
489 winItemPtr->header.y2 = y + height;
490 }
491
492 /*
493 *--------------------------------------------------------------
494 *
495 * DisplayWinItem --
496 *
497 * This procedure is invoked to "draw" a window item in a given
498 * drawable. Since the window draws itself, we needn't do any
499 * actual redisplay here. However, this procedure takes care
500 * of actually repositioning the child window so that it occupies
501 * the correct screen position.
502 *
503 * Results:
504 * None.
505 *
506 * Side effects:
507 * The child window's position may get changed. Note: this
508 * procedure gets called both when a window needs to be displayed
509 * and when it ceases to be visible on the screen (e.g. it was
510 * scrolled or moved off-screen or the enclosing canvas is
511 * unmapped).
512 *
513 *--------------------------------------------------------------
514 */
515
516 static void
DisplayWinItem(canvas,itemPtr,display,drawable,regionX,regionY,regionWidth,regionHeight)517 DisplayWinItem(canvas, itemPtr, display, drawable, regionX, regionY,
518 regionWidth, regionHeight)
519 Tk_Canvas canvas; /* Canvas that contains item. */
520 Tk_Item *itemPtr; /* Item to be displayed. */
521 Display *display; /* Display on which to draw item. */
522 Drawable drawable; /* Pixmap or window in which to draw
523 * item. */
524 int regionX, regionY, regionWidth, regionHeight;
525 /* Describes region of canvas that
526 * must be redisplayed (not used). */
527 {
528 WindowItem *winItemPtr = (WindowItem *) itemPtr;
529 int width, height;
530 short x, y;
531 Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
532
533 if (winItemPtr->tkwin == NULL) {
534 return;
535 }
536
537 Tk_CanvasWindowCoords(canvas, (double) winItemPtr->header.x1,
538 (double) winItemPtr->header.y1, &x, &y);
539 width = winItemPtr->header.x2 - winItemPtr->header.x1;
540 height = winItemPtr->header.y2 - winItemPtr->header.y1;
541
542 /*
543 * Reposition and map the window (but in different ways depending
544 * on whether the canvas is the window's parent).
545 */
546
547 if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
548 if ((x != Tk_X(winItemPtr->tkwin)) || (y != Tk_Y(winItemPtr->tkwin))
549 || (width != Tk_Width(winItemPtr->tkwin))
550 || (height != Tk_Height(winItemPtr->tkwin))) {
551 Tk_MoveResizeWindow(winItemPtr->tkwin, x, y, width, height);
552 }
553 Tk_MapWindow(winItemPtr->tkwin);
554 } else {
555 Tk_MaintainGeometry(winItemPtr->tkwin, canvasTkwin, x, y,
556 width, height);
557 }
558 }
559
560 /*
561 *--------------------------------------------------------------
562 *
563 * WinItemToPoint --
564 *
565 * Computes the distance from a given point to a given
566 * rectangle, in canvas units.
567 *
568 * Results:
569 * The return value is 0 if the point whose x and y coordinates
570 * are coordPtr[0] and coordPtr[1] is inside the window. If the
571 * point isn't inside the window then the return value is the
572 * distance from the point to the window.
573 *
574 * Side effects:
575 * None.
576 *
577 *--------------------------------------------------------------
578 */
579
580 static double
WinItemToPoint(canvas,itemPtr,pointPtr)581 WinItemToPoint(canvas, itemPtr, pointPtr)
582 Tk_Canvas canvas; /* Canvas containing item. */
583 Tk_Item *itemPtr; /* Item to check against point. */
584 double *pointPtr; /* Pointer to x and y coordinates. */
585 {
586 WindowItem *winItemPtr = (WindowItem *) itemPtr;
587 double x1, x2, y1, y2, xDiff, yDiff;
588
589 x1 = winItemPtr->header.x1;
590 y1 = winItemPtr->header.y1;
591 x2 = winItemPtr->header.x2;
592 y2 = winItemPtr->header.y2;
593
594 /*
595 * Point is outside rectangle.
596 */
597
598 if (pointPtr[0] < x1) {
599 xDiff = x1 - pointPtr[0];
600 } else if (pointPtr[0] >= x2) {
601 xDiff = pointPtr[0] + 1 - x2;
602 } else {
603 xDiff = 0;
604 }
605
606 if (pointPtr[1] < y1) {
607 yDiff = y1 - pointPtr[1];
608 } else if (pointPtr[1] >= y2) {
609 yDiff = pointPtr[1] + 1 - y2;
610 } else {
611 yDiff = 0;
612 }
613
614 return hypot(xDiff, yDiff);
615 }
616
617 /*
618 *--------------------------------------------------------------
619 *
620 * WinItemToArea --
621 *
622 * This procedure is called to determine whether an item
623 * lies entirely inside, entirely outside, or overlapping
624 * a given rectangle.
625 *
626 * Results:
627 * -1 is returned if the item is entirely outside the area
628 * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
629 * inside the given area.
630 *
631 * Side effects:
632 * None.
633 *
634 *--------------------------------------------------------------
635 */
636
637 static int
WinItemToArea(canvas,itemPtr,rectPtr)638 WinItemToArea(canvas, itemPtr, rectPtr)
639 Tk_Canvas canvas; /* Canvas containing item. */
640 Tk_Item *itemPtr; /* Item to check against rectangle. */
641 double *rectPtr; /* Pointer to array of four coordinates
642 * (x1, y1, x2, y2) describing rectangular
643 * area. */
644 {
645 WindowItem *winItemPtr = (WindowItem *) itemPtr;
646
647 if ((rectPtr[2] <= winItemPtr->header.x1)
648 || (rectPtr[0] >= winItemPtr->header.x2)
649 || (rectPtr[3] <= winItemPtr->header.y1)
650 || (rectPtr[1] >= winItemPtr->header.y2)) {
651 return -1;
652 }
653 if ((rectPtr[0] <= winItemPtr->header.x1)
654 && (rectPtr[1] <= winItemPtr->header.y1)
655 && (rectPtr[2] >= winItemPtr->header.x2)
656 && (rectPtr[3] >= winItemPtr->header.y2)) {
657 return 1;
658 }
659 return 0;
660 }
661
662 /*
663 *--------------------------------------------------------------
664 *
665 * ScaleWinItem --
666 *
667 * This procedure is invoked to rescale a rectangle or oval
668 * item.
669 *
670 * Results:
671 * None.
672 *
673 * Side effects:
674 * The rectangle or oval referred to by itemPtr is rescaled
675 * so that the following transformation is applied to all
676 * point coordinates:
677 * x' = originX + scaleX*(x-originX)
678 * y' = originY + scaleY*(y-originY)
679 *
680 *--------------------------------------------------------------
681 */
682
683 static void
ScaleWinItem(canvas,itemPtr,originX,originY,scaleX,scaleY)684 ScaleWinItem(canvas, itemPtr, originX, originY, scaleX, scaleY)
685 Tk_Canvas canvas; /* Canvas containing rectangle. */
686 Tk_Item *itemPtr; /* Rectangle to be scaled. */
687 double originX, originY; /* Origin about which to scale rect. */
688 double scaleX; /* Amount to scale in X direction. */
689 double scaleY; /* Amount to scale in Y direction. */
690 {
691 WindowItem *winItemPtr = (WindowItem *) itemPtr;
692
693 winItemPtr->x = originX + scaleX*(winItemPtr->x - originX);
694 winItemPtr->y = originY + scaleY*(winItemPtr->y - originY);
695 if (winItemPtr->width > 0) {
696 winItemPtr->width = scaleX*winItemPtr->width;
697 }
698 if (winItemPtr->height > 0) {
699 winItemPtr->height = scaleY*winItemPtr->height;
700 }
701 ComputeWindowBbox(canvas, winItemPtr);
702 }
703
704 /*
705 *--------------------------------------------------------------
706 *
707 * TranslateWinItem --
708 *
709 * This procedure is called to move a rectangle or oval by a
710 * given amount.
711 *
712 * Results:
713 * None.
714 *
715 * Side effects:
716 * The position of the rectangle or oval is offset by
717 * (xDelta, yDelta), and the bounding box is updated in the
718 * generic part of the item structure.
719 *
720 *--------------------------------------------------------------
721 */
722
723 static void
TranslateWinItem(canvas,itemPtr,deltaX,deltaY)724 TranslateWinItem(canvas, itemPtr, deltaX, deltaY)
725 Tk_Canvas canvas; /* Canvas containing item. */
726 Tk_Item *itemPtr; /* Item that is being moved. */
727 double deltaX, deltaY; /* Amount by which item is to be
728 * moved. */
729 {
730 WindowItem *winItemPtr = (WindowItem *) itemPtr;
731
732 winItemPtr->x += deltaX;
733 winItemPtr->y += deltaY;
734 ComputeWindowBbox(canvas, winItemPtr);
735 }
736
737 /*
738 *--------------------------------------------------------------
739 *
740 * WinItemStructureProc --
741 *
742 * This procedure is invoked whenever StructureNotify events
743 * occur for a window that's managed as part of a canvas window
744 * item. This procudure's only purpose is to clean up when
745 * windows are deleted.
746 *
747 * Results:
748 * None.
749 *
750 * Side effects:
751 * The window is disassociated from the window item when it is
752 * deleted.
753 *
754 *--------------------------------------------------------------
755 */
756
757 static void
WinItemStructureProc(clientData,eventPtr)758 WinItemStructureProc(clientData, eventPtr)
759 ClientData clientData; /* Pointer to record describing window item. */
760 XEvent *eventPtr; /* Describes what just happened. */
761 {
762 WindowItem *winItemPtr = (WindowItem *) clientData;
763
764 if (eventPtr->type == DestroyNotify) {
765 winItemPtr->tkwin = NULL;
766 }
767 }
768
769 /*
770 *--------------------------------------------------------------
771 *
772 * WinItemRequestProc --
773 *
774 * This procedure is invoked whenever a window that's associated
775 * with a window canvas item changes its requested dimensions.
776 *
777 * Results:
778 * None.
779 *
780 * Side effects:
781 * The size and location on the screen of the window may change,
782 * depending on the options specified for the window item.
783 *
784 *--------------------------------------------------------------
785 */
786
787 static void
WinItemRequestProc(clientData,tkwin)788 WinItemRequestProc(clientData, tkwin)
789 ClientData clientData; /* Pointer to record for window item. */
790 Tk_Window tkwin; /* Window that changed its desired
791 * size. */
792 {
793 WindowItem *winItemPtr = (WindowItem *) clientData;
794
795 ComputeWindowBbox(winItemPtr->canvas, winItemPtr);
796 DisplayWinItem(winItemPtr->canvas, (Tk_Item *) winItemPtr,
797 (Display *) NULL, (Drawable) None, 0, 0, 0, 0);
798 }
799
800 /*
801 *--------------------------------------------------------------
802 *
803 * WinItemLostSlaveProc --
804 *
805 * This procedure is invoked by Tk whenever some other geometry
806 * claims control over a slave that used to be managed by us.
807 *
808 * Results:
809 * None.
810 *
811 * Side effects:
812 * Forgets all canvas-related information about the slave.
813 *
814 *--------------------------------------------------------------
815 */
816
817 /* ARGSUSED */
818 static void
WinItemLostSlaveProc(clientData,tkwin)819 WinItemLostSlaveProc(clientData, tkwin)
820 ClientData clientData; /* WindowItem structure for slave window that
821 * was stolen away. */
822 Tk_Window tkwin; /* Tk's handle for the slave window. */
823 {
824 WindowItem *winItemPtr = (WindowItem *) clientData;
825 Tk_Window canvasTkwin = Tk_CanvasTkwin(winItemPtr->canvas);
826
827 Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
828 WinItemStructureProc, (ClientData) winItemPtr);
829 if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
830 Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
831 }
832 Tk_UnmapWindow(winItemPtr->tkwin);
833 winItemPtr->tkwin = NULL;
834 }
835