1 /* $XConsortium: recv.c /main/5 1995/07/15 20:38:46 drk $ */
2 /*
3 * Motif
4 *
5 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
6 *
7 * These libraries and programs are free software; you can
8 * redistribute them and/or modify them under the terms of the GNU
9 * Lesser General Public License as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * These libraries and programs are distributed in the hope that
14 * they will be useful, but WITHOUT ANY WARRANTY; without even the
15 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 * PURPOSE. See the GNU Lesser General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with these librararies and programs; if not, write
21 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
22 * Floor, Boston, MA 02110-1301 USA
23 *
24 */
25 /*
26 * HISTORY
27 */
28
29 #include "wsm_proto.h"
30 #include "utm_send.h"
31 #include <X11/Xatom.h>
32 #include <Xm/TransferP.h> /* for XmeNamedSource() */
33
34 #ifdef JUNK
35 static Boolean ConvertProc(
36 Widget, Atom *, Atom *, XtPointer, unsigned long, int, Atom *,
37 XtPointer *, unsigned long *, int *
38 );
39 #endif /* JUNK */
40
41 extern Time GetTimestamp (Display *dpy);
42
43
44 /* Function Name: WSMDefaultOwnSelection
45 * Description: This is the default routine that owns the proper
46 * selection and the processes incomming messages
47 * from the Wsm protocol.
48 * Arguments: w - A widget on the screen we want to own the
49 * WSM or WM selection for.
50 * NOTE: THIS MUST HAVE A XmNconvertCallback RESOURCE!
51 * client_type - The type of client we are.
52 * request_callback - The callback call when a message
53 * is received.
54 * request_data - Data passed to the request callback.
55 * Returns: True if no one currently owns the selection and I have
56 * taken ownership.
57 *
58 * NOTE: The reply that is filled in by the application programmer is
59 * passed to FreeReply, so that memory may be freed. If you
60 * want to take advantage of this, check wsm_proto.h or free.c
61 * to see what is freed for each type of protocol request, and
62 * then set the reply->any.allocated field to True to activate
63 * automatic memory freeing.
64 */
65
66 Boolean
WSMDefaultOwnSelection(Widget w,WSMClientType client_type,WSMRequestCallbackFunc request_callback,XtPointer request_data)67 WSMDefaultOwnSelection(Widget w, WSMClientType client_type,
68 WSMRequestCallbackFunc request_callback,
69 XtPointer request_data)
70 {
71 Time time;
72 Display *dpy = XtDisplay(w);
73 Atom own_selection =
74 _WSMGetSelectionAtom(dpy,
75 XScreenNumberOfScreen(XtScreen(w)), client_type);
76
77 if (XGetSelectionOwner(dpy, own_selection) != None) {
78 /*
79 * Someone out there already owns this selection, we should give
80 * up and return.
81 */
82
83 fprintf(stderr,"Error - Someone out there already owns this selection.\n");
84
85 return(False);
86 }
87
88 if (!XtIsRealized(w)) {
89 fprintf(stderr, "%s must be realized, and is not.\n",
90 "Programmer Error: Widget passed to WSMDefaultOwnSelection");
91 return(False);
92 }
93
94 WSMRegisterRequestCallback(XtDisplay(w),
95 XScreenNumberOfScreen(XtScreen(w)),
96 request_callback, request_data);
97
98 /*
99 * NOTE - w MUST have its XmNconvertCallback set properly,
100 * otherwise, no conversions will be handled!
101 */
102 time = GetTimestamp(XtDisplay(w)); /* CurrentTime or Zero is a no-no!*/
103 XmeNamedSource(w, own_selection, time);
104
105 return(True);
106 }
107
108 /* Function Name: WSMRegisterRequestCallback
109 * Description: Registers the callback that will be called when
110 * a request comes in on the WSM protocol.
111 * Arguments: disp - The display.
112 * scr_num - The Screen number.
113 * callback, data - The proc to register and the data
114 * to send to it.
115 * Returns: none.
116 *
117 * NOTE: The reply that is filled in by the application programmer is
118 * passed to FreeReply, so that memory may be freed. If you
119 * want to take advantage of this, check wsm_proto.h or free.c
120 * to see what is freed for each type of protocol request, and
121 * then set the reply->any.allocated field to True to activate
122 * automatic memory freeing.
123 */
124
125 void
WSMRegisterRequestCallback(Display * disp,int scr_num,WSMRequestCallbackFunc callback,XtPointer data)126 WSMRegisterRequestCallback(Display *disp, int scr_num,
127 WSMRequestCallbackFunc callback, XtPointer data)
128 {
129 WSMScreenInfo *scr_info;
130
131 scr_info = _WSMGetScreenInfo(disp, scr_num);
132
133 /*
134 * Since only one client can own a particular selection, we can hang
135 * this data off of the screen data structure. This is necessary because
136 * No data is passed to the ConvertProc by Xm or Xt.
137 *
138 * NOTE: We do not need to have room for one callback for the WSM and
139 * one for the WM, since any given client will be one or the other,
140 * not both.
141 */
142
143 scr_info->request_callback = callback;
144 scr_info->request_data = data;
145 }
146
147
148 /* Function Name: WSMIsKnownTarget
149 * Description: Returns True if this target is part of the WSM protocol.
150 * Arguments: w - Any widget on the screen of the client
151 * we are talking to.
152 * target - the target to check if part of the protocol.
153 * Returns: True if this target is part of the WSM protocol.
154 *
155 * NOTE: This could be extended to know about extensions.
156 */
157
158 Boolean
WSMIsKnownTarget(Widget w,Atom target)159 WSMIsKnownTarget(Widget w, Atom target)
160 {
161 WSMDispInfo * disp_info = _WSMGetDispInfo(XtDisplay(w));
162
163 /*
164 * Can't switch on dynamic data, sigh...
165 */
166
167 if (disp_info->connect == target)
168 return(True);
169 if (disp_info->extensions == target)
170 return(True);
171 if (disp_info->config_fmt == target)
172 return(True);
173 if (disp_info->get_state == target)
174 return(True);
175 if (disp_info->set_state == target)
176 return(True);
177 if (disp_info->reg_window == target)
178 return(True);
179 if (disp_info->get_background == target)
180 return(True);
181 if (disp_info->set_background == target)
182 return(True);
183 if (disp_info->wm_windows == target)
184 return(True);
185 if (disp_info->wm_focus == target)
186 return(True);
187 if (disp_info->wm_pointer == target)
188 return(True);
189
190 return(False);
191 }
192
193 /* Function Name: WSMGetTargetList
194 * Description: Returns the list of targets understood by the WSM
195 * protocol.
196 * Arguments: w - Any widget on the same screen as the client we
197 * are talking to.
198 * include_defaults - Whether or not to include the
199 * targets TIMESTAMP, MULTIPLE, and TARGETS.
200 * in the returned list.
201 * RETURNED len_ret - The number of atoms returned.
202 * Returns: The targets atom list. This list has been allocated with
203 * XtMalloc, and must be free'd by the caller.
204 */
205
206 Atom *
WSMGetTargetList(Widget w,Boolean include_defaults,unsigned long * len_ret)207 WSMGetTargetList(Widget w, Boolean include_defaults, unsigned long *len_ret)
208 {
209 WSMDispInfo *disp_info = _WSMGetDispInfo(XtDisplay(w));
210 register int i;
211 Atom *list;
212
213 *len_ret = NUM_WSM_TARGETS;
214 if (include_defaults)
215 *len_ret += NUM_EXTRA_TARGETS;
216
217 list = (Atom *) XtMalloc(sizeof(Atom) * (*len_ret));
218
219 i = 0;
220 list[i++] = disp_info->connect;
221 list[i++] = disp_info->extensions;
222 list[i++] = disp_info->config_fmt;
223 list[i++] = disp_info->get_state;
224 list[i++] = disp_info->set_state;
225 list[i++] = disp_info->reg_window;
226 list[i++] = disp_info->get_background;
227 list[i++] = disp_info->set_background;
228 list[i++] = disp_info->wm_windows;
229 list[i++] = disp_info->wm_focus;
230 list[i++] = disp_info->wm_pointer;
231 if (include_defaults) {
232 list[i++] = disp_info->targets;
233 list[i++] = disp_info->multiple;
234 list[i++] = disp_info->timestamp;
235 }
236
237 return(list);
238 }
239
240 /* Function Name: WSMProcessProtoTarget
241 * Description: Unpacks the data sent across to us that matches the
242 * target, then calls the request_callback proceedure.
243 * Arguments: w - Any widget that is on the same screen as the
244 * client that we are talking to.
245 * target - The target that defines which request this is.
246 * input, input_len, input_fmt - The input data.
247 * return_type - This is always set to the target IFF we
248 * know how to process this request.
249 * output, output_len, output_fmt - The data to send back
250 * to the requester.
251 * Returns: True if we know how to process this message and there
252 * are no errors
253 */
254
255 Boolean
WSMProcessProtoTarget(Widget w,Atom target,XtPointer input,unsigned long input_len,int input_fmt,Atom * return_type,XtPointer * output,unsigned long * output_len,int * output_fmt)256 WSMProcessProtoTarget(Widget w, Atom target, XtPointer input,
257 unsigned long input_len, int input_fmt,
258 Atom *return_type, XtPointer *output,
259 unsigned long *output_len, int *output_fmt)
260 {
261 Display *dpy;
262 int scr_num;
263 WSMScreenInfo *screen_info;
264 WSMRequest request;
265 WSMReply reply;
266
267 /*
268 * Check the Target to make sure it is valid.
269 * Check the format to make sure it is WSM_PROTO_FMT.
270 */
271
272 if (!WSMIsKnownTarget(w, target))
273 return(False);
274
275 if (input_fmt != WSM_PROTO_FMT) {
276 fprintf(stderr, "Format of the request must be %d\n", WSM_PROTO_FMT);
277 return(False);
278 }
279
280 dpy = XtDisplay(w);
281 scr_num = XScreenNumberOfScreen(XtScreen(w));
282
283 /*
284 * Unpack up the request from the wire.
285 */
286
287 _WSMUnpackRequest(dpy, scr_num, (MessageData) input, input_len,
288 _WSMTargetToReqType(dpy, target), &request);
289
290 /*
291 * Call the app's callback function to process the request.
292 */
293
294 screen_info = _WSMGetScreenInfo(dpy, scr_num);
295 reply.any.type = request.any.type;
296 reply.any.allocated = False;
297 (*screen_info->request_callback)(w, screen_info->request_data,
298 &request, &reply);
299 /*
300 * Pack up the reply and send it back.
301 */
302
303 *output = (XtPointer) _WSMPackReply(dpy, scr_num, &reply, output_len);
304 *output_fmt = WSM_PROTO_FMT;
305 *return_type = target; /* Is this the right return type? */
306
307 FreeRequest(&request);
308 FreeReply(&reply);
309
310 return(TRUE);
311 }
312
313 /************************************************************
314 *
315 * Internal routines.
316 *
317 ************************************************************/
318
319
320 #ifdef JUNK
321 /*================================================================*
322 | The following functions are used to handle selection/UTM |
323 | conversion requests that are received by the selection OWNER. |
324 *================================================================*/
325
326
327 /*----------------------------------------------------------------*
328 | UTMConvertProc |
329 | This is the UTM conversion proc called when a request comes in |
330 | for the selection owner. |
331 | |
332 | NOTE - This function MUST have been set up as the callback for |
333 | the utm widget's XmNconvertCallback procedure! |
334 | |
335 | Arguments: w - The widget making the request. |
336 | clientData - not used. |
337 | callData - the UTM convert callback structure. |
338 *----------------------------------------------------------------*/
339 static void
UTMConvertProc(Widget w,XtPointer clientData,XtPointer callData)340 UTMConvertProc(Widget w, XtPointer clientData, XtPointer callData)
341 {
342 int scr = XScreenNumberOfScreen(XtScreen(w));
343 XmConvertCallbackStruct *ccs = (XmConvertCallbackStruct *)callData;
344 Atom lose_sel = XInternAtom(XtDisplay(w), "_MOTIF_LOSE_SELECTION", False);
345 WSMScreenInfo *scrInfo = _WSMGetScreenInfo(XtDisplay(w), scr);
346
347 /*
348 * Check if the callback was invoked for the right reason.
349 * The reason field is not set to anything interresting by the transfer
350 * code, so check the selection.
351 */
352 if ((!ccs) || ((ccs->selection != scrInfo->wm_selection) &&
353 (ccs->selection != scrInfo->wsm_selection)))
354 return;
355
356 if (ccs->target == lose_sel)
357 {
358 /* Done with the conversion - free any data used. */
359 }
360
361 /*
362 * Handle a conversion request with parameter data.
363 */
364 else
365 {
366 ConvertProc (w, &(ccs->selection), &(ccs->target),
367 ccs->parm,
368 ccs->parm_length,
369 ccs->parm_format,
370 &(ccs->type),
371 &(ccs->value),
372 &(ccs->length),
373 &(ccs->format));
374 }
375 }
376
377
378
379 /* Function Name: ConvertProc
380 * Description: This is the conversion proc. called when a request
381 * comes in that we need to process.
382 * Arguments: w - The widget that owns the selection?
383 * selection - The selection to be converted.
384 * target - The target to convert.
385 * return_type - The type of the return stream.
386 * output - The output data stream.
387 * output_len - The length of the output stream.
388 * output_fmt - The format of the output stream.
389 * Returns: True if we can convert the selection, False otherwise.
390 */
391
392 /*ARGSUSED*/
393 static Boolean
ConvertProc(Widget w,Atom * selection,Atom * target,XtPointer input,unsigned long input_len,int input_fmt,Atom * return_type,XtPointer * output,unsigned long * output_len,int * output_fmt)394 ConvertProc(Widget w, Atom *selection, Atom *target,
395 XtPointer input, unsigned long input_len, int input_fmt,
396 Atom *return_type, XtPointer *output, unsigned long *output_len,
397 int *output_fmt)
398 {
399 WSMDispInfo *disp_info;
400
401 /* set up some defaults. selection code doesn't like garbage! */
402 *output = NULL;
403 *output_len = 0;
404 *output_fmt = 8;
405
406 disp_info = _WSMGetDispInfo(XtDisplay(w));
407
408 /*
409 * Since this function is only registered for one selection, I am going
410 * to assume that the intrinsics didn't give me the wrong thing.
411 */
412
413 if (*target == disp_info->targets) {
414 *return_type = XA_STRING;
415 *output = (XtPointer) WSMGetTargetList(w, TRUE, output_len);
416 *output_fmt = 32;
417 return(True);
418 }
419 /*
420 * Intrinsics will handle MULTIPLE and TIMESTAMP for me.
421 */
422
423 if (WSMProcessProtoTarget(w, *target, input, input_len, input_fmt,
424 return_type, output, output_len, output_fmt))
425 {
426 return(TRUE);
427 }
428
429 return(False); /* unknown type, returning... */
430 }
431 #endif /*JUNK*/
432