Add MoveFromEdge* actions, shorten client_directional_edge_search with some handy #defines

This commit is contained in:
Mikael Magnusson 2006-10-31 03:33:21 +00:00
parent efa508a2a2
commit b18846db69
6 changed files with 123 additions and 103 deletions

View file

@ -1,3 +1,8 @@
3.4:
* Add MoveFromEdge* actions corresponding to MoveToEdge* but aligns far
edges instead of near edges, so if you have two overlapping windows you
can easily put them side by side.
3.3.1:
* Fix panels getting a border with keepBorder turned on.
* Fix a crash in mirrorhorizontal when drawing a surface with width 1.

View file

@ -39,6 +39,8 @@
Add showDelay for the dock
Tue Jul 18 23:43:15 CEST 2006 - jonaskoelker(a)gnu.org
hack code for great justice
Tue Oct 31 03:30:26 UTC 2006 - mikachu(a)openbox.org
Add movefromedge* actions
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://openbox.org/"
@ -284,6 +286,10 @@
<xs:enumeration value="MoveRelativeHorz"/>
<xs:enumeration value="MoveRelativeVert"/>
<xs:enumeration value="MoveToCenter"/>
<xs:enumeration value="MoveFromEdgeEast"/>
<xs:enumeration value="MoveFromEdgeNorth"/>
<xs:enumeration value="MoveFromEdgeSouth"/>
<xs:enumeration value="MoveFromEdgeWest"/>
<xs:enumeration value="MoveToEdgeEast"/>
<xs:enumeration value="MoveToEdgeNorth"/>
<xs:enumeration value="MoveToEdgeSouth"/>

View file

