* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
{
GtkMnemonicHash *mnemonic_hash;
+ GtkWidget *attach_widget;
GtkWidget *default_widget;
GtkWidget *focus_widget;
GtkWindow *transient_parent;
PROP_DELETABLE,
PROP_GRAVITY,
PROP_TRANSIENT_FOR,
+ PROP_ATTACHED_TO,
PROP_OPACITY,
PROP_HAS_RESIZE_GRIP,
PROP_RESIZE_GRIP_VISIBLE,
gint *minimum_size,
gint *natural_size);
-static void ensure_state_flag_window_unfocused (GtkWidget *widget);
+static void ensure_state_flag_backdrop (GtkWidget *widget);
G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
GTK_PARAM_READWRITE));
/**
- * GtkWindow:has-resize-grip
+ * GtkWindow:has-resize-grip:
*
* Whether the window has a corner resize grip.
*
GTK_TYPE_WINDOW,
GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT));
+ /**
+ * GtkWindow:attached-to:
+ *
+ * The widget to which this window is attached.
+ * See gtk_window_set_attached_to().
+ *
+ * Examples of places where specifying this relation is useful are
+ * for instance a #GtkMenu created by a #GtkComboBox, a completion
+ * popup window created by #GtkEntry or a typeahead search entry
+ * created by #GtkTreeView.
+ *
+ * Since: 3.4
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_ATTACHED_TO,
+ g_param_spec_object ("attached-to",
+ P_("Attached to Widget"),
+ P_("The widget where the window is attached"),
+ GTK_TYPE_WIDGET,
+ GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
/**
* GtkWindow:opacity:
*
case PROP_TRANSIENT_FOR:
gtk_window_set_transient_for (window, g_value_get_object (value));
break;
+ case PROP_ATTACHED_TO:
+ gtk_window_set_attached_to (window, g_value_get_object (value));
+ break;
case PROP_OPACITY:
gtk_window_set_opacity (window, g_value_get_double (value));
break;
case PROP_TRANSIENT_FOR:
g_value_set_object (value, gtk_window_get_transient_for (window));
break;
+ case PROP_ATTACHED_TO:
+ g_value_set_object (value, gtk_window_get_attached_to (window));
+ break;
case PROP_OPACITY:
g_value_set_double (value, gtk_window_get_opacity (window));
break;
return list;
}
+static void
+remove_attach_widget (GtkWindow *window)
+{
+ GtkWindowPrivate *priv = window->priv;
+
+ if (priv->attach_widget)
+ {
+ _gtk_widget_remove_attached_window (priv->attach_widget, window);
+
+ g_object_unref (priv->attach_widget);
+ priv->attach_widget = NULL;
+ }
+}
+
static void
gtk_window_dispose (GObject *object)
{
gtk_window_set_focus (window, NULL);
gtk_window_set_default (window, NULL);
+ remove_attach_widget (GTK_WINDOW (object));
+
G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
}
return window->priv->transient_parent;
}
+/**
+ * gtk_window_set_attached_to:
+ * @window: a #GtkWindow
+ * @attach_widget: (allow-none): a #GtkWidget, or %NULL
+ *
+ * Marks @window as attached to @attach_widget. This creates a logical binding
+ * between the window and the widget it belongs to, which is used by GTK+ to
+ * propagate information such as styling or accessibility to @window as if it
+ * was a children of @attach_widget.
+ *
+ * Examples of places where specifying this relation is useful are for instance
+ * a #GtkMenu created by a #GtkComboBox, a completion popup window
+ * created by #GtkEntry or a typeahead search entry created by #GtkTreeView.
+ *
+ * Note that this function should not be confused with
+ * gtk_window_set_transient_for(), which specifies a window manager relation
+ * between two toplevels instead.
+ *
+ * Passing %NULL for @attach_widget detaches the window.
+ *
+ * Since: 3.4
+ **/
+void
+gtk_window_set_attached_to (GtkWindow *window,
+ GtkWidget *attach_widget)
+{
+ GtkStyleContext *context;
+ GtkWindowPrivate *priv;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_WIDGET (window) != attach_widget);
+
+ priv = window->priv;
+
+ if (priv->attach_widget == attach_widget)
+ return;
+
+ remove_attach_widget (window);
+
+ priv->attach_widget = attach_widget;
+
+ if (priv->attach_widget)
+ {
+ _gtk_widget_add_attached_window (priv->attach_widget, window);
+
+ g_object_ref (priv->attach_widget);
+ }
+
+ /* Update the style, as the widget path might change. */
+ context = gtk_widget_get_style_context (GTK_WIDGET (window));
+ if (priv->attach_widget)
+ gtk_style_context_set_parent (context, gtk_widget_get_style_context (priv->attach_widget));
+ else
+ gtk_style_context_set_parent (context, NULL);
+}
+
+/**
+ * gtk_window_get_attached_to:
+ * @window: a #GtkWindow
+ *
+ * Fetches the attach widget for this window. See
+ * gtk_window_set_attached_to().
+ *
+ * Return value: (transfer none): the widget where the window is attached,
+ * or %NULL if the window is not attached to any widget.
+ *
+ * Since: 3.4
+ **/
+GtkWidget *
+gtk_window_get_attached_to (GtkWindow *window)
+{
+ g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
+
+ return window->priv->attach_widget;
+}
+
/**
* gtk_window_set_opacity:
* @window: a #GtkWindow
{
GtkIconTheme *icon_theme;
- g_list_foreach (icon_list, (GFunc) g_object_unref, NULL);
- g_list_free (icon_list);
+ g_list_free_full (icon_list, g_object_unref);
icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
g_signal_connect (icon_theme, "changed",
g_list_foreach (list,
(GFunc) g_object_ref, NULL);
- g_list_foreach (info->icon_list,
- (GFunc) g_object_unref, NULL);
-
- g_list_free (info->icon_list);
+ g_list_free_full (info->icon_list, g_object_unref);
info->icon_list = g_list_copy (list);
info->icon_name = g_strdup (name);
g_free (tmp);
- g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL);
- g_list_free (info->icon_list);
+ g_list_free_full (info->icon_list, g_object_unref);
info->icon_list = NULL;
update_themed_icon (NULL, window);
g_list_foreach (list,
(GFunc) g_object_ref, NULL);
- g_list_foreach (default_icon_list,
- (GFunc) g_object_unref, NULL);
-
- g_list_free (default_icon_list);
+ g_list_free_full (default_icon_list, g_object_unref);
default_icon_list = g_list_copy (list);
g_free (default_icon_name);
default_icon_name = g_strdup (name);
- g_list_foreach (default_icon_list,
- (GFunc) g_object_unref, NULL);
-
- g_list_free (default_icon_list);
+ g_list_free_full (default_icon_list, g_object_unref);
default_icon_list = NULL;
/* Update all toplevels */
/**
* gtk_window_get_position:
* @window: a #GtkWindow
- * @root_x: (out) (allow-none): eturn location for X coordinate of
+ * @root_x: (out) (allow-none): return location for X coordinate of
* gravity-determined reference point, or %NULL
* @root_y: (out) (allow-none): return location for Y coordinate of
* gravity-determined reference point, or %NULL
if (priv->transient_parent)
gtk_window_set_transient_for (window, NULL);
+ remove_attach_widget (GTK_WINDOW (widget));
+
/* frees the icons */
gtk_window_set_icon_list (window, NULL);
_gtk_widget_set_visible_flag (widget, TRUE);
- need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget);
- _gtk_container_set_need_resize (container, FALSE);
+ need_resize = _gtk_widget_get_alloc_needed (widget) || !gtk_widget_get_realized (widget);
if (need_resize)
{
else
gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
- ensure_state_flag_window_unfocused (widget);
+ ensure_state_flag_backdrop (widget);
}
static gboolean
}
#endif
- gtk_window_set_application (window, gtk_window_get_application (window));
-
/* Icons */
gtk_window_realize_icon (window);
rect.width, rect.height);
}
-static void
-gtk_window_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
+/* _gtk_window_set_allocation:
+ * @window: a #GtkWindow
+ * @allocation: the new allocation
+ *
+ * This function is like gtk_widget_set_allocation()
+ * but does the necessary extra work to update
+ * the resize grip positioning, etc.
+ *
+ * Call this instead of gtk_widget_set_allocation()
+ * when overriding ::size_allocate in a GtkWindow
+ * subclass without chaining up.
+ */
+void
+_gtk_window_set_allocation (GtkWindow *window,
+ GtkAllocation *allocation)
{
- GtkWindow *window = GTK_WINDOW (widget);
- GtkAllocation child_allocation;
- GtkWidget *child;
- guint border_width;
+ GtkWidget *widget = (GtkWidget *)window;
gtk_widget_set_allocation (widget, allocation);
if (gtk_widget_get_realized (widget))
{
- /* If it's not a toplevel we're embedded, we need to resize the window's
- * window and skip the grip.
+ /* If it's not a toplevel we're embedded, we need to resize
+ * the window's window and skip the grip.
*/
if (!gtk_widget_is_toplevel (widget))
- {
- gdk_window_move_resize (gtk_widget_get_window (widget),
- allocation->x, allocation->y,
- allocation->width, allocation->height);
- }
+ {
+ gdk_window_move_resize (gtk_widget_get_window (widget),
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+ }
else
- {
- update_grip_visibility (window);
- set_grip_position (window);
- }
+ {
+ update_grip_visibility (window);
+ set_grip_position (window);
+ }
}
+}
+
+static void
+gtk_window_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkWindow *window = GTK_WINDOW (widget);
+ GtkAllocation child_allocation;
+ GtkWidget *child;
+ guint border_width;
+
+ _gtk_window_set_allocation (window, allocation);
child = gtk_bin_get_child (&(window->bin));
if (child && gtk_widget_get_visible (child))
border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
child_allocation.x = border_width;
child_allocation.y = border_width;
- child_allocation.width =
- MAX (1, (gint)allocation->width - child_allocation.x * 2);
- child_allocation.height =
- MAX (1, (gint)allocation->height - child_allocation.y * 2);
+ child_allocation.width = MAX (1, allocation->width - border_width * 2);
+ child_allocation.height = MAX (1, allocation->height - border_width * 2);
gtk_widget_size_allocate (child, &child_allocation);
}
update_grip_visibility (GTK_WINDOW (widget));
if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
- ensure_state_flag_window_unfocused (widget);
+ ensure_state_flag_backdrop (widget);
return FALSE;
}
* Since: 3.0
*/
gboolean
-gtk_window_get_resize_grip_area (GtkWindow *window,
+gtk_window_get_resize_grip_area (GtkWindow *window,
GdkRectangle *rect)
{
GtkWidget *widget = GTK_WIDGET (window);
context = gtk_widget_get_style_context (widget);
- gtk_style_context_save (context);
-
if (!gtk_widget_get_app_paintable (widget) &&
gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
{
- GtkStateFlags state;
-
- state = gtk_widget_get_state_flags (widget);
-
- if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget)))
- state |= GTK_STATE_FLAG_FOCUSED;
+ gtk_style_context_save (context);
- gtk_style_context_set_state (context, state);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
gtk_render_background (context, cr, 0, 0,
gtk_widget_get_allocated_width (widget),
gtk_widget_get_allocated_height (widget));
- }
- gtk_style_context_restore (context);
+ gtk_style_context_restore (context);
+ }
if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr);
}
static void
-ensure_state_flag_window_unfocused (GtkWidget *widget)
+ensure_state_flag_backdrop (GtkWidget *widget)
{
GdkWindow *window;
gboolean window_focused = TRUE;
window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
if (!window_focused)
- gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED, FALSE);
+ gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);
else
- gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED);
+ gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
gtk_widget_queue_draw (widget);
}