2002-05-10 Seth Nickell <snickell@stanford.edu>
* .cvsignore: * Makefile.am: * gnome-window-properties.c: (wm_selection_changed), (wm_widget_clear), (wm_widget_new), (wm_widget_add_wm), (response_cb), (state_changed), (restart_label_update), (restart_dialog_raise), (restart_dialog_destroyed), (show_restart_dialog), (hide_restart_dialog), (update_session), (init_session), (update_gui), (init_callback), (restart_finalize), (restart_failure), (show_restart_info), (restart_finish), (restart_callback), (restart), (revert_callback), (cancel_callback), (apply_wm), (create_dialog), (main): * gnome-window-properties.glade: * window-capplet.png: * window-properties.desktop.in: * 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:
This commit is contained in:
parent
00c628d44b
commit
ad15ad16c9
10 changed files with 2118 additions and 0 deletions
331
capplets/windows/wm-exec.c
Normal file
331
capplets/windows/wm-exec.c
Normal file
|
@ -0,0 +1,331 @@
|
|||
/* -*- 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue