Clients Menus and Slits are all 'ObWindow's now.
Stacking is done with ObWindows. Slits add themselves to the stacking order, as do clients of course. Added some macros for adding/removing to the stacking order.
This commit is contained in:
parent
506122a110
commit
58cfbb7f84
17 changed files with 244 additions and 169 deletions
|
@ -26,13 +26,13 @@ openbox3_SOURCES=parse.tab.c parse.lex.c action.c client.c config.c \
|
|||
extensions.c focus.c frame.c grab.c menu.c menu_render.c \
|
||||
openbox.c framerender.c parse.c plugin.c prop.c screen.c \
|
||||
stacking.c dispatch.c event.c group.c timer.c xerror.c \
|
||||
moveresize.c startup.c popup.c slit.c
|
||||
moveresize.c startup.c popup.c slit.c window.c
|
||||
|
||||
noinst_HEADERS=action.h client.h config.h dispatch.h event.h extensions.h \
|
||||
focus.h frame.h framerender.h geom.h gettext.h grab.h group.h \
|
||||
menu.h openbox.h parse.h parse.tab.h plugin.h prop.h screen.h \
|
||||
stacking.h timer.h xerror.h moveresize.h startup.h popup.h \
|
||||
slit.h
|
||||
slit.h window.h
|
||||
|
||||
# kill the implicit .c.y rule
|
||||
%.c: %.y
|
||||
|
|
|
@ -222,14 +222,14 @@ void action_focusraise(union ActionData *data)
|
|||
{
|
||||
if (data->client.c) {
|
||||
client_focus(data->client.c);
|
||||
stacking_raise(data->client.c);
|
||||
stacking_raise(CLIENT_AS_WINDOW(data->client.c));
|
||||
}
|
||||
}
|
||||
|
||||
void action_raise(union ActionData *data)
|
||||
{
|
||||
if (data->client.c)
|
||||
stacking_raise(data->client.c);
|
||||
stacking_raise(CLIENT_AS_WINDOW(data->client.c));
|
||||
}
|
||||
|
||||
void action_unshaderaise(union ActionData *data)
|
||||
|
@ -238,7 +238,7 @@ void action_unshaderaise(union ActionData *data)
|
|||
if (data->client.c->shaded)
|
||||
client_shade(data->client.c, FALSE);
|
||||
else
|
||||
stacking_raise(data->client.c);
|
||||
stacking_raise(CLIENT_AS_WINDOW(data->client.c));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,7 +246,7 @@ void action_shadelower(union ActionData *data)
|
|||
{
|
||||
if (data->client.c) {
|
||||
if (data->client.c->shaded)
|
||||
stacking_lower(data->client.c);
|
||||
stacking_lower(CLIENT_AS_WINDOW(data->client.c));
|
||||
else
|
||||
client_shade(data->client.c, TRUE);
|
||||
}
|
||||
|
@ -255,7 +255,7 @@ void action_shadelower(union ActionData *data)
|
|||
void action_lower(union ActionData *data)
|
||||
{
|
||||
if (data->client.c)
|
||||
stacking_lower(data->client.c);
|
||||
stacking_lower(CLIENT_AS_WINDOW(data->client.c));
|
||||
}
|
||||
|
||||
void action_close(union ActionData *data)
|
||||
|
|
|
@ -158,7 +158,7 @@ void client_manage_all()
|
|||
|
||||
w = startup_stack_order[i-1];
|
||||
c = g_hash_table_lookup(client_map, &w);
|
||||
if (c) stacking_lower(c);
|
||||
if (c) stacking_lower(CLIENT_AS_WINDOW(c));
|
||||
}
|
||||
g_free(startup_stack_order);
|
||||
startup_stack_order = NULL;
|
||||
|
@ -222,6 +222,7 @@ void client_manage(Window window)
|
|||
/* create the Client struct, and populate it from the hints on the
|
||||
window */
|
||||
self = g_new(Client, 1);
|
||||
self->obwin.type = Window_Client;
|
||||
self->window = window;
|
||||
client_get_all(self);
|
||||
|
||||
|
@ -242,14 +243,14 @@ void client_manage(Window window)
|
|||
grab_server(FALSE);
|
||||
|
||||
client_list = g_list_append(client_list, self);
|
||||
stacking_list = g_list_append(stacking_list, self);
|
||||
stacking_add(self);
|
||||
g_assert(!g_hash_table_lookup(client_map, &self->window));
|
||||
g_hash_table_insert(client_map, &self->window, self);
|
||||
|
||||
/* update the focus lists */
|
||||
focus_order_add_new(self);
|
||||
|
||||
stacking_raise(self);
|
||||
stacking_raise(CLIENT_AS_WINDOW(self));
|
||||
|
||||
screen_update_struts();
|
||||
|
||||
|
@ -336,7 +337,7 @@ void client_unmanage(Client *self)
|
|||
frame_hide(self->frame);
|
||||
|
||||
client_list = g_list_remove(client_list, self);
|
||||
stacking_list = g_list_remove(stacking_list, self);
|
||||
stacking_remove(self);
|
||||
g_hash_table_remove(client_map, &self->window);
|
||||
|
||||
/* update the focus lists */
|
||||
|
@ -1455,8 +1456,7 @@ static StackLayer calc_layer(Client *self)
|
|||
{
|
||||
StackLayer l;
|
||||
|
||||
if (self->iconic) l = Layer_Icon;
|
||||
else if (self->fullscreen) l = Layer_Fullscreen;
|
||||
if (self->fullscreen) l = Layer_Fullscreen;
|
||||
else if (self->type == Type_Desktop) l = Layer_Desktop;
|
||||
else if (self->type == Type_Dock) {
|
||||
if (!self->below) l = Layer_Top;
|
||||
|
@ -1484,7 +1484,7 @@ static void calc_recursive(Client *self, Client *orig, StackLayer l,
|
|||
|
||||
if (!raised && l != old)
|
||||
if (orig->frame) /* only restack if the original window is managed */
|
||||
stacking_raise(self);
|
||||
stacking_raise(CLIENT_AS_WINDOW(self));
|
||||
}
|
||||
|
||||
void client_calc_layer(Client *self)
|
||||
|
@ -2028,7 +2028,7 @@ void client_set_desktop(Client *self, guint target, gboolean donthide)
|
|||
client_showhide(self);
|
||||
/* raise if it was not already on the desktop */
|
||||
if (old != DESKTOP_ALL)
|
||||
stacking_raise(self);
|
||||
stacking_raise(CLIENT_AS_WINDOW(self));
|
||||
screen_update_struts();
|
||||
|
||||
/* add to the new desktop(s) */
|
||||
|
@ -2310,7 +2310,7 @@ void client_activate(Client *self)
|
|||
if (self->shaded)
|
||||
client_shade(self, FALSE);
|
||||
client_focus(self);
|
||||
stacking_raise(self);
|
||||
stacking_raise(CLIENT_AS_WINDOW(self));
|
||||
}
|
||||
|
||||
gboolean client_focused(Client *self)
|
||||
|
|
|
@ -110,6 +110,8 @@ typedef enum {
|
|||
|
||||
|
||||
typedef struct Client {
|
||||
ObWindow obwin;
|
||||
|
||||
Window window;
|
||||
|
||||
/*! The window's decorations. NULL while the window is being managed! */
|
||||
|
|
|
@ -13,6 +13,8 @@ extern gboolean config_focus_last;
|
|||
extern gboolean config_focus_last_on_desktop;
|
||||
/*! Show a popup dialog while cycling focus */
|
||||
extern gboolean config_focus_popup;
|
||||
/*! The number of slits to create */
|
||||
extern int config_slit_number;
|
||||
|
||||
/* The name of the theme */
|
||||
char *config_theme;
|
||||
|
|
|
@ -916,6 +916,8 @@ static void event_handle_menu(Menu *menu, XEvent *e)
|
|||
static void event_handle_slit(Slit *s, XEvent *e)
|
||||
{
|
||||
switch (e->type) {
|
||||
case ButtonPress:
|
||||
stacking_raise(SLIT_AS_WINDOW(s));
|
||||
case EnterNotify:
|
||||
slit_hide(s, FALSE);
|
||||
break;
|
||||
|
|
|
@ -40,8 +40,7 @@ void focus_startup()
|
|||
-100, -100, 1, 1, 0,
|
||||
CopyFromParent, InputOutput, CopyFromParent,
|
||||
CWOverrideRedirect, &attrib);
|
||||
XMapWindow(ob_display, focus_backup);
|
||||
stacking_raise_internal(focus_backup);
|
||||
XMapRaised(ob_display, focus_backup);
|
||||
|
||||
/* start with nothing focused */
|
||||
focus_set_client(NULL);
|
||||
|
|
|
@ -154,6 +154,7 @@ Menu *menu_new_full(char *label, char *name, Menu *parent,
|
|||
Menu *self;
|
||||
|
||||
self = g_new0(Menu, 1);
|
||||
self->obwin.type = Window_Menu;
|
||||
self->label = g_strdup(label);
|
||||
self->name = g_strdup(name);
|
||||
self->parent = parent;
|
||||
|
@ -350,7 +351,9 @@ void menu_control_show(Menu *self, int x, int y, Client *client) {
|
|||
MIN(y, screen_physical_size.height - self->size.height));
|
||||
|
||||
if (!self->shown) {
|
||||
stacking_raise_internal(self->frame);
|
||||
/* XXX gotta add to the stacking list first!
|
||||
stacking_raise(MENU_AS_WINDOW(self));
|
||||
*/
|
||||
XMapWindow(ob_display, self->frame);
|
||||
self->shown = TRUE;
|
||||
} else if (self->shown && self->open_submenu) {
|
||||
|
|
|
@ -18,6 +18,8 @@ typedef void(*menu_controller_mouseover)(struct MenuEntry *self,
|
|||
gboolean enter);
|
||||
|
||||
typedef struct Menu {
|
||||
ObWindow obwin;
|
||||
|
||||
char *label;
|
||||
char *name;
|
||||
|
||||
|
|
|
@ -186,7 +186,6 @@ int main(int argc, char **argv)
|
|||
|
||||
menu_startup();
|
||||
frame_startup();
|
||||
stacking_startup();
|
||||
moveresize_startup();
|
||||
focus_startup();
|
||||
screen_startup();
|
||||
|
@ -215,7 +214,6 @@ int main(int argc, char **argv)
|
|||
screen_shutdown();
|
||||
focus_shutdown();
|
||||
moveresize_shutdown();
|
||||
stacking_shutdown();
|
||||
frame_shutdown();
|
||||
menu_shutdown();
|
||||
grab_shutdown();
|
||||
|
|
|
@ -1,38 +1,13 @@
|
|||
#include "slit.h"
|
||||
#include "screen.h"
|
||||
#include "grab.h"
|
||||
#include "timer.h"
|
||||
#include "openbox.h"
|
||||
#include "render/theme.h"
|
||||
#include "render/render.h"
|
||||
|
||||
#define SLIT_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
|
||||
EnterWindowMask | LeaveWindowMask)
|
||||
#define SLITAPP_EVENT_MASK (StructureNotifyMask)
|
||||
|
||||
struct Slit {
|
||||
Window frame;
|
||||
|
||||
/* user-requested position stuff */
|
||||
SlitPosition pos;
|
||||
int gravity;
|
||||
int user_x, user_y;
|
||||
|
||||
/* actual position (when not auto-hidden) */
|
||||
int x, y;
|
||||
int w, h;
|
||||
|
||||
gboolean horz;
|
||||
gboolean hide;
|
||||
gboolean hidden;
|
||||
|
||||
Appearance *a_frame;
|
||||
|
||||
Timer *hide_timer;
|
||||
|
||||
GList *slit_apps;
|
||||
};
|
||||
|
||||
GHashTable *slit_map = NULL;
|
||||
GHashTable *slit_app_map = NULL;
|
||||
|
||||
|
@ -53,12 +28,14 @@ void slit_startup()
|
|||
|
||||
nslits = 1;
|
||||
slit = g_new0(struct Slit, nslits);
|
||||
slit->obwin.type = Window_Slit;
|
||||
|
||||
for (i = 0; i < nslits; ++i) {
|
||||
slit[i].horz = FALSE;
|
||||
slit[i].hide = FALSE;
|
||||
slit[i].hidden = TRUE;
|
||||
slit[i].pos = SlitPos_TopRight;
|
||||
slit[i].layer = Layer_Top;
|
||||
|
||||
attrib.event_mask = SLIT_EVENT_MASK;
|
||||
attrib.override_redirect = True;
|
||||
|
@ -71,6 +48,8 @@ void slit_startup()
|
|||
XSetWindowBorderWidth(ob_display, slit[i].frame, theme_bwidth);
|
||||
|
||||
g_hash_table_insert(slit_map, &slit[i].frame, &slit[i]);
|
||||
stacking_add(&slit[i]);
|
||||
stacking_raise(SLIT_AS_WINDOW(&slit[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,6 +61,7 @@ void slit_shutdown()
|
|||
XDestroyWindow(ob_display, slit[i].frame);
|
||||
appearance_free(slit[i].a_frame);
|
||||
g_hash_table_remove(slit_map, &slit[i].frame);
|
||||
stacking_remove(&slit[i]);
|
||||
}
|
||||
g_hash_table_destroy(slit_app_map);
|
||||
g_hash_table_destroy(slit_map);
|
||||
|
|
|
@ -1,24 +1,15 @@
|
|||
#ifndef __slit_h
|
||||
#define __slit_h
|
||||
|
||||
#include "timer.h"
|
||||
#include "render/render.h"
|
||||
#include "window.h"
|
||||
#include "stacking.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
typedef struct Slit Slit;
|
||||
|
||||
typedef struct SlitApp {
|
||||
int ignore_unmaps;
|
||||
|
||||
Slit *slit;
|
||||
Window icon_win;
|
||||
Window win;
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
} SlitApp;
|
||||
|
||||
typedef enum {
|
||||
SlitPos_Floating,
|
||||
SlitPos_TopLeft,
|
||||
|
@ -31,6 +22,44 @@ typedef enum {
|
|||
SlitPos_Left
|
||||
} SlitPosition;
|
||||
|
||||
typedef struct Slit {
|
||||
ObWindow obwin;
|
||||
|
||||
Window frame;
|
||||
StackLayer layer;
|
||||
|
||||
/* user-requested position stuff */
|
||||
SlitPosition pos;
|
||||
int gravity;
|
||||
int user_x, user_y;
|
||||
|
||||
/* actual position (when not auto-hidden) */
|
||||
int x, y;
|
||||
int w, h;
|
||||
|
||||
gboolean horz;
|
||||
gboolean hide;
|
||||
gboolean hidden;
|
||||
|
||||
Appearance *a_frame;
|
||||
|
||||
Timer *hide_timer;
|
||||
|
||||
GList *slit_apps;
|
||||
} Slit;
|
||||
|
||||
typedef struct SlitApp {
|
||||
int ignore_unmaps;
|
||||
|
||||
Slit *slit;
|
||||
Window icon_win;
|
||||
Window win;
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
} SlitApp;
|
||||
|
||||
extern GHashTable *slit_map;
|
||||
extern GHashTable *slit_app_map;
|
||||
|
||||
|
|
|
@ -4,28 +4,11 @@
|
|||
#include "client.h"
|
||||
#include "group.h"
|
||||
#include "frame.h"
|
||||
#include "window.h"
|
||||
#include <glib.h>
|
||||
|
||||
GList *stacking_list = NULL;
|
||||
|
||||
static Window top_window = None;
|
||||
|
||||
void stacking_startup()
|
||||
{
|
||||
XSetWindowAttributes attrib;
|
||||
attrib.override_redirect = TRUE;
|
||||
top_window = XCreateWindow(ob_display, ob_root,
|
||||
-100, -100, 1, 1, 0,
|
||||
CopyFromParent, InputOutput, CopyFromParent,
|
||||
CWOverrideRedirect, &attrib);
|
||||
XMapWindow(ob_display, top_window);
|
||||
}
|
||||
|
||||
void stacking_shutdown()
|
||||
{
|
||||
XDestroyWindow(ob_display, top_window);
|
||||
}
|
||||
|
||||
void stacking_set_list()
|
||||
{
|
||||
Window *windows, *win_it;
|
||||
|
@ -44,7 +27,8 @@ void stacking_set_list()
|
|||
win_it = windows;
|
||||
for (it = g_list_last(stacking_list); it != NULL;
|
||||
it = it->prev, ++win_it)
|
||||
*win_it = ((Client*)it->data)->window;
|
||||
if (WINDOW_IS_CLIENT(it->data))
|
||||
*win_it = window_top(it->data);
|
||||
} else
|
||||
windows = NULL;
|
||||
|
||||
|
@ -67,7 +51,7 @@ static GList *find_lowest_transient(Client *c)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void raise_recursive(Client *client)
|
||||
static void raise_recursive(ObWindow *window)
|
||||
{
|
||||
Window wins[2]; /* only ever restack 2 windows. */
|
||||
GList *it, *low;
|
||||
|
@ -75,21 +59,27 @@ static void raise_recursive(Client *client)
|
|||
|
||||
g_assert(stacking_list != NULL); /* this would be bad */
|
||||
|
||||
/* remove the client before looking so we can't run into ourselves and our
|
||||
/* remove the window before looking so we can't run into ourselves and our
|
||||
transients can't either. */
|
||||
stacking_list = g_list_remove(stacking_list, client);
|
||||
stacking_list = g_list_remove(stacking_list, window);
|
||||
|
||||
/* raise transients first */
|
||||
for (sit = client->transients; sit; sit = sit->next)
|
||||
raise_recursive(sit->data);
|
||||
if (WINDOW_IS_CLIENT(window)) {
|
||||
Client *client = WINDOW_AS_CLIENT(window);
|
||||
for (sit = client->transients; sit; sit = sit->next)
|
||||
raise_recursive(sit->data);
|
||||
}
|
||||
|
||||
/* find 'it' where it is the positiion in the stacking order where
|
||||
'client' will be inserted *before* */
|
||||
'window' will be inserted *before* */
|
||||
|
||||
low = find_lowest_transient(client);
|
||||
if (WINDOW_IS_CLIENT(window))
|
||||
low = find_lowest_transient(WINDOW_AS_CLIENT(window));
|
||||
else
|
||||
low = NULL;
|
||||
/* the stacking list is from highest to lowest */
|
||||
for (it = g_list_last(stacking_list); it; it = it->prev) {
|
||||
if (it == low || client->layer < ((Client*)it->data)->layer) {
|
||||
if (it == low || window_layer(window) < window_layer(it->data)) {
|
||||
it = it->next;
|
||||
break;
|
||||
}
|
||||
|
@ -104,110 +94,112 @@ static void raise_recursive(Client *client)
|
|||
if (it == stacking_list)
|
||||
wins[0] = focus_backup;
|
||||
else if (it != NULL)
|
||||
wins[0] = ((Client*)it->prev->data)->frame->window;
|
||||
wins[0] = window_top(it->prev->data);
|
||||
else
|
||||
wins[0] = ((Client*)g_list_last(stacking_list)->data)->frame->window;
|
||||
wins[1] = client->frame->window;
|
||||
wins[0] = window_top(g_list_last(stacking_list)->data);
|
||||
wins[1] = window_top(window);
|
||||
|
||||
stacking_list = g_list_insert_before(stacking_list, it, client);
|
||||
stacking_list = g_list_insert_before(stacking_list, it, window);
|
||||
|
||||
XRestackWindows(ob_display, wins, 2);
|
||||
}
|
||||
|
||||
void stacking_raise(Client *client)
|
||||
void stacking_raise(ObWindow *window)
|
||||
{
|
||||
g_assert(stacking_list != NULL); /* this would be bad */
|
||||
|
||||
/* move up the transient chain as far as possible first */
|
||||
while (client->transient_for) {
|
||||
if (client->transient_for != TRAN_GROUP) {
|
||||
client = client->transient_for;
|
||||
} else {
|
||||
GSList *it;
|
||||
if (WINDOW_IS_CLIENT(window)) {
|
||||
Client *client = WINDOW_AS_CLIENT(window);
|
||||
/* move up the transient chain as far as possible first */
|
||||
while (client->transient_for) {
|
||||
if (client->transient_for != TRAN_GROUP) {
|
||||
client = client->transient_for;
|
||||
} else {
|
||||
GSList *it;
|
||||
|
||||
/* the check for TRAN_GROUP is to prevent an infinate loop with
|
||||
2 transients of the same group at the head of the group's
|
||||
members list */
|
||||
for (it = client->group->members; it; it = it->next) {
|
||||
Client *c = it->data;
|
||||
/* the check for TRAN_GROUP is to prevent an infinate loop with
|
||||
2 transients of the same group at the head of the group's
|
||||
members list */
|
||||
for (it = client->group->members; it; it = it->next) {
|
||||
Client *c = it->data;
|
||||
|
||||
if (c != client && c->transient_for != TRAN_GROUP) {
|
||||
client = it->data;
|
||||
break;
|
||||
if (c != client && c->transient_for != TRAN_GROUP) {
|
||||
client = it->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (it == NULL) break;
|
||||
}
|
||||
if (it == NULL) break;
|
||||
}
|
||||
window = CLIENT_AS_WINDOW(client);
|
||||
}
|
||||
|
||||
raise_recursive(client);
|
||||
raise_recursive(window);
|
||||
|
||||
stacking_set_list();
|
||||
}
|
||||
|
||||
static void lower_recursive(Client *client, Client *above)
|
||||
static void lower_recursive(ObWindow *window, ObWindow *above)
|
||||
{
|
||||
Window wins[2]; /* only ever restack 2 windows. */
|
||||
GList *it;
|
||||
GSList *sit;
|
||||
|
||||
/* find 'it' where 'it' is the position in the stacking_list where the
|
||||
'client' will be placed *after* */
|
||||
'window' will be placed *after* */
|
||||
|
||||
for (it = g_list_last(stacking_list); it != stacking_list; it = it->prev)
|
||||
if (client->layer <= ((Client*)it->data)->layer && it->data != above)
|
||||
if (window_layer(window) <= window_layer(it->data) &&
|
||||
it->data != above)
|
||||
break;
|
||||
|
||||
if (it->data != client) { /* not already the bottom */
|
||||
wins[0] = ((Client*)it->data)->frame->window;
|
||||
wins[1] = client->frame->window;
|
||||
if (it->data != window) { /* not already the bottom */
|
||||
wins[0] = window_top(it->data);
|
||||
wins[1] = window_top(window);
|
||||
|
||||
stacking_list = g_list_remove(stacking_list, client);
|
||||
stacking_list = g_list_insert_before(stacking_list, it->next, client);
|
||||
stacking_list = g_list_remove(stacking_list, window);
|
||||
stacking_list = g_list_insert_before(stacking_list, it->next, window);
|
||||
XRestackWindows(ob_display, wins, 2);
|
||||
}
|
||||
|
||||
for (sit = client->transients; sit; sit = sit->next)
|
||||
lower_recursive(sit->data, client);
|
||||
if (WINDOW_IS_CLIENT(window)) {
|
||||
Client *client = WINDOW_AS_CLIENT(window);
|
||||
for (sit = client->transients; sit; sit = sit->next)
|
||||
lower_recursive(CLIENT_AS_WINDOW(sit->data), window);
|
||||
}
|
||||
}
|
||||
|
||||
void stacking_lower(Client *client)
|
||||
void stacking_lower(ObWindow *window)
|
||||
{
|
||||
g_assert(stacking_list != NULL); /* this would be bad */
|
||||
|
||||
/* move up the transient chain as far as possible first */
|
||||
while (client->transient_for) {
|
||||
if (client->transient_for != TRAN_GROUP) {
|
||||
client = client->transient_for;
|
||||
} else {
|
||||
GSList *it;
|
||||
if (WINDOW_IS_CLIENT(window)) {
|
||||
Client *client = WINDOW_AS_CLIENT(window);
|
||||
/* move up the transient chain as far as possible first */
|
||||
while (client->transient_for) {
|
||||
if (client->transient_for != TRAN_GROUP) {
|
||||
client = client->transient_for;
|
||||
} else {
|
||||
GSList *it;
|
||||
|
||||
/* the check for TRAN_GROUP is to prevent an infinate loop with
|
||||
2 transients of the same group at the head of the group's
|
||||
members list */
|
||||
for (it = client->group->members; it; it = it->next) {
|
||||
Client *c = it->data;
|
||||
/* the check for TRAN_GROUP is to prevent an infinate loop with
|
||||
2 transients of the same group at the head of the group's
|
||||
members list */
|
||||
for (it = client->group->members; it; it = it->next) {
|
||||
Client *c = it->data;
|
||||
|
||||
if (c != client && c->transient_for != TRAN_GROUP) {
|
||||
client = it->data;
|
||||
break;
|
||||
if (c != client && c->transient_for != TRAN_GROUP) {
|
||||
client = it->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (it == NULL) break;
|
||||
}
|
||||
if (it == NULL) break;
|
||||
}
|
||||
window = CLIENT_AS_WINDOW(client);
|
||||
}
|
||||
|
||||
lower_recursive(client, NULL);
|
||||
lower_recursive(window, NULL);
|
||||
|
||||
stacking_set_list();
|
||||
}
|
||||
|
||||
void stacking_raise_internal(Window win)
|
||||
{
|
||||
Window wins[2]; /* only ever restack 2 windows. */
|
||||
|
||||
wins[0] = top_window;
|
||||
wins[1] = win;
|
||||
|
||||
XRestackWindows(ob_display, wins, 2);
|
||||
}
|
||||
|
|
|
@ -1,46 +1,42 @@
|
|||
#ifndef __stacking_h
|
||||
#define __stacking_h
|
||||
|
||||
#include "window.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
struct Client;
|
||||
|
||||
/*! The possible stacking layers a client window can be a part of */
|
||||
typedef enum {
|
||||
Layer_Icon, /*!< 0 - iconified windows, in any order at all */
|
||||
Layer_Desktop, /*!< 1 - desktop windows */
|
||||
Layer_Below, /*!< 2 - normal windows w/ below */
|
||||
Layer_Normal, /*!< 3 - normal windows */
|
||||
Layer_Above, /*!< 4 - normal windows w/ above */
|
||||
Layer_Top, /*!< 5 - always-on-top-windows (docks?) */
|
||||
Layer_Fullscreen, /*!< 6 - fullscreeen windows */
|
||||
Layer_Internal /*!< 7 - openbox windows/menus */
|
||||
Layer_Desktop, /*!< 0 - desktop windows */
|
||||
Layer_Below, /*!< 1 - normal windows w/ below */
|
||||
Layer_Normal, /*!< 2 - normal windows */
|
||||
Layer_Above, /*!< 3 - normal windows w/ above */
|
||||
Layer_Top, /*!< 4 - always-on-top-windows (docks?) */
|
||||
Layer_Fullscreen, /*!< 5 - fullscreeen windows */
|
||||
Layer_Internal /*!< 6 - openbox windows/menus */
|
||||
} StackLayer;
|
||||
|
||||
/* list of Client*s in stacking order from highest to lowest */
|
||||
/* list of ObWindow*s in stacking order from highest to lowest */
|
||||
extern GList *stacking_list;
|
||||
|
||||
void stacking_startup();
|
||||
void stacking_shutdown();
|
||||
|
||||
/*! Sets the client stacking list on the root window from the
|
||||
stacking_clientlist */
|
||||
/*! Sets the window stacking list on the root window from the
|
||||
stacking_list */
|
||||
void stacking_set_list();
|
||||
|
||||
/*! Raises a client window above all others in its stacking layer
|
||||
#define stacking_add(win) stacking_list = g_list_append(stacking_list, win);
|
||||
#define stacking_remove(win) stacking_list = g_list_remove(stacking_list, win);
|
||||
|
||||
/*! Raises a window above all others in its stacking layer
|
||||
raiseWindow has a couple of constraints that lowerWindow does not.<br>
|
||||
1) raiseWindow can be called after changing a Client's stack layer, and
|
||||
1) raiseWindow can be called after changing a Window's stack layer, and
|
||||
the list will be reorganized properly.<br>
|
||||
2) raiseWindow guarantees that XRestackWindows() will <i>always</i> be
|
||||
called for the specified client.
|
||||
called for the specified window.
|
||||
*/
|
||||
void stacking_raise(struct Client *client);
|
||||
void stacking_raise(ObWindow *window);
|
||||
|
||||
/*! Lowers a client window below all others in its stacking layer */
|
||||
void stacking_lower(struct Client *client);
|
||||
|
||||
/*! Raises an internal window (e.g. menus) */
|
||||
void stacking_raise_internal(Window win);
|
||||
void stacking_lower(ObWindow *window);
|
||||
|
||||
#endif
|
||||
|
|
33
openbox/window.c
Normal file
33
openbox/window.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "window.h"
|
||||
#include "menu.h"
|
||||
#include "slit.h"
|
||||
#include "client.h"
|
||||
#include "frame.h"
|
||||
|
||||
Window window_top(ObWindow *self)
|
||||
{
|
||||
switch (self->type) {
|
||||
case Window_Menu:
|
||||
return ((Menu*)self)->frame;
|
||||
case Window_Slit:
|
||||
return ((Slit*)self)->frame;
|
||||
case Window_Client:
|
||||
return ((Client*)self)->frame->window;
|
||||
}
|
||||
g_assert_not_reached();
|
||||
return None;
|
||||
}
|
||||
|
||||
Window window_layer(ObWindow *self)
|
||||
{
|
||||
switch (self->type) {
|
||||
case Window_Menu:
|
||||
return Layer_Internal;
|
||||
case Window_Slit:
|
||||
return ((Slit*)self)->layer;
|
||||
case Window_Client:
|
||||
return ((Client*)self)->layer;
|
||||
}
|
||||
g_assert_not_reached();
|
||||
return None;
|
||||
}
|
35
openbox/window.h
Normal file
35
openbox/window.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef __window_h
|
||||
#define __window_h
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
typedef enum {
|
||||
Window_Menu,
|
||||
Window_Slit,
|
||||
Window_Client
|
||||
} Window_InternalType;
|
||||
|
||||
typedef struct ObWindow {
|
||||
Window_InternalType type;
|
||||
} ObWindow;
|
||||
|
||||
#define WINDOW_IS_MENU(win) (((ObWindow*)win)->type == Window_Menu)
|
||||
#define WINDOW_IS_SLIT(win) (((ObWindow*)win)->type == Window_Slit)
|
||||
#define WINDOW_IS_CLIENT(win) (((ObWindow*)win)->type == Window_Client)
|
||||
|
||||
struct Menu;
|
||||
struct Slit;
|
||||
struct Client;
|
||||
|
||||
#define WINDOW_AS_MENU(win) ((struct Menu*)win)
|
||||
#define WINDOW_AS_SLIT(win) ((struct Slit*)win)
|
||||
#define WINDOW_AS_CLIENT(win) ((struct Client*)win)
|
||||
|
||||
#define MENU_AS_WINDOW(menu) ((ObWindow*)menu)
|
||||
#define SLIT_AS_WINDOW(slit) ((ObWindow*)slit)
|
||||
#define CLIENT_AS_WINDOW(client) ((ObWindow*)client)
|
||||
|
||||
Window window_top(ObWindow *self);
|
||||
Window window_layer(ObWindow *self);
|
||||
|
||||
#endif
|
|
@ -65,6 +65,8 @@ static void resist_move(Client *c, int *x, int *y)
|
|||
Client *target;
|
||||
int tl, tt, tr, tb; /* 1 past the target's edges on each side */
|
||||
|
||||
if (!WINDOW_IS_CLIENT(it->data))
|
||||
continue;
|
||||
target = it->data;
|
||||
/* don't snap to self or non-visibles */
|
||||
if (!target->frame->visible || target == c) continue;
|
||||
|
|
Loading…
Reference in a new issue