OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tk/] [mac/] [tkMacEmbed.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkMacEmbed.c --
3
 *
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.
10
 *
11
 * Copyright (c) 1996-97 Sun Microsystems, Inc.
12
 *
13
 * See the file "license.terms" for information on usage and redistribution
14
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15
 *
16
 *  RCS: @(#) $Id: tkMacEmbed.c,v 1.1.1.1 2002-01-16 10:25:55 markom Exp $
17
 */
18
 
19
#include "tkInt.h"
20
#include "tkPort.h"
21
#include "X.h"
22
#include "Xlib.h"
23
#include <stdio.h>
24
 
25
#include <Windows.h>
26
#include <QDOffscreen.h>
27
#include "tkMacInt.h"
28
 
29
/*
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.
33
 */
34
 
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
40
                                 * in this process. */
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
48
                                 * this process. */
49
    struct Container *nextPtr;  /* Next in list of all containers in
50
                                 * this process. */
51
} Container;
52
 
53
static Container *firstContainerPtr = NULL;
54
                                        /* First in list of all containers
55
                                         * managed by this process.  */
56
/*
57
 * Globals defined in this file
58
 */
59
 
60
TkMacEmbedHandler *gMacEmbedHandler = NULL;
61
 
62
/*
63
 * Prototypes for static procedures defined in this file:
64
 */
65
 
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,
71
                            XEvent *eventPtr));
72
static void             EmbedFocusProc _ANSI_ARGS_((ClientData clientData,
73
                            XEvent *eventPtr));
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,
79
                            XEvent *eventPtr));
80
static void             EmbedWindowDeleted _ANSI_ARGS_((TkWindow *winPtr));
81
 
82
 
83
/*
84
 *----------------------------------------------------------------------
85
 *
86
 * Tk_MacSetEmbedHandler --
87
 *
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
91
 *
92
 * Results:
93
 *      None
94
 *
95
 * Side effects:
96
 *      The embed handler is set.
97
 *
98
 *----------------------------------------------------------------------
99
 */
100
void
101
Tk_MacSetEmbedHandler(
102
    Tk_MacEmbedRegisterWinProc *registerWinProc,
103
    Tk_MacEmbedGetGrafPortProc *getPortProc,
104
    Tk_MacEmbedMakeContainerExistProc *containerExistProc,
105
    Tk_MacEmbedGetClipProc *getClipProc,
106
    Tk_MacEmbedGetOffsetInParentProc *getOffsetProc)
107
{
108
    if (gMacEmbedHandler == NULL) {
109
        gMacEmbedHandler = (TkMacEmbedHandler *) ckalloc(sizeof(TkMacEmbedHandler));
110
    }
111
    gMacEmbedHandler->registerWinProc = registerWinProc;
112
    gMacEmbedHandler->getPortProc = getPortProc;
113
    gMacEmbedHandler->containerExistProc = containerExistProc;
114
    gMacEmbedHandler->getClipProc = getClipProc;
115
    gMacEmbedHandler->getOffsetProc = getOffsetProc;
116
}
117
 
118
 
119
/*
120
 *----------------------------------------------------------------------
121
 *
122
 * TkpMakeWindow --
123
 *
124
 *      Creates an X Window (Mac subwindow).
125
 *
126
 * Results:
127
 *      The window id is returned.
128
 *
129
 * Side effects:
130
 *      None.
131
 *
132
 *----------------------------------------------------------------------
133
 */
134
 
135
Window
136
TkpMakeWindow(
137
    TkWindow *winPtr,
138
    Window parent)
