2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
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. *
30 *******************************************************************************
32 * File: ChkpntClient.c
33 * Description: CDE client-side checkpoint protocol functions. Private API
34 * functions for use by the CDE client program.
35 * Created: Mon Sep 6 09:00:00 1993
38 * $TOG: ChkpntClient.c /main/7 1998/04/09 17:49:06 mgreess $
40 * (C) Copyright 1993, Hewlett-Packard, all rights reserved.
42 *******************************************************************************
45 #define NUMPROPERTIES 8
46 #define INVALID_TIME ((Time) -1)
52 #include "Dt/ChkpntP.h"
53 #include "DtSvcLock.h"
56 Display *display; /* Display pointer */
57 Window window; /* Window id for the program */
58 char *pname; /* Actual name of the program */
59 Atom aSelection; /* Atom for root selection */
60 Atom *aProperty; /* Atom array for window props */
61 int maxprops; /* Size of above array */
62 Atom aChkpntMsg; /* Atom for Checkpoint message */
63 Boolean bChkpnt; /* Should I do checkpointing ? */
64 } dtcp_info; /* Data structure for this client*/
65 static DtChkpntMsg dtcp_msg; /* Message structure union */
68 * myCheckClientEvent --- Helper Boolean function to pass to XCheckIfEvent()
69 * Checks for PropertyNotify & SelectionNotify events in the event queue.
71 static Bool myCheckClientEvent(Display *display, XEvent *event, char *args)
75 /* Only check the client window events */
77 onMyWindow = (event->xany.window == dtcp_info.window);
78 _DtSvcProcessUnlock();
98 * myDtChkpntMsgSend --- Helper function: Send a checkpoint message to the listener
100 static myDtChkpntMsgSend(char *message, char *type)
102 static long msgcount = 0; /* Running count of messages */
103 static int propnum = 0; /* Which property are we using ? */
104 static Time oldtime = INVALID_TIME; /* Recycled from old PropertyNotify events */
105 Time timestamp= INVALID_TIME;
106 char buf_msgcount[32];
107 char buf_seconds[128];
108 struct timeval time_val;
109 struct timezone time_zone;
115 /* Check to see if checkpoint is actually on */
117 if (dtcp_info.bChkpnt == False) {
118 _DtSvcProcessUnlock();
122 /* Fill the message list. ("pname" and "window" were filled at init) */
123 dtcp_msg.record.type = type;
124 sprintf(buf_msgcount, "%ld", msgcount);
125 dtcp_msg.record.count = buf_msgcount; /* Running message count */
126 gettimeofday(&time_val, &time_zone);
127 sprintf(buf_seconds,"%lf",time_val.tv_sec + (time_val.tv_usec/1000000.0 ));
128 dtcp_msg.record.seconds = buf_seconds; /* Info from gettimeofday()*/
129 dtcp_msg.record.message = message; /* Actual message string */
132 * We maintain a list of properties and use them round robin -- hoping to
134 * The listener should then track the message count to see if messages are
138 /* Fill the window property with necessary information */
139 status = XStringListToTextProperty(dtcp_msg.array,DT_PERF_CHKPNT_MSG_SIZE, &tp);
141 /* Hang the property on the window */
142 if ( !( (status == Success) || (status > 0) )) {
143 _DtSvcProcessUnlock();
147 XSetTextProperty(dtcp_info.display, dtcp_info.window,
148 &tp, dtcp_info.aProperty[propnum]);
151 if (oldtime != INVALID_TIME) { /* Valid timestamp to be recycled */
154 else { /* Check event queue */
155 bool = XCheckIfEvent(dtcp_info.display, &event,
156 myCheckClientEvent, NULL);
158 if (event.type == PropertyNotify)
159 timestamp = event.xproperty.time;
160 else timestamp = event.xselection.time;
162 else { /* Synthesize time by generating a PropertyNotify */
163 XChangeProperty(dtcp_info.display, dtcp_info.window,
164 dtcp_info.aProperty[propnum], XA_STRING,
166 (unsigned char *) NULL, 0);
167 XFlush(dtcp_info.display);
169 XWindowEvent(dtcp_info.display, dtcp_info.window,
170 PropertyChangeMask, &event);
171 if (event.type == PropertyNotify) {
172 timestamp = event.xproperty.time;
178 * Send the checkpoint message: do a ConvertSelection()
181 /* Note: Currently listener makes no use of the "aChkpntMsg" info */
182 XConvertSelection(dtcp_info.display,dtcp_info.aSelection,
183 dtcp_info.aChkpntMsg, dtcp_info.aProperty[propnum],
184 dtcp_info.window, timestamp);
185 XFlush(dtcp_info.display);
188 * Toss SelectionNotify and PropertyNotify events from the event queue
190 oldtime = INVALID_TIME;
192 bool = XCheckIfEvent(dtcp_info.display, &event,
193 myCheckClientEvent, NULL);
194 if (event.type == PropertyNotify) /* Save timestamp for recycling */
195 oldtime = event.xproperty.time;
196 else oldtime = event.xselection.time;
197 } while(bool == True);
200 * Increment the property and message counters
202 if (++propnum >= dtcp_info.maxprops)
206 _DtSvcProcessUnlock();
211 * _DtPerfChkpntInit --- Initialize the checkpointing mechanism
213 _DtPerfChkpntInit(Display *display,
218 static char winstring[32]; /* Storage for window id */
220 char propname[80]; /* Temp buffer for property name */
225 * Fill the dtcp_info structure
228 dtcp_info.display = display;
229 dtcp_info.pname = prog_name;
230 dtcp_info.bChkpnt = bChkpnt;
231 dtcp_info.aChkpntMsg = XA_STRING;
233 /* Pre-compute Atom names and save them away in the dtcp_info structure */
234 dtcp_info.aSelection = XInternAtom(dtcp_info.display,
235 DT_PERF_CHKPNT_SEL, False);
236 dtcp_info.maxprops = NUMPROPERTIES;
237 dtcp_info.aProperty = (Atom *) malloc(dtcp_info.maxprops * sizeof(Atom));
238 for (i= 0; i < dtcp_info.maxprops; i++) {
239 sprintf(propname, "%s_%x", DT_PERF_CLIENT_CHKPNT_PROP, i);
240 dtcp_info.aProperty[i] = XInternAtom(dtcp_info.display,
245 * Check to see if listener is available
247 tmpwin = XGetSelectionOwner(dtcp_info.display, dtcp_info.aSelection);
248 if (tmpwin == None) { /* No listener */
249 dtcp_info.bChkpnt = False;
250 _DtSvcProcessUnlock();
255 * Create a permanent window for hanging messages on
257 tmpdisplay = display;
258 tmpdisplay = XOpenDisplay(""); /* Temporary display connection */
259 XSetCloseDownMode(tmpdisplay, RetainPermanent);
260 dtcp_info.window = XCreateSimpleWindow(tmpdisplay, parentwin,
262 BlackPixel(display,DefaultScreen(display)),
263 WhitePixel(display,DefaultScreen(display)));
264 { /* Hang a name on the permanent window => helps debugging */
267 XTextProperty text_prop;
269 buffer = malloc(strlen(prog_name) + 8);
270 sprintf(buffer, "DtPerf %s", prog_name);
273 XStringListToTextProperty(array, 1, &text_prop);
274 XSetWMName(tmpdisplay, dtcp_info.window, &text_prop);
275 XFree(text_prop.value);
276 if (buffer) free(buffer);
279 XCloseDisplay(tmpdisplay);
282 * Pre-fill the message structure entries for "pname" and "window"
284 dtcp_msg.record.pname = prog_name;
285 sprintf(winstring, "%lx", (long) dtcp_info.window);
286 dtcp_msg.record.window = winstring;
289 * Express interest in Property change events
291 XSelectInput(dtcp_info.display, dtcp_info.window, PropertyChangeMask);
293 /* Inform listener that you are ready to send messages */
294 myDtChkpntMsgSend("Begin checkpoint delivery", DT_PERF_CHKPNT_MSG_INIT);
295 _DtSvcProcessUnlock();
297 } /* DtChkpntInit() */
301 * _DtPerfChkpntMsgSend --- Send a checkpoint message to the listener
303 _DtPerfChkpntMsgSend(char *message)
305 myDtChkpntMsgSend(message, DT_PERF_CHKPNT_MSG_CHKPNT);
309 * myDtPerfChkpntEnd --- End the checkpointing message delivery
313 myDtChkpntMsgSend("End checkpoint delivery", DT_PERF_CHKPNT_MSG_END);