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
23 /* $TOG: SmCommun.c /main/14 1999/09/20 13:47:25 mgreess $ */
25 * (c) Copyright 1997, The Open Group
27 /*************************************<+>*************************************
28 *****************************************************************************
32 ** Project: HP DT Session Manager (dtsession)
36 ** This file contains functionality needed to communicate with the
37 ** other DT components. This includes initialization and callback code.
39 *****************************************************************************
40 *************************************<+>*************************************/
42 * (c) Copyright 1996 Digital Equipment Corporation.
43 * (c) Copyright 1990, 1993, 1994, 1996 Hewlett-Packard Company
44 * (c) Copyright 1993, 1994, 1996 International Business Machines Corp.
45 * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
46 * (c) Copyright 1993, 1994, 1996 Novell, Inc.
47 * (c) Copyright 1996 FUJITSU LIMITED.
48 * (c) Copyright 1996 Hitachi.
52 #ifdef _SUN_OS /* for the strtok calls */
55 #include <X11/Intrinsic.h>
56 #include <X11/StringDefs.h>
57 #if defined (USE_X11SSEXT)
58 #include <X11/extensions/scrnsaver.h>
59 #endif /* USE_X11SSEXT */
63 #include <Dt/Action.h>
64 #include <Dt/SessionM.h>
65 #include <Dt/UserMsg.h>
66 #include <Dt/Indicator.h>
67 #include <Dt/MsgLog.h>
73 #include "SmRestore.h"
76 #include "SmProtocol.h"
77 #include "SmGlobals.h"
81 * Pulic var declarations
83 extern int clientRunning; /* from SmConMgmt.c */
84 extern char **smExecArray;
87 * Defines for this file only
94 * Constants for the Save_Session ToolTalk message
96 static const char *SAVE_TYPE = "save_type";
97 static const char *SHUTDOWN = "shutdown";
98 static const char *INTERACT_STYLE = "interact_style";
99 static const char *FAST = "fast";
100 static const char *GLOBAL = "global";
101 static const char *NUM_BACKUPS = "num_sessions_backedup";
102 static const char *SAVE_LOCAL = "Local";
103 static const char *SAVE_GLOBAL = "Global";
104 static const char *SAVE_BOTH = "Both";
105 static const char *INTERACT_NONE = "None";
106 static const char *INTERACT_ERRORS = "Errors";
107 static const char *TRUE_STR = "True";
108 static const char *FALSE_STR = "False";
111 * Local function definitions
114 static void DtwmStarted(void);
117 ProcessSaveSessionMessage (
123 Boolean shutdown = DEFAULT_SHUTDOWN;
124 int interactStyle = DEFAULT_INTERACT_STYLE;
125 Boolean fast = DEFAULT_FAST;
126 Boolean global = DEFAULT_GLOBAL;
127 int numSessionsBackedup;
131 int num_args = tt_message_args_count (saveMsg);
136 for (i = 0; i < num_args; i++) {
138 type = tt_message_arg_type (saveMsg, i);
139 status = tt_ptr_error (type);
140 if (status != TT_OK || type == NULL)
143 value = tt_message_arg_val (saveMsg, i);
144 status = tt_ptr_error (value);
145 if (status != TT_OK || value == NULL)
148 if (!strcmp (type, SAVE_TYPE)) {
149 if (!strcmp (value, SAVE_LOCAL))
150 saveType = SmSaveLocal;
151 else if (!strcmp (value, SAVE_GLOBAL))
152 saveType = SmSaveGlobal;
153 else if (!strcmp (value, SAVE_BOTH))
154 saveType = SmSaveBoth;
161 else if (!strcmp (type, SHUTDOWN)) {
162 if (!strcmp (value, TRUE_STR))
164 else if (!strcmp (value, FALSE_STR))
167 else if (!strcmp (type, INTERACT_STYLE)){
168 if (!strcmp (value, INTERACT_NONE))
169 interactStyle = SmInteractStyleNone;
170 else if (!strcmp (value, INTERACT_ERRORS))
171 interactStyle = SmInteractStyleErrors;
173 else if (!strcmp (type, FAST)) {
174 if (!strcmp (value, TRUE_STR))
176 else if (!strcmp (value, FALSE_STR))
179 else if (!strcmp (type, GLOBAL)) {
180 if (!strcmp (value, TRUE_STR))
182 else if (!strcmp (value, FALSE_STR))
185 else if (!strcmp (type, NUM_BACKUPS)) {
186 numSessionsBackedup = atoi (value);
187 if (numSessionsBackedup > 0)
188 smRes.numSessionsBackedup = numSessionsBackedup;
194 pch1 = strdup ((char *) GETMESSAGE (40, 16,
195 "The Save_Session message contains the unrecognized argument '%s'."));
197 pch2 = XtMalloc (strlen (pch1)+strlen (type)+3);
199 (void) sprintf (pch2, pch1, type);
200 DtMsgLogMessage (smGD.programName,
201 DtMsgLogWarning, pch2);
202 free (pch1); free (pch2);
214 if (saveType == -1) {
215 PostSaveSessionErrorDialog ();
219 smGD.smState = IN_PROCESS;
220 tmpMsg = tttk_message_create (0, TT_NOTICE, TT_SESSION, 0,
221 "DtActivity_Beginning", 0);
222 tt_message_send (tmpMsg);
223 tt_message_destroy (tmpMsg);
225 SaveState ((smGD.sessionType == HOME_SESSION),
226 smSettings.startState, saveType, shutdown,
227 interactStyle, fast, global);
229 tmpMsg = tttk_message_create (0, TT_NOTICE, TT_SESSION, 0,
230 "DtActivity_Began", 0);
231 tt_message_send (tmpMsg);
232 tt_message_destroy (tmpMsg);
238 /*************************************<->*************************************
240 * handleSessionMgrRequest ()
245 * Handle ToolTalk requests for which the session manager is responsible.
250 * Incoming request, and the pattern it matched.
255 * Whether the message has been consumed.
261 *************************************<->***********************************/
263 handleSessionMgrRequest(
270 Tt_callback_action rc;
273 if (tt_message_state( msg ) != TT_SENT)
275 /* msg is a reply to ourself */
276 return TT_CALLBACK_CONTINUE;
279 op = tt_message_op( msg );
280 status = tt_ptr_error( op );
281 if ((status != TT_OK) || (op == 0))
283 /* Let tttk_Xt_input_handler() Do The Right Thing */
284 return TT_CALLBACK_CONTINUE;
288 if (strcmp( op, SM_DISPLAY_LOCK ) == 0)
290 if(smGD.smState == READY)
292 smGD.smState = IN_PROCESS;
295 rc = TT_CALLBACK_PROCESSED;
297 else if (strcmp( op, SM_XSESSION_EXIT ) == 0)
299 if(smGD.smState == READY)
301 smGD.smState = IN_PROCESS;
304 * The session may have been canceled so set the smState
307 smGD.smState = READY;
308 destroyMsg = False; /* done in SmUI.c */
310 rc = TT_CALLBACK_PROCESSED;
312 else if (strcmp( op, SM_RESOURCES_RELOAD ) == 0)
314 if(smGD.smState == READY)
316 smGD.smState = IN_PROCESS;
319 rc = TT_CALLBACK_PROCESSED;
321 else if (strcmp( op, SM_SAVE_SESSION ) == 0)
323 if(smGD.smState == READY)
325 smGD.smState = IN_PROCESS;
326 ProcessSaveSessionMessage (msg);
328 rc = TT_CALLBACK_PROCESSED;
332 rc = TT_CALLBACK_CONTINUE;
336 if (destroyMsg == True)
338 tt_message_reply( msg );
339 tt_message_destroy( msg );
347 /*************************************<->*************************************
354 * Initialize the BMS and register the session manager with it. Then
355 * register all requests and notifications that the session manager is
361 * app = Application context for dtsession
371 *************************************<->***********************************/
383 * Before we start anything - initialize the customize data structure
385 smCust.screenSavChange = False;
386 smCust.audioChange = False;
387 smCust.keyboardChange = False;
388 smCust.fontChange = False;
389 smCust.pointerChange = False;
390 smCust.dClickChange = False;
391 smCust.preeditChange = False;
393 makeConnect = DtAppInitialize(smGD.appCon, smGD.display, smGD.topLevelWid,
397 smDD.okString = XmStringCreateLocalized(((char *)GETMESSAGE(18, 39, "OK")));
398 smDD.okLogoutString = XmStringCreateLocalized(((char *)GETMESSAGE(18, 39, "OK")));
399 smDD.cancelLogoutString = XmStringCreateLocalized(((char *)GETMESSAGE(18,40, "Cancel")));
400 smDD.helpString = XmStringCreateLocalized(((char *)GETMESSAGE(18, 41, "Help")));
402 if(makeConnect == False)
408 smGD.bmsDead = False;
412 status = tt_ptr_error( procId );
413 if (status == TT_OK) {
415 status = tt_int_error( fd );
416 if (status == TT_OK) {
417 XtAppAddInput( smGD.appCon, fd, (XtPointer)XtInputReadMask,
418 tttk_Xt_input_handler, procId );
421 if (status != TT_OK) {
425 smGD.requests2Handle = 0;
426 if (status == TT_OK) {
427 smGD.requests2Handle = tt_pattern_create();
428 tt_pattern_category_set( smGD.requests2Handle, TT_HANDLE );
429 tt_pattern_class_add( smGD.requests2Handle, TT_REQUEST );
430 tt_pattern_scope_add( smGD.requests2Handle, TT_SESSION );
431 sessId = tt_default_session();
432 tt_pattern_session_add( smGD.requests2Handle, sessId );
434 tt_pattern_op_add( smGD.requests2Handle, SM_DISPLAY_LOCK );
435 tt_pattern_op_add( smGD.requests2Handle, SM_XSESSION_EXIT );
436 tt_pattern_op_add( smGD.requests2Handle, SM_RESOURCES_RELOAD );
437 tt_pattern_op_add( smGD.requests2Handle, SM_SAVE_SESSION );
438 tt_pattern_callback_add( smGD.requests2Handle,
439 handleSessionMgrRequest );
440 status = tt_pattern_register( smGD.requests2Handle );
441 if (status != TT_OK) {
447 char *errfmt, *errmsg, *statmsg;
449 errfmt = SmNewString((char *) GETMESSAGE (6, 1,
450 "Could not connect to ToolTalk message server:\n%sExiting ...\n"));
451 statmsg = tt_status_message(status);
452 errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2);
453 sprintf(errmsg, errfmt, statmsg);
455 PrintError(DtError, errmsg);
460 } /* END OF FUNCTION StartMsgServer */
463 /*************************************<->*************************************
465 * DtwmStarted (fields, client_data, num_words)
482 *************************************<->***********************************/
486 smGD.dtwmRunning = True;
487 } /* END OF FUNCTION DtwmStarted */
490 /*************************************<->*************************************
497 * A request has come in (usually from the customizer) to restore one of
498 * the settings to their default states
506 * smToSet = (global) turns off flag of setting no longer set
512 *************************************<->***********************************/
518 if(toRestore == XaDtSmScreenInfo)
520 smToSet.screenSavChange = False;
522 else if(toRestore == XaDtSmAudioInfo)
524 smToSet.audioChange = False;
526 else if(toRestore == XaDtSmKeyboardInfo)
528 smToSet.keyboardChange = False;
530 else if(toRestore == XaDtSmPointerInfo)
532 smToSet.pointerChange = False;
533 smToSet.pointerMapChange = False;
535 } /* END OF FUNCTION RestoreDefaults */
538 /*************************************<->*************************************
540 * ProcessPropertyNotify ()
545 * The customizer has changed one of the properties on the sm top level
546 * window. This fact is remembered, so that at shutdown the information
555 * smToSet = (global) turns on flag of setting being set
561 *************************************<->***********************************/
563 ProcessPropertyNotify(
566 XPropertyEvent *pEvent = (XPropertyEvent *) next;
568 if (pEvent->state != PropertyNewValue)
573 if(pEvent->atom == XaDtSmScreenInfo)
575 smToSet.screenSavChange = True;
576 smCust.screenSavChange = True;
578 else if(pEvent->atom == XaDtSmAudioInfo)
580 smToSet.audioChange = True;
581 smCust.audioChange = True;
583 else if(pEvent->atom == XaDtSmKeyboardInfo)
585 smToSet.keyboardChange = True;
586 smCust.keyboardChange = True;
588 else if(pEvent->atom == XaDtSmFontInfo)
590 smCust.fontChange = True;
592 else if(pEvent->atom == XaDtSmPreeditInfo)
594 smCust.preeditChange = True;
596 else if(pEvent->atom == XaDtSmPointerInfo)
598 smToSet.pointerChange = True;
599 smCust.pointerChange = True;
600 smToSet.pointerMapChange = True;
601 smCust.dClickChange = True;
603 } /* END OF FUNCTION RecordChanges */
607 /*************************************<->*************************************
609 * ProcessClientMessage(next)
614 * A client message has come from somewhere. Process it if we know how.
618 * next - the client message event
628 *************************************<->***********************************/
630 ProcessClientMessage(
633 XClientMessageEvent *cEvent = (XClientMessageEvent *) next;
636 * If this event came from the style manager - process it
638 if(cEvent->message_type == XaDtSmStmProtocol)
640 if(cEvent->data.l[0] == XaDtSmSaveToHome)
643 * The style manager is asking for a save home session
645 if(smGD.smState == READY)
651 smGD.smState = IN_PROCESS;
652 msg = tttk_message_create( 0, TT_NOTICE, TT_SESSION, 0,
653 "DtActivity_Beginning", 0 );
654 tt_message_send( msg );
655 tt_message_destroy( msg );
657 startStateOrig = smSettings.startState;
658 confirmModeOrig = smSettings.confirmMode;
660 smSettings.startState = cEvent->data.l[1];
661 smSettings.confirmMode = cEvent->data.l[2];;
663 smGD.homeSave = True;
664 SaveState(True, smSettings.startState, SmSaveLocal,
665 DEFAULT_SHUTDOWN, SmInteractStyleNone,
666 DEFAULT_FAST, DEFAULT_GLOBAL);
667 smGD.homeSave = False;
669 smSettings.startState = startStateOrig;
670 smSettings.confirmMode = confirmModeOrig;
672 msg = tttk_message_create( 0, TT_NOTICE, TT_SESSION, 0,
673 "DtActivity_Began", 0 );
674 tt_message_send( msg );
675 tt_message_destroy( msg );
679 else if (cEvent->data.l[0] == XaDtSmRestoreDefault)
681 RestoreDefaults((Atom) cEvent->data.l[1]);
684 else if(cEvent->message_type == XaSmWmProtocol)
687 * If this event came from the ws manager - process it
689 if(cEvent->data.l[0] == XaWmExitSession)
692 * The ws manager is sending an exit session message
694 if(smGD.smState == READY)
696 smGD.smState = IN_PROCESS;
700 else if(cEvent->data.l[0] == XaWmLockDisplay)
703 * The ws manager is sending an lock display message
705 if(smGD.smState == READY)
707 smGD.smState = IN_PROCESS;
711 else if(cEvent->data.l[0] == XaWmWindowAck)
714 * The ws manager is sending a "client has been managed"
716 clientRunning = True;
718 else if(cEvent->data.l[0] == XaWmReady)
721 * The ws manager is sending a "ready for clients"
723 smGD.dtwmRunning = True;
726 else if (cEvent->message_type == XaDtSmStateInfo)
729 int flags = (int)cEvent->data.l[0];
732 * Session state has been changed. Get new values.
734 if(_DtGetSmState(smGD.display, smGD.topLevelWindow, &state) == Success)
736 char *newRes = malloc(BUFSIZ);
739 * Copy selected changes to data areas.
741 if (flags & SM_STATE_START)
743 smSettings.startState = state.smStartState;
746 if (flags & SM_STATE_CONFIRM)
748 smSettings.confirmMode = state.smConfirmMode;
752 if (flags & SM_STATE_CYCLETIMEOUT)
754 smSaverRes.cycleTimeout = state.smCycleTimeout;
755 sprintf(newRes+strlen(newRes), "dtsession*%scycleTimeout: %d\n",
757 smSaverRes.cycleTimeout/60);
760 if (flags & SM_STATE_LOCKTIMEOUT)
762 smSaverRes.lockTimeout = state.smLockTimeout;
763 sprintf(newRes+strlen(newRes), "dtsession*%slockTimeout: %d\n",
765 smSaverRes.lockTimeout/60);
768 if (flags & SM_STATE_SAVERTIMEOUT)
770 smSaverRes.saverTimeout = state.smSaverTimeout;
771 sprintf(newRes+strlen(newRes), "dtsession*%ssaverTimeout: %d\n",
773 smSaverRes.saverTimeout/60);
776 if (flags & SM_STATE_RANDOM)
778 smSaverRes.random = state.smRandom;
779 sprintf(newRes+strlen(newRes), "dtsession*%srandom: %s\n",
781 smSaverRes.random ? "True\n" : "False\n");
784 if (newRes[0] != '\0')
786 _DtAddToResource(smGD.display, newRes);
792 else if (cEvent->message_type == XaDtSmSaverInfo)
797 * Session screen saver list has been changed. Get new values.
799 if(_DtGetSmSaver(smGD.display, smGD.topLevelWindow, &saver) == Success)
803 SM_FREE(smGD.saverList);
804 smGD.saverList = SmNewString(saver.saverList);
805 SM_FREE(saver.saverList);
807 pRes = malloc(strlen("dtsession*saverList: ") +
808 strlen(smGD.saverList) +
809 strlen(smGD.extensionSpec) +
810 2); /* for the '/n' and '/0' */
813 sprintf(pRes, "dtsession*%ssaverList: %s\n",
816 _DtAddToResource(smGD.display, pRes);
820 if (smGD.saverListParse)
822 SM_FREE(smGD.saverListParse);
823 smGD.saverListParse = NULL;
827 #if defined (USE_HPSSEXT)
828 else if(cEvent->message_type == XaSmScreenSaveRet)
830 if(cEvent->data.l[0] == SS_ON)
832 if (smSaverRes.saverTimeout + smSaverRes.lockTimeout > 0 &&
833 smGD.smState == READY)
835 smGD.smState = IN_PROCESS;
840 #endif /* USE_HPSSEXT */
844 } /* END OF FUNCTION ProcessClientMessage */
846 /*************************************<->*************************************
848 * ProcessScreenSaverMessage(next)
853 * A screen saver message has come from the server. Process it if we know how.
857 * next - the client message event
867 *************************************<->***********************************/
868 #if defined (USE_X11SSEXT)
871 ProcessScreenSaverMessage(
874 XScreenSaverNotifyEvent *ssEvent = (XScreenSaverNotifyEvent *) next;
875 static int ssCount = 0;
877 if (ssEvent->state == ScreenSaverOn)
880 * Screen saver activated.
882 if (smSaverRes.saverTimeout + smSaverRes.lockTimeout > 0 &&
883 smGD.smState == READY)
886 * Resource says to lock the display and SM is ready, so lock it.
888 smGD.smState = IN_PROCESS;
893 #endif /* USE_X11SSEXT */
895 /*************************************<->*************************************
897 * ProcessReloadActionsDatabase(void)
902 * Register for notification of action database changes and load the action
903 * database into our address space. This function can be called directly
904 * by session mgr code, or called as a callback by the actions database.
914 * The first time in, this call registers itself as a callback routine with
915 * the actions database. The first and subsequent times in, this call will
916 * load the actions database into the session mgr address space.
918 *************************************<->***********************************/
921 ProcessReloadActionsDatabase(void)
923 static int needtoregister = 1;
928 * Have not yet registered with the actions database to call this
929 * callback when the database changes. Do so.
931 DtDbReloadNotify((DtDbReloadCallbackProc) ProcessReloadActionsDatabase,
937 * Our copy of the actions database must be out of date. Reload.
943 ProcessEvent(Widget w, XtPointer client_data, XEvent *event,
944 Boolean *continue_to_dispatch)
949 ProcessClientMessage(event);
952 ProcessPropertyNotify(event);
955 #if defined (USE_X11SSEXT)
956 if (event->type == smGD.ssEventType)
957 ProcessScreenSaverMessage(event);