]>
Commit | Line | Data |
---|---|---|
1 | To: ouster@sprite.berkeley.edu | |
2 | Cc: hopkins | |
3 | Subject: more multiple display stuff | |
4 | --text follows this line-- | |
5 | A problem I fixed is that the "focus" command only returns the focus | |
6 | of the main window's display, and there's no way to find out the focus | |
7 | on other displays. I fixed this by adding a "focus -query .window" | |
8 | form, that returns the focus of the display of the named window. When | |
9 | the tcl menu tracking code supports multiple displays, it will need to | |
10 | use this form to save the focus of the appropriate display before | |
11 | popping up a menu. | |
12 | ||
13 | A problem I haven't fixed yet is with the "selection" command, which | |
14 | right now will only retrieve the selection from the display of the | |
15 | main window. Pasting into a text field on another display with ^V | |
16 | inserts the selection from the main display. It could be changed to | |
17 | take a window argument similar to "focus". | |
18 | ||
19 | I wish I could think of a better flag name than "-query"... | |
20 | ||
21 | I had a go at hacking the Tk C code to keep track of one focus per | |
22 | display instead of per main window. (Should I be using one main | |
23 | window per display? I'm not now, I'm just creating remote toplevels | |
24 | with the -screen argument.) I moved the "struct TkWindow *focusPtr;" | |
25 | from the TkMainInfo to the TkDisplay structure, and modified the code | |
26 | in tkEvent.c that handled it and tkWindow.c that initialized it. | |
27 | ||
28 | In tkEvent.c, I changed 3 "winPtr->mainPtr->focusPtr"'s to | |
29 | "winPtr->dispPtr->focusPtr", in Tk_HandleEvent and TkEventDeadWindow. | |
30 | I worked over Tk_FocusCmd and TkFocusEventProc, included below. | |
31 | I'm not sure what the "winPtr == winPtr->dispPtr->mouseMainPtr" test | |
32 | at the end of Tk_FocusCmd really intends, but the transformation was | |
33 | pretty straightforward, and it seems to work for my cases. | |
34 | ||
35 | I've looked at the tcl code to try to figure out how to make it track | |
36 | properly with multiple displays. I think I'll need a function that | |
37 | given the name of a window, returns a unique string describing the | |
38 | display, that I can use to make tk_priv keys that distinguish between | |
39 | displays. The tcl functions tk_mbUnpost, tk_nextMenu, and | |
40 | tk_nextMenuEntry all need to take an argument so they can figure out | |
41 | which display to work on. | |
42 | ||
43 | Another unrelated fix I made to Tk and Tcl was to put the TK_LIBRARY | |
44 | and TCL_LIBRARY strings into global variables, and refer to those | |
45 | variables instead of embeding strings in the code, so it's possible to | |
46 | set them up properly before initializing, since I want to be able to | |
47 | set a couple environment variables and run the application with no | |
48 | installation. Is there a more appropriate way to do this? | |
49 | ||
50 | -Don | |
51 | ||
52 | Here is the code for Tk_FocusCmd and TkFocusEventProc: | |
53 | ||
54 | \f | |
55 | /* | |
56 | *-------------------------------------------------------------- | |
57 | * | |
58 | * Tk_FocusCmd -- | |
59 | * | |
60 | * This procedure is invoked to process the "focus" Tcl command. | |
61 | * See the user documentation for details on what it does. | |
62 | * | |
63 | * Results: | |
64 | * A standard Tcl result. | |
65 | * | |
66 | * Side effects: | |
67 | * See the user documentation. | |
68 | * | |
69 | *-------------------------------------------------------------- | |
70 | */ | |
71 | ||
72 | int | |
73 | Tk_FocusCmd(clientData, interp, argc, argv) | |
74 | ClientData clientData; /* Main window associated with | |
75 | * interpreter. */ | |
76 | Tcl_Interp *interp; /* Current interpreter. */ | |
77 | int argc; /* Number of arguments. */ | |
78 | char **argv; /* Argument strings. */ | |
79 | { | |
80 | Tk_Window tkwin = (Tk_Window) clientData; | |
81 | register TkWindow *winPtr = (TkWindow *) clientData; | |
82 | register TkWindow *newPtr; | |
83 | ||
84 | if (argc > 3) { | |
85 | focusSyntax: | |
86 | Tcl_AppendResult(interp, "too many args: should be \"", | |
87 | argv[0], " ?-query? ?window?\"", (char *) NULL); | |
88 | return TCL_ERROR; | |
89 | } | |
90 | ||
91 | if (argc == 1) { | |
92 | if (winPtr->dispPtr->focusPtr == NULL) { | |
93 | interp->result = "none"; | |
94 | } else { | |
95 | interp->result = winPtr->dispPtr->focusPtr->pathName; | |
96 | } | |
97 | return TCL_OK; | |
98 | } | |
99 | ||
100 | if (argv[1][0] == '-') { | |
101 | int switchLength; | |
102 | ||
103 | switchLength = strlen(argv[1]); | |
104 | if ((switchLength >= 2) | |
105 | && (strncmp(argv[1], "-query", switchLength) == 0)) { | |
106 | ||
107 | if (argc != 3) { | |
108 | goto focusSyntax; | |
109 | } | |
110 | ||
111 | newPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin); | |
112 | if (newPtr == NULL) { | |
113 | return TCL_ERROR; | |
114 | } | |
115 | if (newPtr->dispPtr->focusPtr == NULL) { | |
116 | interp->result = "none"; | |
117 | } else { | |
118 | interp->result = newPtr->dispPtr->focusPtr->pathName; | |
119 | } | |
120 | return TCL_OK; | |
121 | } | |
122 | } | |
123 | ||
124 | if (argc != 2) { | |
125 | goto focusSyntax; | |
126 | } | |
127 | ||
128 | if (strcmp(argv[1], "none") == 0) { | |
129 | newPtr = NULL; | |
130 | } else { | |
131 | newPtr = (TkWindow *) Tk_NameToWindow(interp, argv[1], tkwin); | |
132 | if (newPtr == NULL) { | |
133 | return TCL_ERROR; | |
134 | } | |
135 | } | |
136 | if (newPtr->dispPtr->focusPtr == newPtr) { | |
137 | return TCL_OK; | |
138 | } | |
139 | if (winPtr == newPtr->dispPtr->mouseMainPtr) { /* XXX: ??? presumably */ | |
140 | if ((newPtr->dispPtr->focusPtr != NULL) | |
141 | && (newPtr->dispPtr->focusPtr->focusProc != NULL)) { | |
142 | (*newPtr->dispPtr->focusPtr->focusProc)( | |
143 | newPtr->dispPtr->focusPtr->focusData, 0); | |
144 | } | |
145 | newPtr->dispPtr->focusPtr = newPtr; | |
146 | if ((newPtr != NULL) && (newPtr->focusProc != NULL)) { | |
147 | (*newPtr->focusProc)(newPtr->focusData, 1); | |
148 | } | |
149 | } else { | |
150 | newPtr->dispPtr->focusPtr = newPtr; | |
151 | } | |
152 | return TCL_OK; | |
153 | } | |
154 | \f | |
155 | /* | |
156 | *-------------------------------------------------------------- | |
157 | * | |
158 | * TkFocusEventProc -- | |
159 | * | |
160 | * This procedure is invoked whenever the pointer enters | |
161 | * or leaves a top-level window. It notifies the current | |
162 | * owner of the focus, if any. | |
163 | * | |
164 | * Results: | |
165 | * None. | |
166 | * | |
167 | * Side effects: | |
168 | * None. | |
169 | * | |
170 | *-------------------------------------------------------------- | |
171 | */ | |
172 | ||
173 | void | |
174 | TkFocusEventProc(winPtr, eventPtr) | |
175 | register TkWindow *winPtr; /* Top-level window just entered or left. */ | |
176 | XEvent *eventPtr; /* EnterWindow or LeaveWindow event. */ | |
177 | { | |
178 | register TkWindow *focusPtr; | |
179 | TkWindow *newMouseMainPtr = NULL; | |
180 | ||
181 | if (eventPtr->type == EnterNotify) { | |
182 | newMouseMainPtr = winPtr->mainPtr->winPtr; | |
183 | } | |
184 | if (winPtr->dispPtr->mouseMainPtr == newMouseMainPtr) { | |
185 | return; | |
186 | } | |
187 | if (winPtr->dispPtr->mouseMainPtr != NULL) { | |
188 | focusPtr = winPtr->dispPtr->focusPtr; | |
189 | if ((focusPtr != NULL) | |
190 | && (focusPtr->focusProc != NULL)) { | |
191 | (*focusPtr->focusProc)(focusPtr->focusData, 0); | |
192 | } | |
193 | } | |
194 | winPtr->dispPtr->mouseMainPtr = newMouseMainPtr; | |
195 | if (newMouseMainPtr != NULL) { | |
196 | focusPtr = newMouseMainPtr->dispPtr->focusPtr; | |
197 | if ((focusPtr != NULL) | |
198 | && (focusPtr->focusProc != NULL)) { | |
199 | (*focusPtr->focusProc)(focusPtr->focusData, 1); | |
200 | } | |
201 | } | |
202 | } |