summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Wong <gtw@gnu.org>2009-08-27 10:42:14 -0600
committerGary Wong <gtw@gnu.org>2009-08-27 10:42:14 -0600
commitbb4f6e5fb316fb10400fa0d77ce076105fa1861b (patch)
tree557f2a438ab6561467c913175b7266d7df6e1805
parent85b1eed0a83f47f525c2826dfce3263cbd7d6a81 (diff)
Implement edge resistance when resizing frames.
-rw-r--r--ChangeLog6
-rw-r--r--frame.c334
2 files changed, 177 insertions, 163 deletions
diff --git a/ChangeLog b/ChangeLog
index f712496..ce89b5b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2009-08-27 Gary Wong <gtw@gnu.org>
+
+ * frame.c (recalc_size): Implement edge resistance when resizing
+ frames.
+ (edge_resist): New function.
+
2009-08-26 Gary Wong <gtw@gnu.org>
* frame.c (frame_motion_notify, frame_button_release): Implement
diff --git a/frame.c b/frame.c
index 7994978..5e92d58 100644
--- a/frame.c
+++ b/frame.c
@@ -40,7 +40,7 @@ static enum _window_operation {
static enum size_which {
SIZE_LESSER, SIZE_NONE, SIZE_GREATER
} size_x, size_y;
-static int dx, dy, var_x, fixed_x, var_y, fixed_y, init_x, init_y, moved;
+static int dx, dy, init_x, init_y, moved;
static struct gwm_window *feedback;
static struct h_edge {
@@ -164,59 +164,158 @@ static void free_edges( void ) {
r_edges = NULL;
}
+static void edge_resist( int old_t, int old_b, int old_l, int old_r,
+ int new_t, int new_b, int new_l, int new_r,
+ int *ex, int *ey ) {
+
+ *ex = *ey = 0;
+
+ if( new_t < old_t ) {
+ /* Trying to move up; look for bottom edges with
+ new_t < y <= new_t + EDGE_RESIST. */
+ int i0 = 0, i1 = num_b_edges - 1, i;
+
+ while( i1 > i0 + 1 ) {
+ int i_mid = ( i0 + i1 ) >> 1;
+
+ if( b_edges[ i_mid ].y <= new_t )
+ i0 = i_mid;
+ else
+ i1 = i_mid;
+ }
+
+ while( i0 < num_b_edges && b_edges[ i0 ].y <= new_t )
+ i0++;
+
+ for( i = i0; i < num_b_edges && b_edges[ i ].y <= new_t + EDGE_RESIST;
+ i++ )
+ if( b_edges[ i ].x_min < new_r && b_edges[ i ].x_max > new_l )
+ *ey = b_edges[ i ].y - new_t;
+ } else if( new_b > old_b ) {
+ /* Trying to move down; look for top edges with
+ new_b > y >= new_b - EDGE_RESIST. */
+ int i0 = 0, i1 = num_t_edges - 1, i;
+
+ while( i1 > i0 + 1 ) {
+ int i_mid = ( i0 + i1 ) >> 1;
+
+ if( t_edges[ i_mid ].y >= new_b )
+ i1 = i_mid;
+ else
+ i0 = i_mid;
+ }
+
+ while( i1 >= 0 && t_edges[ i1 ].y >= new_b )
+ i1--;
+
+ for( i = i1; i >= 0 && t_edges[ i ].y >= new_b - EDGE_RESIST; i-- )
+ if( t_edges[ i ].x_min < new_r && t_edges[ i ].x_max > new_l )
+ *ey = t_edges[ i ].y - new_b;
+ }
+
+ if( new_l < old_l ) {
+ /* Trying to move left; look for right edges with
+ new_l < x <= new_l + EDGE_RESIST. */
+ int i0 = 0, i1 = num_r_edges - 1, i;
+
+ while( i1 > i0 + 1 ) {
+ int i_mid = ( i0 + i1 ) >> 1;
+
+ if( r_edges[ i_mid ].x <= new_l )
+ i0 = i_mid;
+ else
+ i1 = i_mid;
+ }
+
+ while( i0 < num_r_edges && r_edges[ i0 ].x <= new_l )
+ i0++;
+
+ for( i = i0; i < num_r_edges && r_edges[ i ].x <= new_l + EDGE_RESIST;
+ i++ )
+ if( r_edges[ i ].y_min < new_b && r_edges[ i ].y_max > new_t )
+ *ex = r_edges[ i ].x - new_l;
+ } else if( new_r > old_r ) {
+ /* Trying to move right; look for left edges with
+ new_r > x >= new_r - EDGE_RESIST. */
+ int i0 = 0, i1 = num_l_edges - 1, i;
+
+ while( i1 > i0 + 1 ) {
+ int i_mid = ( i0 + i1 ) >> 1;
+
+ if( l_edges[ i_mid ].x >= new_r )
+ i1 = i_mid;
+ else
+ i0 = i_mid;
+ }
+
+ while( i1 >= 0 && l_edges[ i1 ].x >= new_r )
+ i1--;
+
+ for( i = i1; i >= 0 && l_edges[ i ].x >= new_r - EDGE_RESIST; i-- )
+ if( l_edges[ i ].y_min < new_b && l_edges[ i ].y_max > new_t )
+ *ex = l_edges[ i ].x - new_r;
+ }
+}
+
static void recalc_size( struct gwm_window *window, int x, int y,
- xcb_timestamp_t t ) {
+ int apply_edge_resist, xcb_timestamp_t t ) {
- int new_x, new_y, new_width, new_height, child_width, child_height;
+ int new_width, new_height, child_width, child_height;
enum size_which old_size_x = size_x, old_size_y = size_y;
+ int old_t, old_b, old_l, old_r, new_t, new_b, new_l, new_r;
+
+ old_t = window->u.frame.y;
+ old_b = old_t + window->u.frame.height + ( FRAME_X_BORDER << 1 );
+ old_l = window->u.frame.x;
+ old_r = old_l + window->u.frame.width + ( FRAME_X_BORDER << 1 );
if( size_x == SIZE_LESSER ) {
- var_x = x - dx;
- new_width = fixed_x - var_x;
+ new_l = x - dx;
+ new_r = old_r;
} else if( size_x == SIZE_GREATER ) {
- var_x = x - dx;
- new_width = var_x - fixed_x;
+ new_l = old_l;
+ new_r = x - dx;
} else if( x < window->u.frame.x + ( window->u.frame.width >> 2 ) ) {
/* Start sizing left border. */
size_x = SIZE_LESSER;
- var_x = window->u.frame.x;
- fixed_x = window->u.frame.x + window->u.frame.width;
- dx = x - var_x;
- new_width = fixed_x - var_x;
+ new_l = old_l;
+ new_r = old_r;
+ dx = x - old_l;
} else if( x > window->u.frame.x + window->u.frame.width -
( window->u.frame.width >> 2 ) ) {
/* Start sizing right border. */
size_x = SIZE_GREATER;
- var_x = window->u.frame.x + window->u.frame.width;
- fixed_x = window->u.frame.x;
- dx = x - var_x;
- new_width = var_x - fixed_x;
- } else
- new_width = window->u.frame.width;
+ new_l = old_l;
+ new_r = old_r;
+ dx = x - old_r;
+ } else {
+ new_l = old_l;
+ new_r = old_r;
+ }
if( size_y == SIZE_LESSER ) {
- var_y = y - dy;
- new_height = fixed_y - var_y;
+ new_t = y - dy;
+ new_b = old_b;
} else if( size_y == SIZE_GREATER ) {
- var_y = y - dy;
- new_height = var_y - fixed_y;
+ new_t = old_t;
+ new_b = y - dy;
} else if( y < window->u.frame.y + ( window->u.frame.height >> 2 ) ) {
/* Start sizing top border. */
size_y = SIZE_LESSER;
- var_y = window->u.frame.y;
- fixed_y = window->u.frame.y + window->u.frame.height;
- dy = y - var_y;
- new_height = fixed_y - var_y;
+ new_t = old_t;
+ new_b = old_b;
+ dy = y - old_t;
} else if( y > window->u.frame.y + window->u.frame.height -
( window->u.frame.height >> 2 ) ) {
/* Start sizing bottom border. */
size_y = SIZE_GREATER;
- var_y = window->u.frame.y + window->u.frame.height;
- fixed_y = window->u.frame.y;
- dy = y - var_y;
- new_height = var_y - fixed_y;
- } else
- new_height = window->u.frame.height;
+ new_t = old_t;
+ new_b = old_b;
+ dy = y - old_b;
+ } else {
+ new_t = old_t;
+ new_b = old_b;
+ }
if( size_x != old_size_x || size_y != old_size_y )
xcb_change_active_pointer_grab( c, cursors[ CURSOR_TL + size_y * 3 +
@@ -224,7 +323,27 @@ static void recalc_size( struct gwm_window *window, int x, int y,
XCB_EVENT_MASK_BUTTON_RELEASE |
XCB_EVENT_MASK_POINTER_MOTION_HINT |
XCB_EVENT_MASK_BUTTON_MOTION );
-
+
+ if( apply_edge_resist ) {
+ int ex, ey;
+
+ edge_resist( old_t, old_b, old_l, old_r,
+ new_t, new_b, new_l, new_r, &ex, &ey );
+
+ if( ex > 0 )
+ new_l += ex;
+ else
+ new_r += ex;
+
+ if( ey > 0 )
+ new_t += ey;
+ else
+ new_b += ey;
+ }
+
+ new_width = new_r - new_l - ( FRAME_X_BORDER << 1 );
+ new_height = new_b - new_t - ( FRAME_X_BORDER << 1 );
+
child_width = new_width - ( FRAME_BORDER_WIDTH << 1 );
child_height = new_height - FRAME_TITLE_HEIGHT - FRAME_BORDER_WIDTH;
apply_size_constraints( window->u.frame.child, &child_width,
@@ -232,39 +351,17 @@ static void recalc_size( struct gwm_window *window, int x, int y,
new_width = child_width + ( FRAME_BORDER_WIDTH << 1 );
new_height = child_height + FRAME_TITLE_HEIGHT + FRAME_BORDER_WIDTH;
- switch( size_x ) {
- case SIZE_NONE:
- new_x = window->u.frame.x;
- break;
+ if( size_x == SIZE_LESSER )
+ new_l = new_r - new_width - ( FRAME_X_BORDER << 1 );
- case SIZE_LESSER:
- new_x = fixed_x - new_width;
- break;
-
- case SIZE_GREATER:
- new_x = fixed_x;
- break;
- }
+ if( size_y == SIZE_LESSER )
+ new_t = new_b - new_height - ( FRAME_X_BORDER << 1 );
- switch( size_y ) {
- case SIZE_NONE:
- new_y = window->u.frame.y;
- break;
-
- case SIZE_LESSER:
- new_y = fixed_y - new_height;
- break;
-
- case SIZE_GREATER:
- new_y = fixed_y;
- break;
- }
-
- if( new_x != window->u.frame.x || new_y != window->u.frame.y ||
+ if( new_l != window->u.frame.x || new_t != window->u.frame.y ||
new_width != window->u.frame.width ||
new_height != window->u.frame.height ) {
int new_fb_width, new_fb_height;
- uint32_t values[ 4 ] = { new_x, new_y, new_width, new_height };
+ uint32_t values[ 4 ] = { new_l, new_t, new_width, new_height };
xcb_configure_window( c, window->w, XCB_CONFIG_WINDOW_X |
XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH |
@@ -339,7 +436,7 @@ static void frame_button_press( struct gwm_window *window,
if( window_op == OP_RESIZE ) {
size_x = size_y = SIZE_NONE;
- recalc_size( window, ev->root_x, ev->root_y, ev->time );
+ recalc_size( window, ev->root_x, ev->root_y, FALSE, ev->time );
} else {
dx = ev->event_x;
dy = ev->event_y;
@@ -391,105 +488,15 @@ static void frame_motion_notify( struct gwm_window *window,
new_r = new_l + window->u.frame.width + ( FRAME_X_BORDER << 1 );
if( !( ev->state & XCB_MOD_MASK_CONTROL ) ) {
- int dx = 0, dy = 0;
-
- if( new_t < old_t ) {
- /* Trying to move up; look for bottom edges with
- new_t < y <= new_t + EDGE_RESIST. */
- int i0 = 0, i1 = num_b_edges - 1, i;
-
- while( i1 > i0 + 1 ) {
- int i_mid = ( i0 + i1 ) >> 1;
-
- if( b_edges[ i_mid ].y <= new_t )
- i0 = i_mid;
- else
- i1 = i_mid;
- }
-
- while( i0 < num_b_edges && b_edges[ i0 ].y <= new_t )
- i0++;
-
- for( i = i0; i < num_b_edges && b_edges[ i ].y <=
- new_t + EDGE_RESIST; i++ )
- if( b_edges[ i ].x_min < new_r &&
- b_edges[ i ].x_max > new_l )
- dy = b_edges[ i ].y - new_t;
- } else if( new_b > old_b ) {
- /* Trying to move down; look for top edges with
- new_b > y >= new_b - EDGE_RESIST. */
- int i0 = 0, i1 = num_t_edges - 1, i;
-
- while( i1 > i0 + 1 ) {
- int i_mid = ( i0 + i1 ) >> 1;
-
- if( t_edges[ i_mid ].y >= new_b )
- i1 = i_mid;
- else
- i0 = i_mid;
- }
-
- while( i1 >= 0 && t_edges[ i1 ].y >= new_b )
- i1--;
-
- for( i = i1; i >= 0 && t_edges[ i ].y >=
- new_b - EDGE_RESIST; i-- )
- if( t_edges[ i ].x_min < new_r &&
- t_edges[ i ].x_max > new_l )
- dy = t_edges[ i ].y - new_b;
- }
-
- new_t += dy;
- new_b += dy;
-
- if( new_l < old_l ) {
- /* Trying to move left; look for right edges with
- new_l < x <= new_l + EDGE_RESIST. */
- int i0 = 0, i1 = num_r_edges - 1, i;
-
- while( i1 > i0 + 1 ) {
- int i_mid = ( i0 + i1 ) >> 1;
-
- if( r_edges[ i_mid ].x <= new_l )
- i0 = i_mid;
- else
- i1 = i_mid;
- }
-
- while( i0 < num_r_edges && r_edges[ i0 ].x <= new_l )
- i0++;
-
- for( i = i0; i < num_r_edges && r_edges[ i ].x <=
- new_l + EDGE_RESIST; i++ )
- if( r_edges[ i ].y_min < new_b &&
- r_edges[ i ].y_max > new_t )
- dx = r_edges[ i ].x - new_l;
- } else if( new_r > old_r ) {
- /* Trying to move right; look for left edges with
- new_r > x >= new_r - EDGE_RESIST. */
- int i0 = 0, i1 = num_l_edges - 1, i;
-
- while( i1 > i0 + 1 ) {
- int i_mid = ( i0 + i1 ) >> 1;
-
- if( l_edges[ i_mid ].x >= new_r )
- i1 = i_mid;
- else
- i0 = i_mid;
- }
-
- while( i1 >= 0 && l_edges[ i1 ].x >= new_r )
- i1--;
-
- for( i = i1; i >= 0 && l_edges[ i ].x >=
- new_r - EDGE_RESIST; i-- )
- if( l_edges[ i ].y_min < new_b &&
- l_edges[ i ].y_max > new_t )
- dx = l_edges[ i ].x - new_r;
- }
+ int ex, ey;
- new_l += dx;
- new_r += dx;
+ edge_resist( old_t, old_b, old_l, old_r,
+ new_t, new_b, new_l, new_r, &ex, &ey );
+
+ new_t += ey;
+ new_b += ey;
+ new_l += ex;
+ new_r += ex;
}
if( new_t != old_t || new_l != old_l ) {
@@ -506,10 +513,11 @@ static void frame_motion_notify( struct gwm_window *window,
break;
case OP_RESIZE:
- /* FIXME Implement edge resistance when resizing, too. This is a
- bit harder than moving, because size constraints might prevent
- us from sizing exactly to an edge. */
- recalc_size( window, ev->root_x, ev->root_y, ev->time );
+ recalc_size( window, ev->root_x, ev->root_y,
+ !( ev->state & XCB_MOD_MASK_CONTROL ) &&
+ window->u.frame.child->u.managed.width_inc == 1 &&
+ window->u.frame.child->u.managed.height_inc == 1,
+ ev->time );
break;
default: