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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tix/] [generic/] [tixMwm.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tixMwm.c --
3
 *
4
 *      Communicating with the Motif window manager.
5
 *
6
 *
7
 * Copyright (c) 1996, Expert Interface Technologies
8
 *
9
 * See the file "license.terms" for information on usage and redistribution
10
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
 *
12
 */
13
 
14
#include <tkInt.h>
15
#include <tixPort.h>
16
#include <tixInt.h>
17
#include <X11/Xlib.h>
18
#include <X11/Xatom.h>
19
#include <X11/Xproto.h>
20
#include <X11/Xutil.h>
21
 
22
 
23
#ifdef HAS_MOTIF_INC
24
#include <Xm/MwmUtil.h>
25
#else
26
 
27
/*
28
 * This section is provided for the machines that don't have the Motif
29
 * header files installed.
30
 */
31
 
32
#define MWM_DECOR_ALL           (1L << 0)
33
#define MWM_DECOR_BORDER        (1L << 1)
34
#define MWM_DECOR_RESIZEH       (1L << 2)
35
#define MWM_DECOR_TITLE         (1L << 3)
36
#define MWM_DECOR_MENU          (1L << 4)
37
#define MWM_DECOR_MINIMIZE      (1L << 5)
38
#define MWM_DECOR_MAXIMIZE      (1L << 6)
39
 
40
#define MWM_HINTS_DECORATIONS   (1L << 1)
41
 
42
#define PROP_MOTIF_WM_HINTS_ELEMENTS    5
43
#define PROP_MWM_HINTS_ELEMENTS         PROP_MOTIF_WM_HINTS_ELEMENTS
44
 
45
/* atom name for _MWM_HINTS property */
46
#define _XA_MOTIF_WM_HINTS      "_MOTIF_WM_HINTS"
47
#define _XA_MWM_HINTS           _XA_MOTIF_WM_HINTS
48
 
49
#define _XA_MOTIF_WM_MENU       "_MOTIF_WM_MENU"
50
#define _XA_MWM_MENU            _XA_MOTIF_WM_MENU
51
 
52
#define _XA_MOTIF_WM_INFO       "_MOTIF_WM_INFO"
53
#define _XA_MWM_INFO            _XA_MOTIF_WM_INFO
54
 
55
#define PROP_MOTIF_WM_INFO_ELEMENTS     2
56
#define PROP_MWM_INFO_ELEMENTS          PROP_MOTIF_WM_INFO_ELEMENTS
57
 
58
typedef struct
59
{
60
    CARD32      flags;
61
    CARD32      functions;
62
    CARD32      decorations;
63
    INT32       inputMode;
64
    CARD32      status;
65
} PropMotifWmHints;
66
 
67
typedef PropMotifWmHints        PropMwmHints;
68
 
69
typedef struct
70
{
71
    CARD32 flags;
72
    CARD32 wmWindow;
73
} PropMotifWmInfo;
74
 
75
typedef PropMotifWmInfo PropMwmInfo;
76
 
77
#endif  /* HAS_MOTIF_INC */
78
 
79
#define MWM_DECOR_UNKNOWN (-1)
80
#define MWM_DECOR_EVERYTHING (MWM_DECOR_BORDER |\
81
                              MWM_DECOR_RESIZEH |\
82
                              MWM_DECOR_TITLE |\
83
                              MWM_DECOR_MENU |\
84
                              MWM_DECOR_MINIMIZE |\
85
                              MWM_DECOR_MAXIMIZE)
86
 
87
typedef struct _Tix_MwmInfo {
88
    Tcl_Interp        * interp;
89
    Tk_Window           tkwin;
90
    PropMwmHints        prop;           /* not used */
91
    Atom                mwm_hints_atom;
92
    Tcl_HashTable       protocols;
93
    unsigned int        isremapping : 1;
94
    unsigned int        resetProtocol : 1;
95
    unsigned int        addedMwmMsg : 1;
96
} Tix_MwmInfo;
97
 
98
typedef struct Tix_MwmProtocol {
99
    Atom                protocol;
100
    char              * name;
101
    char              * menuMessage;
102
    size_t              messageLen;
103
    unsigned int        active : 1;
104
} Tix_MwmProtocol;
105
 
106
 
107
/* Function declaration */
108
 
109
static void             AddMwmProtocol _ANSI_ARGS_((Tcl_Interp *interp,
110
                            Tix_MwmInfo *wmPtr, char * name, char * message));
111
static void             ActivateMwmProtocol _ANSI_ARGS_((Tcl_Interp *interp,
112
                            Tix_MwmInfo *wmPtr, char * name));