139
{
140
    MacDrawable *macWin;
141
    XEvent event;
142
 
143
    /*
144
     * If this window is marked as embedded then
145
     * the window structure should have already been
146
     * created in the TkpUseWindow function.
147
     */
148
 
149
    if (Tk_IsEmbedded(winPtr)) {
150
        return (Window) winPtr->privatePtr;
151
    }
152
 
153
    /*
154
     * Allocate sub window
155
     */
156
 
157
    macWin = (MacDrawable *) ckalloc(sizeof(MacDrawable));
158
    if (macWin == NULL) {
159
        winPtr->privatePtr = NULL;
160
        return None;
161
    }
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;
168
 
169
    if (Tk_IsTopLevel(macWin->winPtr)) {
170
 
171
        /*
172
         *This will be set when we are mapped.
173
         */
174
 
175
        macWin->portPtr = (GWorldPtr) NULL;
176
        macWin->toplevel = macWin;
177
        macWin->xOff = 0;
178
        macWin->yOff = 0;
179
    } else {
180
        macWin->portPtr = NULL;
181
        macWin->xOff = winPtr->parentPtr->privatePtr->xOff +
182
            winPtr->parentPtr->changes.border_width +
183
            winPtr->changes.x;
184
        macWin->yOff = winPtr->parentPtr->privatePtr->yOff +
185
            winPtr->parentPtr->changes.border_width +
186
            winPtr->changes.y;
187
        macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel;
188
    }
189
 
190
    macWin->toplevel->referenceCount++;
191
 
192
    /*
193
     * TODO: need general solution for visibility events.
194
     */
195
    event.xany.serial = Tk_Display(winPtr)->request;
196
    event.xany.send_event = False;
197
    event.xany.display = Tk_Display(winPtr);
198
 
199
    event.xvisibility.type = VisibilityNotify;
200
    event.xvisibility.window = (Window) macWin;;
201
    event.xvisibility.state = VisibilityUnobscured;
202
    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
203
 
204
    return (Window) macWin;
205
}
206
 
207
/*
208
 *----------------------------------------------------------------------
209
 *
210
 * TkpUseWindow --
211
 *
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.
216
 *
217
 * Results:
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.
222
 *
223
 * Side effects:
224
 *      None.
225
 *
226
 *----------------------------------------------------------------------
227
 */
228
 
229
int
230
TkpUseWindow(
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. */
237
{
238
    TkWindow *winPtr = (TkWindow *) tkwin;
239
    MacDrawable *parent, *macWin;
240
    Container *containerPtr;
241
    XEvent event;
242
    int result;
243
 
244
    if (winPtr->window != None) {
245
        panic("TkpUseWindow: X window already assigned");
246
    }
247
 
248
    /*
249
     * Decode the container pointer, and look for it among the
250
     *list of available containers.
251
     *
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
254
     * of containers.
255
     *
256
     */
257
 
258
    if (Tcl_GetInt(interp, string, &result) != TCL_OK) {
259
        return TCL_ERROR;
260
    }
261
 
262
    parent = (MacDrawable *) result;
263
 
264
    /*
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.
269
     */
270
 
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;
276
            break;
277
        }
278
    }
279
 
280
    /*
281
     * Make the embedded window.
282
     */
283
 
284
    macWin = (MacDrawable *) ckalloc(sizeof(MacDrawable));
285
    if (macWin == NULL) {
286
        winPtr->privatePtr = NULL;
287
        return TCL_ERROR;
288
    }
289
 
290
    macWin->winPtr = winPtr;
291
    winPtr->privatePtr = macWin;
292
 
293
    /*
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.
299
     */
300
 
301
    macWin->portPtr = (GWorldPtr) NULL;
302
 
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++;
309
 
310
    winPtr->flags |= TK_EMBEDDED;
311
 
312
 
313
    /*
314
     * Make a copy of the TK_EMBEDDED flag, since sometimes
315
     * we need this to get the port after the TkWindow structure
316
     * has been freed.
317
     */
318
 
319
    macWin->flags |= TK_EMBEDDED;
320
 
321
    /*
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.
325
     */
326
 
327
    if (containerPtr == NULL) {
328
        /*
329
         * If someone has registered an in process embedding handler, then
330
         * see if it can handle this window...
331
         */
332
 
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.",
337
                     (char *) NULL);
338
            return TCL_ERROR;
339
        } else {
340
            containerPtr = (Container *) ckalloc(sizeof(Container));
341
 
342
            containerPtr->parentPtr = NULL;
343
            containerPtr->embedded = (Window) macWin;
344
            containerPtr->embeddedPtr = macWin->winPtr;
345
            containerPtr->nextPtr = firstContainerPtr;
346
            firstContainerPtr = containerPtr;
347
 
348
        }
