2002-06-02 Seth Nickell <snickell@stanford.edu> * .cvsignore: Update to deal with the .pc file that gets generated. * Makefile.am: Build a real library, not just a non-installed. This is to get around problems dealing with GObject inheritance and static memory problems. We have a run time loaded object deriving from the library, so it has to link it in. But then the problem that occurs is that both the run-time loaded library and the program that calls it statically link the .la in. Then they have different memory spaces, and type registration goes to pot. Open to suggestions if there's a way of doing this without making an installed library. * gnome-window-manager.c: (gnome_window_manager_new), (gnome_window_manager_get_name), (gnome_window_manager_set_theme), (gnome_window_manager_get_theme_list), (gnome_window_manager_set_font), (gnome_window_manager_get_focus_follows_mouse), (gnome_window_manager_set_focus_follows_mouse), (gnome_window_manager_init), (gnome_window_manager_finalize), (gnome_window_manager_class_init), (gnome_window_manager_get_type): * gnome-window-manager.h: Lots of formatting fixes, change some of the boilerplate. * gnome-window-settings-2.0.pc.in: Since we're installing a library, go the whole way. Its good to make this easy to depend on for external window managers anyway, now that I think of it. * gnome-wm-manager.c: (gnome_wm_manager_init), (gnome_wm_manager_get_list), (gnome_wm_manager_set_current), (gnome_wm_manager_get_current), (gnome_wm_manager_change_wm_to_settings), (restart_label_update), (restart_dialog_raise), (restart_dialog_destroyed), (show_restart_dialog), (hide_restart_dialog), (init_session), (update_session), (init_callback), (restart_finalize), (restart_failure), (show_restart_info), (restart_finish), (restart_callback), (restart), (revert_callback), (cancel_callback): * gnome-wm-manager.h: Add code for doing the window manager switch to the library, snitched out of wm-properties. Its probably a little broken right now. * wm-exec.c: (wm_is_running), (find_gnome_wm_window), (find_wm_window_from_client), (window_has_wm_state), (descendent_has_wm_state), (find_wm_window_from_hunt), (find_wm_window), (start_timeout), (start_do), (kill_timeout), (wm_restart), (wm_guess_current): * wm-list.c: (is_blank), (wm_compare), (wm_free), (wm_check_present), (wm_copy), (wm_list_find), (wm_list_find_exec), (wm_list_find_files), (wm_list_read_dir), (wm_list_init), (wm_list_save), (wm_list_revert), (wm_list_add), (wm_list_delete), (wm_list_set_current), (wm_list_get_current), (wm_list_get_revert), (wm_read_from_xml), (wm_list_read_from_xml), (wm_write_to_xml), (wm_list_write_to_xml), (xml_read_bool), (xml_write_bool): * wm-properties.h: Take wm-switching code out of the capplet, move it here. (Jacob, I did a make dist and build the resulting tarball, hope things don't break for you this time ... )
331 lines
8.5 KiB
C
331 lines
8.5 KiB
C
/* -*- 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 {
|
|
GnomeDesktopItem *dentry;
|
|
gint retries;
|
|
WMResultFunc callback;
|
|
gpointer data;
|
|
};
|
|
|
|
gboolean
|
|
wm_is_running (void)
|
|
{
|
|
gboolean result;
|
|
guint old_mask;
|
|
XWindowAttributes attrs;
|
|
|
|
gdk_error_trap_push ();
|
|
|
|
XGetWindowAttributes (GDK_DISPLAY(), GDK_ROOT_WINDOW(), &attrs);
|
|
|
|
XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
|
|
SubstructureRedirectMask);
|
|
XSync (GDK_DISPLAY(), False);
|
|
if (gdk_error_trap_pop () == 0) {
|
|
result = FALSE;
|
|
XSelectInput (GDK_DISPLAY(), GDK_ROOT_WINDOW(),
|
|
attrs.your_event_mask);
|
|
} else
|
|
result = TRUE;
|
|
|
|
|
|
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;
|
|
GdkAtom cardinal_atom = gdk_atom_intern ("CARDINAL", FALSE);
|
|
|
|
gdk_error_trap_push ();
|
|
if (XGetWindowProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(),
|
|
gdk_x11_atom_to_xatom (gdk_atom_intern ("_WIN_SUPPORTING_WM_CHECK", FALSE)),
|
|
0, 1, False, gdk_x11_atom_to_xatom (cardinal_atom),
|
|
&r_type, &r_format,
|
|
&count, &bytes_remain, &prop) == Success && prop)
|
|
{
|
|
if (r_type == gdk_x11_atom_to_xatom (cardinal_atom) && r_format == 32 && count == 1)
|
|
{
|
|
Window n = *(long *)prop;
|
|
if (XGetWindowProperty(GDK_DISPLAY(), n,
|
|
gdk_x11_atom_to_xatom (gdk_atom_intern ("_WIN_SUPPORTING_WM_CHECK", FALSE)),
|
|
0, 1, False, gdk_x11_atom_to_xatom (cardinal_atom),
|
|
&r_type, &r_format, &count, &bytes_remain,
|
|
&prop2) == Success && prop)
|
|
{
|
|
if (r_type == gdk_x11_atom_to_xatom (cardinal_atom) && r_format == 32 && count == 1)
|
|
{
|
|
XFree(prop);
|
|
XFree(prop2);
|
|
gdk_error_trap_pop ();
|
|
return n;
|
|
}
|
|
XFree(prop2);
|
|
}
|
|
}
|
|
XFree(prop);
|
|
}
|
|
gdk_error_trap_pop ();
|
|
return None;
|
|
}
|
|
|
|
static Window
|
|
find_wm_window_from_client (GdkWindow *client)
|
|
{
|
|
Window window, frame, parent, root;
|
|
Window *children;
|
|
unsigned int nchildren;
|
|
gboolean needs_pop = TRUE;
|
|
|
|
if (!client)
|
|
return None;
|
|
|
|
frame = None;
|
|
window = GDK_WINDOW_XWINDOW (client);
|
|
|
|
gdk_error_trap_push ();
|
|
|
|
while (XQueryTree (GDK_DISPLAY(), window,
|
|
&root, &parent, &children, &nchildren))
|
|
{
|
|
if (gdk_error_trap_pop != 0)
|
|
{
|
|
needs_pop = FALSE;
|
|
break;
|
|
}
|
|
|
|
gdk_error_trap_push ();
|
|
|
|
if (children)
|
|
XFree(children);
|
|
|
|
if (window == root)
|
|
break;
|
|
|
|
if (root == parent) {
|
|
frame = window;
|
|
break;
|
|
}
|
|
window = parent;
|
|
}
|
|
|
|
if (needs_pop)
|
|
gdk_error_trap_pop ();
|
|
|
|
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_x11_atom_to_xatom (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;
|
|
gint i;
|
|
|
|
frame = None;
|
|
|
|
gdk_error_trap_push ();
|
|
|
|
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_trap_pop ();
|
|
|
|
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_item_unref (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_item_unref (info->dentry);
|
|
g_free (info);
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
start_do (RestartInfo *info)
|
|
{
|
|
gnome_desktop_item_launch (info->dentry, 0, 0, NULL);
|
|
|
|
info->retries = 10;
|
|
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_item_unref (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_item_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_item_unref (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;
|
|
}
|