113
static void             DeactivateMwmProtocol _ANSI_ARGS_((Tcl_Interp *interp,
114
                            Tix_MwmInfo *wmPtr, char * name));
115
static void             DeleteMwmProtocol _ANSI_ARGS_((Tcl_Interp *interp,
116
                            Tix_MwmInfo *wmPtr, char * name));
117
static Tix_MwmInfo *    GetMwmInfo _ANSI_ARGS_((Tcl_Interp *interp,
118
                            Tk_Window tkwin));
119
static Tix_MwmProtocol* GetMwmProtocol _ANSI_ARGS_((Tcl_Interp * interp,
120
                            Tix_MwmInfo * wmPtr, Atom protocol));
121
static int              IsMwmRunning _ANSI_ARGS_((Tcl_Interp * interp,
122
                            Tix_MwmInfo*wmPtr));
123
static int              MwmDecor _ANSI_ARGS_((Tcl_Interp * interp,
124
                            char * string));
125
static int              MwmProtocol _ANSI_ARGS_((Tcl_Interp * interp,
126
                            Tix_MwmInfo * wmPtr, int argc, char ** argv));
127
static void             QueryMwmHints _ANSI_ARGS_((Tix_MwmInfo * wmPtr));
128
static void             RemapWindow _ANSI_ARGS_((ClientData clientData));
129
static void             RemapWindowWhenIdle _ANSI_ARGS_((
130
                            Tix_MwmInfo * wmPtr));
131
static void             ResetProtocols _ANSI_ARGS_((ClientData clientData));
132
static void             ResetProtocolsWhenIdle _ANSI_ARGS_((
133
                            Tix_MwmInfo * wmPtr));
134
static int              SetMwmDecorations _ANSI_ARGS_((Tcl_Interp *interp,
135
                            Tix_MwmInfo*wmPtr, int argc, char ** argv));
136
static int              SetMwmTransientFor _ANSI_ARGS_((Tcl_Interp *interp,
137
                            Tix_MwmInfo*wmPtr, TkWindow *mainWindow, int argc,
138
                            char ** argv));
139
static void             StructureProc _ANSI_ARGS_((ClientData clientData,
140
                            XEvent *eventPtr));
141
 
142
/* Local variables */
143
 
144
static Tcl_HashTable mwmTable;
145
 
146
 
147
/*
148
 *----------------------------------------------------------------------
149
 *
150
 * Tix_MwmCmd --
151
 *
152
 *      This procedure is invoked to process the "mwm" Tcl command.
153
 *      See the user documentation for details on what it does.
154
 *
155
 * Results:
156
 *      A standard Tcl result.
157
 *
158
 * Side effects:
159
 *      See the user documentation.
160
 *
161
 *----------------------------------------------------------------------
162
 */
163
 
164
/* ARGSUSED */
165
int
166
Tix_MwmCmd(clientData, interp, argc, argv)
167
    ClientData clientData;      /* Main window associated with
168
                                 * interpreter. */
169
    Tcl_Interp *interp;         /* Current interpreter. */
170
    int argc;                   /* Number of arguments. */
171
    char **argv;                /* Argument strings. */
172
{
173
    Tk_Window tkwin = (Tk_Window) clientData;
174
    TkWindow *winPtr;
175
    char c;
176
    size_t length;
177
    Tix_MwmInfo * wmPtr;
178
 
179
    if (argc < 3) {
180
        Tcl_AppendResult(interp, "wrong # args: should be \"",
181
                argv[0], " option pathname ?arg ...?\"", (char *) NULL);
182
        return TCL_ERROR;
183
    }
184
    c = argv[1][0];
185
    length = strlen(argv[1]);
186
 
187
    if (!(winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin))) {
188
        return TCL_ERROR;
189
    }
190
    if (!Tk_IsTopLevel(winPtr)) {
191
        Tcl_AppendResult(interp, argv[2], " is not a toplevel window.", NULL);
192
        return TCL_ERROR;
193
    }
194
    if (!(wmPtr=GetMwmInfo(interp, (Tk_Window) winPtr))) {
195
        return TCL_ERROR;
196
    }
197
 
198
    if ((c == 'd') && (strncmp(argv[1], "decorations", length) == 0)) {
199
        return SetMwmDecorations(interp, wmPtr, argc-3, argv+3);
200
    }
201
    else if ((c == 'i') && (strncmp(argv[1], "ismwmrunning", length) == 0)) {
202
        if (IsMwmRunning(interp, wmPtr)) {
203
            Tcl_AppendResult(interp, "1", NULL);
204
        } else {
205
            Tcl_AppendResult(interp, "0", NULL);
206
        }
207
        return TCL_OK;
208
    }