@ -303,28 +303,60 @@ void setup_action_cycle_windows_previous(ObAction **a, ObUserAction uact)
(*a)->data.cycle.dialog = TRUE;
}
void setup_action_movefromedge_north(ObAction **a, ObUserAction uact)
{
(*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
(*a)->data.diraction.direction = OB_DIRECTION_NORTH;
(*a)->data.diraction.hang = TRUE;
}
void setup_action_movefromedge_south(ObAction **a, ObUserAction uact)
{
(*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
(*a)->data.diraction.direction = OB_DIRECTION_SOUTH;
(*a)->data.diraction.hang = TRUE;
}
void setup_action_movefromedge_east(ObAction **a, ObUserAction uact)
{
(*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
(*a)->data.diraction.direction = OB_DIRECTION_EAST;
(*a)->data.diraction.hang = TRUE;
}
void setup_action_movefromedge_west(ObAction **a, ObUserAction uact)
{
(*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
(*a)->data.diraction.direction = OB_DIRECTION_WEST;
(*a)->data.diraction.hang = TRUE;
}
void setup_action_movetoedge_north(ObAction **a, ObUserAction uact)
{
(*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
(*a)->data.diraction.direction = OB_DIRECTION_NORTH;
(*a)->data.diraction.hang = FALSE;
}
void setup_action_movetoedge_south(ObAction **a, ObUserAction uact)
{
(*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
(*a)->data.diraction.direction = OB_DIRECTION_SOUTH;
(*a)->data.diraction.hang = FALSE;
}
void setup_action_movetoedge_east(ObAction **a, ObUserAction uact)
{
(*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
(*a)->data.diraction.direction = OB_DIRECTION_EAST;
(*a)->data.diraction.hang = FALSE;
}
void setup_action_movetoedge_west(ObAction **a, ObUserAction uact)
{
(*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
(*a)->data.diraction.direction = OB_DIRECTION_WEST;
(*a)->data.diraction.hang = FALSE;
}
void setup_action_growtoedge_north(ObAction **a, ObUserAction uact)
@ -783,6 +815,26 @@ ActionString actionstrings[] =
action_cycle_windows,
setup_action_cycle_windows_previous
},
{
"movefromedgenorth",
action_movetoedge,
setup_action_movefromedge_north
},
{
"movefromedgesouth",
action_movetoedge,
setup_action_movefromedge_south
},
{
"movefromedgewest",
action_movetoedge,
setup_action_movefromedge_west
},
{
"movefromedgeeast",
action_movetoedge,
setup_action_movefromedge_east
},
{
"movetoedgenorth",
action_movetoedge,
@ -1554,18 +1606,20 @@ void action_movetoedge(union ActionData *data)
switch(data->diraction.direction) {
case OB_DIRECTION_NORTH:
y = client_directional_edge_search(c, OB_DIRECTION_NORTH);
y = client_directional_edge_search(c, OB_DIRECTION_NORTH, data->diraction.hang)
- (data->diraction.hang ? c->frame->area.height : 0);
break;
case OB_DIRECTION_WEST:
x = client_directional_edge_search(c, OB_DIRECTION_WEST);
x = client_directional_edge_search(c, OB_DIRECTION_WEST, data->diraction.hang)
- (data->diraction.hang ? c->frame->area.width : 0);
break;
case OB_DIRECTION_SOUTH:
y = client_directional_edge_search(c, OB_DIRECTION_SOUTH) -
c->frame->area.height;
y = client_directional_edge_search(c, OB_DIRECTION_SOUTH, data->diraction.hang)
- (data->diraction.hang ? 0 : c->frame->area.height);
break;
case OB_DIRECTION_EAST:
x = client_directional_edge_search(c, OB_DIRECTION_EAST) -
c->frame->area.width;
x = client_directional_edge_search(c, OB_DIRECTION_EAST, data->diraction.hang)
- (data->diraction.hang ? 0 : c->frame->area.width);
break;
default:
g_assert_not_reached();
@ -1594,7 +1648,7 @@ void action_growtoedge(union ActionData *data)
switch(data->diraction.direction) {
case OB_DIRECTION_NORTH:
dest = client_directional_edge_search(c, OB_DIRECTION_NORTH);
dest = client_directional_edge_search(c, OB_DIRECTION_NORTH, FALSE);
if (a->y == y)
height = c->frame->area.height / 2;
else {
@ -1603,7 +1657,7 @@ void action_growtoedge(union ActionData *data)
}
break;
case OB_DIRECTION_WEST:
dest = client_directional_edge_search(c, OB_DIRECTION_WEST);
dest = client_directional_edge_search(c, OB_DIRECTION_WEST, FALSE);
if (a->x == x)
width = c->frame->area.width / 2;
else {
@ -1612,7 +1666,7 @@ void action_growtoedge(union ActionData *data)
}
break;
case OB_DIRECTION_SOUTH:
dest = client_directional_edge_search(c, OB_DIRECTION_SOUTH);
dest = client_directional_edge_search(c, OB_DIRECTION_SOUTH, FALSE);
if (a->y + a->height == y + c->frame->area.height) {
height = c->frame->area.height / 2;
y = a->y + a->height - height;
@ -1622,7 +1676,7 @@ void action_growtoedge(union ActionData *data)
height -= (height - c->frame->area.height) % c->size_inc.height;
break;
case OB_DIRECTION_EAST:
dest = client_directional_edge_search(c, OB_DIRECTION_EAST);
dest = client_directional_edge_search(c, OB_DIRECTION_EAST, FALSE);
if (a->x + a->width == x + c->frame->area.width) {
width = c->frame->area.width / 2;
x = a->x + a->width - width;

View file

@ -65,6 +65,7 @@ struct InterDirectionalAction{
struct DirectionalAction{
struct AnyAction any;
ObDirection direction;
gboolean hang;
};
struct Execute {

View file

@ -3216,11 +3216,30 @@ void client_update_sm_client_id(ObClient *self)
&self->sm_client_id);
}
#define WANT_EDGE(cur, c) \
if(cur == c) \
continue; \
if(!client_normal_or_dock(cur)) \
continue; \
if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL) \
continue; \
if(cur->iconic) \
continue; \
if(cur->layer < c->layer && !config_resist_layers_below) \
continue;
#define HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end) \
if ((his_edge_start >= my_edge_start && \
his_edge_start <= my_edge_end) || \
(my_edge_start >= his_edge_start && \
my_edge_start <= his_edge_end)) \
dest = his_offset;
/* finds the nearest edge in the given direction from the current client
* note to self: the edge is the -frame- edge (the actual one), not the
* client edge.
*/
gint client_directional_edge_search(ObClient *c, ObDirection dir)
gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
{
gint dest, monitor_dest;
gint my_edge_start, my_edge_end, my_offset;
@ -3237,11 +3256,11 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir)
case OB_DIRECTION_NORTH:
my_edge_start = c->frame->area.x;
my_edge_end = c->frame->area.x + c->frame->area.width;
my_offset = c->frame->area.y;
my_offset = c->frame->area.y + (hang ? c->frame->area.height : 0);
/* default: top of screen */
dest = a->y;
monitor_dest = monitor->y;
dest = a->y + (hang ? c->frame->area.height : 0);
monitor_dest = monitor->y + (hang ? c->frame->area.height : 0);
/* if the monitor edge comes before the screen edge, */
/* use that as the destination instead. (For xinerama) */
if (monitor_dest != dest && my_offset > monitor_dest)
@ -3251,45 +3270,29 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir)
gint his_edge_start, his_edge_end, his_offset;
ObClient *cur = it->data;
if(cur == c)
continue;
if(!client_normal(cur))
continue;
if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
continue;
if(cur->iconic)
continue;
if(cur->layer < c->layer && !config_resist_layers_below)
continue;
WANT_EDGE(cur, c)
his_edge_start = cur->frame->area.x;
his_edge_end = cur->frame->area.x + cur->frame->area.width;
his_offset = cur->frame->area.y + cur->frame->area.height;
his_offset = cur->frame->area.y + (hang ? 0 : cur->frame->area.height);
if(his_offset + 1 > my_offset)
continue;
if(his_offset < dest)
continue;
if(his_edge_start >= my_edge_start &&
his_edge_start <= my_edge_end)
dest = his_offset;
if(my_edge_start >= his_edge_start &&
my_edge_start <= his_edge_end)
dest = his_offset;
HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
}
break;
case OB_DIRECTION_SOUTH:
my_edge_start = c->frame->area.x;
my_edge_end = c->frame->area.x + c->frame->area.width;
my_offset = c->frame->area.y + c->frame->area.height;
my_offset = c->frame->area.y + (hang ? 0 : c->frame->area.height);
/* default: bottom of screen */
dest = a->y + a->height;
monitor_dest = monitor->y + monitor->height;
dest = a->y + a->height - (hang ? c->frame->area.height : 0);
monitor_dest = monitor->y + monitor->height - (hang ? c->frame->area.height : 0);
/* if the monitor edge comes before the screen edge, */
/* use that as the destination instead. (For xinerama) */
if (monitor_dest != dest && my_offset < monitor_dest)
@ -3299,20 +3302,11 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir)
gint his_edge_start, his_edge_end, his_offset;
ObClient *cur = it->data;
if(cur == c)
continue;
if(!client_normal(cur))
continue;
if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
continue;
if(cur->iconic)
continue;
if(cur->layer < c->layer && !config_resist_layers_below)
continue;
WANT_EDGE(cur, c)
his_edge_start = cur->frame->area.x;
his_edge_end = cur->frame->area.x + cur->frame->area.width;
his_offset = cur->frame->area.y;
his_offset = cur->frame->area.y + (hang ? cur->frame->area.height : 0);
if(his_offset - 1 < my_offset)
@ -3320,25 +3314,18 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir)
if(his_offset > dest)
continue;
if(his_edge_start >= my_edge_start &&
his_edge_start <= my_edge_end)
dest = his_offset;
if(my_edge_start >= his_edge_start &&
my_edge_start <= his_edge_end)
dest = his_offset;
HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
}
break;
case OB_DIRECTION_WEST:
my_edge_start = c->frame->area.y;
my_edge_end = c->frame->area.y + c->frame->area.height;
my_offset = c->frame->area.x;
my_offset = c->frame->area.x + (hang ? c->frame->area.width : 0);
/* default: leftmost egde of screen */
dest = a->x;
monitor_dest = monitor->x;
dest = a->x + (hang ? c->frame->area.width : 0);
monitor_dest = monitor->x + (hang ? c->frame->area.width : 0);
/* if the monitor edge comes before the screen edge, */
/* use that as the destination instead. (For xinerama) */
if (monitor_dest != dest && my_offset > monitor_dest)
@ -3348,46 +3335,29 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir)
gint his_edge_start, his_edge_end, his_offset;
ObClient *cur = it->data;
if(cur == c)
continue;
if(!client_normal(cur))
continue;
if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
continue;
if(cur->iconic)
continue;
if(cur->layer < c->layer && !config_resist_layers_below)
continue;
WANT_EDGE(cur, c)
his_edge_start = cur->frame->area.y;
his_edge_end = cur->frame->area.y + cur->frame->area.height;
his_offset = cur->frame->area.x + cur->frame->area.width;
his_offset = cur->frame->area.x + (hang ? 0 : cur->frame->area.width);
if(his_offset + 1 > my_offset)
continue;
if(his_offset < dest)
continue;
if(his_edge_start >= my_edge_start &&
his_edge_start <= my_edge_end)
dest = his_offset;
if(my_edge_start >= his_edge_start &&
my_edge_start <= his_edge_end)
dest = his_offset;
HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
}
break;
break;
case OB_DIRECTION_EAST:
my_edge_start = c->frame->area.y;
my_edge_end = c->frame->area.y + c->frame->area.height;
my_offset = c->frame->area.x + c->frame->area.width;
my_offset = c->frame->area.x + (hang ? 0 : c->frame->area.width);
/* default: rightmost edge of screen */
dest = a->x + a->width;
monitor_dest = monitor->x + monitor->width;
dest = a->x + a->width - (hang ? c->frame->area.width : 0);
monitor_dest = monitor->x + monitor->width - (hang ? c->frame->area.width : 0);
/* if the monitor edge comes before the screen edge, */
/* use that as the destination instead. (For xinerama) */
if (monitor_dest != dest && my_offset < monitor_dest)
@ -3397,35 +3367,19 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir)
gint his_edge_start, his_edge_end, his_offset;
ObClient *cur = it->data;
if(cur == c)
continue;
if(!client_normal(cur))
continue;
if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
continue;
if(cur->iconic)
continue;
if(cur->layer < c->layer && !config_resist_layers_below)
continue;
WANT_EDGE(cur, c)
his_edge_start = cur->frame->area.y;
his_edge_end = cur->frame->area.y + cur->frame->area.height;
his_offset = cur->frame->area.x;
his_offset = cur->frame->area.x + (hang ? cur->frame->area.width : 0);
if(his_offset - 1 < my_offset)
continue;
if(his_offset > dest)
continue;
if(his_edge_start >= my_edge_start &&
his_edge_start <= my_edge_end)
dest = his_offset;
if(my_edge_start >= his_edge_start &&
my_edge_start <= his_edge_end)
dest = his_offset;
HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
}
break;
case OB_DIRECTION_NORTHEAST:

View file

@ -575,7 +575,7 @@ ObClient *client_search_transient(ObClient *self, ObClient *search);
ObClient *client_find_directional(ObClient *c, ObDirection dir);
/*! Return the closest edge in the given direction */
gint client_directional_edge_search(ObClient *c, ObDirection dir);
gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang);
/*! Set a client window to be above/below other clients.
@layer < 0 indicates the client should be placed below other clients.<br>