cheesy client with static bit gravity, used to test the below change.

2002-01-19  Havoc Pennington  <hp@pobox.com>

	* src/wm-tester/test-resizing.c: cheesy client with static
	bit gravity, used to test the below change.

	* src/window.c (meta_window_move_resize_internal): implement
	Owen's proposal for window resizing.
	http://mail.gnome.org/archives/wm-spec-list/1999-November/msg00088.html

	Currently you have to do METACITY_USE_STATIC_GRAVITY=1 in order to
	use it, because some GDK bug is screwing up exposes on my frames
	when it's enabled.

	* src/display.c (meta_display_create_x_cursor): fix glyph for
	NE/NW cursors

	* src/frames.c (get_control): add ability to resize from top

	* src/frame.c (meta_frame_get_flags): can't resize shaded windows
	(meta_frame_sync_to_window): add gravity arg

	* src/common.h (MetaWindowType): move here from window.h so
	it can be used in themes stuff.
	(MetaFrameFlags): remove META_FRAME_TRANSIENT since it
	overlaps with window type and was unused.
This commit is contained in:
Havoc Pennington 2002-01-19 23:59:11 +00:00 committed by Havoc Pennington
parent 19d2e8c7e1
commit 5fdb8463de
13 changed files with 645 additions and 62 deletions

View File

@ -1,3 +1,29 @@
2002-01-19 Havoc Pennington <hp@pobox.com>
* src/wm-tester/test-resizing.c: cheesy client with static
bit gravity, used to test the below change.
* src/window.c (meta_window_move_resize_internal): implement
Owen's proposal for window resizing.
http://mail.gnome.org/archives/wm-spec-list/1999-November/msg00088.html
Currently you have to do METACITY_USE_STATIC_GRAVITY=1 in order to
use it, because some GDK bug is screwing up exposes on my frames
when it's enabled.
* src/display.c (meta_display_create_x_cursor): fix glyph for
NE/NW cursors
* src/frames.c (get_control): add ability to resize from top
* src/frame.c (meta_frame_get_flags): can't resize shaded windows
(meta_frame_sync_to_window): add gravity arg
* src/common.h (MetaWindowType): move here from window.h so
it can be used in themes stuff.
(MetaFrameFlags): remove META_FRAME_TRANSIENT since it
overlaps with window type and was unused.
2002-01-18 Havoc Pennington <hp@pobox.com>
* src/window.c (constrain_position): give priority to keeping NW

View File

@ -34,13 +34,12 @@ typedef enum
META_FRAME_ALLOWS_MAXIMIZE = 1 << 3,
META_FRAME_ALLOWS_VERTICAL_RESIZE = 1 << 4,
META_FRAME_ALLOWS_HORIZONTAL_RESIZE = 1 << 5,
META_FRAME_TRANSIENT = 1 << 6,
META_FRAME_HAS_FOCUS = 1 << 7,
META_FRAME_SHADED = 1 << 8,
META_FRAME_STUCK = 1 << 9,
META_FRAME_MAXIMIZED = 1 << 10,
META_FRAME_ALLOWS_SHADE = 1 << 11,
META_FRAME_ALLOWS_MOVE = 1 << 12
META_FRAME_HAS_FOCUS = 1 << 6,
META_FRAME_SHADED = 1 << 7,
META_FRAME_STUCK = 1 << 8,
META_FRAME_MAXIMIZED = 1 << 9,
META_FRAME_ALLOWS_SHADE = 1 << 10,
META_FRAME_ALLOWS_MOVE = 1 << 11
} MetaFrameFlags;
typedef enum
@ -130,6 +129,19 @@ typedef enum
META_FOCUS_MODE_MOUSE
} MetaFocusMode;
typedef enum
{
META_WINDOW_NORMAL,
META_WINDOW_DESKTOP,
META_WINDOW_DOCK,
META_WINDOW_DIALOG,
META_WINDOW_MODAL_DIALOG,
META_WINDOW_TOOLBAR,
META_WINDOW_MENU,
META_WINDOW_TYPE_LAST
} MetaWindowType;
/* should investigate changing these to whatever most apps use */
#define META_ICON_WIDTH 32
#define META_ICON_HEIGHT 32

