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