CTWM
Loading...
Searching...
No Matches
/usr/src/RPM/BUILD/ctwm-4.1.0/session.c
Go to the documentation of this file.
1/*
2 * Copyright 1988 by Evans & Sutherland Computer Corporation,
3 * Salt Lake City, Utah
4 * Portions Copyright 1989 by the Massachusetts Institute of Technology
5 * Cambridge, Massachusetts
6 *
7 * Copyright 1992 Claude Lecommandeur.
8 */
9
10/*********************************************************************
11 *
12 * This module has been modified by
13 * Matthew McNeill (21 Mar 1997) - University of Durham (UK)
14 * for the support of the X Session Management Protocol
15 *
16 *********************************************************************
17 *
18 * Copyright (c) 1996-1997 The University of Durham, UK -
19 * Department of Computer Science.
20 * All rights reserved.
21 *
22 * Permission is hereby granted, without written agreement and without
23 * licence or royalty fees, to use, copy, modify, and distribute this
24 * software and its documentation, provided that usage, copying, modification
25 * or distribution is not for direct commercial advantage and that the
26 * above copyright notice and the following two paragraphs appear in
27 * all copies of this software. To use, copy, modify or distribute this
28 * software and its documentation otherwise requires a fee and/or specific
29 * permission.
30 *
31 * IN NO EVENT SHALL THE UNIVERSITY OF DURHAM BE LIABLE TO ANY PARTY FOR
32 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
33 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
34 * DURHAM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *
36 * THE UNIVERSITY OF DURHAM SPECIFICALLY DISCLAIMS ANY WARRANTIES,
37 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
38 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
39 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF DURHAM HAS NO OBLIGATION TO
40 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
41 *
42 ********************************************************************/
43
44/**********************************************************************
45 *
46 * $XConsortium: session.c,v 1.18 95/01/04 22:28:37 mor Exp $
47 *
48 * Session support for the X11R6 XSMP (X Session Management Protocol)
49 *
50 * 95/01/04 Ralph Mor, X Consortium Initial Version.
51 *
52 * Do the necessary modification to be integrated in ctwm.
53 * Can no longer be used for the standard twm.
54 *
55 * 21 Mar 1997 Matthew McNeill, Durham University Modified Version.
56 *
57 **********************************************************************/
58
59#include "ctwm.h"
60
61#include <stdio.h>
62#include <stdlib.h>
63#include <unistd.h>
64#include <sys/stat.h> // For umask
65#include <limits.h> // PATH_MAX
66
67#include <X11/Xatom.h>
68
69#include "ctwm_atoms.h"
70#include "ctwm_shutdown.h"
71#include "icons.h"
72#include "list.h"
73#include "screen.h"
74#include "session.h"
75
76
79static char *twm_clientId;
81static bool sent_save_done = false;
82
85 Bool fast);
86static char *GetClientID(Window window);
87static char *GetWindowRole(Window window);
89 char *clientId, char *windowRole);
90static int ReadWinConfigEntry(FILE *configFile, unsigned short version,
97
98#define SAVEFILE_VERSION 2
99
100
101/*===[ Get Client SM_CLIENT_ID ]=============================================*/
102
103static char *GetClientID(Window window)
104/* This function returns the value of the session manager client ID property
105 * given a valid window handle. If no such property exists on a window then
106 * null is returned
107 */
108{
109 char *client_id = NULL;
113 int actual_format;
114 unsigned long nitems;
115 unsigned long bytes_after;
116 Window *prop = NULL;
117
120 &nitems, &bytes_after, (unsigned char **)&prop) == Success) {
121 if(actual_type == XA_WINDOW && actual_format == 32 &&
122 nitems == 1 && bytes_after == 0) {
124
126 if(tp.encoding == XA_STRING &&
127 tp.format == 8 && tp.nitems != 0) {
128 client_id = (char *) tp.value;
129 }
130 }
131 }
132
133 if(prop) {
134 XFree(prop);
135 }
136 }
137
138 return client_id;
139}
140
141/*===[ Get Window Role ]=====================================================*/
142
143static char *GetWindowRole(Window window)
144/* this function returns the WM_WINDOW_ROLE property of a window
145 */
146{
148
149 if(XGetTextProperty(dpy, window, &tp, XA_WM_WINDOW_ROLE)) {
150 if(tp.encoding == XA_STRING && tp.format == 8 && tp.nitems != 0) {
151 return ((char *) tp.value);
152 }
153 }
154
155 return NULL;
156}
157
158/*===[ Various file write procedures ]=======================================*/
159
160static int write_byte(FILE *file, unsigned char b)
161{
162 if(fwrite((char *) &b, 1, 1, file) != 1) {
163 return 0;
164 }
165 return 1;
166}
167
168/*---------------------------------------------------------------------------*/
169
170static int write_ushort(FILE *file, unsigned short s)
171{
172 unsigned char file_short[2];
173
174 file_short[0] = (s & (unsigned)0xff00) >> 8;
175 file_short[1] = s & 0xff;
176 if(fwrite((char *) file_short, (int) sizeof(file_short), 1, file) != 1) {
177 return 0;
178 }
179 return 1;
180}
181
182/*---------------------------------------------------------------------------*/
183
184static int write_short(FILE *file, short s)
185{
186 unsigned char file_short[2];
187
188 file_short[0] = (s & (unsigned)0xff00) >> 8;
189 file_short[1] = s & 0xff;
190 if(fwrite((char *) file_short, (int) sizeof(file_short), 1, file) != 1) {
191 return 0;
192 }
193 return 1;
194}
195
196/*---------------------------------------------------------------------------*
197 * Matthew McNeill Feb 1997 - required to save the occupation state as an
198 * integer.
199 */
200
201static int write_int(FILE *file, int i)
202{
203 unsigned char file_int[4];
204
205 file_int[0] = (i & (unsigned)0xff000000) >> 24;
206 file_int[1] = (i & (unsigned)0x00ff0000) >> 16;
207 file_int[2] = (i & (unsigned)0x0000ff00) >> 8;
208 file_int[3] = (i & (unsigned)0x000000ff);
209 if(fwrite((char *) file_int, (int) sizeof(file_int), 1, file) != 1) {
210 return 0;
211 }
212 return 1;
213}
214
215/*---------------------------------------------------------------------------*/
216
217static int write_counted_string(FILE *file, char *string)
218{
219 if(string) {
220 unsigned char count = strlen(string);
221
222 if(write_byte(file, count) == 0) {
223 return 0;
224 }
225 if(fwrite(string, (int) sizeof(char), (int) count, file) != count) {
226 return 0;
227 }
228 }
229 else {
230 if(write_byte(file, 0) == 0) {
231 return 0;
232 }
233 }
234
235 return 1;
236}
237
238/*===[ various file read procedures ]========================================*/
239
240static int read_byte(FILE *file, unsigned char *bp)
241{
242 if(fread((char *) bp, 1, 1, file) != 1) {
243 return 0;
244 }
245 return 1;
246}
247
248/*---------------------------------------------------------------------------*/
249
250static int read_ushort(FILE *file, unsigned short *shortp)
251{
252 unsigned char file_short[2];
253
254 if(fread((char *) file_short, (int) sizeof(file_short), 1, file) != 1) {
255 return 0;
256 }
257 *shortp = file_short[0] * 256 + file_short[1];
258 return 1;
259}
260
261/*---------------------------------------------------------------------------*/
262
263static int read_short(FILE *file, short *shortp)
264{
265 unsigned char file_short[2];
266
267 if(fread((char *) file_short, (int) sizeof(file_short), 1, file) != 1) {
268 return 0;
269 }
270 *shortp = file_short[0] * 256 + file_short[1];
271 return 1;
272}
273
274/*---------------------------------------------------------------------------*
275 * Matthew McNeill Feb 1997 - required to save the occupation state as an
276 * integer.
277 */
278
279static int read_int(FILE *file, int *intp)
280{
281 unsigned char file_int[4];
282
283 if(fread((char *) file_int, (int) sizeof(file_int), 1, file) != 1) {
284 return 0;
285 }
286 *intp = (((int) file_int[0]) << 24) & 0xff000000;
287 *intp += (((int) file_int[1]) << 16) & 0x00ff0000;
288 *intp += (((int) file_int[2]) << 8) & 0x0000ff00;
289 *intp += ((int) file_int[3]);
290 return 1;
291}
292
293/*---------------------------------------------------------------------------*/
294
296{
297 unsigned char len;
298 char *data;
299
300 if(read_byte(file, &len) == 0) {
301 return 0;
302 }
303 if(len == 0) {
304 data = 0;
305 }
306 else {
307 data = malloc((unsigned) len + 1);
308 if(!data) {
309 return 0;
310 }
311 if(fread(data, (int) sizeof(char), (int) len, file) != len) {
312 free(data);
313 return 0;
314 }
315 data[len] = '\0';
316 }
317 *stringp = data;
318 return 1;
319}
320
321/*===[ Definition of a window config entry ]===================================
322 *
323 * An entry in the saved window config file looks like this:
324 *
325 * FIELD BYTES
326 * ----- ----
327 * SM_CLIENT_ID ID len 1 (may be 0)
328 * SM_CLIENT_ID LIST of bytes (may be NULL)
329 *
330 * WM_WINDOW_ROLE length 1 (may be 0)
331 * WM_WINDOW_ROLE LIST of bytes (may be NULL)
332 *
333 * if no WM_WINDOW_ROLE (length = 0)
334 *
335 * WM_CLASS "res name" length 1
336 * WM_CLASS "res name" LIST of bytes
337 * WM_CLASS "res class" length 1
338 * WM_CLASS "res class" LIST of bytes
339 * WM_NAME length 1 (0 if name changed)
340 * WM_NAME LIST of bytes
341 * WM_COMMAND arg count 1 (0 if no SM_CLIENT_ID)
342 * For each arg in WM_COMMAND
343 * arg length 1
344 * arg LIST of bytes
345 *
346 * Iconified bool 1
347 * Icon info present bool 1
348 *
349 * if icon info present
350 * icon x 2
351 * icon y 2
352 *
353 * Geom x 2
354 * Geom y 2
355 * Geom width 2
356 * Geom height 2
357 *
358 * Width ever changed by user 1
359 * Height ever changed by user 1
360 *
361 * ------------------[ Matthew McNeill Feb 1997 ]----------------------------
362 *
363 * Workspace Occupation 4
364 *
365 */
366
367
368/*===[ Write Window Config Entry to file ]===================================*/
369
371 char *clientId, char *windowRole)
372/* this function writes a window configuration entry of a given window to
373 * the given configuration file
374 */
375{
376 char **wm_command;
377 int wm_command_count, i;
378
379 /* ...unless the config file says otherwise. */
380 if(LookInList(Scr == NULL ? ScreenList [0]->DontSave : Scr->DontSave,
381 theWindow->name, &theWindow->class)) {
382 return 1;
383 }
384
386 return 0;
387 }
388
390 return 0;
391 }
392
393 if(!windowRole) {
394 if(!write_counted_string(configFile, theWindow->class.res_name)) {
395 return 0;
396 }
397 if(!write_counted_string(configFile, theWindow->class.res_class)) {
398 return 0;
399 }
400 if(theWindow->nameChanged) {
401 /*
402 * If WM_NAME changed on this window, we can't use it as
403 * a criteria for looking up window configurations. See the
404 * longer explanation in the GetWindowConfig() function below.
405 */
406
408 return 0;
409 }
410 }
411 else {
413 return 0;
414 }
415 }
416
417 wm_command = NULL;
418 wm_command_count = 0;
419 XGetCommand(dpy, theWindow->w, &wm_command, &wm_command_count);
420
421 if(clientId || !wm_command || wm_command_count == 0) {
422 if(!write_byte(configFile, 0)) {
423 return 0;
424 }
425 }
426 else {
427 if(!write_byte(configFile, (char) wm_command_count)) {
428 return 0;
429 }
430 for(i = 0; i < wm_command_count; i++)
431 if(!write_counted_string(configFile, wm_command[i])) {
432 return 0;
433 }
434 XFreeStringList(wm_command);
435 }
436 }
437
438 /* ===================[ Matthew McNeill Feb 1997 ]========================= *
439 * there has been a structural change to TwmWindow in ctwm. The Icon information
440 * is in a sub-structure now. The presence of icon information is not indicative
441 * of its current state. There is a new boolean condition for this (isicon)
442 */
443
444 if(!write_byte(configFile, theWindow->isicon ? 1 : 0)) {
445 return 0; /* iconified */
446 }
447
448 /* ===================[ Matthew McNeill Feb 1997 ]========================= *
449 * there has been a structural change to TwmWindow in ctwm. The Icon information
450 * is in a sub-structure now, if there is no icon, this sub-structure does
451 * not exist and the attempted access (below) causes a core dump.
452 * we need to check that the structure exists before trying to access it
453 */
454 if(theWindow->icon) {
455 if(!write_byte(configFile, theWindow->icon->w ? 1 : 0)) {
456 return 0; /* icon info exists */
457 }
458 if(theWindow->icon->w) {
459 int icon_x, icon_y;
460 XGetGeometry(dpy, theWindow->icon->w, &JunkRoot, &icon_x,
461 &icon_y, &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth);
462 if(!write_short(configFile, (short) icon_x)) {
463 return 0;
464 }
465 if(!write_short(configFile, (short) icon_y)) {
466 return 0;
467 }
468 }
469 }
470 else {
471 if(!write_byte(configFile, 0)) {
472 return 0; /* icon does not have any information */
473 }
474 }
475 /* ======================================================================= */
476
477 if(!write_short(configFile, (short) theWindow->frame_x)) {
478 return 0;
479 }
480 if(!write_short(configFile, (short) theWindow->frame_y)) {
481 return 0;
482 }
483 if(!write_ushort(configFile, (unsigned short) theWindow->attr.width)) {
484 return 0;
485 }
486 if(!write_ushort(configFile, (unsigned short) theWindow->attr.height)) {
487 return 0;
488 }
489 if(!write_byte(configFile, theWindow->widthEverChangedByUser ? 1 : 0)) {
490 return 0;
491 }
492 if(!write_byte(configFile, theWindow->heightEverChangedByUser ? 1 : 0)) {
493 return 0;
494 }
495
496 /* ===================[ Matthew McNeill Feb 1997 ]=======================*
497 * write an extra piece of information to the file, this is the occupation
498 * number and is a bit field of the workspaces occupied by the client.
499 */
500
501 if(!write_int(configFile, theWindow->occupation)) {
502 return 0;
503 }
504
505 /* ======================================================================*/
506
507 return 1;
508}
509
510/*===[ Read Window Configuration Entry ]=====================================*/
511
512static int ReadWinConfigEntry(FILE *configFile, unsigned short version,
514/* this function reads the next window configuration entry from the given file
515 * else it returns 0 if none exists or there is a problem
516 */
517{
519 unsigned char byte;
520 int i;
521
522 *pentry = entry = calloc(1, sizeof(TWMWinConfigEntry));
523 if(!*pentry) {
524 return 0;
525 }
526
527 if(!read_counted_string(configFile, &entry->client_id)) {
528 goto give_up;
529 }
530
531 if(!read_counted_string(configFile, &entry->window_role)) {
532 goto give_up;
533 }
534
535 if(!entry->window_role) {
536 if(!read_counted_string(configFile, &entry->class.res_name)) {
537 goto give_up;
538 }
539 if(!read_counted_string(configFile, &entry->class.res_class)) {
540 goto give_up;
541 }
542 if(!read_counted_string(configFile, &entry->wm_name)) {
543 goto give_up;
544 }
545
546 if(!read_byte(configFile, &byte)) {
547 goto give_up;
548 }
549 entry->wm_command_count = byte;
550
551 if(entry->wm_command_count == 0) {
552 entry->wm_command = NULL;
553 }
554 else {
555 entry->wm_command = calloc(entry->wm_command_count, sizeof(char *));
556
557 if(!entry->wm_command) {
558 goto give_up;
559 }
560
561 for(i = 0; i < entry->wm_command_count; i++)
562 if(!read_counted_string(configFile, &entry->wm_command[i])) {
563 goto give_up;
564 }
565 }
566 }
567
568 if(!read_byte(configFile, &byte)) {
569 goto give_up;
570 }
571
572 entry->iconified = byte;
573
574 if(!read_byte(configFile, &byte)) {
575 goto give_up;
576 }
577
578 entry->icon_info_present = byte;
579
580 if(entry->icon_info_present) {
581 if(!read_short(configFile, (short *) &entry->icon_x)) {
582 goto give_up;
583 }
584 if(!read_short(configFile, (short *) &entry->icon_y)) {
585 goto give_up;
586 }
587 }
588
589 if(!read_short(configFile, (short *) &entry->x)) {
590 goto give_up;
591 }
592 if(!read_short(configFile, (short *) &entry->y)) {
593 goto give_up;
594 }
595 if(!read_ushort(configFile, &entry->width)) {
596 goto give_up;
597 }
598 if(!read_ushort(configFile, &entry->height)) {
599 goto give_up;
600 }
601
602 if(version > 1) {
603 if(!read_byte(configFile, &byte)) {
604 goto give_up;
605 }
606 entry->width_ever_changed_by_user = byte;
607
608 if(!read_byte(configFile, &byte)) {
609 goto give_up;
610 }
611 entry->height_ever_changed_by_user = byte;
612 }
613 else {
614 entry->width_ever_changed_by_user = False;
615 entry->height_ever_changed_by_user = False;
616 }
617
618 /* ===================[ Matthew McNeill Feb 1997 ]======================= *
619 * read in the occupation information to restore the windows to the
620 * correct workspaces.
621 */
622
623 if(!read_int(configFile, &entry->occupation)) {
624 goto give_up;
625 }
626
627 /* ====================================================================== */
628
629 return 1;
630
631give_up:
632
633 if(entry->client_id) {
634 free(entry->client_id);
635 }
636 if(entry->window_role) {
637 free(entry->window_role);
638 }
639 if(entry->class.res_name) {
640 free(entry->class.res_name);
641 }
642 if(entry->class.res_class) {
643 free(entry->class.res_class);
644 }
645 if(entry->wm_name) {
646 free(entry->wm_name);
647 }
648 if(entry->wm_command_count && entry->wm_command) {
649 for(i = 0; i < entry->wm_command_count; i++)
650 if(entry->wm_command[i]) {
651 free(entry->wm_command[i]);
652 }
653 }
654 if(entry->wm_command) {
655 free(entry->wm_command);
656 }
657
658 free(entry);
659 *pentry = NULL;
660
661 return 0;
662}
663
664/*===[ Read In Win Config File ]=============================================*/
665
667/* this function reads the window configuration file and stores the information
668 * in a data structure which is returned
669 */
670{
673 int done = 0;
674 unsigned short version;
675
676 configFile = fopen(filename, "rb");
677 if(!configFile) {
678 return;
679 }
680
683 done = 1;
684 }
685
686 while(!done) {
688 entry->next = winConfigHead;
690 }
691 else {
692 done = 1;
693 }
694 }
695
697}
698
699/*===[ Get Window Configuration ]============================================*
700 * Matthew McNeill Feb 1997 - added extra parameter (occupation) to return
701 * restored occupation of the window
702 */
703
704int GetWindowConfig(TwmWindow *theWindow, short *x, short *y,
705 unsigned short *width, unsigned short *height,
706 bool *iconified, bool *icon_info_present,
707 short *icon_x, short *icon_y,
708 bool *width_ever_changed_by_user,
709 bool *height_ever_changed_by_user,
710 int *occupation) /* <== [ Matthew McNeill Feb 1997 ] == */
711/* This function attempts to extract all the relevant information from the
712 * given window and return values via the rest of the parameters to the
713 * function
714 */
715{
716 char *clientId, *windowRole;
718 int found = 0;
719
721
722 if(!ptr) {
723 return 0;
724 }
725
728
729 while(ptr && !found) {
730 int client_id_match = (!clientId && !ptr->client_id) ||
731 (clientId && ptr->client_id &&
732 strcmp(clientId, ptr->client_id) == 0);
733
734 if(!ptr->tag && client_id_match) {
735 if(windowRole || ptr->window_role) {
736 found = (windowRole && ptr->window_role &&
737 strcmp(windowRole, ptr->window_role) == 0);
738 }
739 else {
740 /*
741 * Compare WM_CLASS + only compare WM_NAME if the
742 * WM_NAME in the saved file is non-NULL. If the
743 * WM_NAME in the saved file is NULL, this means that
744 * the client changed the value of WM_NAME during the
745 * session, and we can not use it as a criteria for
746 * our search. For example, with xmh, at save time
747 * the window name might be "xmh: folderY". However,
748 * if xmh does not properly restore state when it is
749 * restarted, the initial window name might be
750 * "xmh: folderX". This would cause the window manager
751 * to fail in finding the saved window configuration.
752 * The best we can do is ignore WM_NAME if its value
753 * changed in the previous session.
754 */
755
756 if(strcmp(theWindow->class.res_name,
757 ptr->class.res_name) == 0 &&
758 strcmp(theWindow->class.res_class,
759 ptr->class.res_class) == 0 &&
760 (ptr->wm_name == NULL ||
761 strcmp(theWindow->name, ptr->wm_name) == 0)) {
762 if(clientId) {
763 /*
764 * If a client ID was present, we should not check
765 * WM_COMMAND because Xt will put a -xtsessionID arg
766 * on the command line.
767 */
768
769 found = 1;
770 }
771 else {
772 /*
773 * For non-XSMP clients, also check WM_COMMAND.
774 */
775
776 char **wm_command = NULL;
777 int wm_command_count = 0, i;
778
780 &wm_command, &wm_command_count);
781
782 if(wm_command_count == ptr->wm_command_count) {
783 for(i = 0; i < wm_command_count; i++)
784 if(strcmp(wm_command[i],
785 ptr->wm_command[i]) != 0) {
786 break;
787 }
788
789 if(i == wm_command_count) {
790 found = 1;
791 }
792 }
793 }
794 }
795 }
796 }
797
798 if(!found) {
799 ptr = ptr->next;
800 }
801 }
802
803 if(found) {
804 *x = ptr->x;
805 *y = ptr->y;
806 *width = ptr->width;
807 *height = ptr->height;
808 *iconified = ptr->iconified;
809 *icon_info_present = ptr->icon_info_present;
810 *width_ever_changed_by_user = ptr->width_ever_changed_by_user;
811 *height_ever_changed_by_user = ptr->height_ever_changed_by_user;
812
813 if(*icon_info_present) {
814 *icon_x = ptr->icon_x;
815 *icon_y = ptr->icon_y;
816 }
817
818 *occupation = ptr->occupation; /* <== [ Matthew McNeill Feb 1997 ] == */
819
820 ptr->tag = 1;
821 }
822 else {
823 *iconified = 0;
824 }
825
826 if(clientId) {
828 }
829
830 if(windowRole) {
832 }
833
834 return found;
835}
836
837/*===[ Unique Filename Generator ]===========================================*/
838
839static char *unique_filename(char *path, char *prefix, int *fd)
840/* this function attempts to allocate a temporary filename to store the
841 * information of the windows
842 */
843{
844#ifdef MISSING_MKSTEMP
845 char *name;
846
847 while(1) {
848 name = (char *) tempnam(path, prefix);
849 *fd = open(name, O_CREAT | O_EXCL);
850 if(*fd >= 0) {
851 return name;
852 }
853 free(name);
854 }
855#else
856 char *tempFile;
858
859 asprintf(&tempFile, "%s/%sXXXXXX", path, prefix);
860 prev_umask = umask(077);
861 *fd = mkstemp(tempFile);
863 if(*fd >= 0) {
864 return tempFile;
865 }
866 else {
867 free(tempFile);
868 return NULL;
869 }
870#endif
871}
872
873/*===[ SAVE WINDOW INFORMATION ]=============================================*/
874
875#ifndef PATH_MAX
876# define PATH_MAX 1023
877#endif
878
880/* this is where all the work is done in saving the state of the windows.
881 * it is not done in Phase One because phase one is used for the other clients
882 * to make sure that all the property information on their windows is correct
883 * and up to date
884 */
885{
886 int scrnum;
889 char *clientId, *windowRole;
891 char *path;
892 char *filename = NULL;
896 char discardCommand[PATH_MAX + 4];
897 int numVals, i;
898 static int first_time = 1;
899 int configFd;
900
901 if(first_time) {
902 char userId[20];
904
906 prop1.type = SmARRAY8;
907 prop1.num_vals = 1;
908 prop1.vals = &prop1val;
909 prop1val.value = Argv[0];
910 prop1val.length = strlen(Argv[0]);
911
912 sprintf(userId, "%d", getuid());
913 prop2.name = SmUserID;
914 prop2.type = SmARRAY8;
915 prop2.num_vals = 1;
916 prop2.vals = &prop2val;
917 prop2val.value = (SmPointer) userId;
918 prop2val.length = strlen(userId);
919
921 prop3.type = SmCARD8;
922 prop3.num_vals = 1;
923 prop3.vals = &prop3val;
924 prop3val.value = (SmPointer) &hint;
925 prop3val.length = 1;
926
927 props[0] = &prop1;
928 props[1] = &prop2;
929 props[2] = &prop3;
930
932
933 first_time = 0;
934 }
935
936 path = getenv("SM_SAVE_DIR");
937 if(!path) {
938 path = getenv("HOME");
939 if(!path) {
940 path = ".";
941 }
942 }
943 /*==============[ Matthew McNeill Feb 1997 ]==============*
944 * changed the unique name to CTWM rather than TWM
945 * this is tidier and more functional and prevents
946 * TWM picking up CTWM config files. The format is
947 * no longer the same since the new format supports
948 * virtaul workspaces.
949 *========================================================*/
950 if((filename = unique_filename(path, ".ctwm", &configFd)) == NULL) {
951 goto bad;
952 }
953
954 if(!(configFile = fdopen(configFd, "wb"))) { /* wb = write binary */
955 goto bad;
956 }
957
959 goto bad;
960 }
961
962 success = True;
963
964 for(scrnum = 0; scrnum < NumScreens && success; scrnum++) {
965 if(ScreenList[scrnum] != NULL) {
968
969 while(theWindow && success) {
972
975 success = False;
976 }
977
978 if(clientId) {
980 }
981
982 if(windowRole) {
984 }
985
986 theWindow = theWindow->next;
987 }
988 }
989 }
990
991 prop1.name = SmRestartCommand;
992 prop1.type = SmLISTofARRAY8;
993
994 prop1.vals = calloc((Argc + 4), sizeof(SmPropValue));
995
996 if(!prop1.vals) {
997 success = False;
998 goto bad;
999 }
1000
1001 numVals = 0;
1002
1003 for(i = 0; i < Argc; i++) {
1004 if(strcmp(Argv[i], "-clientId") == 0 ||
1005 strcmp(Argv[i], "-restore") == 0) {
1006 i++;
1007 }
1008 else {
1009 prop1.vals[numVals].value = (SmPointer) Argv[i];
1010 prop1.vals[numVals++].length = strlen(Argv[i]);
1011 }
1012 }
1013
1014 prop1.vals[numVals].value = (SmPointer) "-clientId";
1015 prop1.vals[numVals++].length = 9;
1016
1017 prop1.vals[numVals].value = (SmPointer) twm_clientId;
1018 prop1.vals[numVals++].length = strlen(twm_clientId);
1019
1020 prop1.vals[numVals].value = (SmPointer) "-restore";
1021 prop1.vals[numVals++].length = 8;
1022
1023 prop1.vals[numVals].value = (SmPointer) filename;
1024 prop1.vals[numVals++].length = strlen(filename);
1025
1026 prop1.num_vals = numVals;
1027
1028 sprintf(discardCommand, "rm %s", filename);
1029 prop2.name = SmDiscardCommand;
1030 prop2.type = SmARRAY8;
1031 prop2.num_vals = 1;
1032 prop2.vals = &prop2val;
1034 prop2val.length = strlen(discardCommand);
1035
1036 props[0] = &prop1;
1037 props[1] = &prop2;
1038
1040 free(prop1.vals);
1041
1042bad:
1044 sent_save_done = true;
1045
1046 if(configFile) {
1048 }
1049
1050 if(filename) {
1051 free(filename);
1052 }
1053}
1054
1055/*===[ Save Yourself SM CallBack ]===========================================*/
1056
1059 Bool fast)
1060/* this procedure is called by the session manager when requesting the
1061 * window manager to save its status, ie all the window configurations
1062 */
1063{
1066 sent_save_done = true;
1067 }
1068 else {
1069 sent_save_done = false;
1070 }
1071}
1072
1073/*===[ Die SM Call Back ]====================================================*/
1074
1076/* this procedure is called by the session manager when requesting that the
1077 * application shut istelf down
1078 */
1079{
1082 DoShutdown();
1083}
1084
1085/*===[ Save Complete SM Call Back ]==========================================*/
1086
1088/* This function is called to say that the save has been completed and that
1089 * the program can continue its operation
1090 */
1091{
1092 ;
1093}
1094
1095/*===[ Shutdown Cancelled SM Call Back ]=====================================*/
1096
1098
1099{
1100 if(!sent_save_done) {
1102 sent_save_done = true;
1103 }
1104}
1105
1106/*===[ Process ICE Message ]=================================================*/
1107
1114
1115
1116/*===[ Connect To Session Manager ]==========================================*/
1117
1119/* This procedure attempts to connect to the session manager and setup the
1120 * interclent exchange via the Call Backs
1121 */
1122{
1123 char errorMsg[256];
1124 unsigned long mask;
1127
1130
1131 callbacks.save_yourself.callback = SaveYourselfCB;
1132 callbacks.save_yourself.client_data = (SmPointer) NULL;
1133
1134 callbacks.die.callback = DieCB;
1135 callbacks.die.client_data = (SmPointer) NULL;
1136
1137 callbacks.save_complete.callback = SaveCompleteCB;
1138 callbacks.save_complete.client_data = (SmPointer) NULL;
1139
1140 callbacks.shutdown_cancelled.callback = ShutdownCancelledCB;
1141 callbacks.shutdown_cancelled.client_data = (SmPointer) NULL;
1142
1144 NULL, /* use SESSION_MANAGER env */
1148 mask,
1149 &callbacks,
1151 &twm_clientId,
1152 256, errorMsg);
1153
1154 if(smcConn == NULL) {
1155#ifdef DEBUG
1156 /* == [ Matthew McNeill Feb 1997 ] == */
1157 fprintf(stderr, "%s : Connection to session manager failed. (%s)", ProgramName,
1158 errorMsg);
1159#endif
1160 return;
1161 }
1162
1164
1166 appContext,
1170 (XtPointer) iceConn);
1171}
1172
1173
1175{
1176 if(smcConn) {
1178 }
1179}
static int PlaceX
Definition add_window.c:82
char * ProgramName
Definition ctwm_main.c:146
int Argc
Definition ctwm_main.c:148
unsigned int JunkBW
Definition ctwm.h:359
unsigned int JunkWidth
Definition ctwm_main.c:144
Window JunkRoot
Definition ctwm_main.c:142
Display * dpy
Definition ctwm_main.c:84
XtAppContext appContext
Definition ctwm_main.c:83
char ** Argv
Definition ctwm_main.c:149
unsigned int JunkHeight
Definition ctwm.h:359
unsigned int JunkDepth
Definition ctwm.h:359
int NumScreens
How many Screens are on our display.
Definition ctwm_main.c:89
#define Scr
ScreenInfo ** ScreenList
List of ScreenInfo structs for each Screen.
Definition ctwm_main.c:92
void DoShutdown(void)
Cleanup and exit ctwm.
void * LookInList(name_list *list_head, const char *name, XClassHint *class)
Definition list.c:101
int y
Definition menus.c:70
int x
Definition menus.c:69
static int ptr
Definition parse.c:74
static int len
Definition parse.c:75
static TWMWinConfigEntry * winConfigHead
Definition session.c:80
void ReadWinConfigFile(char *filename)
Definition session.c:666
static void ProcessIceMsgProc(XtPointer client_data, int *source, XtInputId *id)
Definition session.c:1108
SmcConn smcConn
Definition session.c:77
static int write_short(FILE *file, short s)
Definition session.c:184
static int read_int(FILE *file, int *intp)
Definition session.c:279
static int read_byte(FILE *file, unsigned char *bp)
Definition session.c:240
static int write_byte(FILE *file, unsigned char b)
Definition session.c:160
static int write_int(FILE *file, int i)
Definition session.c:201
static char * GetClientID(Window window)
Definition session.c:103
static void DieCB(SmcConn smcCon, SmPointer clientData)
Definition session.c:1075
int GetWindowConfig(TwmWindow *theWindow, short *x, short *y, unsigned short *width, unsigned short *height, bool *iconified, bool *icon_info_present, short *icon_x, short *icon_y, bool *width_ever_changed_by_user, bool *height_ever_changed_by_user, int *occupation)
Definition session.c:704
static XtInputId iceInputId
Definition session.c:78
static int ReadWinConfigEntry(FILE *configFile, unsigned short version, TWMWinConfigEntry **pentry)
Definition session.c:512
static int read_short(FILE *file, short *shortp)
Definition session.c:263
static int write_ushort(FILE *file, unsigned short s)
Definition session.c:170
static void ShutdownCancelledCB(SmcConn smcCon, SmPointer clientData)
Definition session.c:1097
static char * unique_filename(char *path, char *prefix, int *fd)
Definition session.c:839
static void SaveCompleteCB(SmcConn smcCon, SmPointer clientData)
Definition session.c:1087
static int read_counted_string(FILE *file, char **stringp)
Definition session.c:295
void shutdown_session(void)
Definition session.c:1174
static int write_counted_string(FILE *file, char *string)
Definition session.c:217
static void SaveYourselfPhase2CB(SmcConn smcCon, SmPointer clientData)
Definition session.c:879
static char * twm_clientId
Definition session.c:79
static bool sent_save_done
Definition session.c:81
#define SAVEFILE_VERSION
Definition session.c:98
static int read_ushort(FILE *file, unsigned short *shortp)
Definition session.c:250
static char * GetWindowRole(Window window)
Definition session.c:143
static void SaveYourselfCB(SmcConn smcCon, SmPointer clientData, int saveType, Bool shutdown, int interactStyle, Bool fast)
Definition session.c:1057
#define PATH_MAX
Definition session.c:876
static int WriteWinConfigEntry(FILE *configFile, TwmWindow *theWindow, char *clientId, char *windowRole)
Definition session.c:370
void ConnectToSessionManager(char *previous_id)
Definition session.c:1118
Info and control for each X Screen we control.
Definition screen.h:96
TwmWindow * FirstWindow
The head of the screen's twm window list.
Definition screen.h:151
Info and control for every X Window we take over.
char * name
Current window name. Points into TwmWindow::names.