check WM_CLIENT_LEADER for dialogs, if WM_TRANSIENT_FOR is not set

This commit is contained in:
seanpringle
2012-09-11 14:01:15 +10:00
parent 1d93b2edb2
commit 91cac07077
3 changed files with 46 additions and 19 deletions

View File

@@ -8,6 +8,7 @@ int window_get_atom_prop(Window w, Atom atom, Atom *list, int count);
void window_set_atom_prop(Window w, Atom prop, Atom *atoms, int count);
int window_get_cardinal_prop(Window w, Atom atom, unsigned long *list, int count);
void window_set_cardinal_prop(Window w, Atom prop, unsigned long *values, int count);
int window_get_window_prop(Window w, Atom atom, Window *list, int count);
void window_set_window_prop(Window w, Atom prop, Window *values, int count);
void ewmh_client_list();
client* window_build_client(Window win);
@@ -19,7 +20,7 @@ void query_visible_windows(stack *s);
int window_send_clientmessage(Window target, Window subject, Atom atom, unsigned long protocol, unsigned long mask);
int client_send_wm_protocol(client *c, Atom protocol);
void client_close(client *c);
void client_place_spot(client *c, int spot, int force);
void client_place_spot(client *c, int spot, int mon, int force);
void client_spot_cycle(client *c);
Window spot_focus_top_window(int spot, int mon, Window except);
void client_stack_family(client *c, stack *all, stack *raise);

59
xoat.c
View File

