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