View File

@ -179,6 +179,9 @@ meta_display_open (const char *name)
display->prev_focus_window = NULL;
display->showing_desktop = FALSE;
/* FIXME copy the checks from GDK probably */
display->static_gravity_works = g_getenv ("METACITY_USE_STATIC_GRAVITY") != NULL;
/* we have to go ahead and do this so error handlers work */
all_displays = g_slist_prepend (all_displays, display);
@ -1638,10 +1641,10 @@ meta_display_create_x_cursor (MetaDisplay *display,
glyph = XC_bottom_left_corner;
break;
case META_CURSOR_NE_RESIZE:
glyph = XC_top_left_corner;
glyph = XC_top_right_corner;
break;
case META_CURSOR_NW_RESIZE:
glyph = XC_top_right_corner;
glyph = XC_top_left_corner;
break;
default:

View File

@ -118,6 +118,7 @@ struct _MetaDisplay
GList *workspaces;
guint showing_desktop : 1;
guint static_gravity_works : 1;
/*< private-ish >*/
MetaEventQueue *events;

View File

@ -210,7 +210,8 @@ meta_frame_get_flags (MetaFrame *frame)
flags |= META_FRAME_ALLOWS_MOVE;
if (frame->window->has_resize_func &&
!frame->window->maximized)
!frame->window->maximized &&
!frame->window->shaded)
{
if (frame->window->size_hints.min_width <
frame->window->size_hints.max_width)
@ -256,7 +257,8 @@ meta_frame_calc_geometry (MetaFrame *frame,
}
static void
set_background_none (MetaFrame *frame)
set_background_none (MetaFrame *frame,
int resize_gravity)
{
XSetWindowAttributes attrs;
@ -269,6 +271,7 @@ set_background_none (MetaFrame *frame)
void
meta_frame_sync_to_window (MetaFrame *frame,
int resize_gravity,
gboolean need_move,
gboolean need_resize)
{
@ -283,7 +286,7 @@ meta_frame_sync_to_window (MetaFrame *frame,
/* set bg to none to avoid flicker */
if (need_resize)
set_background_none (frame);
set_background_none (frame, resize_gravity);
if (need_move && need_resize)
XMoveResizeWindow (frame->window->display->xdisplay,

View File

@ -67,6 +67,7 @@ MetaFrameFlags meta_frame_get_flags (MetaFrame *frame);
void meta_frame_calc_geometry (MetaFrame *frame,
MetaFrameGeometry *geomp);
void meta_frame_sync_to_window (MetaFrame *frame,
int gravity,
gboolean need_move,
gboolean need_resize);

View File

@ -2042,8 +2042,28 @@ get_control (MetaFrames *frames,
if (has_vert || has_horiz)
{
if (y >= (fgeom.height - fgeom.bottom_height - RESIZE_EXTENDS) &&
x >= (fgeom.width - fgeom.right_width - RESIZE_EXTENDS))
if (y < fgeom.top_height && x < RESIZE_EXTENDS)
{
if (has_vert && has_horiz)
return META_FRAME_CONTROL_RESIZE_NW;
else if (has_vert)
return META_FRAME_CONTROL_RESIZE_N;
else
return META_FRAME_CONTROL_RESIZE_W;
}
else if (y < fgeom.top_height && x >= (fgeom.width - RESIZE_EXTENDS))
{
if (has_vert && has_horiz)
return META_FRAME_CONTROL_RESIZE_NE;
else if (has_vert)
return META_FRAME_CONTROL_RESIZE_N;
else
return META_FRAME_CONTROL_RESIZE_E;
}
else if (y >= (fgeom.height - fgeom.bottom_height - RESIZE_EXTENDS) &&
x >= (fgeom.width - fgeom.right_width - RESIZE_EXTENDS))
{
if (has_vert && has_horiz)
return META_FRAME_CONTROL_RESIZE_SE;
@ -2062,6 +2082,11 @@ get_control (MetaFrames *frames,
else
return META_FRAME_CONTROL_RESIZE_W;
}
else if (y < fgeom.top_height)
{
if (has_vert)
return META_FRAME_CONTROL_RESIZE_N;
}
else if (y >= (fgeom.height - fgeom.bottom_height - RESIZE_EXTENDS))
{
if (has_vert)

View File

@ -666,3 +666,108 @@ meta_texture_spec_draw (const MetaTextureSpec *spec,
break;
}
}
MetaFrameStyle*
meta_frame_style_new (void)
{
MetaFrameStyle *style;
style = g_new0 (MetaFrameStyle, 1);
style->refcount = 1;
return style;
}
void
meta_frame_style_ref (MetaFrameStyle *style)
{
g_return_if_fail (style != NULL);
style->refcount += 1;
}
static void
free_button_textures (MetaTextureSpec *textures[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST])
{
int i, j;
i = 0;
while (i < META_BUTTON_TYPE_LAST)
{
j = 0;
while (j < META_BUTTON_STATE_LAST)
{
if (textures[i][j])
meta_texture_spec_free (textures[i][j]);
++j;
}
++i;
}
}
void
meta_frame_style_unref (MetaFrameStyle *style)
{
g_return_if_fail (style != NULL);
g_return_if_fail (style->refcount > 0);
style->refcount -= 1;
if (style->refcount == 0)
{
int i;
free_button_textures (style->button_icons);
free_button_textures (style->button_backgrounds);
i = 0;
while (i < META_FRAME_PIECE_LAST)
{
if (style->pieces[i])
meta_texture_spec_free (style->pieces[i]);
++i;
}
if (style->layout)
meta_frame_layout_free (style->layout);
g_free (style);
}
}
MetaFrameStyleSet*
meta_frame_style_set_new (void)
{
MetaFrameStyleSet *style_set;
style_set = g_new0 (MetaFrameStyleSet, 1);
return style_set;
}
void
meta_frame_style_set_free (MetaFrameStyleSet *style_set)
{
int i, j;
i = 0;
while (i < META_WINDOW_TYPE_LAST)
{
j = 0;
while (j < META_WINDOW_STATE_LAST)
{
if (style_set->styles[i][j])
meta_frame_style_unref (style_set->styles[i][j]);
++j;
}
++i;
}
g_free (style_set);
}

View File

@ -133,6 +133,14 @@ typedef enum
META_TEXTURE_IMAGE
} MetaTextureType;
typedef enum
{
META_TEXTURE_DRAW_UNSCALED,
META_TEXTURE_DRAW_SCALED_VERTICALLY,
META_TEXTURE_DRAW_SCALED_HORIZONTALLY,
META_TEXTURE_DRAW_SCALED_BOTH
} MetaTextureDrawMode;
struct _MetaTextureSpec
{
MetaTextureType type;
@ -243,22 +251,60 @@ typedef enum
struct _MetaFrameStyle
{
int refcount;
MetaTextureSpec *button_icons[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST];
MetaTextureSpec *button_backgrounds[META_BUTTON_TYPE_LAST][META_BUTTON_STATE_LAST];
MetaTextureSpec *pieces[META_FRAME_PIECE_LAST];
MetaFrameLayout *layout;
};
typedef enum
{
META_TEXTURE_DRAW_UNSCALED,
META_TEXTURE_DRAW_SCALED_VERTICALLY,
META_TEXTURE_DRAW_SCALED_HORIZONTALLY,
META_TEXTURE_DRAW_SCALED_BOTH
} MetaTextureDrawMode;
/* FIXME dammit, these are not mutually exclusive; how to handle
* the mess...
*
* normal -> noresize / vert only / horz only / both
focused / unfocused
* max -> focused / unfocused
* shaded -> focused / unfocused
* max/shaded -> focused / unfocused
*
* so 4 states with 8 sub-states in one, 2 sub-states in the other 3,
* meaning 14 total
*
* 14 window states times 7 or 8 window types.
*
*
* MetaFrameStyleSet needs rearranging to think of it this way.
*
*/
META_WINDOW_STATE_MAXIMIZED,
META_WINDOW_STATE_SHADED,
META_WINDOW_STATE_MAXIMIZED_AND_SHADED,
META_WINDOW_STATE_RESIZE_VERTICAL,
META_WINDOW_STATE_RESIZE_HORIZONTAL,
META_WINDOW_STATE_RESIZE_BOTH,
META_WINDOW_STATE_UNFOCUSED,
META_WINDOW_STATE_FOCUSED,
META_WINDOW_STATE_LAST
} MetaWindowState;
struct _MetaFrameStyleSet
{
MetaFrameStyle *styles[META_WINDOW_TYPE_LAST][META_WINDOW_STATE_LAST];
};
MetaFrameLayout* meta_frame_layout_new (void);
void meta_frame_layout_free (MetaFrameLayout *layout);
void meta_frame_layout_get_borders (const MetaFrameLayout *layout,
GtkWidget *widget,
int text_height,
MetaFrameFlags flags,
int *top_height,
int *bottom_height,
int *left_width,
int *right_width);
void meta_frame_layout_calc_geometry (const MetaFrameLayout *layout,
GtkWidget *widget,
int text_height,
@ -267,6 +313,7 @@ void meta_frame_layout_calc_geometry (const MetaFrameLayout *layout,
int client_height,
MetaFrameGeometry *fgeom);
MetaColorSpec* meta_color_spec_new (MetaColorSpecType type);
void meta_color_spec_free (MetaColorSpec *spec);
void meta_color_spec_render (MetaColorSpec *spec,
@ -296,4 +343,11 @@ void meta_texture_spec_draw (const MetaTextureSpec *desc,
int width,
int height);
MetaFrameStyle* meta_frame_style_new (void);
void meta_frame_style_ref (MetaFrameStyle *style);
void meta_frame_style_unref (MetaFrameStyle *style);
MetaFrameStyleSet* meta_frame_style_set_new (void);
void meta_frame_style_set_free (MetaFrameStyleSet *style_set);
#endif

View File

@ -1518,6 +1518,12 @@ adjust_for_gravity (MetaWindow *window,
}
}
static gboolean
static_gravity_works (MetaDisplay *display)
{
return display->static_gravity_works;
}
static void
meta_window_move_resize_internal (MetaWindow *window,
MetaMoveResizeFlags flags,
@ -1537,14 +1543,19 @@ meta_window_move_resize_internal (MetaWindow *window,
gboolean need_resize_frame = FALSE;
int size_dx;
int size_dy;
int pos_dx;
int pos_dy;
int frame_size_dx;
int frame_size_dy;
gboolean is_configure_request;
gboolean do_gravity_adjust;
gboolean is_user_action;
gboolean configure_frame_first;
gboolean use_static_gravity;
/* used for the configure request, but may not be final
* destination due to StaticGravity etc.
*/
int client_move_x;
int client_move_y;
/* We don't need it in the idle queue anymore. */
meta_window_unqueue_move_resize (window);
@ -1590,12 +1601,10 @@ meta_window_move_resize_internal (MetaWindow *window,
else
new_h = window->rect.height + fgeom.top_height + fgeom.bottom_height;
if (new_w != window->frame->rect.width ||
new_h != window->frame->rect.height)
need_resize_frame = TRUE;
frame_size_dx = new_w - window->frame->rect.width;
frame_size_dy = new_h - window->frame->rect.height;
need_resize_frame = (frame_size_dx != 0 || frame_size_dy != 0);
window->frame->rect.width = new_w;
window->frame->rect.height = new_h;
@ -1675,6 +1684,21 @@ meta_window_move_resize_internal (MetaWindow *window,
default:
break;
}
/* For nice effect, when growing the window we want to move/resize
* the frame first, when shrinking the window we want to move/resize
* the client first. If we grow one way and shrink the other,
* see which way we're moving "more"
*
* Mail from Owen subject "Suggestion: Gravity and resizing from the left"
* http://mail.gnome.org/archives/wm-spec-list/1999-November/msg00088.html
*
* An annoying fact you need to know in this code is that StaticGravity
* does nothing if you _only_ resize or _only_ move the frame;
* it must move _and_ resize, otherwise you get NorthWestGravity
* behavior. The move and resize must actually occur, it is not
* enough to set CWX | CWWidth but pass in the current size/pos.
*/
constrain_position (window,
window->frame ? &fgeom : NULL,
@ -1687,41 +1711,100 @@ meta_window_move_resize_internal (MetaWindow *window,
if (window->frame)
{
int new_x, new_y;
int frame_pos_dx, frame_pos_dy;
/* Compute new frame coords */
new_x = root_x_nw - fgeom.left_width;
new_y = root_y_nw - fgeom.top_height;
if (new_x != window->frame->rect.x ||
new_y != window->frame->rect.y)
need_move_frame = TRUE;
frame_pos_dx = new_x - window->frame->rect.x;
frame_pos_dy = new_y - window->frame->rect.y;
if (window->rect.x != fgeom.left_width ||
window->rect.y != fgeom.top_height)
need_move_client = TRUE;
need_move_frame = (frame_pos_dx != 0 || frame_pos_dy != 0);
window->frame->rect.x = new_x;
window->frame->rect.y = new_y;
window->frame->rect.y = new_y;
/* If frame will both move and resize, then StaticGravity
* on the child window will kick in and implicitly move
* the child with respect to the frame. The implicit
* move will keep the child in the same place with
* respect to the root window. If frame only moves
* or only resizes, then the child will just move along
* with the frame.
*/
/* window->rect.x, window->rect.y are relative to frame,
* remember they are the server coords
*/
pos_dx = fgeom.left_width - window->rect.x;
pos_dy = fgeom.top_height - window->rect.y;
window->rect.x = fgeom.left_width;
window->rect.y = fgeom.top_height;
new_x = fgeom.left_width;
new_y = fgeom.top_height;
if (need_resize_frame && need_move_frame &&
static_gravity_works (window->display))
{
/* static gravity kicks in because frame
* is both moved and resized
*/
/* when we move the frame by frame_pos_dx, frame_pos_dy the
* client will implicitly move relative to frame by the
* inverse delta.
*
* When moving client then frame, we move the client by the
* frame delta, to be canceled out by the implicit move by
* the inverse frame delta, resulting in a client at new_x,
* new_y.
*
* When moving frame then client, we move the client
* by the same delta as the frame, because the client
* was "left behind" by the frame - resulting in a client
* at new_x, new_y.
*
* In both cases we need to move the client window
* in all cases where we had to move the frame window.
*/
client_move_x = new_x + frame_pos_dx;
client_move_y = new_y + frame_pos_dy;
if (need_move_frame)
need_move_client = TRUE;
use_static_gravity = TRUE;
}
else
{
client_move_x = new_x;
client_move_y = new_y;
if (client_move_x != window->rect.x ||
client_move_y != window->rect.y)
need_move_client = TRUE;
use_static_gravity = FALSE;
}
/* This is the final target position, but not necessarily what
* we pass to XConfigureWindow, due to StaticGravity implicit
* movement.
*/
window->rect.x = new_x;
window->rect.y = new_y;
}
else
{
if (root_x_nw != window->rect.x ||
root_y_nw != window->rect.y)
need_move_client = TRUE;
pos_dx = root_x_nw - window->rect.x;
pos_dy = root_y_nw - window->rect.y;
window->rect.x = root_x_nw;
window->rect.y = root_y_nw;
client_move_x = window->rect.x;
client_move_y = window->rect.y;
use_static_gravity = FALSE;
}
/* Fill in other frame member variables */
@ -1736,7 +1819,7 @@ meta_window_move_resize_internal (MetaWindow *window,
/* See ICCCM 4.1.5 for when to send ConfigureNotify */
need_configure_notify = FALSE;
/* If this is a configure request and we change nothing, then we
* must send configure notify.
*/
@ -1756,10 +1839,30 @@ meta_window_move_resize_internal (MetaWindow *window,
/* The rest of this function syncs our new size/pos with X as
* efficiently as possible
*/
if (use_static_gravity)
{
if ((size_dx + size_dy) >= 0)
configure_frame_first = FALSE;
else
configure_frame_first = TRUE;
}
else
{
configure_frame_first = FALSE;
}
if (use_static_gravity)
meta_window_set_gravity (window, StaticGravity);
if (configure_frame_first && window->frame)
meta_frame_sync_to_window (window->frame,
resize_gravity,
need_move_frame, need_resize_frame);
values.border_width = 0;
values.x = window->rect.x;
values.y = window->rect.y;
values.x = client_move_x;
values.y = client_move_y;
values.width = window->rect.width;
values.height = window->rect.height;
@ -1792,12 +1895,14 @@ meta_window_move_resize_internal (MetaWindow *window,
meta_error_trap_pop (window->display);
}
/* Now do the frame */
if (window->frame)
{
meta_frame_sync_to_window (window->frame, need_move_frame, need_resize_frame);
}
if (!configure_frame_first && window->frame)
meta_frame_sync_to_window (window->frame,
resize_gravity,
need_move_frame, need_resize_frame);
/* Put gravity back to be nice to lesser window managers */
if (use_static_gravity)
meta_window_set_gravity (window, NorthWestGravity);
if (need_configure_notify)
send_configure_notify (window);

View File

@ -28,17 +28,6 @@
#include <X11/Xutil.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
typedef enum
{
META_WINDOW_NORMAL,
META_WINDOW_DESKTOP,
META_WINDOW_DOCK,
META_WINDOW_DIALOG,
META_WINDOW_MODAL_DIALOG,
META_WINDOW_TOOLBAR,
META_WINDOW_MENU
} MetaWindowType;
struct _MetaWindow
{
MetaDisplay *display;

View File

@ -10,8 +10,12 @@ test_gravity_SOURCES= \
focus_window_SOURCES= \
focus-window.c
noinst_PROGRAMS=wm-tester test-gravity focus-window
test_resizing_SOURCES= \
test-resizing.c
noinst_PROGRAMS=wm-tester test-gravity test-resizing focus-window
wm_tester_LDADD= @METACITY_LIBS@
test_gravity_LDADD= @METACITY_LIBS@
test_resizing_LDADD= @METACITY_LIBS@
focus_window_LDADD= @METACITY_LIBS@

View File

@ -0,0 +1,255 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <glib.h>
static void
calc_rects (XRectangle *rects, int width, int height)
{
int w = (width - 21) / 3;
int h = (height - 21) / 3;
int i;
i = 0;
while (i < 9)
{
rects[i].width = w;
rects[i].height = h;
++i;
}
/* NW */
rects[0].x = 0;
rects[0].y = 0;
/* N */
rects[1].x = width / 2 - w / 2;
rects[1].y = 0;
/* NE */
rects[2].x = width - w;
rects[2].y = 0;
/* E */
rects[3].x = width - w;
rects[3].y = height / 2 - h / 2;
/* SE */
rects[4].x = width - w;
rects[4].y = height - h;
/* S */
rects[5].x = width / 2 - w / 2;
rects[5].y = height - h;
/* SW */
rects[6].x = 0;
rects[6].y = height - h;
/* W */
rects[7].x = 0;
rects[7].y = height / 2 - h / 2;
/* Center */
rects[8].x = width / 2 - w / 2;
rects[8].y = height / 2 - h / 2;
}
static Bool
all_events (Display *display,
XEvent *event,
XPointer arg)
{
return True;
}
static void
get_size (Display *d, Drawable draw,
int *xp, int *yp, int *widthp, int *heightp)
{
int x, y;
unsigned int width, height, border, depth;
Window root;
XGetGeometry (d, draw, &root, &x, &y, &width, &height, &border, &depth);
if (xp)
*xp = x;
if (yp)
*yp = y;
if (widthp)
*widthp = width;
if (*heightp)
*heightp = height;
}
int
main (int argc, char **argv)
{
Display *d;
Window w, cw;
XSizeHints hints;
int screen;
XEvent ev;
int x, y, width, height;
Pixmap pix;
GC gc;
XGCValues gc_vals;
XSetWindowAttributes set_attrs;
XWindowChanges changes;
XRectangle rects[9];
gboolean redraw_pending;
unsigned int mask;
d = XOpenDisplay (NULL);
screen = DefaultScreen (d);
/* Print some debug spew to show how StaticGravity works */
w = XCreateSimpleWindow (d, RootWindow (d, screen),
0, 0, 100, 100, 0,
WhitePixel (d, screen),
WhitePixel (d, screen));
cw = XCreateSimpleWindow (d, w,
0, 0, 100, 100, 0,
WhitePixel (d, screen),
WhitePixel (d, screen));
set_attrs.win_gravity = StaticGravity;
XChangeWindowAttributes (d, cw,
CWWinGravity,
&set_attrs);
get_size (d, w, &x, &y, &width, &height);
g_print ("Parent is %d,%d %d x %d before configuring parent\n",
x, y, width, height);
get_size (d, cw, &x, &y, &width, &height);
g_print ("Child is %d,%d %d x %d before configuring parent\n",
x, y, width, height);
changes.x = 10;
changes.y = 10;
changes.width = 110;
changes.height = 110;
/* last mask wins */
mask = CWX | CWY;
mask = CWWidth | CWHeight;
mask = CWX | CWY | CWWidth | CWHeight;
XConfigureWindow (d, w, mask, &changes);
XSync (d, False);
get_size (d, w, &x, &y, &width, &height);
g_print ("Parent is %d,%d %d x %d after configuring parent\n",
x, y, width, height);
get_size (d, cw, &x, &y, &width, &height);
g_print ("Child is %d,%d %d x %d after configuring parent\n",
x, y, width, height);
XDestroyWindow (d, w);
/* The window that gets displayed */
x = 20;
y = 20;
width = 100;
height = 100;
calc_rects (rects, width, height);
w = XCreateSimpleWindow (d, RootWindow (d, screen),
x, y, width, height, 0,
WhitePixel (d, screen),
WhitePixel (d, screen));
set_attrs.bit_gravity = StaticGravity;
XChangeWindowAttributes (d, w,
CWBitGravity,
&set_attrs);
XSelectInput (d, w,
ButtonPressMask | ExposureMask | StructureNotifyMask);
hints.flags = PMinSize;
hints.min_width = 100;
hints.min_height = 100;
XSetWMNormalHints (d, w, &hints);
XMapWindow (d, w);
redraw_pending = FALSE;
while (1)
{
XNextEvent (d, &ev);
switch (ev.xany.type)
{
case ButtonPress:
if (ev.xbutton.button == 3)
{
g_print ("Exiting on button 3 press\n");
exit (0);
}
break;
case ConfigureNotify:
x = ev.xconfigure.x;
y = ev.xconfigure.y;
width = ev.xconfigure.width;
height = ev.xconfigure.height;
redraw_pending = TRUE;
break;
case Expose:
redraw_pending = TRUE;
break;
default:
break;
}
/* Primitive event compression */
if (XCheckIfEvent (d, &ev, all_events, NULL))
{
XPutBackEvent (d, &ev);
}
else if (redraw_pending)
{
calc_rects (rects, width, height);
pix = XCreatePixmap (d, w, width, height,
DefaultDepth (d, screen));
gc_vals.foreground = WhitePixel (d, screen);
gc = XCreateGC (d, pix, GCForeground, &gc_vals);
XFillRectangle (d, pix, gc, 0, 0, width, height);
/* Draw rectangles at each gravity point */
gc_vals.foreground = BlackPixel (d, screen);
XChangeGC (d, gc, GCForeground, &gc_vals);
XFillRectangles (d, pix, gc, rects, G_N_ELEMENTS (rects));
XCopyArea (d, pix, w, gc, 0, 0, width, height, 0, 0);
XFreePixmap (d, pix);
XFreeGC (d, gc);
redraw_pending = FALSE;
}
}
return 0;
}