]> git.zerfleddert.de Git - micropolis/blob - src/notes/to.ouster
Makefile: Micropolis build fixes for recent macOS
[micropolis] / src / notes / to.ouster
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 }
Impressum, Datenschutz