209
    else if ((c == 'p') && (strncmp(argv[1], "protocol", length) == 0)) {
210
        return MwmProtocol(interp, wmPtr, argc-3, argv+3);
211
    }
212
    else if ((c == 't') && (strncmp(argv[1], "transientfor", length) == 0)) {
213
        return SetMwmTransientFor(interp, wmPtr, winPtr, argc-3, argv+3);
214
    }
215
    else {
216
        Tcl_AppendResult(interp, "unknown or ambiguous option \"",
217
            argv[1], "\": must be decorations, ismwmrunning, protocol ",
218
            "or transientfor",
219
            NULL);
220
        return TCL_ERROR;
221
    }
222
}
223
 
224
/*
225
 *----------------------------------------------------------------------
226
 * TixMwmProtocolHandler --
227
 *
228
 *      A generic X event handler that handles the events from the Mwm
229
 *      Window manager.
230
 *
231
 * Results:
232
 *      True iff the event has been handled.
233
 *
234
 * Side effects:
235
 *      None.
236
 *----------------------------------------------------------------------
237
 */
238
 
239
int
240
TixMwmProtocolHandler(clientData, eventPtr)
241
    ClientData clientData;
242
    XEvent *eventPtr;
243
{
244
    TkWindow *winPtr;
245
    Window handlerWindow;
246
 
247
    if (eventPtr->type != ClientMessage) {
248
        return 0;
249
    }
250
 
251
    handlerWindow = eventPtr->xany.window;
252
    winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, handlerWindow);
253
    if (winPtr != NULL) {
254
        if (eventPtr->xclient.message_type ==
255
            Tk_InternAtom((Tk_Window) winPtr,"_MOTIF_WM_MESSAGES")) {
256
            TkWmProtocolEventProc(winPtr, eventPtr);
257
            return 1;
258
        }
259
    }
260
    return 0;
261
}
262
 
263
static int
264
MwmDecor(interp, string)
265
    Tcl_Interp * interp;
266
    char * string;
267
{
268
    size_t len = strlen(string);
269
 
270
    if (strncmp(string, "-all", len) == 0) {
271
        return MWM_DECOR_ALL;
272
    } else if (strncmp(string, "-border", len) == 0) {
273
        return MWM_DECOR_BORDER;
274
    } else if (strncmp(string, "-resizeh", len) == 0) {
275
        return MWM_DECOR_RESIZEH;
276
    } else if (strncmp(string, "-title", len) == 0) {
277
        return MWM_DECOR_TITLE;
278
    } else if (strncmp(string, "-menu", len) == 0) {
279
        return MWM_DECOR_MENU;
280
    } else if (strncmp(string, "-minimize", len) == 0) {
281
        return MWM_DECOR_MINIMIZE;
282
    } else if (strncmp(string, "-maximize", len) == 0) {
283
        return MWM_DECOR_MAXIMIZE;
284
    } else {
285
        Tcl_AppendResult(interp, "unknown decoration \"", string, "\"", NULL);
286
        return -1;
287
    }
288
}
289
 
290
 
291
static void
292
QueryMwmHints(wmPtr)
293
    Tix_MwmInfo * wmPtr;
294
{
295
    Atom                actualType;
296
    int                 actualFormat;
297
    unsigned long       numItems, bytesAfter;
298
 
299
    wmPtr->prop.flags = MWM_HINTS_DECORATIONS;
300
 
301
    if (XGetWindowProperty(Tk_Display(wmPtr->tkwin),Tk_WindowId(wmPtr->tkwin),
302
        wmPtr->mwm_hints_atom, 0, PROP_MWM_HINTS_ELEMENTS,
303
        False, wmPtr->mwm_hints_atom, &actualType, &actualFormat, &numItems,
304
        &bytesAfter, (unsigned char **) & wmPtr->prop) == Success) {
305
 
306
        if ((actualType != wmPtr->mwm_hints_atom) || (actualFormat != 32) ||
307
            (numItems <= 0)) {
308
            /* It looks like this window doesn't have a _XA_MWM_HINTS
309
             * property. Let's give the default value
310
             */
311
            wmPtr->prop.decorations = MWM_DECOR_EVERYTHING;
312
        }
313
    } else {
314
        /* We get an error somehow. Pretend that the decorations are all
315
         */
316
        wmPtr->prop.decorations = MWM_DECOR_EVERYTHING;
317
    }
318
}
319
 
320
static void
321
RemapWindow(clientData)
322
    ClientData clientData;
323
{
324
    Tix_MwmInfo * wmPtr = (Tix_MwmInfo *)clientData;
325
 
326
    Tk_UnmapWindow(wmPtr->tkwin);
327
    Tk_MapWindow(wmPtr->tkwin);
328
    wmPtr->isremapping = 0;
329
}
330
 