349
    } else {
350
 
351
        /*
352
         * The window is embedded in another Tk window.
353
         */
354
 
355
        macWin->xOff = parent->winPtr->privatePtr->xOff +
356
                parent->winPtr->changes.border_width +
357
                winPtr->changes.x;
358
        macWin->yOff = parent->winPtr->privatePtr->yOff +
359
                parent->winPtr->changes.border_width +
360
                winPtr->changes.y;
361
 
362
 
363
        /*
364
         * Finish filling up the container structure with the embedded window's
365
         * information.
366
         */
367
 
368
        containerPtr->embedded = (Window) macWin;
369
        containerPtr->embeddedPtr = macWin->winPtr;
370
 
371
        /*
372
         * Create an event handler to clean up the Container structure when
373
         * tkwin is eventually deleted.
374
         */
375
 
376
        Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc,
377
                (ClientData) winPtr);
378
 
379
    }
380
 
381
   /*
382
     * TODO: need general solution for visibility events.
383
     */
384
 
385
    event.xany.serial = Tk_Display(winPtr)->request;
386
    event.xany.send_event = False;
387
    event.xany.display = Tk_Display(winPtr);
388
 
389
    event.xvisibility.type = VisibilityNotify;
390
    event.xvisibility.window = (Window) macWin;;
391
    event.xvisibility.state = VisibilityUnobscured;
392
    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
393
 
394
 
395
    /*
396
     * TODO: need general solution for visibility events.
397
     */
398
 
399
    event.xany.serial = Tk_Display(winPtr)->request;
400
    event.xany.send_event = False;
401
    event.xany.display = Tk_Display(winPtr);
402
 
403
    event.xvisibility.type = VisibilityNotify;
404
    event.xvisibility.window = (Window) macWin;;
405
    event.xvisibility.state = VisibilityUnobscured;
406
    Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
407
 
408
    return TCL_OK;
409
}
410
 
411
/*
412
 *----------------------------------------------------------------------
413
 *
414
 * TkpMakeContainer --
415
 *
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.
420
 *
421
 * Results:
422
 *      None.
423
 *
424
 * Side effects:
425
 *      None.
426
 *
427
 *----------------------------------------------------------------------
428
 */
429
 
430
void
431
TkpMakeContainer(
432
    Tk_Window tkwin)            /* Token for a window that is about to
433
                                 * become a container. */
434
{
435
    TkWindow *winPtr = (TkWindow *) tkwin;
436
    Container *containerPtr;
437
 
438
    /*
439
     * Register the window as a container so that, for example, we can
440
     * make sure the argument to -use is valid.
441
     */
442
 
443
 
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;
453
 
454
    /*
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.
460
     */
461
 
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);
471
 
472
}
473
 
474
/*
475
 *----------------------------------------------------------------------
476
 *
477
 * TkMacContainerId --
478
 *
479
 *      Given an embedded window, this procedure returns the MacDrawable
480
 *      identifier for the associated container window.
481
 *
482
 * Results:
483
 *      The return value is the MacDrawable for winPtr's
484
 *      container window.
485
 *
486
 * Side effects:
487
 *      None.
488
 *
489
 *----------------------------------------------------------------------
490
 */
491
 
492
MacDrawable *
493
TkMacContainerId(winPtr)
494
    TkWindow *winPtr;           /* Tk's structure for an embedded window. */
495
{
496
    Container *containerPtr;
497
 
498
    for (containerPtr = firstContainerPtr; containerPtr != NULL;
499
            containerPtr = containerPtr->nextPtr) {
500
        if (containerPtr->embeddedPtr == winPtr) {
501
            return (MacDrawable *) containerPtr->parent;
502
        }
503
    }
504
    panic("TkMacContainerId couldn't find window");
505
    return None;
506
}
507
 
508
/*
509
 *----------------------------------------------------------------------
510
 *
511
 * TkMacGetHostToplevel --
512
 *
513
 *      Given the TkWindow, return the MacDrawable for the outermost
514
 *      toplevel containing it.  This will be a real Macintosh window.
515
 *
516
 * Results:
517
 *      Returns a MacDrawable corresponding to a Macintosh Toplevel
518
 *
519
 * Side effects:
520
 *      None.
521
 *
522
 *----------------------------------------------------------------------
523
 */
