69#include "ctwm_atoms.h"
84 int saveType, Bool shutdown,
int interactStyle,
89 char *clientId,
char *windowRole);
93static void DieCB(SmcConn smcCon, SmPointer clientData);
98#define SAVEFILE_VERSION 2
109 char *client_id = NULL;
110 Window client_leader;
114 unsigned long nitems;
115 unsigned long bytes_after;
118 if(XGetWindowProperty(
dpy, window, XA_WM_CLIENT_LEADER,
119 0L, 1L, False, AnyPropertyType, &actual_type, &actual_format,
120 &nitems, &bytes_after, (
unsigned char **)&prop) == Success) {
121 if(actual_type == XA_WINDOW && actual_format == 32 &&
122 nitems == 1 && bytes_after == 0) {
123 client_leader = *prop;
125 if(XGetTextProperty(
dpy, client_leader, &tp, XA_SM_CLIENT_ID)) {
126 if(tp.encoding == XA_STRING &&
127 tp.format == 8 && tp.nitems != 0) {
128 client_id = (
char *) tp.value;
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);
162 if(fwrite((
char *) &b, 1, 1, file) != 1) {
172 unsigned char file_short[2];
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) {
186 unsigned char file_short[2];
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) {
203 unsigned char file_int[4];
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) {
220 unsigned char count = strlen(
string);
225 if(fwrite(
string, (
int)
sizeof(
char), (
int) count, file) != count) {
242 if(fread((
char *) bp, 1, 1, file) != 1) {
252 unsigned char file_short[2];
254 if(fread((
char *) file_short, (
int)
sizeof(file_short), 1, file) != 1) {
257 *shortp = file_short[0] * 256 + file_short[1];
265 unsigned char file_short[2];
267 if(fread((
char *) file_short, (
int)
sizeof(file_short), 1, file) != 1) {
270 *shortp = file_short[0] * 256 + file_short[1];
281 unsigned char file_int[4];
283 if(fread((
char *) file_int, (
int)
sizeof(file_int), 1, file) != 1) {
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]);
307 data = malloc((
unsigned)
len + 1);
311 if(fread(data, (
int)
sizeof(
char), (
int)
len, file) !=
len) {
371 char *clientId,
char *windowRole)
377 int wm_command_count, i;
418 wm_command_count = 0;
419 XGetCommand(
dpy, theWindow->
w, &wm_command, &wm_command_count);
421 if(clientId || !wm_command || wm_command_count == 0) {
427 if(!
write_byte(configFile, (
char) wm_command_count)) {
430 for(i = 0; i < wm_command_count; i++)
434 XFreeStringList(wm_command);
454 if(theWindow->
icon) {
458 if(theWindow->
icon->
w) {
639 if(entry->
class.res_name) {
640 free(entry->
class.res_name);
642 if(entry->
class.res_class) {
643 free(entry->
class.res_class);
674 unsigned short version;
676 configFile = fopen(filename,
"rb");
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,
716 char *clientId, *windowRole;
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);
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);
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)) {
776 char **wm_command = NULL;
777 int wm_command_count = 0, i;
779 XGetCommand(
dpy, theWindow->
w,
780 &wm_command, &wm_command_count);
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) {
789 if(i == wm_command_count) {
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;
813 if(*icon_info_present) {
814 *icon_x =
ptr->icon_x;
815 *icon_y =
ptr->icon_y;
818 *occupation =
ptr->occupation;
844#ifdef MISSING_MKSTEMP
848 name = (
char *) tempnam(path, prefix);
849 *fd = open(name, O_CREAT | O_EXCL);
859 asprintf(&tempFile,
"%s/%sXXXXXX", path, prefix);
860 prev_umask = umask(077);
861 *fd = mkstemp(tempFile);
876# define PATH_MAX 1023
889 char *clientId, *windowRole;
890 FILE *configFile = NULL;
892 char *filename = NULL;
893 Bool success = False;
894 SmProp prop1, prop2, prop3, *props[3];
895 SmPropValue prop1val, prop2val, prop3val;
898 static int first_time = 1;
903 char hint = SmRestartIfRunning;
905 prop1.name = SmProgram;
906 prop1.type = SmARRAY8;
908 prop1.vals = &prop1val;
909 prop1val.value =
Argv[0];
910 prop1val.length = strlen(
Argv[0]);
912 sprintf(userId,
"%d", getuid());
913 prop2.name = SmUserID;
914 prop2.type = SmARRAY8;
916 prop2.vals = &prop2val;
917 prop2val.value = (SmPointer) userId;
918 prop2val.length = strlen(userId);
920 prop3.name = SmRestartStyleHint;
921 prop3.type = SmCARD8;
923 prop3.vals = &prop3val;
924 prop3val.value = (SmPointer) &hint;
931 SmcSetProperties(smcCon, 3, props);
936 path = getenv(
"SM_SAVE_DIR");
938 path = getenv(
"HOME");
954 if(!(configFile = fdopen(configFd,
"wb"))) {
964 for(scrnum = 0; scrnum <
NumScreens && success; scrnum++) {
969 while(theWindow && success) {
974 clientId, windowRole)) {
986 theWindow = theWindow->
next;
991 prop1.name = SmRestartCommand;
992 prop1.type = SmLISTofARRAY8;
994 prop1.vals = calloc((
Argc + 4),
sizeof(SmPropValue));
1003 for(i = 0; i <
Argc; i++) {
1004 if(strcmp(
Argv[i],
"-clientId") == 0 ||
1005 strcmp(
Argv[i],
"-restore") == 0) {
1009 prop1.vals[numVals].value = (SmPointer)
Argv[i];
1010 prop1.vals[numVals++].length = strlen(
Argv[i]);
1014 prop1.vals[numVals].value = (SmPointer)
"-clientId";
1015 prop1.vals[numVals++].length = 9;
1020 prop1.vals[numVals].value = (SmPointer)
"-restore";
1021 prop1.vals[numVals++].length = 8;
1023 prop1.vals[numVals].value = (SmPointer) filename;
1024 prop1.vals[numVals++].length = strlen(filename);
1026 prop1.num_vals = numVals;
1028 sprintf(discardCommand,
"rm %s", filename);
1029 prop2.name = SmDiscardCommand;
1030 prop2.type = SmARRAY8;
1032 prop2.vals = &prop2val;
1033 prop2val.value = (SmPointer) discardCommand;
1034 prop2val.length = strlen(discardCommand);
1039 SmcSetProperties(smcCon, 2, props);
1043 SmcSaveYourselfDone(smcCon, success);
1058 int saveType, Bool shutdown,
int interactStyle,
1065 SmcSaveYourselfDone(smcCon, False);
1075static void DieCB(SmcConn smcCon, SmPointer clientData)
1080 SmcCloseConnection(smcCon, 0, NULL);
1101 SmcSaveYourselfDone(smcCon, False);
1111 IceConn ice_conn = (IceConn) client_data;
1112 IceProcessMessages(ice_conn, NULL, NULL);
1125 SmcCallbacks callbacks;
1128 mask = SmcSaveYourselfProcMask | SmcDieProcMask |
1129 SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask;
1132 callbacks.save_yourself.client_data = (SmPointer) NULL;
1134 callbacks.die.callback =
DieCB;
1135 callbacks.die.client_data = (SmPointer) NULL;
1138 callbacks.save_complete.client_data = (SmPointer) NULL;
1141 callbacks.shutdown_cancelled.client_data = (SmPointer) NULL;
1157 fprintf(stderr,
"%s : Connection to session manager failed. (%s)",
ProgramName,
1163 iceConn = SmcGetIceConnection(
smcConn);
1167 IceConnectionNumber(iceConn),
1168 (XtPointer) XtInputReadMask,
1170 (XtPointer) iceConn);
1177 SmcCloseConnection(
smcConn, 0, NULL);
int NumScreens
How many Screens are on our display.
ScreenInfo ** ScreenList
List of ScreenInfo structs for each Screen.
void DoShutdown(void)
Cleanup and exit ctwm.
int frame_x
X position on screen of frame.
int frame_y
Y position on screen of frame.
void * LookInList(name_list *list_head, const char *name, XClassHint *class)
static TWMWinConfigEntry * winConfigHead
void ReadWinConfigFile(char *filename)
static void ProcessIceMsgProc(XtPointer client_data, int *source, XtInputId *id)
static int write_short(FILE *file, short s)
static int read_int(FILE *file, int *intp)
static int read_byte(FILE *file, unsigned char *bp)
static int write_byte(FILE *file, unsigned char b)
static int write_int(FILE *file, int i)
static char * GetClientID(Window window)
static void DieCB(SmcConn smcCon, SmPointer clientData)
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)
static XtInputId iceInputId
static int ReadWinConfigEntry(FILE *configFile, unsigned short version, TWMWinConfigEntry **pentry)
static int read_short(FILE *file, short *shortp)
static int write_ushort(FILE *file, unsigned short s)
static void ShutdownCancelledCB(SmcConn smcCon, SmPointer clientData)
static char * unique_filename(char *path, char *prefix, int *fd)
static void SaveCompleteCB(SmcConn smcCon, SmPointer clientData)
static int read_counted_string(FILE *file, char **stringp)
void shutdown_session(void)
static int write_counted_string(FILE *file, char *string)
static void SaveYourselfPhase2CB(SmcConn smcCon, SmPointer clientData)
static char * twm_clientId
static bool sent_save_done
static int read_ushort(FILE *file, unsigned short *shortp)
static char * GetWindowRole(Window window)
static void SaveYourselfCB(SmcConn smcCon, SmPointer clientData, int saveType, Bool shutdown, int interactStyle, Bool fast)
static int WriteWinConfigEntry(FILE *configFile, TwmWindow *theWindow, char *clientId, char *windowRole)
void ConnectToSessionManager(char *previous_id)
Info and control for each X Screen we control.
TwmWindow * FirstWindow
The head of the screen's twm window list.
struct TWMWinConfigEntry * next
bool width_ever_changed_by_user
bool height_ever_changed_by_user
Info and control for every X Window we take over.
struct TwmWindow * next
Next TwmWindow on the Screen.
bool heightEverChangedByUser
Has TwmWindow::attr height ever changed? Used only in sessions.
Window w
The actual X Window handle.
bool nameChanged
Has TwmWindow::name ever changed? Used only in session saving.
char * name
Current window name. Points into TwmWindow::names.
struct Icon * icon
The current icon.
int occupation
Workspaces the window is in (bitmap).
bool widthEverChangedByUser
Has TwmWindow::attr width ever changed? Used only in sessions.
XClassHint class
Window class info. From XGetClassHint().
XWindowAttributes attr
Window attributes from XGetWindowAttributes().
bool isicon
Is the window an icon now ?