331
static void
332
RemapWindowWhenIdle(wmPtr)
333
    Tix_MwmInfo * wmPtr;
334
{
335
    if (!wmPtr->isremapping) {
336
        wmPtr->isremapping = 1;
337
        Tk_DoWhenIdle(RemapWindow, (ClientData)wmPtr);
338
    }
339
}
340
 
341
/*
342
 * SetMwmDecorations --
343
 *
344
 *
345
 */
346
static
347
int SetMwmDecorations(interp, wmPtr, argc, argv)
348
    Tcl_Interp *interp;
349
    Tix_MwmInfo*wmPtr;
350
    int         argc;
351
    char     ** argv;
352
{
353
    int                 i;
354
    int                 decor;
355
    char                buff[40];
356
 
357
    if (argc == 0 || argc == 1) {
358
        /*
359
         * Query the existing settings
360
         */
361
        QueryMwmHints(wmPtr);
362
 
363
        if (argc == 0) {
364
            /*
365
             * Query all hints
366
             */
367
            sprintf(buff, "-border %d",
368
                ((wmPtr->prop.decorations & MWM_DECOR_BORDER)!=0));
369
            Tcl_AppendElement(interp, buff);
370
 
371
            sprintf(buff, "-resizeh %d",
372
                ((wmPtr->prop.decorations &MWM_DECOR_RESIZEH)!=0));
373
            Tcl_AppendElement(interp, buff);
374
 
375
            sprintf(buff, "-title %d",
376
                ((wmPtr->prop.decorations & MWM_DECOR_TITLE)!=0));
377
            Tcl_AppendElement(interp, buff);
378
 
379
            sprintf(buff, "-menu %d",
380
                ((wmPtr->prop.decorations & MWM_DECOR_MENU)!=0));
381
            Tcl_AppendElement(interp, buff);
382
 
383
            sprintf(buff, "-minimize %d",
384
                ((wmPtr->prop.decorations&MWM_DECOR_MINIMIZE)!=0));
385
            Tcl_AppendElement(interp, buff);
386
 
387
            sprintf(buff, "-maximize %d",
388
                ((wmPtr->prop.decorations&MWM_DECOR_MAXIMIZE)!=0));
389
            Tcl_AppendElement(interp, buff);
390
 
391
            return TCL_OK;
392
        } else {
393
            /*
394
             * Query only one hint
395
             */
396
            if ((decor = MwmDecor(interp, argv[0])) == MWM_DECOR_UNKNOWN) {
397
                return TCL_ERROR;
398
            }
399
 
400
            if (wmPtr->prop.decorations & decor) {
401
                Tcl_AppendResult(interp, "1", NULL);
402
            } else {
403
                Tcl_AppendResult(interp, "0", NULL);
404
            }
405
            return TCL_OK;
406
        }
407
    } else {
408
        if (argc %2) {
409
            Tcl_AppendResult(interp, "value missing for option \"",
410
                argv[argc-1], "\"", NULL);
411
                return TCL_ERROR;
412
        }
413
 
414
        for (i=0; i<argc; i+=2) {
415
            int value;
416
 
417
            if ((decor = MwmDecor(interp, argv[i])) == MWM_DECOR_UNKNOWN)  {
418
                return TCL_ERROR;
419
            }
420
 
421
            if (Tcl_GetBoolean(interp, argv[i+1], &value) != TCL_OK) {
422
                return TCL_ERROR;
423
            }
424
 
425
            if (value) {
426
                wmPtr->prop.decorations |= decor;
427
            }
428
            else {
429
                wmPtr->prop.decorations &= ~decor;
430
            }
431
 
432
            if (decor == MWM_DECOR_ALL) {
433
                if (value) {
434
                    wmPtr->prop.decorations |= MWM_DECOR_EVERYTHING;
435
                } else {
436
                    wmPtr->prop.decorations &= ~MWM_DECOR_EVERYTHING;
437
                }
438
            }
439
        }
440
 
441
        wmPtr->prop.flags = MWM_HINTS_DECORATIONS;
442
        XChangeProperty(Tk_Display(wmPtr->tkwin), Tk_WindowId(wmPtr->tkwin),
443
            wmPtr->mwm_hints_atom, wmPtr->mwm_hints_atom, 32, PropModeReplace,
444
            (unsigned char *) &wmPtr->prop, PROP_MWM_HINTS_ELEMENTS);
445
 
446
        if (Tk_IsMapped(wmPtr->tkwin)) {
447
            /* Needs unmap/map to refresh */
448
            RemapWindowWhenIdle(wmPtr);
449
        }
450
        return TCL_OK;
451
    }
452
}
453
 
