forked from AuroraMiddleware/gtk
Add resize grips to GtkWindow
Allow any window to display a resize grip, in the south-east or south-west corner, depending on text direction. This is implemented as a shaped window that gets overlayed on top of whatever content is there. We add api that allows widgets to avoid the resize grip, if desired. The ::has-resize-grip property controls if a window may display a resize grip. It will only be displayed if the window is resizable and not maximized. The size and visual appearance of the resize grip is under theme control, using the resize-grip-width/height style properties and the paint_resize_grip style function.
This commit is contained in:
parent
368f0d0843
commit
f6347baf64
@ -5051,6 +5051,11 @@ gtk_window_get_opacity
|
||||
gtk_window_set_opacity
|
||||
gtk_window_get_mnemonics_visible
|
||||
gtk_window_set_mnemonics_visible
|
||||
gtk_window_set_has_resize_grip
|
||||
gtk_window_get_has_resize_grip
|
||||
gtk_window_get_resize_grip_is_visible
|
||||
gtk_window_get_resize_grip_area
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_WINDOW
|
||||
GTK_IS_WINDOW
|
||||
|
@ -4379,6 +4379,7 @@ gtk_window_get_frame_dimensions
|
||||
gtk_window_get_gravity
|
||||
gtk_window_get_group
|
||||
gtk_window_get_has_frame
|
||||
gtk_window_get_has_resize_grip
|
||||
gtk_window_get_icon
|
||||
gtk_window_get_icon_list
|
||||
gtk_window_get_icon_name
|
||||
@ -4387,6 +4388,7 @@ gtk_window_get_mnemonics_visible
|
||||
gtk_window_get_modal
|
||||
gtk_window_get_position
|
||||
gtk_window_get_resizable
|
||||
gtk_window_get_resize_grip_area
|
||||
gtk_window_get_role
|
||||
gtk_window_get_screen
|
||||
gtk_window_get_size
|
||||
@ -4423,6 +4425,7 @@ gtk_window_remove_embedded_xid
|
||||
gtk_window_remove_mnemonic
|
||||
gtk_window_reshow_with_initial_size
|
||||
gtk_window_resize
|
||||
gtk_window_resize_grip_is_visible
|
||||
gtk_window_set_accept_focus
|
||||
gtk_window_set_auto_startup_notification
|
||||
gtk_window_set_decorated
|
||||
@ -4441,6 +4444,7 @@ gtk_window_set_frame_dimensions
|
||||
gtk_window_set_geometry_hints
|
||||
gtk_window_set_gravity
|
||||
gtk_window_set_has_frame
|
||||
gtk_window_set_has_resize_grip
|
||||
gtk_window_set_icon
|
||||
gtk_window_set_icon_from_file
|
||||
gtk_window_set_icon_list
|
||||
|
523
gtk/gtkwindow.c
523
gtk/gtkwindow.c
@ -58,6 +58,16 @@
|
||||
* @title: GtkWindow
|
||||
* @short_description: Toplevel which can contain other widgets
|
||||
*
|
||||
* A GtkWindow is a toplevel window which can contain other widgets.
|
||||
* Windows normally have decorations that are under the control
|
||||
* of the windowing system and allow the user to manipulate the window
|
||||
* (resize it, move it, close it,...).
|
||||
*
|
||||
* GTK+ also allows windows to have a resize grip (a small area in the lower
|
||||
* right or left corner) which can be clicked to reszie the window. To
|
||||
* control whether a window has a resize grip, use
|
||||
* gtk_window_set_has_resize_grip().
|
||||
*
|
||||
* <refsect2 id="GtkWindow-BUILDER-UI">
|
||||
* <title>GtkWindow as GtkBuildable</title>
|
||||
* <para>
|
||||
@ -104,6 +114,9 @@ struct _GtkWindowPrivate
|
||||
|
||||
gdouble opacity;
|
||||
|
||||
gboolean has_resize_grip;
|
||||
GdkWindow *grip_window;
|
||||
|
||||
gchar *startup_id;
|
||||
gchar *title;
|
||||
gchar *wmclass_class;
|
||||
@ -116,6 +129,11 @@ struct _GtkWindowPrivate
|
||||
guint frame_top;
|
||||
guint keys_changed_handler;
|
||||
|
||||
/* Don't use this value, it's only used for determining when
|
||||
* to fire notify events on the "resize-grip-visible" property.
|
||||
*/
|
||||
gboolean resize_grip_visible;
|
||||
|
||||
guint16 configure_request_count;
|
||||
|
||||
/* The following flags are initially TRUE (before a window is mapped).
|
||||
@ -200,7 +218,9 @@ enum {
|
||||
PROP_GRAVITY,
|
||||
PROP_TRANSIENT_FOR,
|
||||
PROP_OPACITY,
|
||||
|
||||
PROP_HAS_RESIZE_GRIP,
|
||||
PROP_RESIZE_GRIP_VISIBLE,
|
||||
|
||||
/* Readonly properties */
|
||||
PROP_IS_ACTIVE,
|
||||
PROP_HAS_TOPLEVEL_FOCUS,
|
||||
@ -306,6 +326,8 @@ static gint gtk_window_key_press_event (GtkWidget *widget,
|
||||
GdkEventKey *event);
|
||||
static gint gtk_window_key_release_event (GtkWidget *widget,
|
||||
GdkEventKey *event);
|
||||
static gint gtk_window_button_press_event (GtkWidget *widget,
|
||||
GdkEventButton *event);
|
||||
static gint gtk_window_enter_notify_event (GtkWidget *widget,
|
||||
GdkEventCrossing *event);
|
||||
static gint gtk_window_leave_notify_event (GtkWidget *widget,
|
||||
@ -316,11 +338,17 @@ static gint gtk_window_focus_out_event (GtkWidget *widget,
|
||||
GdkEventFocus *event);
|
||||
static gint gtk_window_client_event (GtkWidget *widget,
|
||||
GdkEventClient *event);
|
||||
static gboolean gtk_window_state_event (GtkWidget *widget,
|
||||
GdkEventWindowState *event);
|
||||
static void gtk_window_check_resize (GtkContainer *container);
|
||||
static gint gtk_window_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static void gtk_window_real_set_focus (GtkWindow *window,
|
||||
GtkWidget *focus);
|
||||
static void gtk_window_direction_changed (GtkWidget *widget,
|
||||
GtkTextDirection prev_dir);
|
||||
static void gtk_window_state_changed (GtkWidget *widget,
|
||||
GtkStateType previous_state);
|
||||
|
||||
static void gtk_window_real_activate_default (GtkWindow *window);
|
||||
static void gtk_window_real_activate_focus (GtkWindow *window);
|
||||
@ -378,6 +406,9 @@ static GList *icon_list_from_theme (GtkWidget *widget,
|
||||
const gchar *name);
|
||||
static void gtk_window_realize_icon (GtkWindow *window);
|
||||
static void gtk_window_unrealize_icon (GtkWindow *window);
|
||||
static void resize_grip_create_window (GtkWindow *window);
|
||||
static void resize_grip_destroy_window (GtkWindow *window);
|
||||
static void update_grip_visibility (GtkWindow *window);
|
||||
|
||||
static void gtk_window_notify_keys_changed (GtkWindow *window);
|
||||
static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
|
||||
@ -541,12 +572,16 @@ gtk_window_class_init (GtkWindowClass *klass)
|
||||
widget_class->enter_notify_event = gtk_window_enter_notify_event;
|
||||
widget_class->leave_notify_event = gtk_window_leave_notify_event;
|
||||
widget_class->focus_in_event = gtk_window_focus_in_event;
|
||||
widget_class->button_press_event = gtk_window_button_press_event;
|
||||
widget_class->focus_out_event = gtk_window_focus_out_event;
|
||||
widget_class->client_event = gtk_window_client_event;
|
||||
widget_class->focus = gtk_window_focus;
|
||||
widget_class->draw = gtk_window_draw;
|
||||
widget_class->get_preferred_width = gtk_window_get_preferred_width;
|
||||
widget_class->get_preferred_height = gtk_window_get_preferred_height;
|
||||
widget_class->window_state_event = gtk_window_state_event;
|
||||
widget_class->direction_changed = gtk_window_direction_changed;
|
||||
widget_class->state_changed = gtk_window_state_changed;
|
||||
|
||||
container_class->check_resize = gtk_window_check_resize;
|
||||
|
||||
@ -804,6 +839,41 @@ gtk_window_class_init (GtkWindowClass *klass)
|
||||
TRUE,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
/**
|
||||
* GtkWindow:has-resize-grip
|
||||
*
|
||||
* Whether the window has a corner resize grip.
|
||||
*
|
||||
* Note that the resize grip is only shown if the window is
|
||||
* actually resizable and not maximized. Use
|
||||
* #GtkWindow:resize-grip-visible to find out if the resize
|
||||
* grip is currently shown.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_HAS_RESIZE_GRIP,
|
||||
g_param_spec_boolean ("has-resize-grip",
|
||||
P_("Resize grip"),
|
||||
P_("Specifies whether the window should have a resize grip"),
|
||||
TRUE,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
/**
|
||||
* GtkWindow: resize-grip-visible:
|
||||
*
|
||||
* Whether a corner resize grip is currently shown.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_RESIZE_GRIP_VISIBLE,
|
||||
g_param_spec_boolean ("resize-grip-visible",
|
||||
P_("Resize grip is visible"),
|
||||
P_("Specifies whether the window's resize grip is visible."),
|
||||
FALSE,
|
||||
GTK_PARAM_READABLE));
|
||||
|
||||
|
||||
/**
|
||||
* GtkWindow:gravity:
|
||||
@ -857,6 +927,24 @@ gtk_window_class_init (GtkWindowClass *klass)
|
||||
1.0,
|
||||
GTK_PARAM_READWRITE));
|
||||
|
||||
|
||||
/* Style properties.
|
||||
*/
|
||||
gtk_widget_class_install_style_property (widget_class,
|
||||
g_param_spec_int ("resize-grip-width",
|
||||
P_("Width of resize grip"),
|
||||
P_("Width of resize grip"),
|
||||
0, G_MAXINT, 16, GTK_PARAM_READWRITE));
|
||||
|
||||
gtk_widget_class_install_style_property (widget_class,
|
||||
g_param_spec_int ("resize-grip-height",
|
||||
P_("Height of resize grip"),
|
||||
P_("Height of resize grip"),
|
||||
0, G_MAXINT, 16, GTK_PARAM_READWRITE));
|
||||
|
||||
|
||||
/* Signals
|
||||
*/
|
||||
window_signals[SET_FOCUS] =
|
||||
g_signal_new (I_("set-focus"),
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
@ -1011,6 +1099,7 @@ gtk_window_init (GtkWindow *window)
|
||||
priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
|
||||
priv->opacity = 1.0;
|
||||
priv->startup_id = NULL;
|
||||
priv->has_resize_grip = TRUE;
|
||||
priv->mnemonics_visible = TRUE;
|
||||
|
||||
g_object_ref_sink (window);
|
||||
@ -1031,7 +1120,7 @@ gtk_window_set_property (GObject *object,
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (object);
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TYPE:
|
||||
@ -1045,10 +1134,9 @@ gtk_window_set_property (GObject *object,
|
||||
break;
|
||||
case PROP_STARTUP_ID:
|
||||
gtk_window_set_startup_id (window, g_value_get_string (value));
|
||||
break;
|
||||
break;
|
||||
case PROP_RESIZABLE:
|
||||
priv->resizable = g_value_get_boolean (value);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (window));
|
||||
gtk_window_set_resizable (window, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_MODAL:
|
||||
gtk_window_set_modal (window, g_value_get_boolean (value));
|
||||
@ -1118,6 +1206,9 @@ gtk_window_set_property (GObject *object,
|
||||
case PROP_OPACITY:
|
||||
gtk_window_set_opacity (window, g_value_get_double (value));
|
||||
break;
|
||||
case PROP_HAS_RESIZE_GRIP:
|
||||
gtk_window_set_has_resize_grip (window, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_MNEMONICS_VISIBLE:
|
||||
gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value));
|
||||
break;
|
||||
@ -1227,6 +1318,12 @@ gtk_window_get_property (GObject *object,
|
||||
case PROP_OPACITY:
|
||||
g_value_set_double (value, gtk_window_get_opacity (window));
|
||||
break;
|
||||
case PROP_HAS_RESIZE_GRIP:
|
||||
g_value_set_boolean (value, priv->has_resize_grip);
|
||||
break;
|
||||
case PROP_RESIZE_GRIP_VISIBLE:
|
||||
g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window));
|
||||
break;
|
||||
case PROP_MNEMONICS_VISIBLE:
|
||||
g_value_set_boolean (value, priv->mnemonics_visible);
|
||||
break;
|
||||
@ -4519,6 +4616,9 @@ gtk_window_map (GtkWidget *widget)
|
||||
if (priv->frame)
|
||||
gdk_window_show (priv->frame);
|
||||
|
||||
if (priv->grip_window)
|
||||
gdk_window_show (priv->grip_window);
|
||||
|
||||
if (!disable_startup_notification)
|
||||
{
|
||||
/* Do we have a custom startup-notification id? */
|
||||
@ -4570,7 +4670,7 @@ gtk_window_unmap (GtkWidget *widget)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (widget);
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
GtkWindowGeometryInfo *info;
|
||||
GtkWindowGeometryInfo *info;
|
||||
GdkWindow *gdk_window;
|
||||
GdkWindowState state;
|
||||
|
||||
@ -4793,6 +4893,9 @@ gtk_window_realize (GtkWidget *widget)
|
||||
|
||||
/* Icons */
|
||||
gtk_window_realize_icon (window);
|
||||
|
||||
if (priv->has_resize_grip)
|
||||
resize_grip_create_window (window);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -4832,9 +4935,106 @@ gtk_window_unrealize (GtkWidget *widget)
|
||||
/* Icons */
|
||||
gtk_window_unrealize_icon (window);
|
||||
|
||||
if (priv->grip_window != NULL)
|
||||
resize_grip_destroy_window (window);
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
|
||||
}
|
||||
|
||||
static GdkWindowEdge
|
||||
get_grip_edge (GtkWidget *widget)
|
||||
{
|
||||
return gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST;
|
||||
}
|
||||
|
||||
static void
|
||||
set_grip_cursor (GtkWindow *window)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (window);
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
GdkWindowEdge edge;
|
||||
GdkDisplay *display;
|
||||
GdkCursorType cursor_type;
|
||||
GdkCursor *cursor;
|
||||
|
||||
if (priv->grip_window == NULL)
|
||||
return;
|
||||
|
||||
if (gtk_widget_is_sensitive (widget))
|
||||
{
|
||||
edge = get_grip_edge (widget);
|
||||
|
||||
if (edge == GDK_WINDOW_EDGE_SOUTH_EAST)
|
||||
cursor_type = GDK_BOTTOM_RIGHT_CORNER;
|
||||
else
|
||||
cursor_type = GDK_BOTTOM_LEFT_CORNER;
|
||||
|
||||
display = gtk_widget_get_display (widget);
|
||||
cursor = gdk_cursor_new_for_display (display, cursor_type);
|
||||
gdk_window_set_cursor (priv->grip_window, cursor);
|
||||
gdk_cursor_unref (cursor);
|
||||
}
|
||||
else
|
||||
gdk_window_set_cursor (priv->grip_window, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
set_grip_shape (GtkWindow *window)
|
||||
{
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
cairo_region_t *region;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
double width, height;
|
||||
|
||||
if (priv->grip_window == NULL)
|
||||
return;
|
||||
|
||||
width = gdk_window_get_width (priv->grip_window);
|
||||
height = gdk_window_get_height (priv->grip_window);
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
|
||||
|
||||
cr = cairo_create (surface);
|
||||
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
|
||||
cairo_paint (cr);
|
||||
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
|
||||
if (get_grip_edge (GTK_WIDGET (window)) == GDK_WINDOW_EDGE_SOUTH_EAST)
|
||||
{
|
||||
cairo_move_to (cr, width, 0.0);
|
||||
cairo_line_to (cr, width, height);
|
||||
cairo_line_to (cr, 0.0, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_move_to (cr, 0.0, 0.0);
|
||||
cairo_line_to (cr, width, height);
|
||||
cairo_line_to (cr, 0.0, height);
|
||||
}
|
||||
cairo_close_path (cr);
|
||||
cairo_fill (cr);
|
||||
cairo_destroy (cr);
|
||||
region = gdk_cairo_region_create_from_surface (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
gdk_window_shape_combine_region (priv->grip_window, region, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
set_grip_position (GtkWindow *window)
|
||||
{
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
GdkRectangle rect;
|
||||
|
||||
if (priv->grip_window == NULL)
|
||||
return;
|
||||
|
||||
gtk_window_get_resize_grip_area (window, &rect);
|
||||
gdk_window_raise (priv->grip_window);
|
||||
gdk_window_move_resize (priv->grip_window,
|
||||
rect.x, rect.y,
|
||||
rect.width, rect.height);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
@ -4987,11 +5187,263 @@ gtk_window_configure_event (GtkWidget *widget,
|
||||
allocation.height = event->height;
|
||||
gtk_widget_set_allocation (widget, &allocation);
|
||||
|
||||
gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again?
|
||||
|
||||
_gtk_container_queue_resize (GTK_CONTAINER (widget));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_window_state_event (GtkWidget *widget,
|
||||
GdkEventWindowState *event)
|
||||
{
|
||||
update_grip_visibility (GTK_WINDOW (widget));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_direction_changed (GtkWidget *widget,
|
||||
GtkTextDirection prev_dir)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (widget);
|
||||
|
||||
set_grip_cursor (window);
|
||||
set_grip_position (window);
|
||||
set_grip_shape (window);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_state_changed (GtkWidget *widget,
|
||||
GtkStateType previous_state)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (widget);
|
||||
|
||||
set_grip_cursor (window);
|
||||
update_grip_visibility (window);
|
||||
}
|
||||
|
||||
static void
|
||||
resize_grip_create_window (GtkWindow *window)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkWindowPrivate *priv;
|
||||
GdkWindowAttr attributes;
|
||||
gint attributes_mask;
|
||||
GdkRectangle rect;
|
||||
|
||||
priv = window->priv;
|
||||
widget = GTK_WIDGET (window);
|
||||
|
||||
g_return_if_fail (gtk_widget_get_realized (widget));
|
||||
g_return_if_fail (priv->grip_window == NULL);
|
||||
|
||||
gtk_window_get_resize_grip_area (window, &rect);
|
||||
|
||||
attributes.x = rect.x;
|
||||
attributes.y = rect.y;
|
||||
attributes.width = rect.width;
|
||||
attributes.height = rect.height;
|
||||
attributes.window_type = GDK_WINDOW_CHILD;
|
||||
attributes.wclass = GDK_INPUT_OUTPUT;
|
||||
attributes.event_mask = gtk_widget_get_events (widget) |
|
||||
GDK_EXPOSURE_MASK |
|
||||
GDK_BUTTON_PRESS_MASK;
|
||||
|
||||
attributes_mask = GDK_WA_X | GDK_WA_Y;
|
||||
|
||||
priv->grip_window = gdk_window_new (gtk_widget_get_window (widget),
|
||||
&attributes,
|
||||
attributes_mask);
|
||||
|
||||
gdk_window_set_user_data (priv->grip_window, widget);
|
||||
|
||||
gdk_window_raise (priv->grip_window);
|
||||
|
||||
set_grip_cursor (window);
|
||||
set_grip_shape (window);
|
||||
update_grip_visibility (window);
|
||||
}
|
||||
|
||||
static void
|
||||
resize_grip_destroy_window (GtkWindow *window)
|
||||
{
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
|
||||
gdk_window_set_user_data (priv->grip_window, NULL);
|
||||
gdk_window_destroy (priv->grip_window);
|
||||
priv->grip_window = NULL;
|
||||
update_grip_visibility (window);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_window_set_has_resize_grip:
|
||||
* @window: a #GtkWindow
|
||||
* @value: %TRUE to allow a resize grip
|
||||
*
|
||||
* Sets whether @window has a corner resize grip.
|
||||
*
|
||||
* Note that the resize grip is only shown if the window
|
||||
* is actually resizable and not maximized. Use
|
||||
* gtk_window_resize_grip_is_visible() to find out if the
|
||||
* resize grip is currently shown.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
void
|
||||
gtk_window_set_has_resize_grip (GtkWindow *window,
|
||||
gboolean value)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (window);
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
|
||||
value = value != FALSE;
|
||||
|
||||
if (value != priv->has_resize_grip)
|
||||
{
|
||||
priv->has_resize_grip = value;
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
if (gtk_widget_get_realized (widget))
|
||||
{
|
||||
if (priv->has_resize_grip && priv->grip_window == NULL)
|
||||
resize_grip_create_window (window);
|
||||
else if (!priv->has_resize_grip && priv->grip_window != NULL)
|
||||
resize_grip_destroy_window (window);
|
||||
}
|
||||
|
||||
g_object_notify (G_OBJECT (window), "has-resize-grip");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_grip_visibility (GtkWindow *window)
|
||||
{
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
gboolean val;
|
||||
|
||||
val = gtk_window_resize_grip_is_visible (window);
|
||||
|
||||
if (priv->grip_window != NULL)
|
||||
{
|
||||
if (val)
|
||||
gdk_window_show (priv->grip_window);
|
||||
else
|
||||
gdk_window_hide (priv->grip_window);
|
||||
}
|
||||
|
||||
if (priv->resize_grip_visible != val)
|
||||
{
|
||||
priv->resize_grip_visible = val;
|
||||
|
||||
g_object_notify (G_OBJECT (window), "resize-grip-visible");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_window_resize_grip_is_visible:
|
||||
* @window: a #GtkWindow
|
||||
*
|
||||
* Determines whether a resize grip is visible for the specified window.
|
||||
*
|
||||
* Returns %TRUE if a resize grip exists and is visible.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
gboolean
|
||||
gtk_window_resize_grip_is_visible (GtkWindow *window)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
|
||||
|
||||
if (!window->priv->resizable)
|
||||
return FALSE;
|
||||
|
||||
if (gtk_widget_get_realized (GTK_WIDGET (window)))
|
||||
{
|
||||
GdkWindowState state;
|
||||
|
||||
state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
|
||||
|
||||
if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return window->priv->has_resize_grip;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_window_get_has_resize_grip:
|
||||
* @window: a #GtkWindow
|
||||
*
|
||||
* Determines whether the window may has a resize grip.
|
||||
*
|
||||
* Returns: %TRUE if the window has a resize grip.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
gboolean
|
||||
gtk_window_get_has_resize_grip (GtkWindow *window)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
|
||||
|
||||
return window->priv->has_resize_grip;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_window_get_resize_grip_area:
|
||||
* @window: a #GtkWindow
|
||||
* @rect: a pointer to a #GdkRectangle which we should store the
|
||||
* resize grip area.
|
||||
*
|
||||
* If a window has a resize grip, this will retrieve the grip
|
||||
* position, width and height into the specified #GdkRectangle.
|
||||
*
|
||||
* Returns: %TRUE if the resize grip's area was retrieved.
|
||||
*
|
||||
* Since: 3.0
|
||||
*/
|
||||
gboolean
|
||||
gtk_window_get_resize_grip_area (GtkWindow *window,
|
||||
GdkRectangle *rect)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (window);
|
||||
GtkAllocation allocation;
|
||||
GtkStyle *style;
|
||||
gint grip_width;
|
||||
gint grip_height;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
|
||||
|
||||
if (!window->priv->has_resize_grip)
|
||||
return FALSE;
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
style = gtk_widget_get_style (widget);
|
||||
|
||||
gtk_widget_style_get (widget,
|
||||
"resize-grip-width", &grip_width,
|
||||
"resize-grip-height", &grip_height,
|
||||
NULL);
|
||||
|
||||
if (grip_width > allocation.width)
|
||||
grip_width = allocation.width;
|
||||
|
||||
if (grip_height > allocation.height)
|
||||
grip_height = allocation.height;
|
||||
|
||||
rect->width = grip_width;
|
||||
rect->height = grip_height;
|
||||
rect->y = allocation.y + allocation.height - grip_height;
|
||||
|
||||
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
|
||||
rect->x = allocation.x + allocation.width - grip_width;
|
||||
else
|
||||
rect->x = allocation.x;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* the accel_key and accel_mods fields of the key have to be setup
|
||||
* upon calling this function. it'll then return whether that key
|
||||
* is at all used as accelerator, and if so will OR in the
|
||||
@ -5130,6 +5582,23 @@ gtk_window_key_release_event (GtkWidget *widget,
|
||||
return handled;
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_window_button_press_event (GtkWidget *widget,
|
||||
GdkEventButton *event)
|
||||
{
|
||||
GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
|
||||
|
||||
if (event->window == priv->grip_window)
|
||||
gtk_window_begin_resize_drag (GTK_WINDOW (widget),
|
||||
get_grip_edge (widget),
|
||||
event->button,
|
||||
event->x_root,
|
||||
event->y_root,
|
||||
event->time);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_real_activate_default (GtkWindow *window)
|
||||
{
|
||||
@ -6245,6 +6714,13 @@ gtk_window_move_resize (GtkWindow *window)
|
||||
/* gtk_window_configure_event() filled in widget->allocation */
|
||||
gtk_widget_size_allocate (widget, &allocation);
|
||||
|
||||
if (priv->grip_window != NULL)
|
||||
{
|
||||
set_grip_position (window);
|
||||
set_grip_cursor (window);
|
||||
set_grip_shape (window);
|
||||
}
|
||||
|
||||
gdk_window_process_updates (gdk_window, TRUE);
|
||||
|
||||
gdk_window_configure_finished (gdk_window);
|
||||
@ -6336,7 +6812,7 @@ gtk_window_move_resize (GtkWindow *window)
|
||||
gdk_window_resize (gdk_window,
|
||||
new_request.width, new_request.height);
|
||||
}
|
||||
|
||||
|
||||
if (priv->type == GTK_WINDOW_POPUP)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
@ -6631,6 +7107,9 @@ static gboolean
|
||||
gtk_window_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
if (!gtk_widget_get_app_paintable (widget))
|
||||
gtk_paint_flat_box (gtk_widget_get_style (widget),
|
||||
cr,
|
||||
@ -6639,11 +7118,30 @@ gtk_window_draw (GtkWidget *widget,
|
||||
0, 0,
|
||||
gtk_widget_get_allocated_width (widget),
|
||||
gtk_widget_get_allocated_height (widget));
|
||||
|
||||
if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
|
||||
return GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
|
||||
|
||||
return FALSE;
|
||||
if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
|
||||
ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
|
||||
|
||||
if (priv->has_resize_grip &&
|
||||
gtk_cairo_should_draw_window (cr, priv->grip_window))
|
||||
{
|
||||
GdkRectangle rect;
|
||||
|
||||
cairo_save (cr);
|
||||
gtk_cairo_transform_to_window (cr, widget, priv->grip_window);
|
||||
gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect);
|
||||
gtk_paint_resize_grip (gtk_widget_get_style (widget),
|
||||
cr,
|
||||
gtk_widget_get_state (widget),
|
||||
widget,
|
||||
"statusbar",
|
||||
get_grip_edge (widget),
|
||||
0, 0,
|
||||
rect.width, rect.height);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -7284,6 +7782,9 @@ gtk_window_set_resizable (GtkWindow *window,
|
||||
|
||||
g_object_notify (G_OBJECT (window), "resizable");
|
||||
|
||||
if (priv->grip_window != NULL)
|
||||
update_grip_visibility (window);
|
||||
|
||||
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
|
||||
}
|
||||
|
||||
|
@ -338,6 +338,16 @@ GtkWidget * gtk_window_group_get_current_device_grab (GtkWindowGroup *windo
|
||||
GdkDevice *device);
|
||||
|
||||
|
||||
/* Window grips
|
||||
*/
|
||||
void gtk_window_set_has_resize_grip (GtkWindow *window,
|
||||
gboolean value);
|
||||
gboolean gtk_window_get_has_resize_grip (GtkWindow *window);
|
||||
gboolean gtk_window_resize_grip_is_visible (GtkWindow *window);
|
||||
gboolean gtk_window_get_resize_grip_area (GtkWindow *window,
|
||||
GdkRectangle *rect);
|
||||
|
||||
|
||||
/* --- internal functions --- */
|
||||
void _gtk_window_internal_set_focus (GtkWindow *window,
|
||||
GtkWidget *focus);
|
||||
|
Loading…
Reference in New Issue
Block a user