524
 
525
MacDrawable *
526
TkMacGetHostToplevel(
527
    TkWindow *winPtr)           /* Tk's structure for a window. */
528
{
529
    TkWindow *contWinPtr, *topWinPtr;
530
 
531
    topWinPtr = winPtr->privatePtr->toplevel->winPtr;
532
    if (!Tk_IsEmbedded(topWinPtr)) {
533
        return winPtr->privatePtr->toplevel;
534
    } else {
535
        contWinPtr = TkpGetOtherWindow(topWinPtr);
536
 
537
        /*
538
         * NOTE: Here we should handle out of process embedding.
539
         */
540
 
541
        if (contWinPtr != NULL) {
542
            return TkMacGetHostToplevel(contWinPtr);
543
        } else {
544
            return None;
545
        }
546
    }
547
}
548
 
549
/*
550
 *----------------------------------------------------------------------
551
 *
552
 * TkpClaimFocus --
553
 *
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.
558
 *
559
 * Results:
560
 *      None.
561
 *
562
 * Side effects:
563
 *      The input focus may change.
564
 *
565
 *----------------------------------------------------------------------
566
 */
567
 
568
void
569
TkpClaimFocus(
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. */
575
{
576
    XEvent event;
577
    Container *containerPtr;
578
 
579
    if (!(topLevelPtr->flags & TK_EMBEDDED)) {
580
        return;
581
    }
582
 
583
    for (containerPtr = firstContainerPtr;
584
            containerPtr->embeddedPtr != topLevelPtr;
585
            containerPtr = containerPtr->nextPtr) {
586
        /* Empty loop body. */
587
    }
588
 
589
 
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);
598
}
599
 
600
/*
601
 *----------------------------------------------------------------------
602
 *
603
 * TkpTestembedCmd --
604
 *
605
 *      This procedure implements the "testembed" command.  It returns
606
 *      some or all of the information in the list pointed to by
607
 *      firstContainerPtr.
608
 *
609
 * Results:
610
 *      A standard Tcl result.
611
 *
612
 * Side effects:
613
 *      None.
614
 *
615
 *----------------------------------------------------------------------
616
 */
617
 
618
int
619
TkpTestembedCmd(
620
    ClientData clientData,              /* Main window for application. */
621
    Tcl_Interp *interp,                 /* Current interpreter. */
622
    int argc,                           /* Number of arguments. */
623
    char **argv)                        /* Argument strings. */
624
{
625
    int all;
626
    Container *containerPtr;
627
    Tcl_DString dString;
628
    char buffer[50];
629
 
630
    if ((argc > 1) && (strcmp(argv[1], "all") == 0)) {
631
        all = 1;
632
    } else {
633
        all = 0;
634
    }
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, "");
641
        } else {
642
            if (all) {
643
                sprintf(buffer, "0x%x", (int) containerPtr->parent);
644
                Tcl_DStringAppendElement(&dString, buffer);
645
            } else {
646
                Tcl_DStringAppendElement(&dString, "XXX");
647
            }
648
        }
649
        if (containerPtr->parentPtr == NULL) {
650
            Tcl_DStringAppendElement(&dString, "");
651
        } else {
652
            Tcl_DStringAppendElement(&dString,
653
                    containerPtr->parentPtr->pathName);
654
        }
655
        if (containerPtr->embedded == None) {
656
            Tcl_DStringAppendElement(&dString, "");
657
        } else {
658
            if (all) {
659
                sprintf(buffer, "0x%x", (int) containerPtr->embedded);
660
                Tcl_DStringAppendElement(&dString, buffer);
661
            } else {
662
                Tcl_DStringAppendElement(&dString, "XXX");
663
            }
664
        }
665
        if (containerPtr->embeddedPtr == NULL) {
666
            Tcl_DStringAppendElement(&dString, "");
667
        } else {
668
            Tcl_DStringAppendElement(&dString,
669
                    containerPtr->embeddedPtr->pathName);
670
        }
671
        Tcl_DStringEndSublist(&dString);
672
    }
673
    Tcl_DStringResult(interp, &dString);