454
static int MwmProtocol(interp, wmPtr, argc, argv)
455
    Tcl_Interp * interp;
456
    Tix_MwmInfo * wmPtr;
457
    int argc;
458
    char ** argv;
459
{
460
    size_t len;
461
 
462
    if (argc == 0) {
463
        Tcl_HashSearch    hSearch;
464
        Tcl_HashEntry   * hashPtr;
465
        Tix_MwmProtocol * ptPtr;
466
 
467
        /* Iterate over all the entries in the hash table */
468
        for (hashPtr = Tcl_FirstHashEntry(&wmPtr->protocols, &hSearch);
469
             hashPtr;
470
             hashPtr = Tcl_NextHashEntry(&hSearch)) {
471
 
472
            ptPtr = (Tix_MwmProtocol *)Tcl_GetHashValue(hashPtr);
473
            Tcl_AppendElement(interp, ptPtr->name);
474
        }
475
        return TCL_OK;
476
    }
477
 
478
    len = strlen(argv[0]);
479
    if (strncmp(argv[0], "add", len) == 0 && argc == 3) {
480
        AddMwmProtocol(interp, wmPtr, argv[1], argv[2]);
481
    }
482
    else if (strncmp(argv[0], "activate", len) == 0 && argc == 2) {
483
        ActivateMwmProtocol(interp, wmPtr, argv[1]);
484
    }
485
    else if (strncmp(argv[0], "deactivate", len) == 0 && argc == 2) {
486
        DeactivateMwmProtocol(interp, wmPtr, argv[1]);
487
    }
488
    else if (strncmp(argv[0], "delete", len) == 0 && argc == 2) {
489
        DeleteMwmProtocol(interp, wmPtr, argv[1]);
490
    }
491
    else {
492
        Tcl_AppendResult(interp, "unknown option \"", argv[0],
493
            "\" should be add, activate, deactivate or delete", NULL);
494
        return TCL_ERROR;
495
    }
496
 
497
    return TCL_OK;
498
}
499
 
500
 
501
static void AddMwmProtocol(interp, wmPtr, name, message)
502
    Tcl_Interp  *interp;
503
    Tix_MwmInfo *wmPtr;
504
    char * name;
505
    char * message;
506
{
507
    Atom protocol;
508
    Tix_MwmProtocol *ptPtr;
509
 
510
    protocol = Tk_InternAtom(wmPtr->tkwin, name);
511
    ptPtr = GetMwmProtocol(interp, wmPtr, protocol);
512
 
513
    if (ptPtr->menuMessage != NULL) {
514
        /* This may happen if "protocol add" called twice for the same name */
515
        ckfree(ptPtr->menuMessage);
516
    }
517
 
518
    if (ptPtr->name == NULL) {
519
        ptPtr->name = (char*)tixStrDup(name);
520
    }
521
    ptPtr->menuMessage = (char*)tixStrDup(message);
522
    ptPtr->messageLen  = strlen(message);
523
    ptPtr->active = 1;
524
 
525
    ResetProtocolsWhenIdle(wmPtr);
526
}
527
 
528
static void ActivateMwmProtocol(interp, wmPtr, name)
529
    Tcl_Interp  *interp;
530
    Tix_MwmInfo *wmPtr;
531
    char * name;
532
{
533
    Atom protocol;
534
    Tix_MwmProtocol *ptPtr;
535
 
536
    protocol = Tk_InternAtom(wmPtr->tkwin, name);
537
    ptPtr = GetMwmProtocol(interp, wmPtr, protocol);
538
    ptPtr->active = 1;
539
 
540
    ResetProtocolsWhenIdle(wmPtr);
541
}
542
 
543
static void DeactivateMwmProtocol(interp, wmPtr, name)
544
    Tcl_Interp  *interp;
545
    Tix_MwmInfo *wmPtr;
546
    char * name;
547
{
548
    Atom protocol;
549
    Tix_MwmProtocol *ptPtr;
550
 
551
    protocol = Tk_InternAtom(wmPtr->tkwin, name);
552
    ptPtr = GetMwmProtocol(interp, wmPtr, protocol);
553
    ptPtr->active = 0;
554
 
555
    ResetProtocolsWhenIdle(wmPtr);
556
}
557
 
558
/*
559
 * Any "wm protocol" event handlers for the deleted protocol are
560
 * *not* automatically deleted. It is the application programmer's
561
 * responsibility to delete them using
562
 *
563
 *      wm protocol SOME_JUNK_PROTOCOL {}
564
 */
565
static void DeleteMwmProtocol(interp, wmPtr, name)
566
    Tcl_Interp  *interp;
