Added window manager switching capplet. Please test. (a lot).

1999-02-24  Owen Taylor  <otaylor@redhat.com>

	* capplets/wm-properties: Added window manager
	switching capplet. Please test. (a lot).
This commit is contained in:
Owen Taylor 1999-02-24 22:59:12 +00:00 committed by Owen Taylor
parent b0424d949e
commit a3f33d2f9b
9 changed files with 1833 additions and 1 deletions

View file

@ -1,3 +1,8 @@
1999-02-24 Owen Taylor <otaylor@redhat.com>
* capplets/wm-properties: Added window manager
switching capplet. Please test. (a lot).
1999-02-23 Jonathan Blandford <jrb@redhat.com>
*

View file

@ -2,7 +2,7 @@ always_built_SUBDIRS = mouse-properties keyboard-properties \
desktop-links screensaver-properties background-properties \
theme-switcher sound-properties bell-properties \
ui-properties url-properties gnome-edit-properties \
session-properties
session-properties wm-properties
SUBDIRS = $(always_built_SUBDIRS)

View file

@ -0,0 +1,26 @@
INCLUDES = -I. -I$(srcdir) \
-I$(top_srcdir)/intl -I$(top_builddir)/intl \
-I$(srcdir)/../../control-center \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-I$(includedir) $(GNOME_INCLUDEDIR) $(IMLIB_CFLAGS)
bin_PROGRAMS = wm-properties-capplet
wm_properties_capplet_SOURCES = \
wm-properties.h \
wm-properties-capplet.c \
wm-list.c \
wm-exec.c
wm_properties_capplet_LDADD = \
../../control-center/libcapplet.la \
$(GNOME_LIBDIR) $(ORB_LIBS) $(GNOMEUI_LIBS) $(INTLLIBS) \
-lgnorba $(IMLIB_LIBS)
EXTRA_DIST = wm-properties.desktop
SUBDIRS=wm-desktops
sysdir = $(datadir)/control-center/Desktop
sys_DATA = wm-properties.desktop

View file

@ -0,0 +1,9 @@
wmdatadir = $(datadir)/gnome/wm-properties
wmdata_DATA=\
Enlightenment.desktop \
IceWM.desktop \
WindowMaker.desktop
EXTRA_DIST= $(wmdata_DATA)

View file

