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 * $TOG: ServiceMgrX.C /main/12 1997/06/18 17:32:19 samborn $
26 * Copyright (c) 1992 HaL Computer Systems, Inc. All rights reserved.
27 * UNPUBLISHED -- rights reserved under the Copyright Laws of the United
28 * States. Use of a copyright notice is precautionary only and does not
29 * imply publication or disclosure.
31 * This software contains confidential information and trade secrets of HaL
32 * Computer Systems, Inc. Use, disclosure, or reproduction is prohibited
33 * without the prior express written permission of HaL Computer Systems, Inc.
35 * RESTRICTED RIGHTS LEGEND
36 * Use, duplication, or disclosure by the Government is subject to
37 * restrictions as set forth in subparagraph (c)(l)(ii) of the Rights in
38 * Technical Data and Computer Software clause at DFARS 252.227-7013.
39 * HaL Computer Systems, Inc.
40 * 1315 Dell Avenue, Campbell, CA 95008
50 #define C_ClientEventMgr
54 #define C_WindowSystem
59 #include "Managers/CatMgr.hh"
60 #include "Registration.hh"
64 #include "external-api/olias.h"
65 #include "utility/mmdb_exception.h"
67 LONG_LIVED_CC(ServiceMgr,service_manager)
69 #define OLIAS_PROTOCOL_VERSION 1
71 #define OLIAS_WINDOW_ID_ATOM "__OLIAS_WINDOW_ID"
72 #define OLIAS_EVENT_ATOM "__OLIAS_EVENT"
73 #define OLIAS_REPLY_ATOM "__OLIAS_REPLY"
75 Atom _XA_OLIAS_WINDOW_ID;
79 extern bool g_scroll_to_locator;
80 extern char g_top_locator[];
82 // /////////////////////////////////////////////////////////////////
84 // /////////////////////////////////////////////////////////////////
86 ServiceMgr::ServiceMgr()
89 // We need to wait for the window to be mapped before doing anything
90 XtAddEventHandler (window_system().toplevel(), StructureNotifyMask, False,
91 (XtEventHandler) handle_toplevel_mapped, this);
96 // /////////////////////////////////////////////////////////////////
98 // /////////////////////////////////////////////////////////////////
100 ServiceMgr::~ServiceMgr()
102 // Need to stop being the OLIAS server if it's us.
104 // XGrabServer (window_system().display());
106 Window current_server =
107 XGetSelectionOwner (window_system().display(), _XA_OLIAS_WINDOW_ID);
109 ON_DEBUG(printf ("Current OLIAS server is window 0x%lx\n", current_server));
110 if (current_server == XtWindow (window_system().toplevel()))
112 ON_DEBUG(printf ("Done being the OLIAS server...\n"));
113 ON_DEBUG(fflush (stdout));
115 // OK to use CurrentTime because there is no chance of contention.
116 XSetSelectionOwner (window_system().display(), _XA_OLIAS_WINDOW_ID,
120 // XUngrabServer (window_system().display());
123 // /////////////////////////////////////////////////////////////////
125 // /////////////////////////////////////////////////////////////////
128 ServiceMgr::create_atoms()
130 static Boolean created = False;
134 enum { XA_OLIAS_WINDOW_ID_ATOM, XA_OLIAS_EVENT_ATOM,
135 XA_OLIAS_REPLY_ATOM, NUM_ATOMS };
136 static const char *atom_names[] = { OLIAS_WINDOW_ID_ATOM,
137 OLIAS_EVENT_ATOM, OLIAS_REPLY_ATOM };
139 Atom atoms[XtNumber(atom_names)];
141 XInternAtoms (window_system().display(), (char**)atom_names,
142 XtNumber((char**)atom_names), False, atoms);
144 _XA_OLIAS_WINDOW_ID = atoms[XA_OLIAS_WINDOW_ID_ATOM];
145 _XA_OLIAS_EVENT = atoms[XA_OLIAS_EVENT_ATOM];
146 _XA_OLIAS_REPLY = atoms[XA_OLIAS_REPLY_ATOM];
152 // /////////////////////////////////////////////////////////////////
153 // establish_server - see if there's a server, become one if not
154 // /////////////////////////////////////////////////////////////////
157 ServiceMgr::establish_server()
161 // Operations in this routine must be atomic to avoid race conditions,
162 // hence the server grab.
164 XGrabServer (window_system().display());
166 Window current_server =
167 XGetSelectionOwner (window_system().display(), _XA_OLIAS_WINDOW_ID);
169 ON_DEBUG(printf ("Current OLIAS server is window 0x%lx\n", current_server));
171 // If no current server, we'll become the server.
172 if (current_server == None)
174 ON_DEBUG(printf ("Attempting to become OLIAS server..."));
175 ON_DEBUG(fflush (stdout));
176 current_server = XtWindow (window_system().toplevel());
178 // OK to use CurrentTime because there is no chance of contention.
179 XSetSelectionOwner (window_system().display(), _XA_OLIAS_WINDOW_ID,
180 current_server, CurrentTime);
182 // Make sure it worked.
183 current_server = XGetSelectionOwner (window_system().display(),
184 _XA_OLIAS_WINDOW_ID);
186 if (current_server == XtWindow (window_system().toplevel()))
188 client_event_manager().register_handler(this, window_system().toplevel());
189 ON_DEBUG(puts ("successful!"));
193 ON_DEBUG(puts ("failed!"));
197 XUngrabServer (window_system().display());
200 // /////////////////////////////////////////////////////////////////
202 // /////////////////////////////////////////////////////////////////
205 ServiceMgr::get_olias_event (XEvent *event)
207 // Make sure it's the right event first.
208 if (event->type != ClientMessage ||
209 event->xclient.message_type != _XA_OLIAS_EVENT)
212 Atom selection = event->xclient.data.l[2];
213 Time time = event->xclient.data.l[3];
215 /* -------- Ask for the client the event from the client. -------- */
216 ON_DEBUG(puts ("OLIAS: Received a client display event!"));
218 XtGetSelectionValue (window_system().toplevel(), selection,
220 (XtSelectionCallbackProc) receive_olias_event,
225 // /////////////////////////////////////////////////////////////////
226 // handle_event - dispatch handle application request
227 // /////////////////////////////////////////////////////////////////
230 ServiceMgr::handle_event(Widget, XEvent *event, Boolean *)
232 get_olias_event(event);
235 // /////////////////////////////////////////////////////////////////
236 // process_olias_event
237 // /////////////////////////////////////////////////////////////////
240 ServiceMgr::process_olias_event (Window client,
241 unsigned char *stream, unsigned long)
243 /* Return immediately if the selection couldn't be converted. */
247 unsigned char event_type = *stream++;
249 char *locator; // NOTE: make fixed width and add "mmdb:" to
250 // front ? Should eventually go into calling
251 // program to determine doc type.
255 ON_DEBUG(fprintf (stderr, "received unknown event"));
259 // Skip over the defunct infobase name.
260 // NOTE: It should be removed from the olias api. DJB
261 infobase = (char *) stream;
262 while (*stream != '\0')
265 locator = (char *) stream;
267 UAS_Pointer<UAS_Common> d;
270 if (strchr (locator, ':'))
272 d = UAS_Common::create(locator);
276 char *buffer = new char[strlen("mmdb:LOCATOR=") + strlen(locator) + 1];
277 sprintf (buffer, "mmdb:LOCATOR=%s", locator);
278 d = UAS_Common::create (buffer);
279 if (d != (const int)NULL)
282 g_scroll_to_locator = TRUE;
283 strcpy (g_top_locator, locator);
288 mcatch (demoException&, demo)
290 message_mgr().demo_failure(demo);
298 if (d != (const int)NULL)
301 reply_to_client(client, OLIAS_SUCCESS);
305 reply_to_client(client, OLIAS_LOCATOR_NOT_FOUND);
306 ON_DEBUG(cerr << "Document not found." << endl);
311 // /////////////////////////////////////////////////////////////////
312 // receive_olias_event
313 // /////////////////////////////////////////////////////////////////
316 ServiceMgr::receive_olias_event (Widget, XtPointer client_data,
317 Atom *selection, Atom * /* type */,
318 XtPointer value, unsigned long *length,
321 // NOTE: probably should verify type (olias_event_atom) and format
323 XGetSelectionOwner (window_system().display(),*selection);
324 ((ServiceMgr *) client_data)->
325 process_olias_event (client, (unsigned char *) value, *length);
329 // /////////////////////////////////////////////////////////////////
331 // /////////////////////////////////////////////////////////////////
334 ServiceMgr::reply_to_client (Window client, OliasStatus reply_code)
336 static XClientMessageEvent client_event;
339 // Before we send a reply, we must determine if the client window
340 // is an existing (valid) window. This is done below by searching
341 // for it's window ID in the list of immediate children of the root
342 // window. If the client window is no longer valid then we don't
343 // send a reply. This method seems overly complex to me but after
344 // consulting with our X gurus I determined that this is the best
345 // (only?) way to accomplish this. This code fixes defect ID 16933.
348 // a better way might be to do an XSynch, install an error handler
349 // try a X Command to see if an error is generated, do another,
350 // XSynch, then restore the original Xlib error handler
352 Window root, parent, *children;
353 unsigned int i, nchildren;
354 Boolean client_exists = False;
356 // Query root window for all of its immediate children.
357 if (XQueryTree(window_system().display(),
358 DefaultRootWindow(window_system().display()),
359 &root, &parent, &children, &nchildren)) {
360 // Search for the client window ID in root's list of children.
361 // Assumption: Window was created as a toplevel widget within
362 // external API client.
363 for (i = 0; i < nchildren; i++) {
364 if (children[i] == client) {
365 client_exists = True;
369 // Free up the children array.
373 // If not a valid window then punt sending the reply message
374 if (client == None || !client_exists)
377 client_event.window = client;
378 client_event.type = ClientMessage;
379 client_event.message_type = _XA_OLIAS_REPLY;
380 client_event.format = 32;
381 client_event.data.l[0] = OLIAS_PROTOCOL_VERSION;
382 client_event.data.l[1] = reply_code;
384 ON_DEBUG(printf ("sending reply to 0x%lx\n", client));
386 XSendEvent (window_system().display(), client, False,
387 0L, (XEvent *) &client_event);
388 XFlush (window_system().display());
392 // /////////////////////////////////////////////////////////////////
393 // olias_send_event - internal version for olias-to-olias comm
394 // /////////////////////////////////////////////////////////////////
397 olias_send_event (Widget, OliasEvent *event)
401 UAS_Pointer<UAS_Common> d;
405 case OLIAS_NOOP_EVENT:
408 case OLIAS_DISPLAY_EVENT:
409 locator = ((OliasDisplayEvent *) event)->locator;
410 ON_DEBUG (printf (">>> external-api display <%s>\n", locator));
413 if (strchr (locator, ':'))
415 d = UAS_Common::create (locator);
419 buffer = new char[strlen("mmdb:LOCATOR=") + strlen(locator) + 1];
420 sprintf (buffer, "mmdb:LOCATOR=%s", locator);
421 d = UAS_Common::create (buffer);
423 if (d != (const int)NULL)
427 return (OLIAS_TIMEOUT);
428 ON_DEBUG (printf (">>> g_top_locator = %p\n", g_top_locator));
429 if (g_top_locator == NULL)
430 return (OLIAS_TIMEOUT);
431 g_scroll_to_locator = TRUE;
432 strcpy (g_top_locator, locator);
436 mcatch (demoException&, demo)
438 message_mgr().demo_failure(demo);
445 if (d != (const int)NULL)
448 return (OLIAS_SUCCESS);
452 message_mgr().info_dialog (
453 (char*)UAS_String(CATGETS(Set_Messages, 46, "File a Bug")));
454 return (OLIAS_SUCCESS);
455 // return (OLIAS_LOCATOR_NOT_FOUND); until help lib fixed
460 return (OLIAS_TIMEOUT);