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