Mercurial > hg > xemacs-beta
annotate src/ExternalShell.c @ 5910:eb1e15c9440b
Be less misleading in errors, data.c
src/ChangeLog addition:
2015-05-09 Aidan Kehoe <kehoea@parhasard.net>
* data.c (Flogand):
* data.c (Flogior):
* data.c (Frem):
* data.c (Flsh):
Give less misleading errors in all these functions, e.g. supplying
#'integer-char-or-marker as the predicate on wrong-type-argument,
when float would not be accepted.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sat, 09 May 2015 10:50:32 +0100 |
parents | 2aa9cd456ae7 |
children |
rev | line source |
---|---|
428 | 1 /* External shell widget. |
2 Copyright (C) 1993, 1994 Sun Microsystems, Inc. | |
3 | |
5405
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
3025
diff
changeset
|
4 This library is free software: you can redistribute it and/or modify it |
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
3025
diff
changeset
|
5 under the terms of the GNU General Public License as published by the |
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
3025
diff
changeset
|
6 Free Software Foundation, either version 3 of the License, or (at your |
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
3025
diff
changeset
|
7 option) any later version. |
428 | 8 |
5405
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
3025
diff
changeset
|
9 This library is distributed in the hope that it will be useful, but WITHOUT |
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
3025
diff
changeset
|
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
3025
diff
changeset
|
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
3025
diff
changeset
|
12 for more details. |
428 | 13 |
5405
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
3025
diff
changeset
|
14 You should have received a copy of the GNU General Public License |
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
3025
diff
changeset
|
15 along with this library. If not, see <http://www.gnu.org/licenses/>. */ |
428 | 16 |
17 /* Synched up with: Not in FSF. */ | |
18 | |
19 /* Written by Ben Wing, September 1993. */ | |
20 | |
21 /* This is a special Shell that is designed to use an externally- | |
22 provided window created by someone else (possibly another process). | |
23 That other window should have an associated widget of class | |
24 ExternalClient. The two widgets communicate with each other using | |
25 ClientMessage events and properties on the external window. | |
26 | |
27 Ideally this feature should be independent of Emacs. Unfortunately | |
28 there are lots and lots of specifics that need to be dealt with | |
29 for this to work properly, and some of them can't conveniently | |
30 be handled within the widget's methods. Some day the code may | |
31 be rewritten so that the embedded-widget feature can be used by | |
32 any application, with appropriate entry points that are called | |
33 at specific points within the application. | |
34 | |
35 This feature is similar to the OLE (Object Linking & Embedding) | |
36 feature provided by MS Windows. | |
37 */ | |
38 | |
39 #ifdef emacs | |
40 | |
41 #include <config.h> | |
42 | |
43 #ifndef EXTERNAL_WIDGET | |
44 ERROR! This ought not be getting compiled if EXTERNAL_WIDGET is undefined | |
45 #endif | |
46 | |
47 #endif /* emacs */ | |
48 | |
49 #include <stdio.h> | |
50 #include <string.h> | |
51 #include <X11/StringDefs.h> | |
52 #include "xintrinsicp.h" | |
53 #include <X11/Shell.h> | |
54 #include <X11/ShellP.h> | |
55 #include <X11/Vendor.h> | |
56 #include <X11/VendorP.h> | |
2299 | 57 #include "compiler.h" |
428 | 58 #include "ExternalShellP.h" |
59 #include "extw-Xt.h" | |
60 | |
61 #ifdef emacs | |
62 extern void emacs_Xt_handle_focus_event (XEvent *event); | |
63 #endif | |
64 | |
65 /* Communication between this shell and the client widget: | |
66 | |
67 Communication is through ClientMessage events with message_type | |
68 EXTW_NOTIFY and format 32. Both the shell and the client widget | |
69 communicate with each other by sending the message to the same | |
70 window (the "external window" below), and the data.l[0] value is | |
71 used to determine who sent the message. | |
72 | |
73 The data is formatted as follows: | |
74 | |
75 data.l[0] = who sent this message: external_shell_send (0) or | |
76 external_client_send (1) | |
77 data.l[1] = message type (see enum en_extw_notify below) | |
78 data.l[2-4] = data associated with this message | |
79 | |
80 EventHandler() handles messages from the other side. | |
81 | |
82 extw_send_notify_3() sends a message to the other side. | |
83 | |
84 extw_send_geometry_value() is used when an XtWidgetGeometry structure | |
85 needs to be sent. This is too much data to fit into a | |
86 ClientMessage, so the data is stored in a property and then | |
87 extw_send_notify_3() is called. | |
88 | |
89 extw_get_geometry_value() receives an XtWidgetGeometry structure from a | |
90 property. | |
91 | |
92 extw_wait_for_response() is used when a response to a sent message | |
93 is expected. It looks for a matching event within a | |
94 particular timeout. | |
95 | |
96 The particular message types are as follows: | |
97 | |
98 1) extw_notify_init (event_window, event_mask) | |
99 | |
100 This is sent from the shell to the client after the shell realizes | |
101 its EmacsFrame widget on the client's "external window". This | |
102 tells the client that it should start passing along events of the | |
103 types specified in event_mask. event_window specifies the window | |
104 of the EmacsFrame widget, which is a child of the client's | |
105 external window. | |
106 | |
107 extw_notify_init (client_type) | |
108 | |
109 When the client receives an extw_notify_init message from the | |
110 shell, it sends back a message of the same sort specifying the type | |
111 of the toolkit used by the client (Motif, generic Xt, or Xlib). | |
112 | |
113 2) extw_notify_end () | |
114 | |
115 This is sent from the shell to the client when the shell's | |
116 EmacsFrame widget is destroyed, and tells the client to stop | |
117 passing events along. | |
118 | |
119 3) extw_notify_qg (result) | |
120 | |
121 This is sent from the client to the shell when a QueryGeometry | |
122 request is received on the client. The XtWidgetGeometry structure | |
123 specified in the QueryGeometry request is passed on in the | |
124 EXTW_QUERY_GEOMETRY property (of type EXTW_WIDGET_GEOMETRY) on the | |
125 external window. result is unused. | |
126 | |
127 In response, the shell passes the QueryGeometry request down the | |
128 widget tree, and when a response is received, sends a message of | |
129 type extw_notify_qg back to the client, with result specifying the | |
130 GeometryResult value. If this value is XtGeometryAlmost, the | |
131 returned XtWidgetGeometry structure is stored into the same property | |
132 as above. [BPW is there a possible race condition here?] | |
133 | |
134 4) extw_notify_gm (result) | |
135 | |
136 A very similar procedure to that for extw_notify_qg is followed | |
137 when the shell's RootGeometryManager method is called, indicating | |
138 that a child widget wishes to change the shell's geometry. The | |
139 XtWidgetGeometry structure is stored in the EXTW_GEOMETRY_MANAGER | |
140 property. | |
141 | |
142 5) extw_notify_focus_in (), extw_notify_focus_out () | |
143 | |
144 These are sent from the client to the shell when the client gains | |
145 or loses the keyboard focus. It is done this way because Xt | |
146 maintains its own concept of keyboard focus and only the client | |
147 knows this information. | |
148 */ | |
149 | |
150 #define NOTIFY(w, type, l0, l1, l2) \ | |
151 extw_send_notify_3(XtDisplay((Widget)(w)),\ | |
152 (w)->externalShell.external_window, type, l0, l1, l2) | |
153 | |
3025 | 154 static void ExternalShellInitialize (Widget req, Widget new_, ArgList args, |
428 | 155 Cardinal *num_args); |
156 static void ExternalShellRealize (Widget wid, Mask *vmask, XSetWindowAttributes | |
157 *attr); | |
158 static void ExternalShellDestroy (Widget w); | |
159 static void ChangeManaged (Widget wid); | |
2108 | 160 static XtGeometryResult |
161 ExternalShellRootGeometryManager (Widget gw, XtWidgetGeometry *request, | |
162 XtWidgetGeometry *reply); | |
428 | 163 static void EventHandler (Widget wid, XtPointer closure, XEvent *event, |
164 Boolean *continue_to_dispatch); | |
165 | |
166 #ifndef DEFAULT_WM_TIMEOUT | |
167 # define DEFAULT_WM_TIMEOUT 5000 | |
168 #endif | |
169 | |
170 void ExternalShellUnrealize (Widget w); | |
171 | |
172 static XtResource resources[] = { | |
173 #define offset(field) XtOffset(ExternalShellWidget, externalShell.field) | |
440 | 174 { XtNwindow, XtCWindow, |
175 XtRWindow, sizeof (Window), | |
176 offset (external_window), XtRImmediate, (XtPointer)0 }, | |
177 { XtNclientTimeout, XtCClientTimeout, | |
178 XtRInt, sizeof (int), | |
179 offset(client_timeout), XtRImmediate,(XtPointer)DEFAULT_WM_TIMEOUT }, | |
180 { XtNdeadClient, XtCDeadClient, | |
181 XtRBoolean, sizeof (Boolean), | |
182 offset(dead_client), XtRImmediate, (XtPointer)False }, | |
428 | 183 }; |
184 | |
185 static CompositeClassExtensionRec compositeClassExtRec = { | |
186 NULL, | |
187 NULLQUARK, | |
188 XtCompositeExtensionVersion, | |
440 | 189 sizeof (CompositeClassExtensionRec), |
428 | 190 TRUE, |
191 }; | |
192 | |
193 static ShellClassExtensionRec shellClassExtRec = { | |
194 NULL, | |
195 NULLQUARK, | |
196 XtShellExtensionVersion, | |
440 | 197 sizeof (ShellClassExtensionRec), |
428 | 198 ExternalShellRootGeometryManager |
199 }; | |
200 | |
201 ExternalShellClassRec externalShellClassRec = { | |
202 { /* | |
203 * core_class fields | |
204 */ | |
205 /* superclass */ (WidgetClass) &shellClassRec, | |
206 /* class_name */ "ExternalShell", | |
440 | 207 /* size */ sizeof (ExternalShellRec), |
428 | 208 /* Class Initializer */ NULL, |
209 /* class_part_initialize*/ NULL, /* XtInheritClassPartInitialize, */ | |
210 /* Class init'ed ? */ FALSE, | |
211 /* initialize */ ExternalShellInitialize, | |
212 /* initialize_notify */ NULL, | |
213 /* realize */ ExternalShellRealize, | |
214 /* actions */ NULL, | |
215 /* num_actions */ 0, | |
216 /* resources */ resources, | |
217 /* resource_count */ XtNumber (resources), | |
218 /* xrm_class */ NULLQUARK, | |
219 /* compress_motion */ FALSE, | |
220 /* compress_exposure */ TRUE, | |
221 /* compress_enterleave*/ FALSE, | |
222 /* visible_interest */ TRUE, | |
223 /* destroy */ ExternalShellDestroy, /* XtInheritDestroy, */ | |
224 /* resize */ XtInheritResize, | |
225 /* expose */ NULL, | |
226 /* set_values */ NULL, /* XtInheritSetValues, */ | |
440 | 227 /* set_values_hook */ NULL, |
228 /* set_values_almost */ XtInheritSetValuesAlmost, | |
229 /* get_values_hook */ NULL, | |
428 | 230 /* accept_focus */ NULL, |
231 /* intrinsics version */ XtVersion, | |
232 /* callback offsets */ NULL, | |
233 /* tm_table */ NULL, | |
234 /* query_geometry */ NULL, | |
235 /* display_accelerator*/ NULL, | |
236 /* extension */ NULL | |
237 },{ /* Composite */ | |
238 /* geometry_manager */ XtInheritGeometryManager, | |
239 /* change_managed */ ChangeManaged, /* XtInheritChangeManaged */ | |
240 /* insert_child */ XtInheritInsertChild, | |
241 /* delete_child */ XtInheritDeleteChild, | |
242 /* extension */ (XtPointer)&compositeClassExtRec | |
243 },{ /* Shell */ | |
244 /* extension */ (XtPointer)&shellClassExtRec | |
245 },{ /* ExternalShell */ | |
246 0 | |
247 } | |
248 }; | |
249 | |
250 WidgetClass externalShellWidgetClass = (WidgetClass) &externalShellClassRec; | |
251 | |
252 static void | |
3025 | 253 ExternalShellInitialize (Widget req, Widget new_, ArgList UNUSED (args), |
2286 | 254 Cardinal *UNUSED (num_args)) |
428 | 255 { |
3025 | 256 XtAddEventHandler(new_, 0, |
428 | 257 TRUE, EventHandler, (XtPointer) NULL); |
258 extw_initialize_atoms(XtDisplay(req)); | |
259 extw_which_side = extw_shell_send; | |
260 } | |
261 | |
262 static Widget | |
263 find_managed_child (CompositeWidget w) | |
264 { | |
265 int i; | |
266 Widget *childP = w->composite.children; | |
267 | |
268 for (i = w->composite.num_children; i; i--, childP++) | |
269 if (XtIsWidget(*childP) && XtIsManaged(*childP)) | |
270 return *childP; | |
271 return NULL; | |
272 } | |
273 | |
274 #ifndef XtCXtToolkitError | |
275 # define XtCXtToolkitError "XtToolkitError" | |
276 #endif | |
277 | |
2286 | 278 static void EventHandler (Widget wid, XtPointer UNUSED (closure), |
2108 | 279 XEvent *event, |
2286 | 280 Boolean *UNUSED (continue_to_dispatch)) |
428 | 281 { |
282 ExternalShellWidget w = (ExternalShellWidget) wid; | |
283 | |
284 if(w->core.window != event->xany.window) { | |
285 XtAppErrorMsg(XtWidgetToApplicationContext(wid), | |
286 "invalidWindow","eventHandler",XtCXtToolkitError, | |
287 "Event with wrong window", | |
288 (String *)NULL, (Cardinal *)NULL); | |
289 return; | |
290 } | |
291 | |
292 if (event->type == ClientMessage && | |
293 event->xclient.data.l[0] == extw_client_send && | |
294 event->xclient.message_type == a_EXTW_NOTIFY) | |
295 switch (event->xclient.data.l[1]) { | |
296 | |
297 case extw_notify_gm: | |
298 /* client is alive again. */ | |
299 w->externalShell.dead_client = False; | |
300 break; | |
301 | |
302 case extw_notify_qg: { | |
303 XtWidgetGeometry xwg, xwg_return; | |
304 XtGeometryResult result; | |
305 Widget child = find_managed_child((CompositeWidget) w); | |
306 | |
307 if (child) { | |
308 extw_get_geometry_value(XtDisplay(wid), XtWindow(wid), | |
309 a_EXTW_QUERY_GEOMETRY, &xwg); | |
310 result = XtQueryGeometry(child, &xwg, &xwg_return); | |
311 } else | |
312 result = XtGeometryYes; | |
313 | |
314 extw_send_geometry_value(XtDisplay(wid), XtWindow(wid), | |
315 a_EXTW_QUERY_GEOMETRY, extw_notify_qg, | |
316 result == XtGeometryAlmost ? &xwg_return : | |
317 NULL, result); | |
318 break; | |
319 } | |
320 | |
321 case extw_notify_focus_in: { | |
322 XFocusChangeEvent evnt; | |
440 | 323 |
428 | 324 evnt.type = FocusIn; |
325 evnt.serial = LastKnownRequestProcessed (XtDisplay (wid)); | |
326 evnt.send_event = True; | |
327 evnt.display = XtDisplay (wid); | |
328 evnt.window = XtWindow (wid); | |
329 evnt.mode = NotifyNormal; | |
330 evnt.detail = NotifyAncestor; | |
331 #ifdef emacs | |
332 emacs_Xt_handle_focus_event ((XEvent *) &evnt); | |
333 #else | |
334 XtDispatchEvent ((XEvent *) &evnt); | |
335 #endif | |
336 break; | |
337 } | |
440 | 338 |
428 | 339 case extw_notify_focus_out: { |
340 XFocusChangeEvent evnt; | |
440 | 341 |
428 | 342 evnt.type = FocusOut; |
343 evnt.serial = LastKnownRequestProcessed (XtDisplay (wid)); | |
344 evnt.send_event = True; | |
345 evnt.display = XtDisplay (wid); | |
346 evnt.window = XtWindow (wid); | |
347 evnt.mode = NotifyNormal; | |
348 evnt.detail = NotifyAncestor; | |
349 #ifdef emacs | |
350 emacs_Xt_handle_focus_event ((XEvent *) &evnt); | |
351 #else | |
352 XtDispatchEvent ((XEvent *) &evnt); | |
353 #endif | |
354 break; | |
355 } | |
356 | |
357 case extw_notify_end: | |
358 /* frame should be destroyed. */ | |
359 break; | |
360 } | |
361 } | |
362 | |
363 /* Lifted almost entirely from GetGeometry() in Shell.c | |
364 */ | |
365 static void | |
2286 | 366 GetGeometry (Widget W, Widget UNUSED (child)) |
428 | 367 { |
368 ExternalShellWidget w = (ExternalShellWidget)W; | |
369 int x, y, win_gravity = -1, flag; | |
370 XSizeHints hints; | |
371 Window win = w->externalShell.external_window; | |
440 | 372 |
428 | 373 { |
374 Window dummy_root; | |
375 unsigned int dummy_bd_width, dummy_depth, width, height; | |
440 | 376 |
428 | 377 /* determine the existing size of the window. */ |
378 XGetGeometry(XtDisplay(W), win, &dummy_root, &x, &y, &width, | |
379 &height, &dummy_bd_width, &dummy_depth); | |
380 w->core.width = width; | |
381 w->core.height = height; | |
382 } | |
383 | |
384 if(w->shell.geometry != NULL) { | |
385 char def_geom[128]; | |
386 int width, height; | |
387 | |
388 x = w->core.x; | |
389 y = w->core.y; | |
390 width = w->core.width; | |
391 height = w->core.height; | |
392 hints.flags = 0; | |
393 | |
394 sprintf( def_geom, "%dx%d+%d+%d", width, height, x, y ); | |
395 flag = XWMGeometry( XtDisplay(W), | |
396 XScreenNumberOfScreen(XtScreen(W)), | |
397 w->shell.geometry, def_geom, | |
398 (unsigned int)w->core.border_width, | |
399 &hints, &x, &y, &width, &height, | |
400 &win_gravity | |
401 ); | |
402 if (flag) { | |
403 if (flag & XValue) w->core.x = (Position)x; | |
404 if (flag & YValue) w->core.y = (Position)y; | |
405 if (flag & WidthValue) w->core.width = (Dimension)width; | |
406 if (flag & HeightValue) w->core.height = (Dimension)height; | |
407 } | |
408 else { | |
409 String params[2]; | |
410 Cardinal num_params = 2; | |
411 params[0] = XtName(W); | |
412 params[1] = w->shell.geometry; | |
413 XtAppWarningMsg(XtWidgetToApplicationContext(W), | |
414 "badGeometry", "shellRealize", XtCXtToolkitError, | |
415 "Shell widget \"%s\" has an invalid geometry specification: \"%s\"", | |
416 params, &num_params); | |
417 } | |
418 } | |
419 else | |
420 flag = 0; | |
421 | |
422 w->shell.client_specified |= _XtShellGeometryParsed; | |
423 } | |
424 | |
425 /* Lifted almost entirely from Realize() in Shell.c | |
426 */ | |
427 static void ExternalShellRealize (Widget wid, Mask *vmask, | |
428 XSetWindowAttributes *attr) | |
429 { | |
430 ExternalShellWidget w = (ExternalShellWidget) wid; | |
431 Mask mask = *vmask; | |
432 Window win = w->externalShell.external_window; | |
433 | |
434 if (!win) { | |
435 Cardinal count = 1; | |
436 XtErrorMsg("invalidWindow","shellRealize", XtCXtToolkitError, | |
437 "No external window specified for ExternalShell widget %s", | |
438 &wid->core.name, &count); | |
439 } | |
440 | |
441 if (! (w->shell.client_specified & _XtShellGeometryParsed)) { | |
442 /* we'll get here only if there was no child the first | |
443 time we were realized. If the shell was Unrealized | |
444 and then re-Realized, we probably don't want to | |
445 re-evaluate the defaults anyway. | |
446 */ | |
447 GetGeometry(wid, (Widget)NULL); | |
448 } | |
449 else if (w->core.background_pixmap == XtUnspecifiedPixmap) { | |
450 /* I attempt to inherit my child's background to avoid screen flash | |
451 * if there is latency between when I get resized and when my child | |
452 * is resized. Background=None is not satisfactory, as I want the | |
453 * user to get immediate feedback on the new dimensions (most | |
454 * particularly in the case of a non-reparenting wm). It is | |
455 * especially important to have the server clear any old cruft | |
456 * from the display when I am resized larger. | |
457 */ | |
458 Widget *childP = w->composite.children; | |
459 int i; | |
460 for (i = w->composite.num_children; i; i--, childP++) { | |
461 if (XtIsWidget(*childP) && XtIsManaged(*childP)) { | |
462 if ((*childP)->core.background_pixmap | |
463 != XtUnspecifiedPixmap) { | |
464 mask &= ~(CWBackPixel); | |
465 mask |= CWBackPixmap; | |
466 attr->background_pixmap = | |
467 w->core.background_pixmap = | |
468 (*childP)->core.background_pixmap; | |
469 } else { | |
440 | 470 attr->background_pixel = |
471 w->core.background_pixel = | |
428 | 472 (*childP)->core.background_pixel; |
473 } | |
474 break; | |
475 } | |
476 } | |
477 } | |
478 | |
479 if(w->shell.save_under) { | |
480 mask |= CWSaveUnder; | |
481 attr->save_under = TRUE; | |
482 } | |
483 if(w->shell.override_redirect) { | |
484 mask |= CWOverrideRedirect; | |
485 attr->override_redirect = TRUE; | |
486 } | |
487 if (wid->core.width == 0 || wid->core.height == 0) { | |
488 Cardinal count = 1; | |
489 XtErrorMsg("invalidDimension", "shellRealize", XtCXtToolkitError, | |
490 "Shell widget %s has zero width and/or height", | |
491 &wid->core.name, &count); | |
492 } | |
493 wid->core.window = win; | |
494 XChangeWindowAttributes(XtDisplay(wid), wid->core.window, | |
495 mask, attr); | |
496 | |
497 } | |
498 | |
2108 | 499 static void ExternalShellDestroy (Widget wid) |
428 | 500 { |
501 ExternalShellWidget w = (ExternalShellWidget)wid; | |
502 | |
503 if (XtIsRealized(wid)) | |
504 ExternalShellUnrealize(wid); | |
505 | |
506 NOTIFY(w, extw_notify_end, 0, 0, 0); | |
507 } | |
508 | |
509 /* Invoke matching routine from superclass, but first override its | |
510 geometry opinions with our own routine */ | |
511 | |
2108 | 512 static void ChangeManaged (Widget wid) |
428 | 513 { |
514 if (!XtIsRealized (wid)) | |
515 GetGeometry(wid, (Widget)NULL); | |
516 (*((ShellClassRec*)externalShellClassRec.core_class.superclass)-> | |
517 composite_class.change_managed)(wid); | |
518 } | |
519 | |
520 /* Based on RootGeometryManager() in Shell.c */ | |
521 | |
2108 | 522 static XtGeometryResult |
523 ExternalShellRootGeometryManager (Widget gw, XtWidgetGeometry *request, | |
524 XtWidgetGeometry *reply) | |
428 | 525 { |
526 ExternalShellWidget w = (ExternalShellWidget)gw; | |
527 unsigned int mask = request->request_mode; | |
528 XEvent event; | |
529 int oldx, oldy, oldwidth, oldheight, oldborder_width; | |
530 unsigned long request_num; | |
531 XtWidgetGeometry req = *request; /* don't modify caller's structure */ | |
532 | |
533 oldx = w->core.x; | |
534 oldy = w->core.y; | |
535 oldwidth = w->core.width; | |
536 oldheight = w->core.height; | |
537 oldborder_width = w->core.border_width; | |
538 | |
539 #define PutBackGeometry() \ | |
540 { w->core.x = oldx; \ | |
541 w->core.y = oldy; \ | |
542 w->core.width = oldwidth; \ | |
543 w->core.height = oldheight; \ | |
544 w->core.border_width = oldborder_width; } | |
545 | |
546 if (mask & CWX) { | |
547 if (w->core.x == request->x) mask &= ~CWX; | |
548 else | |
549 w->core.x = request->x; | |
550 } | |
551 if (mask & CWY) { | |
552 if (w->core.y == request->y) mask &= ~CWY; | |
553 else w->core.y = request->y; | |
554 } | |
555 if (mask & CWBorderWidth) { | |
556 if (w->core.border_width == request->border_width) | |
557 mask &= ~CWBorderWidth; | |
558 else w->core.border_width = request->border_width; | |
559 } | |
560 if (mask & CWWidth) { | |
561 if (w->core.width == request->width) mask &= ~CWWidth; | |
562 else w->core.width = request->width; | |
563 } | |
564 if (mask & CWHeight) { | |
565 if (w->core.height == request->height) mask &= ~CWHeight; | |
566 else w->core.height = request->height; | |
567 } | |
568 | |
569 if (!XtIsRealized((Widget)w)) return XtGeometryYes; | |
570 | |
571 req.sibling = None; | |
572 req.request_mode = mask & ~CWSibling; | |
573 request_num = NextRequest(XtDisplay(w)); | |
574 extw_send_geometry_value(XtDisplay(w), XtWindow(w), | |
575 a_EXTW_GEOMETRY_MANAGER, | |
576 extw_notify_gm, &req, 0); | |
577 | |
578 if (w->externalShell.dead_client == TRUE) { | |
579 /* The client is sick. Refuse the request. | |
580 * If the client recovers and decides to honor the | |
581 * request, it will be handled by Shell's EventHandler(). | |
582 */ | |
583 PutBackGeometry(); | |
584 return XtGeometryNo; | |
585 } | |
586 | |
587 if (extw_wait_for_response(gw, &event, request_num, extw_notify_gm, | |
588 w->externalShell.client_timeout)) { | |
589 XtGeometryResult result = (XtGeometryResult) event.xclient.data.l[2]; | |
590 | |
591 if (result != XtGeometryYes) | |
592 PutBackGeometry(); | |
593 if (result == XtGeometryAlmost) { | |
594 extw_get_geometry_value(XtDisplay(w), XtWindow(w), | |
595 a_EXTW_GEOMETRY_MANAGER, reply); | |
596 } | |
597 return result; | |
598 } else { | |
599 w->externalShell.dead_client = TRUE; /* timed out; must be broken */ | |
600 PutBackGeometry(); | |
601 return XtGeometryNo; | |
602 } | |
603 #undef PutBackGeometry | |
604 } | |
605 | |
606 static void | |
607 hack_event_masks_1 (Display *display, Window w, int this_window_propagate) | |
608 { | |
609 Window root, parent, *children; | |
877 | 610 unsigned int nchildren, i; |
428 | 611 |
612 if (!XQueryTree (display, w, &root, &parent, &children, &nchildren)) | |
613 return; | |
614 for (i=0; i<nchildren; i++) | |
615 hack_event_masks_1 (display, children[i], 1); | |
616 if (children) | |
617 XFree (children); | |
618 { | |
619 XWindowAttributes xwa; | |
620 XSetWindowAttributes xswa; | |
621 if (XGetWindowAttributes (display, w, &xwa)) { | |
622 xswa.event_mask = xwa.your_event_mask & ~KeyPressMask; | |
623 if (this_window_propagate) | |
624 xswa.do_not_propagate_mask = xwa.do_not_propagate_mask & ~KeyPressMask; | |
625 XChangeWindowAttributes (display, w, CWEventMask, &xswa); | |
626 } | |
627 } | |
628 } | |
629 | |
630 /* fix all event masks on all subwindows of the specified window so that | |
631 all key presses in any subwindow filter up to the specified window. | |
632 | |
633 We have to do this cruftiness with external widgets so that we don't | |
634 step on Motif's concept of keyboard focus. (Due to the nature of | |
635 Xt and Motif, X's idea of who gets the keyboard events may not jive | |
636 with Xt's idea of same, and Xt redirects the events to the proper | |
637 window. This occurs on the client side and we have no knowledge | |
638 of it, so we have to rely on a SendEvent from the client side to | |
639 receive our keyboard events.) | |
640 */ | |
641 | |
642 static void | |
643 hack_event_masks (Display *display, Window w) | |
644 { | |
645 hack_event_masks_1 (display, w, 0); | |
646 } | |
647 | |
648 /* external entry points */ | |
649 | |
650 Bool | |
651 ExternalShellReady (Widget w, Window win, long event_mask) | |
652 { | |
653 ExternalShellWidget ew = (ExternalShellWidget) w; | |
654 XEvent event; | |
655 unsigned long request_num; | |
656 | |
657 request_num = NextRequest(XtDisplay(w)); | |
658 NOTIFY(ew, extw_notify_init, (long) win, event_mask, 0); | |
659 if (extw_wait_for_response(w, &event, request_num, extw_notify_init, | |
660 ew->externalShell.client_timeout)) | |
661 { | |
662 /* Xt/Xm extw's have more elaborate focus needs than mere | |
663 Xlib ones. | |
664 | |
665 Rather independently, they *don't* need the | |
666 ConfigureNotify event, having fixed up the window size in | |
667 ChangeManaged, above, but Xlib extw's do need this. | |
668 */ | |
669 ew->externalShell.client_type = event.xclient.data.l[2]; | |
670 if (ew->externalShell.client_type != EXTW_TYPE_XLIB) | |
671 { | |
672 hack_event_masks (XtDisplay (w), XtWindow (w)); | |
673 } | |
674 else | |
675 { | |
676 XConfigureEvent ev; | |
677 XWindowAttributes xwa; | |
678 ev.type = ConfigureNotify; | |
679 ev.display = XtDisplay (w); | |
680 ev.event = ev.window = XtWindow (w); | |
681 XGetWindowAttributes (ev.display, ev.window, &xwa); | |
682 ev.x = xwa.x; ev.y = xwa.y; | |
683 ev.width = xwa.width; ev.height = xwa.height; | |
684 ev.border_width = xwa.border_width; | |
685 ev.above = None; | |
686 ev.override_redirect = xwa.override_redirect; | |
687 XtDispatchEvent ((XEvent *) &ev); | |
688 } | |
689 return TRUE; | |
690 } | |
691 else | |
692 return FALSE; | |
693 } | |
694 | |
695 void | |
696 ExternalShellSetFocus (Widget wid) | |
697 { | |
698 ExternalShellWidget w = (ExternalShellWidget) wid; | |
699 | |
700 NOTIFY(w, extw_notify_set_focus, 0, 0, 0); | |
701 } | |
702 | |
703 extern void _XtUnregisterWindow (Window, Widget); | |
704 | |
705 void | |
706 ExternalShellUnrealize (Widget w) | |
707 { | |
708 #if (XT_REVISION > 5) | |
709 XtUnregisterDrawable (XtDisplay (w), w->core.window); | |
710 #else | |
711 extern void _XtUnregisterWindow (Window, Widget); | |
712 _XtUnregisterWindow (w->core.window, w); | |
713 #endif | |
714 w->core.window = 0; | |
715 } |