@ -0,0 +1,332 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/* Copyright (C) 1998 Redhat Software Inc.
* Code available under the Gnu GPL.
* Authors: Owen Taylor <otaylor@redhat.com>
*/
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <libgnome/libgnome.h>
#include "wm-properties.h"
typedef struct _RestartInfo RestartInfo;
struct _RestartInfo {
GnomeDesktopEntry *dentry;
gint retries;
WMResultFunc callback;
gpointer data;
};
gboolean
wm_is_running (void)
{
gboolean result;
gboolean old_warnings = gdk_error_warnings;
guint old_mask;
XWindowAttributes attrs;
gdk_error_warnings = FALSE;
gdk_error_code = 0;
XGetWindowAttributes (GDK_DISPLAY(), GDK_ROOT_WINDOW(), &attrs);
XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
SubstructureRedirectMask);
XSync (GDK_DISPLAY(), False);
if (gdk_error_code == 0) {
result = FALSE;
XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
attrs.your_event_mask);
} else
result = TRUE;
gdk_error_warnings = old_warnings;
return result;
}
/* Cut and paste from gnome-libs/gnome_win_hints_wm_exists, except that we
* return the xid instead of a window
*/
static Window
find_gnome_wm_window(void)
{
Atom r_type;
int r_format;
unsigned long count;
unsigned long bytes_remain;
unsigned char *prop, *prop2;
gint prev_error;
GdkAtom cardinal_atom = gdk_atom_intern ("CARDINAL", FALSE);
prev_error = gdk_error_warnings;
gdk_error_warnings = 0;
if (XGetWindowProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
gdk_atom_intern ("_WIN_SUPPORTING_WM_CHECK", FALSE),
0, 1, False, cardinal_atom,
&r_type, &r_format,
&count, &bytes_remain, &prop) == Success && prop)
{
if (r_type == cardinal_atom && r_format == 32 && count == 1)
{
Window n = *(long *)prop;
if (XGetWindowProperty(GDK_DISPLAY(), n,
gdk_atom_intern ("_WIN_SUPPORTING_WM_CHECK", FALSE),
0, 1, False, cardinal_atom,
&r_type, &r_format, &count, &bytes_remain,
&prop2) == Success && prop)
{
if (r_type == cardinal_atom && r_format == 32 && count == 1)
{
XFree(prop);
XFree(prop2);
gdk_error_warnings = prev_error;
return n;
}
XFree(prop2);
}
}
XFree(prop);
}
gdk_error_warnings = prev_error;
return None;
}
static Window
find_wm_window_from_client (GdkWindow *client)
{
Window window, frame, parent, root;
Window *children;
unsigned int nchildren;
gboolean old_warnings;
if (!client)
return None;
frame = None;
window = GDK_WINDOW_XWINDOW (client);
old_warnings = gdk_error_warnings;
gdk_error_warnings = FALSE;
gdk_error_code = 0;
while (XQueryTree (GDK_DISPLAY(), window,
&root, &parent, &children, &nchildren) &&
(gdk_error_code == 0)) {
if (children)
XFree(children);
if (window == root)
break;
if (root == parent) {
frame = window;
break;
}
window = parent;
}
gdk_error_warnings = old_warnings;
return frame;
}
static gboolean
window_has_wm_state (Window window)
{
Atom r_type;
int r_format;
unsigned long count;
unsigned long bytes_remain;
unsigned char *prop;
if (XGetWindowProperty(GDK_DISPLAY(), window,
gdk_atom_intern ("WM_STATE", FALSE),
0, 0, False, AnyPropertyType,
&r_type, &r_format,
&count, &bytes_remain, &prop) == Success) {
if (r_type != None) {
XFree(prop);
return TRUE;
}
}
return FALSE;
}
static gboolean
descendent_has_wm_state (Window window)
{
gboolean result = FALSE;
Window parent, root;
Window *children;
unsigned int nchildren;
gint i;
if (!XQueryTree (GDK_DISPLAY(), window,
&root, &parent, &children, &nchildren))
return FALSE;
for (i=0; i<nchildren; i++) {
if (window_has_wm_state (children[i]) ||
descendent_has_wm_state (children[i])) {
result = TRUE;
break;
}
}
if (children)
XFree (children);
return result;
}
/* This function tries to find a window manager frame by
* hunting all the children of the root window
*/
static Window
find_wm_window_from_hunt (void)
{
Window parent, root, frame;
Window *children;
unsigned int nchildren;
gboolean old_warnings;
gint i;
frame = None;
old_warnings = gdk_error_warnings;
gdk_error_warnings = FALSE;
gdk_error_code = 0;
XQueryTree (GDK_DISPLAY(), gdk_root_window,
&root, &parent, &children, &nchildren);
/* We are looking for a window that doesn't have WIN_STATE
* set on it, but does have a child with WIN_STATE set
*/
for (i=0; i<nchildren; i++) {
if (!window_has_wm_state (children[i]) &&
descendent_has_wm_state (children[i])) {
frame = children[i];
break;
}
}
if (children)
XFree (children);
gdk_error_warnings = old_warnings;
return frame;
}
static Window
find_wm_window (GdkWindow *client)
{
Window wm_window = None;
/* First, try to find a GNOME compliant WM */
wm_window = find_gnome_wm_window();
if (!wm_window) {
wm_window = find_wm_window_from_client (client);
}
if (!wm_window) {
wm_window = find_wm_window_from_hunt ();
}
return wm_window;
}
static gboolean
start_timeout (gpointer data)
{
RestartInfo *info = data;
if (wm_is_running ()) {
info->callback(WM_SUCCESS, info->data);
gnome_desktop_entry_free (info->dentry);
g_free (info);
return FALSE;
} else {
info->retries--;
if (info->retries > 0)
return TRUE;
else {
info->callback(WM_CANT_START, info->data);
gnome_desktop_entry_free (info->dentry);
g_free (info);
return FALSE;
}
}
}
static void
start_do (RestartInfo *info)
{
gnome_desktop_entry_launch (info->dentry);
info->retries = 20;
gtk_timeout_add (1000, start_timeout, info);
}
static gboolean
kill_timeout (gpointer data)
{
RestartInfo *info = data;
if (!wm_is_running ()) {
start_do (info);
return FALSE;
} else {
info->retries--;
if (info->retries > 0)
return TRUE;
else {
info->callback(WM_ALREADY_RUNNING, info->data);
gnome_desktop_entry_free (info->dentry);
g_free (info);
return FALSE;
}
}
}
void
wm_restart (WindowManager *new,
GdkWindow *client,
WMResultFunc callback,
gpointer data)
{
Window wm_window;
RestartInfo *info;
g_return_if_fail (new->is_present);
info = g_new (RestartInfo, 1);
info->dentry = gnome_desktop_entry_copy (new->dentry);
info->callback = callback;
info->data = data;
info->retries = 10;
if (wm_is_running ()) {
wm_window = find_wm_window (client);
if (!wm_window) {
(*callback) (WM_ALREADY_RUNNING, data);
gnome_desktop_entry_free (info->dentry);
g_free (info);
} else {
XKillClient (GDK_DISPLAY(), wm_window);
gtk_timeout_add (1000, kill_timeout, info);
}
} else {
start_do (info);
}
}
WindowManager *
wm_guess_current (void)
{
return NULL;
}