567
    Tix_MwmInfo *wmPtr;
568
    char * name;
569
{
570
    Atom protocol;
571
    Tix_MwmProtocol *ptPtr;
572
    Tcl_HashEntry * hashPtr;
573
 
574
    protocol = Tk_InternAtom(wmPtr->tkwin, name);
575
    hashPtr = Tcl_FindHashEntry(&wmPtr->protocols, (char*)protocol);
576
 
577
    if (hashPtr) {
578
        ptPtr = (Tix_MwmProtocol *)Tcl_GetHashValue(hashPtr);
579
        ckfree(ptPtr->name);
580
        ckfree(ptPtr->menuMessage);
581
        ckfree((char*)ptPtr);
582
        Tcl_DeleteHashEntry(hashPtr);
583
    }
584
 
585
    ResetProtocolsWhenIdle(wmPtr);
586
}
587
 
588
 
589
static void
590
ResetProtocolsWhenIdle(wmPtr)
591
    Tix_MwmInfo * wmPtr;
592
{
593
    if (!wmPtr->resetProtocol) {
594
        wmPtr->resetProtocol = 1;
595
        Tk_DoWhenIdle(ResetProtocols, (ClientData)wmPtr);
596
    }
597
}
598
 
599
static void ResetProtocols(clientData)
600
    ClientData clientData;
601
{
602
    Tix_MwmInfo       * wmPtr = (Tix_MwmInfo *) clientData;
603
    int                 numProtocols = wmPtr->protocols.numEntries;
604
    Atom              * atoms, mwm_menu_atom, motif_msgs;
605
    Tcl_HashSearch      hSearch;
606
    Tcl_HashEntry     * hashPtr;
607
    Tix_MwmProtocol   * ptPtr;
608
    int                 n;
609
    Tcl_DString         dString;
610
 
611
    atoms = (Atom*)ckalloc(numProtocols * sizeof(Atom));
612
    Tcl_DStringInit(&dString);
613
 
614
    /* Iterate over all the entries in the hash table */
615
    for (hashPtr = Tcl_FirstHashEntry(&wmPtr->protocols, &hSearch), n=0;
616
         hashPtr;
617
         hashPtr = Tcl_NextHashEntry(&hSearch)) {
618
        char tmp[100];
619
 
620
        ptPtr = (Tix_MwmProtocol *)Tcl_GetHashValue(hashPtr);
621
        if (ptPtr->active) {
622
            atoms[n++] = ptPtr->protocol;
623
        }
624
 
625
        Tcl_DStringAppend(&dString, ptPtr->menuMessage, ptPtr->messageLen);
626
        sprintf(tmp, " f.send_msg %d\n", (int)(ptPtr->protocol));
627
        Tcl_DStringAppend(&dString, tmp, (int)strlen(tmp));
628
    }
629
 
630
    /* Atoms for managing the MWM messages */
631
    mwm_menu_atom   = Tk_InternAtom(wmPtr->tkwin, _XA_MWM_MENU);
632
    motif_msgs      = Tk_InternAtom(wmPtr->tkwin, "_MOTIF_WM_MESSAGES");
633
 
634
    /* The _MOTIF_WM_MESSAGES atom must be in the wm_protocols. Otherwise
635
     * Mwm refuese to enable our menu items
636
     */
637
    if (!wmPtr->addedMwmMsg) {
638
        Tix_GlobalVarEval(wmPtr->interp, "wm protocol ",
639
            Tk_PathName(wmPtr->tkwin), " _MOTIF_WM_MESSAGES {;}", NULL);
640
        wmPtr->addedMwmMsg = 1;
641
    }
642
 
643
    /*
644
     * These are the extra MWM protocols defined by this application.
645
     */
646
    XChangeProperty(Tk_Display(wmPtr->tkwin), Tk_WindowId(wmPtr->tkwin),
647
        motif_msgs, XA_ATOM, 32, PropModeReplace,
648
        (unsigned char *)atoms, n);
649
 
650
    /*
651
     * Update the MWM menu items
652
     */
653
    XChangeProperty(Tk_Display(wmPtr->tkwin), Tk_WindowId(wmPtr->tkwin),
654
        mwm_menu_atom, mwm_menu_atom, 8, PropModeReplace,
655
        (unsigned char *)dString.string, dString.length+1);
656
 
657
    Tcl_DStringFree(&dString);
658
    ckfree((char*)atoms);
659
 
660
    /* Done ! */
661
    wmPtr->resetProtocol = 0;
662
    if (Tk_IsMapped(wmPtr->tkwin)) {
663
        /* Needs unmap/map to refresh */
664
        RemapWindowWhenIdle(wmPtr);
665
    }
666
}
667
 