674
    return TCL_OK;
675
}
676
 
677
/*
678
 *----------------------------------------------------------------------
679
 *
680
 * TkpRedirectKeyEvent --
681
 *
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.
689
 *
690
 * Results:
691
 *      None.
692
 *
693
 * Side effects:
694
 *      The event may get sent to a different application.
695
 *
696
 *----------------------------------------------------------------------
697
 */
698
 
699
void
700
TkpRedirectKeyEvent(
701
    TkWindow *winPtr,           /* Window to which the event was originally
702
                                 * reported. */
703
    XEvent *eventPtr)           /* X event to redirect (should be KeyPress
704
                                 * or KeyRelease). */
705
{
706
}
707
 
708
/*
709
 *----------------------------------------------------------------------
710
 *
711
 * TkpGetOtherWindow --
712
 *
713
 *      If both the container and embedded window are in the same
714
 *      process, this procedure will return either one, given the other.
715
 *
716
 * Results:
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.
720
 *
721
 * Side effects:
722
 *      None.
723
 *
724
 *----------------------------------------------------------------------
725
 */
726
 
727
TkWindow *
728
TkpGetOtherWindow(
729
    TkWindow *winPtr)           /* Tk's structure for a container or
730
                                 * embedded window. */
731
{
732
    Container *containerPtr;
733
 
734
    /*
735
     * TkpGetOtherWindow returns NULL if both windows are not
736
     * in the same process...
737
     */
738
 
739
    if (!(winPtr->flags & TK_BOTH_HALVES)) {
740
        return NULL;
741
    }
742
 
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;
749
        }
750
    }
751
    return NULL;
752
}
753
/*
754
 *----------------------------------------------------------------------
755
 *
756
 * EmbeddedEventProc --
757
 *
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.
761
 *
762
 * Results:
763
 *      None.
764
 *
765
 * Side effects:
766
 *      Our internal state gets cleaned up when an embedded window is
767
 *      destroyed.
768
 *
769
 *----------------------------------------------------------------------
770
 */
771
 
772
static void
773
EmbeddedEventProc(clientData, eventPtr)
774
    ClientData clientData;              /* Token for container window. */
775
    XEvent *eventPtr;                   /* ResizeRequest event. */
776
{
777
    TkWindow *winPtr = (TkWindow *) clientData;
778
 
779
    if (eventPtr->type == DestroyNotify) {
780
        EmbedWindowDeleted(winPtr);
781
    }
782
}
783
 
784
/*
785
 *----------------------------------------------------------------------
786
 *
787
 * ContainerEventProc --
788
 *
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.
793
 *
794
 *      NOTE: on the Mac, only the DestroyNotify branch is ever taken.
795
 *      We don't synthesize the other events.
796
 *
797
 * Results:
798
 *      None.
799
 *
800
 * Side effects:
801
 *      Depends on the event.  For example, when ConfigureRequest events
802
 *      occur, geometry information gets set for the container window.
803
 *
804
 *----------------------------------------------------------------------
805
 */
806
 
807
static void
808
ContainerEventProc(clientData, eventPtr)
809
    ClientData clientData;              /* Token for container window. */
810
    XEvent *eventPtr;                   /* ResizeRequest event. */
811
{
812
    TkWindow *winPtr = (TkWindow *) clientData;
813
    Container *containerPtr;
814
    Tk_ErrorHandler errHandler;
815
 
816
    /*
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).
820
     */
821
 
822
    errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1,
823
            -1, -1, (Tk_ErrorProc *) NULL, (ClientData) NULL);
824
 
825
    /*
826
     * Find the Container structure associated with the parent window.
827
     */
828
 
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");
834
        }
835
    }
836
 
