428
+ − 1 /* External client widget.
+ − 2 Copyright (C) 1993, 1994 Sun Microsystems, Inc.
+ − 3
+ − 4 This library is free software; you can redistribute it and/or
+ − 5 modify it under the terms of the GNU Library General Public
+ − 6 License as published by the Free Software Foundation; either
+ − 7 version 2 of the License, or (at your option) any later version.
+ − 8
+ − 9 This library is distributed in the hope that it will be useful,
+ − 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ − 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ − 12 Library General Public License for more details.
+ − 13
+ − 14 You should have received a copy of the GNU Library General Public
+ − 15 License along with this library; if not, write to
+ − 16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ − 17 Boston, MA 02111-1307, USA. */
+ − 18
+ − 19 /* Synched up with: Not in FSF. */
+ − 20
+ − 21 /* Written by Ben Wing, September 1993. */
+ − 22
+ − 23 #ifdef emacs
+ − 24
+ − 25 #include <config.h>
+ − 26
+ − 27 #ifndef EXTERNAL_WIDGET
+ − 28 ERROR! This ought not be getting compiled if EXTERNAL_WIDGET is undefined
+ − 29 #endif
+ − 30
+ − 31 #endif /* emacs */
+ − 32
+ − 33 #include <stdio.h>
+ − 34 #include <string.h>
+ − 35 #include <stdlib.h>
+ − 36 #ifdef EXTW_USES_MOTIF
+ − 37 # include <Xm/XmP.h>
+ − 38 # include <Xm/PrimitiveP.h>
+ − 39 # include <X11/keysym.h>
+ − 40 #else
+ − 41 # include "xintrinsicp.h"
+ − 42 # include <X11/StringDefs.h>
+ − 43 #endif
+ − 44
2299
+ − 45 #include "compiler.h"
428
+ − 46 #include "ExternalClientP.h"
+ − 47 #include "extw-Xt.h"
+ − 48
+ − 49 #ifdef TOOLTALK
442
+ − 50 #include TT_C_H_FILE
428
+ − 51 #endif
+ − 52
+ − 53 /* This is the client widget, used to communicate with an ExternalShell
+ − 54 widget. */
+ − 55
+ − 56 #define NOTIFY(w, type, l0, l1, l2) \
+ − 57 extw_send_notify_3(XtDisplay((Widget)(w)), XtWindow((Widget)(w)),\
+ − 58 type, l0, l1, l2)
+ − 59
+ − 60 static void externalClientInitialize (Widget req, Widget new, ArgList args,
+ − 61 Cardinal *num_args);
+ − 62 static void externalClientRealize (Widget widget, XtValueMask *mask,
+ − 63 XSetWindowAttributes *attrs);
+ − 64 static void Destroy (Widget w);
+ − 65 static void EventHandler (Widget wid, XtPointer closure, XEvent *event,
+ − 66 Boolean *continue_to_dispatch);
+ − 67 static void MaskableEventHandler (Widget wid, XtPointer closure, XEvent *event,
+ − 68 Boolean *continue_to_dispatch);
+ − 69 static XtGeometryResult QueryGeometry(Widget, XtWidgetGeometry *,
+ − 70 XtWidgetGeometry *);
+ − 71 static void ExternalClientFocusIn (Widget, XEvent *, String *, Cardinal *);
+ − 72 static void ExternalClientFocusOut (Widget, XEvent *, String *, Cardinal *);
+ − 73 static void ExternalClientEnter (Widget, XEvent *, String *, Cardinal *);
+ − 74 static void ExternalClientLeave (Widget, XEvent *, String *, Cardinal *);
+ − 75
+ − 76 static int my_error_handler(Display *display, XErrorEvent *xev);
+ − 77 static int (*error_old_handler)(Display *, XErrorEvent *);
+ − 78
+ − 79 static XtResource resources[] = {
+ − 80 #define offset(field) XtOffset(ExternalClientWidget, externalClient.field)
440
+ − 81 { XtNshellTimeout, XtCShellTimeout,
+ − 82 XtRInt, sizeof (int),
+ − 83 offset(shell_timeout), XtRImmediate,(XtPointer)DEFAULT_WM_TIMEOUT },
+ − 84 { XtNdeadShell, XtCDeadShell,
+ − 85 XtRBoolean, sizeof (Boolean),
+ − 86 offset(dead_shell), XtRImmediate, (XtPointer)False },
428
+ − 87 #ifdef EXTW_USES_MOTIF
440
+ − 88 { XmNnavigationType, XmCNavigationType,
+ − 89 XmRNavigationType, sizeof (XmNavigationType),
+ − 90 XtOffset (ExternalClientWidget, primitive.navigation_type),
+ − 91 XtRImmediate, (XtPointer)XmTAB_GROUP },
428
+ − 92 #endif
440
+ − 93 { XtNemacsProcID, XtCEmacsProcID,
+ − 94 XtRString, sizeof (String),
+ − 95 offset(emacs_procid), XtRImmediate, (XtPointer)NULL },
+ − 96 { XtNshellReadyCallback, XtCCallback,
+ − 97 XtRCallback, sizeof (XtCallbackList),
+ − 98 offset(shell_ready_callback), XtRImmediate, (XtPointer)NULL },
+ − 99 { XtNshellName, XtCShellName,
+ − 100 XtRString, sizeof (String),
+ − 101 offset(shell_name), XtRImmediate, (XtPointer)NULL },
+ − 102 { XtNuseToolTalk, XtCUseToolTalk,
+ − 103 XtRBoolean, sizeof (Boolean),
+ − 104 offset(use_tooltalk), XtRImmediate, (XtPointer)False }
428
+ − 105 };
+ − 106
+ − 107 static XtActionsRec actions[] = {
+ − 108 {"focusIn", ExternalClientFocusIn},
+ − 109 {"focusOut", ExternalClientFocusOut},
+ − 110 {"enter", ExternalClientEnter},
+ − 111 {"leave", ExternalClientLeave},
+ − 112 };
+ − 113
+ − 114 ExternalClientClassRec externalClientClassRec = {
+ − 115 { /*
+ − 116 * core_class fields
+ − 117 */
+ − 118 #ifdef EXTW_USES_MOTIF
+ − 119 /* superclass */ (WidgetClass) &xmPrimitiveClassRec,
+ − 120 #else
+ − 121 /* superclass */ (WidgetClass) &coreClassRec,
+ − 122 #endif
+ − 123 /* class_name */ "ExternalClient",
440
+ − 124 /* size */ sizeof (ExternalClientRec),
428
+ − 125 /* Class Initializer */ NULL,
+ − 126 /* class_part_initialize*/ NULL, /* XtInheritClassPartInitialize, */
+ − 127 /* Class init'ed ? */ FALSE,
+ − 128 /* initialize */ externalClientInitialize,
+ − 129 /* initialize_notify */ NULL,
440
+ − 130 /* realize */ externalClientRealize,
428
+ − 131 /* actions */ actions,
+ − 132 /* num_actions */ XtNumber (actions),
+ − 133 /* resources */ resources,
+ − 134 /* resource_count */ XtNumber (resources),
+ − 135 /* xrm_class */ NULLQUARK,
+ − 136 /* compress_motion */ FALSE,
+ − 137 /* compress_exposure */ TRUE,
+ − 138 /* compress_enterleave*/ FALSE,
+ − 139 /* visible_interest */ TRUE,
+ − 140 /* destroy */ Destroy, /* XtInheritDestroy, */
+ − 141 /* resize */ XtInheritResize,
+ − 142 /* expose */ NULL,
+ − 143 /* set_values */ NULL, /* XtInheritSetValues, */
440
+ − 144 /* set_values_hook */ NULL,
+ − 145 /* set_values_almost */ XtInheritSetValuesAlmost,
+ − 146 /* get_values_hook */ NULL,
428
+ − 147 /* accept_focus */ NULL,
+ − 148 /* intrinsics version */ XtVersion,
+ − 149 /* callback offsets */ NULL,
+ − 150 /* tm_table */ "", /* MUST NOT BE NULL or
+ − 151 XtInheritTranslations in Motif!!!!!
+ − 152 Otherwise keyboard focus translations
+ − 153 will not work. */
+ − 154 /* query_geometry */ QueryGeometry,
+ − 155 /* display_accelerator*/ NULL,
+ − 156 /* extension */ NULL
+ − 157 },
+ − 158 #ifdef EXTW_USES_MOTIF
+ − 159 {
+ − 160 XmInheritBorderHighlight,/* Primitive border_highlight */
+ − 161 XmInheritBorderHighlight,/* Primitive border_unhighlight */
+ − 162 XtInheritTranslations, /* translations */
+ − 163 NULL, /* arm_and_activate */
+ − 164 NULL, /* get resources */
+ − 165 0, /* num get_resources */
+ − 166 NULL, /* extension */
+ − 167 },
+ − 168 #endif
+ − 169 {
+ − 170 0
+ − 171 }
+ − 172 };
+ − 173
+ − 174 WidgetClass externalClientWidgetClass = (WidgetClass) &externalClientClassRec;
+ − 175
+ − 176 static void
2286
+ − 177 externalClientInitialize (Widget UNUSED (req), Widget new,
+ − 178 ArgList UNUSED (args), Cardinal *UNUSED (num_args))
428
+ − 179 {
+ − 180 ExternalClientWidget ecw = (ExternalClientWidget) new;
+ − 181 static int error_handler_added = 0;
+ − 182
+ − 183 extw_initialize_atoms (XtDisplay (new));
+ − 184 extw_which_side = extw_client_send;
+ − 185
+ − 186 #ifdef EXTW_USES_MOTIF
+ − 187
+ − 188 /* yes I know this is horrible. However, the XmPrimitive class adds
+ − 189 the Tab translation in its initialization routine, so we have to
+ − 190 override it here. This is all the fault of Xt, which doesn't
+ − 191 provide a proper inheritance mechanism for translations.
+ − 192
+ − 193 -- BPW
+ − 194
+ − 195 */
440
+ − 196
428
+ − 197 XtOverrideTranslations (new,
+ − 198 XtParseTranslationTable ("None<Key>Tab:\n"
+ − 199 "<FocusIn>:focusIn()\n"
+ − 200 "<FocusOut>:focusOut()\n"
+ − 201 "<Enter>:enter()\n"
+ − 202 "<Leave>:leave()\n"));
+ − 203
+ − 204 #endif
440
+ − 205
428
+ − 206 XtAddEventHandler (new, 0, TRUE, EventHandler, (XtPointer) NULL);
+ − 207
+ − 208 ecw->externalClient.shell_ready = False;
+ − 209 ecw->externalClient.has_focus = False;
+ − 210
+ − 211 if (!error_handler_added)
+ − 212 {
+ − 213 error_handler_added = 1;
+ − 214 error_old_handler = XSetErrorHandler (my_error_handler);
+ − 215 }
+ − 216 }
+ − 217
+ − 218
+ − 219 #ifdef TOOLTALK
+ − 220 static Tt_callback_action
2286
+ − 221 tt_callback(Tt_message m, Tt_pattern UNUSED (p))
428
+ − 222 {
+ − 223 ExternalClientWidget ecw = (ExternalClientWidget)tt_message_user (m, 0);
440
+ − 224
428
+ − 225 switch (tt_message_state(m))
+ − 226 {
+ − 227 case TT_FAILED:
+ − 228 /* handle errors here */
+ − 229 break;
+ − 230 case TT_HANDLED:
+ − 231 ecw->externalClient.shell_name = tt_message_arg_val (m, 2);
+ − 232 XtCallCallbackList ((Widget) ecw,
+ − 233 ecw->externalClient.shell_ready_callback, NULL);
+ − 234 break;
+ − 235 }
440
+ − 236
428
+ − 237 tt_message_destroy (m);
+ − 238 return TT_CALLBACK_PROCESSED;
+ − 239 }
+ − 240
+ − 241 static void
+ − 242 send_tooltalk_handshake (ExternalClientWidget ecw, Window win, char *name)
+ − 243 {
+ − 244 Tt_message m = tt_message_create ();
+ − 245
+ − 246 tt_message_op_set (m, "emacs-make-client-screen");
+ − 247 tt_message_scope_set (m, TT_SESSION);
+ − 248 tt_message_class_set (m, TT_REQUEST);
+ − 249 tt_message_arg_add (m, TT_IN, "string", name);
+ − 250 tt_message_iarg_add (m, TT_IN, "int", win);
440
+ − 251 tt_message_arg_add (m, TT_OUT, "string", NULL);
428
+ − 252 tt_message_user_set (m, 0, (void *)ecw);
+ − 253 tt_message_callback_add (m, tt_callback);
+ − 254 if (ecw->externalClient.emacs_procid)
+ − 255 {
+ − 256 tt_message_address_set (m, TT_HANDLER);
+ − 257 tt_message_handler_set (m, ecw->externalClient.emacs_procid);
+ − 258 }
+ − 259 else
+ − 260 tt_message_address_set (m, TT_PROCEDURE);
+ − 261 tt_message_send (m);
+ − 262 }
+ − 263
+ − 264 #endif
+ − 265
+ − 266
+ − 267 static void
+ − 268 externalClientRealize (Widget w, XtValueMask *vm, XSetWindowAttributes *attrs)
+ − 269 {
1094
+ − 270 #ifdef TOOLTALK
428
+ − 271 ExternalClientWidget ecw = (ExternalClientWidget)w;
1094
+ − 272 #endif
440
+ − 273
+ − 274 #ifdef EXTW_USES_MOTIF
428
+ − 275 (*xmPrimitiveWidgetClass->core_class.realize) (w, vm, attrs);
+ − 276 #else
+ − 277 (*coreWidgetClass->core_class.realize) (w, vm, attrs);
+ − 278 #endif
+ − 279
+ − 280 #ifdef TOOLTALK
+ − 281 /* Make sure that the server actually knows about this window id before
+ − 282 * telling Emacs about it.
+ − 283 */
+ − 284 if (ecw->externalClient.use_tooltalk)
+ − 285 {
+ − 286 XSync (XtDisplay (w), False);
+ − 287 send_tooltalk_handshake (ecw, XtWindow (w), XtName (w));
+ − 288 }
440
+ − 289 #endif
428
+ − 290 }
+ − 291
+ − 292
+ − 293 /***********************************************************************/
+ − 294
+ − 295 /* window-to-widget list. */
+ − 296
+ − 297 struct ww_list
+ − 298 {
+ − 299 Window win;
+ − 300 Widget wid;
+ − 301 struct ww_list *next;
+ − 302 };
+ − 303
+ − 304 struct ww_list ww_list[1];
+ − 305
+ − 306 static int
+ − 307 add_ww (Window win, Widget wid)
+ − 308 {
+ − 309 struct ww_list *ww = (struct ww_list *) malloc (sizeof (struct
+ − 310 ww_list));
+ − 311 if (!ww)
+ − 312 return 0;
+ − 313 ww->win = win;
+ − 314 ww->wid = wid;
+ − 315 ww->next = ww_list->next;
+ − 316 ww_list->next = ww;
+ − 317 return 1;
+ − 318 }
+ − 319
+ − 320 static Widget
+ − 321 remove_ww (Window win)
+ − 322 {
+ − 323 struct ww_list *w1, *w2;
+ − 324 Widget wid = 0;
440
+ − 325
428
+ − 326 for (w1=ww_list, w2=w1->next; w2; w1=w2, w2=w2->next)
+ − 327 if (w2->win == win)
+ − 328 {
+ − 329 w1->next = w2->next;
+ − 330 wid = w2->wid;
+ − 331 free (w2);
+ − 332 break;
+ − 333 }
+ − 334 return wid;
+ − 335 }
+ − 336
+ − 337 /***********************************************************************/
+ − 338
+ − 339 /* stolen outright from Intrinsic.c */
+ − 340
2108
+ − 341 static void
+ − 342 ComputeWindowAttributes (Widget widget, XtValueMask *value_mask,
+ − 343 XSetWindowAttributes *values)
428
+ − 344 {
+ − 345 *value_mask = CWEventMask | CWColormap;
+ − 346 (*values).event_mask = XtBuildEventMask(widget);
+ − 347 (*values).colormap = widget->core.colormap;
+ − 348 if (widget->core.background_pixmap != XtUnspecifiedPixmap) {
+ − 349 *value_mask |= CWBackPixmap;
+ − 350 (*values).background_pixmap = widget->core.background_pixmap;
+ − 351 } else {
+ − 352 *value_mask |= CWBackPixel;
+ − 353 (*values).background_pixel = widget->core.background_pixel;
+ − 354 }
+ − 355 if (widget->core.border_pixmap != XtUnspecifiedPixmap) {
+ − 356 *value_mask |= CWBorderPixmap;
+ − 357 (*values).border_pixmap = widget->core.border_pixmap;
+ − 358 } else {
+ − 359 *value_mask |= CWBorderPixel;
+ − 360 (*values).border_pixel = widget->core.border_pixel;
+ − 361 }
+ − 362 if (widget->core.widget_class->core_class.expose == (XtExposeProc) NULL) {
+ − 363 /* Try to avoid redisplay upon resize by making bit_gravity the same
+ − 364 as the default win_gravity */
+ − 365 *value_mask |= CWBitGravity;
+ − 366 (*values).bit_gravity = NorthWestGravity;
+ − 367 }
+ − 368 } /* ComputeWindowAttributes */
+ − 369
+ − 370 static void
+ − 371 end_connection (ExternalClientWidget w)
+ − 372 {
+ − 373 XSetWindowAttributes xswa;
+ − 374 XtValueMask mask;
+ − 375 Widget wid = (Widget) w;
440
+ − 376
428
+ − 377 w->externalClient.shell_ready = False;
+ − 378 XtRemoveEventHandler (wid, w->externalClient.event_mask,
+ − 379 FALSE, MaskableEventHandler, (XtPointer) NULL);
+ − 380 ComputeWindowAttributes (wid, &mask, &xswa);
+ − 381 XChangeWindowAttributes (XtDisplay (wid), XtWindow (wid), mask, &xswa);
+ − 382 XClearArea (XtDisplay (wid), XtWindow (wid), 0, 0, 0, 0, True);
+ − 383 }
+ − 384
+ − 385 static int
+ − 386 my_error_handler (Display *display, XErrorEvent *xev)
+ − 387 {
+ − 388 Widget wid;
440
+ − 389
428
+ − 390 if (xev->error_code != BadWindow)
+ − 391 goto call_old;
+ − 392 wid = remove_ww (xev->resourceid);
+ − 393 if (wid)
+ − 394 {
+ − 395 end_connection ((ExternalClientWidget) wid);
+ − 396 return 0;
+ − 397 }
440
+ − 398
428
+ − 399 call_old:
+ − 400 return error_old_handler (display, xev);
+ − 401 }
+ − 402
+ − 403 static void
2286
+ − 404 MaskableEventHandler (Widget wid, XtPointer UNUSED (closure), XEvent *event,
+ − 405 Boolean *UNUSED (continue_to_dispatch))
428
+ − 406 {
+ − 407 ExternalClientWidget w = (ExternalClientWidget) wid;
440
+ − 408
428
+ − 409 if (w->externalClient.shell_ready)
+ − 410 {
+ − 411 if (event->type == KeyPress || event->type == KeyRelease ||
+ − 412 event->type == ButtonPress || event->type == ButtonRelease ||
+ − 413 event->type == MotionNotify)
+ − 414 event->xkey.subwindow = 0;
+ − 415 #ifdef EXTW_USES_MOTIF
+ − 416 /* hackkkkkkkkkkkkkk! Suppress CTRL-TAB, SHIFT-TAB, etc. so that
+ − 417 Emacs doesn't attempt to interpret focus-change keystrokes. */
+ − 418 if (event->type == KeyPress &&
+ − 419 XLookupKeysym ((XKeyEvent *) event, 0) == XK_Tab &&
+ − 420 (event->xkey.state & ControlMask ||
+ − 421 event->xkey.state & ShiftMask))
+ − 422 return;
+ − 423 #endif
+ − 424 event->xany.window = w->core.window;
+ − 425 XSendEvent (XtDisplay (wid), w->externalClient.event_window, FALSE, 0,
+ − 426 event);
+ − 427 XSync (XtDisplay (wid), 0); /* make sure that any BadWindow errors
+ − 428 (meaning the server died) get handled
+ − 429 before XSendEvent is called again. */
440
+ − 430
428
+ − 431 }
+ − 432 }
+ − 433
+ − 434 static void
2286
+ − 435 EventHandler (Widget wid, XtPointer UNUSED (closure), XEvent *event,
+ − 436 Boolean *UNUSED (continue_to_dispatch))
428
+ − 437 {
+ − 438 ExternalClientWidget w = (ExternalClientWidget) wid;
440
+ − 439
428
+ − 440 if (w->core.window != event->xany.window)
+ − 441 {
+ − 442 XtAppErrorMsg (XtWidgetToApplicationContext (wid),
+ − 443 "invalidWindow","eventHandler",XtCXtToolkitError,
+ − 444 "Event with wrong window",
+ − 445 (String *)NULL, (Cardinal *)NULL);
+ − 446 return;
+ − 447 }
440
+ − 448
428
+ − 449 if (event->type == ClientMessage &&
+ − 450 event->xclient.message_type == a_EXTW_NOTIFY &&
+ − 451 event->xclient.data.l[0] == extw_shell_send)
+ − 452 switch (event->xclient.data.l[1])
+ − 453 {
440
+ − 454
428
+ − 455 case extw_notify_qg:
+ − 456 /* shell is alive again. */
440
+ − 457
428
+ − 458 w->externalClient.dead_shell = False;
+ − 459 break;
440
+ − 460
428
+ − 461 case extw_notify_gm:
+ − 462 {
+ − 463 XtWidgetGeometry xwg, xwg_return;
+ − 464 XtGeometryResult result;
440
+ − 465
428
+ − 466 extw_get_geometry_value (XtDisplay (wid), XtWindow (wid),
+ − 467 a_EXTW_GEOMETRY_MANAGER, &xwg);
+ − 468 result = XtMakeGeometryRequest (wid, &xwg, &xwg_return);
440
+ − 469
428
+ − 470 extw_send_geometry_value (XtDisplay (wid), XtWindow (wid),
+ − 471 a_EXTW_GEOMETRY_MANAGER, extw_notify_gm,
+ − 472 result == XtGeometryAlmost ? &xwg_return :
+ − 473 NULL, result);
+ − 474 break;
+ − 475 }
440
+ − 476
428
+ − 477 case extw_notify_init:
+ − 478 w->externalClient.shell_ready = True;
+ − 479 w->externalClient.event_window = event->xclient.data.l[2];
+ − 480 w->externalClient.event_mask = event->xclient.data.l[3];
+ − 481 add_ww (w->externalClient.event_window, (Widget) w);
440
+ − 482
428
+ − 483 XtAddEventHandler (wid, w->externalClient.event_mask,
+ − 484 FALSE, MaskableEventHandler, (XtPointer) NULL);
+ − 485 #ifdef EXTW_USES_MOTIF
+ − 486 NOTIFY (w, extw_notify_init,
+ − 487 EXTW_TYPE_MOTIF,
+ − 488 0, 0);
+ − 489 #else
+ − 490 NOTIFY (w, extw_notify_init,
+ − 491 EXTW_TYPE_XT,
+ − 492 0, 0);
+ − 493 #endif
+ − 494 break;
440
+ − 495
428
+ − 496 case extw_notify_end:
+ − 497 end_connection (w);
+ − 498 remove_ww (w->externalClient.event_window);
+ − 499 break;
440
+ − 500
428
+ − 501 case extw_notify_set_focus:
+ − 502 #ifdef EXTW_USES_MOTIF
+ − 503 XmProcessTraversal (wid, XmTRAVERSE_CURRENT);
+ − 504 #else
+ − 505 XtSetKeyboardFocus (wid, None);
+ − 506 #endif
+ − 507 break;
440
+ − 508
428
+ − 509 }
+ − 510 }
+ − 511
2108
+ − 512 static void Destroy (Widget wid)
428
+ − 513 {
+ − 514 ExternalClientWidget w = (ExternalClientWidget)wid;
440
+ − 515
428
+ − 516 NOTIFY(w, extw_notify_end, 0, 0, 0);
+ − 517 }
+ − 518
2108
+ − 519 static XtGeometryResult
+ − 520 QueryGeometry (Widget gw, XtWidgetGeometry *request, XtWidgetGeometry *reply)
428
+ − 521 {
2108
+ − 522 ExternalClientWidget w = (ExternalClientWidget) gw;
428
+ − 523 XEvent event;
+ − 524 unsigned long request_num;
+ − 525 Display *display = XtDisplay(gw);
+ − 526 XtWidgetGeometry req = *request; /* don't modify caller's structure */
440
+ − 527
428
+ − 528 if (!XtIsRealized((Widget)w) || !w->externalClient.shell_ready)
+ − 529 return XtGeometryYes;
440
+ − 530
428
+ − 531 if (w->externalClient.dead_shell == TRUE)
+ − 532 /* The shell is sick. */
+ − 533 return XtGeometryNo;
440
+ − 534
428
+ − 535 req.sibling = None;
+ − 536 req.request_mode &= ~CWSibling;
+ − 537 request_num = NextRequest(display);
+ − 538 extw_send_geometry_value(XtDisplay(gw), XtWindow(gw), a_EXTW_QUERY_GEOMETRY,
+ − 539 extw_notify_qg, &req, 0);
+ − 540
+ − 541 if (extw_wait_for_response(gw, &event, request_num, extw_notify_qg,
+ − 542 w->externalClient.shell_timeout)) {
+ − 543 XtGeometryResult result = (XtGeometryResult) event.xclient.data.l[0];
+ − 544
+ − 545 if (result == XtGeometryAlmost) {
+ − 546 extw_get_geometry_value(XtDisplay(gw), XtWindow(gw),
+ − 547 a_EXTW_QUERY_GEOMETRY, reply);
+ − 548 }
+ − 549 return result;
+ − 550 } else {
+ − 551 w->externalClient.dead_shell = TRUE; /* timed out; must be broken */
+ − 552 return XtGeometryNo;
+ − 553 }
+ − 554 }
+ − 555
2286
+ − 556 #ifdef EXTW_USES_MOTIF
+ − 557 # define USED_IF_MOTIF(decl) decl
+ − 558 #else
+ − 559 # define USED_IF_MOTIF(decl) UNUSED (decl)
+ − 560 #endif
+ − 561
+ − 562 static void ExternalClientFocusIn (Widget w, XEvent *event,
+ − 563 String *USED_IF_MOTIF (params),
+ − 564 Cardinal *USED_IF_MOTIF (num_params))
428
+ − 565 {
+ − 566 ExternalClientWidget ecw = (ExternalClientWidget) w;
440
+ − 567
428
+ − 568 if (event->xfocus.send_event && !ecw->externalClient.has_focus) {
+ − 569 ecw->externalClient.has_focus = True;
+ − 570 NOTIFY(ecw, extw_notify_focus_in, 0, 0, 0);
+ − 571 }
+ − 572 #ifdef EXTW_USES_MOTIF
+ − 573 _XmPrimitiveFocusIn (w, event, params, num_params);
+ − 574 #endif
+ − 575 }
+ − 576
2286
+ − 577 static void ExternalClientFocusOut (Widget w, XEvent *event,
+ − 578 String *USED_IF_MOTIF (params),
+ − 579 Cardinal *USED_IF_MOTIF (num_params))
428
+ − 580 {
+ − 581 ExternalClientWidget ecw = (ExternalClientWidget) w;
440
+ − 582
428
+ − 583 if (event->xfocus.send_event && ecw->externalClient.has_focus) {
+ − 584 ecw->externalClient.has_focus = False;
+ − 585 NOTIFY(ecw, extw_notify_focus_out, 0, 0, 0);
+ − 586 }
+ − 587 #ifdef EXTW_USES_MOTIF
+ − 588 _XmPrimitiveFocusOut(w, event, params, num_params);
+ − 589 #endif
+ − 590 }
+ − 591
2286
+ − 592 static void ExternalClientEnter (Widget w, XEvent *event,
+ − 593 String *USED_IF_MOTIF (params),
+ − 594 Cardinal *USED_IF_MOTIF (num_params))
428
+ − 595 {
+ − 596 ExternalClientWidget ecw = (ExternalClientWidget) w;
440
+ − 597
428
+ − 598 if (
+ − 599 #ifdef EXTW_USES_MOTIF
+ − 600 _XmGetFocusPolicy (w) != XmEXPLICIT &&
+ − 601 #endif
+ − 602 !ecw->externalClient.has_focus &&
+ − 603 event->xcrossing.focus && event->xcrossing.detail != NotifyInferior) {
+ − 604 ecw->externalClient.has_focus = True;
+ − 605 NOTIFY(ecw, extw_notify_focus_in, 0, 0, 0);
+ − 606 }
+ − 607 #ifdef EXTW_USES_MOTIF
+ − 608 _XmPrimitiveEnter (w, event, params, num_params);
+ − 609 #endif
+ − 610 }
+ − 611
2286
+ − 612 static void ExternalClientLeave (Widget w, XEvent *event,
+ − 613 String *USED_IF_MOTIF (params),
+ − 614 Cardinal *USED_IF_MOTIF (num_params))
428
+ − 615 {
+ − 616 ExternalClientWidget ecw = (ExternalClientWidget) w;
440
+ − 617
428
+ − 618 if (
+ − 619 #ifdef EXTW_USES_MOTIF
+ − 620 _XmGetFocusPolicy (w) != XmEXPLICIT &&
+ − 621 #endif
+ − 622 ecw->externalClient.has_focus &&
+ − 623 event->xcrossing.focus && event->xcrossing.detail != NotifyInferior) {
+ − 624 ecw->externalClient.has_focus = False;
+ − 625 NOTIFY(ecw, extw_notify_focus_out, 0, 0, 0);
+ − 626 }
+ − 627 #ifdef EXTW_USES_MOTIF
+ − 628 _XmPrimitiveLeave (w, event, params, num_params);
+ − 629 #endif
+ − 630 }