summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrhp <rhp>2001-06-10 07:52:35 +0000
committerrhp <rhp>2001-06-10 07:52:35 +0000
commit2f29ba4f397a9ccd05a45e3010929d5c865245ec (patch)
treec678b2849efe4214ea3bcfef99477b9adf2eb246
parent7f55a132915f79b3e951511329cc575d4b5cb856 (diff)
downloadmutter-2f29ba4f397a9ccd05a45e3010929d5c865245ec.tar.gz
...
-rw-r--r--src/Makefile.am2
-rw-r--r--src/display.c6
-rw-r--r--src/display.h2
-rwxr-xr-xsrc/run-metacity.sh4
-rw-r--r--src/stack.c127
-rw-r--r--src/stack.h92
-rw-r--r--src/window.c1
-rw-r--r--src/window.h1
-rw-r--r--src/workspace.c3
9 files changed, 230 insertions, 8 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index b4faf06dd..5f3c9f393 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -57,6 +57,8 @@ metacity_SOURCES= \
screen.h \
session.c \
session.h \
+ stack.c \
+ stack.h \
theme.c \
theme.h \
uislave.c \
diff --git a/src/display.c b/src/display.c
index 2cf29e05b..c0b4bf21a 100644
--- a/src/display.c
+++ b/src/display.c
@@ -116,7 +116,9 @@ meta_display_open (const char *name)
"_NET_WM_WINDOW_TYPE_MENU",
"_NET_WM_WINDOW_TYPE_DIALOG",
"_NET_WM_WINDOW_TYPE_NORMAL",
- "_NET_WM_STATE_MODAL"
+ "_NET_WM_STATE_MODAL",
+ "_NET_CLIENT_LIST",
+ "_NET_CLIENT_LIST_STACKING"
};
Atom atoms[G_N_ELEMENTS(atom_names)];
@@ -181,6 +183,8 @@ meta_display_open (const char *name)
display->atom_net_wm_window_type_dialog = atoms[25];
display->atom_net_wm_window_type_normal = atoms[26];
display->atom_net_wm_state_modal = atoms[27];
+ display->atom_net_client_list = atoms[28];
+ display->atom_net_client_list_stacking = atoms[29];
screens = NULL;
i = 0;
diff --git a/src/display.h b/src/display.h
index 4421bd2e9..6016b10b7 100644
--- a/src/display.h
+++ b/src/display.h
@@ -74,6 +74,8 @@ struct _MetaDisplay
Atom atom_net_wm_window_type_dialog;
Atom atom_net_wm_window_type_normal;
Atom atom_net_wm_state_modal;
+ Atom atom_net_client_list;
+ Atom atom_net_client_list_stacking;
/* This is the actual window from focus events,
* not the one we last set
diff --git a/src/run-metacity.sh b/src/run-metacity.sh
index 798d711e0..24e0489f5 100755
--- a/src/run-metacity.sh
+++ b/src/run-metacity.sh
@@ -9,7 +9,7 @@ elif test -z "$DEBUG"; then
DEBUG=gdb
fi
-Xnest :1 -scrns $SCREENS -geometry 640x480 &
-DISPLAY=:1 xsetroot -solid royalblue3
+Xnest :1 -scrns $SCREENS -geometry 640x480 -bw 15 &
+usleep 50000
METACITY_UISLAVE_DIR=./uislave DISPLAY=:1 unst libtool --mode=execute $DEBUG ./metacity
killall Xnest
diff --git a/src/stack.c b/src/stack.c
index bf5a7236e..4999095d9 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -20,6 +20,10 @@
*/
#include "stack.h"
+#include "window.h"
+#include "errors.h"
+
+#include <X11/Xatom.h>
struct _MetaStackOp
{
@@ -63,6 +67,7 @@ void
meta_stack_free (MetaStack *stack)
{
GList *tmp;
+ int i;
g_array_free (stack->windows, TRUE);
@@ -251,6 +256,56 @@ compute_layer (MetaWindow *window)
window->layer = META_LAYER_NORMAL;
break;
}
+
+ meta_verbose ("Window %s on layer %d\n",
+ window->desc, window->layer);
+}
+
+static gboolean
+is_transient_for (MetaWindow *transient,
+ MetaWindow *parent)
+{
+ MetaWindow *w;
+
+ w = transient;
+ while (w != NULL)
+ {
+ if (w->xtransient_for == None)
+ return FALSE;
+
+ w = meta_display_lookup_x_window (w->display, w->xtransient_for);
+
+ if (w == transient)
+ return FALSE; /* Cycle detected */
+ else if (w == parent)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static int
+window_stack_cmp (MetaWindow *a,
+ MetaWindow *b)
+{
+ /* Less than means higher in stacking, i.e. at the
+ * front of the list.
+ */
+
+ if (a->xtransient_for != None &&
+ is_transient_for (a, b))
+ {
+ /* a is higher than b due to transient_for */
+ return -1;
+ }
+ else if (b->xtransient_for != None &&
+ is_transient_for (b, a))
+ {
+ /* b is higher than a due to transient_for */
+ return 1;
+ }
+ else
+ return 0; /* leave things as-is */
}
static void
@@ -265,11 +320,17 @@ meta_stack_sync_to_server (MetaStack *stack)
int n_actually_added;
int i, j;
int old_size;
+ GArray *stacked;
/* Bail out if frozen */
if (stack->freeze_count > 0)
return;
+ if (stack->pending == NULL)
+ return;
+
+ meta_verbose ("Syncing window stack to server\n");
+
/* Here comes the fun - figure out all the stacking.
* We make no pretense of efficiency.
* a) replay all the pending operations
@@ -304,7 +365,7 @@ meta_stack_sync_to_server (MetaStack *stack)
tmp = tmp->next;
}
- old_size = stack->window->len;
+ old_size = stack->windows->len;
g_array_set_size (stack->windows,
old_size + n_actually_added);
@@ -447,25 +508,81 @@ meta_stack_sync_to_server (MetaStack *stack)
stack->pending = NULL;
stack->n_added = 0;
-
/* Sort the layer lists */
i = 0;
while (i < META_LAYER_LAST)
{
if (needs_sort[i])
{
-
-
+ stack->layers[i] =
+ g_list_sort (stack->layers[i],
+ (GCompareFunc) window_stack_cmp);
}
++i;
}
/* Create stacked xwindow array */
+ stacked = g_array_new (FALSE, FALSE, sizeof (Window));
+ i = 0;
+ while (i < META_LAYER_LAST)
+ {
+ if (needs_sort[i])
+ {
+ stack->layers[i] =
+ g_list_sort (stack->layers[i],
+ (GCompareFunc) window_stack_cmp);
+ }
+
+ tmp = stack->layers[i];
+ while (tmp != NULL)
+ {
+ MetaWindow *w = tmp->data;
+
+ g_array_append_val (stacked, w->xwindow);
+
+ tmp = tmp->next;
+ }
+
+ ++i;
+ }
+
+ /* All windows should be in some stacking order */
+ if (stacked->len != stack->windows->len)
+ meta_bug ("%d windows stacked, %d windows exist in stack\n",
+ stacked->len, stack->windows->len);
/* Sync to server */
+
+ meta_error_trap_push (stack->screen->display);
+ XRestackWindows (stack->screen->display->xdisplay,
+ (Window *) stacked->data,
+ stacked->len);
+ meta_error_trap_pop (stack->screen->display);
+ /* on error, a window was destroyed; it should eventually
+ * get removed from the stacking list when we unmanage it
+ * and we'll fix stacking at that time.
+ */
/* Sync _NET_CLIENT_LIST and _NET_CLIENT_LIST_STACKING */
-
+
+ XChangeProperty (stack->screen->display->xdisplay,
+ stack->screen->xroot,
+ stack->screen->display->atom_net_client_list,
+ XA_ATOM,
+ 32, PropModeReplace,
+ stack->windows->data,
+ stack->windows->len);
+ XChangeProperty (stack->screen->display->xdisplay,
+ stack->screen->xroot,
+ stack->screen->display->atom_net_client_list_stacking,
+ XA_ATOM,
+ 32, PropModeReplace,
+ stacked->data,
+ stacked->len);
+
+ g_array_free (stacked, TRUE);
+
+ /* That was scary... */
}
diff --git a/src/stack.h b/src/stack.h
new file mode 100644
index 000000000..0f4c7b52d
--- /dev/null
+++ b/src/stack.h
@@ -0,0 +1,92 @@
+/* Metacity Window Stack */
+
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ *
+ * 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.
+ */
+
+#ifndef META_STACK_H
+#define META_STACK_H
+
+#include "screen.h"
+
+/* Type of last-queued stacking operation, hung off of MetaWindow
+ * but an opaque type used only in stack.c
+ */
+typedef struct _MetaStackOp MetaStackOp;
+
+/* These MUST be in the order of stacking */
+typedef enum
+{
+ META_LAYER_DESKTOP = 0,
+ META_LAYER_BOTTOM = 1,
+ META_LAYER_NORMAL = 2,
+ META_LAYER_TOP = 3,
+ META_LAYER_DOCK = 4,
+ META_LAYER_LAST = 5
+} MetaStackLayer;
+
+struct _MetaStack
+{
+ MetaScreen *screen;
+
+ /* All windows that we manage, in mapping order,
+ * for _NET_CLIENT_LIST
+ */
+ GArray *windows;
+
+ /* List of MetaWindow* in each layer */
+ GList *layers[META_LAYER_LAST];
+
+ /* List of MetaStackOp, most recent op
+ * first in list.
+ */
+ GList *pending;
+
+ int freeze_count;
+
+ int n_added;
+};
+
+MetaStack *meta_stack_new (MetaScreen *screen);
+void meta_stack_free (MetaStack *stack);
+void meta_stack_add (MetaStack *stack,
+ MetaWindow *window);
+void meta_stack_remove (MetaStack *stack,
+ MetaWindow *window);
+/* re-read layer-related hints */
+void meta_stack_update_layer (MetaStack *stack,
+ MetaWindow *window);
+/* reconsider transient_for */
+void meta_stack_update_transient (MetaStack *stack,
+ MetaWindow *window);
+
+/* raise/lower within a layer */
+void meta_stack_raise (MetaStack *stack,
+ MetaWindow *window);
+void meta_stack_lower (MetaStack *stack,
+ MetaWindow *window);
+
+/* On thaw, process pending and sync to server */
+void meta_stack_freeze (MetaStack *stack);
+void meta_stack_thaw (MetaStack *stack);
+
+#endif
+
+
+
+
diff --git a/src/window.c b/src/window.c
index 3da2ba06a..4ae30e3a7 100644
--- a/src/window.c
+++ b/src/window.c
@@ -53,6 +53,7 @@ static int update_net_wm_type (MetaWindow *window);
static void recalc_window_type (MetaWindow *window);
static int set_wm_state (MetaWindow *window,
int state);
+static int set_net_wm_state (MetaWindow *window);
static void send_configure_notify (MetaWindow *window);
static gboolean process_configure_request (MetaWindow *window,
int x,
diff --git a/src/window.h b/src/window.h
index 8c7ed0708..cd44a960a 100644
--- a/src/window.h
+++ b/src/window.h
@@ -24,6 +24,7 @@
#include "screen.h"
#include "util.h"
+#include "stack.h"
#include <X11/Xutil.h>
typedef enum
diff --git a/src/workspace.c b/src/workspace.c
index f7e5188c1..8d4415a0c 100644
--- a/src/workspace.c
+++ b/src/workspace.c
@@ -226,3 +226,6 @@ set_active_space_hint (MetaScreen *screen)
32, PropModeReplace, (guchar*) data, 1);
return meta_error_trap_pop (screen->display);
}
+
+
+