This commit is contained in:
rhp 2001-06-10 07:52:35 +00:00
parent 7f55a13291
commit 2f29ba4f39
9 changed files with 230 additions and 8 deletions

View File

@ -57,6 +57,8 @@ metacity_SOURCES= \
screen.h \ screen.h \
session.c \ session.c \
session.h \ session.h \
stack.c \
stack.h \
theme.c \ theme.c \
theme.h \ theme.h \
uislave.c \ uislave.c \

View File

@ -116,7 +116,9 @@ meta_display_open (const char *name)
"_NET_WM_WINDOW_TYPE_MENU", "_NET_WM_WINDOW_TYPE_MENU",
"_NET_WM_WINDOW_TYPE_DIALOG", "_NET_WM_WINDOW_TYPE_DIALOG",
"_NET_WM_WINDOW_TYPE_NORMAL", "_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)]; 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_dialog = atoms[25];
display->atom_net_wm_window_type_normal = atoms[26]; display->atom_net_wm_window_type_normal = atoms[26];
display->atom_net_wm_state_modal = atoms[27]; 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; screens = NULL;
i = 0; i = 0;

View File

@ -74,6 +74,8 @@ struct _MetaDisplay
Atom atom_net_wm_window_type_dialog; Atom atom_net_wm_window_type_dialog;
Atom atom_net_wm_window_type_normal; Atom atom_net_wm_window_type_normal;
Atom atom_net_wm_state_modal; 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, /* This is the actual window from focus events,
* not the one we last set * not the one we last set

View File

@ -9,7 +9,7 @@ elif test -z "$DEBUG"; then
DEBUG=gdb DEBUG=gdb
fi fi
Xnest :1 -scrns $SCREENS -geometry 640x480 & Xnest :1 -scrns $SCREENS -geometry 640x480 -bw 15 &
DISPLAY=:1 xsetroot -solid royalblue3 usleep 50000
METACITY_UISLAVE_DIR=./uislave DISPLAY=:1 unst libtool --mode=execute $DEBUG ./metacity METACITY_UISLAVE_DIR=./uislave DISPLAY=:1 unst libtool --mode=execute $DEBUG ./metacity
killall Xnest killall Xnest

View File

@ -20,6 +20,10 @@
*/ */
#include "stack.h" #include "stack.h"
#include "window.h"
#include "errors.h"
#include <X11/Xatom.h>
struct _MetaStackOp struct _MetaStackOp
{ {
@ -63,6 +67,7 @@ void
meta_stack_free (MetaStack *stack) meta_stack_free (MetaStack *stack)
{ {
GList *tmp; GList *tmp;
int i;
g_array_free (stack->windows, TRUE); g_array_free (stack->windows, TRUE);
@ -251,6 +256,56 @@ compute_layer (MetaWindow *window)
window->layer = META_LAYER_NORMAL; window->layer = META_LAYER_NORMAL;
break; 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 static void
@ -265,11 +320,17 @@ meta_stack_sync_to_server (MetaStack *stack)
int n_actually_added; int n_actually_added;
int i, j; int i, j;
int old_size; int old_size;
GArray *stacked;
/* Bail out if frozen */ /* Bail out if frozen */
if (stack->freeze_count > 0) if (stack->freeze_count > 0)
return; return;
if (stack->pending == NULL)
return;
meta_verbose ("Syncing window stack to server\n");
/* Here comes the fun - figure out all the stacking. /* Here comes the fun - figure out all the stacking.
* We make no pretense of efficiency. * We make no pretense of efficiency.
* a) replay all the pending operations * a) replay all the pending operations
@ -304,7 +365,7 @@ meta_stack_sync_to_server (MetaStack *stack)
tmp = tmp->next; tmp = tmp->next;
} }
old_size = stack->window->len; old_size = stack->windows->len;
g_array_set_size (stack->windows, g_array_set_size (stack->windows,
old_size + n_actually_added); old_size + n_actually_added);
@ -447,25 +508,81 @@ meta_stack_sync_to_server (MetaStack *stack)
stack->pending = NULL; stack->pending = NULL;
stack->n_added = 0; stack->n_added = 0;
/* Sort the layer lists */ /* Sort the layer lists */
i = 0; i = 0;
while (i < META_LAYER_LAST) while (i < META_LAYER_LAST)
{ {
if (needs_sort[i]) if (needs_sort[i])
{ {
stack->layers[i] =
g_list_sort (stack->layers[i],
(GCompareFunc) window_stack_cmp);
} }
++i; ++i;
} }
/* Create stacked xwindow array */ /* 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 */ /* 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 */ /* 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... */
} }

92
src/stack.h Normal file
View File

@ -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

View File

@ -53,6 +53,7 @@ static int update_net_wm_type (MetaWindow *window);
static void recalc_window_type (MetaWindow *window); static void recalc_window_type (MetaWindow *window);
static int set_wm_state (MetaWindow *window, static int set_wm_state (MetaWindow *window,
int state); int state);
static int set_net_wm_state (MetaWindow *window);
static void send_configure_notify (MetaWindow *window); static void send_configure_notify (MetaWindow *window);
static gboolean process_configure_request (MetaWindow *window, static gboolean process_configure_request (MetaWindow *window,
int x, int x,

View File

@ -24,6 +24,7 @@
#include "screen.h" #include "screen.h"
#include "util.h" #include "util.h"
#include "stack.h"
#include <X11/Xutil.h> #include <X11/Xutil.h>
typedef enum typedef enum

View File

@ -226,3 +226,6 @@ set_active_space_hint (MetaScreen *screen)
32, PropModeReplace, (guchar*) data, 1); 32, PropModeReplace, (guchar*) data, 1);
return meta_error_trap_pop (screen->display); return meta_error_trap_pop (screen->display);
} }