@@ -110,6 +110,12 @@ void window_set_cardinal_prop(Window w, Atom prop, unsigned long *values, int co
XChangeProperty(display, w, prop, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)values, count);
}
int window_get_window_prop(Window w, Atom atom, Window *list, int count)
{
Atom type; int items;
return window_get_prop(w, atom, &type, &items, list, count*sizeof(Window)) && type == XA_WINDOW ? items:0;
}
void window_set_window_prop(Window w, Atom prop, Window *values, int count)
{
XChangeProperty(display, w, prop, XA_WINDOW, 32, PropModeReplace, (unsigned char*)values, count);
@@ -143,8 +149,9 @@ client* window_build_client(Window win)
if (XGetWindowAttributes(display, c->window, &c->attr))
{
c->visible = c->attr.map_state == IsViewable ? 1:0;
XGetTransientForHint(display, c->window, &c->transient_for);
XGetTransientForHint(display, c->window, &c->transient);
window_get_atom_prop(win, atoms[_NET_WM_WINDOW_TYPE], &c->type, 1);
window_get_window_prop(win, atoms[WM_CLIENT_LEADER], &c->leader, 1);
c->manage = !c->attr.override_redirect
&& c->type != atoms[_NET_WM_WINDOW_TYPE_DESKTOP]
@@ -286,17 +293,36 @@ void client_close(client *c)
XKillClient(display, c->window);
}
void client_place_spot(client *c, int spot, int force)
void client_place_spot(client *c, int spot, int mon, int force)
{
if (!c) return;
client *t;
if (c->transient_for && !force)
// try to center over our transient parent
if (!force && c->transient && (t = window_build_client(c->transient)))
{
client *t = window_build_client(c->transient_for);
spot = t->spot;
mon = t->monitor;
client_free(t);
}
c->spot = spot;
else
// try to center over top-most window in our group
if (!force && c->leader && c->type == atoms[_NET_WM_WINDOW_TYPE_DIALOG])
{
int i; stack wins;
query_visible_windows(&wins);
for (i = 0; i < wins.depth; i++)
{
if ((t = wins.clients[i]) && t->manage && t->window != c->window && t->leader == c->leader)
{
spot = t->spot;
mon = t->monitor;
break;
}
}
}
c->spot = spot; c->monitor = mon;
monitor *m = &monitors[c->monitor];
int x = m->spots[spot].x, y = m->spots[spot].y, w = m->spots[spot].w, h = m->spots[spot].h;
@@ -393,7 +419,7 @@ void client_stack_family(client *c, stack *all, stack *raise)
int i; client *o, *self = NULL;
for (i = 0; i < all->depth; i++)
{
if ((o = all->clients[i]) && o->manage && o->visible && o->transient_for == c->window)
if ((o = all->clients[i]) && o->manage && o->visible && o->transient == c->window)
client_stack_family(o, all, raise);
else
if (o && o->visible && o->window == c->window)
@@ -425,9 +451,9 @@ void client_raise_family(client *c)
if ((o = all.clients[i]) && client_has_state(o, atoms[_NET_WM_STATE_ABOVE]))
client_stack_family(o, &all, &raise);
while (c->transient_for)
while (c->transient)
{
client *t = window_build_client(c->transient_for);
client *t = window_build_client(c->transient);
if (t) c = family.clients[family.depth++] = t;
}
@@ -483,7 +509,7 @@ void action_move(void *data, int num, client *cli)
{
if (!cli) return;
client_raise_family(cli);
client_place_spot(cli, num, 1);
client_place_spot(cli, num, cli->monitor, 1);
}
void action_focus(void *data, int num, client *cli)
@@ -528,7 +554,7 @@ void action_move_monitor(void *data, int num, client *cli)
if (!cli) return;
client_raise_family(cli);
cli->monitor = MAX(0, MIN(current_mon+num, nmonitors-1));
client_place_spot(cli, cli->spot, 1);
client_place_spot(cli, cli->spot, cli->monitor, 1);
}
void action_focus_monitor(void *data, int num, client *cli)
@@ -554,7 +580,7 @@ void action_fullscreen(void *data, int num, client *cli)
cli->spot = spot;
client_update_border(cli);
client_place_spot(cli, cli->spot, 1);
client_place_spot(cli, cli->spot, cli->monitor, 1);
}
void action_above(void *data, int num, client *cli)
@@ -588,8 +614,7 @@ void action_rollback(void *data, int num, client *cli)
if ((s = snapshot.clients[i]) && (c = window_build_client(s->window))
&& !strcmp(s->class, c->class) && c->visible && c->manage)
{
c->monitor = s->monitor;
client_place_spot(c, s->spot, 1);
client_place_spot(c, s->spot, s->monitor, 1);
client_raise_family(c);
if (s->spot == current_spot && s->monitor == current_mon)
{
@@ -638,10 +663,10 @@ void configure_request(XEvent *ev)
{
XConfigureRequestEvent *e = &ev->xconfigurerequest;
client *c = window_build_client(e->window);
if (c && c->manage && c->visible && !c->transient_for)
if (c && c->manage && c->visible && !c->transient)
{
client_update_border(c);
client_place_spot(c, c->spot, 0);
client_place_spot(c, c->spot, c->monitor, 0);
}
else
if (c)
@@ -682,7 +707,7 @@ void map_request(XEvent *e)
if (c->attr.width <= m->spots[spot].w && c->attr.height <= m->spots[spot].h)
break;
client_place_spot(c, spot, 0);
client_place_spot(c, spot, c->monitor, 0);
client_update_border(c);
}
if (c) XMapWindow(display, c->window);
@@ -931,7 +956,7 @@ int main(int argc, char *argv[])
window_listen(c->window);
client_update_border(c);
client_place_spot(c, c->spot, 0);
client_place_spot(c, c->spot, c->monitor, 0);
// only activate first one
if (!current) client_activate(c);

3
xoat.h
View File

@@ -94,7 +94,7 @@ int nmonitors = 1;
typedef struct {
Window window;
XWindowAttributes attr;
Window transient_for;
Window transient, leader;
Atom type, states[MAX_NET_WM_STATES+1];
short monitor, spot, visible, manage, input, urgent;
char *class;
@@ -151,6 +151,7 @@ wm_strut struts;
X(_NET_WM_STATE_ABOVE),\
X(_NET_WM_STATE_DEMANDS_ATTENTION),\
X(WM_DELETE_WINDOW),\
X(WM_CLIENT_LEADER),\
X(WM_TAKE_FOCUS),\
X(WM_PROTOCOLS)