668
 
669
static
670
int SetMwmTransientFor(interp, wmPtr, mainWindow, argc, argv)
671
    Tcl_Interp *interp;
672
    Tix_MwmInfo*wmPtr;
673
    TkWindow   *mainWindow;
674
    int         argc;
675
    char     ** argv;
676
{
677
    Atom        transfor_atom;
678
    TkWindow  * master;
679
 
680
    transfor_atom = Tk_InternAtom(wmPtr->tkwin, "WM_TRANSIENT_FOR");
681
    if (argc == 0) {
682
        return TCL_OK;
683
    } else if (argc == 1) {
684
        master = (TkWindow *) Tk_NameToWindow(interp, argv[0],
685
            (Tk_Window)mainWindow);
686
        if (master == NULL) {
687
            return TCL_ERROR;
688
        }
689
        XChangeProperty(Tk_Display(wmPtr->tkwin), Tk_WindowId(wmPtr->tkwin),
690
            transfor_atom, XA_WINDOW, 32, PropModeReplace,
691
            (unsigned char *)&master->window, 1);
692
        return TCL_OK;
693
    } else {
694
        return TCL_ERROR;
695
    }
696
}
697
 
698
/*
699
 *----------------------------------------------------------------------
700
 *
701
 * StructureProc --
702
 *
703
 *      Gets called in response to StructureNotify events in toplevels
704
 *      operated by the tixMwm command.
705
 *
706
 * Results:
707
 *      none
708
 *
709
 * Side effects:
710
 *      The Tix_MwmInfo for the toplevel is deleted when the toplevel
711
 *      is destroyed.
712
 *
713
 *----------------------------------------------------------------------
714
 */
715
static void
716
StructureProc(clientData, eventPtr)
717
    ClientData clientData;              /* Our information about window
718
                                         * referred to by eventPtr. */
719
    XEvent *eventPtr;                   /* Describes what just happened. */
720
{
721
    register Tix_MwmInfo * wmPtr = (Tix_MwmInfo *) clientData;
722
    Tcl_HashEntry *hashPtr;
723
 
724
    if (eventPtr->type == DestroyNotify) {
725
        Tcl_HashSearch    hSearch;
726
        Tix_MwmProtocol * ptPtr;
727
 
728
        /* Delete all protocols in the hash table associated with
729
         * this toplevel
730
         */
731
        for (hashPtr = Tcl_FirstHashEntry(&wmPtr->protocols, &hSearch);
732
             hashPtr;
733
             hashPtr = Tcl_NextHashEntry(&hSearch)) {
734
 
735
            ptPtr = (Tix_MwmProtocol *)Tcl_GetHashValue(hashPtr);
736
            ckfree(ptPtr->name);
737
            ckfree(ptPtr->menuMessage);
738
            ckfree((char*)ptPtr);
739
            Tcl_DeleteHashEntry(hashPtr);
740
        }
741
 
742
        Tcl_DeleteHashTable(&wmPtr->protocols);
743
 
744
        /*
745
         * Delete info about this toplevel in the table of all toplevels
746
         * controlled by tixMwm
747
         */
748
        hashPtr = Tcl_FindHashEntry(&mwmTable, (char*)wmPtr->tkwin);
749
        if (hashPtr != NULL) {
750
            Tcl_DeleteHashEntry(hashPtr);
751
        }
752
 
753
        if (wmPtr->resetProtocol) {
754
            Tk_CancelIdleCall(ResetProtocols, (ClientData)wmPtr);
755
            wmPtr->resetProtocol = 0;
756
        }
757
 
758
        ckfree((char*)wmPtr);
759
    }
760
}
761
 
762
static Tix_MwmInfo *
763
GetMwmInfo(interp, tkwin)
764
    Tcl_Interp * interp;
765
    Tk_Window tkwin;
