static void EmbWinLostSlaveProc( ClientData clientData, /* Pointer to record describing window item. */ Tk_Window tkwin) /* Window that was claimed away by another * geometry manager. */ { TkTextEmbWindowClient *client = (TkTextEmbWindowClient*)clientData; TkTextSegment *ewPtr = client->parent; TkTextIndex index; Tcl_HashEntry *hPtr; TkTextEmbWindowClient *loop; Tk_DeleteEventHandler(client->tkwin, StructureNotifyMask, EmbWinStructureProc, (ClientData) client); Tcl_CancelIdleCall(EmbWinDelayedUnmap, (ClientData) client); if (client->textPtr->tkwin != Tk_Parent(tkwin)) { Tk_UnmaintainGeometry(tkwin, client->textPtr->tkwin); } else { Tk_UnmapWindow(tkwin); } hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.sharedTextPtr->windowTable, Tk_PathName(client->tkwin)); Tcl_DeleteHashEntry(hPtr); client->tkwin = NULL; ewPtr->body.ew.tkwin = NULL; /* * Free up the memory allocation for this client. */ loop = ewPtr->body.ew.clients; if (loop == client) { ewPtr->body.ew.clients = client->next; } else { while (loop->next != client) { loop = loop->next; } loop->next = client->next; } ckfree((char *) client); index.tree = ewPtr->body.ew.sharedTextPtr->tree; index.linePtr = ewPtr->body.ew.linePtr; index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr); TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index); TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL, index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY); }
void Ttk_DeleteManager(Ttk_Manager *mgr) { Tk_DeleteEventHandler( mgr->masterWindow, ManagerEventMask, ManagerEventHandler, mgr); while (mgr->nSlaves > 0) { Ttk_ForgetSlave(mgr, mgr->nSlaves - 1); } if (mgr->slaves) { ckfree((ClientData)mgr->slaves); } Tcl_CancelIdleCall(ManagerIdleProc, mgr); ckfree((ClientData)mgr); }
/* ARGSUSED */ static void WinItemLostSlaveProc( ClientData clientData, /* WindowItem structure for slave window that * was stolen away. */ Tk_Window tkwin) /* Tk's handle for the slave window. */ { WindowItem *winItemPtr = clientData; Tk_Window canvasTkwin = Tk_CanvasTkwin(winItemPtr->canvas); Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask, WinItemStructureProc, winItemPtr); if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) { Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin); } Tk_UnmapWindow(winItemPtr->tkwin); winItemPtr->tkwin = NULL; }
static void DeleteWinItem( Tk_Canvas canvas, /* Overall info about widget. */ Tk_Item *itemPtr, /* Item that is being deleted. */ Display *display) /* Display containing window for canvas. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas); if (winItemPtr->tkwin != NULL) { Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask, WinItemStructureProc, winItemPtr); Tk_ManageGeometry(winItemPtr->tkwin, NULL, NULL); if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) { Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin); } Tk_UnmapWindow(winItemPtr->tkwin); } }
static void FocusMapProc( ClientData clientData, /* Toplevel window. */ XEvent *eventPtr) /* Information about event. */ { TkWindow *winPtr = clientData; DisplayFocusInfo *displayFocusPtr; if (eventPtr->type == VisibilityNotify) { displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr); DEBUG(winPtr->dispPtr, ("auto-focussing on %s, force %d\n", winPtr->pathName, displayFocusPtr->forceFocus)); Tk_DeleteEventHandler((Tk_Window) winPtr, VisibilityChangeMask, FocusMapProc, clientData); displayFocusPtr->focusOnMapPtr = NULL; TkSetFocusWin(winPtr, displayFocusPtr->forceFocus); } }
/* ARGSUSED */ static void PlaceLostSlaveProc( ClientData clientData, /* Slave structure for slave window that was * stolen away. */ Tk_Window tkwin) /* Tk's handle for the slave window. */ { register Slave *slavePtr = clientData; TkDisplay *dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr; if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); } Tk_UnmapWindow(tkwin); UnlinkSlave(slavePtr); Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable, (char *) tkwin)); Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc, slavePtr); FreeSlave(slavePtr); }
static void ElementStateEventProc(ClientData clientData, XEvent *ev) { ElementStateTracker *es = (ElementStateTracker *)clientData; Ttk_LayoutNode *node; switch (ev->type) { case MotionNotify : node = Ttk_LayoutIdentify( es->corePtr->layout,ev->xmotion.x,ev->xmotion.y); ActivateElement(es, node); break; case LeaveNotify: ActivateElement(es, 0); if (ev->xcrossing.mode == NotifyGrab) PressElement(es, 0); break; case EnterNotify: node = Ttk_LayoutIdentify( es->corePtr->layout,ev->xcrossing.x,ev->xcrossing.y); ActivateElement(es, node); break; case ButtonPress: node = Ttk_LayoutIdentify( es->corePtr->layout, ev->xbutton.x, ev->xbutton.y); if (node) PressElement(es, node); break; case ButtonRelease: ReleaseElement(es); break; case DestroyNotify: /* Unregister this event handler and free client data. */ Tk_DeleteEventHandler(es->corePtr->tkwin, ElementStateMask, ElementStateEventProc, es); ckfree(clientData); break; } }
static void CursorEventProc(ClientData clientData, XEvent *eventPtr) { WidgetCore *corePtr = (WidgetCore *)clientData; CursorManager *cm = GetCursorManager(corePtr->interp); switch (eventPtr->type) { case DestroyNotify: if (cm->owner == corePtr) LoseCursor(cm, corePtr); Tk_DeleteEventHandler( corePtr->tkwin, CursorEventMask, CursorEventProc, clientData); break; case FocusIn: if (RealFocusEvent(eventPtr->xfocus.detail)) ClaimCursor(cm, corePtr); break; case FocusOut: if (RealFocusEvent(eventPtr->xfocus.detail)) LoseCursor(cm, corePtr); break; } }
void TkTextWinFreeClient( Tcl_HashEntry *hPtr, /* Hash entry corresponding to this client, or * NULL */ TkTextEmbWindowClient *client) /* Client data structure, with the 'tkwin' * field to be cleaned up. */ { if (hPtr != NULL) { /* * (It's possible for there to be no hash table entry for this window, * if an error occurred while creating the window segment but before * the window got added to the table) */ Tcl_DeleteHashEntry(hPtr); } /* * Delete the event handler for the window before destroying the window, * so that EmbWinStructureProc doesn't get called (we'll already do * everything that it would have done, and it will just get confused). */ if (client->tkwin != NULL) { Tk_DeleteEventHandler(client->tkwin, StructureNotifyMask, EmbWinStructureProc, client); Tk_DestroyWindow(client->tkwin); } Tcl_CancelIdleCall(EmbWinDelayedUnmap, client); /* * Free up this client. */ ckfree((char *) client); }
int Tk_CreateConsoleWindow( Tcl_Interp *interp) /* Interpreter to use for prompting. */ { Tcl_Channel chan; ConsoleInfo *info; Tk_Window mainWindow; Tcl_Command token; int result = TCL_OK; int haveConsoleChannel = 1; /* Init an interp with Tcl and Tk */ Tcl_Interp *consoleInterp = Tcl_CreateInterp(); if (Tcl_Init(consoleInterp) != TCL_OK) { goto error; } if (Tk_Init(consoleInterp) != TCL_OK) { goto error; } /* * Fetch the instance data from whatever std channel is a * console channel. If none, create fresh instance data. */ if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDIN)) == &consoleChannelType) { } else if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDOUT)) == &consoleChannelType) { } else if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDERR)) == &consoleChannelType) { } else { haveConsoleChannel = 0; } if (haveConsoleChannel) { ChannelData *data = (ChannelData *) Tcl_GetChannelInstanceData(chan); info = data->info; if (info->consoleInterp) { /* New ConsoleInfo for a new console window */ info = (ConsoleInfo *) ckalloc(sizeof(ConsoleInfo)); info->refCount = 0; /* Update any console channels to make use of the new console */ if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDIN)) == &consoleChannelType) { data = (ChannelData *) Tcl_GetChannelInstanceData(chan); data->info->refCount--; data->info = info; data->info->refCount++; } if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDOUT)) == &consoleChannelType) { data = (ChannelData *) Tcl_GetChannelInstanceData(chan); data->info->refCount--; data->info = info; data->info->refCount++; } if (Tcl_GetChannelType(chan = Tcl_GetStdChannel(TCL_STDERR)) == &consoleChannelType) { data = (ChannelData *) Tcl_GetChannelInstanceData(chan); data->info->refCount--; data->info = info; data->info->refCount++; } } } else { info = (ConsoleInfo *) ckalloc(sizeof(ConsoleInfo)); info->refCount = 0; } info->consoleInterp = consoleInterp; info->interp = interp; Tcl_CallWhenDeleted(consoleInterp, InterpDeleteProc, info); info->refCount++; Tcl_CreateThreadExitHandler(DeleteConsoleInterp, consoleInterp); /* * Add console commands to the interp */ token = Tcl_CreateObjCommand(interp, "console", ConsoleObjCmd, info, ConsoleDeleteProc); info->refCount++; /* * We don't have to count the ref held by the [consoleinterp] command * in the consoleInterp. The ref held by the consoleInterp delete * handler takes care of us. */ Tcl_CreateObjCommand(consoleInterp, "consoleinterp", InterpreterObjCmd, info, NULL); mainWindow = Tk_MainWindow(interp); if (mainWindow) { Tk_CreateEventHandler(mainWindow, StructureNotifyMask, ConsoleEventProc, info); info->refCount++; } Tcl_Preserve(consoleInterp); result = Tcl_GlobalEval(consoleInterp, "source $tk_library/console.tcl"); if (result == TCL_ERROR) { Tcl_SetReturnOptions(interp, Tcl_GetReturnOptions(consoleInterp, result)); Tcl_SetObjResult(interp, Tcl_GetObjResult(consoleInterp)); } Tcl_Release(consoleInterp); if (result == TCL_ERROR) { Tcl_DeleteCommandFromToken(interp, token); mainWindow = Tk_MainWindow(interp); if (mainWindow) { Tk_DeleteEventHandler(mainWindow, StructureNotifyMask, ConsoleEventProc, info); if (--info->refCount <= 0) { ckfree((char *) info); } } goto error; } return TCL_OK; error: Tcl_AddErrorInfo(interp, "\n (creating console window)"); if (!Tcl_InterpDeleted(consoleInterp)) { Tcl_DeleteInterp(consoleInterp); } return TCL_ERROR; }
int Tk_PlaceObjCmd( ClientData clientData, /* Interpreter main window. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tk_Window main_win = clientData; Tk_Window tkwin; Slave *slavePtr; TkDisplay *dispPtr; Tk_OptionTable optionTable; static const char *const optionStrings[] = { "configure", "forget", "info", "slaves", NULL }; enum options { PLACE_CONFIGURE, PLACE_FORGET, PLACE_INFO, PLACE_SLAVES }; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "option|pathName args"); return TCL_ERROR; } /* * Create the option table for this widget class. If it has already been * created, the cached pointer will be returned. */ optionTable = Tk_CreateOptionTable(interp, optionSpecs); /* * Handle special shortcut where window name is first argument. */ if (Tcl_GetString(objv[1])[0] == '.') { if (TkGetWindowFromObj(interp, main_win, objv[1], &tkwin) != TCL_OK) { return TCL_ERROR; } /* * Initialize, if that hasn't been done yet. */ dispPtr = ((TkWindow *) tkwin)->dispPtr; if (!dispPtr->placeInit) { Tcl_InitHashTable(&dispPtr->masterTable, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&dispPtr->slaveTable, TCL_ONE_WORD_KEYS); dispPtr->placeInit = 1; } return ConfigureSlave(interp, tkwin, optionTable, objc-2, objv+2); } /* * Handle more general case of option followed by window name followed by * possible additional arguments. */ if (TkGetWindowFromObj(interp, main_win, objv[2], &tkwin) != TCL_OK) { return TCL_ERROR; } /* * Initialize, if that hasn't been done yet. */ dispPtr = ((TkWindow *) tkwin)->dispPtr; if (!dispPtr->placeInit) { Tcl_InitHashTable(&dispPtr->masterTable, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&dispPtr->slaveTable, TCL_ONE_WORD_KEYS); dispPtr->placeInit = 1; } if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings, sizeof(char *), "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { case PLACE_CONFIGURE: if (objc == 3 || objc == 4) { Tcl_Obj *objPtr; slavePtr = FindSlave(tkwin); if (slavePtr == NULL) { return TCL_OK; } objPtr = Tk_GetOptionInfo(interp, (char *) slavePtr, optionTable, (objc == 4) ? objv[3] : NULL, tkwin); if (objPtr == NULL) { return TCL_ERROR; } Tcl_SetObjResult(interp, objPtr); return TCL_OK; } return ConfigureSlave(interp, tkwin, optionTable, objc-3, objv+3); case PLACE_FORGET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "pathName"); return TCL_ERROR; } slavePtr = FindSlave(tkwin); if (slavePtr == NULL) { return TCL_OK; } if ((slavePtr->masterPtr != NULL) && (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin))) { Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); } UnlinkSlave(slavePtr); Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable, (char *) tkwin)); Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc, slavePtr); Tk_ManageGeometry(tkwin, NULL, NULL); Tk_UnmapWindow(tkwin); FreeSlave(slavePtr); break; case PLACE_INFO: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "pathName"); return TCL_ERROR; } return PlaceInfoCommand(interp, tkwin); case PLACE_SLAVES: { Master *masterPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "pathName"); return TCL_ERROR; } masterPtr = FindMaster(tkwin); if (masterPtr != NULL) { Tcl_Obj *listPtr = Tcl_NewObj(); for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; slavePtr = slavePtr->nextPtr) { Tcl_ListObjAppendElement(NULL, listPtr, TkNewWindowObj(slavePtr->tkwin)); } Tcl_SetObjResult(interp, listPtr); } break; } } return TCL_OK; }
static int EmbWinConfigure( TkText *textPtr, /* Information about text widget that contains * embedded window. */ TkTextSegment *ewPtr, /* Embedded window to be configured. */ int objc, /* Number of strings in objv. */ Tcl_Obj *const objv[]) /* Array of objects describing configuration * options. */ { Tk_Window oldWindow; TkTextEmbWindowClient *client; /* * Copy over client specific value before querying or setting. */ client = EmbWinGetClient(textPtr, ewPtr); if (client != NULL) { ewPtr->body.ew.tkwin = client->tkwin; } else { ewPtr->body.ew.tkwin = NULL; } oldWindow = ewPtr->body.ew.tkwin; if (Tk_SetOptions(textPtr->interp, (char *) &ewPtr->body.ew, ewPtr->body.ew.optionTable, objc, objv, textPtr->tkwin, NULL, NULL) != TCL_OK) { return TCL_ERROR; } if (oldWindow != ewPtr->body.ew.tkwin) { if (oldWindow != NULL) { Tcl_DeleteHashEntry(Tcl_FindHashEntry( &textPtr->sharedTextPtr->windowTable, Tk_PathName(oldWindow))); Tk_DeleteEventHandler(oldWindow, StructureNotifyMask, EmbWinStructureProc, client); Tk_ManageGeometry(oldWindow, NULL, NULL); if (textPtr->tkwin != Tk_Parent(oldWindow)) { Tk_UnmaintainGeometry(oldWindow, textPtr->tkwin); } else { Tk_UnmapWindow(oldWindow); } } if (client != NULL) { client->tkwin = NULL; } if (ewPtr->body.ew.tkwin != NULL) { Tk_Window ancestor, parent; Tcl_HashEntry *hPtr; int isNew; /* * Make sure that the text is either the parent of the embedded * window or a descendant of that parent. Also, don't allow a * top-level window to be managed inside a text. */ parent = Tk_Parent(ewPtr->body.ew.tkwin); for (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) { if (ancestor == parent) { break; } if (Tk_TopWinHierarchy(ancestor)) { badMaster: Tcl_AppendResult(textPtr->interp, "can't embed ", Tk_PathName(ewPtr->body.ew.tkwin), " in ", Tk_PathName(textPtr->tkwin), NULL); ewPtr->body.ew.tkwin = NULL; if (client != NULL) { client->tkwin = NULL; } return TCL_ERROR; } } if (Tk_TopWinHierarchy(ewPtr->body.ew.tkwin) || (ewPtr->body.ew.tkwin == textPtr->tkwin)) { goto badMaster; } if (client == NULL) { /* * Have to make the new client. */ client = (TkTextEmbWindowClient *) ckalloc(sizeof(TkTextEmbWindowClient)); client->next = ewPtr->body.ew.clients; client->textPtr = textPtr; client->tkwin = NULL; client->chunkCount = 0; client->displayed = 0; client->parent = ewPtr; ewPtr->body.ew.clients = client; } client->tkwin = ewPtr->body.ew.tkwin; /* * Take over geometry management for the window, plus create an * event handler to find out when it is deleted. */ Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType, client); Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask, EmbWinStructureProc, client); /* * Special trick! Must enter into the hash table *after* calling * Tk_ManageGeometry: if the window was already managed elsewhere * in this text, the Tk_ManageGeometry call will cause the entry * to be removed, which could potentially lose the new entry. */ hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->windowTable, Tk_PathName(ewPtr->body.ew.tkwin), &isNew); Tcl_SetHashValue(hPtr, ewPtr); } } return TCL_OK; }
static int ConfigureWinItem( Tcl_Interp *interp, /* Used for error reporting. */ Tk_Canvas canvas, /* Canvas containing itemPtr. */ Tk_Item *itemPtr, /* Window item to reconfigure. */ int objc, /* Number of elements in objv. */ Tcl_Obj *const objv[], /* Arguments describing things to configure. */ int flags) /* Flags to pass to Tk_ConfigureWidget. */ { WindowItem *winItemPtr = (WindowItem *) itemPtr; Tk_Window oldWindow; Tk_Window canvasTkwin; oldWindow = winItemPtr->tkwin; canvasTkwin = Tk_CanvasTkwin(canvas); if (TCL_OK != Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, objc, (const char **) objv, (char *) winItemPtr, flags|TK_CONFIG_OBJS)) { return TCL_ERROR; } /* * A few of the options require additional processing. */ if (oldWindow != winItemPtr->tkwin) { if (oldWindow != NULL) { Tk_DeleteEventHandler(oldWindow, StructureNotifyMask, WinItemStructureProc, winItemPtr); Tk_ManageGeometry(oldWindow, NULL, NULL); Tk_UnmaintainGeometry(oldWindow, canvasTkwin); Tk_UnmapWindow(oldWindow); } if (winItemPtr->tkwin != NULL) { Tk_Window ancestor, parent; /* * Make sure that the canvas is either the parent of the window * associated with the item or a descendant of that parent. Also, * don't allow a top-of-hierarchy window to be managed inside a * canvas. */ parent = Tk_Parent(winItemPtr->tkwin); for (ancestor = canvasTkwin ;; ancestor = Tk_Parent(ancestor)) { if (ancestor == parent) { break; } if (((Tk_FakeWin *) ancestor)->flags & TK_TOP_HIERARCHY) { goto badWindow; } } if (((Tk_FakeWin *) winItemPtr->tkwin)->flags & TK_TOP_HIERARCHY){ goto badWindow; } if (winItemPtr->tkwin == canvasTkwin) { goto badWindow; } Tk_CreateEventHandler(winItemPtr->tkwin, StructureNotifyMask, WinItemStructureProc, winItemPtr); Tk_ManageGeometry(winItemPtr->tkwin, &canvasGeomType, winItemPtr); } } if ((winItemPtr->tkwin != NULL) && (itemPtr->state == TK_STATE_HIDDEN)) { if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) { Tk_UnmapWindow(winItemPtr->tkwin); } else { Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin); } } ComputeWindowBbox(canvas, winItemPtr); return TCL_OK; badWindow: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't use %s in a window item of this canvas", Tk_PathName(winItemPtr->tkwin))); Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL); winItemPtr->tkwin = NULL; return TCL_ERROR; }
void TkSetFocusWin( TkWindow *winPtr, /* Window that is to be the new focus for its * display and application. */ int force) /* If non-zero, set the X focus to this window * even if the application doesn't currently * have the X focus. */ { ToplevelFocusInfo *tlFocusPtr; DisplayFocusInfo *displayFocusPtr; TkWindow *topLevelPtr; int allMapped, serial; displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr); /* * If force is set, we should make sure we grab the focus regardless of * the current focus window since under Windows, we may need to take * control away from another application. */ if (winPtr == displayFocusPtr->focusWinPtr && !force) { return; } /* * Find the top-level window for winPtr, then find (or create) a record * for the top-level. Also see whether winPtr and all its ancestors are * mapped. */ allMapped = 1; for (topLevelPtr = winPtr; ; topLevelPtr = topLevelPtr->parentPtr) { if (topLevelPtr == NULL) { /* * The window is being deleted. No point in worrying about giving * it the focus. */ return; } if (!(topLevelPtr->flags & TK_MAPPED)) { allMapped = 0; } if (topLevelPtr->flags & TK_TOP_HIERARCHY) { break; } } /* * If the new focus window isn't mapped, then we can't focus on it (X will * generate an error, for example). Instead, create an event handler that * will set the focus to this window once it gets mapped. At the same * time, delete any old handler that might be around; it's no longer * relevant. */ if (displayFocusPtr->focusOnMapPtr != NULL) { Tk_DeleteEventHandler((Tk_Window) displayFocusPtr->focusOnMapPtr, StructureNotifyMask, FocusMapProc, displayFocusPtr->focusOnMapPtr); displayFocusPtr->focusOnMapPtr = NULL; } if (!allMapped) { Tk_CreateEventHandler((Tk_Window) winPtr, VisibilityChangeMask, FocusMapProc, winPtr); displayFocusPtr->focusOnMapPtr = winPtr; displayFocusPtr->forceFocus = force; return; } for (tlFocusPtr = winPtr->mainPtr->tlFocusPtr; tlFocusPtr != NULL; tlFocusPtr = tlFocusPtr->nextPtr) { if (tlFocusPtr->topLevelPtr == topLevelPtr) { break; } } if (tlFocusPtr == NULL) { tlFocusPtr = (ToplevelFocusInfo *) ckalloc(sizeof(ToplevelFocusInfo)); tlFocusPtr->topLevelPtr = topLevelPtr; tlFocusPtr->nextPtr = winPtr->mainPtr->tlFocusPtr; winPtr->mainPtr->tlFocusPtr = tlFocusPtr; } tlFocusPtr->focusWinPtr = winPtr; /* * Reset the window system's focus window and generate focus events, with * two special cases: * * 1. If the application is embedded and doesn't currently have the focus, * don't set the focus directly. Instead, see if the embedding code can * claim the focus from the enclosing container. * 2. Otherwise, if the application doesn't currently have the focus, * don't change the window system's focus unless it was already in this * application or "force" was specified. */ if ((topLevelPtr->flags & TK_EMBEDDED) && (displayFocusPtr->focusWinPtr == NULL)) { TkpClaimFocus(topLevelPtr, force); } else if ((displayFocusPtr->focusWinPtr != NULL) || force) { /* * Generate events to shift focus between Tk windows. We do this * regardless of what TkpChangeFocus does with the real X focus so * that Tk widgets track focus commands when there is no window * manager. GenerateFocusEvents will set up a serial number marker so * we discard focus events that are triggered by the ChangeFocus. */ serial = TkpChangeFocus(TkpGetWrapperWindow(topLevelPtr), force); if (serial != 0) { displayFocusPtr->focusSerial = serial; } GenerateFocusEvents(displayFocusPtr->focusWinPtr, winPtr); displayFocusPtr->focusWinPtr = winPtr; winPtr->dispPtr->focusPtr = winPtr; } }