View file

@ -0,0 +1,361 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/* Copyright (C) 1998 Redhat Software Inc.
* Code available under the Gnu GPL.
* Authors: Owen Taylor <otaylor@redhat.com>
*/
#include <dirent.h>
#include <unistd.h>
#include <ctype.h>
#include <libgnome/libgnome.h>
#include "wm-properties.h"
/* Current list of window managers */
GList *window_managers = NULL;
/* List on startup */
static GList *window_managers_save = NULL;
/* Current window manager */
static WindowManager *current_wm;
/* Window manager on startup */
static WindowManager *current_wm_save;
gboolean
is_blank (gchar *str)
{
while (*str) {
if (!isspace(*str))
return FALSE;
str++;
}
return TRUE;
}
static gint
wm_compare (gconstpointer a, gconstpointer b)
{
const WindowManager *wm_a = (const WindowManager *)a;
const WindowManager *wm_b = (const WindowManager *)b;
return g_strcasecmp (wm_a->dentry->name, wm_b->dentry->name);
}
static void
wm_free (WindowManager *wm)
{
gnome_desktop_entry_free (wm->dentry);
g_free (wm->config_exec);
g_free (wm->config_tryexec);;
g_free (wm);
}
void
wm_check_present (WindowManager *wm)
{
gchar *path;
if (wm->dentry->exec) {
if (wm->dentry->tryexec) {
path = gnome_is_program_in_path (wm->dentry->tryexec);
wm->is_present = (path != NULL);
if (path)
g_free (path);
} else
wm->is_present = TRUE;
} else
wm->is_present = FALSE;
if (wm->config_exec) {
if (wm->config_tryexec) {
path = gnome_is_program_in_path (wm->config_tryexec);
wm->is_config_present = (path != NULL);
if (path)
g_free (path);
} else
wm->is_config_present = TRUE;
} else
wm->is_config_present = FALSE;
}
static WindowManager *
wm_copy (WindowManager *wm)
{
WindowManager *result = g_new (WindowManager, 1);
result->dentry = gnome_desktop_entry_copy (wm->dentry);
result->config_exec = g_strdup (wm->config_exec);
result->config_tryexec = g_strdup (wm->config_tryexec);
result->session_managed = wm->session_managed;
result->is_user = wm->is_user;
result->is_present = wm->is_present;
result->is_config_present = wm->is_config_present;
return result;
}
static WindowManager *
wm_list_find (GList *list, gchar *name)
{
GList *tmp_list = list;
while (tmp_list) {
WindowManager *wm = tmp_list->data;
if (strcmp (wm->dentry->name, name) == 0)
return wm;
tmp_list = tmp_list->next;
}
return NULL;
}
static GList *
wm_list_find_files (gchar *directory)
{
DIR *dir;
struct dirent *child;
GList *result = NULL;
gchar *suffix;
dir = opendir (directory);
if (dir == NULL)
return NULL;
while ((child = readdir (dir)) != NULL) {
/* Ignore files without .desktop suffix, and ignore
* .desktop files with no prefix
*/
suffix = child->d_name + strlen (child->d_name) - 8;
/* strlen(".desktop") == 8 */
if (suffix <= child->d_name ||
strcmp (suffix, ".desktop") != 0)
continue;
result = g_list_prepend (result,
g_concat_dir_and_file (directory,
child->d_name));
}
closedir (dir);
return result;
}
static void
wm_list_read_dir (gchar *directory, gboolean is_user)
{
WindowManager *wm;
GList *tmp_list;
GList *files;
gchar *prefix;
files = wm_list_find_files (directory);
tmp_list = files;
while (tmp_list) {
wm = g_new (WindowManager, 1);
wm->dentry = gnome_desktop_entry_load_unconditional (tmp_list->data);
if (!wm->dentry) {
g_free (wm);
tmp_list = tmp_list->next;
continue;
}
prefix = g_strconcat ("=", wm->dentry->location, "=/Window Manager/", NULL);
gnome_config_push_prefix (prefix);
g_free (prefix);
wm->config_exec = gnome_config_get_string ("ConfigExec");
wm->config_tryexec = gnome_config_get_string ("ConfigTryExec");
wm->session_managed = gnome_config_get_bool ("SessionManaged=0");
wm->is_user = is_user;
if (wm->config_exec && is_blank (wm->config_exec)) {
g_free (wm->config_exec);
wm->config_exec = NULL;
}
gnome_config_pop_prefix ();
wm_check_present (wm);
if (wm->dentry->name && wm->dentry->exec &&
(wm->is_user || wm->is_present)) {
window_managers =
g_list_insert_sorted (window_managers,
wm,
wm_compare);
window_managers_save =
g_list_insert_sorted (window_managers_save,
wm_copy (wm),
wm_compare);
} else {
wm_free (wm);
}
tmp_list = tmp_list->next;
}
g_list_free (files);
}
void
wm_list_init (void)
{
gchar *tempdir;
gchar *name;
tempdir = gnome_unconditional_datadir_file ("gnome/wm-properties/");
wm_list_read_dir (tempdir, FALSE);
g_free (tempdir);
tempdir = gnome_util_home_file("wm-properties/");
wm_list_read_dir (tempdir, TRUE);
g_free (tempdir);
name = gnome_config_get_string ("wm-properties/Config/Config/Current");
if (name) {
current_wm = wm_list_find (window_managers, name);
g_free (name);
}
if (!current_wm && window_managers)
current_wm = window_managers->data;
if (!current_wm)
g_error ("No window manager desktops found!");
current_wm_save = wm_list_find (window_managers_save, current_wm->dentry->name);
}
void
wm_list_save (void)
{
GList *old_files;
GList *tmp_list;
gchar *tempdir;
gchar *filename;
gchar *prefix;
WindowManager *wm;
/* Clean out the current contents of .gnome/wm-desktops
*/
tempdir = gnome_util_home_file("wm-properties/");
old_files = wm_list_find_files (tempdir);
g_free (tempdir);
tmp_list = old_files;
while (tmp_list) {
prefix = g_strconcat ("=", tmp_list->data, "=", NULL);
gnome_config_clean_file (prefix);
gnome_config_sync_file (prefix);
g_free (prefix);
tmp_list = tmp_list->next;
}
g_list_free (old_files);
/* Save the user's desktops
*/
tmp_list = window_managers;
while (tmp_list) {
wm = tmp_list->data;
if (wm->is_user) {
gnome_desktop_entry_save (wm->dentry);
prefix = g_strconcat ("=", wm->dentry->location, "=/Window Manager/", NULL);
gnome_config_push_prefix (prefix);
g_free (prefix);
if (wm->config_exec)
gnome_config_set_string ("ConfigExec", wm->config_exec);
if (wm->config_tryexec)
gnome_config_set_string ("ConfigTryExec", wm->config_tryexec);
gnome_config_set_bool ("SessionManaged=0", wm->session_managed);
gnome_config_pop_prefix ();
}
tmp_list = tmp_list->next;
}
/* Save the current window manager
*/
gnome_config_set_string ("wm-properties/Config/Config/Current",
current_wm->dentry->name);
gnome_config_sync ();
}
void
wm_list_revert (void)
{
GList *tmp_list;
gchar *old_name = g_strdup (current_wm->dentry->name);
g_list_foreach (window_managers, (GFunc)wm_free, NULL);
g_list_free (window_managers);
window_managers = NULL;
tmp_list = window_managers_save;
while (tmp_list) {
window_managers = g_list_prepend (window_managers,
wm_copy (tmp_list->data));
tmp_list = tmp_list->next;
}
window_managers = g_list_reverse (window_managers);
current_wm = wm_list_find (window_managers, old_name);
g_free (old_name);
}
void
wm_list_add (WindowManager *wm)
{
g_return_if_fail (wm != NULL);
window_managers = g_list_insert_sorted (window_managers, wm,
wm_compare);
}
void
wm_list_delete (WindowManager *wm)
{
GList *node;
g_return_if_fail (wm != NULL);
g_return_if_fail (wm != current_wm);
node = g_list_find (window_managers, wm);
g_return_if_fail (node != NULL);
window_managers = g_list_remove_link (window_managers, node);
g_list_free_1 (node);
wm_free (wm);
}
void
wm_list_set_current (WindowManager *wm)
{
current_wm = wm;
}
WindowManager *
wm_list_get_current (void)
{
return current_wm;
}
WindowManager *
wm_list_get_revert (void)
{
return wm_list_find (window_managers, current_wm_save->dentry->name);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,56 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/* Copyright (C) 1998 Redhat Software Inc.
* Code available under the Gnu GPL.
* Authors: Owen Taylor <otaylor@redhat.com>
*/
#include <gdk/gdk.h>
#include <libgnome/libgnome.h>
typedef struct _WindowManager WindowManager;
struct _WindowManager {
GnomeDesktopEntry *dentry;
gchar *config_exec;
gchar *config_tryexec;
gboolean session_managed : 1;
gboolean is_user : 1;
gboolean is_present : 1;
gboolean is_config_present : 1;
};
/* Utility functions */
gboolean is_blank (gchar *str);
/* Fill in the is_present and is_config_present fields */
void wm_check_present (WindowManager *wm);
/* Management of window manager list */
void wm_list_init (void);
void wm_list_save (void);
void wm_list_revert (void);
void wm_list_add (WindowManager *window_manager);
void wm_list_delete (WindowManager *window_manager);
void wm_list_set_current (WindowManager *window_manager);
WindowManager *wm_list_get_current (void);
WindowManager *wm_list_get_revert (void);
extern GList *window_managers;
/* Management of current window manager */
typedef enum {
WM_SUCCESS,
WM_ALREADY_RUNNING,
WM_CANT_START
} WMResult;
typedef void (*WMResultFunc) (WMResult result, gpointer data);
void wm_restart (WindowManager *new,
GdkWindow *client,
WMResultFunc callback,
gpointer data);
gboolean wm_is_running (void);
WindowManager *wm_guess_current (void);

View file

@ -106,6 +106,8 @@ capplets/theme-switcher/Makefile
capplets/ui-properties/Makefile
capplets/url-properties/Makefile
capplets/gnome-edit-properties/Makefile
capplets/wm-properties/Makefile
capplets/wm-properties/wm-desktops/Makefile
idl/Makefile
intl/Makefile])