837
    if (eventPtr->type == CreateNotify) {
838
        /*
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
842
         * ones).
843
         */
844
 
845
        containerPtr->embedded = eventPtr->xcreatewindow.window;
846
    } else if (eventPtr->type == ConfigureRequest) {
847
        if ((eventPtr->xconfigurerequest.x != 0)
848
                || (eventPtr->xconfigurerequest.y != 0)) {
849
            /*
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.
858
             */
859
 
860
            if ((eventPtr->xconfigurerequest.width == winPtr->changes.width)
861
                    && (eventPtr->xconfigurerequest.height
862
                    == winPtr->changes.height)) {
863
                EmbedSendConfigure(containerPtr);
864
            }
865
        }
866
        EmbedGeometryRequest(containerPtr,
867
                eventPtr->xconfigurerequest.width,
868
                eventPtr->xconfigurerequest.height);
869
    } else if (eventPtr->type == MapRequest) {
870
        /*
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
873
         * on the screen.
874
         */
875
 
876
        XMapWindow(eventPtr->xmaprequest.display,
877
                eventPtr->xmaprequest.window);
878
    } else if (eventPtr->type == DestroyNotify) {
879
        /*
880
         * The embedded application is gone.  Destroy the container window.
881
         */
882
 
883
        Tk_DestroyWindow((Tk_Window) winPtr);
884
    }
885
    Tk_DeleteErrorHandler(errHandler);
886
}
887
 
888
/*
889
 *----------------------------------------------------------------------
890
 *
891
 * EmbedStructureProc --
892
 *
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.
898
 *
899
 * Results:
900
 *      None.
901
 *
902
 * Side effects:
903
 *      The embedded window gets resized to match the container.
904
 *
905
 *----------------------------------------------------------------------
906
 */
907
 
908
static void
909
EmbedStructureProc(clientData, eventPtr)
910
    ClientData clientData;              /* Token for container window. */
911
    XEvent *eventPtr;                   /* ResizeRequest event. */
912
{
913
    Container *containerPtr = (Container *) clientData;
914
    Tk_ErrorHandler errHandler;
915
 
916
    if (eventPtr->type == ConfigureNotify) {
917
        if (containerPtr->embedded != None) {
918
            /*
919
             * Ignore errors, since the embedded application could have
920
             * deleted its window.
921
             */
922
 
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);
931
        }
932
    } else if (eventPtr->type == DestroyNotify) {
933
        EmbedWindowDeleted(containerPtr->parentPtr);
934
    }
935
}
936
 
937
/*
938
 *----------------------------------------------------------------------
939
 *
940
 * EmbedActivateProc --
941
 *
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.
946
 *
947
 * Results:
948
 *      None.
949
 *
950
 * Side effects:
951
 *      The X focus may change.
952
 *
953
 *----------------------------------------------------------------------
954
 */
955
 
956
static void
957
EmbedActivateProc(clientData, eventPtr)
958
    ClientData clientData;              /* Token for container window. */
959
    XEvent *eventPtr;                   /* ResizeRequest event. */
960
{
961
    Container *containerPtr = (Container *) clientData;
962
 
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);
968
        }
969
    }
970
}
971
 
972
/*
973
 *----------------------------------------------------------------------
974
 *
975
 * EmbedFocusProc --
976
 *
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
981
 *      application.
982
 *
983
 * Results:
984
 *      None.
985
 *
986
 * Side effects:
987
 *      The X focus may change.
988
 *
989
 *----------------------------------------------------------------------
990
 */
991
 
992
static void
993
EmbedFocusProc(clientData, eventPtr)
994
    ClientData clientData;              /* Token for container window. */
995
    XEvent *eventPtr;                   /* ResizeRequest event. */
996
{
997
    Container *containerPtr = (Container *) clientData;
998
    Display *display;
999
    XEvent event;
1000
 
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;
1008
 
1009
    if (eventPtr->type == FocusIn) {
1010
        /*
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).
1015
         */
1016
 
1017
            event.xfocus.detail = NotifyNonlinear;
1018
            event.xfocus.type = FocusIn;
1019
 
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.
1023
         */
1024
 
1025
            event.xfocus.type = FocusOut;
1026
            event.xfocus.detail = NotifyNonlinear;
1027
         }
1028
 
1029
        Tk_QueueWindowEvent(&event, TCL_QUEUE_MARK);
1030
    }
1031
}
1032
 
1033
/*
1034
 *----------------------------------------------------------------------
1035
 *
1036
 * EmbedGeometryRequest --
1037
 *
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.
1042
 *
1043
 *      NOTE: On the Mac, this is a stub, since we don't synthesize
1044
 *      ConfigureRequest events.
1045
 *
1046
 * Results:
1047
 *      None.
1048
 *
1049
 * Side effects:
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.
1054
 *
1055
 *----------------------------------------------------------------------
1056
 */
