/*
* tkFocus.c --
*
* This file contains procedures that manage the input
* focus for Tk.
*
* Copyright (c) 1990-1994 The Regents of the University of California.
* Copyright (c) 1994-1995 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* SCCS: @(#) tkFocus.c 1.27 96/02/15 18:53:29
*/
#include "tkInt.h"
/*
* For each top-level window that has ever received the focus, there
* is a record of the following type:
*/
typedef struct TkFocusInfo {
* top-level, it will be given to this
* window. */
* a given application. */
} FocusInfo;
static int focusDebug = 0;
/*
* The following magic value is stored in the "send_event" field of
* FocusIn and FocusOut events that are generated in this file. This
* allows us to separate "real" events coming from the server from
* those that we generated.
*/
/*
* Forward declarations for procedures defined in this file:
*/
int focus));
/*
*--------------------------------------------------------------
*
* Tk_FocusCmd --
*
* This procedure is invoked to process the "focus" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*--------------------------------------------------------------
*/
int
* interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
char c;
/*
* If invoked with no arguments, just return the current focus window.
*/
if (argc == 1) {
if (focusWinPtr != NULL) {
}
return TCL_OK;
}
/*
* If invoked with a single argument beginning with "." then focus
* on that window.
*/
if (argc == 2) {
if (argv[1][0] == 0) {
return TCL_OK;
}
return TCL_ERROR;
}
}
return TCL_OK;
}
}
if (argc != 3) {
return TCL_ERROR;
}
return TCL_ERROR;
}
}
if (argc != 3) {
return TCL_ERROR;
}
if (argv[2][0] == 0) {
return TCL_OK;
}
return TCL_ERROR;
}
if (argc != 3) {
return TCL_ERROR;
}
return TCL_ERROR;
}
return TCL_OK;
}
}
return TCL_OK;
}
}
} else {
"\": must be -displayof, -force, or -lastfor", (char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
* TkFocusFilterEvent --
*
* This procedure is invoked by Tk_HandleEvent when it encounters
* a FocusIn, FocusOut, Enter, or Leave event.
*
* Results:
* A return value of 1 means that Tk_HandleEvent should process
* the event normally (i.e. event handlers should be invoked).
* A return value of 0 means that this event should be ignored.
*
* Side effects:
* Additional events may be generated, and the focus may switch.
*
*--------------------------------------------------------------
*/
int
{
/*
* Design notes: the window manager and X server work together to
* transfer the focus among top-level windows. This procedure takes
* care of transferring the focus from a top-level window to the
* actual window within that top-level that has the focus. We
* do this by synthesizing X events to move the focus around. None
* of the FocusIn and FocusOut events generated by X are ever used
* outside of this procedure; only the synthesized events get through
* to the rest of the application. At one point (e.g. Tk4.0b1) Tk
* used to call X to move the focus from a top-level to one of its
* descendants, then just pass through the events generated by X.
* This approach didn't work very well, for a variety of reasons.
* For example, if X generates the events they go at the back of
* the event queue, which could cause problems if other things
* have already happened, such as moving the focus to yet another
* window.
*/
/*
* If this was a generated event, just turn off the generated
* flag and pass the event through.
*/
return 1;
}
/*
* This was not a generated event. We'll return 1 (so that the
* event will be processed) if it's an Enter or Leave event, and
* 0 (so that the event won't be processed) if it's a FocusIn or
* FocusOut event. Also, skip NotifyPointer, NotifyPointerRoot,
* and NotifyInferior focus events immediately; they're not
* useful and tend to cause confusion.
*/
retValue = 0;
return retValue;
}
} else {
retValue = 1;
return retValue;
}
}
/*
* If winPtr isn't a top-level window than just ignore the event.
*/
return retValue;
}
/*
* If there is a grab in effect and this window is outside the
* grabbed tree, then ignore the event.
*/
return retValue;
}
/*
* Find the FocusInfo structure for the window, and make a new one
* if there isn't one already.
*/
break;
}
}
}
/*
* It is possible that there were outstanding FocusIn and FocusOut
* events on their way to us at the time the focus was changed
* internally with the "focus" command. If so, these events could
* potentially cause us to lose the focus (switch it to the window
* of the last FocusIn event) even though the focus change occurred
* after those events. The following code detects this and puts
* the focus back to the place where it was rightfully set.
*/
if (focusDebug) {
printf("check event serial %d, delta %d\n",
}
if (focusDebug) {
}
}
if (focusDebug) {
}
if (focusDebug) {
}
/*
* If there is no window manager, or if the window manager isn't
* moving the focus around (e.g. the disgusting "NoTitleFocus"
* option has been selected in twm), then we won't get FocusIn
* or FocusOut events. Instead, the "focus" field will be set
* in an Enter event to indicate that we've already got the focus
* when then mouse enters the window (even though we didn't get
* a FocusIn event). Watch for this and grab the focus when it
* happens.
*/
if (focusDebug) {
printf("Focussed implicitly on %s\n",
}
}
/*
* If the pointer just left a window for which we automatically
* claimed the focus on enter, generate FocusOut events. Note:
* dispPtr->implicitWinPtr may not be the same as
* dispPtr->focusWinPtr (e.g. because the "focus" command was
* used to redirect the focus after it arrived at
* dispPtr->implicitWinPtr)!!
*/
if (focusDebug) {
printf("Defocussed implicitly\n");
}
}
}
return retValue;
}
/*
*----------------------------------------------------------------------
*
* SetFocus --
*
* This procedure is invoked to change the focus window for a
* given display in a given application.
*
* Results:
* None.
*
* Side effects:
* Event handlers may be invoked to process the change of
* focus.
*
*----------------------------------------------------------------------
*/
static void
* 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. */
{
return;
}
/*
* Find the top-level window for winPtr, then find (or create)
* a record for the top-level.
*/
if (topLevelPtr == NULL) {
/*
* The window is being deleted. No point in worrying about
* giving it the focus.
*/
return;
}
break;
}
}
break;
}
}
}
/*
* Reset the focus, but only if the application already has the
* input focus or "force" has been specified.
*/
/*
* Reset the focus in X if it has changed top-levels and if the
* new top-level isn't override-redirect (the only reason to
* change the X focus is so that the window manager can redecorate
* the focus window, but if it's override-redirect then it won't
* be decorated anyway; also, changing the focus to menus causes
* all sorts of problems with olvwm: the focus gets lost if
* keyboard traversal is used to move among menus.
*/
(topLevelPtr2 != NULL)
/* Empty loop body. */
}
} else {
topLevelPtr2 = NULL;
}
if ((topLevelPtr2 != topLevelPtr)
}
} else {
/*
* The window isn't mapped, so we can't give it the focus
* right now. Create an event handler that will give it
* the focus as soon as it is mapped.
*/
}
}
}
/*
* Remember the current serial number for the X server and issue
* a dummy server request. This marks the position at which we
* changed the focus, so we can distinguish FocusIn and FocusOut
* events on either side of the mark.
*/
if (focusDebug) {
}
}
/*
*----------------------------------------------------------------------
*
* TkGetFocus --
*
* Given a window, this procedure returns the current focus
* window for its application and display.
*
* Results:
* The return value is a pointer to the window that currently
* has the input focus for the specified application and
* display, or NULL if none.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
TkWindow *
* and a display. */
{
return focusWinPtr;
}
}
/*
*----------------------------------------------------------------------
*
* TkFocusDeadWindow --
*
* This procedure is invoked when it is determined that
* a window is dead. It cleans up focus-related information
* about the window.
*
* Results:
* None.
*
* Side effects:
* Various things get cleaned up and recycled.
*
*----------------------------------------------------------------------
*/
void
* that is being deleted. */
{
/*
* Search for focus records that refer to this window either as
* the top-level window or the current focus window.
*/
/*
* The top-level window is the one being deleted: free
* the focus record and release the focus back to PointerRoot
* if we acquired it implicitly.
*/
if (focusDebug) {
printf("releasing focus to root after %s died\n",
}
}
}
}
} else {
}
break;
/*
* The deleted window had the focus for its top-level:
* move the focus to the top-level itself.
*/
if (focusDebug) {
printf("forwarding focus to %s after %s died\n",
}
}
break;
}
}
}
}
/*
*----------------------------------------------------------------------
*
* GenerateFocusEvents --
*
* This procedure is called to create FocusIn and FocusOut events to
* move the input focus from one window to another.
*
* Results:
* None.
*
* Side effects:
* FocusIn and FocusOut events are generated.
*
*----------------------------------------------------------------------
*/
static void
* be NULL). */
* NULL). */
{
return;
}
}
}
/*
*----------------------------------------------------------------------
*
* ChangeXFocus --
*
* This procedure is invoked to move the official X focus from
* one top-level to another. We do this when the application
* changes the focus window from one top-level to another, in
* order to notify the window manager so that it can highlight
* the new focus top-level.
*
* Results:
* None.
*
* Side effects:
* The official X focus window changes; the application's focus
* window isn't changed by this procedure.
*
*----------------------------------------------------------------------
*/
static void
* the X focus. */
int force; /* Non-zero means claim the focus even
* if it didn't originally belong to
* topLevelPtr's application. */
{
int dummy;
/*
* If the focus was received implicitly, then there's no advantage
* in setting an explicit focus; just return.
*/
return;
}
/*
* Check to make sure that the focus is still in one of the
* windows of this application. Furthermore, grab the server
* to make sure that the focus doesn't change in the middle
* of this operation.
*/
if (!focusDebug) {
}
if (!force) {
goto done;
}
}
/*
* Tell X to change the focus. Ignore errors that occur when changing
* the focus: it is still possible that the window we're focussing
* to could have gotten unmapped, which will generate an error.
*/
if (focusDebug) {
}
done:
if (!focusDebug) {
}
}
/*
*----------------------------------------------------------------------
*
* FocusMapProc --
*
* This procedure is called as an event handler for StructureNotify
* events, if a window receives the focus at a time when its
* toplevel isn't mapped. The procedure is needed because X
* won't allow the focus to be set to an unmapped window; we
* detect when the toplevel is mapped and set the focus to it then.
*
* Results:
* None.
*
* Side effects:
* If this is a map event, the focus gets set to the toplevel
* given by clientData.
*
*----------------------------------------------------------------------
*/
static void
{
}
}