Commit 5fdb8463 authored by Havoc Pennington's avatar Havoc Pennington Committed by Havoc Pennington
Browse files

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.
parent 19d2e8c7
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
......
......@@ -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
......
......@@ -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:
......
......@@ -118,6 +118,7 @@ struct _MetaDisplay
GList *workspaces;
guint showing_desktop : 1;
guint static_gravity_works : 1;
/*< private-ish >*/
MetaEventQueue *events;
......
......@@ -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,
......
......@@ -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);
......
......@@ -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)
......
......@@ -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);
}
......@@ -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
......@@ -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 */