766
{
767
    static inited = 0;
768
    Tcl_HashEntry *hashPtr;
769
    int isNew;
770
 
771
    if (!inited) {
772
        Tcl_InitHashTable(&mwmTable, TCL_ONE_WORD_KEYS);
773
        inited = 1;
774
    }
775
 
776
    hashPtr = Tcl_CreateHashEntry(&mwmTable, (char*)tkwin, &isNew);
777
 
778
    if (!isNew) {
779
        return (Tix_MwmInfo *)Tcl_GetHashValue(hashPtr);
780
    }
781
    else {
782
        Tix_MwmInfo * wmPtr;
783
 
784
        wmPtr = (Tix_MwmInfo*) ckalloc(sizeof(Tix_MwmInfo));
785
        wmPtr->interp           = interp;
786
        wmPtr->tkwin            = tkwin;
787
        wmPtr->isremapping      = 0;
788
        wmPtr->resetProtocol    = 0;
789
        wmPtr->addedMwmMsg      = 0;
790
        if (Tk_WindowId(wmPtr->tkwin) == 0) {
791
            Tk_MakeWindowExist(wmPtr->tkwin);
792
        }
793
        wmPtr->mwm_hints_atom   = Tk_InternAtom(wmPtr->tkwin, _XA_MWM_HINTS);
794
 
795
        Tcl_InitHashTable(&wmPtr->protocols, TCL_ONE_WORD_KEYS);
796
 
797
        QueryMwmHints(wmPtr);
798
 
799
        Tcl_SetHashValue(hashPtr, (char*)wmPtr);
800
 
801
        Tk_CreateEventHandler(tkwin, StructureNotifyMask,
802
            StructureProc, (ClientData)wmPtr);
803
 
804
        return wmPtr;
805
    }
806
}
807
 
808
static Tix_MwmProtocol *
809
GetMwmProtocol(interp,  wmPtr, protocol)
810
    Tcl_Interp * interp;
811
    Tix_MwmInfo * wmPtr;
812
    Atom protocol;
813
{
814
    Tcl_HashEntry     * hashPtr;
815
    int                 isNew;
816
    Tix_MwmProtocol   * ptPtr;
817
 
818
    hashPtr = Tcl_CreateHashEntry(&wmPtr->protocols, (char*)protocol, &isNew);
819
    if (!isNew) {
820
        ptPtr = (Tix_MwmProtocol *)Tcl_GetHashValue(hashPtr);
821
    } else {
822
        ptPtr = (Tix_MwmProtocol *)ckalloc(sizeof(Tix_MwmProtocol));
823
 
824
        ptPtr->protocol         = protocol;
825
        ptPtr->name             = NULL;
826
        ptPtr->menuMessage      = NULL;
827
 
828
        Tcl_SetHashValue(hashPtr, (char*)ptPtr);
829
    }
830
 
831
    return ptPtr;
832
}
833
 
834
 
835
static int
836
IsMwmRunning(interp, wmPtr)
837
    Tcl_Interp *interp;
838
    Tix_MwmInfo*wmPtr;
839
{
840
    Atom motif_wm_info_atom;
841
    Atom actual_type;
842
    int  actual_format;
843
    unsigned long num_items, bytes_after;
844
    PropMotifWmInfo *prop = 0;
845
    Window root;
846
 
847
    root = XRootWindow(Tk_Display(wmPtr->tkwin),Tk_ScreenNumber(wmPtr->tkwin));
848
    motif_wm_info_atom = Tk_InternAtom(wmPtr->tkwin, _XA_MOTIF_WM_INFO);
849
 
850
    /*
851
     * If mwm is running, it will store info in the _XA_MOTIF_WM_INFO
852
     * atom in the root window
853
     */
854
    XGetWindowProperty (Tk_Display(wmPtr->tkwin),
855
        root, motif_wm_info_atom, 0, (long)PROP_MOTIF_WM_INFO_ELEMENTS,
856
        0, motif_wm_info_atom,   &actual_type, &actual_format,
857
        &num_items, &bytes_after, (unsigned char **) &prop);
858
 
859
    if ((actual_type != motif_wm_info_atom) || (actual_format != 32) ||
860
        (num_items < PROP_MOTIF_WM_INFO_ELEMENTS)) {
861
 
862
        /*
863
         * The _XA_MOTIF_WM_INFO doesn't exist for the root window.
864
         * Persumably Mwm is not running.
865
         */
866
        if (prop) {
867
            XFree((char *)prop);
868
        }
869
        return(0);
870
    }
871
    else {
872
        /*
873
         * We still need to verify that the wm_window is indeed a child of
874
         * the root window.
875
         */
876
        Window  wm_window = (Window) prop->wmWindow;
877
        Window  top, parent, *children;
878
        unsigned int num_children;
879
        int     returnVal = 0;
880
        int     i;
881
 
882
        if (XQueryTree(Tk_Display(wmPtr->tkwin), root, &top, &parent,
883
            &children, &num_children)) {
884
 
885
            for (returnVal = 0, i = 0; i < num_children; i++) {
886
                if (children[i] == wm_window) {
887
                    /*
888
                     * is indeed a window of this root: mwm is rinning
889
                     */
890
                    returnVal = 1;
891
                    break;
892
                }
893
            }
894
        }
895
 
896
        if (prop) {
897
            XFree((char *)prop);
898
        }
899
        if (children) {
900
            XFree((char *)children);
901
        }
902
 
903
        return (returnVal);
904
    }
905
}

powered by: WebSVN 2.1.0

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