summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--button.c22
-rw-r--r--button.h3
-rw-r--r--decorate-core.c3
-rw-r--r--decorate-render.c3
-rw-r--r--frame.c334
-rw-r--r--frame.h19
-rw-r--r--gwm.c216
-rw-r--r--gwm.h18
-rw-r--r--managed.c38
10 files changed, 387 insertions, 279 deletions
diff --git a/ChangeLog b/ChangeLog
index 9d75d95..085935c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2009-08-31 Gary Wong <gtw@gnu.org>
+
+ * button.c (button_size, button_xb): New functions. All references
+ to former constants updated.
+ * frame.c (frame_t, frame_b, frame_l, frame_r, frame_xb): New
+ functions. All references to former constants updated.
+ (translate_child_to_frame, translate_frame_to_child): Moved
+ from gwm.c.
+ (apply_size_constraints): Likewise.
+
2009-08-30 Gary Wong <gtw@gnu.org>
* frame.c (frame_button_release): Ignore the event unless the
diff --git a/button.c b/button.c
index 8b0d572..4bd2617 100644
--- a/button.c
+++ b/button.c
@@ -23,6 +23,7 @@
#include <config.h>
+#include <assert.h>
#include <xcb/xcb.h>
#include "gwm.h"
@@ -30,6 +31,23 @@
#include "button.h"
#include "window-table.h"
+#define BUTTON_SIZE 12 /* size of buttons in title bar; excludes X border */
+#define BUTTON_X_BORDER 1
+
+extern int button_size( struct gwm_window *window, int include_x_border ) {
+
+ assert( window->type == WINDOW_BUTTON );
+
+ return BUTTON_SIZE + ( include_x_border ? BUTTON_X_BORDER << 1 : 0 );
+}
+
+extern int button_xb( struct gwm_window *window ) {
+
+ assert( window->type == WINDOW_BUTTON );
+
+ return BUTTON_X_BORDER;
+}
+
static int button_active;
static void set_button_active( struct gwm_window *window, int new ) {
@@ -44,8 +62,8 @@ static void set_button_active( struct gwm_window *window, int new ) {
COL_BUTTON_INACTIVE ];
xcb_change_window_attributes( c, window->w, XCB_CW_BACK_PIXEL, &n );
- queue_window_update( window, 0, 0, FRAME_BUTTON_SIZE, FRAME_BUTTON_SIZE,
- FALSE );
+ queue_window_update( window, 0, 0, button_size( window, FALSE ),
+ button_size( window, FALSE ), FALSE );
}
static void button_button_press( struct gwm_window *window,
diff --git a/button.h b/button.h
index 6971d6a..03a7505 100644
--- a/button.h
+++ b/button.h
@@ -1,6 +1,9 @@
#ifndef BUTTON_H
#define BUTTON_H
+extern int button_size( struct gwm_window *window, int include_x_border );
+extern int button_xb( struct gwm_window *window );
+
extern event_handler button_handlers[];
#endif
diff --git a/decorate-core.c b/decorate-core.c
index 77b7436..c3c3b73 100644
--- a/decorate-core.c
+++ b/decorate-core.c
@@ -31,6 +31,7 @@
#include "gwm.h"
+#include "button.h"
#include "decorate-core.h"
#define FONT_SIZE 12
@@ -141,7 +142,7 @@ extern void core_update_window( struct gwm_window *window ) {
core_text( window->w, window->screen, window == focus_frame ?
COL_TITLE_ACTIVE : COL_TITLE_INACTIVE,
- FRAME_BUTTON_SIZE + FRAME_BORDER_WIDTH * 3,
+ button_size( window->u.frame.button, TRUE ) + 4,
FONT_SIZE, name ? name : "(Untitled)" );
} else if( window->type == WINDOW_FEEDBACK ) {
char *p, text[ 32 ];
diff --git a/decorate-render.c b/decorate-render.c
index 57dfa9b..b30f25a 100644
--- a/decorate-render.c
+++ b/decorate-render.c
@@ -36,6 +36,7 @@
#include "gwm.h"
+#include "button.h"
#include "decorate-render.h"
enum style_id {
@@ -568,7 +569,7 @@ extern void render_update_window( struct gwm_window *window ) {
render_text( window->w, window->screen, window == focus_frame ?
COL_TITLE_ACTIVE : COL_TITLE_INACTIVE,
- FRAME_BUTTON_SIZE + FRAME_BORDER_WIDTH * 3,
+ button_size( window->u.frame.button, TRUE ) + 4,
TITLE_FONT_SIZE, name ? name : "(Untitled)",
STYLE_TITLE, &window->update );
} else if( window->type == WINDOW_FEEDBACK ) {
diff --git a/frame.c b/frame.c
index 8faac26..969733d 100644
--- a/frame.c
+++ b/frame.c
@@ -35,6 +35,263 @@
#define EDGE_RESIST 8
+#define FRAME_X_BORDER 1 /* X border added to all four sides of frame */
+#define FRAME_BORDER_WIDTH 2 /* pixels added to left, right and bottom;
+ includes padding but excludes X border */
+#define FRAME_TITLE_HEIGHT 16 /* pixels added to top; includes title
+ bar but excludes X border */
+
+extern int frame_t( struct gwm_window *window, int include_x_border ) {
+
+ assert( window->type == WINDOW_FRAME );
+
+ return FRAME_TITLE_HEIGHT + ( include_x_border ? FRAME_X_BORDER : 0 );
+}
+
+extern int frame_b( struct gwm_window *window, int include_x_border ) {
+
+ assert( window->type == WINDOW_FRAME );
+
+ return FRAME_BORDER_WIDTH + ( include_x_border ? FRAME_X_BORDER : 0 );
+}
+
+extern int frame_l( struct gwm_window *window, int include_x_border ) {
+
+ assert( window->type == WINDOW_FRAME );
+
+ return FRAME_BORDER_WIDTH + ( include_x_border ? FRAME_X_BORDER : 0 );
+}
+
+extern int frame_r( struct gwm_window *window, int include_x_border ) {
+
+ assert( window->type == WINDOW_FRAME );
+
+ return FRAME_BORDER_WIDTH + ( include_x_border ? FRAME_X_BORDER : 0 );
+}
+
+extern int frame_xb( struct gwm_window *window ) {
+
+ assert( window->type == WINDOW_FRAME );
+
+ return FRAME_X_BORDER;
+}
+
+extern void translate_child_to_frame( struct gwm_window *frame,
+ int *fx, int *fy, int *fwidth,
+ int *fheight, int cx, int cy,
+ int cwidth, int cheight,
+ int cborder, int win_gravity ) {
+
+ *fwidth = cwidth + frame_l( frame, FALSE ) + frame_r( frame, FALSE );
+ *fheight = cheight + frame_t( frame, FALSE ) + frame_b( frame, FALSE );
+
+ switch( win_gravity ) {
+ case XCB_GRAVITY_NORTH_WEST:
+ case XCB_GRAVITY_WEST:
+ case XCB_GRAVITY_SOUTH_WEST:
+ default:
+ *fx = cx;
+ break;
+
+ case XCB_GRAVITY_NORTH:
+ case XCB_GRAVITY_CENTER:
+ case XCB_GRAVITY_SOUTH:
+ *fx = cx + cborder - ( ( frame_l( frame, TRUE ) +
+ frame_r( frame, TRUE ) ) >> 1 );
+ break;
+
+ case XCB_GRAVITY_NORTH_EAST:
+ case XCB_GRAVITY_EAST:
+ case XCB_GRAVITY_SOUTH_EAST:
+ *fx = cx + ( cborder << 1 ) - frame_l( frame, TRUE ) -
+ frame_r( frame, TRUE );
+ break;
+
+ case XCB_GRAVITY_STATIC:
+ *fx = cx + cborder - frame_l( frame, TRUE );
+ }
+
+ switch( win_gravity ) {
+ case XCB_GRAVITY_NORTH_WEST:
+ case XCB_GRAVITY_NORTH:
+ case XCB_GRAVITY_NORTH_EAST:
+ default:
+ *fy = cy;
+ break;
+
+ case XCB_GRAVITY_WEST:
+ case XCB_GRAVITY_CENTER:
+ case XCB_GRAVITY_EAST:
+ *fy = cy + cborder - ( ( frame_t( frame, TRUE ) +
+ frame_b( frame, TRUE ) ) >> 1 );
+ break;
+
+ case XCB_GRAVITY_SOUTH_WEST:
+ case XCB_GRAVITY_SOUTH:
+ case XCB_GRAVITY_SOUTH_EAST:
+ *fy = cy + ( cborder << 1 ) - frame_t( frame, TRUE ) -
+ frame_b( frame, TRUE );
+ break;
+
+ case XCB_GRAVITY_STATIC:
+ *fy = cy + cborder - frame_t( frame, TRUE );
+ break;
+ }
+}
+
+extern void translate_frame_to_child( struct gwm_window *frame,
+ int *cx, int *cy, int fx, int fy,
+ int cborder, int win_gravity ) {
+
+ switch( win_gravity ) {
+ case XCB_GRAVITY_NORTH_WEST:
+ case XCB_GRAVITY_WEST:
+ case XCB_GRAVITY_SOUTH_WEST:
+ default:
+ *cx = fx;
+ break;
+
+ case XCB_GRAVITY_NORTH:
+ case XCB_GRAVITY_CENTER:
+ case XCB_GRAVITY_SOUTH:
+ *cx = fx - cborder + ( ( frame_l( frame, TRUE ) +
+ frame_r( frame, TRUE ) ) >> 1 );
+ break;
+
+ case XCB_GRAVITY_NORTH_EAST:
+ case XCB_GRAVITY_EAST:
+ case XCB_GRAVITY_SOUTH_EAST:
+ *cx = fx - ( cborder << 1 ) + frame_l( frame, TRUE ) +
+ frame_r( frame, TRUE );
+ break;
+
+ case XCB_GRAVITY_STATIC:
+ *cx = fx - cborder + frame_l( frame, TRUE );
+ break;
+ }
+
+ switch( win_gravity ) {
+ case XCB_GRAVITY_NORTH_WEST:
+ case XCB_GRAVITY_NORTH:
+ case XCB_GRAVITY_NORTH_EAST:
+ default:
+ *cy = fy;
+ break;
+
+ case XCB_GRAVITY_WEST:
+ case XCB_GRAVITY_CENTER:
+ case XCB_GRAVITY_EAST:
+ *cy = fy - cborder + ( ( frame_t( frame, TRUE ) +
+ frame_b( frame, TRUE ) ) >> 1 );
+ break;
+
+ case XCB_GRAVITY_SOUTH_WEST:
+ case XCB_GRAVITY_SOUTH:
+ case XCB_GRAVITY_SOUTH_EAST:
+ *cy = fy - ( cborder << 1 ) + frame_t( frame, TRUE ) +
+ frame_b( frame, TRUE );
+ break;
+
+ case XCB_GRAVITY_STATIC:
+ *cy = fy - cborder + frame_t( frame, TRUE );
+ break;
+ }
+}
+
+extern void apply_size_constraints( struct gwm_window *window, int *width,
+ int *height ) {
+
+ int eff_base_width = window->u.managed.base_width ?
+ window->u.managed.base_width : window->u.managed.min_width,
+ eff_base_height = window->u.managed.base_height ?
+ window->u.managed.base_height : window->u.managed.min_height;
+
+ /* Apply the minimum and maximum constraints. These are already known
+ to be compatible. */
+ if( *width < window->u.managed.min_width )
+ *width = window->u.managed.min_width;
+
+ if( *height < window->u.managed.min_height )
+ *height = window->u.managed.min_height;
+
+ if( *width > window->u.managed.max_width )
+ *width = window->u.managed.max_width;
+
+ if( *height > window->u.managed.max_height )
+ *height = window->u.managed.max_height;
+
+ /* Now round down each dimension to an integer multiple of increments.
+ Rounding down cannot violate the maximum constraint, and since
+ eff_base_* >= min_*, it will not reduce below the minimum constraint. */
+ *width -= ( *width - eff_base_width ) % window->u.managed.width_inc;
+ *height -= ( *height - eff_base_height ) % window->u.managed.height_inc;
+
+ if( window->u.managed.min_aspect_x * *height >
+ window->u.managed.min_aspect_y * *width ) {
+ /* Minimum aspect ratio violated. Attempt to either increase the
+ width or decrease the height (whichever is a smaller change), but
+ don't do either if it would go outside the min/max bounds.
+ Both division operations are safe (min_aspect_y is always
+ positive, and min_aspect_x must be positive if there is a
+ violation). Note that an exact solution might not be possible
+ (e.g. certain cases where the aspect ratio and increments are
+ coprime). */
+ int min_x, max_y;
+
+ min_x = ( window->u.managed.min_aspect_x * *height +
+ ( window->u.managed.min_aspect_y - 1 ) ) /
+ window->u.managed.min_aspect_y + window->u.managed.width_inc - 1;
+ min_x -= ( min_x - eff_base_width ) % window->u.managed.width_inc;
+
+ max_y = window->u.managed.min_aspect_y * *width /
+ window->u.managed.min_aspect_x;
+ max_y -= ( max_y - eff_base_height ) % window->u.managed.height_inc;
+
+ if( min_x - *width < *height - max_y ) {
+ /* The width change is smaller: prefer it if possible. */
+ if( min_x >= window->u.managed.min_width )
+ *width = min_x;
+ else if( max_y < window->u.managed.max_height )
+ *height = max_y;
+ } else {
+ /* The height change is smaller: prefer it if possible. */
+ if( max_y < window->u.managed.max_height )
+ *height = max_y;
+ else if( min_x >= window->u.managed.min_width )
+ *width = min_x;
+ }
+ }
+
+ if( window->u.managed.max_aspect_x * *height <
+ window->u.managed.max_aspect_y * *width ) {
+ /* Maximum aspect ratio violated. Much like the case above... */
+ int min_y, max_x;
+
+ min_y = ( window->u.managed.max_aspect_y * *width +
+ ( window->u.managed.max_aspect_x - 1 ) ) /
+ window->u.managed.max_aspect_x + window->u.managed.height_inc - 1;
+ min_y -= ( min_y - eff_base_height ) % window->u.managed.height_inc;
+
+ max_x = window->u.managed.max_aspect_x * *height /
+ window->u.managed.max_aspect_y;
+ max_x -= ( max_x - eff_base_width ) % window->u.managed.width_inc;
+
+ if( min_y - *height < *width - max_x ) {
+ /* The height change is smaller: prefer it if possible. */
+ if( min_y >= window->u.managed.min_height )
+ *height = min_y;
+ else if( max_x < window->u.managed.max_width )
+ *width = max_x;
+ } else {
+ /* The width change is smaller: prefer it if possible. */
+ if( max_x < window->u.managed.max_width )
+ *width = max_x;
+ else if( min_y >= window->u.managed.min_height )
+ *height = min_y;
+ }
+ }
+}
+
static enum _window_operation {
OP_NONE, OP_MOVE, OP_RESIZE
} window_op;
@@ -104,10 +361,10 @@ static void build_edges( int screen ) {
window->screen == screen ) {
int t = window->u.frame.y,
b = window->u.frame.y + window->u.frame.height +
- ( FRAME_X_BORDER << 1 ),
+ ( frame_xb( window ) << 1 ),
l = window->u.frame.x,
r = window->u.frame.x + window->u.frame.width +
- ( FRAME_X_BORDER << 1 );
+ ( frame_xb( window ) << 1 );
if( t >= screens[ screen ]->height_in_pixels || b <= 0 ||
l >= screens[ screen ]->width_in_pixels || r <= 0 )
@@ -266,9 +523,9 @@ static void recalc_size( struct gwm_window *window, int x, int 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_b = old_t + window->u.frame.height + ( frame_xb( window ) << 1 );
old_l = window->u.frame.x;
- old_r = old_l + window->u.frame.width + ( FRAME_X_BORDER << 1 );
+ old_r = old_l + window->u.frame.width + ( frame_xb( window ) << 1 );
if( size_x == SIZE_LESSER ) {
new_l = x - dx;
@@ -342,21 +599,25 @@ static void recalc_size( struct gwm_window *window, int x, int y,
new_b += ey;
}
- new_width = new_r - new_l - ( FRAME_X_BORDER << 1 );
- new_height = new_b - new_t - ( FRAME_X_BORDER << 1 );
+ new_width = new_r - new_l - ( frame_xb( window ) << 1 );
+ new_height = new_b - new_t - ( frame_xb( window ) << 1 );
- child_width = new_width - ( FRAME_BORDER_WIDTH << 1 );
- child_height = new_height - FRAME_TITLE_HEIGHT - FRAME_BORDER_WIDTH;
+ child_width = new_width - frame_l( window, FALSE ) -
+ frame_r( window, FALSE );
+ child_height = new_height - frame_t( window, FALSE ) -
+ frame_b( window, FALSE );
apply_size_constraints( window->u.frame.child, &child_width,
&child_height );
- new_width = child_width + ( FRAME_BORDER_WIDTH << 1 );
- new_height = child_height + FRAME_TITLE_HEIGHT + FRAME_BORDER_WIDTH;
+ new_width = child_width + frame_l( window, FALSE ) +
+ frame_r( window, FALSE );
+ new_height = child_height + frame_t( window, FALSE ) +
+ frame_b( window, FALSE );
if( size_x == SIZE_LESSER )
- new_l = new_r - new_width - ( FRAME_X_BORDER << 1 );
+ new_l = new_r - new_width - ( frame_xb( window ) << 1 );
if( size_y == SIZE_LESSER )
- new_t = new_b - new_height - ( FRAME_X_BORDER << 1 );
+ new_t = new_b - new_height - ( frame_xb( window ) << 1 );
if( new_l != window->u.frame.x || new_t != window->u.frame.y ||
new_width != window->u.frame.width ||
@@ -368,8 +629,10 @@ static void recalc_size( struct gwm_window *window, int x, int y,
XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH |
XCB_CONFIG_WINDOW_HEIGHT, values );
- values[ 0 ] = new_width - ( FRAME_BORDER_WIDTH << 1 );
- values[ 1 ] = new_height - FRAME_TITLE_HEIGHT - FRAME_BORDER_WIDTH;
+ values[ 0 ] = new_width - frame_l( window, FALSE ) -
+ frame_r( window, FALSE );
+ values[ 1 ] = new_height - frame_t( window, FALSE ) -
+ frame_b( window, FALSE );
/* FIXME See _NET_WM_SYNC_REQUEST in the EWMH to avoid resizing the
window faster than the client can redraw it. */
xcb_configure_window( c, window->u.frame.child->w,
@@ -431,8 +694,8 @@ static void frame_button_press( struct gwm_window *window,
if( !initial_press( ev ) || ev->child )
return;
- window_op = ( ev->detail > 1 ) == ( ev->event_y < FRAME_TITLE_HEIGHT ) ?
- OP_RESIZE : OP_MOVE;
+ window_op = ( ev->detail > 1 ) ==
+ ( ev->event_y < frame_t( window, FALSE ) ) ? OP_RESIZE : OP_MOVE;
init_x = ev->root_x;
init_y = ev->root_y;
@@ -482,13 +745,13 @@ static void frame_motion_notify( struct gwm_window *window,
case OP_MOVE:
old_t = window->u.frame.y;
- old_b = old_t + window->u.frame.height + ( FRAME_X_BORDER << 1 );
+ old_b = old_t + window->u.frame.height + ( frame_xb( window ) << 1 );
old_l = window->u.frame.x;
- old_r = old_l + window->u.frame.width + ( FRAME_X_BORDER << 1 );
- new_t = ev->root_y - dy - FRAME_X_BORDER;
- new_b = new_t + window->u.frame.height + ( FRAME_X_BORDER << 1 );
- new_l = ev->root_x - dx - FRAME_X_BORDER;
- new_r = new_l + window->u.frame.width + ( FRAME_X_BORDER << 1 );
+ old_r = old_l + window->u.frame.width + ( frame_xb( window ) << 1 );
+ new_t = ev->root_y - dy - frame_xb( window );
+ new_b = new_t + window->u.frame.height + ( frame_xb( window ) << 1 );
+ new_l = ev->root_x - dx - frame_xb( window );
+ new_r = new_l + window->u.frame.width + ( frame_xb( window ) << 1 );
if( !( ev->state & XCB_MOD_MASK_CONTROL ) ) {
int ex, ey;
@@ -647,13 +910,14 @@ extern void synthetic_configure_notify( struct gwm_window *window ) {
msg.response_type = XCB_CONFIGURE_NOTIFY;
msg.event = msg.window = window->u.frame.child->w;
msg.above_sibling = XCB_NONE;
- msg.x = window->u.frame.x + FRAME_BORDER_WIDTH + FRAME_X_BORDER -
+ msg.x = window->u.frame.x + frame_l( window, TRUE ) -
window->u.frame.child->u.managed.border_width;
- msg.y = window->u.frame.y + FRAME_TITLE_HEIGHT + FRAME_X_BORDER -
+ msg.y = window->u.frame.y + frame_t( window, TRUE ) -
window->u.frame.child->u.managed.border_width;
- msg.width = window->u.frame.width - ( FRAME_BORDER_WIDTH << 1 );
- msg.height = window->u.frame.height - FRAME_TITLE_HEIGHT -
- FRAME_BORDER_WIDTH;
+ msg.width = window->u.frame.width - frame_l( window, FALSE ) -
+ frame_r( window, FALSE );
+ msg.height = window->u.frame.height - frame_t( window, FALSE ) -
+ frame_b( window, FALSE );
msg.border_width = window->u.frame.child->u.managed.border_width;
msg.override_redirect = FALSE;
xcb_send_event( c, FALSE, window->u.frame.child->w,
@@ -684,16 +948,17 @@ static void frame_configure_request( struct gwm_window *window,
/* Ignore border width request, but remember what was asked for. */
window->u.frame.child->u.managed.border_width = ev->border_width;
- translate_frame_to_child( &child_x, &child_y, window->u.frame.x,
- window->u.frame.y,
+ translate_frame_to_child( window, &child_x, &child_y,
+ window->u.frame.x, window->u.frame.y,
window->u.frame.child->u.managed.border_width,
window->u.frame.child->u.managed.win_gravity );
x = ev->value_mask & XCB_CONFIG_WINDOW_X ? ev->x : child_x;
y = ev->value_mask & XCB_CONFIG_WINDOW_Y ? ev->y : child_y;
- translate_child_to_frame( &frame_x, &frame_y, &frame_width, &frame_height,
- x, y, ev->width, ev->height,
+ translate_child_to_frame( window, &frame_x, &frame_y,
+ &frame_width, &frame_height, x, y,
+ ev->width, ev->height,
window->u.frame.child->u.managed.border_width,
window->u.frame.child->u.managed.win_gravity );
@@ -717,9 +982,10 @@ static void frame_configure_request( struct gwm_window *window,
if( frame_width != window->u.frame.width ||
frame_height != window->u.frame.height ) {
- values[ 0 ] = frame_width - ( FRAME_BORDER_WIDTH << 1 );
- values[ 1 ] = frame_height - FRAME_TITLE_HEIGHT -
- FRAME_BORDER_WIDTH;
+ values[ 0 ] = frame_width - frame_l( window, FALSE ) -
+ frame_r( window, FALSE );
+ values[ 1 ] = frame_height - frame_t( window, FALSE ) -
+ frame_b( window, FALSE );
xcb_configure_window( c, ev->window, XCB_CONFIG_WINDOW_WIDTH |
XCB_CONFIG_WINDOW_HEIGHT, values );
}
diff --git a/frame.h b/frame.h
index 72c67a6..21ce61b 100644
--- a/frame.h
+++ b/frame.h
@@ -1,6 +1,25 @@
#ifndef FRAME_H
#define FRAME_H
+extern int frame_t( struct gwm_window *window, int include_x_border );
+extern int frame_b( struct gwm_window *window, int include_x_border );
+extern int frame_l( struct gwm_window *window, int include_x_border );
+extern int frame_r( struct gwm_window *window, int include_x_border );
+extern int frame_xb( struct gwm_window *window );
+
+extern void translate_child_to_frame( struct gwm_window *frame,
+ int *fx, int *fy, int *fwidth,
+ int *fheight, int cx, int cy,
+ int cwidth, int cheight,
+ int cborder, int win_gravity );
+
+extern void translate_frame_to_child( struct gwm_window *frame,
+ int *cx, int *cy, int fx, int fy,
+ int cborder, int win_gravity );
+
+extern void apply_size_constraints( struct gwm_window *window, int *width,
+ int *height );
+
extern void synthetic_configure_notify( struct gwm_window *window );
extern event_handler frame_handlers[], childless_handlers[];
diff --git a/gwm.c b/gwm.c
index ef8761b..4d9cbf0 100644
--- a/gwm.c
+++ b/gwm.c
@@ -979,211 +979,6 @@ extern CONST int final_release( xcb_button_release_event_t *ev ) {
return ( ev->state & 0x1F00 ) == ( 0x80 << ev->detail );
}
-extern void translate_child_to_frame( int *fx, int *fy, int *fwidth,
- int *fheight, int cx, int cy,
- int cwidth, int cheight,
- int cborder, int win_gravity ) {
-
- *fwidth = cwidth + FRAME_BORDER_WIDTH * 2;
- *fheight = cheight + FRAME_BORDER_WIDTH + FRAME_TITLE_HEIGHT;
-
- switch( win_gravity ) {
- case XCB_GRAVITY_NORTH_WEST:
- case XCB_GRAVITY_WEST:
- case XCB_GRAVITY_SOUTH_WEST:
- default:
- *fx = cx;
- break;
-
- case XCB_GRAVITY_NORTH:
- case XCB_GRAVITY_CENTER:
- case XCB_GRAVITY_SOUTH:
- case XCB_GRAVITY_STATIC:
- *fx = cx + cborder - FRAME_BORDER_WIDTH - FRAME_X_BORDER;
- break;
-
- case XCB_GRAVITY_NORTH_EAST:
- case XCB_GRAVITY_EAST:
- case XCB_GRAVITY_SOUTH_EAST:
- *fx = cx + ( ( cborder - FRAME_BORDER_WIDTH - FRAME_X_BORDER ) << 1 );
- break;
- }
-
- switch( win_gravity ) {
- case XCB_GRAVITY_NORTH_WEST:
- case XCB_GRAVITY_NORTH:
- case XCB_GRAVITY_NORTH_EAST:
- default:
- *fy = cy;
- break;
-
- case XCB_GRAVITY_WEST:
- case XCB_GRAVITY_CENTER:
- case XCB_GRAVITY_EAST:
- *fy = cy + cborder - ( ( FRAME_BORDER_WIDTH +
- FRAME_TITLE_HEIGHT ) >> 1 ) - FRAME_X_BORDER;
- break;
-
- case XCB_GRAVITY_SOUTH_WEST:
- case XCB_GRAVITY_SOUTH:
- case XCB_GRAVITY_SOUTH_EAST:
- *fy = cy + ( cborder << 1 ) - FRAME_TITLE_HEIGHT - FRAME_BORDER_WIDTH -
- ( FRAME_X_BORDER << 1 );
- break;
-
- case XCB_GRAVITY_STATIC:
- *fy = cy + cborder - FRAME_TITLE_HEIGHT - FRAME_X_BORDER;
- break;
- }
-}
-
-extern void translate_frame_to_child( int *cx, int *cy, int fx, int fy,
- int cborder, int win_gravity ) {
-
- switch( win_gravity ) {
- case XCB_GRAVITY_NORTH_WEST:
- case XCB_GRAVITY_WEST:
- case XCB_GRAVITY_SOUTH_WEST:
- default:
- *cx = fx;
- break;
-
- case XCB_GRAVITY_NORTH:
- case XCB_GRAVITY_CENTER:
- case XCB_GRAVITY_SOUTH:
- case XCB_GRAVITY_STATIC:
- *cx = fx - cborder + FRAME_BORDER_WIDTH + FRAME_X_BORDER;
- break;
-
- case XCB_GRAVITY_NORTH_EAST:
- case XCB_GRAVITY_EAST:
- case XCB_GRAVITY_SOUTH_EAST:
- *cx = fx + ( ( FRAME_BORDER_WIDTH + FRAME_X_BORDER - cborder ) << 1 );
- break;
- }
-
- switch( win_gravity ) {
- case XCB_GRAVITY_NORTH_WEST:
- case XCB_GRAVITY_NORTH:
- case XCB_GRAVITY_NORTH_EAST:
- default:
- *cy = fy;
- break;
-
- case XCB_GRAVITY_WEST:
- case XCB_GRAVITY_CENTER:
- case XCB_GRAVITY_EAST:
- *cy = fy - cborder + ( ( FRAME_BORDER_WIDTH +
- FRAME_TITLE_HEIGHT ) >> 1 ) + FRAME_X_BORDER;
- break;
-
- case XCB_GRAVITY_SOUTH_WEST:
- case XCB_GRAVITY_SOUTH:
- case XCB_GRAVITY_SOUTH_EAST:
- *cy = fy - ( cborder << 1 ) + FRAME_TITLE_HEIGHT + FRAME_BORDER_WIDTH +
- ( FRAME_X_BORDER << 1 );
- break;
-
- case XCB_GRAVITY_STATIC:
- *cy = fy - cborder + FRAME_TITLE_HEIGHT + FRAME_X_BORDER;
- break;
- }
-}
-
-extern void apply_size_constraints( struct gwm_window *window, int *width,
- int *height ) {
-
- int eff_base_width = window->u.managed.base_width ?
- window->u.managed.base_width : window->u.managed.min_width,
- eff_base_height = window->u.managed.base_height ?
- window->u.managed.base_height : window->u.managed.min_height;
-
- /* Apply the minimum and maximum constraints. These are already known
- to be compatible. */
- if( *width < window->u.managed.min_width )
- *width = window->u.managed.min_width;
-
- if( *height < window->u.managed.min_height )
- *height = window->u.managed.min_height;
-
- if( *width > window->u.managed.max_width )
- *width = window->u.managed.max_width;
-
- if( *height > window->u.managed.max_height )
- *height = window->u.managed.max_height;
-
- /* Now round down each dimension to an integer multiple of increments.
- Rounding down cannot violate the maximum constraint, and since
- eff_base_* >= min_*, it will not reduce below the minimum constraint. */
- *width -= ( *width - eff_base_width ) % window->u.managed.width_inc;
- *height -= ( *height - eff_base_height ) % window->u.managed.height_inc;
-
- if( window->u.managed.min_aspect_x * *height >
- window->u.managed.min_aspect_y * *width ) {
- /* Minimum aspect ratio violated. Attempt to either increase the
- width or decrease the height (whichever is a smaller change), but
- don't do either if it would go outside the min/max bounds.
- Both division operations are safe (min_aspect_y is always
- positive, and min_aspect_x must be positive if there is a
- violation). Note that an exact solution might not be possible
- (e.g. certain cases where the aspect ratio and increments are
- coprime). */
- int min_x, max_y;
-
- min_x = ( window->u.managed.min_aspect_x * *height +
- ( window->u.managed.min_aspect_y - 1 ) ) /
- window->u.managed.min_aspect_y + window->u.managed.width_inc - 1;
- min_x -= ( min_x - eff_base_width ) % window->u.managed.width_inc;
-
- max_y = window->u.managed.min_aspect_y * *width /
- window->u.managed.min_aspect_x;
- max_y -= ( max_y - eff_base_height ) % window->u.managed.height_inc;
-
- if( min_x - *width < *height - max_y ) {
- /* The width change is smaller: prefer it if possible. */
- if( min_x >= window->u.managed.min_width )
- *width = min_x;
- else if( max_y < window->u.managed.max_height )
- *height = max_y;
- } else {
- /* The height change is smaller: prefer it if possible. */
- if( max_y < window->u.managed.max_height )
- *height = max_y;
- else if( min_x >= window->u.managed.min_width )
- *width = min_x;
- }
- }
-
- if( window->u.managed.max_aspect_x * *height <
- window->u.managed.max_aspect_y * *width ) {
- /* Maximum aspect ratio violated. Much like the case above... */
- int min_y, max_x;
-
- min_y = ( window->u.managed.max_aspect_y * *width +
- ( window->u.managed.max_aspect_x - 1 ) ) /
- window->u.managed.max_aspect_x + window->u.managed.height_inc - 1;
- min_y -= ( min_y - eff_base_height ) % window->u.managed.height_inc;
-
- max_x = window->u.managed.max_aspect_x * *height /
- window->u.managed.max_aspect_y;
- max_x -= ( max_x - eff_base_width ) % window->u.managed.width_inc;
-
- if( min_y - *height < *width - max_x ) {
- /* The height change is smaller: prefer it if possible. */
- if( min_y >= window->u.managed.min_height )
- *height = min_y;
- else if( max_x < window->u.managed.max_width )
- *width = max_x;
- } else {
- /* The width change is smaller: prefer it if possible. */
- if( max_x < window->u.managed.max_width )
- *width = max_x;
- else if( min_y >= window->u.managed.min_height )
- *height = min_y;
- }
- }
-}
-
static void stop_listening( struct gwm_window *window ) {
uint32_t value;
@@ -1279,7 +1074,7 @@ static void start_managing_window( struct gwm_window *window,
for( i = 0; i < NUM_PROPS; i++ )
managed_property_change( window, i, props[ i ] );
- translate_child_to_frame( &frame->u.frame.x, &frame->u.frame.y,
+ translate_child_to_frame( frame, &frame->u.frame.x, &frame->u.frame.y,
&frame->u.frame.width, &frame->u.frame.height,
geom->x, geom->y, geom->width, geom->height,
geom->border_width,
@@ -1339,7 +1134,8 @@ static void start_managing_window( struct gwm_window *window,
values[ 2 ] = TRUE; /* override redirect */
values[ 3 ] = XCB_EVENT_MASK_EXPOSURE;
xcb_create_window( c, XCB_COPY_FROM_PARENT, button->w, frame->w,
- 2, 1, FRAME_BUTTON_SIZE, FRAME_BUTTON_SIZE, 1,
+ 2, 1, button_size( button, FALSE ),
+ button_size( button, FALSE ), button_xb( button ),
XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT,
XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL |
XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, values );
@@ -1365,8 +1161,8 @@ static void start_managing_window( struct gwm_window *window,
xcb_change_window_attributes( c, w, XCB_CW_EVENT_MASK, values );
}
- xcb_reparent_window( c, w, frame->w, FRAME_BORDER_WIDTH,
- FRAME_TITLE_HEIGHT );
+ xcb_reparent_window( c, w, frame->w, frame_l( frame, FALSE ),
+ frame_t( frame, FALSE ) );
if( !map_request ) {
values[ 0 ] = XCB_EVENT_MASK_STRUCTURE_NOTIFY |
XCB_EVENT_MASK_PROPERTY_CHANGE |
@@ -1576,7 +1372,7 @@ extern void unmanage_window( struct gwm_window *window ) {
/* Reparent the window back to the root; delete its WM_STATE
property (see ICCCM 4.1.4); and map it if it was iconic. */
- translate_frame_to_child( &x, &y, frame->u.frame.x, frame->u.frame.y,
+ translate_frame_to_child( frame, &x, &y, frame->u.frame.x, frame->u.frame.y,
border_width, window->u.managed.win_gravity );
handle_error_reply( xcb_reparent_window_checked(
c, w, screens[ window->screen ]->root,
diff --git a/gwm.h b/gwm.h
index 1ee7540..03d2d9c 100644
--- a/gwm.h
+++ b/gwm.h
@@ -302,17 +302,6 @@ extern xcb_window_t passive_grab;
extern void install_window_colormap( int screen, struct gwm_window *window,
xcb_timestamp_t t );
-extern void translate_child_to_frame( int *fx, int *fy, int *fwidth,
- int *fheight, int cx, int cy,
- int cwidth, int cheight,
- int cborder, int win_gravity );
-
-extern void translate_frame_to_child( int *cx, int *cy, int fx, int fy,
- int cborder, int win_gravity );
-
-extern void apply_size_constraints( struct gwm_window *window, int *width,
- int *height );
-
extern void generic_expose( struct gwm_window *window,
xcb_expose_event_t *ev );
@@ -328,13 +317,6 @@ extern void unmanage_window( struct gwm_window *window );
asynchronous callbacks scheduled for replies and errors. */
extern xcb_generic_event_t *wait_for_event( void );
-#define FRAME_X_BORDER 1 /* X border added to all four sides of frame */
-#define FRAME_BORDER_WIDTH 2 /* pixels added to left, right and bottom;
- includes padding but excludes X border */
-#define FRAME_TITLE_HEIGHT 16 /* pixels added to top; includes title
- bar but excludes X border */
-#define FRAME_BUTTON_SIZE 12 /* size of buttons in title bar; excludes
- X border */
#define FEEDBACK_WIDTH 96 /* width of size feedback window */
#define FEEDBACK_HEIGHT 24 /* height of size feedback window */
diff --git a/managed.c b/managed.c
index c76bb19..c98d47e 100644
--- a/managed.c
+++ b/managed.c
@@ -170,7 +170,8 @@ extern void managed_property_change( struct gwm_window *window, int prop,
if( window->u.managed.state == STATE_NORMAL )
queue_window_update( window->u.managed.frame, 0, 0,
window->u.managed.frame->u.frame.width,
- FRAME_TITLE_HEIGHT, FALSE );
+ frame_t( window->u.managed.frame, FALSE ),
+ FALSE );
} else {
window->u.managed.name = NULL;
window->u.managed.net_wm_name = 0;
@@ -245,15 +246,18 @@ extern void managed_property_change( struct gwm_window *window, int prop,
if( window->u.managed.state == STATE_NORMAL )
queue_window_update( window->u.managed.frame, 0, 0,
window->u.managed.frame->u.frame.width,
- FRAME_TITLE_HEIGHT, FALSE );
+ frame_t( window->u.managed.frame, FALSE ),
+ FALSE );
break;
case PROP_WM_NORMAL_HINTS:
/* WM_NORMAL_HINTS property (see ICCCM 2.0, section 4.1.2.3). */
window->u.managed.hints &= ~HINT_POSITION;
- window->u.managed.min_width = FRAME_TITLE_HEIGHT;
- window->u.managed.min_height = FRAME_TITLE_HEIGHT >> 1;
+ window->u.managed.min_width = frame_t( window->u.managed.frame,
+ FALSE );
+ window->u.managed.min_height = frame_t( window->u.managed.frame,
+ FALSE ) >> 1;
window->u.managed.max_width = 0x7FFF;
window->u.managed.max_height = 0x7FFF;
window->u.managed.width_inc = 1;
@@ -335,13 +339,17 @@ extern void managed_property_change( struct gwm_window *window, int prop,
/* Sanity check. */
screen = screens[ window->screen ];
- if( window->u.managed.min_width < FRAME_TITLE_HEIGHT )
- window->u.managed.min_width = FRAME_TITLE_HEIGHT;
+ if( window->u.managed.min_width < frame_t( window->u.managed.frame,
+ FALSE ) )
+ window->u.managed.min_width = frame_t( window->u.managed.frame,
+ FALSE );
if( window->u.managed.min_width > screen->width_in_pixels )
window->u.managed.min_width = screen->width_in_pixels;
-
- if( window->u.managed.min_height < FRAME_TITLE_HEIGHT >> 1 )
- window->u.managed.min_height = FRAME_TITLE_HEIGHT >> 1;
+
+ if( window->u.managed.min_height < frame_t( window->u.managed.frame,
+ FALSE ) >> 1 )
+ window->u.managed.min_height = frame_t( window->u.managed.frame,
+ FALSE ) >> 1;
if( window->u.managed.min_height > screen->height_in_pixels )
window->u.managed.min_height = screen->height_in_pixels;
@@ -382,9 +390,11 @@ extern void managed_property_change( struct gwm_window *window, int prop,
if( window->u.managed.state == STATE_NORMAL ) {
/* Recalculate constraints. */
int width = window->u.managed.frame->u.frame.width -
- ( FRAME_BORDER_WIDTH << 1 );
+ frame_l( window->u.managed.frame, FALSE ) -
+ frame_r( window->u.managed.frame, FALSE );
int height = window->u.managed.frame->u.frame.height -
- FRAME_TITLE_HEIGHT - FRAME_BORDER_WIDTH;
+ frame_t( window->u.managed.frame, FALSE ) -
+ frame_b( window->u.managed.frame, FALSE );
int old_width, old_height;
old_width = width;
@@ -471,13 +481,15 @@ extern void match_managed_shape( struct gwm_window *window, int shaped ) {
rect.x = rect.y = 0;
rect.width = window->u.managed.frame->u.frame.width;
- rect.height = FRAME_TITLE_HEIGHT;
+ rect.height = frame_t( window->u.managed.frame, FALSE );
xcb_shape_rectangles( c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, 0,
window->u.managed.frame->w, 0, 0, 1, &rect );
xcb_shape_combine( c, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_BOUNDING,
XCB_SHAPE_SK_BOUNDING, window->u.managed.frame->w,
- FRAME_BORDER_WIDTH, FRAME_TITLE_HEIGHT, window->w );
+ frame_l( window->u.managed.frame, FALSE ),
+ frame_t( window->u.managed.frame, FALSE ),
+ window->w );
} else
xcb_shape_mask( c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING,
window->u.managed.frame->w, 0, 0, XCB_NONE );