1/* 2 * tkMacOSXWm.c -- 3 * 4 * This module takes care of the interactions between a Tk-based 5 * application and the window manager. Among other things, it implements 6 * the "wm" command and passes geometry information to the window 7 * manager. 8 * 9 * Copyright (c) 1994-1997 Sun Microsystems, Inc. 10 * Copyright 2001-2009, Apple Inc. 11 * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net> 12 * 13 * See the file "license.terms" for information on usage and redistribution 14 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 15 * 16 * RCS: @(#) $Id$ 17 */ 18 19#include "tkMacOSXPrivate.h" 20#include "tkScrollbar.h" 21#include "tkMacOSXWm.h" 22#include "tkMacOSXEvent.h" 23#include "tkMacOSXDebug.h" 24 25/* 26#ifdef TK_MAC_DEBUG 27#define TK_MAC_DEBUG_WINDOWS 28#endif 29*/ 30 31/* 32 * Window attributes and classes 33 */ 34 35#define WM_NSMASK_SHIFT 36 36#define tkWindowDoesNotHideAttribute \ 37 ((UInt64) 1 << kHIWindowBitDoesNotHide) 38#define tkCanJoinAllSpacesAttribute \ 39 ((UInt64) NSWindowCollectionBehaviorCanJoinAllSpaces << 34) 40#define tkMoveToActiveSpaceAttribute \ 41 ((UInt64) NSWindowCollectionBehaviorMoveToActiveSpace << 34) 42#define tkNonactivatingPanelAttribute \ 43 ((UInt64) NSNonactivatingPanelMask << WM_NSMASK_SHIFT) 44#define tkHUDWindowAttribute \ 45 ((UInt64) NSHUDWindowMask << WM_NSMASK_SHIFT) 46#define tkAlwaysValidAttributes (kWindowNoUpdatesAttribute \ 47 | kWindowNoActivatesAttribute | kWindowHideOnSuspendAttribute \ 48 | kWindowHideOnFullScreenAttribute | kWindowNoConstrainAttribute \ 49 | kWindowNoShadowAttribute | kWindowLiveResizeAttribute \ 50 | kWindowOpaqueForEventsAttribute | kWindowIgnoreClicksAttribute \ 51 | kWindowDoesNotCycleAttribute | tkWindowDoesNotHideAttribute \ 52 | tkCanJoinAllSpacesAttribute | tkMoveToActiveSpaceAttribute \ 53 | tkNonactivatingPanelAttribute | tkHUDWindowAttribute) 54 55static const struct { 56 const UInt64 validAttrs, defaultAttrs, forceOnAttrs, forceOffAttrs; 57 int flags; NSUInteger styleMask; 58} macClassAttrs[] = { 59 [kAlertWindowClass] = { 60 .defaultAttrs = kWindowDoesNotCycleAttribute, }, 61 [kMovableAlertWindowClass] = { 62 .defaultAttrs = kWindowDoesNotCycleAttribute, }, 63 [kModalWindowClass] = { 64 .defaultAttrs = kWindowDoesNotCycleAttribute, }, 65 [kMovableModalWindowClass] = { 66 .validAttrs = kWindowCloseBoxAttribute | kWindowMetalAttribute | 67 kWindowFullZoomAttribute | kWindowResizableAttribute, 68 .defaultAttrs = kWindowDoesNotCycleAttribute, }, 69 [kFloatingWindowClass] = { 70 .validAttrs = kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute | 71 kWindowMetalAttribute | kWindowToolbarButtonAttribute | 72 kWindowNoTitleBarAttribute | kWindowFullZoomAttribute | 73 kWindowResizableAttribute | kWindowSideTitlebarAttribute, 74 .defaultAttrs = kWindowStandardFloatingAttributes | 75 kWindowHideOnSuspendAttribute | kWindowDoesNotCycleAttribute, 76 .forceOnAttrs = kWindowResizableAttribute, 77 .forceOffAttrs = kWindowCollapseBoxAttribute, 78 .styleMask = NSUtilityWindowMask, }, 79 [kDocumentWindowClass] = { 80 .validAttrs = kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute | 81 kWindowMetalAttribute | kWindowToolbarButtonAttribute | 82 kWindowNoTitleBarAttribute | 83 kWindowUnifiedTitleAndToolbarAttribute | 84 kWindowInWindowMenuAttribute | kWindowFullZoomAttribute | 85 kWindowResizableAttribute, 86 .forceOnAttrs = kWindowResizableAttribute, 87 .defaultAttrs = kWindowStandardDocumentAttributes | 88 kWindowLiveResizeAttribute | kWindowInWindowMenuAttribute, }, 89 [kUtilityWindowClass] = { 90 .validAttrs = kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute | 91 kWindowMetalAttribute | kWindowToolbarButtonAttribute | 92 kWindowNoTitleBarAttribute | kWindowFullZoomAttribute | 93 kWindowResizableAttribute | kWindowSideTitlebarAttribute, 94 .defaultAttrs = kWindowStandardFloatingAttributes | 95 kWindowHideOnFullScreenAttribute | 96 tkWindowDoesNotHideAttribute | tkNonactivatingPanelAttribute | 97 kWindowDoesNotCycleAttribute, 98 .forceOnAttrs = kWindowResizableAttribute, 99 .forceOffAttrs = kWindowCollapseBoxAttribute, 100 .flags = WM_TOPMOST, 101 .styleMask = NSUtilityWindowMask, }, 102 [kHelpWindowClass] = { 103 .defaultAttrs = kWindowHideOnSuspendAttribute, 104 .forceOnAttrs = kWindowNoTitleBarAttribute | 105 kWindowDoesNotCycleAttribute, 106 .flags = WM_TOPMOST, }, 107 [kSheetWindowClass] = { 108 .validAttrs = kWindowResizableAttribute, 109 .forceOnAttrs = kWindowNoTitleBarAttribute | 110 kWindowDoesNotCycleAttribute, 111 .styleMask = NSDocModalWindowMask, }, 112 [kToolbarWindowClass] = { 113 .defaultAttrs = kWindowHideOnSuspendAttribute, 114 .forceOnAttrs = kWindowNoTitleBarAttribute | 115 kWindowDoesNotCycleAttribute, 116 .styleMask = NSUtilityWindowMask, }, 117 [kPlainWindowClass] = { 118 .defaultAttrs = kWindowDoesNotCycleAttribute, 119 .forceOnAttrs = kWindowNoTitleBarAttribute, }, 120 [kOverlayWindowClass] = { 121 .forceOnAttrs = kWindowNoTitleBarAttribute | 122 kWindowDoesNotCycleAttribute, 123 .flags = WM_TOPMOST | WM_TRANSPARENT, }, 124 [kSheetAlertWindowClass] = { 125 .forceOnAttrs = kWindowNoTitleBarAttribute | 126 kWindowDoesNotCycleAttribute, 127 .styleMask = NSDocModalWindowMask, }, 128 [kAltPlainWindowClass] = { 129 .defaultAttrs = kWindowDoesNotCycleAttribute, 130 .forceOnAttrs = kWindowNoTitleBarAttribute, }, 131 [kSimpleWindowClass] = { 132 .defaultAttrs = kWindowDoesNotCycleAttribute, 133 .forceOnAttrs = kWindowNoTitleBarAttribute, }, 134 [kDrawerWindowClass] = { 135 .validAttrs = kWindowMetalAttribute | kWindowResizableAttribute, 136 .forceOnAttrs = kWindowNoTitleBarAttribute | 137 kWindowDoesNotCycleAttribute, }, 138}; 139 140#define ForceAttributes(attributes, class) \ 141 ((attributes) & (~macClassAttrs[(class)].forceOffAttrs | \ 142 (macClassAttrs[(class)].forceOnAttrs & ~kWindowResizableAttribute))) 143 144/* 145 * Data for [wm attributes] command: 146 */ 147 148typedef enum { 149 WMATT_ALPHA, WMATT_FULLSCREEN, WMATT_MODIFIED, WMATT_NOTIFY, 150 WMATT_TITLEPATH, WMATT_TOPMOST, WMATT_TRANSPARENT, 151 _WMATT_LAST_ATTRIBUTE 152} WmAttribute; 153 154static const char *WmAttributeNames[] = { 155 "-alpha", "-fullscreen", "-modified", "-notify", 156 "-titlepath", "-topmost", "-transparent", 157 NULL 158}; 159 160/* 161 * The variable below is used to enable or disable tracing in this module. If 162 * tracing is enabled, then information is printed on standard output about 163 * interesting interactions with the window manager. 164 */ 165 166static int wmTracing = 0; 167 168/* 169 * The following structure is the official type record for geometry management 170 * of top-level windows. 171 */ 172 173static void TopLevelReqProc(ClientData dummy, Tk_Window tkwin); 174 175static const Tk_GeomMgr wmMgrType = { 176 "wm", /* name */ 177 TopLevelReqProc, /* requestProc */ 178 NULL, /* lostSlaveProc */ 179}; 180 181/* 182 * The following keeps state for Aqua dock icon bounce notification. 183 */ 184 185static int tkMacOSXWmAttrNotifyVal = 0; 186 187/* 188 * Hash table for Mac Window -> TkWindow mapping. 189 */ 190 191static Tcl_HashTable windowTable; 192static int windowHashInit = false; 193 194/* 195 * Forward declarations for procedures defined in this file: 196 */ 197 198static NSRect InitialWindowBounds(TkWindow *winPtr, 199 NSWindow *macWindow); 200static int ParseGeometry(Tcl_Interp *interp, char *string, 201 TkWindow *winPtr); 202static void TopLevelEventProc(ClientData clientData, 203 XEvent *eventPtr); 204static void WmStackorderToplevelWrapperMap(TkWindow *winPtr, 205 Display *display, Tcl_HashTable *table); 206static void UpdateGeometryInfo(ClientData clientData); 207static void UpdateSizeHints(TkWindow *winPtr); 208static void UpdateVRootGeometry(WmInfo *wmPtr); 209static int WmAspectCmd(Tk_Window tkwin, TkWindow *winPtr, 210 Tcl_Interp *interp, int objc, 211 Tcl_Obj *const objv[]); 212static int WmAttributesCmd(Tk_Window tkwin, TkWindow *winPtr, 213 Tcl_Interp *interp, int objc, 214 Tcl_Obj *const objv[]); 215static int WmClientCmd(Tk_Window tkwin, TkWindow *winPtr, 216 Tcl_Interp *interp, int objc, 217 Tcl_Obj *const objv[]); 218static int WmColormapwindowsCmd(Tk_Window tkwin, 219 TkWindow *winPtr, Tcl_Interp *interp, int objc, 220 Tcl_Obj *const objv[]); 221static int WmCommandCmd(Tk_Window tkwin, TkWindow *winPtr, 222 Tcl_Interp *interp, int objc, 223 Tcl_Obj *const objv[]); 224static int WmDeiconifyCmd(Tk_Window tkwin, TkWindow *winPtr, 225 Tcl_Interp *interp, int objc, 226 Tcl_Obj *const objv[]); 227static int WmFocusmodelCmd(Tk_Window tkwin, TkWindow *winPtr, 228 Tcl_Interp *interp, int objc, 229 Tcl_Obj *const objv[]); 230static int WmForgetCmd(Tk_Window tkwin, TkWindow *winPtr, 231 Tcl_Interp *interp, int objc, 232 Tcl_Obj *const objv[]); 233static int WmFrameCmd(Tk_Window tkwin, TkWindow *winPtr, 234 Tcl_Interp *interp, int objc, 235 Tcl_Obj *const objv[]); 236static int WmGeometryCmd(Tk_Window tkwin, TkWindow *winPtr, 237 Tcl_Interp *interp, int objc, 238 Tcl_Obj *const objv[]); 239static int WmGridCmd(Tk_Window tkwin, TkWindow *winPtr, 240 Tcl_Interp *interp, int objc, 241 Tcl_Obj *const objv[]); 242static int WmGroupCmd(Tk_Window tkwin, TkWindow *winPtr, 243 Tcl_Interp *interp, int objc, 244 Tcl_Obj *const objv[]); 245static int WmIconbitmapCmd(Tk_Window tkwin, TkWindow *winPtr, 246 Tcl_Interp *interp, int objc, 247 Tcl_Obj *const objv[]); 248static int WmIconifyCmd(Tk_Window tkwin, TkWindow *winPtr, 249 Tcl_Interp *interp, int objc, 250 Tcl_Obj *const objv[]); 251static int WmIconmaskCmd(Tk_Window tkwin, TkWindow *winPtr, 252 Tcl_Interp *interp, int objc, 253 Tcl_Obj *const objv[]); 254static int WmIconnameCmd(Tk_Window tkwin, TkWindow *winPtr, 255 Tcl_Interp *interp, int objc, 256 Tcl_Obj *const objv[]); 257static int WmIconphotoCmd(Tk_Window tkwin, TkWindow *winPtr, 258 Tcl_Interp *interp, int objc, 259 Tcl_Obj *const objv[]); 260static int WmIconpositionCmd(Tk_Window tkwin, TkWindow *winPtr, 261 Tcl_Interp *interp, int objc, 262 Tcl_Obj *const objv[]); 263static int WmIconwindowCmd(Tk_Window tkwin, TkWindow *winPtr, 264 Tcl_Interp *interp, int objc, 265 Tcl_Obj *const objv[]); 266static int WmManageCmd(Tk_Window tkwin, TkWindow *winPtr, 267 Tcl_Interp *interp, int objc, 268 Tcl_Obj *const objv[]); 269static int WmMaxsizeCmd(Tk_Window tkwin, TkWindow *winPtr, 270 Tcl_Interp *interp, int objc, 271 Tcl_Obj *const objv[]); 272static int WmMinsizeCmd(Tk_Window tkwin, TkWindow *winPtr, 273 Tcl_Interp *interp, int objc, 274 Tcl_Obj *const objv[]); 275static int WmOverrideredirectCmd(Tk_Window tkwin, 276 TkWindow *winPtr, Tcl_Interp *interp, int objc, 277 Tcl_Obj *const objv[]); 278static int WmPositionfromCmd(Tk_Window tkwin, TkWindow *winPtr, 279 Tcl_Interp *interp, int objc, 280 Tcl_Obj *const objv[]); 281static int WmProtocolCmd(Tk_Window tkwin, TkWindow *winPtr, 282 Tcl_Interp *interp, int objc, 283 Tcl_Obj *const objv[]); 284static int WmResizableCmd(Tk_Window tkwin, TkWindow *winPtr, 285 Tcl_Interp *interp, int objc, 286 Tcl_Obj *const objv[]); 287static int WmSizefromCmd(Tk_Window tkwin, TkWindow *winPtr, 288 Tcl_Interp *interp, int objc, 289 Tcl_Obj *const objv[]); 290static int WmStackorderCmd(Tk_Window tkwin, TkWindow *winPtr, 291 Tcl_Interp *interp, int objc, 292 Tcl_Obj *const objv[]); 293static int WmStateCmd(Tk_Window tkwin, TkWindow *winPtr, 294 Tcl_Interp *interp, int objc, 295 Tcl_Obj *const objv[]); 296static int WmTitleCmd(Tk_Window tkwin, TkWindow *winPtr, 297 Tcl_Interp *interp, int objc, 298 Tcl_Obj *const objv[]); 299static int WmTransientCmd(Tk_Window tkwin, TkWindow *winPtr, 300 Tcl_Interp *interp, int objc, 301 Tcl_Obj *const objv[]); 302static int WmWithdrawCmd(Tk_Window tkwin, TkWindow *winPtr, 303 Tcl_Interp *interp, int objc, 304 Tcl_Obj *const objv[]); 305static void WmUpdateGeom(WmInfo *wmPtr, TkWindow *winPtr); 306static int WmWinStyle(Tcl_Interp *interp, TkWindow *winPtr, 307 int objc, Tcl_Obj *const objv[]); 308static void ApplyWindowAttributeFlagChanges(TkWindow *winPtr, 309 NSWindow *macWindow, UInt64 oldAttributes, 310 int oldFlags, int create, int initial); 311static void ApplyMasterOverrideChanges(TkWindow *winPtr, 312 NSWindow *macWindow); 313static void GetMinSize(TkWindow *winPtr, int *minWidthPtr, 314 int *minHeightPtr); 315static void GetMaxSize(TkWindow *winPtr, int *maxWidthPtr, 316 int *maxHeightPtr); 317static void RemapWindows(TkWindow *winPtr, 318 MacDrawable *parentWin); 319 320#pragma mark TKWindow(TKWm) 321 322#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 323@interface NSWindow(TkWm) 324- (void)setCanCycle:(BOOL)canCycleFlag; 325@end 326#endif 327 328@interface NSDrawerWindow : NSWindow 329{ 330 id _i1, _i2; 331} 332@end 333 334@implementation TKWindow 335@end 336 337@implementation TKWindow(TKWm) 338- (BOOL)canBecomeKeyWindow { 339 TkWindow *winPtr = TkMacOSXGetTkWindow(self); 340 341 return (winPtr && winPtr->wmInfoPtr && (winPtr->wmInfoPtr->macClass == 342 kHelpWindowClass || winPtr->wmInfoPtr->attributes & 343 kWindowNoActivatesAttribute)) ? NO : YES; 344} 345@end 346 347#pragma mark - 348 349/* 350 *---------------------------------------------------------------------- 351 * 352 * SetWindowSizeLimits -- 353 * 354 * Sets NSWindow size limits 355 * 356 * Results: 357 * None. 358 * 359 * Side effects: 360 * None. 361 * 362 *---------------------------------------------------------------------- 363 */ 364 365static void 366SetWindowSizeLimits( 367 TkWindow *winPtr) 368{ 369 NSWindow *macWindow = TkMacOSXDrawableWindow(winPtr->window); 370 WmInfo *wmPtr = winPtr->wmInfoPtr; 371 int minWidth, minHeight, maxWidth, maxHeight, base; 372 373 if (!macWindow) { 374 return; 375 } 376 GetMinSize(winPtr, &minWidth, &minHeight); 377 GetMaxSize(winPtr, &maxWidth, &maxHeight); 378 if (wmPtr->gridWin) { 379 base = winPtr->reqWidth - (wmPtr->reqGridWidth * wmPtr->widthInc); 380 if (base < 0) { 381 base = 0; 382 } 383 minWidth = base + (minWidth * wmPtr->widthInc); 384 maxWidth = base + (maxWidth * wmPtr->widthInc); 385 base = winPtr->reqHeight - (wmPtr->reqGridHeight * wmPtr->heightInc); 386 if (base < 0) { 387 base = 0; 388 } 389 minHeight = base + (minHeight * wmPtr->heightInc); 390 maxHeight = base + (maxHeight * wmPtr->heightInc); 391 } 392 if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) { 393 minWidth = maxWidth = wmPtr->configWidth; 394 } 395 if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) { 396 minHeight = maxHeight = wmPtr->configHeight; 397 } 398 if (wmPtr->gridWin) { 399 [macWindow setResizeIncrements:NSMakeSize(wmPtr->widthInc, 400 wmPtr->heightInc)]; 401 } else if (wmPtr->sizeHintsFlags & PAspect && wmPtr->minAspect.x == 402 wmPtr->maxAspect.x && wmPtr->minAspect.y == wmPtr->maxAspect.y) { 403 NSSize aspect = NSMakeSize(wmPtr->minAspect.x, wmPtr->minAspect.y); 404 CGFloat ratio = aspect.width/aspect.height; 405 [macWindow setContentAspectRatio:aspect]; 406 if ((CGFloat)minWidth/(CGFloat)minHeight > ratio) { 407 minHeight = lround(minWidth / ratio); 408 } else { 409 minWidth = lround(minHeight * ratio); 410 } 411 if ((CGFloat)maxWidth/(CGFloat)maxHeight > ratio) { 412 maxWidth = lround(maxHeight * ratio); 413 } else { 414 maxHeight = lround(maxWidth / ratio); 415 } 416 if ((CGFloat)wmPtr->configWidth/(CGFloat)wmPtr->configHeight > ratio) { 417 wmPtr->configWidth = lround(wmPtr->configHeight * ratio); 418 if (wmPtr->configWidth < minWidth) { 419 wmPtr->configWidth = minWidth; 420 wmPtr->configHeight = minHeight; 421 } 422 } else { 423 wmPtr->configHeight = lround(wmPtr->configWidth / ratio); 424 if (wmPtr->configHeight < minHeight) { 425 wmPtr->configWidth = minWidth; 426 wmPtr->configHeight = minHeight; 427 } 428 } 429 } else { 430 [macWindow setResizeIncrements:NSMakeSize(1.0, 1.0)]; 431 } 432 [macWindow setContentMinSize:NSMakeSize(minWidth, minHeight)]; 433 [macWindow setContentMaxSize:NSMakeSize(maxWidth, maxHeight)]; 434} 435 436/* 437 *---------------------------------------------------------------------- 438 * 439 * FrontWindowAtPoint -- 440 * 441 * Find frontmost toplevel window at a given screen location. 442 * 443 * Results: 444 * TkWindow*. 445 * 446 * Side effects: 447 * None. 448 * 449 *---------------------------------------------------------------------- 450 */ 451 452static TkWindow* 453FrontWindowAtPoint( 454 int x, int y) 455{ 456 457 NSPoint p = NSMakePoint(x, tkMacOSXZeroScreenHeight - y); 458 NSWindow *win = nil; 459 NSInteger windowCount; 460 NSInteger *windowNumbers; 461 462 NSCountWindows(&windowCount); 463 if (windowCount) { 464 windowNumbers = (NSInteger *) ckalloc(windowCount * sizeof(NSInteger)); 465 NSWindowList(windowCount, windowNumbers); 466 for (NSInteger index = 0; index < windowCount; index++) { 467 NSWindow *w = [NSApp windowWithWindowNumber:windowNumbers[index]]; 468 if (w && NSMouseInRect(p, [w frame], NO)) { 469 win = w; 470 break; 471 } 472 } 473 ckfree((char *) windowNumbers); 474 } 475 return (win ? TkMacOSXGetTkWindow(win) : NULL); 476} 477 478 479/* 480 *---------------------------------------------------------------------- 481 * 482 * TkWmNewWindow -- 483 * 484 * This procedure is invoked whenever a new top-level window is created. 485 * Its job is to initialize the WmInfo structure for the window. 486 * 487 * Results: 488 * None. 489 * 490 * Side effects: 491 * A WmInfo structure gets allocated and initialized. 492 * 493 *---------------------------------------------------------------------- 494 */ 495 496void 497TkWmNewWindow( 498 TkWindow *winPtr) /* Newly-created top-level window. */ 499{ 500 WmInfo *wmPtr = (WmInfo *) ckalloc(sizeof(WmInfo)); 501 502 wmPtr->winPtr = winPtr; 503 wmPtr->reparent = None; 504 wmPtr->titleUid = NULL; 505 wmPtr->iconName = NULL; 506 wmPtr->master = None; 507 wmPtr->hints.flags = InputHint | StateHint; 508 wmPtr->hints.input = True; 509 wmPtr->hints.initial_state = NormalState; 510 wmPtr->hints.icon_pixmap = None; 511 wmPtr->hints.icon_window = None; 512 wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0; 513 wmPtr->hints.icon_mask = None; 514 wmPtr->hints.window_group = None; 515 wmPtr->leaderName = NULL; 516 wmPtr->masterWindowName = NULL; 517 wmPtr->icon = NULL; 518 wmPtr->iconFor = NULL; 519 wmPtr->sizeHintsFlags = 0; 520 wmPtr->minWidth = wmPtr->minHeight = 1; 521 wmPtr->maxWidth = 0; 522 wmPtr->maxHeight = 0; 523 wmPtr->gridWin = NULL; 524 wmPtr->widthInc = wmPtr->heightInc = 1; 525 wmPtr->minAspect.x = wmPtr->minAspect.y = 1; 526 wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1; 527 wmPtr->reqGridWidth = wmPtr->reqGridHeight = -1; 528 wmPtr->gravity = NorthWestGravity; 529 wmPtr->width = -1; 530 wmPtr->height = -1; 531 wmPtr->x = winPtr->changes.x; 532 wmPtr->y = winPtr->changes.y; 533 wmPtr->parentWidth = winPtr->changes.width 534 + 2*winPtr->changes.border_width; 535 wmPtr->parentHeight = winPtr->changes.height 536 + 2*winPtr->changes.border_width; 537 wmPtr->xInParent = 0; 538 wmPtr->yInParent = 0; 539 wmPtr->cmapList = NULL; 540 wmPtr->cmapCount = 0; 541 wmPtr->configX = 0; 542 wmPtr->configY = 0; 543 wmPtr->configWidth = -1; 544 wmPtr->configHeight = -1; 545 wmPtr->vRoot = None; 546 wmPtr->protPtr = NULL; 547 wmPtr->cmdArgv = NULL; 548 wmPtr->clientMachine = NULL; 549 wmPtr->flags = WM_NEVER_MAPPED; 550 wmPtr->macClass = kDocumentWindowClass; 551 wmPtr->attributes = macClassAttrs[kDocumentWindowClass].defaultAttrs; 552 wmPtr->scrollWinPtr = NULL; 553 wmPtr->menuPtr = NULL; 554 wmPtr->window = nil; 555 winPtr->wmInfoPtr = wmPtr; 556 557 UpdateVRootGeometry(wmPtr); 558 559 /* 560 * Tk must monitor structure events for top-level windows, in order to 561 * detect size and position changes caused by window managers. 562 */ 563 564 Tk_CreateEventHandler((Tk_Window) winPtr, StructureNotifyMask, 565 TopLevelEventProc, winPtr); 566 567 /* 568 * Arrange for geometry requests to be reflected from the window to the 569 * window manager. 570 */ 571 572 Tk_ManageGeometry((Tk_Window) winPtr, &wmMgrType, (ClientData) 0); 573} 574 575/* 576 *---------------------------------------------------------------------- 577 * 578 * TkWmMapWindow -- 579 * 580 * This procedure is invoked to map a top-level window. This module gets 581 * a chance to update all window-manager-related information in 582 * properties before the window manager sees the map event and checks the 583 * properties. It also gets to decide whether or not to even map the 584 * window after all. 585 * 586 * Results: 587 * None. 588 * 589 * Side effects: 590 * Properties of winPtr may get updated to provide up-to-date information 591 * to the window manager. The window may also get mapped, but it may not 592 * be if this procedure decides that isn't appropriate (e.g. because the 593 * window is withdrawn). 594 * 595 *---------------------------------------------------------------------- 596 */ 597 598void 599TkWmMapWindow( 600 TkWindow *winPtr) /* Top-level window that's about to be 601 * mapped. */ 602{ 603 WmInfo *wmPtr = winPtr->wmInfoPtr; 604 605 if (wmPtr->flags & WM_NEVER_MAPPED) { 606 /* 607 * Create the underlying Mac window for this Tk window. 608 */ 609 610 if (!TkMacOSXHostToplevelExists(winPtr)) { 611 TkMacOSXMakeRealWindowExist(winPtr); 612 } 613 614 wmPtr->flags &= ~WM_NEVER_MAPPED; 615 616 /* 617 * Generate configure event when we first map the window. 618 */ 619 620 TkGenWMConfigureEvent((Tk_Window) winPtr, wmPtr->x, wmPtr->y, -1, -1, 621 TK_LOCATION_CHANGED); 622 623 /* 624 * This is the first time this window has ever been mapped. Store all 625 * the window-manager-related information for the window. 626 */ 627 628 if (wmPtr->titleUid == NULL) { 629 wmPtr->titleUid = winPtr->nameUid; 630 } 631 632 if (!Tk_IsEmbedded(winPtr)) { 633 TkSetWMName(winPtr, wmPtr->titleUid); 634 } 635 636 TkWmSetClass(winPtr); 637 638 if (wmPtr->iconName != NULL) { 639 XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName); 640 } 641 642 wmPtr->flags |= WM_UPDATE_SIZE_HINTS; 643 } 644 if (wmPtr->hints.initial_state == WithdrawnState) { 645 return; 646 } 647 648 /* 649 * TODO: we need to display a window if it's iconic on creation. 650 */ 651 652 if (wmPtr->hints.initial_state == IconicState) { 653 return; 654 } 655 656 /* 657 * Update geometry information. 658 */ 659 660 wmPtr->flags |= WM_ABOUT_TO_MAP; 661 if (wmPtr->flags & WM_UPDATE_PENDING) { 662 Tk_CancelIdleCall(UpdateGeometryInfo, winPtr); 663 } 664 UpdateGeometryInfo(winPtr); 665 wmPtr->flags &= ~WM_ABOUT_TO_MAP; 666 667 /* 668 * Map the window. 669 */ 670 671 XMapWindow(winPtr->display, winPtr->window); 672} 673 674/* 675 *---------------------------------------------------------------------- 676 * 677 * TkWmUnmapWindow -- 678 * 679 * This procedure is invoked to unmap a top-level window. On the 680 * Macintosh all we do is call XUnmapWindow. 681 * 682 * Results: 683 * None. 684 * 685 * Side effects: 686 * Unmaps the window. 687 * 688 *---------------------------------------------------------------------- 689 */ 690 691void 692TkWmUnmapWindow( 693 TkWindow *winPtr) /* Top-level window that's about to be 694 * mapped. */ 695{ 696 XUnmapWindow(winPtr->display, winPtr->window); 697} 698 699/* 700 *---------------------------------------------------------------------- 701 * 702 * TkWmDeadWindow -- 703 * 704 * This procedure is invoked when a top-level window is about to be 705 * deleted. It cleans up the wm-related data structures for the window. 706 * 707 * Results: 708 * None. 709 * 710 * Side effects: 711 * The WmInfo structure for winPtr gets freed up. 712 * 713 *---------------------------------------------------------------------- 714 */ 715 716void 717TkWmDeadWindow( 718 TkWindow *winPtr) /* Top-level window that's being deleted. */ 719{ 720 WmInfo *wmPtr = winPtr->wmInfoPtr, *wmPtr2; 721 722 if (wmPtr == NULL) { 723 return; 724 } 725 if (wmPtr->hints.flags & IconPixmapHint) { 726 Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap); 727 } 728 if (wmPtr->hints.flags & IconMaskHint) { 729 Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask); 730 } 731 if (wmPtr->iconName != NULL) { 732 ckfree(wmPtr->iconName); 733 } 734 if (wmPtr->leaderName != NULL) { 735 ckfree(wmPtr->leaderName); 736 } 737 if (wmPtr->masterWindowName != NULL) { 738 ckfree(wmPtr->masterWindowName); 739 } 740 if (wmPtr->icon != NULL) { 741 wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; 742 wmPtr2->iconFor = NULL; 743 } 744 if (wmPtr->iconFor != NULL) { 745 wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr; 746 wmPtr2->icon = NULL; 747 wmPtr2->hints.flags &= ~IconWindowHint; 748 } 749 while (wmPtr->protPtr != NULL) { 750 ProtocolHandler *protPtr; 751 752 protPtr = wmPtr->protPtr; 753 wmPtr->protPtr = protPtr->nextPtr; 754 Tcl_EventuallyFree(protPtr, TCL_DYNAMIC); 755 } 756 if (wmPtr->cmdArgv != NULL) { 757 ckfree((char *) wmPtr->cmdArgv); 758 } 759 if (wmPtr->clientMachine != NULL) { 760 ckfree((char *) wmPtr->clientMachine); 761 } 762 if (wmPtr->flags & WM_UPDATE_PENDING) { 763 Tk_CancelIdleCall(UpdateGeometryInfo, winPtr); 764 } 765 766 /* 767 * Delete the Mac window and remove it from the windowTable. The window 768 * could be nil if the window was never mapped. However, we don't do this 769 * for embedded windows, they don't go in the window list, and they do not 770 * own their portPtr's. 771 */ 772 773 NSWindow *window = wmPtr->window; 774 if (window && !Tk_IsEmbedded(winPtr) ) { 775 [[window parentWindow] removeChildWindow:window]; 776 [window close]; 777 TkMacOSXUnregisterMacWindow(window); 778 if (winPtr->window) { 779 ((MacDrawable *)winPtr->window)->view = nil; 780 } 781 TkMacOSXMakeCollectableAndRelease(wmPtr->window); 782 } 783 784 ckfree((char *) wmPtr); 785 winPtr->wmInfoPtr = NULL; 786} 787 788/* 789 *---------------------------------------------------------------------- 790 * 791 * TkWmSetClass -- 792 * 793 * This procedure is invoked whenever a top-level window's class is 794 * changed. If the window has been mapped then this procedure updates the 795 * window manager property for the class. If the window hasn't been 796 * mapped, the update is deferred until just before the first mapping. 797 * 798 * Results: 799 * None. 800 * 801 * Side effects: 802 * A window property may get updated. 803 * 804 *---------------------------------------------------------------------- 805 */ 806 807void 808TkWmSetClass( 809 TkWindow *winPtr) /* Newly-created top-level window. */ 810{ 811 return; 812} 813 814/* 815 *---------------------------------------------------------------------- 816 * 817 * Tk_WmObjCmd -- 818 * 819 * This procedure is invoked to process the "wm" Tcl command. See the 820 * user documentation for details on what it does. 821 * 822 * Results: 823 * A standard Tcl result. 824 * 825 * Side effects: 826 * See the user documentation. 827 * 828 *---------------------------------------------------------------------- 829 */ 830 831/* ARGSUSED */ 832int 833Tk_WmObjCmd( 834 ClientData clientData, /* Main window associated with interpreter. */ 835 Tcl_Interp *interp, /* Current interpreter. */ 836 int objc, /* Number of arguments. */ 837 Tcl_Obj *const objv[]) /* Argument objects. */ 838{ 839 Tk_Window tkwin = (Tk_Window) clientData; 840 static const char *optionStrings[] = { 841 "aspect", "attributes", "client", "colormapwindows", 842 "command", "deiconify", "focusmodel", "forget", 843 "frame", "geometry", "grid", "group", 844 "iconbitmap", "iconify", "iconmask", "iconname", 845 "iconphoto", "iconposition", "iconwindow", 846 "manage", "maxsize", "minsize", "overrideredirect", 847 "positionfrom", "protocol", "resizable", "sizefrom", 848 "stackorder", "state", "title", "transient", 849 "withdraw", NULL }; 850 enum options { 851 WMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS, 852 WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FORGET, 853 WMOPT_FRAME, WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, 854 WMOPT_ICONBITMAP, WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME, 855 WMOPT_ICONPHOTO, WMOPT_ICONPOSITION, WMOPT_ICONWINDOW, 856 WMOPT_MANAGE, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT, 857 WMOPT_POSITIONFROM, WMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM, 858 WMOPT_STACKORDER, WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT, 859 WMOPT_WITHDRAW }; 860 int index, length; 861 char *argv1; 862 TkWindow *winPtr; 863 864 if (objc < 2) { 865 wrongNumArgs: 866 Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?"); 867 return TCL_ERROR; 868 } 869 870 argv1 = Tcl_GetStringFromObj(objv[1], &length); 871 if ((argv1[0] == 't') && (strncmp(argv1, "tracing", length) == 0) 872 && (length >= 3)) { 873 if ((objc != 2) && (objc != 3)) { 874 Tcl_WrongNumArgs(interp, 2, objv, "?boolean?"); 875 return TCL_ERROR; 876 } 877 if (objc == 2) { 878 Tcl_SetResult(interp, ((wmTracing) ? "on" : "off"), TCL_STATIC); 879 return TCL_OK; 880 } 881 return Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing); 882 } 883 884 if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, 885 &index) != TCL_OK) { 886 return TCL_ERROR; 887 } 888 889 if (objc < 3) { 890 goto wrongNumArgs; 891 } 892 893 if (TkGetWindowFromObj(interp, tkwin, objv[2], (Tk_Window *) &winPtr) 894 != TCL_OK) { 895 return TCL_ERROR; 896 } 897 if (!Tk_IsTopLevel(winPtr) 898 && (index != WMOPT_MANAGE) && (index != WMOPT_FORGET)) { 899 Tcl_AppendResult(interp, "window \"", winPtr->pathName, 900 "\" isn't a top-level window", NULL); 901 return TCL_ERROR; 902 } 903 904 switch ((enum options) index) { 905 case WMOPT_ASPECT: 906 return WmAspectCmd(tkwin, winPtr, interp, objc, objv); 907 case WMOPT_ATTRIBUTES: 908 return WmAttributesCmd(tkwin, winPtr, interp, objc, objv); 909 case WMOPT_CLIENT: 910 return WmClientCmd(tkwin, winPtr, interp, objc, objv); 911 case WMOPT_COLORMAPWINDOWS: 912 return WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv); 913 case WMOPT_COMMAND: 914 return WmCommandCmd(tkwin, winPtr, interp, objc, objv); 915 case WMOPT_DEICONIFY: 916 return WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv); 917 case WMOPT_FOCUSMODEL: 918 return WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv); 919 case WMOPT_FORGET: 920 return WmForgetCmd(tkwin, winPtr, interp, objc, objv); 921 case WMOPT_FRAME: 922 return WmFrameCmd(tkwin, winPtr, interp, objc, objv); 923 case WMOPT_GEOMETRY: 924 return WmGeometryCmd(tkwin, winPtr, interp, objc, objv); 925 case WMOPT_GRID: 926 return WmGridCmd(tkwin, winPtr, interp, objc, objv); 927 case WMOPT_GROUP: 928 return WmGroupCmd(tkwin, winPtr, interp, objc, objv); 929 case WMOPT_ICONBITMAP: 930 return WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv); 931 case WMOPT_ICONIFY: 932 return WmIconifyCmd(tkwin, winPtr, interp, objc, objv); 933 case WMOPT_ICONMASK: 934 return WmIconmaskCmd(tkwin, winPtr, interp, objc, objv); 935 case WMOPT_ICONNAME: 936 return WmIconnameCmd(tkwin, winPtr, interp, objc, objv); 937 case WMOPT_ICONPHOTO: 938 return WmIconphotoCmd(tkwin, winPtr, interp, objc, objv); 939 case WMOPT_ICONPOSITION: 940 return WmIconpositionCmd(tkwin, winPtr, interp, objc, objv); 941 case WMOPT_ICONWINDOW: 942 return WmIconwindowCmd(tkwin, winPtr, interp, objc, objv); 943 case WMOPT_MANAGE: 944 return WmManageCmd(tkwin, winPtr, interp, objc, objv); 945 case WMOPT_MAXSIZE: 946 return WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv); 947 case WMOPT_MINSIZE: 948 return WmMinsizeCmd(tkwin, winPtr, interp, objc, objv); 949 case WMOPT_OVERRIDEREDIRECT: 950 return WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv); 951 case WMOPT_POSITIONFROM: 952 return WmPositionfromCmd(tkwin, winPtr, interp, objc, objv); 953 case WMOPT_PROTOCOL: 954 return WmProtocolCmd(tkwin, winPtr, interp, objc, objv); 955 case WMOPT_RESIZABLE: 956 return WmResizableCmd(tkwin, winPtr, interp, objc, objv); 957 case WMOPT_SIZEFROM: 958 return WmSizefromCmd(tkwin, winPtr, interp, objc, objv); 959 case WMOPT_STACKORDER: 960 return WmStackorderCmd(tkwin, winPtr, interp, objc, objv); 961 case WMOPT_STATE: 962 return WmStateCmd(tkwin, winPtr, interp, objc, objv); 963 case WMOPT_TITLE: 964 return WmTitleCmd(tkwin, winPtr, interp, objc, objv); 965 case WMOPT_TRANSIENT: 966 return WmTransientCmd(tkwin, winPtr, interp, objc, objv); 967 case WMOPT_WITHDRAW: 968 return WmWithdrawCmd(tkwin, winPtr, interp, objc, objv); 969 } 970 971 /* This should not happen */ 972 return TCL_ERROR; 973} 974 975/* 976 *---------------------------------------------------------------------- 977 * 978 * WmAspectCmd -- 979 * 980 * This procedure is invoked to process the "wm aspect" Tcl command. See 981 * the user documentation for details on what it does. 982 * 983 * Results: 984 * A standard Tcl result. 985 * 986 * Side effects: 987 * See the user documentation. 988 * 989 *---------------------------------------------------------------------- 990 */ 991 992static int 993WmAspectCmd( 994 Tk_Window tkwin, /* Main window of the application. */ 995 TkWindow *winPtr, /* Toplevel to work with */ 996 Tcl_Interp *interp, /* Current interpreter. */ 997 int objc, /* Number of arguments. */ 998 Tcl_Obj *const objv[]) /* Argument objects. */ 999{ 1000 register WmInfo *wmPtr = winPtr->wmInfoPtr; 1001 int numer1, denom1, numer2, denom2; 1002 1003 if ((objc != 3) && (objc != 7)) { 1004 Tcl_WrongNumArgs(interp, 2, objv, 1005 "window ?minNumer minDenom maxNumer maxDenom?"); 1006 return TCL_ERROR; 1007 } 1008 if (objc == 3) { 1009 if (wmPtr->sizeHintsFlags & PAspect) { 1010 char buf[TCL_INTEGER_SPACE * 4]; 1011 1012 sprintf(buf, "%d %d %d %d", wmPtr->minAspect.x, 1013 wmPtr->minAspect.y, wmPtr->maxAspect.x, 1014 wmPtr->maxAspect.y); 1015 Tcl_SetResult(interp, buf, TCL_VOLATILE); 1016 } 1017 return TCL_OK; 1018 } 1019 if (*Tcl_GetString(objv[3]) == '\0') { 1020 wmPtr->sizeHintsFlags &= ~PAspect; 1021 } else { 1022 if ((Tcl_GetIntFromObj(interp, objv[3], &numer1) != TCL_OK) 1023 || (Tcl_GetIntFromObj(interp, objv[4], &denom1) != TCL_OK) 1024 || (Tcl_GetIntFromObj(interp, objv[5], &numer2) != TCL_OK) 1025 || (Tcl_GetIntFromObj(interp, objv[6], &denom2) != TCL_OK)) { 1026 return TCL_ERROR; 1027 } 1028 if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) || 1029 (denom2 <= 0)) { 1030 Tcl_SetResult(interp, "aspect number can't be <= 0", TCL_STATIC); 1031 return TCL_ERROR; 1032 } 1033 wmPtr->minAspect.x = numer1; 1034 wmPtr->minAspect.y = denom1; 1035 wmPtr->maxAspect.x = numer2; 1036 wmPtr->maxAspect.y = denom2; 1037 wmPtr->sizeHintsFlags |= PAspect; 1038 } 1039 wmPtr->flags |= WM_UPDATE_SIZE_HINTS; 1040 WmUpdateGeom(wmPtr, winPtr); 1041 return TCL_OK; 1042} 1043 1044/* 1045 *---------------------------------------------------------------------- 1046 * 1047 * WmSetAttribute -- 1048 * 1049 * Helper routine for WmAttributesCmd. Sets the value of the specified 1050 * attribute. 1051 * 1052 * Returns: 1053 * 1054 * TCL_OK if successful, TCL_ERROR otherwise. In case of an error, leaves 1055 * a message in the interpreter's result. 1056 * 1057 *---------------------------------------------------------------------- 1058 */ 1059 1060static int 1061WmSetAttribute( 1062 TkWindow *winPtr, /* Toplevel to work with */ 1063 NSWindow *macWindow, 1064 Tcl_Interp *interp, /* Current interpreter */ 1065 WmAttribute attribute, /* Code of attribute to set */ 1066 Tcl_Obj *value) /* New value */ 1067{ 1068 WmInfo *wmPtr = winPtr->wmInfoPtr; 1069 int boolean; 1070 1071 switch (attribute) { 1072 case WMATT_ALPHA: { 1073 double dval; 1074 1075 if (Tcl_GetDoubleFromObj(interp, value, &dval) != TCL_OK) { 1076 return TCL_ERROR; 1077 } 1078 1079 /* 1080 * The user should give (transparent) 0 .. 1.0 (opaque) 1081 */ 1082 1083 if (dval < 0.0) { 1084 dval = 0.0; 1085 } else if (dval > 1.0) { 1086 dval = 1.0; 1087 } 1088 [macWindow setAlphaValue:dval]; 1089 break; 1090 } 1091 case WMATT_FULLSCREEN: 1092 if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) { 1093 return TCL_ERROR; 1094 } 1095 if (boolean != ((wmPtr->flags & WM_FULLSCREEN) != 0)) { 1096 if (TkMacOSXMakeFullscreen(winPtr, macWindow, boolean, interp) 1097 != TCL_OK) { 1098 return TCL_ERROR; 1099 } 1100 } 1101 break; 1102 case WMATT_MODIFIED: 1103 if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) { 1104 return TCL_ERROR; 1105 } 1106 if (boolean != [macWindow isDocumentEdited]) { 1107 [macWindow setDocumentEdited:boolean]; 1108 } 1109 break; 1110 case WMATT_NOTIFY: 1111 if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) { 1112 return TCL_ERROR; 1113 } 1114 if (boolean == !tkMacOSXWmAttrNotifyVal) { 1115 static NSInteger request = -1; 1116 1117 if (request >= 0) { 1118 [NSApp cancelUserAttentionRequest:request]; 1119 request = -1; 1120 } 1121 if (boolean) { 1122 request = [NSApp requestUserAttention:NSCriticalRequest]; 1123 } 1124 tkMacOSXWmAttrNotifyVal = boolean; 1125 } 1126 break; 1127 case WMATT_TITLEPATH: { 1128 const char *path = Tcl_FSGetNativePath(value); 1129 NSString *filename = @""; 1130 1131 if (path && *path) { 1132 filename = [NSString stringWithUTF8String:path]; 1133 } 1134 [macWindow setRepresentedFilename:filename]; 1135 break; 1136 } 1137 case WMATT_TOPMOST: 1138 if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) { 1139 return TCL_ERROR; 1140 } 1141 if (boolean != ((wmPtr->flags & WM_TOPMOST) != 0)) { 1142 int oldFlags = wmPtr->flags; 1143 1144 if (boolean) { 1145 wmPtr->flags |= WM_TOPMOST; 1146 } else { 1147 wmPtr->flags &= ~WM_TOPMOST; 1148 } 1149 ApplyWindowAttributeFlagChanges(winPtr, macWindow, 1150 wmPtr->attributes, oldFlags, 1, 0); 1151 } 1152 break; 1153 case WMATT_TRANSPARENT: 1154 if (Tcl_GetBooleanFromObj(interp, value, &boolean) != TCL_OK) { 1155 return TCL_ERROR; 1156 } 1157 if (boolean != ((wmPtr->flags & WM_TRANSPARENT) != 0)) { 1158 UInt64 oldAttributes = wmPtr->attributes; 1159 int oldFlags = wmPtr->flags; 1160 1161 if (boolean) { 1162 wmPtr->flags |= WM_TRANSPARENT; 1163 wmPtr->attributes |= kWindowNoShadowAttribute; 1164 } else { 1165 wmPtr->flags &= ~WM_TRANSPARENT; 1166 wmPtr->attributes &= ~kWindowNoShadowAttribute; 1167 } 1168 ApplyWindowAttributeFlagChanges(winPtr, macWindow, oldAttributes, 1169 oldFlags, 1, 0); 1170 [macWindow setBackgroundColor:boolean ? [NSColor clearColor] : nil]; 1171 [macWindow setOpaque:!boolean]; 1172 TkMacOSXInvalidateWindow((MacDrawable *) winPtr->window, 1173 TK_PARENT_WINDOW); 1174 } 1175 break; 1176 case _WMATT_LAST_ATTRIBUTE: 1177 default: 1178 return TCL_ERROR; 1179 } 1180 return TCL_OK; 1181} 1182 1183/* 1184 *---------------------------------------------------------------------- 1185 * 1186 * WmGetAttribute -- 1187 * 1188 * Helper routine for WmAttributesCmd. Returns the current value of the 1189 * specified attribute. 1190 * 1191 *---------------------------------------------------------------------- 1192 */ 1193 1194static Tcl_Obj * 1195WmGetAttribute( 1196 TkWindow *winPtr, /* Toplevel to work with */ 1197 NSWindow *macWindow, 1198 WmAttribute attribute) /* Code of attribute to get */ 1199{ 1200 Tcl_Obj *result = NULL; 1201 WmInfo *wmPtr = winPtr->wmInfoPtr; 1202 1203 switch (attribute) { 1204 case WMATT_ALPHA: 1205 result = Tcl_NewDoubleObj([macWindow alphaValue]); 1206 break; 1207 case WMATT_FULLSCREEN: 1208 result = Tcl_NewBooleanObj(wmPtr->flags & WM_FULLSCREEN); 1209 break; 1210 case WMATT_MODIFIED: 1211 result = Tcl_NewBooleanObj([macWindow isDocumentEdited]); 1212 break; 1213 case WMATT_NOTIFY: 1214 result = Tcl_NewBooleanObj(tkMacOSXWmAttrNotifyVal); 1215 break; 1216 case WMATT_TITLEPATH: 1217 result = Tcl_NewStringObj([[macWindow representedFilename] UTF8String], 1218 -1); 1219 break; 1220 case WMATT_TOPMOST: 1221 result = Tcl_NewBooleanObj(wmPtr->flags & WM_TOPMOST); 1222 break; 1223 case WMATT_TRANSPARENT: 1224 result = Tcl_NewBooleanObj(wmPtr->flags & WM_TRANSPARENT); 1225 break; 1226 case _WMATT_LAST_ATTRIBUTE: 1227 default: 1228 break; 1229 } 1230 return result; 1231} 1232 1233/* 1234 *---------------------------------------------------------------------- 1235 * 1236 * WmAttributesCmd -- 1237 * 1238 * This procedure is invoked to process the "wm attributes" Tcl command. 1239 * See the user documentation for details on what it does. 1240 * 1241 * Results: 1242 * A standard Tcl result. 1243 * 1244 * Side effects: 1245 * See the user documentation. 1246 * 1247 *---------------------------------------------------------------------- 1248 */ 1249 1250static int 1251WmAttributesCmd( 1252 Tk_Window tkwin, /* Main window of the application. */ 1253 TkWindow *winPtr, /* Toplevel to work with */ 1254 Tcl_Interp *interp, /* Current interpreter. */ 1255 int objc, /* Number of arguments. */ 1256 Tcl_Obj *const objv[]) /* Argument objects. */ 1257{ 1258 int attribute = 0; 1259 NSWindow *macWindow; 1260 1261 if (winPtr->window == None) { 1262 Tk_MakeWindowExist((Tk_Window) winPtr); 1263 } 1264 if (!TkMacOSXHostToplevelExists(winPtr)) { 1265 TkMacOSXMakeRealWindowExist(winPtr); 1266 } 1267 macWindow = TkMacOSXDrawableWindow(winPtr->window); 1268 1269 if (objc == 3) { /* wm attributes $win */ 1270 Tcl_Obj *result = Tcl_NewListObj(0,0); 1271 1272 for (attribute = 0; attribute < _WMATT_LAST_ATTRIBUTE; ++attribute) { 1273 Tcl_ListObjAppendElement(interp, result, 1274 Tcl_NewStringObj(WmAttributeNames[attribute], -1)); 1275 Tcl_ListObjAppendElement(interp, result, 1276 WmGetAttribute(winPtr, macWindow, attribute)); 1277 } 1278 Tcl_SetObjResult(interp, result); 1279 } else if (objc == 4) { /* wm attributes $win -attribute */ 1280 if (Tcl_GetIndexFromObj(interp, objv[3], WmAttributeNames, 1281 "attribute", 0, &attribute) != TCL_OK) { 1282 return TCL_ERROR; 1283 } 1284 Tcl_SetObjResult(interp, WmGetAttribute(winPtr, macWindow, attribute)); 1285 } else if ((objc - 3) % 2 == 0) { /* wm attributes $win -att value... */ 1286 int i; 1287 1288 for (i = 3; i < objc; i += 2) { 1289 if (Tcl_GetIndexFromObj(interp, objv[i], WmAttributeNames, 1290 "attribute", 0, &attribute) != TCL_OK) { 1291 return TCL_ERROR; 1292 } 1293 if (WmSetAttribute(winPtr, macWindow, interp, attribute, objv[i+1]) 1294 != TCL_OK) { 1295 return TCL_ERROR; 1296 } 1297 } 1298 } else { 1299 Tcl_WrongNumArgs(interp, 2, objv, "window ?-attribute ?value ...??"); 1300 return TCL_ERROR; 1301 } 1302 return TCL_OK; 1303} 1304 1305/* 1306 *---------------------------------------------------------------------- 1307 * 1308 * WmClientCmd -- 1309 * 1310 * This procedure is invoked to process the "wm client" Tcl command. See 1311 * the user documentation for details on what it does. 1312 * 1313 * Results: 1314 * A standard Tcl result. 1315 * 1316 * Side effects: 1317 * See the user documentation. 1318 * 1319 *---------------------------------------------------------------------- 1320 */ 1321 1322static int 1323WmClientCmd( 1324 Tk_Window tkwin, /* Main window of the application. */ 1325 TkWindow *winPtr, /* Toplevel to work with */ 1326 Tcl_Interp *interp, /* Current interpreter. */ 1327 int objc, /* Number of arguments. */ 1328 Tcl_Obj *const objv[]) /* Argument objects. */ 1329{ 1330 register WmInfo *wmPtr = winPtr->wmInfoPtr; 1331 char *argv3; 1332 int length; 1333 1334 if ((objc != 3) && (objc != 4)) { 1335 Tcl_WrongNumArgs(interp, 2, objv, "window ?name?"); 1336 return TCL_ERROR; 1337 } 1338 if (objc == 3) { 1339 if (wmPtr->clientMachine != NULL) { 1340 Tcl_SetResult(interp, wmPtr->clientMachine, TCL_STATIC); 1341 } 1342 return TCL_OK; 1343 } 1344 argv3 = Tcl_GetStringFromObj(objv[3], &length); 1345 if (argv3[0] == 0) { 1346 if (wmPtr->clientMachine != NULL) { 1347 ckfree((char *) wmPtr->clientMachine); 1348 wmPtr->clientMachine = NULL; 1349 } 1350 return TCL_OK; 1351 } 1352 if (wmPtr->clientMachine != NULL) { 1353 ckfree((char *) wmPtr->clientMachine); 1354 } 1355 wmPtr->clientMachine = ckalloc((unsigned) length + 1); 1356 strcpy(wmPtr->clientMachine, argv3); 1357 return TCL_OK; 1358} 1359 1360/* 1361 *---------------------------------------------------------------------- 1362 * 1363 * WmColormapwindowsCmd -- 1364 * 1365 * This procedure is invoked to process the "wm colormapwindows" Tcl 1366 * command. See the user documentation for details on what it does. 1367 * 1368 * Results: 1369 * A standard Tcl result. 1370 * 1371 * Side effects: 1372 * See the user documentation. 1373 * 1374 *---------------------------------------------------------------------- 1375 */ 1376 1377static int 1378WmColormapwindowsCmd( 1379 Tk_Window tkwin, /* Main window of the application. */ 1380 TkWindow *winPtr, /* Toplevel to work with */ 1381 Tcl_Interp *interp, /* Current interpreter. */ 1382 int objc, /* Number of arguments. */ 1383 Tcl_Obj *const objv[]) /* Argument objects. */ 1384{ 1385 register WmInfo *wmPtr = winPtr->wmInfoPtr; 1386 TkWindow **cmapList; 1387 TkWindow *winPtr2; 1388 int i, windowObjc, gotToplevel = 0; 1389 Tcl_Obj **windowObjv; 1390 1391 if ((objc != 3) && (objc != 4)) { 1392 Tcl_WrongNumArgs(interp, 2, objv, "window ?windowList?"); 1393 return TCL_ERROR; 1394 } 1395 if (objc == 3) { 1396 Tk_MakeWindowExist((Tk_Window) winPtr); 1397 for (i = 0; i < wmPtr->cmapCount; i++) { 1398 if ((i == (wmPtr->cmapCount-1)) 1399 && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) { 1400 break; 1401 } 1402 Tcl_AppendElement(interp, wmPtr->cmapList[i]->pathName); 1403 } 1404 return TCL_OK; 1405 } 1406 if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv) 1407 != TCL_OK) { 1408 return TCL_ERROR; 1409 } 1410 cmapList = (TkWindow **) ckalloc((unsigned) 1411 ((windowObjc+1) * sizeof(TkWindow*))); 1412 for (i = 0; i < windowObjc; i++) { 1413 if (TkGetWindowFromObj(interp, tkwin, windowObjv[i], 1414 (Tk_Window *) &winPtr2) != TCL_OK) { 1415 ckfree((char *) cmapList); 1416 return TCL_ERROR; 1417 } 1418 if (winPtr2 == winPtr) { 1419 gotToplevel = 1; 1420 } 1421 if (winPtr2->window == None) { 1422 Tk_MakeWindowExist((Tk_Window) winPtr2); 1423 } 1424 cmapList[i] = winPtr2; 1425 } 1426 if (!gotToplevel) { 1427 wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP; 1428 cmapList[windowObjc] = winPtr; 1429 windowObjc++; 1430 } else { 1431 wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP; 1432 } 1433 wmPtr->flags |= WM_COLORMAPS_EXPLICIT; 1434 if (wmPtr->cmapList != NULL) { 1435 ckfree((char *) wmPtr->cmapList); 1436 } 1437 wmPtr->cmapList = cmapList; 1438 wmPtr->cmapCount = windowObjc; 1439 1440 /* 1441 * On the Macintosh all of this is just an excercise in compatability as 1442 * we don't support colormaps. If we did they would be installed here. 1443 */ 1444 1445 return TCL_OK; 1446} 1447 1448/* 1449 *---------------------------------------------------------------------- 1450 * 1451 * WmCommandCmd -- 1452 * 1453 * This procedure is invoked to process the "wm command" Tcl command. See 1454 * the user documentation for details on what it does. 1455 * 1456 * Results: 1457 * A standard Tcl result. 1458 * 1459 * Side effects: 1460 * See the user documentation. 1461 * 1462 *---------------------------------------------------------------------- 1463 */ 1464 1465static int 1466WmCommandCmd( 1467 Tk_Window tkwin, /* Main window of the application. */ 1468 TkWindow *winPtr, /* Toplevel to work with */ 1469 Tcl_Interp *interp, /* Current interpreter. */ 1470 int objc, /* Number of arguments. */ 1471 Tcl_Obj *const objv[]) /* Argument objects. */ 1472{ 1473 register WmInfo *wmPtr = winPtr->wmInfoPtr; 1474 char *argv3; 1475 int cmdArgc; 1476 const char **cmdArgv; 1477 1478 if ((objc != 3) && (objc != 4)) { 1479 Tcl_WrongNumArgs(interp, 2, objv, "window ?value?"); 1480 return TCL_ERROR; 1481 } 1482 if (objc == 3) { 1483 if (wmPtr->cmdArgv != NULL) { 1484 argv3 = Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv); 1485 Tcl_SetResult(interp, argv3, TCL_VOLATILE); 1486 ckfree(argv3); 1487 } 1488 return TCL_OK; 1489 } 1490 argv3 = Tcl_GetString(objv[3]); 1491 if (argv3[0] == 0) { 1492 if (wmPtr->cmdArgv != NULL) { 1493 ckfree((char *) wmPtr->cmdArgv); 1494 wmPtr->cmdArgv = NULL; 1495 } 1496 return TCL_OK; 1497 } 1498 if (Tcl_SplitList(interp, argv3, &cmdArgc, &cmdArgv) != TCL_OK) { 1499 return TCL_ERROR; 1500 } 1501 if (wmPtr->cmdArgv != NULL) { 1502 ckfree((char *) wmPtr->cmdArgv); 1503 } 1504 wmPtr->cmdArgc = cmdArgc; 1505 wmPtr->cmdArgv = cmdArgv; 1506 return TCL_OK; 1507} 1508 1509/* 1510 *---------------------------------------------------------------------- 1511 * 1512 * WmDeiconifyCmd -- 1513 * 1514 * This procedure is invoked to process the "wm deiconify" Tcl command. 1515 * See the user documentation for details on what it does. 1516 * 1517 * Results: 1518 * A standard Tcl result. 1519 * 1520 * Side effects: 1521 * See the user documentation. 1522 * 1523 *---------------------------------------------------------------------- 1524 */ 1525 1526static int 1527WmDeiconifyCmd( 1528 Tk_Window tkwin, /* Main window of the application. */ 1529 TkWindow *winPtr, /* Toplevel to work with */ 1530 Tcl_Interp *interp, /* Current interpreter. */ 1531 int objc, /* Number of arguments. */ 1532 Tcl_Obj *const objv[]) /* Argument objects. */ 1533{ 1534 register WmInfo *wmPtr = winPtr->wmInfoPtr; 1535 1536 if (objc != 3) { 1537 Tcl_WrongNumArgs(interp, 2, objv, "window"); 1538 return TCL_ERROR; 1539 } 1540 if (wmPtr->iconFor != NULL) { 1541 Tcl_AppendResult(interp, "can't deiconify ", Tcl_GetString(objv[2]), 1542 ": it is an icon for ", Tk_PathName(wmPtr->iconFor), NULL); 1543 return TCL_ERROR; 1544 } 1545 if (winPtr->flags & TK_EMBEDDED) { 1546 Tcl_AppendResult(interp, "can't deiconify ", winPtr->pathName, 1547 ": it is an embedded window", NULL); 1548 return TCL_ERROR; 1549 } 1550 TkpWmSetState(winPtr, TkMacOSXIsWindowZoomed(winPtr) ? 1551 ZoomState : NormalState); 1552 return TCL_OK; 1553} 1554 1555/* 1556 *---------------------------------------------------------------------- 1557 * 1558 * WmFocusmodelCmd -- 1559 * 1560 * This procedure is invoked to process the "wm focusmodel" Tcl command. 1561 * See the user documentation for details on what it does. 1562 * 1563 * Results: 1564 * A standard Tcl result. 1565 * 1566 * Side effects: 1567 * See the user documentation. 1568 * 1569 *---------------------------------------------------------------------- 1570 */ 1571 1572static int 1573WmFocusmodelCmd( 1574 Tk_Window tkwin, /* Main window of the application. */ 1575 TkWindow *winPtr, /* Toplevel to work with */ 1576 Tcl_Interp *interp, /* Current interpreter. */ 1577 int objc, /* Number of arguments. */ 1578 Tcl_Obj *const objv[]) /* Argument objects. */ 1579{ 1580 register WmInfo *wmPtr = winPtr->wmInfoPtr; 1581 static const char *optionStrings[] = { 1582 "active", "passive", NULL }; 1583 enum options { 1584 OPT_ACTIVE, OPT_PASSIVE }; 1585 int index; 1586 1587 if ((objc != 3) && (objc != 4)) { 1588 Tcl_WrongNumArgs(interp, 2, objv, "window ?active|passive?"); 1589 return TCL_ERROR; 1590 } 1591 if (objc == 3) { 1592 Tcl_SetResult(interp, (wmPtr->hints.input ? "passive" : "active"), 1593 TCL_STATIC); 1594 return TCL_OK; 1595 } 1596 1597 if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, 1598 &index) != TCL_OK) { 1599 return TCL_ERROR; 1600 } 1601 if (index == OPT_ACTIVE) { 1602 wmPtr->hints.input = False; 1603 } else { /* OPT_PASSIVE */ 1604 wmPtr->hints.input = True; 1605 } 1606 return TCL_OK; 1607} 1608 1609/* 1610 *---------------------------------------------------------------------- 1611 * 1612 * WmForgetCmd -- 1613 * 1614 * This procedure is invoked to process the "wm forget" Tcl command. 1615 * See the user documentation for details on what it does. 1616 * 1617 * Results: 1618 * A standard Tcl result. 1619 * 1620 * Side effects: 1621 * See the user documentation. 1622 * 1623 *---------------------------------------------------------------------- 1624 */ 1625 1626static int 1627WmForgetCmd( 1628 Tk_Window tkwin, /* Main window of the application. */ 1629 TkWindow *winPtr, /* Toplevel or Frame to work with */ 1630 Tcl_Interp *interp, /* Current interpreter. */ 1631 int objc, /* Number of arguments. */ 1632 Tcl_Obj *const objv[]) /* Argument objects. */ 1633{ 1634#if 1 1635 Tcl_AppendResult(interp, "wm forget is not yet supported", NULL); 1636 return TCL_ERROR; 1637#else 1638 register Tk_Window frameWin = (Tk_Window)winPtr; 1639 char *oldClass = (char*)Tk_Class(frameWin); 1640 1641 if (Tk_IsTopLevel(frameWin)) { 1642 MacDrawable *macWin = (MacDrawable *) winPtr->window; 1643 CGrafPtr destPort = TkMacOSXGetDrawablePort(winPtr->window); 1644 1645 TkFocusJoin(winPtr); 1646 Tk_UnmapWindow(frameWin); 1647 1648 if (destPort != NULL) { 1649 WindowRef winRef = GetWindowFromPort(destPort); 1650 1651 TkMacOSXUnregisterMacWindow(winRef); 1652 DisposeWindow(winRef); 1653 } 1654 macWin->grafPtr = NULL; 1655 macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel; 1656 macWin->flags &= ~TK_HOST_EXISTS; 1657 1658 RemapWindows(winPtr, macWin); 1659 TkWmDeadWindow(winPtr); 1660 winPtr->flags &= 1661 ~(TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED); 1662 1663 TkMapTopFrame(frameWin); 1664 } else { 1665 /* Already not managed by wm - ignore it */ 1666 } 1667 return TCL_OK; 1668#endif 1669} 1670 1671/* 1672 *---------------------------------------------------------------------- 1673 * 1674 * WmFrameCmd -- 1675 * 1676 * This procedure is invoked to process the "wm frame" Tcl command. See 1677 * the user documentation for details on what it does. 1678 * 1679 * Results: 1680 * A standard Tcl result. 1681 * 1682 * Side effects: 1683 * See the user documentation. 1684 * 1685 *---------------------------------------------------------------------- 1686 */ 1687 1688static int 1689WmFrameCmd( 1690 Tk_Window tkwin, /* Main window of the application. */ 1691 TkWindow *winPtr, /* Toplevel to work with */ 1692 Tcl_Interp *interp, /* Current interpreter. */ 1693 int objc, /* Number of arguments. */ 1694 Tcl_Obj *const objv[]) /* Argument objects. */ 1695{ 1696 register WmInfo *wmPtr = winPtr->wmInfoPtr; 1697 Window window; 1698 char buf[TCL_INTEGER_SPACE]; 1699 1700 if (objc != 3) { 1701 Tcl_WrongNumArgs(interp, 2, objv, "window"); 1702 return TCL_ERROR; 1703 } 1704 window = wmPtr->reparent; 1705 if (window == None) { 1706 window = Tk_WindowId((Tk_Window) winPtr); 1707 } 1708 sprintf(buf, "0x%x", (unsigned) window); 1709 Tcl_SetResult(interp, buf, TCL_VOLATILE); 1710 return TCL_OK; 1711} 1712 1713/* 1714 *---------------------------------------------------------------------- 1715 * 1716 * WmGeometryCmd -- 1717 * 1718 * This procedure is invoked to process the "wm geometry" Tcl command. 1719 * See the user documentation for details on what it does. 1720 * 1721 * Results: 1722 * A standard Tcl result. 1723 * 1724 * Side effects: 1725 * See the user documentation. 1726 * 1727 *---------------------------------------------------------------------- 1728 */ 1729 1730static int 1731WmGeometryCmd( 1732 Tk_Window tkwin, /* Main window of the application. */ 1733 TkWindow *winPtr, /* Toplevel to work with */ 1734 Tcl_Interp *interp, /* Current interpreter. */ 1735 int objc, /* Number of arguments. */ 1736 Tcl_Obj *const objv[]) /* Argument objects. */ 1737{ 1738 register WmInfo *wmPtr = winPtr->wmInfoPtr; 1739 char xSign, ySign; 1740 int width, height; 1741 char *argv3; 1742 1743 if ((objc != 3) && (objc != 4)) { 1744 Tcl_WrongNumArgs(interp, 2, objv, "window ?newGeometry?"); 1745 return TCL_ERROR; 1746 } 1747 if (objc == 3) { 1748 char buf[16 + TCL_INTEGER_SPACE * 4]; 1749 1750 xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+'; 1751 ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+'; 1752 if (wmPtr->gridWin != NULL) { 1753 width = wmPtr->reqGridWidth + (winPtr->changes.width 1754 - winPtr->reqWidth)/wmPtr->widthInc; 1755 height = wmPtr->reqGridHeight + (winPtr->changes.height 1756 - winPtr->reqHeight)/wmPtr->heightInc; 1757 } else { 1758 width = winPtr->changes.width; 1759 height = winPtr->changes.height; 1760 } 1761 sprintf(buf, "%dx%d%c%d%c%d", 1762 width, height, xSign, wmPtr->x, ySign, wmPtr->y); 1763 Tcl_SetResult(interp, buf, TCL_VOLATILE); 1764 return TCL_OK; 1765 } 1766 argv3 = Tcl_GetString(objv[3]); 1767 if (*argv3 == '\0') { 1768 wmPtr->width = -1; 1769 wmPtr->height = -1; 1770 WmUpdateGeom(wmPtr, winPtr); 1771 return TCL_OK; 1772 } 1773 return ParseGeometry(interp, argv3, winPtr); 1774} 1775 1776/* 1777 *---------------------------------------------------------------------- 1778 * 1779 * WmGridCmd -- 1780 * 1781 * This procedure is invoked to process the "wm grid" Tcl command. See 1782 * the user documentation for details on what it does. 1783 * 1784 * Results: 1785 * A standard Tcl result. 1786 * 1787 * Side effects: 1788 * See the user documentation. 1789 * 1790 *---------------------------------------------------------------------- 1791 */ 1792 1793static int 1794WmGridCmd( 1795 Tk_Window tkwin, /* Main window of the application. */ 1796 TkWindow *winPtr, /* Toplevel to work with */ 1797 Tcl_Interp *interp, /* Current interpreter. */ 1798 int objc, /* Number of arguments. */ 1799 Tcl_Obj *const objv[]) /* Argument objects. */ 1800{ 1801 register WmInfo *wmPtr = winPtr->wmInfoPtr; 1802 int reqWidth, reqHeight, widthInc, heightInc; 1803 1804 if ((objc != 3) && (objc != 7)) { 1805 Tcl_WrongNumArgs(interp, 2, objv, 1806 "window ?baseWidth baseHeight widthInc heightInc?"); 1807 return TCL_ERROR; 1808 } 1809 if (objc == 3) { 1810 if (wmPtr->sizeHintsFlags & PBaseSize) { 1811 char buf[TCL_INTEGER_SPACE * 4]; 1812 1813 sprintf(buf, "%d %d %d %d", wmPtr->reqGridWidth, 1814 wmPtr->reqGridHeight, wmPtr->widthInc, 1815 wmPtr->heightInc); 1816 Tcl_SetResult(interp, buf, TCL_VOLATILE); 1817 } 1818 return TCL_OK; 1819 } 1820 if (*Tcl_GetString(objv[3]) == '\0') { 1821 /* 1822 * Turn off gridding and reset the width and height to make sense as 1823 * ungridded numbers. 1824 */ 1825 1826 wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc); 1827 if (wmPtr->width != -1) { 1828 wmPtr->width = winPtr->reqWidth + (wmPtr->width 1829 - wmPtr->reqGridWidth)*wmPtr->widthInc; 1830 wmPtr->height = winPtr->reqHeight + (wmPtr->height 1831 - wmPtr->reqGridHeight)*wmPtr->heightInc; 1832 } 1833 wmPtr->widthInc = 1; 1834 wmPtr->heightInc = 1; 1835 } else { 1836 if ((Tcl_GetIntFromObj(interp, objv[3], &reqWidth) != TCL_OK) 1837 || (Tcl_GetIntFromObj(interp, objv[4], &reqHeight) != TCL_OK) 1838 || (Tcl_GetIntFromObj(interp, objv[5], &widthInc) != TCL_OK) 1839 || (Tcl_GetIntFromObj(interp, objv[6], &heightInc)!=TCL_OK)) { 1840 return TCL_ERROR; 1841 } 1842 if (reqWidth < 0) { 1843 Tcl_SetResult(interp, "baseWidth can't be < 0", TCL_STATIC); 1844 return TCL_ERROR; 1845 } 1846 if (reqHeight < 0) { 1847 Tcl_SetResult(interp, "baseHeight can't be < 0", TCL_STATIC); 1848 return TCL_ERROR; 1849 } 1850 if (widthInc <= 0) { 1851 Tcl_SetResult(interp, "widthInc can't be <= 0", TCL_STATIC); 1852 return TCL_ERROR; 1853 } 1854 if (heightInc <= 0) { 1855 Tcl_SetResult(interp, "heightInc can't be <= 0", TCL_STATIC); 1856 return TCL_ERROR; 1857 } 1858 Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc, 1859 heightInc); 1860 } 1861 wmPtr->flags |= WM_UPDATE_SIZE_HINTS; 1862 WmUpdateGeom(wmPtr, winPtr); 1863 return TCL_OK; 1864} 1865 1866/* 1867 *---------------------------------------------------------------------- 1868 * 1869 * WmGroupCmd -- 1870 * 1871 * This procedure is invoked to process the "wm group" Tcl command. See 1872 * the user documentation for details on what it does. 1873 * 1874 * Results: 1875 * A standard Tcl result. 1876 * 1877 * Side effects: 1878 * See the user documentation. 1879 * 1880 *---------------------------------------------------------------------- 1881 */ 1882 1883static int 1884WmGroupCmd( 1885 Tk_Window tkwin, /* Main window of the application. */ 1886 TkWindow *winPtr, /* Toplevel to work with */ 1887 Tcl_Interp *interp, /* Current interpreter. */ 1888 int objc, /* Number of arguments. */ 1889 Tcl_Obj *const objv[]) /* Argument objects. */ 1890{ 1891 register WmInfo *wmPtr = winPtr->wmInfoPtr; 1892 Tk_Window tkwin2; 1893 char *argv3; 1894 int length; 1895 1896 if ((objc != 3) && (objc != 4)) { 1897 Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?"); 1898 return TCL_ERROR; 1899 } 1900 if (objc == 3) { 1901 if (wmPtr->hints.flags & WindowGroupHint) { 1902 Tcl_SetResult(interp, wmPtr->leaderName, TCL_STATIC); 1903 } 1904 return TCL_OK; 1905 } 1906 argv3 = Tcl_GetStringFromObj(objv[3], &length); 1907 if (*argv3 == '\0') { 1908 wmPtr->hints.flags &= ~WindowGroupHint; 1909 if (wmPtr->leaderName != NULL) { 1910 ckfree(wmPtr->leaderName); 1911 } 1912 wmPtr->leaderName = NULL; 1913 } else { 1914 if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) { 1915 return TCL_ERROR; 1916 } 1917 Tk_MakeWindowExist(tkwin2); 1918 if (wmPtr->leaderName != NULL) { 1919 ckfree(wmPtr->leaderName); 1920 } 1921 wmPtr->hints.window_group = Tk_WindowId(tkwin2); 1922 wmPtr->hints.flags |= WindowGroupHint; 1923 wmPtr->leaderName = ckalloc((unsigned) (length + 1)); 1924 strcpy(wmPtr->leaderName, argv3); 1925 } 1926 return TCL_OK; 1927} 1928 1929/* 1930 *---------------------------------------------------------------------- 1931 * 1932 * WmIconbitmapCmd -- 1933 * 1934 * This procedure is invoked to process the "wm iconbitmap" Tcl command. 1935 * See the user documentation for details on what it does. 1936 * 1937 * Results: 1938 * A standard Tcl result. 1939 * 1940 * Side effects: 1941 * See the user documentation. 1942 * 1943 *---------------------------------------------------------------------- 1944 */ 1945 1946static int 1947WmIconbitmapCmd( 1948 Tk_Window tkwin, /* Main window of the application. */ 1949 TkWindow *winPtr, /* Toplevel to work with */ 1950 Tcl_Interp *interp, /* Current interpreter. */ 1951 int objc, /* Number of arguments. */ 1952 Tcl_Obj *const objv[]) /* Argument objects. */ 1953{ 1954 register WmInfo *wmPtr = winPtr->wmInfoPtr; 1955 Pixmap pixmap; 1956 char *str; 1957 int len; 1958 1959 if ((objc != 3) && (objc != 4)) { 1960 Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?"); 1961 return TCL_ERROR; 1962 } 1963 if (objc == 3) { 1964 if (wmPtr->hints.flags & IconPixmapHint) { 1965 Tcl_SetResult(interp, (char*)Tk_NameOfBitmap(winPtr->display, 1966 wmPtr->hints.icon_pixmap), TCL_STATIC); 1967 } 1968 return TCL_OK; 1969 } 1970 str = Tcl_GetStringFromObj(objv[3], &len); 1971 if (winPtr->window == None) { 1972 Tk_MakeWindowExist((Tk_Window) winPtr); 1973 } 1974 if (!TkMacOSXHostToplevelExists(winPtr)) { 1975 TkMacOSXMakeRealWindowExist(winPtr); 1976 } 1977 if (WmSetAttribute(winPtr, TkMacOSXDrawableWindow(winPtr->window), interp, 1978 WMATT_TITLEPATH, objv[3]) == TCL_OK) { 1979 if (!len) { 1980 if (wmPtr->hints.icon_pixmap != None) { 1981 Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap); 1982 wmPtr->hints.icon_pixmap = None; 1983 } 1984 wmPtr->hints.flags &= ~IconPixmapHint; 1985 } 1986 } else { 1987 pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr, Tk_GetUid(str)); 1988 if (pixmap == None) { 1989 return TCL_ERROR; 1990 } 1991 wmPtr->hints.icon_pixmap = pixmap; 1992 wmPtr->hints.flags |= IconPixmapHint; 1993 } 1994 return TCL_OK; 1995} 1996 1997/* 1998 *---------------------------------------------------------------------- 1999 * 2000 * WmIconifyCmd -- 2001 * 2002 * This procedure is invoked to process the "wm iconify" Tcl command. See 2003 * the user documentation for details on what it does. 2004 * 2005 * Results: 2006 * A standard Tcl result. 2007 * 2008 * Side effects: 2009 * See the user documentation. 2010 * 2011 *---------------------------------------------------------------------- 2012 */ 2013 2014static int 2015WmIconifyCmd( 2016 Tk_Window tkwin, /* Main window of the application. */ 2017 TkWindow *winPtr, /* Toplevel to work with */ 2018 Tcl_Interp *interp, /* Current interpreter. */ 2019 int objc, /* Number of arguments. */ 2020 Tcl_Obj *const objv[]) /* Argument objects. */ 2021{ 2022 register WmInfo *wmPtr = winPtr->wmInfoPtr; 2023 if (objc != 3) { 2024 Tcl_WrongNumArgs(interp, 2, objv, "window"); 2025 return TCL_ERROR; 2026 } 2027 if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) { 2028 Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName, 2029 "\": override-redirect flag is set", NULL); 2030 return TCL_ERROR; 2031 } 2032 if (wmPtr->master != None) { 2033 Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName, 2034 "\": it is a transient", NULL); 2035 return TCL_ERROR; 2036 } 2037 if (wmPtr->iconFor != NULL) { 2038 Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName, 2039 ": it is an icon for ", Tk_PathName(wmPtr->iconFor), NULL); 2040 return TCL_ERROR; 2041 } 2042 if (winPtr->flags & TK_EMBEDDED) { 2043 Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName, 2044 ": it is an embedded window", NULL); 2045 return TCL_ERROR; 2046 } 2047 TkpWmSetState(winPtr, IconicState); 2048 return TCL_OK; 2049} 2050 2051/* 2052 *---------------------------------------------------------------------- 2053 * 2054 * WmIconmaskCmd -- 2055 * 2056 * This procedure is invoked to process the "wm iconmask" Tcl command. 2057 * See the user documentation for details on what it does. 2058 * 2059 * Results: 2060 * A standard Tcl result. 2061 * 2062 * Side effects: 2063 * See the user documentation. 2064 * 2065 *---------------------------------------------------------------------- 2066 */ 2067 2068static int 2069WmIconmaskCmd( 2070 Tk_Window tkwin, /* Main window of the application. */ 2071 TkWindow *winPtr, /* Toplevel to work with */ 2072 Tcl_Interp *interp, /* Current interpreter. */ 2073 int objc, /* Number of arguments. */ 2074 Tcl_Obj *const objv[]) /* Argument objects. */ 2075{ 2076 register WmInfo *wmPtr = winPtr->wmInfoPtr; 2077 Pixmap pixmap; 2078 char *argv3; 2079 2080 if ((objc != 3) && (objc != 4)) { 2081 Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?"); 2082 return TCL_ERROR; 2083 } 2084 if (objc == 3) { 2085 if (wmPtr->hints.flags & IconMaskHint) { 2086 Tcl_SetResult(interp, (char *) Tk_NameOfBitmap(winPtr->display, 2087 wmPtr->hints.icon_mask), TCL_STATIC); 2088 } 2089 return TCL_OK; 2090 } 2091 argv3 = Tcl_GetString(objv[3]); 2092 if (*argv3 == '\0') { 2093 if (wmPtr->hints.icon_mask != None) { 2094 Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask); 2095 } 2096 wmPtr->hints.flags &= ~IconMaskHint; 2097 } else { 2098 pixmap = Tk_GetBitmap(interp, tkwin, argv3); 2099 if (pixmap == None) { 2100 return TCL_ERROR; 2101 } 2102 wmPtr->hints.icon_mask = pixmap; 2103 wmPtr->hints.flags |= IconMaskHint; 2104 } 2105 return TCL_OK; 2106} 2107 2108/* 2109 *---------------------------------------------------------------------- 2110 * 2111 * WmIconnameCmd -- 2112 * 2113 * This procedure is invoked to process the "wm iconname" Tcl command. 2114 * See the user documentation for details on what it does. 2115 * 2116 * Results: 2117 * A standard Tcl result. 2118 * 2119 * Side effects: 2120 * See the user documentation. 2121 * 2122 *---------------------------------------------------------------------- 2123 */ 2124 2125static int 2126WmIconnameCmd( 2127 Tk_Window tkwin, /* Main window of the application. */ 2128 TkWindow *winPtr, /* Toplevel to work with */ 2129 Tcl_Interp *interp, /* Current interpreter. */ 2130 int objc, /* Number of arguments. */ 2131 Tcl_Obj *const objv[]) /* Argument objects. */ 2132{ 2133 register WmInfo *wmPtr = winPtr->wmInfoPtr; 2134 const char *argv3; 2135 int length; 2136 2137 if (objc > 4) { 2138 Tcl_WrongNumArgs(interp, 2, objv, "window ?newName?"); 2139 return TCL_ERROR; 2140 } 2141 if (objc == 3) { 2142 if (wmPtr->iconName != NULL) { 2143 Tcl_SetObjResult(interp, Tcl_NewStringObj(wmPtr->iconName, -1)); 2144 } 2145 return TCL_OK; 2146 } 2147 2148 if (wmPtr->iconName != NULL) { 2149 ckfree((char *) wmPtr->iconName); 2150 } 2151 argv3 = Tcl_GetStringFromObj(objv[3], &length); 2152 wmPtr->iconName = ckalloc((unsigned) length + 1); 2153 strcpy(wmPtr->iconName, argv3); 2154 if (!(wmPtr->flags & WM_NEVER_MAPPED)) { 2155 XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName); 2156 } 2157 return TCL_OK; 2158} 2159 2160/* 2161 *---------------------------------------------------------------------- 2162 * 2163 * WmIconphotoCmd -- 2164 * 2165 * This procedure is invoked to process the "wm iconphoto" Tcl command. 2166 * See the user documentation for details on what it does. Not yet 2167 * implemented for OS X. 2168 * 2169 * Results: 2170 * A standard Tcl result. 2171 * 2172 * Side effects: 2173 * See the user documentation. 2174 * 2175 *---------------------------------------------------------------------- 2176 */ 2177 2178static int 2179WmIconphotoCmd( 2180 Tk_Window tkwin, /* Main window of the application. */ 2181 TkWindow *winPtr, /* Toplevel to work with */ 2182 Tcl_Interp *interp, /* Current interpreter. */ 2183 int objc, /* Number of arguments. */ 2184 Tcl_Obj *const objv[]) /* Argument objects. */ 2185{ 2186 Tk_PhotoHandle photo; 2187 int i, width, height, isDefault = 0; 2188 2189 if (objc < 4) { 2190 Tcl_WrongNumArgs(interp, 2, objv, 2191 "window ?-default? image1 ?image2 ...?"); 2192 return TCL_ERROR; 2193 } 2194 if (strcmp(Tcl_GetString(objv[3]), "-default") == 0) { 2195 isDefault = 1; 2196 if (objc == 4) { 2197 Tcl_WrongNumArgs(interp, 2, objv, 2198 "window ?-default? image1 ?image2 ...?"); 2199 return TCL_ERROR; 2200 } 2201 } 2202 2203 /* 2204 * Iterate over all images to retrieve their sizes, in order to allocate a 2205 * buffer large enough to hold all images. 2206 */ 2207 2208 for (i = 3 + isDefault; i < objc; i++) { 2209 photo = Tk_FindPhoto(interp, Tcl_GetString(objv[i])); 2210 if (photo == NULL) { 2211 Tcl_AppendResult(interp, "can't use \"", Tcl_GetString(objv[i]), 2212 "\" as iconphoto: not a photo image", NULL); 2213 return TCL_ERROR; 2214 } 2215 Tk_PhotoGetSize(photo, &width, &height); 2216 } 2217 2218 /* 2219 * TODO: This requires implementation for OS X, but we silently return for 2220 * now. 2221 */ 2222 2223 return TCL_OK; 2224} 2225 2226/* 2227 *---------------------------------------------------------------------- 2228 * 2229 * WmIconpositionCmd -- 2230 * 2231 * This procedure is invoked to process the "wm iconposition" Tcl 2232 * command. See the user documentation for details on what it does. 2233 * 2234 * Results: 2235 * A standard Tcl result. 2236 * 2237 * Side effects: 2238 * See the user documentation. 2239 * 2240 *---------------------------------------------------------------------- 2241 */ 2242 2243static int 2244WmIconpositionCmd( 2245 Tk_Window tkwin, /* Main window of the application. */ 2246 TkWindow *winPtr, /* Toplevel to work with */ 2247 Tcl_Interp *interp, /* Current interpreter. */ 2248 int objc, /* Number of arguments. */ 2249 Tcl_Obj *const objv[]) /* Argument objects. */ 2250{ 2251 register WmInfo *wmPtr = winPtr->wmInfoPtr; 2252 int x, y; 2253 2254 if ((objc != 3) && (objc != 5)) { 2255 Tcl_WrongNumArgs(interp, 2, objv, "window ?x y?"); 2256 return TCL_ERROR; 2257 } 2258 if (objc == 3) { 2259 if (wmPtr->hints.flags & IconPositionHint) { 2260 char buf[TCL_INTEGER_SPACE * 2]; 2261 2262 sprintf(buf, "%d %d", wmPtr->hints.icon_x, 2263 wmPtr->hints.icon_y); 2264 Tcl_SetResult(interp, buf, TCL_VOLATILE); 2265 } 2266 return TCL_OK; 2267 } 2268 if (*Tcl_GetString(objv[3]) == '\0') { 2269 wmPtr->hints.flags &= ~IconPositionHint; 2270 } else { 2271 if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) 2272 || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)){ 2273 return TCL_ERROR; 2274 } 2275 wmPtr->hints.icon_x = x; 2276 wmPtr->hints.icon_y = y; 2277 wmPtr->hints.flags |= IconPositionHint; 2278 } 2279 return TCL_OK; 2280} 2281 2282/* 2283 *---------------------------------------------------------------------- 2284 * 2285 * WmIconwindowCmd -- 2286 * 2287 * This procedure is invoked to process the "wm iconwindow" Tcl command. 2288 * See the user documentation for details on what it does. 2289 * 2290 * Results: 2291 * A standard Tcl result. 2292 * 2293 * Side effects: 2294 * See the user documentation. 2295 * 2296 *---------------------------------------------------------------------- 2297 */ 2298 2299static int 2300WmIconwindowCmd( 2301 Tk_Window tkwin, /* Main window of the application. */ 2302 TkWindow *winPtr, /* Toplevel to work with */ 2303 Tcl_Interp *interp, /* Current interpreter. */ 2304 int objc, /* Number of arguments. */ 2305 Tcl_Obj *const objv[]) /* Argument objects. */ 2306{ 2307 register WmInfo *wmPtr = winPtr->wmInfoPtr; 2308 Tk_Window tkwin2; 2309 WmInfo *wmPtr2; 2310 2311 if ((objc != 3) && (objc != 4)) { 2312 Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?"); 2313 return TCL_ERROR; 2314 } 2315 if (objc == 3) { 2316 if (wmPtr->icon != NULL) { 2317 Tcl_SetResult(interp, Tk_PathName(wmPtr->icon), TCL_STATIC); 2318 } 2319 return TCL_OK; 2320 } 2321 if (*Tcl_GetString(objv[3]) == '\0') { 2322 wmPtr->hints.flags &= ~IconWindowHint; 2323 if (wmPtr->icon != NULL) { 2324 wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; 2325 wmPtr2->iconFor = NULL; 2326 wmPtr2->hints.initial_state = WithdrawnState; 2327 } 2328 wmPtr->icon = NULL; 2329 } else { 2330 if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) { 2331 return TCL_ERROR; 2332 } 2333 if (!Tk_IsTopLevel(tkwin2)) { 2334 Tcl_AppendResult(interp, "can't use ", Tcl_GetString(objv[3]), 2335 " as icon window: not at top level", NULL); 2336 return TCL_ERROR; 2337 } 2338 wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr; 2339 if (wmPtr2->iconFor != NULL) { 2340 Tcl_AppendResult(interp, Tcl_GetString(objv[3]), 2341 " is already an icon for ", 2342 Tk_PathName(wmPtr2->iconFor), NULL); 2343 return TCL_ERROR; 2344 } 2345 if (wmPtr->icon != NULL) { 2346 WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; 2347 wmPtr3->iconFor = NULL; 2348 } 2349 Tk_MakeWindowExist(tkwin2); 2350 wmPtr->hints.icon_window = Tk_WindowId(tkwin2); 2351 wmPtr->hints.flags |= IconWindowHint; 2352 wmPtr->icon = tkwin2; 2353 wmPtr2->iconFor = (Tk_Window) winPtr; 2354 if (!(wmPtr2->flags & WM_NEVER_MAPPED)) { 2355 /* 2356 * Don't have iconwindows on the Mac. We just withdraw. 2357 */ 2358 2359 Tk_UnmapWindow(tkwin2); 2360 } 2361 } 2362 return TCL_OK; 2363} 2364 2365/* 2366 *---------------------------------------------------------------------- 2367 * 2368 * WmManageCmd -- 2369 * 2370 * This procedure is invoked to process the "wm manage" Tcl command. See 2371 * the user documentation for details on what it does. 2372 * 2373 * Results: 2374 * A standard Tcl result. 2375 * 2376 * Side effects: 2377 * See the user documentation. 2378 * 2379 *---------------------------------------------------------------------- 2380 */ 2381 2382static int 2383WmManageCmd( 2384 Tk_Window tkwin, /* Main window of the application. */ 2385 TkWindow *winPtr, /* Toplevel or Frame to work with */ 2386 Tcl_Interp *interp, /* Current interpreter. */ 2387 int objc, /* Number of arguments. */ 2388 Tcl_Obj *const objv[]) /* Argument objects. */ 2389{ 2390#if 1 2391 Tcl_AppendResult(interp, "wm manage is not yet supported", NULL); 2392 return TCL_ERROR; 2393#else 2394 register Tk_Window frameWin = (Tk_Window)winPtr; 2395 register WmInfo *wmPtr = winPtr->wmInfoPtr; 2396 char *oldClass = (char*)Tk_Class(frameWin); 2397 2398 if (!Tk_IsTopLevel(frameWin)) { 2399 MacDrawable *macWin = (MacDrawable *) winPtr->window; 2400 2401 if (!Tk_IsManageable(frameWin)) { 2402 Tcl_AppendResult(interp, "window \"", 2403 Tk_PathName(frameWin), "\" is not manageable: must be " 2404 "a frame, labelframe or toplevel", NULL); 2405 return TCL_ERROR; 2406 } 2407 TkFocusSplit(winPtr); 2408 Tk_UnmapWindow(frameWin); 2409 if (wmPtr == NULL) { 2410 TkWmNewWindow(winPtr); 2411 if (winPtr->window == None) { 2412 Tk_MakeWindowExist((Tk_Window) winPtr); 2413 macWin = (MacDrawable *) winPtr->window; 2414 } 2415 TkWmMapWindow(winPtr); 2416 Tk_UnmapWindow(frameWin); 2417 } 2418 wmPtr = winPtr->wmInfoPtr; 2419 winPtr->flags &= ~TK_MAPPED; 2420 macWin->grafPtr = NULL; 2421 macWin->toplevel = macWin; 2422 RemapWindows(winPtr, macWin); 2423 winPtr->flags |= 2424 (TK_TOP_HIERARCHY|TK_TOP_LEVEL|TK_HAS_WRAPPER|TK_WIN_MANAGED); 2425 TkMapTopFrame(frameWin); 2426 } else if (Tk_IsTopLevel(frameWin)) { 2427 /* Already managed by wm - ignore it */ 2428 } 2429 return TCL_OK; 2430#endif 2431} 2432 2433/* 2434 *---------------------------------------------------------------------- 2435 * 2436 * WmMaxsizeCmd -- 2437 * 2438 * This procedure is invoked to process the "wm maxsize" Tcl command. See 2439 * the user documentation for details on what it does. 2440 * 2441 * Results: 2442 * A standard Tcl result. 2443 * 2444 * Side effects: 2445 * See the user documentation. 2446 * 2447 *---------------------------------------------------------------------- 2448 */ 2449 2450static int 2451WmMaxsizeCmd( 2452 Tk_Window tkwin, /* Main window of the application. */ 2453 TkWindow *winPtr, /* Toplevel to work with */ 2454 Tcl_Interp *interp, /* Current interpreter. */ 2455 int objc, /* Number of arguments. */ 2456 Tcl_Obj *const objv[]) /* Argument objects. */ 2457{ 2458 register WmInfo *wmPtr = winPtr->wmInfoPtr; 2459 int width, height; 2460 2461 if ((objc != 3) && (objc != 5)) { 2462 Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?"); 2463 return TCL_ERROR; 2464 } 2465 if (objc == 3) { 2466 char buf[TCL_INTEGER_SPACE * 2]; 2467 2468 GetMaxSize(winPtr, &width, &height); 2469 sprintf(buf, "%d %d", width, height); 2470 Tcl_SetResult(interp, buf, TCL_VOLATILE); 2471 return TCL_OK; 2472 } 2473 if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK) 2474 || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) { 2475 return TCL_ERROR; 2476 } 2477 wmPtr->maxWidth = width; 2478 wmPtr->maxHeight = height; 2479 wmPtr->flags |= WM_UPDATE_SIZE_HINTS; 2480 WmUpdateGeom(wmPtr, winPtr); 2481 return TCL_OK; 2482} 2483 2484/* 2485 *---------------------------------------------------------------------- 2486 * 2487 * WmMinsizeCmd -- 2488 * 2489 * This procedure is invoked to process the "wm minsize" Tcl command. See 2490 * the user documentation for details on what it does. 2491 * 2492 * Results: 2493 * A standard Tcl result. 2494 * 2495 * Side effects: 2496 * See the user documentation. 2497 * 2498 *---------------------------------------------------------------------- 2499 */ 2500 2501static int 2502WmMinsizeCmd( 2503 Tk_Window tkwin, /* Main window of the application. */ 2504 TkWindow *winPtr, /* Toplevel to work with */ 2505 Tcl_Interp *interp, /* Current interpreter. */ 2506 int objc, /* Number of arguments. */ 2507 Tcl_Obj *const objv[]) /* Argument objects. */ 2508{ 2509 register WmInfo *wmPtr = winPtr->wmInfoPtr; 2510 int width, height; 2511 2512 if ((objc != 3) && (objc != 5)) { 2513 Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?"); 2514 return TCL_ERROR; 2515 } 2516 if (objc == 3) { 2517 char buf[TCL_INTEGER_SPACE * 2]; 2518 2519 GetMinSize(winPtr, &width, &height); 2520 sprintf(buf, "%d %d", width, height); 2521 Tcl_SetResult(interp, buf, TCL_VOLATILE); 2522 return TCL_OK; 2523 } 2524 if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK) 2525 || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) { 2526 return TCL_ERROR; 2527 } 2528 wmPtr->minWidth = width; 2529 wmPtr->minHeight = height; 2530 wmPtr->flags |= WM_UPDATE_SIZE_HINTS; 2531 WmUpdateGeom(wmPtr, winPtr); 2532 return TCL_OK; 2533} 2534 2535/* 2536 *---------------------------------------------------------------------- 2537 * 2538 * WmOverrideredirectCmd -- 2539 * 2540 * This procedure is invoked to process the "wm overrideredirect" Tcl 2541 * command. See the user documentation for details on what it does. 2542 * 2543 * Results: 2544 * A standard Tcl result. 2545 * 2546 * Side effects: 2547 * See the user documentation. 2548 * 2549 *---------------------------------------------------------------------- 2550 */ 2551 2552static int 2553WmOverrideredirectCmd( 2554 Tk_Window tkwin, /* Main window of the application. */ 2555 TkWindow *winPtr, /* Toplevel to work with */ 2556 Tcl_Interp *interp, /* Current interpreter. */ 2557 int objc, /* Number of arguments. */ 2558 Tcl_Obj *const objv[]) /* Argument objects. */ 2559{ 2560 int boolean; 2561 XSetWindowAttributes atts; 2562 2563 if ((objc != 3) && (objc != 4)) { 2564 Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?"); 2565 return TCL_ERROR; 2566 } 2567 if (objc == 3) { 2568 Tcl_SetObjResult(interp, Tcl_NewBooleanObj( 2569 Tk_Attributes((Tk_Window) winPtr)->override_redirect)); 2570 return TCL_OK; 2571 } 2572 if (Tcl_GetBooleanFromObj(interp, objv[3], &boolean) != TCL_OK) { 2573 return TCL_ERROR; 2574 } 2575 atts.override_redirect = (boolean) ? True : False; 2576 Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, &atts); 2577 ApplyMasterOverrideChanges(winPtr, NULL); 2578 return TCL_OK; 2579} 2580 2581/* 2582 *---------------------------------------------------------------------- 2583 * 2584 * WmPositionfromCmd -- 2585 * 2586 * This procedure is invoked to process the "wm positionfrom" Tcl 2587 * command. See the user documentation for details on what it does. 2588 * 2589 * Results: 2590 * A standard Tcl result. 2591 * 2592 * Side effects: 2593 * See the user documentation. 2594 * 2595 *---------------------------------------------------------------------- 2596 */ 2597 2598static int 2599WmPositionfromCmd( 2600 Tk_Window tkwin, /* Main window of the application. */ 2601 TkWindow *winPtr, /* Toplevel to work with */ 2602 Tcl_Interp *interp, /* Current interpreter. */ 2603 int objc, /* Number of arguments. */ 2604 Tcl_Obj *const objv[]) /* Argument objects. */ 2605{ 2606 register WmInfo *wmPtr = winPtr->wmInfoPtr; 2607 static const char *optionStrings[] = { 2608 "program", "user", NULL }; 2609 enum options { 2610 OPT_PROGRAM, OPT_USER }; 2611 int index; 2612 2613 if ((objc != 3) && (objc != 4)) { 2614 Tcl_WrongNumArgs(interp, 2, objv, "window ?user/program?"); 2615 return TCL_ERROR; 2616 } 2617 if (objc == 3) { 2618 if (wmPtr->sizeHintsFlags & USPosition) { 2619 Tcl_SetResult(interp, "user", TCL_STATIC); 2620 } else if (wmPtr->sizeHintsFlags & PPosition) { 2621 Tcl_SetResult(interp, "program", TCL_STATIC); 2622 } 2623 return TCL_OK; 2624 } 2625 if (*Tcl_GetString(objv[3]) == '\0') { 2626 wmPtr->sizeHintsFlags &= ~(USPosition|PPosition); 2627 } else { 2628 if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, 2629 &index) != TCL_OK) { 2630 return TCL_ERROR; 2631 } 2632 if (index == OPT_USER) { 2633 wmPtr->sizeHintsFlags &= ~PPosition; 2634 wmPtr->sizeHintsFlags |= USPosition; 2635 } else { 2636 wmPtr->sizeHintsFlags &= ~USPosition; 2637 wmPtr->sizeHintsFlags |= PPosition; 2638 } 2639 } 2640 wmPtr->flags |= WM_UPDATE_SIZE_HINTS; 2641 WmUpdateGeom(wmPtr, winPtr); 2642 return TCL_OK; 2643} 2644 2645/* 2646 *---------------------------------------------------------------------- 2647 * 2648 * WmProtocolCmd -- 2649 * 2650 * This procedure is invoked to process the "wm protocol" Tcl command. 2651 * See the user documentation for details on what it does. 2652 * 2653 * Results: 2654 * A standard Tcl result. 2655 * 2656 * Side effects: 2657 * See the user documentation. 2658 * 2659 *---------------------------------------------------------------------- 2660 */ 2661 2662static int 2663WmProtocolCmd( 2664 Tk_Window tkwin, /* Main window of the application. */ 2665 TkWindow *winPtr, /* Toplevel to work with */ 2666 Tcl_Interp *interp, /* Current interpreter. */ 2667 int objc, /* Number of arguments. */ 2668 Tcl_Obj *const objv[]) /* Argument objects. */ 2669{ 2670 register WmInfo *wmPtr = winPtr->wmInfoPtr; 2671 register ProtocolHandler *protPtr, *prevPtr; 2672 Atom protocol; 2673 char *cmd; 2674 int cmdLength; 2675 2676 if ((objc < 3) || (objc > 5)) { 2677 Tcl_WrongNumArgs(interp, 2, objv, "window ?name? ?command?"); 2678 return TCL_ERROR; 2679 } 2680 if (objc == 3) { 2681 /* 2682 * Return a list of all defined protocols for the window. 2683 */ 2684 2685 for (protPtr = wmPtr->protPtr; protPtr != NULL; 2686 protPtr = protPtr->nextPtr) { 2687 Tcl_AppendElement(interp, 2688 Tk_GetAtomName((Tk_Window) winPtr, protPtr->protocol)); 2689 } 2690 return TCL_OK; 2691 } 2692 protocol = Tk_InternAtom((Tk_Window) winPtr, Tcl_GetString(objv[3])); 2693 if (objc == 4) { 2694 /* 2695 * Return the command to handle a given protocol. 2696 */ 2697 2698 for (protPtr = wmPtr->protPtr; protPtr != NULL; 2699 protPtr = protPtr->nextPtr) { 2700 if (protPtr->protocol == protocol) { 2701 Tcl_SetResult(interp, protPtr->command, TCL_STATIC); 2702 return TCL_OK; 2703 } 2704 } 2705 return TCL_OK; 2706 } 2707 2708 /* 2709 * Delete any current protocol handler, then create a new one with the 2710 * specified command, unless the command is empty. 2711 */ 2712 2713 for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL; 2714 prevPtr = protPtr, protPtr = protPtr->nextPtr) { 2715 if (protPtr->protocol == protocol) { 2716 if (prevPtr == NULL) { 2717 wmPtr->protPtr = protPtr->nextPtr; 2718 } else { 2719 prevPtr->nextPtr = protPtr->nextPtr; 2720 } 2721 Tcl_EventuallyFree(protPtr, TCL_DYNAMIC); 2722 break; 2723 } 2724 } 2725 cmd = Tcl_GetStringFromObj(objv[4], &cmdLength); 2726 if (cmdLength > 0) { 2727 protPtr = (ProtocolHandler *) ckalloc(HANDLER_SIZE(cmdLength)); 2728 protPtr->protocol = protocol; 2729 protPtr->nextPtr = wmPtr->protPtr; 2730 wmPtr->protPtr = protPtr; 2731 protPtr->interp = interp; 2732 strcpy(protPtr->command, cmd); 2733 } 2734 return TCL_OK; 2735} 2736 2737/* 2738 *---------------------------------------------------------------------- 2739 * 2740 * WmResizableCmd -- 2741 * 2742 * This procedure is invoked to process the "wm resizable" Tcl command. 2743 * See the user documentation for details on what it does. 2744 * 2745 * Results: 2746 * A standard Tcl result. 2747 * 2748 * Side effects: 2749 * See the user documentation. 2750 * 2751 *---------------------------------------------------------------------- 2752 */ 2753 2754static int 2755WmResizableCmd( 2756 Tk_Window tkwin, /* Main window of the application. */ 2757 TkWindow *winPtr, /* Toplevel to work with */ 2758 Tcl_Interp *interp, /* Current interpreter. */ 2759 int objc, /* Number of arguments. */ 2760 Tcl_Obj *const objv[]) /* Argument objects. */ 2761{ 2762 register WmInfo *wmPtr = winPtr->wmInfoPtr; 2763 int width, height; 2764 UInt64 oldAttributes = wmPtr->attributes; 2765 int oldFlags = wmPtr->flags; 2766 2767 if ((objc != 3) && (objc != 5)) { 2768 Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?"); 2769 return TCL_ERROR; 2770 } 2771 if (objc == 3) { 2772 char buf[TCL_INTEGER_SPACE * 2]; 2773 2774 sprintf(buf, "%d %d", 2775 (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) ? 0 : 1, 2776 (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) ? 0 : 1); 2777 Tcl_SetResult(interp, buf, TCL_VOLATILE); 2778 return TCL_OK; 2779 } 2780 if ((Tcl_GetBooleanFromObj(interp, objv[3], &width) != TCL_OK) 2781 || (Tcl_GetBooleanFromObj(interp, objv[4], &height) != TCL_OK)) { 2782 return TCL_ERROR; 2783 } 2784 if (width) { 2785 wmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE; 2786 wmPtr->attributes |= kWindowHorizontalZoomAttribute; 2787 } else { 2788 wmPtr->flags |= WM_WIDTH_NOT_RESIZABLE; 2789 wmPtr->attributes &= ~kWindowHorizontalZoomAttribute; 2790 } 2791 if (height) { 2792 wmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE; 2793 wmPtr->attributes |= kWindowVerticalZoomAttribute; 2794 } else { 2795 wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE; 2796 wmPtr->attributes &= ~kWindowVerticalZoomAttribute; 2797 } 2798 if (width || height) { 2799 wmPtr->attributes |= kWindowResizableAttribute; 2800 } else { 2801 wmPtr->attributes &= ~kWindowResizableAttribute; 2802 } 2803 wmPtr->flags |= WM_UPDATE_SIZE_HINTS; 2804 if (wmPtr->scrollWinPtr != NULL) { 2805 TkScrollbarEventuallyRedraw((TkScrollbar *) 2806 wmPtr->scrollWinPtr->instanceData); 2807 } 2808 WmUpdateGeom(wmPtr, winPtr); 2809 ApplyWindowAttributeFlagChanges(winPtr, NULL, oldAttributes, oldFlags, 1,0); 2810 return TCL_OK; 2811} 2812 2813/* 2814 *---------------------------------------------------------------------- 2815 * 2816 * WmSizefromCmd -- 2817 * 2818 * This procedure is invoked to process the "wm sizefrom" Tcl command. 2819 * See the user documentation for details on what it does. 2820 * 2821 * Results: 2822 * A standard Tcl result. 2823 * 2824 * Side effects: 2825 * See the user documentation. 2826 * 2827 *---------------------------------------------------------------------- 2828 */ 2829 2830static int 2831WmSizefromCmd( 2832 Tk_Window tkwin, /* Main window of the application. */ 2833 TkWindow *winPtr, /* Toplevel to work with */ 2834 Tcl_Interp *interp, /* Current interpreter. */ 2835 int objc, /* Number of arguments. */ 2836 Tcl_Obj *const objv[]) /* Argument objects. */ 2837{ 2838 register WmInfo *wmPtr = winPtr->wmInfoPtr; 2839 static const char *optionStrings[] = { 2840 "program", "user", NULL }; 2841 enum options { 2842 OPT_PROGRAM, OPT_USER }; 2843 int index; 2844 2845 if ((objc != 3) && (objc != 4)) { 2846 Tcl_WrongNumArgs(interp, 2, objv, "window ?user|program?"); 2847 return TCL_ERROR; 2848 } 2849 if (objc == 3) { 2850 if (wmPtr->sizeHintsFlags & USSize) { 2851 Tcl_SetResult(interp, "user", TCL_STATIC); 2852 } else if (wmPtr->sizeHintsFlags & PSize) { 2853 Tcl_SetResult(interp, "program", TCL_STATIC); 2854 } 2855 return TCL_OK; 2856 } 2857 2858 if (*Tcl_GetString(objv[3]) == '\0') { 2859 wmPtr->sizeHintsFlags &= ~(USSize|PSize); 2860 } else { 2861 if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, 2862 &index) != TCL_OK) { 2863 return TCL_ERROR; 2864 } 2865 if (index == OPT_USER) { 2866 wmPtr->sizeHintsFlags &= ~PSize; 2867 wmPtr->sizeHintsFlags |= USSize; 2868 } else { /* OPT_PROGRAM */ 2869 wmPtr->sizeHintsFlags &= ~USSize; 2870 wmPtr->sizeHintsFlags |= PSize; 2871 } 2872 } 2873 wmPtr->flags |= WM_UPDATE_SIZE_HINTS; 2874 WmUpdateGeom(wmPtr, winPtr); 2875 return TCL_OK; 2876} 2877 2878/* 2879 *---------------------------------------------------------------------- 2880 * 2881 * WmStackorderCmd -- 2882 * 2883 * This procedure is invoked to process the "wm stackorder" Tcl command. 2884 * See the user documentation for details on what it does. 2885 * 2886 * Results: 2887 * A standard Tcl result. 2888 * 2889 * Side effects: 2890 * See the user documentation. 2891 * 2892 *---------------------------------------------------------------------- 2893 */ 2894 2895static int 2896WmStackorderCmd( 2897 Tk_Window tkwin, /* Main window of the application. */ 2898 TkWindow *winPtr, /* Toplevel to work with */ 2899 Tcl_Interp *interp, /* Current interpreter. */ 2900 int objc, /* Number of arguments. */ 2901 Tcl_Obj *const objv[]) /* Argument objects. */ 2902{ 2903 TkWindow **windows, **window_ptr; 2904 static const char *optionStrings[] = { 2905 "isabove", "isbelow", NULL }; 2906 enum options { 2907 OPT_ISABOVE, OPT_ISBELOW }; 2908 int index; 2909 2910 if ((objc != 3) && (objc != 5)) { 2911 Tcl_WrongNumArgs(interp, 2, objv, "window ?isabove|isbelow window?"); 2912 return TCL_ERROR; 2913 } 2914 2915 if (objc == 3) { 2916 windows = TkWmStackorderToplevel(winPtr); 2917 if (windows == NULL) { 2918 Tcl_Panic("TkWmStackorderToplevel failed"); 2919 } 2920 2921 for (window_ptr = windows; *window_ptr ; window_ptr++) { 2922 Tcl_AppendElement(interp, (*window_ptr)->pathName); 2923 } 2924 ckfree((char *) windows); 2925 return TCL_OK; 2926 } else { 2927 TkWindow *winPtr2; 2928 int index1=-1, index2=-1, result; 2929 2930 if (TkGetWindowFromObj(interp, tkwin, objv[4], (Tk_Window *) &winPtr2) 2931 != TCL_OK) { 2932 return TCL_ERROR; 2933 } 2934 2935 if (!Tk_IsTopLevel(winPtr2)) { 2936 Tcl_AppendResult(interp, "window \"", winPtr2->pathName, 2937 "\" isn't a top-level window", NULL); 2938 return TCL_ERROR; 2939 } 2940 2941 if (!Tk_IsMapped(winPtr)) { 2942 Tcl_AppendResult(interp, "window \"", winPtr->pathName, 2943 "\" isn't mapped", NULL); 2944 return TCL_ERROR; 2945 } 2946 2947 if (!Tk_IsMapped(winPtr2)) { 2948 Tcl_AppendResult(interp, "window \"", winPtr2->pathName, 2949 "\" isn't mapped", NULL); 2950 return TCL_ERROR; 2951 } 2952 2953 /* 2954 * Lookup stacking order of all toplevels that are children of "." and 2955 * find the position of winPtr and winPtr2 in the stacking order. 2956 */ 2957 2958 windows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr); 2959 if (windows == NULL) { 2960 Tcl_AppendResult(interp, "TkWmStackorderToplevel failed", NULL); 2961 return TCL_ERROR; 2962 } 2963 2964 for (window_ptr = windows; *window_ptr ; window_ptr++) { 2965 if (*window_ptr == winPtr) { 2966 index1 = (window_ptr - windows); 2967 } 2968 if (*window_ptr == winPtr2) { 2969 index2 = (window_ptr - windows); 2970 } 2971 } 2972 if (index1 == -1) { 2973 Tcl_Panic("winPtr window not found"); 2974 } 2975 if (index2 == -1) { 2976 Tcl_Panic("winPtr2 window not found"); 2977 } 2978 2979 ckfree((char *) windows); 2980 2981 if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, 2982 &index) != TCL_OK) { 2983 return TCL_ERROR; 2984 } 2985 if (index == OPT_ISABOVE) { 2986 result = index1 > index2; 2987 } else { /* OPT_ISBELOW */ 2988 result = index1 < index2; 2989 } 2990 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); 2991 return TCL_OK; 2992 } 2993 return TCL_OK; 2994} 2995 2996/* 2997 *---------------------------------------------------------------------- 2998 * 2999 * WmStateCmd -- 3000 * 3001 * This procedure is invoked to process the "wm state" Tcl command. See 3002 * the user documentation for details on what it does. 3003 * 3004 * Results: 3005 * A standard Tcl result. 3006 * 3007 * Side effects: 3008 * See the user documentation. 3009 * 3010 *---------------------------------------------------------------------- 3011 */ 3012 3013static int 3014WmStateCmd( 3015 Tk_Window tkwin, /* Main window of the application. */ 3016 TkWindow *winPtr, /* Toplevel to work with */ 3017 Tcl_Interp *interp, /* Current interpreter. */ 3018 int objc, /* Number of arguments. */ 3019 Tcl_Obj *const objv[]) /* Argument objects. */ 3020{ 3021 register WmInfo *wmPtr = winPtr->wmInfoPtr; 3022 static const char *optionStrings[] = { 3023 "normal", "iconic", "withdrawn", "zoomed", NULL }; 3024 enum options { 3025 OPT_NORMAL, OPT_ICONIC, OPT_WITHDRAWN, OPT_ZOOMED }; 3026 int index; 3027 3028 if ((objc < 3) || (objc > 4)) { 3029 Tcl_WrongNumArgs(interp, 2, objv, "window ?state?"); 3030 return TCL_ERROR; 3031 } 3032 if (objc == 4) { 3033 if (wmPtr->iconFor != NULL) { 3034 Tcl_AppendResult(interp, "can't change state of ", 3035 Tcl_GetString(objv[2]), ": it is an icon for ", 3036 Tk_PathName(wmPtr->iconFor), NULL); 3037 return TCL_ERROR; 3038 } 3039 if (winPtr->flags & TK_EMBEDDED) { 3040 Tcl_AppendResult(interp, "can't change state of ", 3041 winPtr->pathName, ": it is an embedded window", NULL); 3042 return TCL_ERROR; 3043 } 3044 3045 if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, 3046 &index) != TCL_OK) { 3047 return TCL_ERROR; 3048 } 3049 3050 if (index == OPT_NORMAL) { 3051 TkpWmSetState(winPtr, NormalState); 3052 3053 /* 3054 * This varies from 'wm deiconify' because it does not force the 3055 * window to be raised and receive focus 3056 */ 3057 } else if (index == OPT_ICONIC) { 3058 if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) { 3059 Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName, 3060 "\": override-redirect flag is set", NULL); 3061 return TCL_ERROR; 3062 } 3063 if (wmPtr->master != None) { 3064 Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName, 3065 "\": it is a transient", NULL); 3066 return TCL_ERROR; 3067 } 3068 TkpWmSetState(winPtr, IconicState); 3069 } else if (index == OPT_WITHDRAWN) { 3070 TkpWmSetState(winPtr, WithdrawnState); 3071 } else { /* OPT_ZOOMED */ 3072 TkpWmSetState(winPtr, ZoomState); 3073 } 3074 } else if (wmPtr->iconFor != NULL) { 3075 Tcl_SetResult(interp, "icon", TCL_STATIC); 3076 } else { 3077 if (wmPtr->hints.initial_state == NormalState || 3078 wmPtr->hints.initial_state == ZoomState) { 3079 wmPtr->hints.initial_state = (TkMacOSXIsWindowZoomed(winPtr) ? 3080 ZoomState : NormalState); 3081 } 3082 switch (wmPtr->hints.initial_state) { 3083 case NormalState: 3084 Tcl_SetResult(interp, "normal", TCL_STATIC); 3085 break; 3086 case IconicState: 3087 Tcl_SetResult(interp, "iconic", TCL_STATIC); 3088 break; 3089 case WithdrawnState: 3090 Tcl_SetResult(interp, "withdrawn", TCL_STATIC); 3091 break; 3092 case ZoomState: 3093 Tcl_SetResult(interp, "zoomed", TCL_STATIC); 3094 break; 3095 } 3096 } 3097 return TCL_OK; 3098} 3099 3100/* 3101 *---------------------------------------------------------------------- 3102 * 3103 * WmTitleCmd -- 3104 * 3105 * This procedure is invoked to process the "wm title" Tcl command. See 3106 * the user documentation for details on what it does. 3107 * 3108 * Results: 3109 * A standard Tcl result. 3110 * 3111 * Side effects: 3112 * See the user documentation. 3113 * 3114 *---------------------------------------------------------------------- 3115 */ 3116 3117static int 3118WmTitleCmd( 3119 Tk_Window tkwin, /* Main window of the application. */ 3120 TkWindow *winPtr, /* Toplevel to work with */ 3121 Tcl_Interp *interp, /* Current interpreter. */ 3122 int objc, /* Number of arguments. */ 3123 Tcl_Obj *const objv[]) /* Argument objects. */ 3124{ 3125 register WmInfo *wmPtr = winPtr->wmInfoPtr; 3126 char *argv3; 3127 int length; 3128 3129 if (objc > 4) { 3130 Tcl_WrongNumArgs(interp, 2, objv, "window ?newTitle?"); 3131 return TCL_ERROR; 3132 } 3133 if (objc == 3) { 3134 Tcl_SetResult(interp, (char *)((wmPtr->titleUid != NULL) ? 3135 wmPtr->titleUid : winPtr->nameUid), TCL_STATIC); 3136 return TCL_OK; 3137 } 3138 argv3 = Tcl_GetStringFromObj(objv[3], &length); 3139 wmPtr->titleUid = Tk_GetUid(argv3); 3140 if (!(wmPtr->flags & WM_NEVER_MAPPED) && !Tk_IsEmbedded(winPtr)) { 3141 TkSetWMName(winPtr, wmPtr->titleUid); 3142 } 3143 return TCL_OK; 3144} 3145 3146/* 3147 *---------------------------------------------------------------------- 3148 * 3149 * WmTransientCmd -- 3150 * 3151 * This procedure is invoked to process the "wm transient" Tcl command. 3152 * See the user documentation for details on what it does. 3153 * 3154 * Results: 3155 * A standard Tcl result. 3156 * 3157 * Side effects: 3158 * See the user documentation. 3159 * 3160 *---------------------------------------------------------------------- 3161 */ 3162 3163static int 3164WmTransientCmd( 3165 Tk_Window tkwin, /* Main window of the application. */ 3166 TkWindow *winPtr, /* Toplevel to work with */ 3167 Tcl_Interp *interp, /* Current interpreter. */ 3168 int objc, /* Number of arguments. */ 3169 Tcl_Obj *const objv[]) /* Argument objects. */ 3170{ 3171 register WmInfo *wmPtr = winPtr->wmInfoPtr; 3172 Tk_Window master; 3173 WmInfo *wmPtr2; 3174 char *masterWindowName; 3175 int length; 3176 3177 if ((objc != 3) && (objc != 4)) { 3178 Tcl_WrongNumArgs(interp, 2, objv, "window ?master?"); 3179 return TCL_ERROR; 3180 } 3181 if (objc == 3) { 3182 if (wmPtr->master != None) { 3183 Tcl_SetResult(interp, wmPtr->masterWindowName, TCL_STATIC); 3184 } 3185 return TCL_OK; 3186 } 3187 if (Tcl_GetString(objv[3])[0] == '\0') { 3188 wmPtr->master = None; 3189 if (wmPtr->masterWindowName != NULL) { 3190 ckfree(wmPtr->masterWindowName); 3191 } 3192 wmPtr->masterWindowName = NULL; 3193 } else { 3194 if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) { 3195 return TCL_ERROR; 3196 } 3197 Tk_MakeWindowExist(master); 3198 3199 if (wmPtr->iconFor != NULL) { 3200 Tcl_AppendResult(interp, "can't make \"", Tcl_GetString(objv[2]), 3201 "\" a transient: it is an icon for ", 3202 Tk_PathName(wmPtr->iconFor), NULL); 3203 return TCL_ERROR; 3204 } 3205 3206 wmPtr2 = ((TkWindow *) master)->wmInfoPtr; 3207 3208 /* Under some circumstances, wmPtr2 is NULL here */ 3209 if (wmPtr2 != NULL && wmPtr2->iconFor != NULL) { 3210 Tcl_AppendResult(interp, "can't make \"", Tcl_GetString(objv[3]), 3211 "\" a master: it is an icon for ", 3212 Tk_PathName(wmPtr2->iconFor), NULL); 3213 return TCL_ERROR; 3214 } 3215 3216 if ((TkWindow *) master == winPtr) { 3217 Tcl_AppendResult(interp, "can't make \"", Tk_PathName(winPtr), 3218 "\" its own master", NULL); 3219 return TCL_ERROR; 3220 } 3221 3222 wmPtr->master = Tk_WindowId(master); 3223 masterWindowName = Tcl_GetStringFromObj(objv[3], &length); 3224 if (wmPtr->masterWindowName != NULL) { 3225 ckfree(wmPtr->masterWindowName); 3226 } 3227 wmPtr->masterWindowName = ckalloc((unsigned) length+1); 3228 strcpy(wmPtr->masterWindowName, masterWindowName); 3229 } 3230 ApplyMasterOverrideChanges(winPtr, NULL); 3231 return TCL_OK; 3232} 3233 3234/* 3235 *---------------------------------------------------------------------- 3236 * 3237 * WmWithdrawCmd -- 3238 * 3239 * This procedure is invoked to process the "wm withdraw" Tcl command. 3240 * See the user documentation for details on what it does. 3241 * 3242 * Results: 3243 * A standard Tcl result. 3244 * 3245 * Side effects: 3246 * See the user documentation. 3247 * 3248 *---------------------------------------------------------------------- 3249 */ 3250 3251static int 3252WmWithdrawCmd( 3253 Tk_Window tkwin, /* Main window of the application. */ 3254 TkWindow *winPtr, /* Toplevel to work with */ 3255 Tcl_Interp *interp, /* Current interpreter. */ 3256 int objc, /* Number of arguments. */ 3257 Tcl_Obj *const objv[]) /* Argument objects. */ 3258{ 3259 register WmInfo *wmPtr = winPtr->wmInfoPtr; 3260 3261 if (objc != 3) { 3262 Tcl_WrongNumArgs(interp, 2, objv, "window"); 3263 return TCL_ERROR; 3264 } 3265 if (wmPtr->iconFor != NULL) { 3266 Tcl_AppendResult(interp, "can't withdraw ", Tcl_GetString(objv[2]), 3267 ": it is an icon for ", Tk_PathName(wmPtr->iconFor), NULL); 3268 return TCL_ERROR; 3269 } 3270 TkpWmSetState(winPtr, WithdrawnState); 3271 return TCL_OK; 3272} 3273 3274/* 3275 * Invoked by those wm subcommands that affect geometry. 3276 * Schedules a geometry update. 3277 */ 3278 3279static void 3280WmUpdateGeom( 3281 WmInfo *wmPtr, 3282 TkWindow *winPtr) 3283{ 3284 if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { 3285 Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr); 3286 wmPtr->flags |= WM_UPDATE_PENDING; 3287 } 3288} 3289 3290/* 3291 *---------------------------------------------------------------------- 3292 * 3293 * Tk_SetGrid -- 3294 * 3295 * This procedure is invoked by a widget when it wishes to set a grid 3296 * coordinate system that controls the size of a top-level window. It 3297 * provides a C interface equivalent to the "wm grid" command and is 3298 * usually asscoiated with the -setgrid option. 3299 * 3300 * Results: 3301 * None. 3302 * 3303 * Side effects: 3304 * Grid-related information will be passed to the window manager, so that 3305 * the top-level window associated with tkwin will resize on even grid 3306 * units. If some other window already controls gridding for the 3307 * top-level window then this procedure call has no effect. 3308 * 3309 *---------------------------------------------------------------------- 3310 */ 3311 3312void 3313Tk_SetGrid( 3314 Tk_Window tkwin, /* Token for window. New window mgr info will 3315 * be posted for the top-level window 3316 * associated with this window. */ 3317 int reqWidth, /* Width (in grid units) corresponding to the 3318 * requested geometry for tkwin. */ 3319 int reqHeight, /* Height (in grid units) corresponding to the 3320 * requested geometry for tkwin. */ 3321 int widthInc, int heightInc)/* Pixel increments corresponding to a change 3322 * of one grid unit. */ 3323{ 3324 TkWindow *winPtr = (TkWindow *) tkwin; 3325 WmInfo *wmPtr; 3326 3327 /* 3328 * Ensure widthInc and heightInc are greater than 0 3329 */ 3330 3331 if (widthInc <= 0) { 3332 widthInc = 1; 3333 } 3334 if (heightInc <= 0) { 3335 heightInc = 1; 3336 } 3337 3338 /* 3339 * Find the top-level window for tkwin, plus the window manager 3340 * information. 3341 */ 3342 3343 while (!(winPtr->flags & TK_TOP_LEVEL)) { 3344 winPtr = winPtr->parentPtr; 3345 } 3346 wmPtr = winPtr->wmInfoPtr; 3347 3348 if ((wmPtr->gridWin != NULL) && (wmPtr->gridWin != tkwin)) { 3349 return; 3350 } 3351 3352 if ((wmPtr->reqGridWidth == reqWidth) 3353 && (wmPtr->reqGridHeight == reqHeight) 3354 && (wmPtr->widthInc == widthInc) 3355 && (wmPtr->heightInc == heightInc) 3356 && ((wmPtr->sizeHintsFlags & (PBaseSize|PResizeInc)) 3357 == (PBaseSize|PResizeInc))) { 3358 return; 3359 } 3360 3361 /* 3362 * If gridding was previously off, then forget about any window size 3363 * requests made by the user or via "wm geometry": these are in pixel 3364 * units and there's no easy way to translate them to grid units since the 3365 * new requested size of the top-level window in pixels may not yet have 3366 * been registered yet (it may filter up the hierarchy in DoWhenIdle 3367 * handlers). However, if the window has never been mapped yet then just 3368 * leave the window size alone: assume that it is intended to be in grid 3369 * units but just happened to have been specified before this procedure 3370 * was called. 3371 */ 3372 3373 if ((wmPtr->gridWin == NULL) && !(wmPtr->flags & WM_NEVER_MAPPED)) { 3374 wmPtr->width = -1; 3375 wmPtr->height = -1; 3376 } 3377 3378 /* 3379 * Set the new gridding information, and start the process of passing all 3380 * of this information to the window manager. 3381 */ 3382 3383 wmPtr->gridWin = tkwin; 3384 wmPtr->reqGridWidth = reqWidth; 3385 wmPtr->reqGridHeight = reqHeight; 3386 wmPtr->widthInc = widthInc; 3387 wmPtr->heightInc = heightInc; 3388 wmPtr->sizeHintsFlags |= PBaseSize|PResizeInc; 3389 wmPtr->flags |= WM_UPDATE_SIZE_HINTS; 3390 if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { 3391 Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr); 3392 wmPtr->flags |= WM_UPDATE_PENDING; 3393 } 3394} 3395 3396/* 3397 *---------------------------------------------------------------------- 3398 * 3399 * Tk_UnsetGrid -- 3400 * 3401 * This procedure cancels the effect of a previous call to Tk_SetGrid. 3402 * 3403 * Results: 3404 * None. 3405 * 3406 * Side effects: 3407 * If tkwin currently controls gridding for its top-level window, 3408 * gridding is cancelled for that top-level window; if some other window 3409 * controls gridding then this procedure has no effect. 3410 * 3411 *---------------------------------------------------------------------- 3412 */ 3413 3414void 3415Tk_UnsetGrid( 3416 Tk_Window tkwin) /* Token for window that is currently 3417 * controlling gridding. */ 3418{ 3419 TkWindow *winPtr = (TkWindow *) tkwin; 3420 WmInfo *wmPtr; 3421 3422 /* 3423 * Find the top-level window for tkwin, plus the window manager 3424 * information. 3425 */ 3426 3427 while (!(winPtr->flags & TK_TOP_LEVEL)) { 3428 winPtr = winPtr->parentPtr; 3429 } 3430 wmPtr = winPtr->wmInfoPtr; 3431 if (tkwin != wmPtr->gridWin) { 3432 return; 3433 } 3434 3435 wmPtr->gridWin = NULL; 3436 wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc); 3437 if (wmPtr->width != -1) { 3438 wmPtr->width = winPtr->reqWidth + (wmPtr->width 3439 - wmPtr->reqGridWidth)*wmPtr->widthInc; 3440 wmPtr->height = winPtr->reqHeight + (wmPtr->height 3441 - wmPtr->reqGridHeight)*wmPtr->heightInc; 3442 } 3443 wmPtr->widthInc = 1; 3444 wmPtr->heightInc = 1; 3445 3446 wmPtr->flags |= WM_UPDATE_SIZE_HINTS; 3447 if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { 3448 Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr); 3449 wmPtr->flags |= WM_UPDATE_PENDING; 3450 } 3451} 3452 3453/* 3454 *---------------------------------------------------------------------- 3455 * 3456 * TopLevelEventProc -- 3457 * 3458 * This procedure is invoked when a top-level (or other externally- 3459 * managed window) is restructured in any way. 3460 * 3461 * Results: 3462 * None. 3463 * 3464 * Side effects: 3465 * Tk's internal data structures for the window get modified to reflect 3466 * the structural change. 3467 * 3468 *---------------------------------------------------------------------- 3469 */ 3470 3471static void 3472TopLevelEventProc( 3473 ClientData clientData, /* Window for which event occurred. */ 3474 XEvent *eventPtr) /* Event that just happened. */ 3475{ 3476 TkWindow *winPtr = clientData; 3477 3478 winPtr->wmInfoPtr->flags |= WM_VROOT_OFFSET_STALE; 3479 if (eventPtr->type == DestroyNotify) { 3480 if (!(winPtr->flags & TK_ALREADY_DEAD)) { 3481 /* 3482 * A top-level window was deleted externally (e.g., by the window 3483 * manager). This is probably not a good thing, but cleanup as 3484 * best we can. The error handler is needed because 3485 * Tk_DestroyWindow will try to destroy the window, but of course 3486 * it's already gone. 3487 */ 3488 3489 Tk_ErrorHandler handler = Tk_CreateErrorHandler(winPtr->display, 3490 -1, -1, -1, NULL, NULL); 3491 3492 Tk_DestroyWindow((Tk_Window) winPtr); 3493 Tk_DeleteErrorHandler(handler); 3494 } 3495 if (wmTracing) { 3496 TkMacOSXDbgMsg("TopLevelEventProc: %s deleted", winPtr->pathName); 3497 } 3498 } else if (eventPtr->type == ReparentNotify) { 3499 Tcl_Panic("recieved unwanted reparent event"); 3500 } 3501} 3502 3503/* 3504 *---------------------------------------------------------------------- 3505 * 3506 * TopLevelReqProc -- 3507 * 3508 * This procedure is invoked by the geometry manager whenever the 3509 * requested size for a top-level window is changed. 3510 * 3511 * Results: 3512 * None. 3513 * 3514 * Side effects: 3515 * Arrange for the window to be resized to satisfy the request (this 3516 * happens as a when-idle action). 3517 * 3518 *---------------------------------------------------------------------- 3519 */ 3520 3521 /* ARGSUSED */ 3522static void 3523TopLevelReqProc( 3524 ClientData dummy, /* Not used. */ 3525 Tk_Window tkwin) /* Information about window. */ 3526{ 3527 TkWindow *winPtr = (TkWindow *) tkwin; 3528 WmInfo *wmPtr; 3529 3530 wmPtr = winPtr->wmInfoPtr; 3531 wmPtr->flags |= WM_UPDATE_SIZE_HINTS; 3532 if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { 3533 Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr); 3534 wmPtr->flags |= WM_UPDATE_PENDING; 3535 } 3536} 3537 3538/* 3539 *---------------------------------------------------------------------- 3540 * 3541 * UpdateGeometryInfo -- 3542 * 3543 * This procedure is invoked when a top-level window is first mapped, and 3544 * also as a when-idle procedure, to bring the geometry and/or position 3545 * of a top-level window back into line with what has been requested by 3546 * the user and/or widgets. This procedure doesn't return until the 3547 * window manager has responded to the geometry change. 3548 * 3549 * Results: 3550 * None. 3551 * 3552 * Side effects: 3553 * The window's size and location may change, unless the WM prevents that 3554 * from happening. 3555 * 3556 *---------------------------------------------------------------------- 3557 */ 3558 3559static void 3560UpdateGeometryInfo( 3561 ClientData clientData) /* Pointer to the window's record. */ 3562{ 3563 TkWindow *winPtr = clientData; 3564 WmInfo *wmPtr = winPtr->wmInfoPtr; 3565 int x, y, width, height, min, max; 3566 3567 wmPtr->flags &= ~WM_UPDATE_PENDING; 3568 3569 if (wmPtr->flags & WM_FULLSCREEN) { 3570 return; 3571 } 3572 3573 /* 3574 * Compute the new size for the top-level window. See the user 3575 * documentation for details on this, but the size requested depends on 3576 * (a) the size requested internally by the window's widgets, (b) the size 3577 * requested by the user in a "wm geometry" command or via wm-based 3578 * interactive resizing (if any), and (c) whether or not the window is 3579 * gridded. Don't permit sizes <= 0 because this upsets the X server. 3580 */ 3581 3582 if (wmPtr->width == -1) { 3583 width = winPtr->reqWidth; 3584 } else if (wmPtr->gridWin != NULL) { 3585 width = winPtr->reqWidth 3586 + (wmPtr->width - wmPtr->reqGridWidth)*wmPtr->widthInc; 3587 } else { 3588 width = wmPtr->width; 3589 } 3590 if (width <= 0) { 3591 width = 1; 3592 } 3593 3594 /* 3595 * Account for window max/min width 3596 */ 3597 3598 if (wmPtr->gridWin != NULL) { 3599 min = winPtr->reqWidth 3600 + (wmPtr->minWidth - wmPtr->reqGridWidth)*wmPtr->widthInc; 3601 if (wmPtr->maxWidth > 0) { 3602 max = winPtr->reqWidth 3603 + (wmPtr->maxWidth - wmPtr->reqGridWidth)*wmPtr->widthInc; 3604 } else { 3605 max = 0; 3606 } 3607 } else { 3608 min = wmPtr->minWidth; 3609 max = wmPtr->maxWidth; 3610 } 3611 if (width < min) { 3612 width = min; 3613 } else if ((max > 0) && (width > max)) { 3614 width = max; 3615 } 3616 3617 if (wmPtr->height == -1) { 3618 height = winPtr->reqHeight; 3619 } else if (wmPtr->gridWin != NULL) { 3620 height = winPtr->reqHeight 3621 + (wmPtr->height - wmPtr->reqGridHeight)*wmPtr->heightInc; 3622 } else { 3623 height = wmPtr->height; 3624 } 3625 if (height <= 0) { 3626 height = 1; 3627 } 3628 3629 /* 3630 * Account for window max/min height 3631 */ 3632 3633 if (wmPtr->gridWin != NULL) { 3634 min = winPtr->reqHeight 3635 + (wmPtr->minHeight - wmPtr->reqGridHeight)*wmPtr->heightInc; 3636 if (wmPtr->maxHeight > 0) { 3637 max = winPtr->reqHeight 3638 + (wmPtr->maxHeight-wmPtr->reqGridHeight)*wmPtr->heightInc; 3639 } else { 3640 max = 0; 3641 } 3642 } else { 3643 min = wmPtr->minHeight; 3644 max = wmPtr->maxHeight; 3645 } 3646 if (height < min) { 3647 height = min; 3648 } else if ((max > 0) && (height > max)) { 3649 height = max; 3650 } 3651 3652 /* 3653 * Compute the new position for the upper-left pixel of the window's 3654 * decorative frame. This is tricky, because we need to include the border 3655 * widths supplied by a reparented parent in this calculation, but can't 3656 * use the parent's current overall size since that may change as a result 3657 * of this code. 3658 */ 3659 3660 if (wmPtr->flags & WM_NEGATIVE_X) { 3661 x = wmPtr->vRootWidth - wmPtr->x 3662 - (width + (wmPtr->parentWidth - winPtr->changes.width)); 3663 } else { 3664 x = wmPtr->x; 3665 } 3666 if (wmPtr->flags & WM_NEGATIVE_Y) { 3667 y = wmPtr->vRootHeight - wmPtr->y 3668 - (height + (wmPtr->parentHeight - winPtr->changes.height)); 3669 } else { 3670 y = wmPtr->y; 3671 } 3672 3673 /* 3674 * If the window's size is going to change and the window is supposed to 3675 * not be resizable by the user, then we have to update the size hints. 3676 * There may also be a size-hint-update request pending from somewhere 3677 * else, too. 3678 */ 3679 3680 if (((width != winPtr->changes.width) 3681 || (height != winPtr->changes.height)) 3682 && (wmPtr->gridWin == NULL) 3683 && ((wmPtr->sizeHintsFlags & (PMinSize|PMaxSize)) == 0)) { 3684 wmPtr->flags |= WM_UPDATE_SIZE_HINTS; 3685 } 3686 if (wmPtr->flags & WM_UPDATE_SIZE_HINTS) { 3687 UpdateSizeHints(winPtr); 3688 } 3689 3690 /* 3691 * Reconfigure the window if it isn't already configured correctly. A few 3692 * tricky points: 3693 * 3694 * 1. If the window is embedded and the container is also in this process, 3695 * don't actually reconfigure the window; just pass the desired size on 3696 * to the container. Also, zero out any position information, since 3697 * embedded windows are not allowed to move. 3698 * 2. Sometimes the window manager will give us a different size than we 3699 * asked for (e.g. mwm has a minimum size for windows), so base the 3700 * size check on what we *asked for* last time, not what we got. 3701 * 3. Don't move window unless a new position has been requested for it. 3702 * This is because of "features" in some window managers (e.g. twm, as 3703 * of 4/24/91) where they don't interpret coordinates according to 3704 * ICCCM. Moving a window to its current location may cause it to shift 3705 * position on the screen. 3706 */ 3707 3708 if (Tk_IsEmbedded(winPtr)) { 3709 TkWindow *contWinPtr = TkpGetOtherWindow(winPtr); 3710 3711 /* 3712 * TODO: Here we should handle out of process embedding. 3713 */ 3714 3715 if (contWinPtr != NULL) { 3716 /* 3717 * This window is embedded and the container is also in this 3718 * process, so we don't need to do anything special about the 3719 * geometry, except to make sure that the desired size is known by 3720 * the container. Also, zero out any position information, since 3721 * embedded windows are not allowed to move. 3722 */ 3723 3724 wmPtr->x = wmPtr->y = 0; 3725 wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y); 3726 Tk_GeometryRequest((Tk_Window) contWinPtr, width, height); 3727 } 3728 return; 3729 } 3730 if (wmPtr->flags & WM_MOVE_PENDING) { 3731 wmPtr->configWidth = width; 3732 wmPtr->configHeight = height; 3733 if (wmTracing) { 3734 TkMacOSXDbgMsg("Moving to %d %d, resizing to %d x %d", x, y, 3735 width, height); 3736 } 3737 SetWindowSizeLimits(winPtr); 3738 wmPtr->flags |= WM_SYNC_PENDING; 3739 XMoveResizeWindow(winPtr->display, winPtr->window, x, y, 3740 wmPtr->configWidth, wmPtr->configHeight); 3741 wmPtr->flags &= ~WM_SYNC_PENDING; 3742 } else if ((width != wmPtr->configWidth) 3743 || (height != wmPtr->configHeight)) { 3744 wmPtr->configWidth = width; 3745 wmPtr->configHeight = height; 3746 if (wmTracing) { 3747 TkMacOSXDbgMsg("Resizing to %d x %d\n", width, height); 3748 } 3749 SetWindowSizeLimits(winPtr); 3750 wmPtr->flags |= WM_SYNC_PENDING; 3751 XResizeWindow(winPtr->display, winPtr->window, wmPtr->configWidth, 3752 wmPtr->configHeight); 3753 wmPtr->flags &= ~WM_SYNC_PENDING; 3754 } else { 3755 SetWindowSizeLimits(winPtr); 3756 } 3757} 3758 3759/* 3760 *---------------------------------------------------------------------- 3761 * 3762 * UpdateSizeHints -- 3763 * 3764 * This procedure is called to update the window manager's size hints 3765 * information from the information in a WmInfo structure. 3766 * 3767 * Results: 3768 * None. 3769 * 3770 * Side effects: 3771 * Properties get changed for winPtr. 3772 * 3773 *---------------------------------------------------------------------- 3774 */ 3775 3776static void 3777UpdateSizeHints( 3778 TkWindow *winPtr) 3779{ 3780 WmInfo *wmPtr = winPtr->wmInfoPtr; 3781 3782 wmPtr->flags &= ~WM_UPDATE_SIZE_HINTS; 3783} 3784 3785/* 3786 *---------------------------------------------------------------------- 3787 * 3788 * ParseGeometry -- 3789 * 3790 * This procedure parses a geometry string and updates information used 3791 * to control the geometry of a top-level window. 3792 * 3793 * Results: 3794 * A standard Tcl return value, plus an error message in the interp's 3795 * result if an error occurs. 3796 * 3797 * Side effects: 3798 * The size and/or location of winPtr may change. 3799 * 3800 *---------------------------------------------------------------------- 3801 */ 3802 3803static int 3804ParseGeometry( 3805 Tcl_Interp *interp, /* Used for error reporting. */ 3806 char *string, /* String containing new geometry. Has the 3807 * standard form "=wxh+x+y". */ 3808 TkWindow *winPtr) /* Pointer to top-level window whose geometry 3809 * is to be changed. */ 3810{ 3811 WmInfo *wmPtr = winPtr->wmInfoPtr; 3812 int x, y, width, height, flags; 3813 char *end; 3814 char *p = string; 3815 3816 /* 3817 * The leading "=" is optional. 3818 */ 3819 3820 if (*p == '=') { 3821 p++; 3822 } 3823 3824 /* 3825 * Parse the width and height, if they are present. Don't actually update 3826 * any of the fields of wmPtr until we've successfully parsed the entire 3827 * geometry string. 3828 */ 3829 3830 width = wmPtr->width; 3831 height = wmPtr->height; 3832 x = wmPtr->x; 3833 y = wmPtr->y; 3834 flags = wmPtr->flags; 3835 if (isdigit(UCHAR(*p))) { 3836 width = strtoul(p, &end, 10); 3837 p = end; 3838 if (*p != 'x') { 3839 goto error; 3840 } 3841 p++; 3842 if (!isdigit(UCHAR(*p))) { 3843 goto error; 3844 } 3845 height = strtoul(p, &end, 10); 3846 p = end; 3847 } 3848 3849 /* 3850 * Parse the X and Y coordinates, if they are present. 3851 */ 3852 3853 if (*p != '\0') { 3854 flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y); 3855 if (*p == '-') { 3856 flags |= WM_NEGATIVE_X; 3857 } else if (*p != '+') { 3858 goto error; 3859 } 3860 p++; 3861 if (!isdigit(UCHAR(*p)) && (*p != '-')) { 3862 goto error; 3863 } 3864 x = strtol(p, &end, 10); 3865 p = end; 3866 if (*p == '-') { 3867 flags |= WM_NEGATIVE_Y; 3868 } else if (*p != '+') { 3869 goto error; 3870 } 3871 p++; 3872 if (!isdigit(UCHAR(*p)) && (*p != '-')) { 3873 goto error; 3874 } 3875 y = strtol(p, &end, 10); 3876 if (*end != '\0') { 3877 goto error; 3878 } 3879 3880 /* 3881 * Assume that the geometry information came from the user, unless an 3882 * explicit source has been specified. Otherwise most window managers 3883 * assume that the size hints were program-specified and they ignore 3884 * them. 3885 */ 3886 3887 if ((wmPtr->sizeHintsFlags & (USPosition|PPosition)) == 0) { 3888 wmPtr->sizeHintsFlags |= USPosition; 3889 flags |= WM_UPDATE_SIZE_HINTS; 3890 } 3891 } 3892 3893 /* 3894 * Everything was parsed OK. Update the fields of *wmPtr and arrange for 3895 * the appropriate information to be percolated out to the window manager 3896 * at the next idle moment. 3897 */ 3898 3899 wmPtr->width = width; 3900 wmPtr->height = height; 3901 if ((x != wmPtr->x) || (y != wmPtr->y) 3902 || ((flags & (WM_NEGATIVE_X|WM_NEGATIVE_Y)) 3903 != (wmPtr->flags & (WM_NEGATIVE_X|WM_NEGATIVE_Y)))) { 3904 if (wmPtr->flags & WM_FULLSCREEN) { 3905 wmPtr->configX = x; 3906 wmPtr->configY = y; 3907 } else { 3908 wmPtr->x = x; 3909 wmPtr->y = y; 3910 } 3911 flags |= WM_MOVE_PENDING; 3912 } 3913 wmPtr->flags = flags; 3914 3915 if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { 3916 Tcl_DoWhenIdle(UpdateGeometryInfo, winPtr); 3917 wmPtr->flags |= WM_UPDATE_PENDING; 3918 } 3919 return TCL_OK; 3920 3921 error: 3922 Tcl_AppendResult(interp, "bad geometry specifier \"", string, "\"", NULL); 3923 return TCL_ERROR; 3924} 3925 3926/* 3927 *---------------------------------------------------------------------- 3928 * 3929 * Tk_GetRootCoords -- 3930 * 3931 * Given a token for a window, this procedure traces through the window's 3932 * lineage to find the (virtual) root-window coordinates corresponding to 3933 * point (0,0) in the window. 3934 * 3935 * Results: 3936 * The locations pointed to by xPtr and yPtr are filled in with the root 3937 * coordinates of the (0,0) point in tkwin. If a virtual root window is 3938 * in effect for the window, then the coordinates in the virtual root are 3939 * returned. 3940 * 3941 * Side effects: 3942 * None. 3943 * 3944 *---------------------------------------------------------------------- 3945 */ 3946 3947void 3948Tk_GetRootCoords( 3949 Tk_Window tkwin, /* Token for window. */ 3950 int *xPtr, /* Where to store x-displacement of (0,0). */ 3951 int *yPtr) /* Where to store y-displacement of (0,0). */ 3952{ 3953 int x, y; 3954 TkWindow *winPtr = (TkWindow *) tkwin; 3955 3956 /* 3957 * Search back through this window's parents all the way to a top-level 3958 * window, combining the offsets of each window within its parent. 3959 */ 3960 3961 x = y = 0; 3962 while (1) { 3963 x += winPtr->changes.x + winPtr->changes.border_width; 3964 y += winPtr->changes.y + winPtr->changes.border_width; 3965 if (winPtr->flags & TK_TOP_LEVEL) { 3966 TkWindow *otherPtr; 3967 3968 if (!(Tk_IsEmbedded(winPtr))) { 3969 x += winPtr->wmInfoPtr->xInParent; 3970 y += winPtr->wmInfoPtr->yInParent; 3971 break; 3972 } 3973 3974 otherPtr = TkpGetOtherWindow(winPtr); 3975 if (otherPtr == NULL) { 3976 if (tkMacOSXEmbedHandler->getOffsetProc != NULL) { 3977 Point theOffset; 3978 3979 /* 3980 * We do not require that the changes.x & changes.y for a 3981 * non-Tk master window be kept up to date. So we first 3982 * subtract off the possibly bogus values that have been 3983 * added on at the top of this pass through the loop, and 3984 * then call out to the getOffsetProc to give us the 3985 * correct offset. 3986 */ 3987 3988 x -= winPtr->changes.x + winPtr->changes.border_width; 3989 y -= winPtr->changes.y + winPtr->changes.border_width; 3990 3991 tkMacOSXEmbedHandler->getOffsetProc((Tk_Window) winPtr, 3992 &theOffset); 3993 3994 x += theOffset.h; 3995 y += theOffset.v; 3996 } 3997 break; 3998 } 3999 4000 /* 4001 * The container window is in the same application. Query its 4002 * coordinates. 4003 */ 4004 4005 winPtr = otherPtr; 4006 4007 /* 4008 * Remember to offset by the container window here, since at the 4009 * end of this if branch, we will pop out to the container's 4010 * parent... 4011 */ 4012 4013 x += winPtr->changes.x + winPtr->changes.border_width; 4014 y += winPtr->changes.y + winPtr->changes.border_width; 4015 } 4016 winPtr = winPtr->parentPtr; 4017 } 4018 *xPtr = x; 4019 *yPtr = y; 4020} 4021 4022/* 4023 *---------------------------------------------------------------------- 4024 * 4025 * Tk_CoordsToWindow -- 4026 * 4027 * This is a Macintosh specific implementation of this function. Given 4028 * the root coordinates of a point, this procedure returns the token for 4029 * the top-most window covering that point, if there exists such a window 4030 * in this application. 4031 * 4032 * Results: 4033 * The return result is either a token for the window corresponding to 4034 * rootX and rootY, or else NULL to indicate that there is no such 4035 * window. 4036 * 4037 * Side effects: 4038 * None. 4039 * 4040 *---------------------------------------------------------------------- 4041 */ 4042 4043Tk_Window 4044Tk_CoordsToWindow( 4045 int rootX, int rootY, /* Coordinates of point in root window. If a 4046 * virtual-root window manager is in use, 4047 * these coordinates refer to the virtual 4048 * root, not the real root. */ 4049 Tk_Window tkwin) /* Token for any window in application; used 4050 * to identify the display. */ 4051{ 4052 TkWindow *winPtr, *childPtr; 4053 TkWindow *nextPtr; /* Coordinates of highest child found so far 4054 * that contains point. */ 4055 int x, y; /* Coordinates in winPtr. */ 4056 int tmpx, tmpy, bd; 4057 4058 /* 4059 * Step 1: find the top-level window that contains the desired point. 4060 */ 4061 4062 winPtr = FrontWindowAtPoint(rootX, rootY); 4063 if (!winPtr) { 4064 return NULL; 4065 } 4066 4067 /* 4068 * Step 2: work down through the hierarchy underneath this window. At each 4069 * level, scan through all the children to find the highest one in the 4070 * stacking order that contains the point. Then repeat the whole process 4071 * on that child. 4072 */ 4073 4074 x = rootX - winPtr->wmInfoPtr->xInParent; 4075 y = rootY - winPtr->wmInfoPtr->yInParent; 4076 while (1) { 4077 x -= winPtr->changes.x; 4078 y -= winPtr->changes.y; 4079 nextPtr = NULL; 4080 4081 /* 4082 * Container windows cannot have children. So if it is a container, 4083 * look there, otherwise inspect the children. 4084 */ 4085 4086 if (Tk_IsContainer(winPtr)) { 4087 childPtr = TkpGetOtherWindow(winPtr); 4088 if (childPtr != NULL) { 4089 if (Tk_IsMapped(childPtr)) { 4090 tmpx = x - childPtr->changes.x; 4091 tmpy = y - childPtr->changes.y; 4092 bd = childPtr->changes.border_width; 4093 4094 if ((tmpx >= -bd) && (tmpy >= -bd) 4095 && (tmpx < (childPtr->changes.width + bd)) 4096 && (tmpy < (childPtr->changes.height + bd))) { 4097 nextPtr = childPtr; 4098 } 4099 } 4100 } 4101 4102 /* 4103 * TODO: Here we should handle out of process embedding. 4104 */ 4105 } else { 4106 for (childPtr = winPtr->childList; childPtr != NULL; 4107 childPtr = childPtr->nextPtr) { 4108 if (!Tk_IsMapped(childPtr) || 4109 (childPtr->flags & TK_TOP_LEVEL)) { 4110 continue; 4111 } 4112 tmpx = x - childPtr->changes.x; 4113 tmpy = y - childPtr->changes.y; 4114 bd = childPtr->changes.border_width; 4115 if ((tmpx >= -bd) && (tmpy >= -bd) 4116 && (tmpx < (childPtr->changes.width + bd)) 4117 && (tmpy < (childPtr->changes.height + bd))) { 4118 nextPtr = childPtr; 4119 } 4120 } 4121 } 4122 if (nextPtr == NULL) { 4123 break; 4124 } 4125 winPtr = nextPtr; 4126 } 4127 return (Tk_Window) winPtr; 4128} 4129 4130/* 4131 *---------------------------------------------------------------------- 4132 * 4133 * Tk_TopCoordsToWindow -- 4134 * 4135 * Given a Tk Window, and coordinates of a point relative to that window 4136 * this procedure returns the top-most child of the window (excluding 4137 * toplevels) covering that point, if there exists such a window in this 4138 * application. It also sets newX, and newY to the coords of the point 4139 * relative to the window returned. 4140 * 4141 * Results: 4142 * The return result is either a token for the window corresponding to 4143 * rootX and rootY, or else NULL to indicate that there is no such 4144 * window. newX and newY are also set to the coords of the point relative 4145 * to the returned window. 4146 * 4147 * Side effects: 4148 * None. 4149 * 4150 *---------------------------------------------------------------------- 4151 */ 4152 4153Tk_Window 4154Tk_TopCoordsToWindow( 4155 Tk_Window tkwin, /* Token for a Tk Window which defines the 4156 * coordinates for rootX & rootY */ 4157 int rootX, int rootY, /* Coordinates of a point in tkWin. */ 4158 int *newX, int *newY) /* Coordinates of point in the upperMost child 4159 * of tkWin containing (rootX,rootY) */ 4160{ 4161 TkWindow *winPtr, *childPtr; 4162 TkWindow *nextPtr; /* Coordinates of highest child found so far 4163 * that contains point. */ 4164 int x, y; /* Coordinates in winPtr. */ 4165 Window *children; /* Children of winPtr, or NULL. */ 4166 4167 winPtr = (TkWindow *) tkwin; 4168 x = rootX; 4169 y = rootY; 4170 while (1) { 4171 nextPtr = NULL; 4172 children = NULL; 4173 4174 /* 4175 * Container windows cannot have children. So if it is a container, 4176 * look there, otherwise inspect the children. 4177 */ 4178 4179 if (Tk_IsContainer(winPtr)) { 4180 childPtr = TkpGetOtherWindow(winPtr); 4181 if (childPtr != NULL) { 4182 if (Tk_IsMapped(childPtr) && 4183 x > childPtr->changes.x && 4184 x < childPtr->changes.x + childPtr->changes.width && 4185 y > childPtr->changes.y && 4186 y < childPtr->changes.y + childPtr->changes.height) { 4187 nextPtr = childPtr; 4188 } 4189 } 4190 4191 /* 4192 * TODO: Here we should handle out of process embedding. 4193 */ 4194 } else { 4195 for (childPtr = winPtr->childList; childPtr != NULL; 4196 childPtr = childPtr->nextPtr) { 4197 if (!Tk_IsMapped(childPtr) || 4198 (childPtr->flags & TK_TOP_LEVEL)) { 4199 continue; 4200 } 4201 if (x < childPtr->changes.x || y < childPtr->changes.y) { 4202 continue; 4203 } 4204 if (x > childPtr->changes.x + childPtr->changes.width || 4205 y > childPtr->changes.y + childPtr->changes.height) { 4206 continue; 4207 } 4208 nextPtr = childPtr; 4209 } 4210 } 4211 if (nextPtr == NULL) { 4212 break; 4213 } 4214 winPtr = nextPtr; 4215 x -= winPtr->changes.x; 4216 y -= winPtr->changes.y; 4217 } 4218 *newX = x; 4219 *newY = y; 4220 return (Tk_Window) winPtr; 4221} 4222 4223/* 4224 *---------------------------------------------------------------------- 4225 * 4226 * UpdateVRootGeometry -- 4227 * 4228 * This procedure is called to update all the virtual root geometry 4229 * information in wmPtr. 4230 * 4231 * Results: 4232 * None. 4233 * 4234 * Side effects: 4235 * The vRootX, vRootY, vRootWidth, and vRootHeight fields in wmPtr are 4236 * filled with the most up-to-date information. 4237 * 4238 *---------------------------------------------------------------------- 4239 */ 4240 4241static void 4242UpdateVRootGeometry( 4243 WmInfo *wmPtr) /* Window manager information to be updated. 4244 * The wmPtr->vRoot field must be valid. */ 4245{ 4246 TkWindow *winPtr = wmPtr->winPtr; 4247 unsigned int bd, dummy; 4248 Window dummy2; 4249 Status status; 4250 Tk_ErrorHandler handler; 4251 4252 /* 4253 * If this isn't a virtual-root window manager, just return information 4254 * about the screen. 4255 */ 4256 4257 wmPtr->flags &= ~WM_VROOT_OFFSET_STALE; 4258 if (wmPtr->vRoot == None) { 4259 noVRoot: 4260 wmPtr->vRootX = wmPtr->vRootY = 0; 4261 wmPtr->vRootWidth = DisplayWidth(winPtr->display, winPtr->screenNum); 4262 wmPtr->vRootHeight = DisplayHeight(winPtr->display, winPtr->screenNum); 4263 return; 4264 } 4265 4266 /* 4267 * Refresh the virtual root information if it's out of date. 4268 */ 4269 4270 handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1, NULL, NULL); 4271 status = XGetGeometry(winPtr->display, wmPtr->vRoot, 4272 &dummy2, &wmPtr->vRootX, &wmPtr->vRootY, 4273 &wmPtr->vRootWidth, &wmPtr->vRootHeight, &bd, &dummy); 4274 if (wmTracing) { 4275 TkMacOSXDbgMsg("x = %d, y = %d, width = %d, height = %d, status = %d", 4276 wmPtr->vRootX, wmPtr->vRootY, wmPtr->vRootWidth, 4277 wmPtr->vRootHeight, status); 4278 } 4279 Tk_DeleteErrorHandler(handler); 4280 if (status == 0) { 4281 /* 4282 * The virtual root is gone! Pretend that it never existed. 4283 */ 4284 4285 wmPtr->vRoot = None; 4286 goto noVRoot; 4287 } 4288} 4289 4290/* 4291 *---------------------------------------------------------------------- 4292 * 4293 * Tk_GetVRootGeometry -- 4294 * 4295 * This procedure returns information about the virtual root window 4296 * corresponding to a particular Tk window. 4297 * 4298 * Results: 4299 * The values at xPtr, yPtr, widthPtr, and heightPtr are set with the 4300 * offset and dimensions of the root window corresponding to tkwin. If 4301 * tkwin is being managed by a virtual root window manager these values 4302 * correspond to the virtual root window being used for tkwin; otherwise 4303 * the offsets will be 0 and the dimensions will be those of the screen. 4304 * 4305 * Side effects: 4306 * Vroot window information is refreshed if it is out of date. 4307 * 4308 *---------------------------------------------------------------------- 4309 */ 4310 4311void 4312Tk_GetVRootGeometry( 4313 Tk_Window tkwin, /* Window whose virtual root is to be 4314 * queried. */ 4315 int *xPtr, int *yPtr, /* Store x and y offsets of virtual root 4316 * here. */ 4317 int *widthPtr, /* Store dimensions of virtual root here. */ 4318 int *heightPtr) 4319{ 4320 WmInfo *wmPtr; 4321 TkWindow *winPtr = (TkWindow *) tkwin; 4322 4323 /* 4324 * Find the top-level window for tkwin, and locate the window manager 4325 * information for that window. 4326 */ 4327 4328 while (!(winPtr->flags & TK_TOP_LEVEL)) { 4329 winPtr = winPtr->parentPtr; 4330 } 4331 wmPtr = winPtr->wmInfoPtr; 4332 4333 /* 4334 * Make sure that the geometry information is up-to-date, then copy it out 4335 * to the caller. 4336 */ 4337 4338 if (wmPtr->flags & WM_VROOT_OFFSET_STALE) { 4339 UpdateVRootGeometry(wmPtr); 4340 } 4341 *xPtr = wmPtr->vRootX; 4342 *yPtr = wmPtr->vRootY; 4343 *widthPtr = wmPtr->vRootWidth; 4344 *heightPtr = wmPtr->vRootHeight; 4345} 4346 4347/* 4348 *---------------------------------------------------------------------- 4349 * 4350 * Tk_MoveToplevelWindow -- 4351 * 4352 * This procedure is called instead of Tk_MoveWindow to adjust the x-y 4353 * location of a top-level window. It delays the actual move to a later 4354 * time and keeps window-manager information up-to-date with the move. 4355 * 4356 * Results: 4357 * None. 4358 * 4359 * Side effects: 4360 * The window is eventually moved so that its upper-left corner 4361 * (actually, the upper-left corner of the window's decorative frame, if 4362 * there is one) is at (x,y). 4363 * 4364 *---------------------------------------------------------------------- 4365 */ 4366 4367void 4368Tk_MoveToplevelWindow( 4369 Tk_Window tkwin, /* Window to move. */ 4370 int x, int y) /* New location for window (within parent). */ 4371{ 4372 TkWindow *winPtr = (TkWindow *) tkwin; 4373 WmInfo *wmPtr = winPtr->wmInfoPtr; 4374 4375 if (!(winPtr->flags & TK_TOP_LEVEL)) { 4376 Tcl_Panic("Tk_MoveToplevelWindow called with non-toplevel window"); 4377 } 4378 wmPtr->x = x; 4379 wmPtr->y = y; 4380 wmPtr->flags |= WM_MOVE_PENDING; 4381 wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y); 4382 if ((wmPtr->sizeHintsFlags & (USPosition|PPosition)) == 0) { 4383 wmPtr->sizeHintsFlags |= USPosition; 4384 wmPtr->flags |= WM_UPDATE_SIZE_HINTS; 4385 } 4386 4387 /* 4388 * If the window has already been mapped, must bring its geometry 4389 * up-to-date immediately, otherwise an event might arrive from the server 4390 * that would overwrite wmPtr->x and wmPtr->y and lose the new position. 4391 */ 4392 4393 if (!(wmPtr->flags & WM_NEVER_MAPPED)) { 4394 if (wmPtr->flags & WM_UPDATE_PENDING) { 4395 Tk_CancelIdleCall(UpdateGeometryInfo, winPtr); 4396 } 4397 UpdateGeometryInfo(winPtr); 4398 } 4399} 4400 4401/* 4402 *---------------------------------------------------------------------- 4403 * 4404 * TkWmRestackToplevel -- 4405 * 4406 * This procedure restacks a top-level window. 4407 * 4408 * Results: 4409 * None. 4410 * 4411 * Side effects: 4412 * WinPtr gets restacked as specified by aboveBelow and otherPtr. This 4413 * procedure doesn't return until the restack has taken effect and the 4414 * ConfigureNotify event for it has been received. 4415 * 4416 *---------------------------------------------------------------------- 4417 */ 4418 4419void 4420TkWmRestackToplevel( 4421 TkWindow *winPtr, /* Window to restack. */ 4422 int aboveBelow, /* Gives relative position for restacking; 4423 * must be Above or Below. */ 4424 TkWindow *otherPtr) /* Window relative to which to restack; if 4425 * NULL, then winPtr gets restacked above or 4426 * below *all* siblings. */ 4427{ 4428 NSWindow *macWindow; 4429 NSInteger otherMacWindowNumber; 4430 4431 /* 4432 * Get the mac window. Make sure it exists & is mapped. 4433 */ 4434 4435 if (winPtr->window == None) { 4436 Tk_MakeWindowExist((Tk_Window) winPtr); 4437 } 4438 if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) { 4439 /* 4440 * Can't set stacking order properly until the window is on the screen 4441 * (mapping it may give it a reparent window), so make sure it's on 4442 * the screen. 4443 */ 4444 4445 TkWmMapWindow(winPtr); 4446 } 4447 macWindow = TkMacOSXDrawableWindow(winPtr->window); 4448 4449 /* 4450 * Get the window in which a raise or lower is in relation to. 4451 */ 4452 4453 if (otherPtr != NULL) { 4454 if (otherPtr->window == None) { 4455 Tk_MakeWindowExist((Tk_Window) otherPtr); 4456 } 4457 if (otherPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) { 4458 TkWmMapWindow(otherPtr); 4459 } 4460 otherMacWindowNumber = [TkMacOSXDrawableWindow(otherPtr->window) 4461 windowNumber]; 4462 } else { 4463 otherMacWindowNumber = 0; 4464 } 4465 [macWindow orderWindow:(aboveBelow == Above ? NSWindowAbove : NSWindowBelow) 4466 relativeTo:otherMacWindowNumber]; 4467} 4468 4469/* 4470 *---------------------------------------------------------------------- 4471 * 4472 * TkWmAddToColormapWindows -- 4473 * 4474 * This procedure is called to add a given window to the 4475 * WM_COLORMAP_WINDOWS property for its top-level, if it isn't already 4476 * there. It is invoked by the Tk code that creates a new colormap, in 4477 * order to make sure that colormap information is propagated to the 4478 * window manager by default. 4479 * 4480 * Results: 4481 * None. 4482 * 4483 * Side effects: 4484 * WinPtr's window gets added to the WM_COLORMAP_WINDOWS property of its 4485 * nearest top-level ancestor, unless the colormaps have been set 4486 * explicitly with the "wm colormapwindows" command. 4487 * 4488 *---------------------------------------------------------------------- 4489 */ 4490 4491void 4492TkWmAddToColormapWindows( 4493 TkWindow *winPtr) /* Window with a non-default colormap. Should 4494 * not be a top-level window. */ 4495{ 4496 TkWindow *topPtr; 4497 TkWindow **oldPtr, **newPtr; 4498 int count, i; 4499 4500 if (winPtr->window == None) { 4501 return; 4502 } 4503 4504 for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) { 4505 if (topPtr == NULL) { 4506 /* 4507 * Window is being deleted. Skip the whole operation. 4508 */ 4509 4510 return; 4511 } 4512 if (topPtr->flags & TK_TOP_LEVEL) { 4513 break; 4514 } 4515 } 4516 if (topPtr->wmInfoPtr->flags & WM_COLORMAPS_EXPLICIT) { 4517 return; 4518 } 4519 4520 /* 4521 * Make sure that the window isn't already in the list. 4522 */ 4523 4524 count = topPtr->wmInfoPtr->cmapCount; 4525 oldPtr = topPtr->wmInfoPtr->cmapList; 4526 4527 for (i = 0; i < count; i++) { 4528 if (oldPtr[i] == winPtr) { 4529 return; 4530 } 4531 } 4532 4533 /* 4534 * Make a new bigger array and use it to reset the property. Automatically 4535 * add the toplevel itself as the last element of the list. 4536 */ 4537 4538 newPtr = (TkWindow **) ckalloc((unsigned) (count+2)*sizeof(TkWindow *)); 4539 if (count > 0) { 4540 memcpy(newPtr, oldPtr, count * sizeof(TkWindow *)); 4541 } 4542 if (count == 0) { 4543 count++; 4544 } 4545 newPtr[count-1] = winPtr; 4546 newPtr[count] = topPtr; 4547 if (oldPtr != NULL) { 4548 ckfree((char *) oldPtr); 4549 } 4550 4551 topPtr->wmInfoPtr->cmapList = newPtr; 4552 topPtr->wmInfoPtr->cmapCount = count+1; 4553 4554 /* 4555 * On the Macintosh all of this is just an excercise in compatability as 4556 * we don't support colormaps. If we did they would be installed here. 4557 */ 4558} 4559 4560/* 4561 *---------------------------------------------------------------------- 4562 * 4563 * TkWmRemoveFromColormapWindows -- 4564 * 4565 * This procedure is called to remove a given window from the 4566 * WM_COLORMAP_WINDOWS property for its top-level. It is invoked when 4567 * windows are deleted. 4568 * 4569 * Results: 4570 * None. 4571 * 4572 * Side effects: 4573 * WinPtr's window gets removed from the WM_COLORMAP_WINDOWS property of 4574 * its nearest top-level ancestor, unless the top-level itself is being 4575 * deleted too. 4576 * 4577 *---------------------------------------------------------------------- 4578 */ 4579 4580void 4581TkWmRemoveFromColormapWindows( 4582 TkWindow *winPtr) /* Window that may be present in 4583 * WM_COLORMAP_WINDOWS property for its 4584 * top-level. Should not be a top-level 4585 * window. */ 4586{ 4587 TkWindow *topPtr, **oldPtr; 4588 int count, i, j; 4589 4590 for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) { 4591 if (topPtr == NULL) { 4592 /* 4593 * Ancestors have been deleted, so skip the whole operation. Seems 4594 * like this can't ever happen? 4595 */ 4596 4597 return; 4598 } 4599 if (topPtr->flags & TK_TOP_LEVEL) { 4600 break; 4601 } 4602 } 4603 if (topPtr->flags & TK_ALREADY_DEAD) { 4604 /* 4605 * Top-level is being deleted, so there's no need to cleanup the 4606 * WM_COLORMAP_WINDOWS property. 4607 */ 4608 4609 return; 4610 } 4611 4612 /* 4613 * Find the window and slide the following ones down to cover it up. 4614 */ 4615 4616 count = topPtr->wmInfoPtr->cmapCount; 4617 oldPtr = topPtr->wmInfoPtr->cmapList; 4618 for (i = 0; i < count; i++) { 4619 if (oldPtr[i] == winPtr) { 4620 for (j = i ; j < count-1; j++) { 4621 oldPtr[j] = oldPtr[j+1]; 4622 } 4623 topPtr->wmInfoPtr->cmapCount = count - 1; 4624 break; 4625 } 4626 } 4627} 4628 4629/* 4630 *---------------------------------------------------------------------- 4631 * 4632 * TkGetPointerCoords -- 4633 * 4634 * Fetch the position of the mouse pointer. 4635 * 4636 * Results: 4637 * *xPtr and *yPtr are filled in with the (virtual) root coordinates of 4638 * the mouse pointer for tkwin's display. If the pointer isn't on tkwin's 4639 * screen, then -1 values are returned for both coordinates. The argument 4640 * tkwin must be a toplevel window. 4641 * 4642 * Side effects: 4643 * None. 4644 * 4645 *---------------------------------------------------------------------- 4646 */ 4647 4648void 4649TkGetPointerCoords( 4650 Tk_Window tkwin, /* Toplevel window that identifies screen on 4651 * which lookup is to be done. */ 4652 int *xPtr, int *yPtr) /* Store pointer coordinates here. */ 4653{ 4654 XQueryPointer(NULL, None, NULL, NULL, xPtr, yPtr, NULL, NULL, NULL); 4655} 4656 4657/* 4658 *---------------------------------------------------------------------- 4659 * 4660 * InitialWindowBounds -- 4661 * 4662 * This function calculates the initial bounds for a new Mac toplevel 4663 * window. Unless the geometry is specified by the user this code will 4664 * auto place the windows in a cascade diagonially across the main 4665 * monitor of the Mac. 4666 * 4667 * Results: 4668 * Window bounds. 4669 * 4670 * Side effects: 4671 * None. 4672 * 4673 *---------------------------------------------------------------------- 4674 */ 4675 4676static NSRect 4677InitialWindowBounds( 4678 TkWindow *winPtr, /* Window to get initial bounds for. */ 4679 NSWindow *macWindow) 4680{ 4681 WmInfo *wmPtr = winPtr->wmInfoPtr; 4682 4683 if (!(wmPtr->sizeHintsFlags & (USPosition | PPosition))) { 4684 static NSPoint cascadePoint = { .x = 0, .y = 0 }; 4685 NSRect frame; 4686 4687 cascadePoint = [macWindow cascadeTopLeftFromPoint:cascadePoint]; 4688 frame = [macWindow frame]; 4689 wmPtr->x = frame.origin.x; 4690 wmPtr->y = tkMacOSXZeroScreenHeight - (frame.origin.y + 4691 frame.size.height); 4692 } 4693 return NSMakeRect(wmPtr->x, wmPtr->y, winPtr->changes.width, 4694 winPtr->changes.height); 4695} 4696 4697/* 4698 *---------------------------------------------------------------------- 4699 * 4700 * TkMacOSXResizable -- 4701 * 4702 * This function determines if the passed in window is part of a toplevel 4703 * window that is resizable. If the window is resizable in the x, y or 4704 * both directions, true is returned. 4705 * 4706 * Results: 4707 * True if resizable, false otherwise. 4708 * 4709 * Side effects: 4710 * None. 4711 * 4712 *---------------------------------------------------------------------- 4713 */ 4714 4715int 4716TkMacOSXResizable( 4717 TkWindow *winPtr) /* Tk window or NULL. */ 4718{ 4719 WmInfo *wmPtr; 4720 4721 if (winPtr == NULL) { 4722 return false; 4723 } 4724 while (winPtr->wmInfoPtr == NULL) { 4725 winPtr = winPtr->parentPtr; 4726 } 4727 4728 wmPtr = winPtr->wmInfoPtr; 4729 if ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) && 4730 (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) { 4731 return false; 4732 } else { 4733 return true; 4734 } 4735} 4736 4737/* 4738 *---------------------------------------------------------------------- 4739 * 4740 * TkMacOSXGrowToplevel -- 4741 * 4742 * The function is invoked when the user clicks in the grow region of a 4743 * Tk window. The function will handle the dragging procedure and not 4744 * return until completed. Finally, the function may place information 4745 * Tk's event queue is the window was resized. 4746 * 4747 * Results: 4748 * True if events were placed on event queue, false otherwise. 4749 * 4750 * Side effects: 4751 * None. 4752 * 4753 *---------------------------------------------------------------------- 4754 */ 4755 4756int 4757TkMacOSXGrowToplevel( 4758 void *whichWindow, 4759 XPoint start) 4760{ 4761 return false; 4762} 4763 4764/* 4765 *---------------------------------------------------------------------- 4766 * 4767 * TkSetWMName -- 4768 * 4769 * Set the title for a toplevel window. If the window is embedded, do not 4770 * change the window title. 4771 * 4772 * Results: 4773 * None. 4774 * 4775 * Side effects: 4776 * The title of the window is changed. 4777 * 4778 *---------------------------------------------------------------------- 4779 */ 4780 4781void 4782TkSetWMName( 4783 TkWindow *winPtr, 4784 Tk_Uid titleUid) 4785{ 4786 if (Tk_IsEmbedded(winPtr)) { 4787 return; 4788 } 4789 4790 NSString *title = [[NSString alloc] initWithUTF8String:titleUid]; 4791 [TkMacOSXDrawableWindow(winPtr->window) setTitle:title]; 4792 [title release]; 4793} 4794 4795/* 4796 *---------------------------------------------------------------------- 4797 * 4798 * TkGetTransientMaster -- 4799 * 4800 * If the passed window has the TRANSIENT_FOR property set this will 4801 * return the master window. Otherwise it will return None. 4802 * 4803 * Results: 4804 * The master window or None. 4805 * 4806 * Side effects: 4807 * None. 4808 * 4809 *---------------------------------------------------------------------- 4810 */ 4811 4812Window 4813TkGetTransientMaster( 4814 TkWindow *winPtr) 4815{ 4816 if (winPtr->wmInfoPtr != NULL) { 4817 return winPtr->wmInfoPtr->master; 4818 } 4819 return None; 4820} 4821 4822/* 4823 *---------------------------------------------------------------------- 4824 * 4825 * TkMacOSXGetXWindow -- 4826 * 4827 * Returns the X window Id associated with the given NSWindow*. 4828 * 4829 * Results: 4830 * The window id is returned. None is returned if not a Tk window. 4831 * 4832 * Side effects: 4833 * None. 4834 * 4835 *---------------------------------------------------------------------- 4836 */ 4837 4838Window 4839TkMacOSXGetXWindow( 4840 void *macWinPtr) 4841{ 4842 Tcl_HashEntry *hPtr; 4843 4844 if (!macWinPtr || !windowHashInit) { 4845 return None; 4846 } 4847 hPtr = Tcl_FindHashEntry(&windowTable, macWinPtr); 4848 if (hPtr == NULL) { 4849 return None; 4850 } 4851 return (Window) Tcl_GetHashValue(hPtr); 4852} 4853 4854/* 4855 *---------------------------------------------------------------------- 4856 * 4857 * TkMacOSXGetTkWindow -- 4858 * 4859 * Returns the TkWindow* associated with the given NSWindow*. 4860 * 4861 * Results: 4862 * The TkWindow* returned. NULL is returned if not a Tk window. 4863 * 4864 * Side effects: 4865 * None. 4866 * 4867 *---------------------------------------------------------------------- 4868 */ 4869 4870TkWindow* 4871TkMacOSXGetTkWindow( 4872 NSWindow *w) 4873{ 4874 Window window = TkMacOSXGetXWindow(w); 4875 TkDisplay *dispPtr = TkGetDisplayList(); 4876 4877 return (window != None ? 4878 (TkWindow *)Tk_IdToWindow(dispPtr->display, window) : NULL); 4879} 4880 4881/* 4882 *---------------------------------------------------------------------- 4883 * 4884 * TkMacOSXIsWindowZoomed -- 4885 * 4886 * Ask Carbon if the given window is in the zoomed out state. Because 4887 * dragging & growing a window can change the Carbon zoom state, we 4888 * cannot rely on wmInfoPtr->hints.initial_state for this information. 4889 * 4890 * Results: 4891 * True if window is zoomed out, false otherwise. 4892 * 4893 * Side effects: 4894 * None. 4895 * 4896 *---------------------------------------------------------------------- 4897 */ 4898 4899MODULE_SCOPE int 4900TkMacOSXIsWindowZoomed( 4901 TkWindow *winPtr) 4902{ 4903 return [TkMacOSXDrawableWindow(winPtr->window) isZoomed]; 4904} 4905 4906/* 4907 *---------------------------------------------------------------------- 4908 * 4909 * TkMacOSXZoomToplevel -- 4910 * 4911 * The function is invoked when the user clicks in the zoom region of a 4912 * Tk window or when the window state is set/unset to "zoomed" manually. 4913 * If the window is to be zoomed (in or out), the window size is changed 4914 * and events are generated to let Tk know what happened. 4915 * 4916 * Results: 4917 * True if events were placed on event queue, false otherwise. 4918 * 4919 * Side effects: 4920 * The window may be resized & events placed on Tk's queue. 4921 * 4922 *---------------------------------------------------------------------- 4923 */ 4924 4925int 4926TkMacOSXZoomToplevel( 4927 void *whichWindow, /* The Macintosh window to zoom. */ 4928 short zoomPart) /* Either inZoomIn or inZoomOut */ 4929{ 4930 NSWindow *window = whichWindow; 4931 TkWindow *winPtr = TkMacOSXGetTkWindow(window); 4932 WmInfo *wmPtr; 4933 4934 if (!winPtr || !winPtr->wmInfoPtr) { 4935 return false; 4936 } 4937 wmPtr = winPtr->wmInfoPtr; 4938 if ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) && 4939 (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) { 4940 return false; 4941 } 4942 4943 /* 4944 * Do nothing if already in desired zoom state. 4945 */ 4946 4947 if (![window isZoomed] == (zoomPart == inZoomIn)) { 4948 return false; 4949 } 4950 [window zoom:NSApp]; 4951 wmPtr->hints.initial_state = 4952 (zoomPart == inZoomIn ? NormalState : ZoomState); 4953 return true; 4954} 4955 4956/* 4957 *---------------------------------------------------------------------- 4958 * 4959 * TkUnsupported1Cmd -- 4960 * 4961 * This procedure is invoked to process the 4962 * "::tk::unsupported::MacWindowStyle" Tcl command. This command allows 4963 * you to set the style of decoration for a Macintosh window. 4964 * 4965 * Results: 4966 * A standard Tcl result. 4967 * 4968 * Side effects: 4969 * Changes the style of a new Mac window. 4970 * 4971 *---------------------------------------------------------------------- 4972 */ 4973 4974/* ARGSUSED */ 4975int 4976TkUnsupported1ObjCmd( 4977 ClientData clientData, /* Main window associated with interpreter. */ 4978 Tcl_Interp *interp, /* Current interpreter. */ 4979 int objc, /* Number of arguments. */ 4980 Tcl_Obj *const objv[]) /* Argument objects. */ 4981{ 4982 static const char *subcmds[] = { 4983 "style", NULL 4984 }; 4985 enum SubCmds { 4986 TKMWS_STYLE 4987 }; 4988 Tk_Window tkwin = clientData; 4989 TkWindow *winPtr; 4990 int index; 4991 4992 if (objc < 3) { 4993 Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?"); 4994 return TCL_ERROR; 4995 } 4996 4997 winPtr = (TkWindow *) 4998 Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); 4999 if (winPtr == NULL) { 5000 return TCL_ERROR; 5001 } 5002 if (!(winPtr->flags & TK_TOP_LEVEL)) { 5003 Tcl_ResetResult(interp); 5004 Tcl_AppendResult(interp, "window \"", winPtr->pathName, 5005 "\" isn't a top-level window", NULL); 5006 return TCL_ERROR; 5007 } 5008 5009 if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0, 5010 &index) != TCL_OK) { 5011 return TCL_ERROR; 5012 } 5013 if (((enum SubCmds) index) == TKMWS_STYLE) { 5014 if ((objc < 3) || (objc > 5)) { 5015 Tcl_WrongNumArgs(interp, 2, objv, "window ?class attributes?"); 5016 return TCL_ERROR; 5017 } 5018 return WmWinStyle(interp, winPtr, objc, objv); 5019 } 5020 /* won't be reached */ 5021 return TCL_ERROR; 5022} 5023 5024/* 5025 *---------------------------------------------------------------------- 5026 * 5027 * WmWinStyle -- 5028 * 5029 * This procedure is invoked to process the 5030 * "::tk::unsupported::MacWindowStyle style" subcommand. This command 5031 * allows you to set the style of decoration for a Macintosh window. 5032 * 5033 * Results: 5034 * A standard Tcl result. 5035 * 5036 * Side effects: 5037 * Changes the style of a new Mac window. 5038 * 5039 *---------------------------------------------------------------------- 5040 */ 5041 5042static int 5043WmWinStyle( 5044 Tcl_Interp *interp, /* Current interpreter. */ 5045 TkWindow *winPtr, /* Window to be manipulated. */ 5046 int objc, /* Number of arguments. */ 5047 Tcl_Obj * const objv[]) /* Argument objects. */ 5048{ 5049 struct StrIntMap { 5050 const char *strValue; 5051 UInt64 intValue; 5052 }; 5053 static const struct StrIntMap classMap[] = { 5054 { "alert", kAlertWindowClass }, 5055 { "moveableAlert", kMovableAlertWindowClass }, 5056 { "modal", kModalWindowClass }, 5057 { "moveableModal", kMovableModalWindowClass }, 5058 { "floating", kFloatingWindowClass }, 5059 { "document", kDocumentWindowClass }, 5060 { "utility", kUtilityWindowClass }, 5061 { "help", kHelpWindowClass }, 5062 { "sheet", kSheetWindowClass }, 5063 { "toolbar", kToolbarWindowClass }, 5064 { "plain", kPlainWindowClass }, 5065 { "overlay", kOverlayWindowClass }, 5066 { "sheetAlert", kSheetAlertWindowClass }, 5067 { "altPlain", kAltPlainWindowClass }, 5068 { "simple", kSimpleWindowClass }, 5069 { "drawer", kDrawerWindowClass }, 5070 { NULL } 5071 }; 5072 static const struct StrIntMap compositeAttrMap[] = { 5073 { "none", kWindowNoAttributes }, 5074 { "standardDocument", kWindowStandardDocumentAttributes }, 5075 { "standardFloating", kWindowStandardFloatingAttributes }, 5076 { "fullZoom", kWindowFullZoomAttribute }, 5077 { NULL } 5078 }; 5079 static const struct StrIntMap attrMap[] = { 5080 { "closeBox", kWindowCloseBoxAttribute }, 5081 { "horizontalZoom", kWindowHorizontalZoomAttribute }, 5082 { "verticalZoom", kWindowVerticalZoomAttribute }, 5083 { "collapseBox", kWindowCollapseBoxAttribute }, 5084 { "resizable", kWindowResizableAttribute }, 5085 { "sideTitlebar", kWindowSideTitlebarAttribute }, 5086 { "toolbarButton", kWindowToolbarButtonAttribute }, 5087 { "unifiedTitleAndToolbar", kWindowUnifiedTitleAndToolbarAttribute }, 5088 { "metal", kWindowMetalAttribute }, 5089 { "noTitleBar", kWindowNoTitleBarAttribute }, 5090 { "texturedSquareCorners", kWindowTexturedSquareCornersAttribute }, 5091 { "metalNoContentSeparator", kWindowMetalNoContentSeparatorAttribute }, 5092 { "doesNotCycle", kWindowDoesNotCycleAttribute }, 5093 { "noUpdates", kWindowNoUpdatesAttribute }, 5094 { "noActivates", kWindowNoActivatesAttribute }, 5095 { "opaqueForEvents", kWindowOpaqueForEventsAttribute }, 5096 { "noShadow", kWindowNoShadowAttribute }, 5097 { "hideOnSuspend", kWindowHideOnSuspendAttribute }, 5098 { "hideOnFullScreen", kWindowHideOnFullScreenAttribute }, 5099 { "inWindowMenu", kWindowInWindowMenuAttribute }, 5100 { "liveResize", kWindowLiveResizeAttribute }, 5101 { "ignoreClicks", kWindowIgnoreClicksAttribute }, 5102 { "noConstrain", kWindowNoConstrainAttribute }, 5103 { "doesNotHide", tkWindowDoesNotHideAttribute }, 5104 { "canJoinAllSpaces", tkCanJoinAllSpacesAttribute }, 5105 { "moveToActiveSpace", tkMoveToActiveSpaceAttribute }, 5106 { "nonActivating", tkNonactivatingPanelAttribute }, 5107 { "hud", tkHUDWindowAttribute }, 5108 { NULL } 5109 }; 5110 int index, i; 5111 WmInfo *wmPtr = winPtr->wmInfoPtr; 5112 5113 if (objc == 3) { 5114 Tcl_Obj *attributeList, *newResult = NULL; 5115 UInt64 attributes; 5116 5117 for (i = 0; classMap[i].strValue != NULL; i++) { 5118 if (wmPtr->macClass == classMap[i].intValue) { 5119 newResult = Tcl_NewStringObj(classMap[i].strValue, -1); 5120 break; 5121 } 5122 } 5123 if (newResult == NULL) { 5124 Tcl_Panic("invalid class"); 5125 } 5126 5127 attributeList = Tcl_NewListObj(0, NULL); 5128 attributes = wmPtr->attributes; 5129 5130 for (i = 0; compositeAttrMap[i].strValue != NULL; i++) { 5131 UInt64 intValue = compositeAttrMap[i].intValue; 5132 5133 if (intValue && (attributes & intValue) == intValue) { 5134 Tcl_ListObjAppendElement(interp, attributeList, 5135 Tcl_NewStringObj(compositeAttrMap[i].strValue, 5136 -1)); 5137 attributes &= ~intValue; 5138 break; 5139 } 5140 } 5141 for (i = 0; attrMap[i].strValue != NULL; i++) { 5142 if (attributes & attrMap[i].intValue) { 5143 Tcl_ListObjAppendElement(interp, attributeList, 5144 Tcl_NewStringObj(attrMap[i].strValue, -1)); 5145 } 5146 } 5147 Tcl_ListObjAppendElement(interp, newResult, attributeList); 5148 Tcl_SetObjResult(interp, newResult); 5149 } else { 5150 int attrObjc; 5151 Tcl_Obj **attrObjv = NULL; 5152 WindowClass macClass; 5153 UInt64 oldAttributes = wmPtr->attributes; 5154 int oldFlags = wmPtr->flags; 5155 5156 if (Tcl_GetIndexFromObjStruct(interp, objv[3], classMap, 5157 sizeof(struct StrIntMap), "class", 0, &index) != TCL_OK) { 5158 goto badClassAttrs; 5159 } 5160 macClass = classMap[index].intValue; 5161 if (objc == 5) { 5162 if (Tcl_ListObjGetElements(interp, objv[4], &attrObjc, &attrObjv) 5163 != TCL_OK) { 5164 goto badClassAttrs; 5165 } 5166 wmPtr->attributes = kWindowNoAttributes; 5167 for (i = 0; i < attrObjc; i++) { 5168 if (Tcl_GetIndexFromObjStruct(interp, attrObjv[i], 5169 compositeAttrMap, sizeof(struct StrIntMap), 5170 "attribute", 0, &index) == TCL_OK) { 5171 wmPtr->attributes |= compositeAttrMap[index].intValue; 5172 } else if (Tcl_GetIndexFromObjStruct(interp, attrObjv[i], 5173 attrMap, sizeof(struct StrIntMap), 5174 "attribute", 0, &index) == TCL_OK) { 5175 Tcl_ResetResult(interp); 5176 wmPtr->attributes |= attrMap[index].intValue; 5177 } else { 5178 goto badClassAttrs; 5179 } 5180 } 5181 } else { 5182 wmPtr->attributes = macClassAttrs[macClass].defaultAttrs; 5183 } 5184 wmPtr->attributes &= (tkAlwaysValidAttributes | 5185 macClassAttrs[macClass].validAttrs); 5186 wmPtr->flags |= macClassAttrs[macClass].flags; 5187 wmPtr->macClass = macClass; 5188 ApplyWindowAttributeFlagChanges(winPtr, NULL, oldAttributes, oldFlags, 5189 0, 1); 5190 return TCL_OK; 5191 5192 badClassAttrs: 5193 wmPtr->attributes = oldAttributes; 5194 return TCL_ERROR; 5195 } 5196 return TCL_OK; 5197} 5198 5199/* 5200 *---------------------------------------------------------------------- 5201 * 5202 * TkpMakeMenuWindow -- 5203 * 5204 * Configure the window to be either a undecorated pull-down (or pop-up) 5205 * menu, or as a toplevel floating menu (palette). 5206 * 5207 * Results: 5208 * None. 5209 * 5210 * Side effects: 5211 * Changes the style bit used to create a new Mac toplevel. 5212 * 5213 *---------------------------------------------------------------------- 5214 */ 5215 5216void 5217TkpMakeMenuWindow( 5218 Tk_Window tkwin, /* New window. */ 5219 int transient) /* 1 means menu is only posted briefly as a 5220 * popup or pulldown or cascade. 0 means menu 5221 * is always visible, e.g. as a floating 5222 * menu. */ 5223{ 5224 TkWindow *winPtr = (TkWindow *) tkwin; 5225 5226 if (transient) { 5227 winPtr->wmInfoPtr->macClass = kSimpleWindowClass; 5228 winPtr->wmInfoPtr->attributes = kWindowNoActivatesAttribute; 5229 } else { 5230 winPtr->wmInfoPtr->macClass = kFloatingWindowClass; 5231 winPtr->wmInfoPtr->attributes = kWindowStandardFloatingAttributes; 5232 winPtr->wmInfoPtr->flags |= WM_WIDTH_NOT_RESIZABLE; 5233 winPtr->wmInfoPtr->flags |= WM_HEIGHT_NOT_RESIZABLE; 5234 } 5235} 5236 5237/* 5238 *---------------------------------------------------------------------- 5239 * 5240 * TkMacOSXMakeRealWindowExist -- 5241 * 5242 * This function finally creates the real Macintosh window that the Mac 5243 * actually understands. 5244 * 5245 * Results: 5246 * None. 5247 * 5248 * Side effects: 5249 * A new Macintosh toplevel is created. 5250 * 5251 *---------------------------------------------------------------------- 5252 */ 5253 5254void 5255TkMacOSXMakeRealWindowExist( 5256 TkWindow *winPtr) /* Tk window. */ 5257{ 5258 WmInfo *wmPtr = winPtr->wmInfoPtr; 5259 MacDrawable *macWin; 5260 5261 if (TkMacOSXHostToplevelExists(winPtr)) { 5262 return; 5263 } 5264 5265 macWin = (MacDrawable *) winPtr->window; 5266 5267 /* 5268 * If this is embedded, make sure its container's toplevel exists, 5269 * then return... 5270 */ 5271 5272 if (Tk_IsEmbedded(winPtr)) { 5273 TkWindow *contWinPtr = TkpGetOtherWindow(winPtr); 5274 5275 if (contWinPtr != NULL) { 5276 TkMacOSXMakeRealWindowExist( 5277 contWinPtr->privatePtr->toplevel->winPtr); 5278 macWin->flags |= TK_HOST_EXISTS; 5279 return; 5280 } 5281 5282 if (tkMacOSXEmbedHandler == NULL) { 5283 Tcl_Panic("TkMacOSXMakeRealWindowExist could not find container"); 5284 } 5285 if (tkMacOSXEmbedHandler->containerExistProc && 5286 tkMacOSXEmbedHandler->containerExistProc((Tk_Window) winPtr) 5287 != TCL_OK) { 5288 Tcl_Panic("ContainerExistProc could not make container"); 5289 } 5290 return; 5291 5292 /* 5293 * TODO: Here we should handle out of process embedding. 5294 */ 5295 } 5296 5297 WindowClass macClass = wmPtr->macClass; 5298 wmPtr->attributes &= (tkAlwaysValidAttributes | 5299 macClassAttrs[macClass].validAttrs); 5300 wmPtr->flags |= macClassAttrs[macClass].flags | 5301 ((wmPtr->attributes & kWindowResizableAttribute) ? 0 : 5302 WM_WIDTH_NOT_RESIZABLE|WM_HEIGHT_NOT_RESIZABLE); 5303 UInt64 attributes = (wmPtr->attributes & 5304 ~macClassAttrs[macClass].forceOffAttrs) | 5305 macClassAttrs[macClass].forceOnAttrs; 5306 NSUInteger styleMask = macClassAttrs[macClass].styleMask | 5307 ((attributes & kWindowNoTitleBarAttribute) ? 0 : NSTitledWindowMask) | 5308 ((attributes & kWindowCloseBoxAttribute) ? NSClosableWindowMask : 0) | 5309 ((attributes & kWindowCollapseBoxAttribute) ? 5310 NSMiniaturizableWindowMask : 0) | 5311 ((attributes & kWindowResizableAttribute) ? NSResizableWindowMask : 0) | 5312 ((attributes & kWindowMetalAttribute) ? 5313 NSTexturedBackgroundWindowMask : 0) | 5314 ((attributes & kWindowUnifiedTitleAndToolbarAttribute) ? 5315 NSUnifiedTitleAndToolbarWindowMask : 0) | 5316 ((attributes & kWindowSideTitlebarAttribute) ? 1 << 9 : 0) | 5317 (attributes >> WM_NSMASK_SHIFT); 5318 Class winClass = (macClass == kDrawerWindowClass ? [NSDrawerWindow class] : 5319 (styleMask & (NSUtilityWindowMask|NSDocModalWindowMask| 5320 NSNonactivatingPanelMask|NSHUDWindowMask)) ? [NSPanel class] : 5321 [TKWindow class]); 5322 NSRect structureRect = [winClass frameRectForContentRect:NSZeroRect 5323 styleMask:styleMask]; 5324 NSRect contentRect = NSMakeRect(5 - structureRect.origin.x, 5325 tkMacOSXZeroScreenHeight - (tkMacOSXZeroScreenTop + 5 + 5326 structureRect.origin.y + structureRect.size.height + 200), 200, 200); 5327 NSWindow *window = [[winClass alloc] initWithContentRect:contentRect 5328 styleMask:styleMask backing:NSBackingStoreBuffered defer:YES]; 5329 if (!window) { 5330 Tcl_Panic("couldn't allocate new Mac window"); 5331 } 5332 TkMacOSXMakeUncollectable(window); 5333 TKContentView *contentView = [[TKContentView alloc] 5334 initWithFrame:NSZeroRect]; 5335 [window setContentView:contentView]; 5336 [contentView release]; 5337 [window setDelegate:NSApp]; 5338 [window setAcceptsMouseMovedEvents:YES]; 5339 [window setReleasedWhenClosed:NO]; 5340 [window setAutodisplay:NO]; 5341 if (styleMask & NSUtilityWindowMask) { 5342 [(NSPanel*)window setFloatingPanel:YES]; 5343 } 5344 if ((styleMask & (NSTexturedBackgroundWindowMask|NSHUDWindowMask)) && 5345 !(styleMask & NSDocModalWindowMask)) { 5346 /* 5347 * Workaround for [Bug 2824538]: Texured windows are draggable 5348 * from opaque content. 5349 */ 5350 [window setMovableByWindowBackground:NO]; 5351 } 5352 [window setDocumentEdited:NO]; 5353 wmPtr->window = window; 5354 macWin->view = contentView; 5355 TkMacOSXApplyWindowAttributes(winPtr, window); 5356 5357 NSRect geometry = InitialWindowBounds(winPtr, window); 5358 geometry.size.width += structureRect.size.width; 5359 geometry.size.height += structureRect.size.height; 5360 geometry.origin.y = tkMacOSXZeroScreenHeight - (geometry.origin.y + 5361 geometry.size.height); 5362 [window setFrame:geometry display:NO]; 5363 5364 TkMacOSXRegisterOffScreenWindow((Window) macWin, window); 5365 macWin->flags |= TK_HOST_EXISTS; 5366} 5367 5368/* 5369 *---------------------------------------------------------------------- 5370 * 5371 * TkMacOSXRegisterOffScreenWindow -- 5372 * 5373 * This function adds the passed in Off Screen Port to the hash table 5374 * that maps Mac windows to root X windows. 5375 * 5376 * Results: 5377 * None. 5378 * 5379 * Side effects: 5380 * An entry is added to the windowTable hash table. 5381 * 5382 *---------------------------------------------------------------------- 5383 */ 5384 5385void 5386TkMacOSXRegisterOffScreenWindow( 5387 Window window, /* Window structure. */ 5388 void *portPtr) /* Pointer to a Mac Window. */ 5389{ 5390 Tcl_HashEntry *valueHashPtr; 5391 int isNew; 5392 5393 if (!windowHashInit) { 5394 Tcl_InitHashTable(&windowTable, TCL_ONE_WORD_KEYS); 5395 windowHashInit = true; 5396 } 5397 valueHashPtr = Tcl_CreateHashEntry(&windowTable, (char *) portPtr, &isNew); 5398 if (!isNew) { 5399 Tcl_Panic("Same macintosh window allocated twice!"); 5400 } 5401 Tcl_SetHashValue(valueHashPtr, window); 5402} 5403 5404/* 5405 *---------------------------------------------------------------------- 5406 * 5407 * TkMacOSXUnregisterMacWindow -- 5408 * 5409 * Given a macintosh port window, this function removes the association 5410 * between this window and the root X window that Tk cares about. 5411 * 5412 * Results: 5413 * None. 5414 * 5415 * Side effects: 5416 * An entry is removed from the windowTable hash table. 5417 * 5418 *---------------------------------------------------------------------- 5419 */ 5420 5421void 5422TkMacOSXUnregisterMacWindow( 5423 void *macWinPtr) /* Reference to a Mac Window */ 5424{ 5425 Tcl_HashEntry *entryPtr; 5426 5427 if (!windowHashInit) { 5428 Tcl_Panic("TkMacOSXUnregisterMacWindow: unmapping before inited"); 5429 } 5430 entryPtr = Tcl_FindHashEntry(&windowTable, macWinPtr); 5431 if (!entryPtr) { 5432 TkMacOSXDbgMsg("Failed to find window %p", macWinPtr); 5433 } else { 5434 Tcl_DeleteHashEntry(entryPtr); 5435 } 5436} 5437 5438/* 5439 *---------------------------------------------------------------------- 5440 * 5441 * TkMacOSXSetScrollbarGrow -- 5442 * 5443 * Sets a flag for a toplevel window indicating that the passed Tk 5444 * scrollbar window will display the grow region for the toplevel window. 5445 * 5446 * Results: 5447 * None. 5448 * 5449 * Side effects: 5450 * A flag is set int windows toplevel parent. 5451 * 5452 *---------------------------------------------------------------------- 5453 */ 5454 5455void 5456TkMacOSXSetScrollbarGrow( 5457 TkWindow *winPtr, /* Tk scrollbar window. */ 5458 int flag) /* Boolean value true or false. */ 5459{ 5460 if (flag) { 5461 winPtr->privatePtr->toplevel->flags |= TK_SCROLLBAR_GROW; 5462 winPtr->privatePtr->toplevel->winPtr->wmInfoPtr->scrollWinPtr = winPtr; 5463 } else if (winPtr->privatePtr->toplevel->winPtr->wmInfoPtr->scrollWinPtr 5464 == winPtr) { 5465 winPtr->privatePtr->toplevel->flags &= ~TK_SCROLLBAR_GROW; 5466 winPtr->privatePtr->toplevel->winPtr->wmInfoPtr->scrollWinPtr = NULL; 5467 } 5468} 5469 5470/* 5471 *---------------------------------------------------------------------- 5472 * 5473 * TkWmFocusToplevel -- 5474 * 5475 * This is a utility procedure invoked by focus-management code. It 5476 * exists because of the extra wrapper windows that exist under Unix; its 5477 * job is to map from wrapper windows to the corresponding toplevel 5478 * windows. On PCs and Macs there are no wrapper windows so no mapping is 5479 * necessary; this procedure just determines whether a window is a 5480 * toplevel or not. 5481 * 5482 * Results: 5483 * If winPtr is a toplevel window, returns the pointer to the window; 5484 * otherwise returns NULL. 5485 * 5486 * Side effects: 5487 * None. 5488 * 5489 *---------------------------------------------------------------------- 5490 */ 5491 5492TkWindow * 5493TkWmFocusToplevel( 5494 TkWindow *winPtr) /* Window that received a focus-related 5495 * event. */ 5496{ 5497 if (!(winPtr->flags & TK_TOP_LEVEL)) { 5498 return NULL; 5499 } 5500 return winPtr; 5501} 5502 5503/* 5504 *---------------------------------------------------------------------- 5505 * 5506 * TkpGetWrapperWindow -- 5507 * 5508 * This is a utility procedure invoked by focus-management code. It maps 5509 * to the wrapper for a top-level, which is just the same as the 5510 * top-level on Macs and PCs. 5511 * 5512 * Results: 5513 * If winPtr is a toplevel window, returns the pointer to the window; 5514 * otherwise returns NULL. 5515 * 5516 * Side effects: 5517 * None. 5518 * 5519 *---------------------------------------------------------------------- 5520 */ 5521 5522TkWindow * 5523TkpGetWrapperWindow( 5524 TkWindow *winPtr) /* Window that received a focus-related 5525 * event. */ 5526{ 5527 if (!(winPtr->flags & TK_TOP_LEVEL)) { 5528 return NULL; 5529 } 5530 return winPtr; 5531} 5532 5533/* 5534 *---------------------------------------------------------------------- 5535 * 5536 * TkpWmSetState -- 5537 * 5538 * Sets the window manager state for the wrapper window of a given 5539 * toplevel window. 5540 * 5541 * Results: 5542 * None. 5543 * 5544 * Side effects: 5545 * May maximize, minimize, restore, or withdraw a window. 5546 * 5547 *---------------------------------------------------------------------- 5548 */ 5549 5550void 5551TkpWmSetState( 5552 TkWindow *winPtr, /* Toplevel window to operate on. */ 5553 int state) /* One of IconicState, ZoomState, NormalState, 5554 * or WithdrawnState. */ 5555{ 5556 WmInfo *wmPtr = winPtr->wmInfoPtr; 5557 NSWindow *macWin; 5558 5559 wmPtr->hints.initial_state = state; 5560 if (wmPtr->flags & WM_NEVER_MAPPED) { 5561 return; 5562 } 5563 5564 macWin = TkMacOSXDrawableWindow(winPtr->window); 5565 5566 if (state == WithdrawnState) { 5567 Tk_UnmapWindow((Tk_Window) winPtr); 5568 } else if (state == IconicState) { 5569 /* 5570 * The window always gets unmapped. If we can show the icon version of 5571 * the window we also collapse it. 5572 */ 5573 5574 if (macWin && ([macWin styleMask] & NSMiniaturizableWindowMask) && 5575 ![macWin isMiniaturized]) { 5576 [macWin miniaturize:NSApp]; 5577 } 5578 Tk_UnmapWindow((Tk_Window) winPtr); 5579 } else if (state == NormalState || state == ZoomState) { 5580 Tk_MapWindow((Tk_Window) winPtr); 5581 if (macWin && ([macWin styleMask] & NSMiniaturizableWindowMask) && 5582 [macWin isMiniaturized]) { 5583 [macWin deminiaturize:NSApp]; 5584 } 5585 TkMacOSXZoomToplevel(macWin, state == NormalState ? inZoomIn : 5586 inZoomOut); 5587 } 5588} 5589 5590/* 5591 *---------------------------------------------------------------------- 5592 * 5593 * TkpIsWindowFloating -- 5594 * 5595 * Returns 1 if a window is floating, 0 otherwise. 5596 * 5597 * Results: 5598 * 1 or 0 depending on window's floating attribute. 5599 * 5600 * Side effects: 5601 * None. 5602 * 5603 *---------------------------------------------------------------------- 5604 */ 5605 5606int 5607TkpIsWindowFloating( 5608 void *wRef) 5609{ 5610 return [(NSWindow *)wRef level] == kCGFloatingWindowLevel; 5611} 5612 5613/* 5614 *---------------------------------------------------------------------- 5615 * 5616 * TkMacOSXWindowClass -- 5617 * 5618 * Returns OS X window class of window 5619 * 5620 * Results: 5621 * 1 or 0 depending on window's floating attribute. 5622 * 5623 * Side effects: 5624 * None. 5625 * 5626 *---------------------------------------------------------------------- 5627 */ 5628 5629MODULE_SCOPE WindowClass 5630TkMacOSXWindowClass( 5631 TkWindow *winPtr) 5632{ 5633 return winPtr->wmInfoPtr->macClass; 5634} 5635 5636/* 5637 *-------------------------------------------------------------- 5638 * 5639 * TkMacOSXWindowOffset -- 5640 * 5641 * Determines the x and y offset from the orgin of the toplevel window 5642 * dressing (the structure region, i.e. title bar) and the orgin of the 5643 * content area. 5644 * 5645 * Results: 5646 * The x & y offset in pixels. 5647 * 5648 * Side effects: 5649 * None. 5650 * 5651 *---------------------------------------------------------------------- 5652 */ 5653 5654void 5655TkMacOSXWindowOffset( 5656 void *wRef, 5657 int *xOffset, 5658 int *yOffset) 5659{ 5660 TkWindow *winPtr = TkMacOSXGetTkWindow(wRef); 5661 5662 if (winPtr && winPtr->wmInfoPtr) { 5663 *xOffset = winPtr->wmInfoPtr->xInParent; 5664 *yOffset = winPtr->wmInfoPtr->yInParent; 5665 } else { 5666 *xOffset = 0; 5667 *yOffset = 0; 5668 } 5669} 5670 5671/* 5672 *---------------------------------------------------------------------- 5673 * 5674 * TkpGetMS -- 5675 * 5676 * Return a relative time in milliseconds. It doesn't matter when the 5677 * epoch was. 5678 * 5679 * Results: 5680 * Number of milliseconds. 5681 * 5682 * Side effects: 5683 * None. 5684 * 5685 *---------------------------------------------------------------------- 5686 */ 5687 5688unsigned long 5689TkpGetMS(void) 5690{ 5691 Tcl_Time now; 5692 5693 Tcl_GetTime(&now); 5694 return (long) now.sec * 1000 + now.usec / 1000; 5695} 5696 5697/* 5698 *---------------------------------------------------------------------- 5699 * 5700 * XSetInputFocus -- 5701 * 5702 * Change the focus window for the application. 5703 * 5704 * Results: 5705 * None. 5706 * 5707 * Side effects: 5708 * None. 5709 * 5710 *---------------------------------------------------------------------- 5711 */ 5712 5713void 5714XSetInputFocus( 5715 Display* display, 5716 Window focus, 5717 int revert_to, 5718 Time time) 5719{ 5720 /* 5721 * Don't need to do a thing. Tk manages the focus for us. 5722 */ 5723} 5724 5725/* 5726 *---------------------------------------------------------------------- 5727 * 5728 * TkpChangeFocus -- 5729 * 5730 * This procedure is a stub on the Mac because we always own the focus if 5731 * we are a front most application. 5732 * 5733 * Results: 5734 * The return value is the serial number of the command that changed the 5735 * focus. It may be needed by the caller to filter out focus change 5736 * events that were queued before the command. If the procedure doesn't 5737 * actually change the focus then it returns 0. 5738 * 5739 * Side effects: 5740 * None. 5741 * 5742 *---------------------------------------------------------------------- 5743 */ 5744 5745int 5746TkpChangeFocus( 5747 TkWindow *winPtr, /* Window that is to receive the X focus. */ 5748 int force) /* Non-zero means claim the focus even if it 5749 * didn't originally belong to topLevelPtr's 5750 * application. */ 5751{ 5752 /* 5753 * We don't really need to do anything on the Mac. Tk will keep all this 5754 * state for us. 5755 */ 5756 5757 if (winPtr->atts.override_redirect) { 5758 return 0; 5759 } 5760 5761 /* 5762 * Remember the current serial number for the X server and issue a dummy 5763 * server request. This marks the position at which we changed the focus, 5764 * so we can distinguish FocusIn and FocusOut events on either side of the 5765 * mark. 5766 */ 5767 5768 return NextRequest(winPtr->display); 5769} 5770 5771/* 5772 *---------------------------------------------------------------------- 5773 * 5774 * WmStackorderToplevelWrapperMap -- 5775 * 5776 * This procedure will create a table that maps the reparent wrapper X id 5777 * for a toplevel to the TkWindow structure that is wraps. Tk keeps track 5778 * of a mapping from the window X id to the TkWindow structure but that 5779 * does us no good here since we only get the X id of the wrapper window. 5780 * Only those toplevel windows that are mapped have a position in the 5781 * stacking order. 5782 * 5783 * Results: 5784 * None. 5785 * 5786 * Side effects: 5787 * Adds entries to the passed hashtable. 5788 * 5789 *---------------------------------------------------------------------- 5790 */ 5791 5792static void 5793WmStackorderToplevelWrapperMap( 5794 TkWindow *winPtr, /* TkWindow to recurse on */ 5795 Display *display, /* X display of parent window */ 5796 Tcl_HashTable *table) /* Maps mac window to TkWindow */ 5797{ 5798 TkWindow *childPtr; 5799 Tcl_HashEntry *hPtr; 5800 int newEntry; 5801 5802 if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr) 5803 && (winPtr->display == display)) { 5804 hPtr = Tcl_CreateHashEntry(table, 5805 (char*) TkMacOSXDrawableWindow(winPtr->window), &newEntry); 5806 Tcl_SetHashValue(hPtr, winPtr); 5807 } 5808 5809 for (childPtr = winPtr->childList; childPtr != NULL; 5810 childPtr = childPtr->nextPtr) { 5811 WmStackorderToplevelWrapperMap(childPtr, display, table); 5812 } 5813} 5814 5815/* 5816 *---------------------------------------------------------------------- 5817 * 5818 * TkWmStackorderToplevel -- 5819 * 5820 * This procedure returns the stack order of toplevel windows. 5821 * 5822 * Results: 5823 * An array of pointers to tk window objects in stacking order or else 5824 * NULL if there was an error. 5825 * 5826 * Side effects: 5827 * None. 5828 * 5829 *---------------------------------------------------------------------- 5830 */ 5831 5832TkWindow ** 5833TkWmStackorderToplevel( 5834 TkWindow *parentPtr) /* Parent toplevel window. */ 5835{ 5836 TkWindow *childWinPtr, **windows, **window_ptr; 5837 Tcl_HashTable table; 5838 Tcl_HashEntry *hPtr; 5839 Tcl_HashSearch search; 5840 NSInteger windowCount; 5841 NSInteger *windowNumbers; 5842 5843 /* 5844 * Map mac windows to a TkWindow of the wrapped toplevel. 5845 */ 5846 5847 Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS); 5848 WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table); 5849 5850 windows = (TkWindow **) 5851 ckalloc((table.numEntries+1) * sizeof(TkWindow *)); 5852 5853 /* 5854 * Special cases: If zero or one toplevels were mapped there is no need to 5855 * enumerate Windows. 5856 */ 5857 5858 switch (table.numEntries) { 5859 case 0: 5860 windows[0] = NULL; 5861 goto done; 5862 case 1: 5863 hPtr = Tcl_FirstHashEntry(&table, &search); 5864 windows[0] = Tcl_GetHashValue(hPtr); 5865 windows[1] = NULL; 5866 goto done; 5867 } 5868 5869 NSCountWindows(&windowCount); 5870 if (!windowCount) { 5871 ckfree((char *) windows); 5872 windows = NULL; 5873 } else { 5874 window_ptr = windows + table.numEntries; 5875 *window_ptr-- = NULL; 5876 windowNumbers = (NSInteger *) ckalloc(windowCount * sizeof(NSInteger)); 5877 NSWindowList(windowCount, windowNumbers); 5878 for (NSInteger index = 0; index < windowCount; index++) { 5879 NSWindow *w = [NSApp windowWithWindowNumber:windowNumbers[index]]; 5880 5881 if (w) { 5882 hPtr = Tcl_FindHashEntry(&table, (char*) w); 5883 if (hPtr != NULL) { 5884 childWinPtr = Tcl_GetHashValue(hPtr); 5885 *window_ptr-- = childWinPtr; 5886 } 5887 } 5888 } 5889 if (window_ptr != (windows-1)) { 5890 Tcl_Panic("num matched toplevel windows does not equal num " 5891 "children"); 5892 } 5893 ckfree((char *) windowNumbers); 5894 } 5895 5896 done: 5897 Tcl_DeleteHashTable(&table); 5898 return windows; 5899} 5900 5901/* 5902 *---------------------------------------------------------------------- 5903 * 5904 * TkMacOSXApplyWindowAttributes -- 5905 * 5906 * This procedure applies all window attributes to the NSWindow. 5907 * 5908 * Results: 5909 * None. 5910 * 5911 * Side effects: 5912 * None. 5913 * 5914 *---------------------------------------------------------------------- 5915 */ 5916 5917void 5918TkMacOSXApplyWindowAttributes( 5919 TkWindow *winPtr, 5920 NSWindow *macWindow) 5921{ 5922 WmInfo *wmPtr = winPtr->wmInfoPtr; 5923 ApplyWindowAttributeFlagChanges(winPtr, macWindow, 0, 0, 0, 1); 5924 if (wmPtr->master != None || winPtr->atts.override_redirect) { 5925 ApplyMasterOverrideChanges(winPtr, macWindow); 5926 } 5927} 5928 5929/* 5930 *---------------------------------------------------------------------- 5931 * 5932 * ApplyWindowAttributeFlagChanges -- 5933 * 5934 * This procedure applies window attribute and flag changes. 5935 * 5936 * Results: 5937 * None. 5938 * 5939 * Side effects: 5940 * None. 5941 * 5942 *---------------------------------------------------------------------- 5943 */ 5944 5945static void 5946ApplyWindowAttributeFlagChanges( 5947 TkWindow *winPtr, 5948 NSWindow *macWindow, 5949 UInt64 oldAttributes, 5950 int oldFlags, 5951 int create, 5952 int initial) 5953{ 5954 WmInfo *wmPtr = winPtr->wmInfoPtr; 5955 UInt64 newAttributes = ForceAttributes(wmPtr->attributes, wmPtr->macClass); 5956 UInt64 changedAttributes = newAttributes ^ ForceAttributes(oldAttributes, 5957 wmPtr->macClass); 5958 5959 if (changedAttributes || wmPtr->flags != oldFlags || initial) { 5960 if (!macWindow) { 5961 if (winPtr->window == None) { 5962 if (create) { 5963 Tk_MakeWindowExist((Tk_Window) winPtr); 5964 } else { 5965 return; 5966 } 5967 } 5968 if (!TkMacOSXHostToplevelExists(winPtr)) { 5969 if (create) { 5970 TkMacOSXMakeRealWindowExist(winPtr); 5971 } else { 5972 return; 5973 } 5974 } 5975 macWindow = TkMacOSXDrawableWindow(winPtr->window); 5976 } 5977 if ((changedAttributes & kWindowCloseBoxAttribute) || initial) { 5978 [[macWindow standardWindowButton:NSWindowCloseButton] 5979 setEnabled:!!(newAttributes & kWindowCloseBoxAttribute)]; 5980 } 5981 if ((changedAttributes & kWindowCollapseBoxAttribute) || initial) { 5982 [[macWindow standardWindowButton:NSWindowMiniaturizeButton] 5983 setEnabled:!!(newAttributes & kWindowCollapseBoxAttribute)]; 5984 } 5985 if ((changedAttributes & (kWindowResizableAttribute | 5986 kWindowFullZoomAttribute)) || initial) { 5987 [macWindow setShowsResizeIndicator: 5988 !!(newAttributes & kWindowResizableAttribute)]; 5989 [[macWindow standardWindowButton:NSWindowZoomButton] 5990 setEnabled:(newAttributes & kWindowResizableAttribute) && 5991 (newAttributes & kWindowFullZoomAttribute)]; 5992 if (newAttributes & kWindowResizableAttribute) { 5993 wmPtr->flags &= ~(WM_WIDTH_NOT_RESIZABLE | 5994 WM_HEIGHT_NOT_RESIZABLE); 5995 } else { 5996 wmPtr->flags |= (WM_WIDTH_NOT_RESIZABLE | 5997 WM_HEIGHT_NOT_RESIZABLE); 5998 } 5999 WmUpdateGeom(wmPtr, winPtr); 6000 } 6001 if ((changedAttributes & kWindowToolbarButtonAttribute) || initial) { 6002 [macWindow setShowsToolbarButton: 6003 !!(newAttributes & kWindowToolbarButtonAttribute)]; 6004 if ((newAttributes & kWindowToolbarButtonAttribute) && 6005 ![macWindow toolbar]) { 6006 NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@""]; 6007 [toolbar setVisible:NO]; 6008 [macWindow setToolbar:toolbar]; 6009 [toolbar release]; 6010 NSCell *toolbarButtonCell = [[macWindow standardWindowButton: 6011 NSWindowToolbarButton] cell]; 6012 [toolbarButtonCell setTarget:[macWindow contentView]]; 6013 [toolbarButtonCell setAction:@selector(tkToolbarButton:)]; 6014 } 6015 } 6016 if ((changedAttributes & kWindowNoShadowAttribute) || initial) { 6017 [macWindow setHasShadow: 6018 !(newAttributes & kWindowNoShadowAttribute)]; 6019 } 6020 if ((changedAttributes & kWindowHideOnSuspendAttribute) || initial) { 6021 [macWindow setHidesOnDeactivate: 6022 !!(newAttributes & kWindowHideOnSuspendAttribute)]; 6023 } 6024 if ((changedAttributes & kWindowInWindowMenuAttribute) || initial) { 6025 [macWindow setExcludedFromWindowsMenu: 6026 !(newAttributes & kWindowInWindowMenuAttribute)]; 6027 } 6028 if ((changedAttributes & kWindowIgnoreClicksAttribute) || initial) { 6029 [macWindow setIgnoresMouseEvents: 6030 !!(newAttributes & kWindowIgnoreClicksAttribute)]; 6031 } 6032 if ((changedAttributes & tkWindowDoesNotHideAttribute) || initial) { 6033 [macWindow setCanHide: 6034 !(newAttributes & tkWindowDoesNotHideAttribute)]; 6035 } 6036 if ((changedAttributes & (kWindowDoesNotCycleAttribute | 6037 tkCanJoinAllSpacesAttribute | tkMoveToActiveSpaceAttribute)) || 6038 initial) { 6039 NSWindowCollectionBehavior b = NSWindowCollectionBehaviorDefault; 6040 if (newAttributes & tkCanJoinAllSpacesAttribute) { 6041 b |= NSWindowCollectionBehaviorCanJoinAllSpaces; 6042 } else if (newAttributes & tkMoveToActiveSpaceAttribute) { 6043 b |= NSWindowCollectionBehaviorMoveToActiveSpace; 6044 } 6045#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 6046 if (newAttributes & kWindowDoesNotCycleAttribute) { 6047 b |= NSWindowCollectionBehaviorIgnoresCycle; 6048 } else { 6049 b |= NSWindowCollectionBehaviorParticipatesInCycle; 6050 } 6051#endif 6052 [macWindow setCollectionBehavior:b]; 6053#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 6054 if (((changedAttributes & kWindowDoesNotCycleAttribute) || initial) 6055#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 6056 && tkMacOSXMacOSXVersion < 1006 6057#endif 6058 ) { 6059 [macWindow setCanCycle: 6060 !(newAttributes & kWindowDoesNotCycleAttribute)]; 6061 } 6062#endif 6063 } 6064 if ((wmPtr->flags & WM_TOPMOST) != (oldFlags & WM_TOPMOST)) { 6065 [macWindow setLevel:(wmPtr->flags & WM_TOPMOST) ? 6066 kCGUtilityWindowLevel : ([macWindow isKindOfClass: 6067 [NSPanel class]] && [macWindow isFloatingPanel] ? 6068 kCGFloatingWindowLevel : kCGNormalWindowLevel)]; 6069 } 6070 6071 /* 6072 * The change of window class/attributes might have changed the window 6073 * structure widths: 6074 */ 6075 6076 NSRect structureRect = [macWindow frameRectForContentRect:NSZeroRect]; 6077 wmPtr->xInParent = -structureRect.origin.x; 6078 wmPtr->yInParent = structureRect.origin.y + structureRect.size.height; 6079 wmPtr->parentWidth = winPtr->changes.width + structureRect.size.width; 6080 wmPtr->parentHeight = winPtr->changes.height + structureRect.size.height; 6081 } 6082} 6083 6084/* 6085 *---------------------------------------------------------------------- 6086 * 6087 * ApplyMasterOverrideChanges -- 6088 * 6089 * This procedure applies changes to override_redirect or master. 6090 * 6091 * Results: 6092 * None. 6093 * 6094 * Side effects: 6095 * None. 6096 * 6097 *---------------------------------------------------------------------- 6098 */ 6099 6100static void 6101ApplyMasterOverrideChanges( 6102 TkWindow *winPtr, 6103 NSWindow *macWindow) 6104{ 6105 WmInfo *wmPtr = winPtr->wmInfoPtr; 6106 UInt64 oldAttributes = wmPtr->attributes; 6107 int oldFlags = wmPtr->flags; 6108 6109 /* 6110 * FIX: We need an UpdateWrapper equivalent to make this 100% correct 6111 */ 6112 6113 if (winPtr->atts.override_redirect) { 6114 if (wmPtr->macClass == kDocumentWindowClass) { 6115 wmPtr->macClass = kSimpleWindowClass; 6116 wmPtr->attributes = macClassAttrs[kSimpleWindowClass].defaultAttrs; 6117 } 6118 wmPtr->attributes |= kWindowNoActivatesAttribute; 6119 } else { 6120 if (wmPtr->macClass == kSimpleWindowClass && 6121 oldAttributes == kWindowNoActivatesAttribute) { 6122 wmPtr->macClass = kDocumentWindowClass; 6123 wmPtr->attributes = 6124 macClassAttrs[kDocumentWindowClass].defaultAttrs; 6125 } 6126 wmPtr->attributes &= ~kWindowNoActivatesAttribute; 6127 } 6128 if (!macWindow && winPtr->window != None && 6129 TkMacOSXHostToplevelExists(winPtr)) { 6130 macWindow = TkMacOSXDrawableWindow(winPtr->window); 6131 } 6132 if (macWindow) { 6133 if (winPtr->atts.override_redirect && wmPtr->master != None) { 6134 wmPtr->flags |= WM_TOPMOST; 6135 } else { 6136 wmPtr->flags &= ~WM_TOPMOST; 6137 } 6138 NSWindow *parentWindow = [macWindow parentWindow]; 6139 if (wmPtr->master != None) { 6140 TkDisplay *dispPtr = TkGetDisplayList(); 6141 TkWindow *masterWinPtr = (TkWindow *) 6142 Tk_IdToWindow(dispPtr->display, wmPtr->master); 6143 6144 if (masterWinPtr && masterWinPtr->window != None && 6145 TkMacOSXHostToplevelExists(masterWinPtr)) { 6146 NSWindow *masterMacWin = 6147 TkMacOSXDrawableWindow(masterWinPtr->window); 6148 6149 if (masterMacWin && masterMacWin != parentWindow && 6150 (winPtr->flags & TK_MAPPED)) { 6151 if (parentWindow) { 6152 [parentWindow removeChildWindow:macWindow]; 6153 } 6154 [masterMacWin addChildWindow:macWindow 6155 ordered:NSWindowAbove]; 6156 if (wmPtr->flags & WM_TOPMOST) { 6157 [macWindow setLevel:kCGUtilityWindowLevel]; 6158 } 6159 } 6160 } 6161 } else if (parentWindow) { 6162 [parentWindow removeChildWindow:macWindow]; 6163 } 6164 ApplyWindowAttributeFlagChanges(winPtr, macWindow, oldAttributes, 6165 oldFlags, 0, 0); 6166 } 6167} 6168 6169/* 6170 *---------------------------------------------------------------------- 6171 * 6172 * TkMacOSXMakeFullscreen -- 6173 * 6174 * This procedure sets a fullscreen window to the size of the screen. 6175 * 6176 * Results: 6177 * A standard Tcl result. 6178 * 6179 * Side effects: 6180 * None. 6181 * 6182 *---------------------------------------------------------------------- 6183 */ 6184 6185int 6186TkMacOSXMakeFullscreen( 6187 TkWindow *winPtr, 6188 NSWindow *window, 6189 int fullscreen, 6190 Tcl_Interp *interp) 6191{ 6192 WmInfo *wmPtr = winPtr->wmInfoPtr; 6193 int result = TCL_OK, wasFullscreen = (wmPtr->flags & WM_FULLSCREEN); 6194 6195 if (fullscreen) { 6196 int screenWidth = WidthOfScreen(Tk_Screen(winPtr)); 6197 int screenHeight = HeightOfScreen(Tk_Screen(winPtr)); 6198 6199 /* 6200 * Check max width and height if set by the user. 6201 */ 6202 6203 if ((wmPtr->maxWidth > 0 && wmPtr->maxWidth < screenWidth) 6204 || (wmPtr->maxHeight > 0 && wmPtr->maxHeight < screenHeight)) { 6205 if (interp) { 6206 Tcl_AppendResult(interp, 6207 "can't set fullscreen attribute for \"", 6208 winPtr->pathName, 6209 "\": max width/height is too small", NULL); 6210 } 6211 result = TCL_ERROR; 6212 wmPtr->flags &= ~WM_FULLSCREEN; 6213 } else { 6214 NSRect bounds = [window contentRectForFrameRect:[window frame]]; 6215 NSRect screenBounds = NSMakeRect(0, 0, screenWidth, screenHeight); 6216 6217 if (!NSEqualRects(bounds, screenBounds) && !wasFullscreen) { 6218 wmPtr->configX = wmPtr->x; 6219 wmPtr->configY = wmPtr->y; 6220 wmPtr->configAttributes = wmPtr->attributes; 6221 wmPtr->attributes &= ~kWindowResizableAttribute; 6222 ApplyWindowAttributeFlagChanges(winPtr, window, 6223 wmPtr->configAttributes, wmPtr->flags, 1, 0); 6224 wmPtr->flags |= WM_SYNC_PENDING; 6225 [window setFrame:[window frameRectForContentRect: 6226 screenBounds] display:YES]; 6227 wmPtr->flags &= ~WM_SYNC_PENDING; 6228 } 6229 wmPtr->flags |= WM_FULLSCREEN; 6230 } 6231 } else { 6232 wmPtr->flags &= ~WM_FULLSCREEN; 6233 } 6234 TkMacOSXEnterExitFullscreen(winPtr, [window isKeyWindow]); 6235 if (wasFullscreen && !(wmPtr->flags & WM_FULLSCREEN)) { 6236 UInt64 oldAttributes = wmPtr->attributes; 6237 NSRect bounds = NSMakeRect(wmPtr->configX, tkMacOSXZeroScreenHeight - 6238 (wmPtr->configY + wmPtr->yInParent + wmPtr->configHeight), 6239 wmPtr->xInParent + wmPtr->configWidth, 6240 wmPtr->yInParent + wmPtr->configHeight); 6241 6242 wmPtr->attributes |= wmPtr->configAttributes & 6243 kWindowResizableAttribute; 6244 ApplyWindowAttributeFlagChanges(winPtr, window, oldAttributes, 6245 wmPtr->flags, 1, 0); 6246 wmPtr->flags |= WM_SYNC_PENDING; 6247 [window setFrame:[window frameRectForContentRect:bounds] display:YES]; 6248 wmPtr->flags &= ~WM_SYNC_PENDING; 6249 } 6250 return result; 6251} 6252 6253/* 6254 *---------------------------------------------------------------------- 6255 * 6256 * TkMacOSXEnterExitFullscreen -- 6257 * 6258 * This procedure enters or exits fullscreen mode if required. 6259 * 6260 * Results: 6261 * None. 6262 * 6263 * Side effects: 6264 * None. 6265 * 6266 *---------------------------------------------------------------------- 6267 */ 6268 6269void 6270TkMacOSXEnterExitFullscreen( 6271 TkWindow *winPtr, 6272 int active) 6273{ 6274 WmInfo *wmPtr = winPtr->wmInfoPtr; 6275 NSWindow *window = TkMacOSXDrawableWindow(winPtr->window); 6276 SystemUIMode mode; 6277 SystemUIOptions options; 6278 6279 GetSystemUIMode(&mode, &options); 6280 if (window && wmPtr && (wmPtr->flags & WM_FULLSCREEN) && active) { 6281 static SystemUIMode fullscreenMode = 0; 6282 static SystemUIOptions fullscreenOptions = 0; 6283 6284 if (!fullscreenMode) { 6285 fullscreenMode = kUIModeAllSuppressed; 6286 } 6287 if (mode != fullscreenMode) { 6288 ChkErr(SetSystemUIMode, fullscreenMode, fullscreenOptions); 6289 wmPtr->flags |= WM_SYNC_PENDING; 6290 [window setFrame:[window frameRectForContentRect:NSMakeRect(0, 0, 6291 WidthOfScreen(Tk_Screen(winPtr)), 6292 HeightOfScreen(Tk_Screen(winPtr)))] display:YES]; 6293 wmPtr->flags &= ~WM_SYNC_PENDING; 6294 } 6295 } else { 6296 if (mode != kUIModeNormal) { 6297 ChkErr(SetSystemUIMode, kUIModeNormal, 0); 6298 } 6299 } 6300} 6301 6302/* 6303 *---------------------------------------------------------------------- 6304 * 6305 * GetMinSize -- 6306 * 6307 * This function computes the current minWidth and minHeight values for a 6308 * window, taking into account the possibility that they may be 6309 * defaulted. 6310 * 6311 * Results: 6312 * The values at *minWidthPtr and *minHeightPtr are filled in with the 6313 * minimum allowable dimensions of wmPtr's window, in grid units. If the 6314 * requested minimum is smaller than the system required minimum, then 6315 * this function computes the smallest size that will satisfy both the 6316 * system and the grid constraints. 6317 * 6318 * Side effects: 6319 * None. 6320 * 6321 *---------------------------------------------------------------------- 6322 */ 6323 6324static void 6325GetMinSize( 6326 TkWindow *winPtr, /* Toplevel window to operate on. */ 6327 int *minWidthPtr, /* Where to store the current minimum width of 6328 * the window. */ 6329 int *minHeightPtr) /* Where to store the current minimum height 6330 * of the window. */ 6331{ 6332 WmInfo *wmPtr = winPtr->wmInfoPtr; 6333 int minWidth = 1, minHeight = 1; 6334 6335 /* 6336 * Compute the minimum width & height by taking the default client size and 6337 * rounding it up to the nearest grid unit. Return the greater of the 6338 * default minimum and the specified minimum. 6339 */ 6340 6341 switch (wmPtr->macClass) { 6342 case kDocumentWindowClass: 6343 case kMovableAlertWindowClass: 6344 case kMovableModalWindowClass: 6345 minWidth = 72; 6346 if (wmPtr->attributes & kWindowResizableAttribute) { 6347 minHeight = 15; 6348 } 6349 if (wmPtr->attributes & kWindowToolbarButtonAttribute) { 6350 minWidth += 29; 6351 } 6352 break; 6353 case kFloatingWindowClass: 6354 case kUtilityWindowClass: 6355 minWidth = 59; 6356 if (wmPtr->attributes & kWindowResizableAttribute) { 6357 minHeight = 11; 6358 } 6359 if (wmPtr->attributes & kWindowSideTitlebarAttribute) { 6360 int tmp = minWidth; 6361 6362 minWidth = minHeight; 6363 minHeight = tmp; 6364 } else if (wmPtr->attributes & kWindowToolbarButtonAttribute) { 6365 minWidth += 29; 6366 } 6367 break; 6368 default: 6369 if (wmPtr->attributes & kWindowResizableAttribute) { 6370 minWidth = 15; 6371 minHeight = 15; 6372 } 6373 break; 6374 } 6375 6376 if (wmPtr->gridWin != NULL) { 6377 int base = winPtr->reqWidth - (wmPtr->reqGridWidth * wmPtr->widthInc); 6378 6379 if (base < 0) { 6380 base = 0; 6381 } 6382 minWidth = ((minWidth - base) + wmPtr->widthInc-1)/wmPtr->widthInc; 6383 base = winPtr->reqHeight - (wmPtr->reqGridHeight * wmPtr->heightInc); 6384 if (base < 0) { 6385 base = 0; 6386 } 6387 minHeight = ((minHeight - base) + wmPtr->heightInc-1)/wmPtr->heightInc; 6388 } 6389 if (minWidth < wmPtr->minWidth) { 6390 minWidth = wmPtr->minWidth; 6391 } 6392 if (minHeight < wmPtr->minHeight) { 6393 minHeight = wmPtr->minHeight; 6394 } 6395 *minWidthPtr = minWidth; 6396 *minHeightPtr = minHeight; 6397} 6398 6399/* 6400 *---------------------------------------------------------------------- 6401 * 6402 * GetMaxSize -- 6403 * 6404 * This function computes the current maxWidth and maxHeight values for a 6405 * window, taking into account the possibility that they may be 6406 * defaulted. 6407 * 6408 * Results: 6409 * The values at *maxWidthPtr and *maxHeightPtr are filled in with the 6410 * maximum allowable dimensions of wmPtr's window, in grid units. If no 6411 * maximum has been specified for the window, then this function computes 6412 * the largest sizes that will fit on the screen. 6413 * 6414 * Side effects: 6415 * None. 6416 * 6417 *---------------------------------------------------------------------- 6418 */ 6419 6420static void 6421GetMaxSize( 6422 TkWindow *winPtr, /* Toplevel window to operate on. */ 6423 int *maxWidthPtr, /* Where to store the current maximum width of 6424 * the window. */ 6425 int *maxHeightPtr) /* Where to store the current maximum height 6426 * of the window. */ 6427{ 6428 WmInfo *wmPtr = winPtr->wmInfoPtr; 6429 NSRect *maxBounds = (NSRect*)(winPtr->display->screens->ext_data); 6430 6431 if (wmPtr->maxWidth > 0) { 6432 *maxWidthPtr = wmPtr->maxWidth; 6433 } else { 6434 int maxWidth = maxBounds->size.width - wmPtr->xInParent; 6435 6436 if (wmPtr->gridWin != NULL) { 6437 maxWidth = wmPtr->reqGridWidth 6438 + (maxWidth - winPtr->reqWidth)/wmPtr->widthInc; 6439 } 6440 *maxWidthPtr = maxWidth; 6441 } 6442 if (wmPtr->maxHeight > 0) { 6443 *maxHeightPtr = wmPtr->maxHeight; 6444 } else { 6445 int maxHeight = maxBounds->size.height - wmPtr->yInParent; 6446 6447 if (wmPtr->gridWin != NULL) { 6448 maxHeight = wmPtr->reqGridHeight 6449 + (maxHeight - winPtr->reqHeight)/wmPtr->heightInc; 6450 } 6451 *maxHeightPtr = maxHeight; 6452 } 6453} 6454 6455/* 6456 *---------------------------------------------------------------------- 6457 * 6458 * RemapWindows 6459 * 6460 * Adjust parent/child relation ships of the given window hierarchy. 6461 * 6462 * Results: 6463 * none 6464 * 6465 * Side effects: 6466 * keeps windowing system (X11) happy 6467 * 6468 *---------------------------------------------------------------------- 6469 */ 6470 6471static void 6472RemapWindows( 6473 TkWindow *winPtr, 6474 MacDrawable *parentWin) 6475{ 6476 TkWindow *childPtr; 6477 6478 /* 6479 * Remove the OS specific window. It will get rebuilt when the window gets 6480 * Mapped. 6481 */ 6482 6483 if (winPtr->window != None) { 6484 MacDrawable *macWin = (MacDrawable *) winPtr->window; 6485 6486 macWin->toplevel = parentWin->toplevel; 6487 winPtr->flags &= ~TK_MAPPED; 6488#ifdef TK_REBUILD_TOPLEVEL 6489 winPtr->flags |= TK_REBUILD_TOPLEVEL; 6490#endif 6491 } 6492 6493 /* Repeat for all the children */ 6494 for (childPtr = winPtr->childList; childPtr != NULL; 6495 childPtr = childPtr->nextPtr) { 6496 RemapWindows(childPtr, (MacDrawable *) winPtr->window); 6497 } 6498} 6499 6500/* 6501 * Local Variables: 6502 * mode: c 6503 * c-basic-offset: 4 6504 * fill-column: 79 6505 * coding: utf-8 6506 * End: 6507 */ 6508