4
* This file contains platform-specific procedures for theMac to provide
5
* basic operations needed for application embedding (where one
6
* application can use as its main window an internal window from
7
* some other application).
8
* Currently only Toplevel embedding within the same Tk application is
9
* allowed on the Macintosh.
11
* Copyright (c) 1996-97 Sun Microsystems, Inc.
13
* See the file "license.terms" for information on usage and redistribution
14
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16
* RCS: @(#) $Id: tkMacEmbed.c,v 1.3 1998/09/14 18:23:35 stanton Exp $
26
#include <QDOffscreen.h>
30
* One of the following structures exists for each container in this
31
* application. It keeps track of the container window and its
32
* associated embedded window.
35
typedef struct Container {
36
Window parent; /* The Mac Drawable for the parent of
37
* the pair (the container). */
38
TkWindow *parentPtr; /* Tk's information about the container,
39
* or NULL if the container isn't
41
Window embedded; /* The MacDrawable for the embedded
42
* window. Starts off as None, but
43
* gets filled in when the window is
44
* eventually created. */
45
TkWindow *embeddedPtr; /* Tk's information about the embedded
46
* window, or NULL if the
47
* embedded application isn't in
49
struct Container *nextPtr; /* Next in list of all containers in
53
static Container *firstContainerPtr = NULL;
54
/* First in list of all containers
55
* managed by this process. */
57
* Globals defined in this file
60
TkMacEmbedHandler *gMacEmbedHandler = NULL;
63
* Prototypes for static procedures defined in this file:
66
static void ContainerEventProc _ANSI_ARGS_((
67
ClientData clientData, XEvent *eventPtr));
68
static void EmbeddedEventProc _ANSI_ARGS_((
69
ClientData clientData, XEvent *eventPtr));
70
static void EmbedActivateProc _ANSI_ARGS_((ClientData clientData,
72
static void EmbedFocusProc _ANSI_ARGS_((ClientData clientData,
74
static void EmbedGeometryRequest _ANSI_ARGS_((
75
Container * containerPtr, int width, int height));
76
static void EmbedSendConfigure _ANSI_ARGS_((
77
Container *containerPtr));
78
static void EmbedStructureProc _ANSI_ARGS_((ClientData clientData,
80
static void EmbedWindowDeleted _ANSI_ARGS_((TkWindow *winPtr));
84
*----------------------------------------------------------------------
86
* Tk_MacSetEmbedHandler --
88
* Registers a handler for an in process form of embedding, like
89
* Netscape plugins, where Tk is loaded into the process, but does
90
* not control the main window
96
* The embed handler is set.
98
*----------------------------------------------------------------------
101
Tk_MacSetEmbedHandler(
102
Tk_MacEmbedRegisterWinProc *registerWinProc,
103
Tk_MacEmbedGetGrafPortProc *getPortProc,
104
Tk_MacEmbedMakeContainerExistProc *containerExistProc,
105
Tk_MacEmbedGetClipProc *getClipProc,
106
Tk_MacEmbedGetOffsetInParentProc *getOffsetProc)
108
if (gMacEmbedHandler == NULL) {
109
gMacEmbedHandler = (TkMacEmbedHandler *) ckalloc(sizeof(TkMacEmbedHandler));
111
gMacEmbedHandler->registerWinProc = registerWinProc;
112
gMacEmbedHandler->getPortProc = getPortProc;
113
gMacEmbedHandler->containerExistProc = containerExistProc;
114
gMacEmbedHandler->getClipProc = getClipProc;
115
gMacEmbedHandler->getOffsetProc = getOffsetProc;
120
*----------------------------------------------------------------------
124
* Creates an X Window (Mac subwindow).
127
* The window id is returned.
132
*----------------------------------------------------------------------
144
* If this window is marked as embedded then
145
* the window structure should have already been
146
* created in the TkpUseWindow function.
149
if (Tk_IsEmbedded(winPtr)) {
150
return (Window) winPtr->privatePtr;
154
* Allocate sub window
157
macWin = (MacDrawable *) ckalloc(sizeof(MacDrawable));
158
if (macWin == NULL) {
159
winPtr->privatePtr = NULL;
162
macWin->winPtr = winPtr;
163
winPtr->privatePtr = macWin;
164
macWin->clipRgn = NewRgn();
165
macWin->aboveClipRgn = NewRgn();
166
macWin->referenceCount = 0;
167
macWin->flags = TK_CLIP_INVALID;
169
if (Tk_IsTopLevel(macWin->winPtr)) {
172
*This will be set when we are mapped.
175
macWin->portPtr = (GWorldPtr) NULL;
176
macWin->toplevel = macWin;
180
macWin->portPtr = NULL;
181
macWin->xOff = winPtr->parentPtr->privatePtr->xOff +
182
winPtr->parentPtr->changes.border_width +
184
macWin->yOff = winPtr->parentPtr->privatePtr->yOff +
185
winPtr->parentPtr->changes.border_width +
187
macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel;
190
macWin->toplevel->referenceCount++;
193
* TODO: need general solution for visibility events.
195
event.xany.serial = Tk_Display(winPtr)->request;
196
event.xany.send_event = False;
197
event.xany.display = Tk_Display(winPtr);
199
event.xvisibility.type = VisibilityNotify;
200
event.xvisibility.window = (Window) macWin;;
201
event.xvisibility.state = VisibilityUnobscured;
202
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
204
return (Window) macWin;
208
*----------------------------------------------------------------------
212
* This procedure causes a Tk window to use a given X window as
213
* its parent window, rather than the root window for the screen.
214
* It is invoked by an embedded application to specify the window
215
* in which it is embedded.
218
* The return value is normally TCL_OK. If an error occurs (such
219
* as string not being a valid window spec), then the return value
220
* is TCL_ERROR and an error message is left in interp->result if
221
* interp is non-NULL.
226
*----------------------------------------------------------------------
231
Tcl_Interp *interp, /* If not NULL, used for error reporting
232
* if string is bogus. */
233
Tk_Window tkwin, /* Tk window that does not yet have an
234
* associated X window. */
235
char *string) /* String identifying an X window to use
236
* for tkwin; must be an integer value. */
238
TkWindow *winPtr = (TkWindow *) tkwin;
239
MacDrawable *parent, *macWin;
240
Container *containerPtr;
244
if (winPtr->window != None) {
245
panic("TkpUseWindow: X window already assigned");
249
* Decode the container pointer, and look for it among the
250
*list of available containers.
252
* N.B. For now, we are limiting the containers to be in the same Tk
253
* application as tkwin, since otherwise they would not be in our list
258
if (Tcl_GetInt(interp, string, &result) != TCL_OK) {
262
parent = (MacDrawable *) result;
265
* Save information about the container and the embedded window
266
* in a Container structure. Currently, there must already be an existing
267
* Container structure, since we only allow the case where both container
268
* and embedded app. are in the same process.
271
for (containerPtr = firstContainerPtr; containerPtr != NULL;
272
containerPtr = containerPtr->nextPtr) {
273
if (containerPtr->parent == (Window) parent) {
274
winPtr->flags |= TK_BOTH_HALVES;
275
containerPtr->parentPtr->flags |= TK_BOTH_HALVES;
281
* Make the embedded window.
284
macWin = (MacDrawable *) ckalloc(sizeof(MacDrawable));
285
if (macWin == NULL) {
286
winPtr->privatePtr = NULL;
290
macWin->winPtr = winPtr;
291
winPtr->privatePtr = macWin;
294
* The portPtr will be NULL for a Tk in Tk embedded window.
295
* It is none of our business what it is for a Tk not in Tk embedded window,
296
* but we will initialize it to NULL, and let the registerWinProc
297
* set it. In any case, you must always use TkMacGetDrawablePort
298
* to get the portPtr. It will correctly find the container's port.
301
macWin->portPtr = (GWorldPtr) NULL;
303
macWin->clipRgn = NewRgn();
304
macWin->aboveClipRgn = NewRgn();
305
macWin->referenceCount = 0;
306
macWin->flags = TK_CLIP_INVALID;
307
macWin->toplevel = macWin;
308
macWin->toplevel->referenceCount++;
310
winPtr->flags |= TK_EMBEDDED;
314
* Make a copy of the TK_EMBEDDED flag, since sometimes
315
* we need this to get the port after the TkWindow structure
319
macWin->flags |= TK_EMBEDDED;
322
* Now check whether it is embedded in another Tk widget. If not (the first
323
* case below) we see if there is an in-process embedding handler registered,
324
* and if so, let that fill in the rest of the macWin.
327
if (containerPtr == NULL) {
329
* If someone has registered an in process embedding handler, then
330
* see if it can handle this window...
333
if (gMacEmbedHandler == NULL ||
334
gMacEmbedHandler->registerWinProc(result, (Tk_Window) winPtr) != TCL_OK) {
335
Tcl_AppendResult(interp, "The window ID ", string,
336
" does not correspond to a valid Tk Window.",
340
containerPtr = (Container *) ckalloc(sizeof(Container));
342
containerPtr->parentPtr = NULL;
343
containerPtr->embedded = (Window) macWin;
344
containerPtr->embeddedPtr = macWin->winPtr;
345
containerPtr->nextPtr = firstContainerPtr;
346
firstContainerPtr = containerPtr;
352
* The window is embedded in another Tk window.
355
macWin->xOff = parent->winPtr->privatePtr->xOff +
356
parent->winPtr->changes.border_width +
358
macWin->yOff = parent->winPtr->privatePtr->yOff +
359
parent->winPtr->changes.border_width +
364
* Finish filling up the container structure with the embedded window's
368
containerPtr->embedded = (Window) macWin;
369
containerPtr->embeddedPtr = macWin->winPtr;
372
* Create an event handler to clean up the Container structure when
373
* tkwin is eventually deleted.
376
Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc,
377
(ClientData) winPtr);
382
* TODO: need general solution for visibility events.
385
event.xany.serial = Tk_Display(winPtr)->request;
386
event.xany.send_event = False;
387
event.xany.display = Tk_Display(winPtr);
389
event.xvisibility.type = VisibilityNotify;
390
event.xvisibility.window = (Window) macWin;;
391
event.xvisibility.state = VisibilityUnobscured;
392
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
396
* TODO: need general solution for visibility events.
399
event.xany.serial = Tk_Display(winPtr)->request;
400
event.xany.send_event = False;
401
event.xany.display = Tk_Display(winPtr);
403
event.xvisibility.type = VisibilityNotify;
404
event.xvisibility.window = (Window) macWin;;
405
event.xvisibility.state = VisibilityUnobscured;
406
Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
412
*----------------------------------------------------------------------
414
* TkpMakeContainer --
416
* This procedure is called to indicate that a particular window
417
* will be a container for an embedded application. This changes
418
* certain aspects of the window's behavior, such as whether it
419
* will receive events anymore.
427
*----------------------------------------------------------------------
432
Tk_Window tkwin) /* Token for a window that is about to
433
* become a container. */
435
TkWindow *winPtr = (TkWindow *) tkwin;
436
Container *containerPtr;
439
* Register the window as a container so that, for example, we can
440
* make sure the argument to -use is valid.
444
Tk_MakeWindowExist(tkwin);
445
containerPtr = (Container *) ckalloc(sizeof(Container));
446
containerPtr->parent = Tk_WindowId(tkwin);
447
containerPtr->parentPtr = winPtr;
448
containerPtr->embedded = None;
449
containerPtr->embeddedPtr = NULL;
450
containerPtr->nextPtr = firstContainerPtr;
451
firstContainerPtr = containerPtr;
452
winPtr->flags |= TK_CONTAINER;
455
* Request SubstructureNotify events so that we can find out when
456
* the embedded application creates its window or attempts to
457
* resize it. Also watch Configure events on the container so that
458
* we can resize the child to match. Also, pass activate events from
459
* the container down to the embedded toplevel.
462
Tk_CreateEventHandler(tkwin,
463
SubstructureNotifyMask|SubstructureRedirectMask,
464
ContainerEventProc, (ClientData) winPtr);
465
Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbedStructureProc,
466
(ClientData) containerPtr);
467
Tk_CreateEventHandler(tkwin, ActivateMask, EmbedActivateProc,
468
(ClientData) containerPtr);
469
Tk_CreateEventHandler(tkwin, FocusChangeMask, EmbedFocusProc,
470
(ClientData) containerPtr);
475
*----------------------------------------------------------------------
477
* TkMacContainerId --
479
* Given an embedded window, this procedure returns the MacDrawable
480
* identifier for the associated container window.
483
* The return value is the MacDrawable for winPtr's
489
*----------------------------------------------------------------------
493
TkMacContainerId(winPtr)
494
TkWindow *winPtr; /* Tk's structure for an embedded window. */
496
Container *containerPtr;
498
for (containerPtr = firstContainerPtr; containerPtr != NULL;
499
containerPtr = containerPtr->nextPtr) {
500
if (containerPtr->embeddedPtr == winPtr) {
501
return (MacDrawable *) containerPtr->parent;
504
panic("TkMacContainerId couldn't find window");
509
*----------------------------------------------------------------------
511
* TkMacGetHostToplevel --
513
* Given the TkWindow, return the MacDrawable for the outermost
514
* toplevel containing it. This will be a real Macintosh window.
517
* Returns a MacDrawable corresponding to a Macintosh Toplevel
522
*----------------------------------------------------------------------
526
TkMacGetHostToplevel(
527
TkWindow *winPtr) /* Tk's structure for a window. */
529
TkWindow *contWinPtr, *topWinPtr;
531
topWinPtr = winPtr->privatePtr->toplevel->winPtr;
532
if (!Tk_IsEmbedded(topWinPtr)) {
533
return winPtr->privatePtr->toplevel;
535
contWinPtr = TkpGetOtherWindow(topWinPtr);
538
* NOTE: Here we should handle out of process embedding.
541
if (contWinPtr != NULL) {
542
return TkMacGetHostToplevel(contWinPtr);
550
*----------------------------------------------------------------------
554
* This procedure is invoked when someone asks for the input focus
555
* to be put on a window in an embedded application, but the
556
* application doesn't currently have the focus. It requests the
557
* input focus from the container application.
563
* The input focus may change.
565
*----------------------------------------------------------------------
570
TkWindow *topLevelPtr, /* Top-level window containing desired
571
* focus window; should be embedded. */
572
int force) /* One means that the container should
573
* claim the focus if it doesn't
574
* currently have it. */
577
Container *containerPtr;
579
if (!(topLevelPtr->flags & TK_EMBEDDED)) {
583
for (containerPtr = firstContainerPtr;
584
containerPtr->embeddedPtr != topLevelPtr;
585
containerPtr = containerPtr->nextPtr) {
586
/* Empty loop body. */
590
event.xfocus.type = FocusIn;
591
event.xfocus.serial = LastKnownRequestProcessed(topLevelPtr->display);
592
event.xfocus.send_event = 1;
593
event.xfocus.display = topLevelPtr->display;
594
event.xfocus.window = containerPtr->parent;
595
event.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS;
596
event.xfocus.detail = force;
597
Tk_QueueWindowEvent(&event,TCL_QUEUE_TAIL);
601
*----------------------------------------------------------------------
605
* This procedure implements the "testembed" command. It returns
606
* some or all of the information in the list pointed to by
610
* A standard Tcl result.
615
*----------------------------------------------------------------------
620
ClientData clientData, /* Main window for application. */
621
Tcl_Interp *interp, /* Current interpreter. */
622
int argc, /* Number of arguments. */
623
char **argv) /* Argument strings. */
626
Container *containerPtr;
630
if ((argc > 1) && (strcmp(argv[1], "all") == 0)) {
635
Tcl_DStringInit(&dString);
636
for (containerPtr = firstContainerPtr; containerPtr != NULL;
637
containerPtr = containerPtr->nextPtr) {
638
Tcl_DStringStartSublist(&dString);
639
if (containerPtr->parent == None) {
640
Tcl_DStringAppendElement(&dString, "");
643
sprintf(buffer, "0x%x", (int) containerPtr->parent);
644
Tcl_DStringAppendElement(&dString, buffer);
646
Tcl_DStringAppendElement(&dString, "XXX");
649
if (containerPtr->parentPtr == NULL) {
650
Tcl_DStringAppendElement(&dString, "");
652
Tcl_DStringAppendElement(&dString,
653
containerPtr->parentPtr->pathName);
655
if (containerPtr->embedded == None) {
656
Tcl_DStringAppendElement(&dString, "");
659
sprintf(buffer, "0x%x", (int) containerPtr->embedded);
660
Tcl_DStringAppendElement(&dString, buffer);
662
Tcl_DStringAppendElement(&dString, "XXX");
665
if (containerPtr->embeddedPtr == NULL) {
666
Tcl_DStringAppendElement(&dString, "");
668
Tcl_DStringAppendElement(&dString,
669
containerPtr->embeddedPtr->pathName);
671
Tcl_DStringEndSublist(&dString);
673
Tcl_DStringResult(interp, &dString);
678
*----------------------------------------------------------------------
680
* TkpRedirectKeyEvent --
682
* This procedure is invoked when a key press or release event
683
* arrives for an application that does not believe it owns the
684
* input focus. This can happen because of embedding; for example,
685
* X can send an event to an embedded application when the real
686
* focus window is in the container application and is an ancestor
687
* of the container. This procedure's job is to forward the event
688
* back to the application where it really belongs.
694
* The event may get sent to a different application.
696
*----------------------------------------------------------------------
701
TkWindow *winPtr, /* Window to which the event was originally
703
XEvent *eventPtr) /* X event to redirect (should be KeyPress
709
*----------------------------------------------------------------------
711
* TkpGetOtherWindow --
713
* If both the container and embedded window are in the same
714
* process, this procedure will return either one, given the other.
717
* If winPtr is a container, the return value is the token for the
718
* embedded window, and vice versa. If the "other" window isn't in
719
* this process, NULL is returned.
724
*----------------------------------------------------------------------
729
TkWindow *winPtr) /* Tk's structure for a container or
730
* embedded window. */
732
Container *containerPtr;
735
* TkpGetOtherWindow returns NULL if both windows are not
736
* in the same process...
739
if (!(winPtr->flags & TK_BOTH_HALVES)) {
743
for (containerPtr = firstContainerPtr; containerPtr != NULL;
744
containerPtr = containerPtr->nextPtr) {
745
if (containerPtr->embeddedPtr == winPtr) {
746
return containerPtr->parentPtr;
747
} else if (containerPtr->parentPtr == winPtr) {
748
return containerPtr->embeddedPtr;
754
*----------------------------------------------------------------------
756
* EmbeddedEventProc --
758
* This procedure is invoked by the Tk event dispatcher when various
759
* useful events are received for a window that is embedded in
760
* another application.
766
* Our internal state gets cleaned up when an embedded window is
769
*----------------------------------------------------------------------
773
EmbeddedEventProc(clientData, eventPtr)
774
ClientData clientData; /* Token for container window. */
775
XEvent *eventPtr; /* ResizeRequest event. */
777
TkWindow *winPtr = (TkWindow *) clientData;
779
if (eventPtr->type == DestroyNotify) {
780
EmbedWindowDeleted(winPtr);
785
*----------------------------------------------------------------------
787
* ContainerEventProc --
789
* This procedure is invoked by the Tk event dispatcher when various
790
* useful events are received for the children of a container
791
* window. It forwards relevant information, such as geometry
792
* requests, from the events into the container's application.
794
* NOTE: on the Mac, only the DestroyNotify branch is ever taken.
795
* We don't synthesize the other events.
801
* Depends on the event. For example, when ConfigureRequest events
802
* occur, geometry information gets set for the container window.
804
*----------------------------------------------------------------------
808
ContainerEventProc(clientData, eventPtr)
809
ClientData clientData; /* Token for container window. */
810
XEvent *eventPtr; /* ResizeRequest event. */
812
TkWindow *winPtr = (TkWindow *) clientData;
813
Container *containerPtr;
814
Tk_ErrorHandler errHandler;
817
* Ignore any X protocol errors that happen in this procedure
818
* (almost any operation could fail, for example, if the embedded
819
* application has deleted its window).
822
errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,
823
-1, -1, (Tk_ErrorProc *) NULL, (ClientData) NULL);
826
* Find the Container structure associated with the parent window.
829
for (containerPtr = firstContainerPtr;
830
containerPtr->parent != eventPtr->xmaprequest.parent;
831
containerPtr = containerPtr->nextPtr) {
832
if (containerPtr == NULL) {
833
panic("ContainerEventProc couldn't find Container record");
837
if (eventPtr->type == CreateNotify) {
839
* A new child window has been created in the container. Record
840
* its id in the Container structure (if more than one child is
841
* created, just remember the last one and ignore the earlier
845
containerPtr->embedded = eventPtr->xcreatewindow.window;
846
} else if (eventPtr->type == ConfigureRequest) {
847
if ((eventPtr->xconfigurerequest.x != 0)
848
|| (eventPtr->xconfigurerequest.y != 0)) {
850
* The embedded application is trying to move itself, which
851
* isn't legal. At this point, the window hasn't actually
852
* moved, but we need to send it a ConfigureNotify event to
853
* let it know that its request has been denied. If the
854
* embedded application was also trying to resize itself, a
855
* ConfigureNotify will be sent by the geometry management
856
* code below, so we don't need to do anything. Otherwise,
857
* generate a synthetic event.
860
if ((eventPtr->xconfigurerequest.width == winPtr->changes.width)
861
&& (eventPtr->xconfigurerequest.height
862
== winPtr->changes.height)) {
863
EmbedSendConfigure(containerPtr);
866
EmbedGeometryRequest(containerPtr,
867
eventPtr->xconfigurerequest.width,
868
eventPtr->xconfigurerequest.height);
869
} else if (eventPtr->type == MapRequest) {
871
* The embedded application's map request was ignored and simply
872
* passed on to us, so we have to map the window for it to appear
876
XMapWindow(eventPtr->xmaprequest.display,
877
eventPtr->xmaprequest.window);
878
} else if (eventPtr->type == DestroyNotify) {
880
* The embedded application is gone. Destroy the container window.
883
Tk_DestroyWindow((Tk_Window) winPtr);
885
Tk_DeleteErrorHandler(errHandler);
889
*----------------------------------------------------------------------
891
* EmbedStructureProc --
893
* This procedure is invoked by the Tk event dispatcher when
894
* a container window owned by this application gets resized
895
* (and also at several other times that we don't care about).
896
* This procedure reflects the size change in the embedded
897
* window that corresponds to the container.
903
* The embedded window gets resized to match the container.
905
*----------------------------------------------------------------------
909
EmbedStructureProc(clientData, eventPtr)
910
ClientData clientData; /* Token for container window. */
911
XEvent *eventPtr; /* ResizeRequest event. */
913
Container *containerPtr = (Container *) clientData;
914
Tk_ErrorHandler errHandler;
916
if (eventPtr->type == ConfigureNotify) {
917
if (containerPtr->embedded != None) {
919
* Ignore errors, since the embedded application could have
920
* deleted its window.
923
errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,
924
-1, -1, (Tk_ErrorProc *) NULL, (ClientData) NULL);
925
Tk_MoveResizeWindow((Tk_Window) containerPtr->embeddedPtr, 0, 0,
926
(unsigned int) Tk_Width(
927
(Tk_Window) containerPtr->parentPtr),
928
(unsigned int) Tk_Height(
929
(Tk_Window) containerPtr->parentPtr));
930
Tk_DeleteErrorHandler(errHandler);
932
} else if (eventPtr->type == DestroyNotify) {
933
EmbedWindowDeleted(containerPtr->parentPtr);
938
*----------------------------------------------------------------------
940
* EmbedActivateProc --
942
* This procedure is invoked by the Tk event dispatcher when
943
* Activate and Deactivate events occur for a container window owned
944
* by this application. It is responsible for forwarding an activate
945
* event down into the embedded toplevel.
951
* The X focus may change.
953
*----------------------------------------------------------------------
957
EmbedActivateProc(clientData, eventPtr)
958
ClientData clientData; /* Token for container window. */
959
XEvent *eventPtr; /* ResizeRequest event. */
961
Container *containerPtr = (Container *) clientData;
963
if (containerPtr->embeddedPtr != NULL) {
964
if (eventPtr->type == ActivateNotify) {
965
TkGenerateActivateEvents(containerPtr->embeddedPtr,1);
966
} else if (eventPtr->type == DeactivateNotify) {
967
TkGenerateActivateEvents(containerPtr->embeddedPtr,0);
973
*----------------------------------------------------------------------
977
* This procedure is invoked by the Tk event dispatcher when
978
* FocusIn and FocusOut events occur for a container window owned
979
* by this application. It is responsible for moving the focus
980
* back and forth between a container application and an embedded
987
* The X focus may change.
989
*----------------------------------------------------------------------
993
EmbedFocusProc(clientData, eventPtr)
994
ClientData clientData; /* Token for container window. */
995
XEvent *eventPtr; /* ResizeRequest event. */
997
Container *containerPtr = (Container *) clientData;
1001
if (containerPtr->embeddedPtr != NULL) {
1002
display = Tk_Display(containerPtr->parentPtr);
1003
event.xfocus.serial = LastKnownRequestProcessed(display);
1004
event.xfocus.send_event = false;
1005
event.xfocus.display = display;
1006
event.xfocus.mode = NotifyNormal;
1007
event.xfocus.window = containerPtr->embedded;
1009
if (eventPtr->type == FocusIn) {
1011
* The focus just arrived at the container. Change the X focus
1012
* to move it to the embedded application, if there is one.
1013
* Ignore X errors that occur during this operation (it's
1014
* possible that the new focus window isn't mapped).
1017
event.xfocus.detail = NotifyNonlinear;
1018
event.xfocus.type = FocusIn;
1020
} else if (eventPtr->type == FocusOut) {
1021
/* When the container gets a FocusOut event, it has to tell the embedded app
1022
* that it has lost the focus.
1025
event.xfocus.type = FocusOut;
1026
event.xfocus.detail = NotifyNonlinear;
1029
Tk_QueueWindowEvent(&event, TCL_QUEUE_MARK);
1034
*----------------------------------------------------------------------
1036
* EmbedGeometryRequest --
1038
* This procedure is invoked when an embedded application requests
1039
* a particular size. It processes the request (which may or may
1040
* not actually honor the request) and reflects the results back
1041
* to the embedded application.
1043
* NOTE: On the Mac, this is a stub, since we don't synthesize
1044
* ConfigureRequest events.
1050
* If we deny the child's size change request, a Configure event
1051
* is synthesized to let the child know how big it ought to be.
1052
* Events get processed while we're waiting for the geometry
1053
* managers to do their thing.
1055
*----------------------------------------------------------------------
1059
EmbedGeometryRequest(containerPtr, width, height)
1060
Container *containerPtr; /* Information about the embedding. */
1061
int width, height; /* Size that the child has requested. */
1063
TkWindow *winPtr = containerPtr->parentPtr;
1066
* Forward the requested size into our geometry management hierarchy
1067
* via the container window. We need to send a Configure event back
1068
* to the embedded application if we decide not to honor its
1069
* request; to make this happen, process all idle event handlers
1070
* synchronously here (so that the geometry managers have had a
1071
* chance to do whatever they want to do), and if the window's size
1072
* didn't change then generate a configure event.
1075
Tk_GeometryRequest((Tk_Window) winPtr, width, height);
1076
while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {
1077
/* Empty loop body. */
1079
if ((winPtr->changes.width != width)
1080
|| (winPtr->changes.height != height)) {
1081
EmbedSendConfigure(containerPtr);
1086
*----------------------------------------------------------------------
1088
* EmbedSendConfigure --
1090
* This is currently a stub. It is called to notify an
1091
* embedded application of its current size and location. This
1092
* procedure is called when the embedded application made a
1093
* geometry request that we did not grant, so that the embedded
1094
* application knows that its geometry didn't change after all.
1095
* It is a response to ConfigureRequest events, which we do not
1096
* currently synthesize on the Mac
1104
*----------------------------------------------------------------------
1108
EmbedSendConfigure(containerPtr)
1109
Container *containerPtr; /* Information about the embedding. */
1114
*----------------------------------------------------------------------
1116
* EmbedWindowDeleted --
1118
* This procedure is invoked when a window involved in embedding
1119
* (as either the container or the embedded application) is
1120
* destroyed. It cleans up the Container structure for the window.
1126
* A Container structure may be freed.
1128
*----------------------------------------------------------------------
1132
EmbedWindowDeleted(winPtr)
1133
TkWindow *winPtr; /* Tk's information about window that
1136
Container *containerPtr, *prevPtr;
1139
* Find the Container structure for this window. Delete the
1140
* information about the embedded application and free the container's
1145
containerPtr = firstContainerPtr;
1147
if (containerPtr->embeddedPtr == winPtr) {
1150
* We also have to destroy our parent, to clean up the container.
1151
* Fabricate an event to do this.
1154
if (containerPtr->parentPtr != NULL &&
1155
containerPtr->parentPtr->flags & TK_BOTH_HALVES) {
1159
Tk_Display(containerPtr->parentPtr)->request;
1160
event.xany.send_event = False;
1161
event.xany.display = Tk_Display(containerPtr->parentPtr);
1163
event.xany.type = DestroyNotify;
1164
event.xany.window = containerPtr->parent;
1165
event.xdestroywindow.event = containerPtr->parent;
1166
Tk_QueueWindowEvent(&event, TCL_QUEUE_HEAD);
1170
containerPtr->embedded = None;
1171
containerPtr->embeddedPtr = NULL;
1175
if (containerPtr->parentPtr == winPtr) {
1176
containerPtr->parentPtr = NULL;
1179
prevPtr = containerPtr;
1180
containerPtr = containerPtr->nextPtr;
1182
if ((containerPtr->embeddedPtr == NULL)
1183
&& (containerPtr->parentPtr == NULL)) {
1184
if (prevPtr == NULL) {
1185
firstContainerPtr = containerPtr->nextPtr;
1187
prevPtr->nextPtr = containerPtr->nextPtr;
1189
ckfree((char *) containerPtr);