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