mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-13 05:50:10 +00:00
window: Add initial support for client-side decorations under Wayland
This change comprises four main parts: * the creation of the widgets that form the decorations, * implementation of get_preferred_height/width, and the for_width/for_height variants, * taking the decorations into account when allocating, * and drawing the decorations themselves. Kristian did the bulk of the original work on this but any bugs are almost certainly mine through the many refactorings and rebasings.
This commit is contained in:
parent
3f9455301e
commit
6a8362111e
621
gtk/gtkwindow.c
621
gtk/gtkwindow.c
@ -49,6 +49,9 @@
|
||||
#include "gtkintl.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtkbox.h"
|
||||
#include "gtkbutton.h"
|
||||
#include "gtkheaderbar.h"
|
||||
#include "a11y/gtkwindowaccessible.h"
|
||||
|
||||
#include "deprecated/gtkstyle.h"
|
||||
@ -57,6 +60,10 @@
|
||||
#include "x11/gdkx.h"
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
#include "wayland/gdkwayland.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION:gtkwindow
|
||||
* @title: GtkWindow
|
||||
@ -134,6 +141,12 @@ struct _GtkWindowPrivate
|
||||
|
||||
guint auto_mnemonics_timeout_id;
|
||||
|
||||
GtkWidget *title_box;
|
||||
GtkWidget *title_icon;
|
||||
GtkWidget *title_min_button;
|
||||
GtkWidget *title_max_button;
|
||||
GtkWidget *title_close_button;
|
||||
|
||||
/* The following flags are initially TRUE (before a window is mapped).
|
||||
* They cause us to compute a configure request that involves
|
||||
* default-only parameters. Once mapped, we set them to FALSE.
|
||||
@ -183,6 +196,7 @@ struct _GtkWindowPrivate
|
||||
* grip-visible" notification
|
||||
*/
|
||||
guint gravity : 5; /* GdkGravity */
|
||||
guint client_decorated : 1; /* Decorations drawn client-side */
|
||||
|
||||
};
|
||||
|
||||
@ -348,6 +362,10 @@ static void gtk_window_style_updated (GtkWidget *widget);
|
||||
static gboolean gtk_window_state_event (GtkWidget *widget,
|
||||
GdkEventWindowState *event);
|
||||
static void gtk_window_check_resize (GtkContainer *container);
|
||||
static void gtk_window_forall (GtkContainer *container,
|
||||
gboolean include_internals,
|
||||
GtkCallback callback,
|
||||
gpointer callback_data);
|
||||
static gint gtk_window_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static void gtk_window_move_focus (GtkWidget *widget,
|
||||
@ -429,6 +447,23 @@ static void gtk_window_on_theme_variant_changed (GtkSettings *settings,
|
||||
#endif
|
||||
static void gtk_window_set_theme_variant (GtkWindow *window);
|
||||
|
||||
|
||||
static void gtk_window_get_preferred_width (GtkWidget *widget,
|
||||
gint *minimum_size,
|
||||
gint *natural_size);
|
||||
static void gtk_window_get_preferred_width_for_height (GtkWidget *widget,
|
||||
gint height,
|
||||
gint *minimum_size,
|
||||
gint *natural_size);
|
||||
|
||||
static void gtk_window_get_preferred_height (GtkWidget *widget,
|
||||
gint *minimum_size,
|
||||
gint *natural_size);
|
||||
static void gtk_window_get_preferred_height_for_width (GtkWidget *widget,
|
||||
gint width,
|
||||
gint *minimum_size,
|
||||
gint *natural_size);
|
||||
|
||||
static GSList *toplevel_list = NULL;
|
||||
static guint window_signals[LAST_SIGNAL] = { 0 };
|
||||
static GList *default_icon_list = NULL;
|
||||
@ -589,8 +624,13 @@ gtk_window_class_init (GtkWindowClass *klass)
|
||||
widget_class->direction_changed = gtk_window_direction_changed;
|
||||
widget_class->state_changed = gtk_window_state_changed;
|
||||
widget_class->style_updated = gtk_window_style_updated;
|
||||
widget_class->get_preferred_width = gtk_window_get_preferred_width;
|
||||
widget_class->get_preferred_width_for_height = gtk_window_get_preferred_width_for_height;
|
||||
widget_class->get_preferred_height = gtk_window_get_preferred_height;
|
||||
widget_class->get_preferred_height_for_width = gtk_window_get_preferred_height_for_width;
|
||||
|
||||
container_class->check_resize = gtk_window_check_resize;
|
||||
container_class->forall = gtk_window_forall;
|
||||
|
||||
klass->set_focus = gtk_window_real_set_focus;
|
||||
|
||||
@ -1115,6 +1155,49 @@ gtk_window_class_init (GtkWindowClass *klass)
|
||||
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_title_min_clicked (GtkWidget *widget, gpointer data)
|
||||
{
|
||||
GtkWindow *window = (GtkWindow *)data;
|
||||
|
||||
gtk_window_iconify (window);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_title_max_clicked (GtkWidget *widget, gpointer data)
|
||||
{
|
||||
GtkWindow *window = (GtkWindow *)data;
|
||||
GdkWindowState state = gdk_window_get_state (gtk_widget_get_window (widget));
|
||||
|
||||
if (state & GDK_WINDOW_STATE_MAXIMIZED)
|
||||
gtk_window_unmaximize (window);
|
||||
else
|
||||
gtk_window_maximize (window);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
send_delete_event (gpointer data)
|
||||
{
|
||||
GtkWidget *window = GTK_WIDGET (data);
|
||||
GdkEvent *event;
|
||||
|
||||
event = gdk_event_new (GDK_DELETE);
|
||||
|
||||
event->any.window = g_object_ref (gtk_widget_get_window (window));
|
||||
event->any.send_event = TRUE;
|
||||
|
||||
gtk_main_do_event (event);
|
||||
gdk_event_free (event);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_title_close_clicked (GtkWidget *button, gpointer data)
|
||||
{
|
||||
gdk_threads_add_idle (send_delete_event, data);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_init (GtkWindow *window)
|
||||
{
|
||||
@ -1634,10 +1717,10 @@ gtk_window_set_title (GtkWindow *window,
|
||||
priv->title = new_title;
|
||||
|
||||
if (gtk_widget_get_realized (widget))
|
||||
{
|
||||
gdk_window_set_title (gtk_widget_get_window (widget),
|
||||
priv->title);
|
||||
}
|
||||
gdk_window_set_title (gtk_widget_get_window (widget), priv->title);
|
||||
|
||||
if (priv->title_box != NULL)
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (priv->title_box), priv->title);
|
||||
|
||||
g_object_notify (G_OBJECT (window), "title");
|
||||
}
|
||||
@ -3322,7 +3405,7 @@ gtk_window_set_decorated (GtkWindow *window,
|
||||
gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
|
||||
if (gdk_window)
|
||||
{
|
||||
if (priv->decorated)
|
||||
if (priv->decorated && !priv->client_decorated)
|
||||
gdk_window_set_decorations (gdk_window,
|
||||
GDK_DECOR_ALL);
|
||||
else
|
||||
@ -4755,6 +4838,68 @@ gtk_window_finalize (GObject *object)
|
||||
G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
create_decoration (GtkWidget *widget)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (widget);
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
GtkStyleContext *context;
|
||||
const char *title = "GtkWindow";
|
||||
|
||||
/* Clien decorations already created */
|
||||
if (priv->client_decorated)
|
||||
return;
|
||||
|
||||
if (priv->type == GTK_WINDOW_POPUP)
|
||||
return;
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (!GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget)))
|
||||
return;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (!priv->decorated)
|
||||
return;
|
||||
|
||||
priv->client_decorated = TRUE;
|
||||
|
||||
priv->title_box = gtk_header_bar_new ();
|
||||
g_object_set (priv->title_box,
|
||||
"spacing", 0,
|
||||
"hpadding", 0,
|
||||
"vpadding", 0,
|
||||
NULL);
|
||||
context = gtk_widget_get_style_context (priv->title_box);
|
||||
gtk_style_context_add_class (context, "titlebar");
|
||||
gtk_widget_set_parent (priv->title_box, GTK_WIDGET (window));
|
||||
|
||||
if (priv->title)
|
||||
title = priv->title;
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (priv->title_box), title);
|
||||
|
||||
priv->title_min_button = gtk_button_new_with_label ("_");
|
||||
gtk_widget_set_can_focus (priv->title_min_button, FALSE);
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (priv->title_box), priv->title_min_button);
|
||||
g_signal_connect (priv->title_min_button, "clicked",
|
||||
G_CALLBACK (gtk_window_title_min_clicked), window);
|
||||
|
||||
priv->title_max_button = gtk_button_new_with_label ("\342\226\253");
|
||||
gtk_widget_set_can_focus (priv->title_max_button, FALSE);
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (priv->title_box), priv->title_max_button);
|
||||
g_signal_connect (priv->title_max_button, "clicked",
|
||||
G_CALLBACK (gtk_window_title_max_clicked), window);
|
||||
|
||||
priv->title_close_button = gtk_button_new_with_label ("×");
|
||||
gtk_widget_set_can_focus (priv->title_close_button, FALSE);
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (priv->title_box), priv->title_close_button);
|
||||
g_signal_connect (priv->title_close_button, "clicked",
|
||||
G_CALLBACK (gtk_window_title_close_clicked), window);
|
||||
|
||||
gtk_widget_show_all (priv->title_box);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_show (GtkWidget *widget)
|
||||
{
|
||||
@ -4892,11 +5037,12 @@ gtk_window_map (GtkWidget *widget)
|
||||
gtk_widget_set_mapped (widget, TRUE);
|
||||
|
||||
child = gtk_bin_get_child (&(window->bin));
|
||||
if (child &&
|
||||
gtk_widget_get_visible (child) &&
|
||||
!gtk_widget_get_mapped (child))
|
||||
if (child != NULL && gtk_widget_get_visible (child))
|
||||
gtk_widget_map (child);
|
||||
|
||||
if (priv->title_box != NULL)
|
||||
gtk_widget_map (priv->title_box);
|
||||
|
||||
gdk_window = gtk_widget_get_window (widget);
|
||||
|
||||
if (priv->maximize_initially)
|
||||
@ -5051,8 +5197,11 @@ gtk_window_unmap (GtkWidget *widget)
|
||||
priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
|
||||
priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
|
||||
|
||||
if (priv->title_box != NULL)
|
||||
gtk_widget_unmap (priv->title_box);
|
||||
|
||||
child = gtk_bin_get_child (&(window->bin));
|
||||
if (child)
|
||||
if (child != NULL)
|
||||
gtk_widget_unmap (child);
|
||||
}
|
||||
|
||||
@ -5138,6 +5287,8 @@ gtk_window_realize (GtkWidget *widget)
|
||||
window = GTK_WINDOW (widget);
|
||||
priv = window->priv;
|
||||
|
||||
create_decoration (widget);
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
if (gtk_widget_get_parent_window (widget))
|
||||
@ -5224,6 +5375,7 @@ gtk_window_realize (GtkWidget *widget)
|
||||
attributes.height = allocation.height;
|
||||
attributes.event_mask = gtk_widget_get_events (widget);
|
||||
attributes.event_mask |= (GDK_EXPOSURE_MASK |
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_KEY_PRESS_MASK |
|
||||
GDK_KEY_RELEASE_MASK |
|
||||
GDK_ENTER_NOTIFY_MASK |
|
||||
@ -5253,7 +5405,7 @@ gtk_window_realize (GtkWidget *widget)
|
||||
if (priv->wm_role)
|
||||
gdk_window_set_role (gdk_window, priv->wm_role);
|
||||
|
||||
if (!priv->decorated)
|
||||
if (!priv->decorated || priv->client_decorated)
|
||||
gdk_window_set_decorations (gdk_window, 0);
|
||||
|
||||
if (!priv->deletable)
|
||||
@ -5502,6 +5654,34 @@ set_grip_position (GtkWindow *window)
|
||||
rect.width, rect.height);
|
||||
}
|
||||
|
||||
static void
|
||||
get_decoration_borders (GtkWidget *widget,
|
||||
GtkBorder *title_border,
|
||||
GtkBorder *window_border)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
GtkStateFlags state;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
state = gtk_style_context_get_state (context);
|
||||
|
||||
if (title_border != NULL)
|
||||
{
|
||||
gtk_style_context_save (context);
|
||||
gtk_style_context_add_class (context, "titlebar");
|
||||
gtk_style_context_get_border (context, state, title_border);
|
||||
gtk_style_context_restore (context);
|
||||
}
|
||||
|
||||
if (window_border != NULL)
|
||||
{
|
||||
gtk_style_context_save (context);
|
||||
gtk_style_context_add_class (context, "window-border");
|
||||
gtk_style_context_get_border (context, state, window_border);
|
||||
gtk_style_context_restore (context);
|
||||
}
|
||||
}
|
||||
|
||||
/* _gtk_window_set_allocation:
|
||||
* @window: a #GtkWindow
|
||||
* @allocation: the original allocation for the window
|
||||
@ -5527,12 +5707,68 @@ _gtk_window_set_allocation (GtkWindow *window,
|
||||
GtkAllocation *allocation_out)
|
||||
{
|
||||
GtkWidget *widget = (GtkWidget *)window;
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
GtkAllocation child_allocation;
|
||||
guint border_width;
|
||||
GtkBorder title_border = { 0 };
|
||||
GtkBorder window_border = { 0 };
|
||||
gint title_height = 0;
|
||||
|
||||
g_assert (allocation != NULL);
|
||||
g_assert (allocation_out != NULL);
|
||||
|
||||
gtk_widget_set_allocation (widget, allocation);
|
||||
|
||||
if (priv->title_box != NULL)
|
||||
get_decoration_borders (widget, &title_border, &window_border);
|
||||
else
|
||||
get_decoration_borders (widget, NULL, &window_border);
|
||||
|
||||
border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
|
||||
|
||||
/* Apply border width */
|
||||
child_allocation = *allocation;
|
||||
child_allocation.x += border_width;
|
||||
child_allocation.y += border_width;
|
||||
child_allocation.width = MAX (1, child_allocation.width - border_width * 2);
|
||||
child_allocation.height = MAX (1, child_allocation.height - border_width * 2);
|
||||
|
||||
if (priv->title_box != NULL &&
|
||||
priv->client_decorated &&
|
||||
priv->decorated)
|
||||
{
|
||||
GtkAllocation title_allocation;
|
||||
|
||||
gtk_widget_get_preferred_height (priv->title_box,
|
||||
NULL,
|
||||
&title_height);
|
||||
|
||||
title_allocation.x = title_border.left +
|
||||
window_border.left;
|
||||
title_allocation.y = title_border.top +
|
||||
window_border.top;
|
||||
title_allocation.width =
|
||||
MAX (1, (gint) allocation->width -
|
||||
title_border.left - title_border.right -
|
||||
window_border.left - window_border.right);
|
||||
title_allocation.height = title_height;
|
||||
|
||||
gtk_widget_size_allocate (priv->title_box, &title_allocation);
|
||||
}
|
||||
|
||||
if (priv->client_decorated && priv->decorated)
|
||||
{
|
||||
child_allocation.x += window_border.left;
|
||||
child_allocation.y += window_border.top +
|
||||
title_height +
|
||||
title_border.top +
|
||||
title_border.bottom;
|
||||
child_allocation.width -= (window_border.left +
|
||||
window_border.right);
|
||||
child_allocation.height -= (child_allocation.y +
|
||||
window_border.bottom);
|
||||
}
|
||||
|
||||
if (gtk_widget_get_realized (widget))
|
||||
{
|
||||
/* If it's not a toplevel we're embedded, we need to resize
|
||||
@ -5551,7 +5787,7 @@ _gtk_window_set_allocation (GtkWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
*allocation_out = *allocation;
|
||||
*allocation_out = child_allocation;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -5559,23 +5795,14 @@ gtk_window_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (widget);
|
||||
GtkAllocation child_allocation;
|
||||
GtkWidget *child;
|
||||
guint border_width;
|
||||
GtkAllocation child_allocation;
|
||||
|
||||
_gtk_window_set_allocation (window, allocation, &child_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, child_allocation.width - border_width * 2);
|
||||
child_allocation.height = MAX (1, child_allocation.height - border_width * 2);
|
||||
|
||||
gtk_widget_size_allocate (child, &child_allocation);
|
||||
}
|
||||
gtk_widget_size_allocate (child, &child_allocation);
|
||||
}
|
||||
|
||||
static gint
|
||||
@ -5904,15 +6131,20 @@ gtk_window_get_resize_grip_area (GtkWindow *window,
|
||||
GdkRectangle *rect)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (window);
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
GtkAllocation allocation;
|
||||
gint grip_width;
|
||||
gint grip_height;
|
||||
GtkBorder window_border = { 0 };
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
|
||||
|
||||
if (!window->priv->has_resize_grip)
|
||||
return FALSE;
|
||||
|
||||
if (priv->client_decorated)
|
||||
get_decoration_borders (widget, NULL, &window_border);
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
gtk_widget_style_get (widget,
|
||||
@ -5928,10 +6160,12 @@ gtk_window_get_resize_grip_area (GtkWindow *window,
|
||||
|
||||
rect->width = grip_width;
|
||||
rect->height = grip_height;
|
||||
rect->y = allocation.y + allocation.height - grip_height;
|
||||
rect->y = allocation.y + allocation.height -
|
||||
grip_height - window_border.bottom;
|
||||
|
||||
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
|
||||
rect->x = allocation.x + allocation.width - grip_width;
|
||||
rect->x = allocation.x + allocation.width -
|
||||
grip_width - window_border.right;
|
||||
else
|
||||
rect->x = allocation.x;
|
||||
|
||||
@ -6096,6 +6330,32 @@ gtk_window_button_press_event (GtkWidget *widget,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (priv->client_decorated &&
|
||||
priv->decorated &&
|
||||
priv->title_box != NULL)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
int border_width;
|
||||
|
||||
gtk_widget_get_allocation (priv->title_box, &allocation);
|
||||
border_width =
|
||||
gtk_container_get_border_width (GTK_CONTAINER (priv->title_box));
|
||||
|
||||
if (allocation.x - border_width <= event->x &&
|
||||
event->x < allocation.x + border_width + allocation.width &&
|
||||
allocation.y - border_width <= event->y &&
|
||||
event->y < allocation.y + border_width + allocation.height)
|
||||
{
|
||||
gdk_window_begin_move_drag_for_device (gtk_widget_get_window(widget),
|
||||
gdk_event_get_device((GdkEvent *) event),
|
||||
event->button,
|
||||
event->x_root,
|
||||
event->y_root,
|
||||
event->time);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -6261,6 +6521,25 @@ gtk_window_check_resize (GtkContainer *container)
|
||||
gtk_window_move_resize (GTK_WINDOW (container));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_forall (GtkContainer *container,
|
||||
gboolean include_internals,
|
||||
GtkCallback callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (container);
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
GtkWidget *child;
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (container));
|
||||
if (child != NULL)
|
||||
(* callback) (child, callback_data);
|
||||
|
||||
if (include_internals &&
|
||||
priv->title_box != NULL)
|
||||
(* callback) (priv->title_box, callback_data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_window_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
@ -6438,6 +6717,239 @@ gtk_window_real_set_focus (GtkWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_get_preferred_width (GtkWidget *widget,
|
||||
gint *minimum_size,
|
||||
gint *natural_size)
|
||||
{
|
||||
GtkWindow *window;
|
||||
GtkWidget *child;
|
||||
GtkWindowPrivate *priv;
|
||||
guint border_width;
|
||||
gint title_min = 0, title_nat = 0;
|
||||
gint child_min = 0, child_nat = 0;
|
||||
GtkBorder title_border = { 0, };
|
||||
GtkBorder window_border = { 0 };
|
||||
|
||||
window = GTK_WINDOW (widget);
|
||||
priv = window->priv;
|
||||
child = gtk_bin_get_child (GTK_BIN (window));
|
||||
|
||||
border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
|
||||
|
||||
if (priv->client_decorated &&
|
||||
priv->decorated)
|
||||
{
|
||||
if (priv->title_box != NULL)
|
||||
{
|
||||
gtk_widget_get_preferred_width (priv->title_box,
|
||||
&title_min, &title_nat);
|
||||
get_decoration_borders (widget, &title_border, &window_border);
|
||||
}
|
||||
else
|
||||
{
|
||||
get_decoration_borders (widget, NULL, &window_border);
|
||||
}
|
||||
|
||||
title_min += border_width * 2 +
|
||||
title_border.left + title_border.right +
|
||||
window_border.left + window_border.right;
|
||||
title_nat += border_width * 2 +
|
||||
title_border.left + title_border.right +
|
||||
window_border.left + window_border.right;
|
||||
}
|
||||
|
||||
if (child && gtk_widget_get_visible (child))
|
||||
{
|
||||
gtk_widget_get_preferred_width (child, &child_min, &child_nat);
|
||||
child_min += border_width * 2 +
|
||||
window_border.left + window_border.right;
|
||||
child_nat += border_width * 2 +
|
||||
window_border.left + window_border.right;
|
||||
}
|
||||
|
||||
*minimum_size = MAX (title_min, child_min);
|
||||
*natural_size = MAX (title_nat, child_nat);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gtk_window_get_preferred_width_for_height (GtkWidget *widget,
|
||||
gint height,
|
||||
gint *minimum_size,
|
||||
gint *natural_size)
|
||||
{
|
||||
GtkWindow *window;
|
||||
GtkWidget *child;
|
||||
GtkWindowPrivate *priv;
|
||||
guint border_width;
|
||||
gint title_min = 0, title_nat = 0;
|
||||
gint child_min = 0, child_nat = 0;
|
||||
GtkBorder title_border = { 0, };
|
||||
GtkBorder window_border = { 0 };
|
||||
|
||||
window = GTK_WINDOW (widget);
|
||||
priv = window->priv;
|
||||
child = gtk_bin_get_child (GTK_BIN (window));
|
||||
|
||||
border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
|
||||
|
||||
if (priv->client_decorated &&
|
||||
priv->decorated)
|
||||
{
|
||||
if (priv->title_box != NULL)
|
||||
{
|
||||
gtk_widget_get_preferred_width_for_height (priv->title_box,
|
||||
height,
|
||||
&title_min, &title_nat);
|
||||
get_decoration_borders (widget, &title_border, &window_border);
|
||||
}
|
||||
else
|
||||
{
|
||||
get_decoration_borders (widget, NULL, &window_border);
|
||||
}
|
||||
|
||||
title_min += border_width * 2 +
|
||||
title_border.left + title_border.right +
|
||||
window_border.left + window_border.right;
|
||||
title_nat += border_width * 2 +
|
||||
title_border.left + title_border.right +
|
||||
window_border.left + window_border.right;
|
||||
}
|
||||
|
||||
if (child && gtk_widget_get_visible (child))
|
||||
{
|
||||
gtk_widget_get_preferred_width_for_height (child,
|
||||
height,
|
||||
&child_min, &child_nat);
|
||||
child_min += border_width * 2 +
|
||||
window_border.left + window_border.right;
|
||||
child_nat += border_width * 2 +
|
||||
window_border.left + window_border.right;
|
||||
}
|
||||
|
||||
*minimum_size = MAX (title_min, child_min);
|
||||
*natural_size = MAX (title_nat, child_nat);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_get_preferred_height (GtkWidget *widget,
|
||||
gint *minimum_size,
|
||||
gint *natural_size)
|
||||
{
|
||||
GtkWindow *window;
|
||||
GtkWindowPrivate *priv;
|
||||
GtkWidget *child;
|
||||
guint border_width;
|
||||
int title_min = 0;
|
||||
int title_height = 0;
|
||||
GtkBorder title_border = { 0, };
|
||||
GtkBorder window_border = { 0 };
|
||||
|
||||
window = GTK_WINDOW (widget);
|
||||
priv = window->priv;
|
||||
child = gtk_bin_get_child (GTK_BIN (window));
|
||||
|
||||
*minimum_size = 0;
|
||||
*natural_size = 0;
|
||||
|
||||
border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
|
||||
|
||||
if (priv->client_decorated &&
|
||||
priv->decorated)
|
||||
{
|
||||
if (priv->title_box != NULL)
|
||||
{
|
||||
gtk_widget_get_preferred_height (priv->title_box,
|
||||
&title_min,
|
||||
&title_height);
|
||||
get_decoration_borders (widget, &title_border, &window_border);
|
||||
}
|
||||
else
|
||||
{
|
||||
get_decoration_borders (widget, NULL, &window_border);
|
||||
}
|
||||
|
||||
*minimum_size = title_min +
|
||||
title_border.top + title_border.bottom +
|
||||
window_border.top + window_border.bottom;
|
||||
|
||||
*natural_size = title_height +
|
||||
title_border.top + title_border.bottom +
|
||||
window_border.top + window_border.bottom;
|
||||
}
|
||||
|
||||
if (child && gtk_widget_get_visible (child))
|
||||
{
|
||||
gint child_min, child_nat;
|
||||
gtk_widget_get_preferred_height (child, &child_min, &child_nat);
|
||||
|
||||
*minimum_size += child_min + 2 * border_width;
|
||||
*natural_size += child_nat + 2 * border_width;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gtk_window_get_preferred_height_for_width (GtkWidget *widget,
|
||||
gint width,
|
||||
gint *minimum_size,
|
||||
gint *natural_size)
|
||||
{
|
||||
GtkWindow *window;
|
||||
GtkWindowPrivate *priv;
|
||||
GtkWidget *child;
|
||||
guint border_width;
|
||||
int title_min = 0;
|
||||
int title_height = 0;
|
||||
GtkBorder title_border = { 0, };
|
||||
GtkBorder window_border = { 0 };
|
||||
|
||||
window = GTK_WINDOW (widget);
|
||||
priv = window->priv;
|
||||
child = gtk_bin_get_child (GTK_BIN (window));
|
||||
|
||||
*minimum_size = 0;
|
||||
*natural_size = 0;
|
||||
|
||||
border_width = gtk_container_get_border_width (GTK_CONTAINER (window));
|
||||
|
||||
if (priv->client_decorated &&
|
||||
priv->decorated)
|
||||
{
|
||||
if (priv->title_box != NULL)
|
||||
{
|
||||
gtk_widget_get_preferred_height_for_width (priv->title_box,
|
||||
width,
|
||||
&title_min,
|
||||
&title_height);
|
||||
get_decoration_borders (widget, &title_border, &window_border);
|
||||
}
|
||||
else
|
||||
{
|
||||
get_decoration_borders (widget, NULL, &window_border);
|
||||
}
|
||||
|
||||
*minimum_size = title_min +
|
||||
title_border.top + title_border.bottom +
|
||||
window_border.top + window_border.bottom;
|
||||
|
||||
*natural_size = title_height +
|
||||
title_border.top + title_border.bottom +
|
||||
window_border.top + window_border.bottom;
|
||||
}
|
||||
|
||||
if (child && gtk_widget_get_visible (child))
|
||||
{
|
||||
gint child_min, child_nat;
|
||||
gtk_widget_get_preferred_height_for_width (child, width,
|
||||
&child_min, &child_nat);
|
||||
|
||||
*minimum_size += child_min + 2 * border_width;
|
||||
*natural_size += child_nat + 2 * border_width;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_window_unset_focus_and_default:
|
||||
* @window: a #GtkWindow
|
||||
@ -7566,15 +8078,70 @@ gtk_window_draw (GtkWidget *widget,
|
||||
GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
|
||||
GtkStyleContext *context;
|
||||
gboolean ret = FALSE;
|
||||
GtkAllocation allocation;
|
||||
GtkBorder title_border = { 0 };
|
||||
GtkBorder window_border = {};
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
if (priv->title_box != NULL)
|
||||
get_decoration_borders (widget, &title_border, &window_border);
|
||||
else
|
||||
get_decoration_borders (widget, NULL, &window_border);
|
||||
|
||||
if (!gtk_widget_get_app_paintable (widget) &&
|
||||
gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
|
||||
{
|
||||
gtk_render_background (context, cr, 0, 0,
|
||||
gtk_widget_get_allocated_width (widget),
|
||||
gtk_widget_get_allocated_height (widget));
|
||||
gtk_style_context_save (context);
|
||||
|
||||
gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
|
||||
|
||||
if (priv->client_decorated &&
|
||||
priv->decorated)
|
||||
{
|
||||
gtk_style_context_add_class (context, "window-border");
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
gtk_render_background (context, cr,
|
||||
window_border.left,
|
||||
window_border.top,
|
||||
allocation.width -
|
||||
(window_border.left +
|
||||
window_border.right),
|
||||
allocation.height -
|
||||
(window_border.top +
|
||||
window_border.bottom));
|
||||
gtk_render_frame (context, cr,
|
||||
0, 0, allocation.width, allocation.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
gtk_render_background (context, cr,
|
||||
0, 0, allocation.width, allocation.height);
|
||||
}
|
||||
|
||||
gtk_style_context_restore (context);
|
||||
}
|
||||
|
||||
if (priv->title_box != NULL)
|
||||
{
|
||||
gtk_style_context_save (context);
|
||||
gtk_style_context_add_class (context, "titlebar");
|
||||
gtk_widget_get_allocation (priv->title_box, &allocation);
|
||||
|
||||
/* Why do these subtract ? */
|
||||
gtk_render_background (context, cr,
|
||||
allocation.x - title_border.left,
|
||||
allocation.y - title_border.top,
|
||||
allocation.width + title_border.left + title_border.right,
|
||||
allocation.height + title_border.top + title_border.left);
|
||||
gtk_render_frame (context, cr,
|
||||
allocation.x - title_border.left,
|
||||
allocation.y - title_border.top,
|
||||
allocation.width + title_border.left + title_border.right,
|
||||
allocation.height + title_border.top + title_border.left);
|
||||
|
||||
gtk_style_context_restore (context);
|
||||
}
|
||||
|
||||
if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw)
|
||||
|
Loading…
Reference in New Issue
Block a user