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 libraries 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 while (*stream != '\0')
264 locator = (char *) stream;
266 UAS_Pointer<UAS_Common> d;
269 if (strchr (locator, ':'))
271 d = UAS_Common::create(locator);
275 bufferlen = strlen("mmdb:LOCATOR=") + strlen(locator) + 1;
276 char *buffer = new char[bufferlen];
277 snprintf (buffer, bufferlen, "mmdb:LOCATOR=%s", locator);
278 d = UAS_Common::create (buffer);
279 if (d != (const int)0)
282 g_scroll_to_locator = TRUE;
283 len = MIN(strlen(locator), 4096 - 1);
284 *((char *) memcpy(g_top_locator, locator, len) + len) = '\0';
289 mcatch (demoException&, demo)
291 message_mgr().demo_failure(demo);
299 if (d != (const int)0)
302 reply_to_client(client, OLIAS_SUCCESS);
306 reply_to_client(client, OLIAS_LOCATOR_NOT_FOUND);
307 ON_DEBUG(cerr << "Document not found." << endl);
312 // /////////////////////////////////////////////////////////////////
313 // receive_olias_event
314 // /////////////////////////////////////////////////////////////////
317 ServiceMgr::receive_olias_event (Widget, XtPointer client_data,
318 Atom *selection, Atom * /* type */,
319 XtPointer value, unsigned long *length,
322 // NOTE: probably should verify type (olias_event_atom) and format
324 XGetSelectionOwner (window_system().display(),*selection);
325 ((ServiceMgr *) client_data)->
326 process_olias_event (client, (unsigned char *) value, *length);
330 // /////////////////////////////////////////////////////////////////
332 // /////////////////////////////////////////////////////////////////
335 ServiceMgr::reply_to_client (Window client, OliasStatus reply_code)
337 static XClientMessageEvent client_event;
340 // Before we send a reply, we must determine if the client window
341 // is an existing (valid) window. This is done below by searching
342 // for it's window ID in the list of immediate children of the root
343 // window. If the client window is no longer valid then we don't
344 // send a reply. This method seems overly complex to me but after
345 // consulting with our X gurus I determined that this is the best
346 // (only?) way to accomplish this. This code fixes defect ID 16933.
349 // a better way might be to do an XSynch, install an error handler
350 // try a X Command to see if an error is generated, do another,
351 // XSynch, then restore the original Xlib error handler
353 Window root, parent, *children;
354 unsigned int i, nchildren;
355 Boolean client_exists = False;
357 // Query root window for all of its immediate children.
358 if (XQueryTree(window_system().display(),
359 DefaultRootWindow(window_system().display()),
360 &root, &parent, &children, &nchildren)) {
361 // Search for the client window ID in root's list of children.
362 // Assumption: Window was created as a toplevel widget within
363 // external API client.
364 for (i = 0; i < nchildren; i++) {
365 if (children[i] == client) {
366 client_exists = True;
370 // Free up the children array.
374 // If not a valid window then punt sending the reply message
375 if (client == None || !client_exists)
378 client_event.window = client;
379 client_event.type = ClientMessage;
380 client_event.message_type = _XA_OLIAS_REPLY;
381 client_event.format = 32;
382 client_event.data.l[0] = OLIAS_PROTOCOL_VERSION;
383 client_event.data.l[1] = reply_code;
385 ON_DEBUG(printf ("sending reply to 0x%lx\n", client));
387 XSendEvent (window_system().display(), client, False,
388 0L, (XEvent *) &client_event);
389 XFlush (window_system().display());
393 // /////////////////////////////////////////////////////////////////
394 // olias_send_event - internal version for olias-to-olias comm
395 // /////////////////////////////////////////////////////////////////
398 olias_send_event (Widget, OliasEvent *event)
403 UAS_Pointer<UAS_Common> d;
407 case OLIAS_NOOP_EVENT:
410 case OLIAS_DISPLAY_EVENT:
411 locator = ((OliasDisplayEvent *) event)->locator;
412 ON_DEBUG (printf (">>> external-api display <%s>\n", locator));
415 if (strchr (locator, ':'))
417 d = UAS_Common::create (locator);
421 bufferlen = strlen("mmdb:LOCATOR=") + strlen(locator) + 1;
422 buffer = new char[bufferlen];
423 snprintf (buffer, bufferlen, "mmdb:LOCATOR=%s", locator);
424 d = UAS_Common::create (buffer);
426 if (d != (const int)0)
430 return (OLIAS_TIMEOUT);
431 ON_DEBUG(printf(">>> g_top_locator = %p\n", g_top_locator));
432 if (g_top_locator[0] == '\0')
433 return (OLIAS_TIMEOUT);
434 g_scroll_to_locator = TRUE;
435 len = MIN(strlen(locator), 4096 - 1);
436 *((char *) memcpy(g_top_locator, locator, len) +len) = '\0';
440 mcatch (demoException&, demo)
442 message_mgr().demo_failure(demo);
449 if (d != (const int)0)
452 return (OLIAS_SUCCESS);
456 message_mgr().info_dialog (
457 (char*)UAS_String(CATGETS(Set_Messages, 46, "File a Bug")));
458 return (OLIAS_SUCCESS);
459 // return (OLIAS_LOCATOR_NOT_FOUND); until help lib fixed
464 return (OLIAS_TIMEOUT);
467 return (OLIAS_LOCATOR_NOT_FOUND);