source: trunk/third/mwm/WmProtocol.c @ 9757

Revision 9757, 24.9 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r9756, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
3 * ALL RIGHTS RESERVED
4*/
5/*
6 * Motif Release 1.2.3
7*/
8#ifdef REV_INFO
9#ifndef lint
10static char rcsid[] = "$RCSfile: WmProtocol.c,v $ $Revision: 1.1.1.1 $ $Date: 1997-03-25 09:12:23 $"
11#endif
12#endif
13/*
14 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
15
16/*
17 * Included Files:
18 */
19
20#include "WmGlobal.h"
21#include "WmICCC.h"
22
23/*
24 * include extern functions
25 */
26
27#include "WmError.h"
28#include "WmFunction.h"
29#include "WmKeyFocus.h"
30#include "WmMenu.h"
31#include "WmWinInfo.h"
32#ifndef NO_WMQUERY
33#include "WmEvent.h"
34#endif /* NO_WMQUERY */
35
36/*
37 * Function Declarations:
38 */
39
40#ifdef _NO_PROTO
41Boolean AddWmTimer ();
42void    DeleteClientWmTimers ();
43void    SetupWmICCC ();
44void    SendClientMsg ();
45void    SendConfigureNotify ();
46void    TimeoutProc ();
47#ifndef NO_WMQUERY
48static Boolean wmq_convert();
49static Boolean wmq_convert_all_clients();
50static void wmq_list_subtree();
51static void wmq_add_xid();
52static void wmq_done();
53static void wmq_lose();
54static void wmq_bump_xids();
55#endif /* NO_WMQUERY */
56#else /* _NO_PROTO */
57void SetupWmICCC (void);
58void SendConfigureNotify (ClientData *pCD);
59void SendClientOffsetMessage (ClientData *pCD);
60void SendClientMsg (Window window, long type, long data0, Time time, long *pData, int dataLen);
61Boolean AddWmTimer (unsigned int timerType, unsigned long timerInterval, ClientData *pCD);
62void DeleteClientWmTimers (ClientData *pCD);
63void TimeoutProc (XtPointer client_data, XtIntervalId *id);
64#ifndef NO_WMQUERY
65static Boolean wmq_convert (Widget w, Atom *pSelection, Atom *pTarget,
66    Atom *pType_return, XtPointer *pValue_return, unsigned long *pLength_return,
67    int *pFormat_return);
68static Boolean wmq_convert_all_clients (Widget w, int screen,
69    Atom *pType_return, XtPointer *pValue_return, unsigned long *pLength_return,
70    int *pFormat_return);
71static void wmq_list_subtree (ClientData *pCD);
72static void wmq_add_xid (XID win);
73static void wmq_done (Widget w, Atom *pSelection, Atom *pTarget);
74static void wmq_lose (Widget w, Atom *pSelection);
75static void wmq_bump_xids(void);
76#endif /* NO_WMQUERY */
77#endif /* _NO_PROTO */
78
79
80
81/*
82 * Global Variables:
83 */
84#ifndef NO_WMQUERY
85Atom *xa_WM_QUERY = NULL;
86Atom xa_WM_POINTER_WINDOW;
87Atom xa_WM_CLIENT_WINDOW;
88Atom xa_WM_ALL_CLIENTS;
89XID *pXids = NULL;
90int numXids = -1;
91int curXids = 0;
92#endif /* NO_WMQUERY */
93
94
95
96/*************************************<->*************************************
97 *
98 *  SetupWmICCC ()
99 *
100 *
101 *  Description:
102 *  -----------
103 *  This function sets up the window manager handling of the inter-client
104 *  communications conventions.
105 *
106 *
107 *  Outputs:
108 *  -------
109 *  (wmGD) = Atoms id's are setup.
110 *
111 *************************************<->***********************************/
112
113#ifdef _NO_PROTO
114void SetupWmICCC ()
115
116#else /* _NO_PROTO */
117void SetupWmICCC (void)
118#endif /* _NO_PROTO */
119{
120    XIconSize sizeList;
121    int scr;
122
123    /*
124     * Make atoms that are required by the ICCC and mwm.  The atom for
125     * _MOTIF_WM_INFO is intern'ed in ProcessMotifWmInfo.
126     */
127
128    wmGD.xa_WM_STATE = XInternAtom (DISPLAY, _XA_WM_STATE, False);
129    wmGD.xa_WM_PROTOCOLS = XInternAtom (DISPLAY, _XA_WM_PROTOCOLS, False);
130    wmGD.xa_WM_CHANGE_STATE = XInternAtom (DISPLAY, _XA_WM_CHANGE_STATE, False);
131    wmGD.xa_WM_SAVE_YOURSELF = XInternAtom (DISPLAY, _XA_WM_SAVE_YOURSELF,
132                                   False);
133    wmGD.xa_WM_DELETE_WINDOW = XInternAtom (DISPLAY, _XA_WM_DELETE_WINDOW,
134                                   False);
135    wmGD.xa_WM_COLORMAP_WINDOWS = XInternAtom (DISPLAY, _XA_WM_COLORMAP_WINDOWS,
136                                   False);
137    wmGD.xa_WM_TAKE_FOCUS = XInternAtom (DISPLAY, _XA_WM_TAKE_FOCUS, False);
138    wmGD.xa_MWM_HINTS = XInternAtom (DISPLAY, _XA_MWM_HINTS, False);
139    wmGD.xa_MWM_MENU = XInternAtom (DISPLAY, _XA_MWM_MENU, False);
140    wmGD.xa_MWM_MESSAGES = XInternAtom (DISPLAY, _XA_MWM_MESSAGES, False);
141    wmGD.xa_MWM_OFFSET = XInternAtom (DISPLAY, _XA_MOTIF_WM_OFFSET, False);
142#ifdef AUTOMATION
143    wmGD.xa_MWM_FRAME_ICON_INFO = XInternAtom (DISPLAY,
144                                               _XA_MWM_FRAME_ICON_INFO, False);
145#endif
146    wmGD.xa_COMPOUND_TEXT = XInternAtom (DISPLAY, "COMPOUND_TEXT", False);
147
148#ifndef NO_WMQUERY
149    if (!(xa_WM_QUERY = (Atom *) XtMalloc (wmGD.numScreens * (sizeof (Atom)))))
150    {
151        Warning ("Insufficient memory to XInternAtom _MOTIF_WM_QUERY_nn");
152    }
153
154    for (scr = 0; scr < wmGD.numScreens; scr++)
155    {
156        if (wmGD.Screens[scr].managed)
157        {
158          char wm_query_scr[32];
159
160          sprintf(wm_query_scr, "_MOTIF_WM_QUERY_%d", scr);
161          xa_WM_QUERY[scr] = XInternAtom (DISPLAY, wm_query_scr, False);
162        }
163    }
164    xa_WM_CLIENT_WINDOW =
165            XInternAtom (DISPLAY, "_MOTIF_WM_CLIENT_WINDOW", False);
166    xa_WM_POINTER_WINDOW =
167            XInternAtom (DISPLAY, "_MOTIF_WM_POINTER_WINDOW", False);
168    xa_WM_ALL_CLIENTS =
169            XInternAtom (DISPLAY, "_MOTIF_WM_ALL_CLIENTS", False);
170#endif /* NO_WMQUERY */
171
172
173    /*
174     * Setup the icon size property on the root window.
175     */
176
177    sizeList.width_inc = 1;
178    sizeList.height_inc = 1;
179
180    for (scr = 0; scr < wmGD.numScreens; scr++)
181    {
182        if (wmGD.Screens[scr].managed)
183        {
184            sizeList.min_width = wmGD.Screens[scr].iconImageMinimum.width;
185            sizeList.min_height = wmGD.Screens[scr].iconImageMinimum.height;
186            sizeList.max_width = wmGD.Screens[scr].iconImageMaximum.width;
187            sizeList.max_height = wmGD.Screens[scr].iconImageMaximum.height;
188
189            XSetIconSizes (DISPLAY, wmGD.Screens[scr].rootWindow,
190                &sizeList, 1);
191        }
192    }
193
194#ifndef NO_WMQUERY
195    /*
196     * Assert ownership of the WM_QUERY selection
197     */
198    for (scr = 0; scr < wmGD.numScreens; scr++)
199    {
200        if (wmGD.Screens[scr].managed)
201        {
202            if (!XtOwnSelection(wmGD.topLevelW,
203                                xa_WM_QUERY[scr],
204                                GetTimestamp(),
205                                wmq_convert,
206                                wmq_lose,
207                                wmq_done))
208              {
209                  Warning ("Failed to own _MOTIF_WM_QUERY_nn selection");
210              }
211        }
212    }
213#endif /* NO_WMQUERY */
214
215
216} /* END OF FUNCTION SetupWmICCC */
217
218
219
220/*************************************<->*************************************
221 *
222 *  SendConfigureNotify (pCD)
223 *
224 *
225 *  Description:
226 *  -----------
227 *  This function is used to send a synthetic ConfigureNotify event when
228 *  a client window is reconfigured in certain ways (e.g., the window is
229 *  moved without being resized).
230 *
231 *
232 *  Inputs:
233 *  ------
234 *  pCD = pointer to client data (window id and client size data)
235 *
236 *************************************<->***********************************/
237
238#ifdef _NO_PROTO
239void SendConfigureNotify (pCD)
240        ClientData *pCD;
241
242#else /* _NO_PROTO */
243void SendConfigureNotify (ClientData *pCD)
244#endif /* _NO_PROTO */
245{
246    XConfigureEvent notifyEvent;
247
248
249    /*
250     * Send a synthetic ConfigureNotify message:
251     */
252
253    notifyEvent.type = ConfigureNotify;
254    notifyEvent.display = DISPLAY;
255    notifyEvent.event = pCD->client;
256    notifyEvent.window = pCD->client;
257    if (pCD->maxConfig)
258    {
259        notifyEvent.x = pCD->maxX;
260        notifyEvent.y = pCD->maxY;
261        notifyEvent.width = pCD->maxWidth;
262        notifyEvent.height = pCD->maxHeight;
263    }
264    else
265    {
266        notifyEvent.x = pCD->clientX;
267        notifyEvent.y = pCD->clientY;
268        notifyEvent.width = pCD->clientWidth;
269        notifyEvent.height = pCD->clientHeight;
270    }
271    notifyEvent.border_width = 0;
272    notifyEvent.above = None;
273    notifyEvent.override_redirect = False;
274
275    XSendEvent (DISPLAY, pCD->client, False, StructureNotifyMask,
276        (XEvent *)&notifyEvent);
277
278
279} /* END OF FUNCTION SendConfigureNotify */
280
281
282
283/*************************************<->*************************************
284 *
285 *  SendClientOffsetMessage (pCD)
286 *
287 *
288 *  Description:
289 *  -----------
290 *  This function is used to send a client message containing the offset
291 *  between the window position reported to the user and the actual
292 *  window position of the client over the root.
293 *
294 *  This can be used by clients that map and unmap windows to help them
295 *  work with the window manager to place the window in the same location
296 *  when remapped.
297 *
298 *  Inputs:
299 *  ------
300 *  pCD = pointer to client data (frame geometry info)
301 *
302 *************************************<->***********************************/
303
304#ifdef _NO_PROTO
305void SendClientOffsetMessage (pCD)
306        ClientData *pCD;
307
308#else /* _NO_PROTO */
309void SendClientOffsetMessage (ClientData *pCD)
310#endif /* _NO_PROTO */
311{
312    long borderWidth = (long)pCD->xBorderWidth;
313    long offsetX = pCD->clientOffset.x;
314    long offsetY = pCD->clientOffset.y;
315
316    XClientMessageEvent clientMsgEvent;
317
318    clientMsgEvent.type = ClientMessage;
319    clientMsgEvent.window = pCD->client;
320    clientMsgEvent.message_type = wmGD.xa_MWM_MESSAGES;
321    clientMsgEvent.format = 32;
322    clientMsgEvent.data.l[0] = wmGD.xa_MWM_OFFSET;
323
324    /*
325     * Use window gravity to allow the user to specify the window
326     * position on the screen  without having to know the dimensions
327     * of the decoration that mwm is adding.
328     */
329   
330    switch (pCD->windowGravity)
331    {
332      case NorthWestGravity:
333      default:
334        {
335            clientMsgEvent.data.l[1] = offsetX;
336            clientMsgEvent.data.l[2] = offsetY;
337            break;
338        }
339       
340      case NorthGravity:
341        {
342            clientMsgEvent.data.l[1] = borderWidth;
343            clientMsgEvent.data.l[2] = offsetY;
344            break;
345        }
346       
347      case NorthEastGravity:
348        {
349            clientMsgEvent.data.l[1] = -(offsetX - (2 * borderWidth));
350            clientMsgEvent.data.l[2] = offsetY;
351            break;
352        }
353       
354      case EastGravity:
355        {
356            clientMsgEvent.data.l[1] = -(offsetX - (2 * borderWidth));
357            clientMsgEvent.data.l[2] = borderWidth + (offsetY - offsetX)/2;
358            break;
359        }
360       
361      case SouthEastGravity:
362        {
363            clientMsgEvent.data.l[1] = -(offsetX - (2 * borderWidth));
364            clientMsgEvent.data.l[2] = -(offsetX - (2 * borderWidth));
365            break;
366        }
367       
368      case SouthGravity:
369        {
370            clientMsgEvent.data.l[1] = borderWidth;
371            clientMsgEvent.data.l[2] = -(offsetX - (2 * borderWidth));
372            break;
373        }
374       
375      case SouthWestGravity:
376        {
377            clientMsgEvent.data.l[1] = offsetX;
378            clientMsgEvent.data.l[2] = -(offsetX - (2 * borderWidth));
379            break;
380        }
381       
382      case WestGravity:
383        {
384            clientMsgEvent.data.l[1] = offsetX;
385            clientMsgEvent.data.l[2] = borderWidth + (offsetY - offsetX)/2;
386            break;
387        }
388       
389      case CenterGravity:
390        {
391            clientMsgEvent.data.l[2] = (offsetY - offsetX)/2;
392            break;
393        }
394    }
395
396    XSendEvent (DISPLAY, pCD->client, False, NoEventMask,
397        (XEvent *)&clientMsgEvent);
398
399
400} /* END OF FUNCTION SendClientOffsetMessage */
401
402
403/*************************************<->*************************************
404 *
405 *  SendClientMsg (window, type, data0, time, pData, dataLen)
406 *
407 *
408 *  Description:
409 *  -----------
410 *  This function is used to send a client message event that to a client
411 *  window.  The message may be sent as part of a protocol arranged for by
412 *  the client with the WM_PROTOCOLS property.
413 *
414 *
415 *  Inputs:
416 *  ------
417 *  window = destination window for the client message event
418 *
419 *  type = client message type
420 *
421 *  data0 = data0 value in the client message
422 *
423 *  time = timestamp to be used in the event
424 *
425 *  pData = pointer to data to be used in the event
426 *
427 *  dataLen = len of data (in 32 bit units)
428 *
429 *************************************<->***********************************/
430
431#ifdef _NO_PROTO
432void SendClientMsg (window, type, data0, time, pData, dataLen)
433        Window window;
434        long type;
435        long data0;
436        Time time;
437        long *pData;
438        int dataLen;
439
440#else /* _NO_PROTO */
441void SendClientMsg (Window window, long type, long data0, Time time, long *pData, int dataLen)
442#endif /* _NO_PROTO */
443{
444    XClientMessageEvent clientMsgEvent;
445    int i;
446
447
448    clientMsgEvent.type = ClientMessage;
449    clientMsgEvent.window = window;
450    clientMsgEvent.message_type = type;
451    clientMsgEvent.format = 32;
452    clientMsgEvent.data.l[0] = data0;
453    clientMsgEvent.data.l[1] = (long)time;
454    if (pData)
455    {
456        /*
457         * Fill in the rest of the ClientMessage event (that holds up to
458         * 5 words of data).
459         */
460
461        if (dataLen > 3)
462        {
463            dataLen = 3;
464        }
465        for (i = 2; i < (2 + dataLen); i++)
466        {
467            clientMsgEvent.data.l[i] = pData[i];
468        }
469    }
470   
471   
472    XSendEvent (DISPLAY, window, False, NoEventMask,
473        (XEvent *)&clientMsgEvent);
474    XFlush(DISPLAY);
475
476
477} /* END OF FUNCTION SendClientMsg */
478
479
480
481/*************************************<->*************************************
482 *
483 *  AddWmTimer (timerType, timerInterval, pCD)
484 *
485 *
486 *  Description:
487 *  -----------
488 *  This function sets a window manager timer of the specified type.
489 *
490 *
491 *  Inputs:
492 *  ------
493 *  timerType = type of timer to be set
494 *
495 *  timerInterval = length of timeout in ms
496 *
497 *  pCD = pointer to client data associated with the timer
498 *
499 *  return = True if timer could be set
500 *
501 *************************************<->***********************************/
502
503#ifdef _NO_PROTO
504Boolean AddWmTimer (timerType, timerInterval, pCD)
505unsigned int timerType;
506unsigned long timerInterval;
507ClientData *pCD;
508
509#else /* _NO_PROTO */
510Boolean AddWmTimer (unsigned int timerType, unsigned long timerInterval, ClientData *pCD)
511#endif /* _NO_PROTO */
512{
513    WmTimer *pWmTimer;
514
515
516    if (!(pWmTimer = (WmTimer *)XtMalloc (sizeof (WmTimer))))
517    {
518        Warning ("Insufficient memory for window manager data");
519        return (False);
520    }
521
522    /* !!! handle for XtAppAddTimeOut error !!! */
523    pWmTimer->timerId = XtAppAddTimeOut (wmGD.mwmAppContext,
524                            timerInterval, (XtTimerCallbackProc)TimeoutProc, (XtPointer)pCD);
525    pWmTimer->timerCD = pCD;
526    pWmTimer->timerType = timerType;
527    pWmTimer->nextWmTimer = wmGD.wmTimers;
528    wmGD.wmTimers = pWmTimer;
529
530    return(True);
531
532} /* END OF FUNCTION AddWmTimer */
533
534
535
536/*************************************<->*************************************
537 *
538 *  DeleteClientWmTimers (pCD)
539 *
540 *
541 *  Description:
542 *  -----------
543 *  This function deletes all window manager timers that are associated with
544 *  the specified client window.
545 *
546 *
547 *  Inputs:
548 *  ------
549 *  pCD = pointer to client data for client whose timers are to be deleted
550 *
551 *  wmGD = (wmTimers)
552 *
553 *************************************<->***********************************/
554
555#ifdef _NO_PROTO
556void DeleteClientWmTimers (pCD)
557        ClientData *pCD;
558
559#else /* _NO_PROTO */
560void DeleteClientWmTimers (ClientData *pCD)
561#endif /* _NO_PROTO */
562{
563    WmTimer *pPrevTimer;
564    WmTimer *pWmTimer;
565    WmTimer *pRemoveTimer;
566
567
568    pPrevTimer = NULL;
569    pWmTimer = wmGD.wmTimers;
570    while (pWmTimer)
571    {
572        if (pWmTimer->timerCD == pCD)
573        {
574            if (pPrevTimer)
575            {
576                pPrevTimer->nextWmTimer = pWmTimer->nextWmTimer;
577            }
578            else
579            {
580                wmGD.wmTimers = pWmTimer->nextWmTimer;
581            }
582            pRemoveTimer = pWmTimer;
583            pWmTimer = pWmTimer->nextWmTimer;
584            XtRemoveTimeOut (pRemoveTimer->timerId);
585            XtFree ((char *)pRemoveTimer);
586        }
587        else
588        {
589            pPrevTimer = pWmTimer;
590            pWmTimer = pWmTimer->nextWmTimer;
591        }
592    }
593
594
595} /* END OF FUNCTION DeleteClientWmTimers */
596
597
598
599/*************************************<->*************************************
600 *
601 *  TimeoutProc (client_data, id)
602 *
603 *
604 *  Description:
605 *  -----------
606 *  This function is an Xtk timeout handler.  It is used to handle various
607 *  window manager timers (i.e. WM_SAVE_YOURSELF quit timeout).
608 *
609 *
610 *  Inputs:
611 *  ------
612 *  client_data = pointer to window manager client data
613 *
614 *  id = Xtk timer id
615 *
616 *************************************<->***********************************/
617
618#ifdef _NO_PROTO
619void TimeoutProc (client_data, id)
620        XtPointer client_data;
621        XtIntervalId *id;
622
623#else /* _NO_PROTO */
624void TimeoutProc (XtPointer client_data, XtIntervalId *id)
625#endif /* _NO_PROTO */
626{
627    WmTimer *pPrevTimer;
628    WmTimer *pWmTimer;
629
630   
631    /*
632     * Find out if the timer still needs to be serviced.
633     */
634
635    pPrevTimer = NULL;
636    pWmTimer = wmGD.wmTimers;
637    while (pWmTimer)
638    {
639        if (pWmTimer->timerId == *id)
640        {
641            break;
642        }
643        pPrevTimer = pWmTimer;
644        pWmTimer = pWmTimer->nextWmTimer;
645    }
646
647    if (pWmTimer)
648    {
649        /*
650         * Do the timer related action.
651         */
652
653        switch (pWmTimer->timerType)
654        {
655            case TIMER_QUIT:
656            {
657                XKillClient (DISPLAY, pWmTimer->timerCD->client);
658                break;
659            }
660
661            case TIMER_RAISE:
662            {
663                Boolean sameScreen;
664
665                if ((wmGD.keyboardFocus == pWmTimer->timerCD) &&
666                    (pWmTimer->timerCD->focusPriority ==
667                        (PSD_FOR_CLIENT(pWmTimer->timerCD))->focusPriority) &&
668                    (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) &&
669                    (pWmTimer->timerCD == GetClientUnderPointer(&sameScreen)))
670                {
671                    Do_Raise (pWmTimer->timerCD, (ClientListEntry *)NULL, STACK_NORMAL);
672                }
673                break;
674            }
675        }
676
677
678        /*
679         * Remove the timer from the wm timer list.
680         */
681
682        if (pPrevTimer)
683        {
684            pPrevTimer->nextWmTimer = pWmTimer->nextWmTimer;
685        }
686        else
687        {
688            wmGD.wmTimers = pWmTimer->nextWmTimer;
689        }
690        XtFree ((char *)pWmTimer);
691    }
692
693    /*
694     * Free up the timer.
695     */
696
697    XtRemoveTimeOut (*id);
698
699
700} /* END OF FUNCTION TimeoutProc */
701
702
703#ifndef NO_WMQUERY
704
705/*************************************<->*************************************
706 *
707 *  Boolean wmq_convert (w, pSelection, pTarget, pType_return,
708 *      pValue_return, pLength_return, pFormat_return)
709 *
710 *
711 *  Description:
712 *  -----------
713 *  This function converts WM_QUERY selections
714 *
715 *  Inputs:
716 *  ------
717 *  w - widget
718 *  pSelection - pointer to selection type (atom)
719 *  pTarget - pointer to requested target type (atom)
720 *
721 *  Outputs:
722 *  ------
723 *  pType_return - pointer to type of data returned (atom)
724 *  pValue_return - pointer to pointer to data returned
725 *  pLength_return - ptr to length of data returned
726 *  pFormat_return - ptr to format of data returned
727 *
728 *  Comments:
729 *  --------
730 *
731 *************************************<->***********************************/
732#ifdef _NO_PROTO
733static Boolean
734wmq_convert (w, pSelection, pTarget, pType_return, pValue_return,
735                pLength_return, pFormat_return)
736    Widget w;
737    Atom *pSelection;
738    Atom *pTarget;
739    Atom *pType_return;
740    XtPointer *pValue_return;
741    unsigned long *pLength_return;
742    int *pFormat_return;
743#else /* _NO_PROTO */
744static Boolean
745wmq_convert (
746    Widget w,
747    Atom *pSelection,
748    Atom *pTarget,
749    Atom *pType_return,
750    XtPointer *pValue_return,
751    unsigned long *pLength_return,
752    int *pFormat_return
753    )
754#endif /* _NO_PROTO */
755{
756
757    Boolean wm_query_found = False;
758    int scr;
759
760
761    for (scr = 0; scr < wmGD.numScreens; scr++)
762    {
763        if (wmGD.Screens[scr].managed)
764        {
765            if (*pSelection == xa_WM_QUERY[scr])
766            {
767                wm_query_found = True;
768                break;
769            }
770        }
771    }
772
773    if (wm_query_found)
774    {
775        if (*pTarget == xa_WM_POINTER_WINDOW)
776        {
777            return (False);
778        }
779        else if (*pTarget == xa_WM_CLIENT_WINDOW)
780        {
781            return (False);
782        }
783        else if (*pTarget == xa_WM_ALL_CLIENTS)
784        {
785            return (wmq_convert_all_clients (w, scr, pType_return,
786                        pValue_return, pLength_return,
787                        pFormat_return));
788        }
789    }
790
791    return (wm_query_found);
792} /* END OF FUNCTION wmq_convert */
793
794
795/*************************************<->*************************************
796 *
797 *  Boolean wmq_convert_all_clients (w, screen, pType_return,
798 *      pValue_return, pLength_return, pFormat_return)
799 *
800 *
801 *  Description:
802 *  -----------
803 *  This function converts the WM_QUERY selection target WM_ALL_CLIENTS
804 *
805 *  Inputs:
806 *  ------
807 *  w - widget
808 *  screen - screen number
809 *
810 *  Outputs:
811 *  ------
812 *  pType_return - pointer to type of data returned (atom)
813 *  pValue_return - pointer to pointer to data returned
814 *  pLength_return - ptr to length of data returned
815 *  pFormat_return - ptr to format of data returned
816 *
817 *  Comments:
818 *  --------
819 *
820 *************************************<->***********************************/
821#ifdef _NO_PROTO
822static Boolean
823wmq_convert_all_clients (w, screen, pType_return, pValue_return,
824                pLength_return, pFormat_return)
825    Widget w;
826    int screen;
827    Atom *pType_return;
828    XtPointer *pValue_return;
829    unsigned long *pLength_return;
830    int *pFormat_return;
831#else /* _NO_PROTO */
832static Boolean
833wmq_convert_all_clients (
834    Widget w,
835    int screen,
836    Atom *pType_return,
837    XtPointer *pValue_return,
838    unsigned long *pLength_return,
839    int *pFormat_return
840    )
841#endif /* _NO_PROTO */
842{
843    WmScreenData *pSD = NULL;
844    ClientListEntry *pEntry;
845    ClientData *pCD;
846
847    /*
848     * Start with empty client list
849     */
850    curXids = 0;
851
852    /*
853     * Get all clients on the specified screen
854     */
855
856    if (wmGD.Screens[screen].managed)
857    {
858        pSD = &wmGD.Screens[screen];
859         
860        /*
861         * Traverse the client list for this screen and
862         * add to the list of window IDs
863         */
864        pEntry = pSD->clientList;
865         
866        while (pEntry)
867        {
868            /*
869             * Filter out entries for icons
870             */
871            if (pEntry->type != MINIMIZED_STATE)
872            {
873                pCD = pEntry->pCD;
874                if (pCD->transientChildren)
875                {
876                    wmq_list_subtree(pCD->transientChildren);
877                }
878                wmq_add_xid ((XID) pCD->client);
879            }
880            pEntry = pEntry->nextSibling;
881        }
882    }
883
884    *pType_return = XA_WINDOW;
885    *pValue_return = (XtPointer) pXids;
886    *pLength_return = curXids;
887    *pFormat_return = 32;
888    return (True);
889
890} /* END OF FUNCTION wmq_convert_all_clients */
891
892
893/*************************************<->*************************************
894 *
895 *  void wmq_list_subtree (pCD)
896 *
897 *
898 *  Description:
899 *  -----------
900 *  This function adds the windows in a transient subtree to the
901 *  global window list
902 *
903 *  Inputs:
904 *  ------
905 *  pCD - client data for "leftmost" child of a subtree
906 *
907 *  Outputs:
908 *  ------
909 *
910 *  Comments:
911 *  --------
912 *
913 *************************************<->***********************************/
914#ifdef _NO_PROTO
915static void
916wmq_list_subtree (pCD)
917    ClientData *pCD;
918#else /* _NO_PROTO */
919static void
920wmq_list_subtree (
921    ClientData *pCD
922    )
923#endif /* _NO_PROTO */
924{
925
926    /*
927     * Do children first
928     */
929    if (pCD->transientChildren)
930    {
931        wmq_list_subtree(pCD->transientChildren);
932    }
933
934    /*
935     * Do me
936     */
937    wmq_add_xid ((XID) pCD->client);
938
939    /*
940     * Do siblings
941     */
942    if (pCD->transientSiblings)
943    {
944        wmq_list_subtree(pCD->transientSiblings);
945    }
946       
947} /* END OF FUNCTION wmq_list_subtree */
948
949
950
951/*************************************<->*************************************
952 *
953 *  void wmq_add_xid (win)
954 *
955 *
956 *  Description:
957 *  -----------
958 *  This function adds an xid to the list
959 *
960 *  Inputs:
961 *  ------
962 *  win - xid to add
963 *
964 *  Outputs:
965 *  ------
966 *
967 *  Comments:
968 *  --------
969 *
970 *************************************<->***********************************/
971#ifdef _NO_PROTO
972static void
973wmq_add_xid (win)
974    XID win;
975#else /* _NO_PROTO */
976static void
977wmq_add_xid (
978    XID win
979    )
980#endif /* _NO_PROTO */
981{
982    if (curXids >= numXids)
983    {
984        wmq_bump_xids();
985    }
986
987    if (curXids < numXids)
988    {
989        pXids[curXids++] = win;
990    }
991
992} /* END OF FUNCTION wmq_add_xid */
993
994
995
996/*************************************<->*************************************
997 *
998 *  void wmq_lose (w, pSelection)
999 *
1000 *
1001 *  Description:
1002 *  -----------
1003 *  This function is called when we lose the WM_QUERY selection
1004 *
1005 *  Inputs:
1006 *  ------
1007 *  w - widget
1008 *  pSelection - pointer to selection type (atom)
1009 *
1010 *  Outputs:
1011 *  ------
1012 *
1013 *  Comments:
1014 *  --------
1015 *  This shouldn't happen!
1016 *
1017 *************************************<->***********************************/
1018#ifdef _NO_PROTO
1019static void
1020wmq_lose (w, pSelection)
1021    Widget w;
1022    Atom *pSelection;
1023#else /* _NO_PROTO */
1024static void
1025wmq_lose (
1026    Widget w,
1027    Atom *pSelection
1028    )
1029#endif /* _NO_PROTO */
1030{
1031    Warning ("Lost _MOTIF_WM_QUERY_nn selection");
1032} /* END OF FUNCTION wmq_lose */
1033
1034
1035
1036/*************************************<->*************************************
1037 *
1038 *  void wmq_done (w, pSelection, pTarget)
1039 *
1040 *
1041 *  Description:
1042 *  -----------
1043 *  This function is called when selection conversion is done.
1044 *
1045 *  Inputs:
1046 *  ------
1047 *  w - widget
1048 *  pSelection - pointer to selection type (atom)
1049 *  pTarget - pointer to requested target type (atom)
1050 *
1051 *  Outputs:
1052 *  ------
1053 *
1054 *  Comments:
1055 *  --------
1056 *  This is here to prevent Xt from freeing our buffers.
1057 *
1058 *************************************<->***********************************/
1059#ifdef _NO_PROTO
1060static void
1061wmq_done (w, pSelection, pTarget)
1062    Widget w;
1063    Atom *pSelection;
1064    Atom *pTarget;
1065#else /* _NO_PROTO */
1066static void
1067wmq_done (
1068    Widget w,
1069    Atom *pSelection,
1070    Atom *pTarget
1071    )
1072#endif /* _NO_PROTO */
1073{
1074} /* END OF FUNCTION wmq_done */
1075
1076
1077
1078/*************************************<->*************************************
1079 *
1080 *  static void wmq_bump_xids ()
1081 *
1082 *
1083 *  Description:
1084 *  -----------
1085 *  This function allocates more xids in our local buffer
1086 *
1087 *  Inputs:
1088 *  ------
1089 *  w - widget
1090 *  pSelection - pointer to selection type (atom)
1091 *  pTarget - pointer to requested target type (atom)
1092 *
1093 *  Outputs:
1094 *  ------
1095 *
1096 *  Comments:
1097 *  --------
1098 *  This is here to prevent Xt from freeing our buffers.
1099 *
1100 *************************************<->***********************************/
1101#ifdef _NO_PROTO
1102static void
1103wmq_bump_xids ()
1104#else /* _NO_PROTO */
1105static void
1106wmq_bump_xids ( void )
1107#endif /* _NO_PROTO */
1108{
1109    XID *px;
1110
1111    if (pXids)
1112    {
1113        if (!(px = (XID *)
1114          XtRealloc ((char *) pXids, (numXids + 32) * (sizeof (XID)))))
1115        {
1116            Warning ("Insufficient memory to convert _MOTIF_WM_QUERY_nn selection");
1117        }
1118        else
1119        {
1120            pXids = px;
1121            numXids += 32;
1122        }
1123    }
1124    else
1125    {
1126        if (!(pXids = (XID *)
1127          XtMalloc (32 * (sizeof (XID)))))
1128        {
1129            Warning ("Insufficient memory to convert _MOTIF_WM_QUERY_nn selection");
1130        }
1131        else
1132        {
1133            numXids = 32;
1134        }
1135    }
1136}
1137
1138#endif /* NO_WMQUERY */
Note: See TracBrowser for help on using the repository browser.