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 \
session.c \
session.h \
stack.c \
stack.h \
theme.c \
theme.h \
uislave.c \

View File

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

View File

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

View File

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

View File

@ -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... */
}

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

View File

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

View File

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