1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-21 13:28:05 +01:00

Initial revision

This commit is contained in:
scottc
1998-09-29 22:36:29 +00:00
commit 9d2e6ef9f1
527 changed files with 138651 additions and 0 deletions

508
src/session.c Normal file
View File

@@ -0,0 +1,508 @@
/* session.c - session state handling
*
* Copyright (c) 1998 Dan Pascu
*
* WindowMaker window manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "WindowMaker.h"
#include "screen.h"
#include "window.h"
#include "session.h"
#include "wcore.h"
#include "framewin.h"
#include "workspace.h"
#include "funcs.h"
#include "properties.h"
#include "application.h"
#include "appicon.h"
#include "dock.h"
#include "list.h"
#include <proplist.h>
static proplist_t sApplications = NULL;
static proplist_t sCommand;
static proplist_t sName;
static proplist_t sHost;
static proplist_t sWorkspace;
static proplist_t sShaded;
static proplist_t sMiniaturized;
static proplist_t sHidden;
static proplist_t sGeometry;
static proplist_t sDock;
static proplist_t sYes, sNo;
static void
make_keys()
{
if (sApplications!=NULL)
return;
sApplications = PLMakeString("Applications");
sCommand = PLMakeString("Command");
sName = PLMakeString("Name");
sHost = PLMakeString("Host");
sWorkspace = PLMakeString("Workspace");
sShaded = PLMakeString("Shaded");
sMiniaturized = PLMakeString("Miniaturized");
sHidden = PLMakeString("Hidden");
sGeometry = PLMakeString("Geometry");
sDock = PLMakeString("Dock");
sYes = PLMakeString("Yes");
sNo = PLMakeString("No");
}
static int
getBool(proplist_t value)
{
char *val;
if (!PLIsString(value)) {
return 0;
}
if (!(val = PLGetString(value))) {
return 0;
}
if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y'))
|| strcasecmp(val, "YES")==0) {
return 1;
} else if ((val[1]=='\0' && (val[0]=='n' || val[0]=='N'))
|| strcasecmp(val, "NO")==0) {
return 0;
} else {
int i;
if (sscanf(val, "%i", &i)==1) {
return (i!=0);
} else {
wwarning(_("can't convert \"%s\" to boolean"), val);
return 0;
}
}
}
static proplist_t
makeWindowState(WWindow *wwin, WApplication *wapp)
{
WScreen *scr = wwin->screen_ptr;
Window win;
int argc;
char **argv;
char *class, *instance, *command=NULL, buffer[256];
proplist_t win_state, cmd, name, workspace;
proplist_t shaded, miniaturized, hidden, geometry;
proplist_t dock;
if (wwin->main_window!=None && wwin->main_window!=wwin->client_win)
win = wwin->main_window;
else
win = wwin->client_win;
if (XGetCommand(dpy, win, &argv, &argc) && argc>0) {
command = FlattenStringList(argv, argc);
XFreeStringList(argv);
}
if (!command)
return NULL;
if (PropGetWMClass(win, &class, &instance)) {
if (class && instance)
sprintf(buffer, "%s.%s", instance, class);
else if (instance)
sprintf(buffer, "%s", instance);
else if (class)
sprintf(buffer, ".%s", class);
else
sprintf(buffer, ".");
name = PLMakeString(buffer);
cmd = PLMakeString(command);
/*sprintf(buffer, "%d", wwin->frame->workspace+1);
workspace = PLMakeString(buffer);*/
workspace = PLMakeString(scr->workspaces[wwin->frame->workspace]->name);
shaded = wwin->flags.shaded ? sYes : sNo;
miniaturized = wwin->flags.miniaturized ? sYes : sNo;
hidden = wwin->flags.hidden ? sYes : sNo;
sprintf(buffer, "%ix%i+%i+%i", wwin->client.width, wwin->client.height,
wwin->frame_x, wwin->frame_y);
geometry = PLMakeString(buffer);
win_state = PLMakeDictionaryFromEntries(sName, name,
sCommand, cmd,
sWorkspace, workspace,
sShaded, shaded,
sMiniaturized, miniaturized,
sHidden, hidden,
sGeometry, geometry,
NULL);
PLRelease(name);
PLRelease(cmd);
PLRelease(workspace);
PLRelease(geometry);
if (wapp && wapp->app_icon && wapp->app_icon->dock) {
int i;
char *name;
if (wapp->app_icon->dock == scr->dock) {
name="Dock";
} else {
for(i=0; i<scr->workspace_count; i++)
if(scr->workspaces[i]->clip == wapp->app_icon->dock)
break;
assert( i < scr->workspace_count);
/*n = i+1;*/
name = scr->workspaces[i]->name;
}
dock = PLMakeString(name);
PLInsertDictionaryEntry(win_state, sDock, dock);
PLRelease(dock);
}
} else {
win_state = NULL;
}
if (instance) XFree(instance);
if (class) XFree(class);
if (command) free(command);
return win_state;
}
void
wSessionSaveState(WScreen *scr)
{
WWindow *wwin = scr->focused_window;
proplist_t win_info, wks;
proplist_t list=NULL;
LinkedList *wapp_list=NULL;
make_keys();
if (!scr->session_state) {
scr->session_state = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
if (!scr->session_state)
return;
}
list = PLMakeArrayFromElements(NULL);
while (wwin) {
WApplication *wapp=wApplicationOf(wwin->main_window);
if (wwin->transient_for==None && list_find(wapp_list, wapp)==NULL
&& !wwin->window_flags.dont_save_session) {
/* A entry for this application was not yet saved. Save one. */
if ((win_info = makeWindowState(wwin, wapp))!=NULL) {
list = PLAppendArrayElement(list, win_info);
PLRelease(win_info);
/* If we were succesful in saving the info for this window
* add the application the window belongs to, to the
* application list, so no multiple entries for the same
* application are saved.
*/
wapp_list = list_cons(wapp, wapp_list);
}
}
wwin = wwin->prev;
}
PLRemoveDictionaryEntry(scr->session_state, sApplications);
PLInsertDictionaryEntry(scr->session_state, sApplications, list);
PLRelease(list);
wks = PLMakeString(scr->workspaces[scr->current_workspace]->name);
PLInsertDictionaryEntry(scr->session_state, sWorkspace, wks);
PLRelease(wks);
list_free(wapp_list);
}
void
wSessionClearState(WScreen *scr)
{
make_keys();
if (!scr->session_state)
return;
PLRemoveDictionaryEntry(scr->session_state, sApplications);
PLRemoveDictionaryEntry(scr->session_state, sWorkspace);
}
static pid_t
execCommand(WScreen *scr, char *command, char *host)
{
pid_t pid;
char **argv;
int argc;
ParseCommand(command, &argv, &argc);
if (argv==NULL) {
return 0;
}
if ((pid=fork())==0) {
char **args;
int i;
SetupEnvironment(scr);
close(ConnectionNumber(dpy));
args = malloc(sizeof(char*)*(argc+1));
if (!args)
exit(111);
for (i=0; i<argc; i++) {
args[i] = argv[i];
}
args[argc] = NULL;
execvp(argv[0], args);
exit(111);
}
while (argc > 0)
free(argv[--argc]);
free(argv);
return pid;
}
static WSavedState*
getWindowState(WScreen *scr, proplist_t win_state)
{
WSavedState *state = wmalloc(sizeof(WSavedState));
proplist_t value;
char *tmp;
int i;
memset(state, 0, sizeof(WSavedState));
state->workspace = -1;
value = PLGetDictionaryEntry(win_state, sWorkspace);
if (value && PLIsString(value)) {
tmp = PLGetString(value);
if (sscanf(tmp, "%i", &state->workspace)!=1) {
state->workspace = -1;
for (i=0; i < scr->workspace_count; i++) {
if (strcmp(scr->workspaces[i]->name, tmp)==0) {
state->workspace = i;
break;
}
}
} else {
state->workspace--;
}
}
if ((value = PLGetDictionaryEntry(win_state, sShaded))!=NULL)
state->shaded = getBool(value);
if ((value = PLGetDictionaryEntry(win_state, sMiniaturized))!=NULL)
state->miniaturized = getBool(value);
if ((value = PLGetDictionaryEntry(win_state, sHidden))!=NULL)
state->hidden = getBool(value);
value = PLGetDictionaryEntry(win_state, sGeometry);
if (value && PLIsString(value)) {
if (sscanf(PLGetString(value), "%ix%i+%i+%i",
&state->w, &state->h, &state->x, &state->y)==4 &&
(state->w>0 && state->h>0)) {
state->use_geometry = 1;
} else if (sscanf(PLGetString(value), "%i,%i,%i,%i",
&state->x, &state->y, &state->w, &state->h)==4 &&
(state->w>0 && state->h>0)) {
/* TODO: remove redundant sscanf() in version 0.20.x */
state->use_geometry = 1;
}
}
return state;
}
#define SAME(x, y) (((x) && (y) && !strcmp((x), (y))) || (!(x) && !(y)))
void
wSessionRestoreState(WScreen *scr)
{
WSavedState *state;
char *instance, *class, *command, *host;
proplist_t win_info, apps, cmd, value;
pid_t pid;
int i, count;
WDock *dock;
WAppIcon *btn=NULL;
int j, n, found;
char *tmp;
make_keys();
if (!scr->session_state)
return;
PLSetStringCmpHook(NULL);
apps = PLGetDictionaryEntry(scr->session_state, sApplications);
if (!apps)
return;
count = PLGetNumberOfElements(apps);
if (count==0)
return;
for (i=0; i<count; i++) {
win_info = PLGetArrayElement(apps, i);
cmd = PLGetDictionaryEntry(win_info, sCommand);
if (!cmd || !PLIsString(cmd) || !(command = PLGetString(cmd))) {
continue;
}
value = PLGetDictionaryEntry(win_info, sName);
if (!value)
continue;
ParseWindowName(value, &instance, &class, "session");
if (!instance && !class)
continue;
value = PLGetDictionaryEntry(win_info, sHost);
if (value && PLIsString(value))
host = PLGetString(value);
else
host = NULL;
state = getWindowState(scr, win_info);
dock = NULL;
value = PLGetDictionaryEntry(win_info, sDock);
if (value && PLIsString(value) && (tmp = PLGetString(value))!=NULL) {
if (sscanf(tmp, "%i", &n)!=1) {
if (!strcasecmp(tmp, "DOCK")) {
dock = scr->dock;
} else {
for (j=0; j < scr->workspace_count; j++) {
if (strcmp(scr->workspaces[j]->name, tmp)==0) {
dock = scr->workspaces[j]->clip;
break;
}
}
}
} else {
if (n == 0) {
dock = scr->dock;
} else if (n>0 && n<=scr->workspace_count) {
dock = scr->workspaces[n-1]->clip;
}
}
}
found = 0;
if (dock!=NULL) {
for (j=0; j<dock->max_icons; j++) {
btn = dock->icon_array[j];
if (btn && SAME(instance, btn->wm_instance) &&
SAME(class, btn->wm_class) &&
SAME(command, btn->command)) {
found = 1;
break;
}
}
}
if (found) {
wDockLaunchWithState(dock, btn, state);
} else if ((pid = execCommand(scr, command, host)) > 0) {
wAddWindowSavedState(instance, class, command, pid, state);
} else {
free(state);
}
if (instance) free(instance);
if (class) free(class);
}
/* clean up */
PLSetStringCmpHook(StringCompareHook);
}
void
wSessionRestoreLastWorkspace(WScreen *scr)
{
proplist_t wks;
int w, i;
char *tmp;
make_keys();
if (!scr->session_state)
return;
PLSetStringCmpHook(NULL);
wks = PLGetDictionaryEntry(scr->session_state, sWorkspace);
if (!wks || !PLIsString(wks))
return;
tmp = PLGetString(wks);
/* clean up */
PLSetStringCmpHook(StringCompareHook);
if (sscanf(tmp, "%i", &w)!=1) {
w = -1;
for (i=0; i < scr->workspace_count; i++) {
if (strcmp(scr->workspaces[i]->name, tmp)==0) {
w = i;
break;
}
}
} else {
w--;
}
if (w!=scr->current_workspace && w<scr->workspace_count) {
wWorkspaceChange(scr, w);
}
}