Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / DtSvc / DtUtil2 / ChkpntListen.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 librararies 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 1993, 1994 Hewlett-Packard Company                     *
25  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
26  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
27  * (c) Copyright 1993, 1994 Novell, Inc.                                *
28  */
29 /* -*-C-*-
30 *******************************************************************************
31 *
32 * File:         ChkpntListen.c
33 * Description:  CDE listener-side checkpoint protocol functions. Internal API 
34 *               functions for use by the CDE checkpoint listener.
35 * Created:      Mon Sep  6 09:00:00 1993
36 * Language:     C
37 *
38 * $XConsortium: ChkpntListen.c /main/6 1996/08/28 15:14:40 drk $
39 *
40 * (C) Copyright 1993, Hewlett-Packard, all rights reserved.
41 *
42 *******************************************************************************
43 */
44
45 #define INVALID_TIME    ((Time) -1)
46
47 #include <stdio.h>
48 #include <string.h>
49 #include "Dt/ChkpntP.h"
50 #include "DtSvcLock.h"
51
52 static struct {
53     Display     *display;               /* Display pointer              */
54     Window      window;                 /* Window id for the program    */
55     Atom        aSelection;             /* Atom  for root selection     */
56     Boolean     bListen;                /* Should I do listening ?      */
57 } dtsvc_info;
58
59 /* _DtPerfChkpntListenInit(): Start the Checkpoint listener */
60 #ifdef _NOPROTO
61 _DtPerfChkpntListenInit(display, parentwin)
62 Display *display;       /* Current display */
63 Window  parentwin;      /* Parent of window associated with listener */
64 #else
65 _DtPerfChkpntListenInit(Display *display, Window parentwin)
66 #endif
67 {
68     Time   timestamp = INVALID_TIME;
69     Window tmpwin;
70     Bool   bsuccess = False;
71
72     _DtSvcProcessLock();
73     dtsvc_info.display    = display;
74     dtsvc_info.window     = XCreateSimpleWindow(display, parentwin,
75                               1, 1, 100, 100, 1,
76                               BlackPixel(display,DefaultScreen(display)),
77                               WhitePixel(display,DefaultScreen(display)));
78     dtsvc_info.bListen    = True;
79     /*
80      * Assert ownership over the appropriate root window selection
81      */
82     dtsvc_info.aSelection = XInternAtom(display, DT_PERF_CHKPNT_SEL, False);
83     if (XGetSelectionOwner(dtsvc_info.display, dtsvc_info.aSelection) == None) {
84         if (timestamp == INVALID_TIME) { /* Generate a valid timestamp */
85             XEvent event;
86             Atom aProperty;
87             char   propname[80];        /* Temp buffer for property name */
88
89             sprintf(propname, "%s_%x", DT_PERF_CLIENT_CHKPNT_PROP, 0);
90             aProperty  = XInternAtom(dtsvc_info.display, propname,False);
91             XSelectInput(dtsvc_info.display,
92                                     dtsvc_info.window, PropertyChangeMask);
93
94             XChangeProperty(dtsvc_info.display,  dtsvc_info.window,
95                                     aProperty, XA_STRING, 8,
96                                     PropModeAppend, (unsigned char *) NULL, 0);
97             XFlush(dtsvc_info.display);
98             loop:
99             XWindowEvent(dtsvc_info.display, dtsvc_info.window,
100                                     PropertyChangeMask,  &event);
101             if (event.type == PropertyNotify) {
102                 timestamp = event.xproperty.time;
103             }
104             else goto loop;
105         }
106         XSetSelectionOwner(dtsvc_info.display, dtsvc_info.aSelection,
107                            dtsvc_info.window,  timestamp);
108         tmpwin = XGetSelectionOwner(dtsvc_info.display, dtsvc_info.aSelection);
109         if ( tmpwin == dtsvc_info.window)
110                 bsuccess = True;/* We are now the listener! */
111     }
112
113     if (bsuccess == False) {
114         fprintf(stderr,
115           "\t** Chkpnt listener: Cannot gain ownership of root selection **\n");
116         fprintf(stderr,
117           "\t** Chkpnt listener: Selection is owned by window: %lx **\n",
118           (long) tmpwin);
119         dtsvc_info.bListen = False;
120         _DtSvcProcessUnlock();
121         return(0);
122     }
123
124     /* Express interests in Events on this window */
125     XSelectInput(dtsvc_info.display, dtsvc_info.window,
126                  SelectionRequest | SelectionClear);
127
128     _DtSvcProcessUnlock();
129     return(1);
130 }
131
132 /* Helper Boolean function to pass to XCheckIfEvent() */
133 static Bool myCheckSelectionEvent(Display *display, XEvent *event, char *args)
134 {
135     _DtSvcProcessLock();
136
137     if (event->xany.window != dtsvc_info.window) { /* Only listener window events*/
138         _DtSvcProcessUnlock();
139         return(False);
140     }
141     else switch(event->type) {                  /* Selection stuff ? */
142         case SelectionClear:
143         case SelectionRequest:
144             _DtSvcProcessUnlock();
145             return (True);
146             break;
147         default:
148             _DtSvcProcessUnlock();
149             return (False);
150             break;
151     }
152 }
153
154 /*
155  * _DtPerfChkpntMsgReceive() Non blocking fetch from message queue
156  */
157 Bool _DtPerfChkpntMsgReceive(DtChkpntMsg *dtcp_msg, Bool bBlock)
158 {
159     XEvent        event;
160     Bool          bool=True;
161     XTextProperty tp;
162     int           i;
163     static char   **Stringlist;
164     static int    numfields = 0;
165
166     _DtSvcProcessLock();
167     if (dtsvc_info.bListen == False) {
168         _DtSvcProcessUnlock();
169         return(False);
170     }
171
172     if (numfields) {    /* Free the storage from last time around */
173         XFreeStringList(Stringlist);
174         numfields = 0;
175     }
176
177     if (bBlock == True)
178         XIfEvent(dtsvc_info.display, &event, myCheckSelectionEvent, NULL);
179     else
180         bool = XCheckIfEvent(dtsvc_info.display, &event,
181                                 myCheckSelectionEvent, NULL);
182     
183     if (bool == True) {
184         switch (event.type) {
185             case SelectionRequest:      /* Message received from a client */
186                 /* Is this a Checkpoint request ?*/
187                 if (event.xselectionrequest.selection == dtsvc_info.aSelection){
188                     /* Correct selection, now fetch the property */
189                     /*
190                      * Note: Need to handle errors if the client is dead
191                      * and the property no longer exists.
192                      */
193                     XGetTextProperty(dtsvc_info.display,
194                                      event.xselectionrequest.requestor,
195                                      &tp,
196                                      event.xselectionrequest.property);
197                     XDeleteProperty (dtsvc_info.display, 
198                                      event.xselectionrequest.requestor,
199                                      event.xselectionrequest.property);
200                     XTextPropertyToStringList(&tp, &Stringlist, &numfields);
201                     XFree(tp.value);
202                     for (i = 0; i < DT_PERF_CHKPNT_MSG_SIZE; i++)
203                         dtcp_msg->array[i] = (Stringlist)[i];
204
205                     /* End? Destroy the, RetainPermanent client window */
206                     if (!strcmp(dtcp_msg->record.type, DT_PERF_CHKPNT_MSG_END))
207                         XDestroyWindow(dtsvc_info.display, 
208                                        event.xselectionrequest.requestor);
209                 }
210                 break;
211             /* */
212             case SelectionClear:        /* We no longer own the selection */
213             default:
214                 fprintf(stderr,"\t** Chkpnt listener: Warning - loss of Selection ownership **\n");
215                 bool = False;
216                 break;
217         }
218     }
219     _DtSvcProcessUnlock();
220     return(bool);
221 }