1057
 
1058
static void
1059
EmbedGeometryRequest(containerPtr, width, height)
1060
    Container *containerPtr;    /* Information about the embedding. */
1061
    int width, height;          /* Size that the child has requested. */
1062
{
1063
    TkWindow *winPtr = containerPtr->parentPtr;
1064
 
1065
    /*
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.
1073
     */
1074
 
1075
    Tk_GeometryRequest((Tk_Window) winPtr, width, height);
1076
    while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {
1077
        /* Empty loop body. */
1078
    }
1079
    if ((winPtr->changes.width != width)
1080
            || (winPtr->changes.height != height)) {
1081
        EmbedSendConfigure(containerPtr);
1082
    }
1083
}
1084
 
1085
/*
1086
 *----------------------------------------------------------------------
1087
 *
1088
 * EmbedSendConfigure --
1089
 *
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
1097
 *
1098
 * Results:
1099
 *      None.
1100
 *
1101
 * Side effects:
1102
 *      None.
1103
 *
1104
 *----------------------------------------------------------------------
1105
 */
1106
 
1107
static void
1108
EmbedSendConfigure(containerPtr)
1109
    Container *containerPtr;    /* Information about the embedding. */
1110
{
1111
}
1112
 
1113
/*
1114
 *----------------------------------------------------------------------
1115
 *
1116
 * EmbedWindowDeleted --
1117
 *
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.
1121
 *
1122
 * Results:
1123
 *      None.
1124
 *
1125
 * Side effects:
1126
 *      A Container structure may be freed.
1127
 *
1128
 *----------------------------------------------------------------------
1129
 */
1130
 
1131
static void
1132
EmbedWindowDeleted(winPtr)
1133
    TkWindow *winPtr;           /* Tk's information about window that
1134
                                 * was deleted. */
1135
{
1136
    Container *containerPtr, *prevPtr;
1137
 
1138
    /*
1139
     * Find the Container structure for this window.  Delete the
1140
     * information about the embedded application and free the container's
1141
     * record.
1142
     */
1143
 
1144
    prevPtr = NULL;
1145
    containerPtr = firstContainerPtr;
1146
    while (1) {
1147
        if (containerPtr->embeddedPtr == winPtr) {
1148
 
1149
            /*
1150
             * We also have to destroy our parent, to clean up the container.
1151
             * Fabricate an event to do this.
1152
             */
1153
 
1154
            if (containerPtr->parentPtr != NULL &&
1155
                    containerPtr->parentPtr->flags & TK_BOTH_HALVES) {
1156
                XEvent event;
1157
 
1158
                event.xany.serial =
1159
                    Tk_Display(containerPtr->parentPtr)->request;
1160
                event.xany.send_event = False;
1161
                event.xany.display = Tk_Display(containerPtr->parentPtr);
1162
 
1163
                event.xany.type = DestroyNotify;
1164
                event.xany.window = containerPtr->parent;
1165
                event.xdestroywindow.event = containerPtr->parent;
1166
                Tk_QueueWindowEvent(&event, TCL_QUEUE_HEAD);
1167
 
1168
            }
1169
 
1170
            containerPtr->embedded = None;
1171
            containerPtr->embeddedPtr = NULL;
1172
 
1173
            break;
1174
        }
1175
        if (containerPtr->parentPtr == winPtr) {
1176
            containerPtr->parentPtr = NULL;
1177
            break;
1178
        }
1179
        prevPtr = containerPtr;
1180
        containerPtr = containerPtr->nextPtr;
1181
    }
1182
    if ((containerPtr->embeddedPtr == NULL)
1183
            && (containerPtr->parentPtr == NULL)) {
1184
        if (prevPtr == NULL) {
1185
            firstContainerPtr = containerPtr->nextPtr;
1186
        } else {
1187
            prevPtr->nextPtr = containerPtr->nextPtr;
1188
        }
1189
        ckfree((char *) containerPtr);
1190
    }
1191
}
1192
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.