[gtk/wip/matthiasc/popup4: 28/76] Reimplement GtkPopover
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/matthiasc/popup4: 28/76] Reimplement GtkPopover
- Date: Sat, 20 Apr 2019 17:33:50 +0000 (UTC)
commit d31de77a6a03fb4669ed689725ae0d99fb761139
Author: Matthias Clasen <mclasen redhat com>
Date: Tue Mar 19 22:49:32 2019 -0400
Reimplement GtkPopover
gtk/gtkmain.c | 21 +
gtk/gtkpopover.c | 2708 ++++++++++++++++---------------------------
gtk/gtkpopover.h | 98 +-
gtk/gtkpopovermenu.c | 2 +
gtk/gtkpopoverprivate.h | 2 -
gtk/gtkwidget.c | 10 +-
gtk/gtkwindow.c | 2 +
gtk/inspector/object-tree.c | 2 +
tests/meson.build | 1 -
tests/testpopup.c | 62 -
10 files changed, 1075 insertions(+), 1833 deletions(-)
---
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index e24c52f971..5f974ac99c 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1329,6 +1329,27 @@ rewrite_event_for_grabs (GdkEvent *event)
event_widget = gtk_get_event_widget (event);
grab_widget = gtk_root_get_for_surface (grab_surface);
+ switch ((guint) event->any.type)
+ {
+ case GDK_BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ case GDK_KEY_PRESS:
+ case GDK_KEY_RELEASE:
+ case GDK_TOUCH_BEGIN:
+ case GDK_TOUCH_END:
+ case GDK_TOUCH_CANCEL:
+ case GDK_TOUCHPAD_SWIPE:
+ case GDK_TOUCHPAD_PINCH:
+ if (grab_surface != event->any.surface &&
+ GTK_IS_POPOVER (grab_widget))
+ {
+ gtk_widget_hide (grab_widget);
+ return NULL;
+ }
+ break;
+ default:;
+ }
+
if (grab_widget &&
gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
return rewrite_event_for_surface (event, grab_surface);
diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c
index 58cd6473bd..078c970e0d 100644
--- a/gtk/gtkpopover.c
+++ b/gtk/gtkpopover.c
@@ -1,5 +1,8 @@
/* GTK - The GIMP Toolkit
- * Copyright © 2013 Carlos Garnacho <carlosg gnome org>
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * Authors:
+ * - Matthias Clasen <mclasen redhat com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,7 +25,8 @@
*
* GtkPopover is a bubble-like context window, primarily meant to
* provide context-dependent information or options. Popovers are
- * attached to a widget, passed at construction time on gtk_popover_new(),
+ * attached to a widget, passed at construction time on gtk_popover_new
+(),
* or updated afterwards through gtk_popover_set_relative_to(), by
* default they will point to the whole widget area, although this
* behavior can be changed through gtk_popover_set_pointing_to().
@@ -104,128 +108,256 @@
#include "config.h"
#include "gtkpopoverprivate.h"
-
-#include "gtkadjustment.h"
-#include "gtkbox.h"
-#include "gtkbutton.h"
-#include "gtkcontainerprivate.h"
+#include "gtkroot.h"
+#include "gtkwidgetprivate.h"
+#include "gtkeventcontrollerkey.h"
#include "gtkcssnodeprivate.h"
-#include "gtkentry.h"
+#include "gtkbindings.h"
+#include "gtkenums.h"
+#include "gtktypebuiltins.h"
+#include "gtkmnemonichash.h"
#include "gtkgizmoprivate.h"
#include "gtkintl.h"
-#include "gtklabel.h"
-#include "gtkmain.h"
-#include "gtkmenusectionbox.h"
-#include "gtkmenutracker.h"
-#include "gtkmodelbutton.h"
#include "gtkprivate.h"
-#include "gtkprogresstrackerprivate.h"
-#include "gtkrender.h"
-#include "gtkroundedboxprivate.h"
-#include "gtkscrollable.h"
-#include "gtksettingsprivate.h"
-#include "gtksizegroup.h"
-#include "gtksnapshot.h"
+#include "gtkmain.h"
#include "gtkstack.h"
-#include "gtkstylecontextprivate.h"
-#include "gtktypebuiltins.h"
-#include "gtkwidgetprivate.h"
-#include "gtkwindowprivate.h"
-#include "gtkgesturemultipress.h"
-#include "gtkeventcontrollerkey.h"
+#include "gtkmenusectionbox.h"
+#include "gdk/gdkeventsprivate.h"
+#include "gtkpointerfocusprivate.h"
+#include "gtkcssnodeprivate.h"
-#include "a11y/gtkpopoveraccessible.h"
+static GListStore *popover_list = NULL;
-#include "gsk/gskroundedrectprivate.h"
+typedef struct {
+ GdkDisplay *display;
+ GskRenderer *renderer;
+ GdkSurface *surface;
+ GtkWidget *focus_widget;
+ gboolean active;
+ GtkWidget *default_widget;
+ GtkMnemonicHash *mnemonic_hash;
+ GList *foci;
-#ifdef GDK_WINDOWING_WAYLAND
-#include "wayland/gdkwayland.h"
-#endif
+ GdkSurfaceState state;
+ GtkWidget *relative_to;
+ GdkRectangle pointing_to;
+ gboolean has_pointing_to;
+ GtkPositionType position;
+ gboolean modal;
+ gboolean has_grab;
+
+ GtkWidget *contents_widget;
+} GtkPopoverPrivate;
-#define TAIL_GAP_WIDTH 24
-#define TAIL_HEIGHT 12
-#define TRANSITION_DIFF 20
-#define TRANSITION_DURATION 150 * 1000
+enum {
+ ACTIVATE_FOCUS,
+ ACTIVATE_DEFAULT,
+ CLOSE,
+ CLOSED,
+ LAST_SIGNAL
+};
-#define POS_IS_VERTICAL(p) ((p) == GTK_POS_TOP || (p) == GTK_POS_BOTTOM)
+static guint signals[LAST_SIGNAL] = { 0 };
enum {
PROP_RELATIVE_TO = 1,
PROP_POINTING_TO,
PROP_POSITION,
PROP_MODAL,
- PROP_CONSTRAIN_TO,
NUM_PROPERTIES
};
-enum {
- CLOSED,
- N_SIGNALS
-};
+static void gtk_popover_set_is_active (GtkPopover *popover,
+ gboolean active);
+static void gtk_popover_set_focus (GtkPopover *popover,
+ GtkWidget *widget);
+static void gtk_popover_set_default (GtkPopover *popover,
+ GtkWidget *widget);
-enum {
- STATE_SHOWING,
- STATE_SHOWN,
- STATE_HIDING,
- STATE_HIDDEN
-};
+static GParamSpec *properties[NUM_PROPERTIES] = { NULL };
+
+static void gtk_popover_root_interface_init (GtkRootInterface *iface);
-typedef struct _GtkPopoverPrivate GtkPopoverPrivate;
-struct _GtkPopoverPrivate
+G_DEFINE_TYPE_WITH_CODE (GtkPopover, gtk_popover, GTK_TYPE_BIN,
+ G_ADD_PRIVATE (GtkPopover)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ROOT,
+ gtk_popover_root_interface_init))
+
+
+static GdkDisplay *
+gtk_popover_root_get_display (GtkRoot *root)
{
- GtkWidget *widget;
- GtkWidget *contents_widget;
- GtkCssNode *arrow_node;
- GtkWindow *window;
- GtkWidget *prev_focus_widget;
- GtkWidget *default_widget;
- GtkWidget *prev_default;
- GtkScrollable *parent_scrollable;
- GtkAdjustment *vadj;
- GtkAdjustment *hadj;
- GdkRectangle pointing_to;
- GtkPopoverConstraint constraint;
- GtkProgressTracker tracker;
- guint prev_focus_unmap_id;
- guint hierarchy_changed_id;
- guint size_allocate_id;
- guint unmap_id;
- guint scrollable_notify_id;
- guint grab_notify_id;
- guint state_changed_id;
- guint has_pointing_to : 1;
- guint preferred_position : 2;
- guint final_position : 2;
- guint current_position : 2;
- guint modal : 1;
- guint button_pressed : 1;
- guint grab_notify_blocked : 1;
- guint state : 2;
- guint visible : 1;
- guint first_frame_skipped : 1;
- gint transition_diff;
- guint tick_id;
-
- gint tip_x;
- gint tip_y;
-};
+ GtkPopover *popover = GTK_POPOVER (root);
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
+ return priv->display;
+}
+
+static GskRenderer *
+gtk_popover_root_get_renderer (GtkRoot *root)
+{
+ GtkPopover *popover = GTK_POPOVER (root);
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
+ return priv->renderer;
+}
+
+static void
+gtk_popover_root_get_surface_transform (GtkRoot *root,
+ int *x,
+ int *y)
+{
+ GtkStyleContext *context;
+ GtkBorder margin, border, padding;
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (root));
+ gtk_style_context_get_margin (context, &margin);
+ gtk_style_context_get_border (context, &border);
+ gtk_style_context_get_padding (context, &padding);
+
+ *x = margin.left + border.left + padding.left;
+ *y = margin.top + border.top + padding.top;
+}
+
+static void
+move_to_rect (GtkPopover *popover)
+{
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GdkRectangle rect;
+ GdkGravity parent_anchor;
+ GdkGravity surface_anchor;
+ GdkAnchorHints anchor_hints;
+
+ gtk_widget_get_surface_allocation (priv->relative_to, &rect);
+ if (priv->has_pointing_to)
+ {
+ rect.x += priv->pointing_to.x;
+ rect.y += priv->pointing_to.y;
+ rect.width = priv->pointing_to.width;
+ rect.height = priv->pointing_to.height;
+ }
+
+ switch (priv->position)
+ {
+ case GTK_POS_LEFT:
+ parent_anchor = GDK_GRAVITY_WEST;
+ surface_anchor = GDK_GRAVITY_EAST;
+ anchor_hints = GDK_ANCHOR_FLIP_X;
+ break;
+
+ case GTK_POS_RIGHT:
+ parent_anchor = GDK_GRAVITY_EAST;
+ surface_anchor = GDK_GRAVITY_WEST;
+ anchor_hints = GDK_ANCHOR_FLIP_X;
+ break;
+
+ case GTK_POS_TOP:
+ parent_anchor = GDK_GRAVITY_NORTH;
+ surface_anchor = GDK_GRAVITY_SOUTH;
+ anchor_hints = GDK_ANCHOR_FLIP_Y;
+ break;
+
+ case GTK_POS_BOTTOM:
+ parent_anchor = GDK_GRAVITY_SOUTH;
+ surface_anchor = GDK_GRAVITY_NORTH;
+ anchor_hints = GDK_ANCHOR_FLIP_Y;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ gdk_surface_move_to_rect (priv->surface,
+ &rect,
+ parent_anchor,
+ surface_anchor,
+ anchor_hints,
+ 0, 0);
+}
+
+static void
+gtk_popover_move_resize (GtkPopover *popover)
+{
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GtkRequisition req;
+
+ gtk_widget_get_preferred_size (GTK_WIDGET (popover), NULL, &req);
+ gdk_surface_resize (priv->surface, req.width, req.height);
+ move_to_rect (popover);
+}
+
+static void
+gtk_popover_root_check_resize (GtkRoot *root)
+{
+ GtkPopover *popover = GTK_POPOVER (root);
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GtkWidget *widget = GTK_WIDGET (popover);
+
+ if (!_gtk_widget_get_alloc_needed (widget))
+ gtk_widget_ensure_allocate (widget);
+ else if (gtk_widget_get_visible (widget))
+ {
+ gtk_popover_move_resize (popover);
+ gtk_widget_allocate (GTK_WIDGET (popover),
+ gdk_surface_get_width (priv->surface),
+ gdk_surface_get_height (priv->surface),
+ -1, NULL);
+ }
+}
+
+
+static void
+gtk_popover_focus_in (GtkWidget *widget)
+{
+ gtk_popover_set_is_active (GTK_POPOVER (widget), TRUE);
+}
+
+static void
+gtk_popover_focus_out (GtkWidget *widget)
+{
+ gtk_popover_set_is_active (GTK_POPOVER (widget), FALSE);
+}
+
+static void
+ensure_state_flag_backdrop (GtkWidget *widget)
+{
+ GtkPopover *popover = GTK_POPOVER (widget);
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
+ if ((priv->state & GDK_SURFACE_STATE_FOCUSED) != 0)
+ gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
+ else
+ gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);
+}
-static GParamSpec *properties[NUM_PROPERTIES];
-static GQuark quark_widget_popovers = 0;
-static guint signals[N_SIGNALS] = { 0 };
+static void
+surface_state_changed (GtkWidget *widget)
+{
+ GtkPopover *popover = GTK_POPOVER (widget);
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GdkSurfaceState new_surface_state;
+ GdkSurfaceState changed_mask;
-static void gtk_popover_update_relative_to (GtkPopover *popover,
- GtkWidget *relative_to);
-static void gtk_popover_set_state (GtkPopover *popover,
- guint state);
-static void gtk_popover_apply_modality (GtkPopover *popover,
- gboolean modal);
+ new_surface_state = gdk_surface_get_state (_gtk_widget_get_surface (widget));
+ changed_mask = new_surface_state ^ priv->state;
+ priv->state = new_surface_state;
-static void gtk_popover_set_scrollable_full (GtkPopover *popover,
- GtkScrollable *scrollable);
+ if (changed_mask & GDK_SURFACE_STATE_FOCUSED)
+ ensure_state_flag_backdrop (widget);
-G_DEFINE_TYPE_WITH_PRIVATE (GtkPopover, gtk_popover, GTK_TYPE_BIN)
+ if (changed_mask & GDK_SURFACE_STATE_WITHDRAWN)
+ {
+ if (priv->state & GDK_SURFACE_STATE_WITHDRAWN)
+ gtk_widget_hide (widget);
+ }
+}
+static void
+surface_size_changed (GtkWindow *window,
+ guint width,
+ guint height)
+{
+}
static void
measure_contents (GtkGizmo *gizmo,
@@ -256,262 +388,165 @@ allocate_contents (GtkGizmo *gizmo,
if (child)
gtk_widget_size_allocate (child,
- &(GtkAllocation) {
- 0, 0,
- width, height
+ &(GtkAllocation) { 0, 0, width, height
}, -1);
}
static void
-node_style_changed_cb (GtkCssNode *node,
- GtkCssStyleChange *change,
- GtkWidget *widget)
+gtk_popover_init (GtkPopover *popover)
{
- if (gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_SIZE))
- gtk_widget_queue_resize (widget);
- else
- gtk_widget_queue_draw (widget);
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GtkEventController *controller;
+ GtkStyleContext *context;
+
+ gtk_widget_set_has_surface (GTK_WIDGET (popover), TRUE);
+
+ priv->position = GTK_POS_TOP;
+ priv->modal = TRUE;
+
+ priv->display = gdk_display_get_default ();
+
+ controller = gtk_event_controller_key_new ();
+ g_signal_connect_swapped (controller, "focus-in", G_CALLBACK (gtk_popover_focus_in), popover);
+ g_signal_connect_swapped (controller, "focus-out", G_CALLBACK (gtk_popover_focus_out), popover);
+ gtk_widget_add_controller (GTK_WIDGET (popover), controller);
+
+ priv->contents_widget = gtk_gizmo_new ("contents",
+ measure_contents,
+ allocate_contents,
+ NULL,
+ NULL);
+ gtk_widget_set_parent (priv->contents_widget, GTK_WIDGET (popover));
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (popover));
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
}
-static gboolean
-key_controller_key_pressed (GtkEventControllerKey *key,
- guint keyval,
- guint keycode,
- GdkModifierType modifiers,
- GtkPopover *popover)
+static void
+gtk_popover_realize (GtkWidget *widget)
{
+ GtkPopover *popover = GTK_POPOVER (widget);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkWidget *toplevel, *focus;
+ GdkRectangle parent_rect;
- if (keyval == GDK_KEY_Escape)
- {
- gtk_popover_popdown (popover);
- return TRUE;
- }
+ gtk_widget_get_surface_allocation (priv->relative_to, &parent_rect);
- if (priv->modal)
- {
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (popover));
+ priv->surface = gdk_surface_new_popup_full (priv->display, gtk_widget_get_surface (priv->relative_to));
- if (GTK_IS_WINDOW (toplevel))
- {
- focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
+ gtk_widget_set_surface (widget, priv->surface);
+ g_signal_connect_swapped (priv->surface, "notify::state", G_CALLBACK (surface_state_changed), widget);
+ g_signal_connect_swapped (priv->surface, "size-changed", G_CALLBACK (surface_size_changed), widget);
- if (focus && gtk_widget_is_ancestor (focus, GTK_WIDGET (popover)))
- {
- if (gtk_event_controller_key_forward (key, focus))
- return TRUE;
- }
+ gtk_widget_register_surface (widget, priv->surface);
- /* Piggyback on the toplevel to have it handle key navigation */
- return gtk_event_controller_key_forward (key, toplevel);
- }
- }
+ GTK_WIDGET_CLASS (gtk_popover_parent_class)->realize (widget);
- return FALSE;
+ priv->renderer = gsk_renderer_new_for_surface (priv->surface);
}
static void
-gesture_pressed (GtkGestureMultiPress *gesture,
- gint n_press,
- gdouble x,
- gdouble y,
- GtkPopover *popover)
+gtk_popover_unrealize (GtkWidget *widget)
{
+ GtkPopover *popover = GTK_POPOVER (widget);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- priv->button_pressed = TRUE;
-}
+ GTK_WIDGET_CLASS (gtk_popover_parent_class)->unrealize (widget);
-static void
-gesture_released (GtkGestureMultiPress *gesture,
- gint n_press,
- gdouble x,
- gdouble y,
- GtkPopover *popover)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- graphene_rect_t child_bounds;
- GtkWidget *child;
+ gsk_renderer_unrealize (priv->renderer);
+ g_clear_object (&priv->renderer);
- if (!priv->button_pressed)
- return;
+ g_signal_handlers_disconnect_by_func (priv->surface, surface_state_changed, widget);
+ g_signal_handlers_disconnect_by_func (priv->surface, surface_size_changed, widget);
- child = gtk_bin_get_child (GTK_BIN (popover));
- if (!child ||
- !gtk_widget_compute_bounds (child, GTK_WIDGET (popover), &child_bounds) ||
- !graphene_rect_contains_point (&child_bounds,
- &(graphene_point_t){x, y}))
- gtk_popover_popdown (popover);
+ g_clear_object (&priv->surface);
}
static void
-gtk_popover_init (GtkPopover *popover)
+gtk_popover_move_focus (GtkWidget *widget,
+ GtkDirectionType dir)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkWidget *widget;
- GtkStyleContext *context;
- GtkEventController *controller;
-
- widget = GTK_WIDGET (popover);
- gtk_widget_set_has_surface (widget, TRUE);
- priv->modal = TRUE;
- priv->tick_id = 0;
- priv->state = STATE_HIDDEN;
- priv->visible = FALSE;
- priv->preferred_position = GTK_POS_TOP;
- priv->constraint = GTK_POPOVER_CONSTRAINT_WINDOW;
-
- priv->arrow_node = gtk_css_node_new ();
- gtk_css_node_set_name (priv->arrow_node, I_("arrow"));
- gtk_css_node_set_parent (priv->arrow_node, gtk_widget_get_css_node (widget));
- gtk_css_node_set_state (priv->arrow_node,
- gtk_css_node_get_state (gtk_widget_get_css_node (widget)));
- g_signal_connect_object (priv->arrow_node, "style-changed",
- G_CALLBACK (node_style_changed_cb), popover, 0);
- g_object_unref (priv->arrow_node);
-
- priv->contents_widget = gtk_gizmo_new ("contents", measure_contents, allocate_contents, NULL, NULL);
-
- gtk_widget_set_parent (priv->contents_widget, widget);
-
- context = gtk_widget_get_style_context (priv->contents_widget);
- gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND);
-
- controller = gtk_event_controller_key_new ();
- g_signal_connect (controller, "key-pressed",
- G_CALLBACK (key_controller_key_pressed), popover);
- gtk_widget_add_controller (widget, controller);
+ gtk_widget_child_focus (widget, dir);
- controller = GTK_EVENT_CONTROLLER (gtk_gesture_multi_press_new ());
- g_signal_connect (controller, "pressed",
- G_CALLBACK (gesture_pressed), popover);
- g_signal_connect (controller, "released",
- G_CALLBACK (gesture_released), popover);
- gtk_widget_add_controller (widget, controller);
+ if (!gtk_widget_get_focus_child (widget))
+ gtk_root_set_focus (GTK_ROOT (widget), NULL);
}
static void
-gtk_popover_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+gtk_popover_show (GtkWidget *widget)
{
- switch (prop_id)
- {
- case PROP_RELATIVE_TO:
- gtk_popover_set_relative_to (GTK_POPOVER (object),
- g_value_get_object (value));
- break;
- case PROP_POINTING_TO:
- gtk_popover_set_pointing_to (GTK_POPOVER (object),
- g_value_get_boxed (value));
- break;
- case PROP_POSITION:
- gtk_popover_set_position (GTK_POPOVER (object),
- g_value_get_enum (value));
- break;
- case PROP_MODAL:
- gtk_popover_set_modal (GTK_POPOVER (object),
- g_value_get_boolean (value));
- break;
- case PROP_CONSTRAIN_TO:
- gtk_popover_set_constrain_to (GTK_POPOVER (object),
- g_value_get_enum (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
+ _gtk_widget_set_visible_flag (widget, TRUE);
+ gtk_css_node_validate (gtk_widget_get_css_node (widget));
+ gtk_widget_realize (widget);
+ gtk_popover_root_check_resize (GTK_ROOT (widget));
+ gtk_widget_map (widget);
+
+ if (!gtk_widget_get_focus_child (widget))
+ gtk_widget_child_focus (widget, GTK_DIR_TAB_FORWARD);
}
static void
-gtk_popover_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+gtk_popover_hide (GtkWidget *widget)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (GTK_POPOVER (object));
-
- switch (prop_id)
- {
- case PROP_RELATIVE_TO:
- g_value_set_object (value, priv->widget);
- break;
- case PROP_POINTING_TO:
- g_value_set_boxed (value, &priv->pointing_to);
- break;
- case PROP_POSITION:
- g_value_set_enum (value, priv->preferred_position);
- break;
- case PROP_MODAL:
- g_value_set_boolean (value, priv->modal);
- break;
- case PROP_CONSTRAIN_TO:
- g_value_set_enum (value, priv->constraint);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
+ _gtk_widget_set_visible_flag (widget, FALSE);
+ gtk_widget_unmap (widget);
+ g_signal_emit (widget, signals[CLOSED], 0);
}
-static gboolean
-transitions_enabled (GtkPopover *popover)
+static void
+grab_prepare_func (GdkSeat *seat,
+ GdkSurface *surface,
+ gpointer data)
{
- return gtk_settings_get_enable_animations (gtk_widget_get_settings (GTK_WIDGET (popover)));
+ gdk_surface_show (surface);
}
static void
-gtk_popover_hide_internal (GtkPopover *popover)
+gtk_popover_map (GtkWidget *widget)
{
+ GtkPopover *popover = GTK_POPOVER (widget);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkWidget *widget = GTK_WIDGET (popover);
-
- if (!priv->visible)
- return;
-
- priv->visible = FALSE;
- g_signal_emit (widget, signals[CLOSED], 0);
+ GtkWidget *child;
+ GdkRectangle parent_rect;
if (priv->modal)
- gtk_popover_apply_modality (popover, FALSE);
-
- if (gtk_widget_get_realized (widget))
{
- cairo_region_t *region = cairo_region_create ();
- gdk_surface_input_shape_combine_region (gtk_widget_get_surface (widget),
- region, 0, 0);
- cairo_region_destroy (region);
+ gdk_seat_grab (gdk_display_get_default_seat (priv->display),
+ priv->surface,
+ GDK_SEAT_CAPABILITY_ALL,
+ TRUE,
+ NULL, NULL, grab_prepare_func, NULL);
+ priv->has_grab = TRUE;
}
-}
-static void
-gtk_popover_finalize (GObject *object)
-{
- GtkPopover *popover = GTK_POPOVER (object);
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ gtk_widget_get_surface_allocation (priv->relative_to, &parent_rect);
+ move_to_rect (popover);
- if (priv->widget)
- gtk_popover_update_relative_to (popover, NULL);
+ GTK_WIDGET_CLASS (gtk_popover_parent_class)->map (widget);
- G_OBJECT_CLASS (gtk_popover_parent_class)->finalize (object);
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ if (child != NULL && gtk_widget_get_visible (child))
+ gtk_widget_map (child);
}
static void
-popover_unset_prev_focus (GtkPopover *popover)
+gtk_popover_unmap (GtkWidget *widget)
{
+ GtkPopover *popover = GTK_POPOVER (widget);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GtkWidget *child;
- if (!priv->prev_focus_widget)
- return;
+ GTK_WIDGET_CLASS (gtk_popover_parent_class)->unmap (widget);
- if (priv->prev_focus_unmap_id)
+ gdk_surface_hide (priv->surface);
+ if (priv->has_grab)
{
- g_signal_handler_disconnect (priv->prev_focus_widget,
- priv->prev_focus_unmap_id);
- priv->prev_focus_unmap_id = 0;
+ gdk_seat_ungrab (gdk_display_get_default_seat (priv->display));
+ priv->has_grab = FALSE;
}
- g_clear_object (&priv->prev_focus_widget);
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ if (child != NULL)
+ gtk_widget_unmap (child);
}
static void
@@ -519,751 +554,80 @@ gtk_popover_dispose (GObject *object)
{
GtkPopover *popover = GTK_POPOVER (object);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ guint i;
+ GtkWidget *child;
- if (priv->modal)
- gtk_popover_apply_modality (popover, FALSE);
-
- if (priv->window)
+ for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (popover_list)); i++)
{
- g_signal_handlers_disconnect_by_data (priv->window, popover);
- _gtk_window_remove_popover (priv->window, GTK_WIDGET (object));
+ gpointer item = g_list_model_get_item (G_LIST_MODEL (popover_list), i);
+ if (item == object)
+ {
+ g_list_store_remove (popover_list, i);
+ break;
+ }
+ else
+ g_object_unref (item);
}
- priv->window = NULL;
-
- if (priv->widget)
- gtk_popover_update_relative_to (popover, NULL);
-
- popover_unset_prev_focus (popover);
-
- g_clear_object (&priv->default_widget);
+ child = gtk_bin_get_child (GTK_BIN (popover));
- if (priv->contents_widget)
+ if (child)
{
- GtkWidget *child = gtk_bin_get_child (GTK_BIN (popover));
-
- if (child)
- {
- /* Parent is content_widget! */
- gtk_widget_unparent (child);
- _gtk_bin_set_child (GTK_BIN (popover), NULL);
- }
-
- gtk_widget_unparent (priv->contents_widget);
- priv->contents_widget = NULL;
+ gtk_widget_unparent (child);
+ _gtk_bin_set_child (GTK_BIN (popover), NULL);
}
+ g_clear_pointer (&priv->contents_widget, gtk_widget_unparent);
+
G_OBJECT_CLASS (gtk_popover_parent_class)->dispose (object);
}
static void
-gtk_popover_realize (GtkWidget *widget)
+gtk_popover_finalize (GObject *object)
{
- GtkAllocation allocation;
- GdkSurface *surface;
-
- gtk_widget_get_surface_allocation (widget, &allocation);
-
- surface = gdk_surface_new_child (gtk_widget_get_parent_surface (widget), &allocation);
-
- gtk_widget_set_surface (widget, surface);
- gtk_widget_register_surface (widget, surface);
-
- GTK_WIDGET_CLASS (gtk_popover_parent_class)->realize (widget);
+ G_OBJECT_CLASS (gtk_popover_parent_class)->finalize (object);
}
static void
-window_active_changed (GtkWindow *window,
- GParamSpec *pspec,
- GtkPopover *popover)
+gtk_popover_constructed (GObject *object)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- if (!priv->modal ||
- !gtk_widget_is_drawable (GTK_WIDGET (popover)))
- return;
+ g_list_store_append (popover_list, object);
+ g_object_unref (object);
+}
- if (gtk_window_is_active (window))
- {
- /* Regain the grab when the window is focused */
- GtkWidget *focus;
-
- gtk_grab_add (GTK_WIDGET (popover));
-
- focus = gtk_window_get_focus (window);
-
- if (focus == NULL || !gtk_widget_is_ancestor (focus, GTK_WIDGET (popover)))
- gtk_widget_grab_focus (GTK_WIDGET (popover));
-
- if (priv->grab_notify_blocked)
- g_signal_handler_unblock (priv->widget, priv->grab_notify_id);
-
- priv->grab_notify_blocked = FALSE;
- }
- else
- {
- /* Temporarily remove the grab when unfocused */
- g_signal_handler_block (priv->widget, priv->grab_notify_id);
- gtk_grab_remove (GTK_WIDGET (popover));
-
- priv->grab_notify_blocked = TRUE;
- }
-}
-
-static void
-window_set_focus (GtkWindow *window,
- GParamSpec *pspec,
- GtkPopover *popover)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkWidget *widget = gtk_root_get_focus (GTK_ROOT (window));
-
- if (!priv->modal || !widget || !gtk_widget_is_drawable (GTK_WIDGET (popover)))
- return;
-
- widget = gtk_widget_get_ancestor (widget, GTK_TYPE_POPOVER);
- while (widget != NULL)
- {
- if (widget == GTK_WIDGET (popover))
- return;
-
- widget = gtk_popover_get_relative_to (GTK_POPOVER (widget));
- if (widget == NULL)
- break;
- widget = gtk_widget_get_ancestor (widget, GTK_TYPE_POPOVER);
- }
-
- popover_unset_prev_focus (popover);
- gtk_widget_hide (GTK_WIDGET (popover));
-}
-
-static void
-prev_focus_unmap_cb (GtkWidget *widget,
- GtkPopover *popover)
-{
- popover_unset_prev_focus (popover);
-}
-
-static void
-gtk_popover_apply_modality (GtkPopover *popover,
- gboolean modal)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- if (!priv->window)
- return;
-
- if (modal)
- {
- GtkWidget *prev_focus;
-
- prev_focus = gtk_window_get_focus (priv->window);
- priv->prev_focus_widget = prev_focus;
- if (priv->prev_focus_widget)
- {
- priv->prev_focus_unmap_id =
- g_signal_connect (prev_focus, "unmap",
- G_CALLBACK (prev_focus_unmap_cb), popover);
- g_object_ref (prev_focus);
- }
- gtk_grab_add (GTK_WIDGET (popover));
- gtk_window_set_focus (priv->window, NULL);
- gtk_widget_grab_focus (GTK_WIDGET (popover));
-
- g_signal_connect (priv->window, "notify::is-active",
- G_CALLBACK (window_active_changed), popover);
- g_signal_connect (priv->window, "notify::focus-widget",
- G_CALLBACK (window_set_focus), popover);
- }
- else
- {
- g_signal_handlers_disconnect_by_data (priv->window, popover);
- if (priv->prev_focus_widget == GTK_WIDGET (priv->window))
- priv->prev_focus_unmap_id = 0;
- gtk_grab_remove (GTK_WIDGET (popover));
-
- /* Let prev_focus_widget regain focus */
- if (priv->prev_focus_widget &&
- gtk_widget_is_drawable (priv->prev_focus_widget))
- {
- if (GTK_IS_ENTRY (priv->prev_focus_widget))
- gtk_entry_grab_focus_without_selecting (GTK_ENTRY (priv->prev_focus_widget));
- else
- gtk_widget_grab_focus (priv->prev_focus_widget);
- }
- else if (priv->window)
- gtk_widget_grab_focus (GTK_WIDGET (priv->window));
-
- popover_unset_prev_focus (popover);
- }
-}
-
-static gboolean
-show_animate_cb (GtkWidget *widget,
- GdkFrameClock *frame_clock,
- gpointer user_data)
-{
- GtkPopover *popover = GTK_POPOVER (widget);
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- gdouble t;
-
- if (priv->first_frame_skipped)
- gtk_progress_tracker_advance_frame (&priv->tracker,
- gdk_frame_clock_get_frame_time (frame_clock));
- else
- priv->first_frame_skipped = TRUE;
-
- t = gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE);
-
- if (priv->state == STATE_SHOWING)
- {
- priv->transition_diff = TRANSITION_DIFF - (TRANSITION_DIFF * t);
- gtk_widget_set_opacity (widget, t);
- }
- else if (priv->state == STATE_HIDING)
- {
- priv->transition_diff = -TRANSITION_DIFF * t;
- gtk_widget_set_opacity (widget, 1.0 - t);
- }
-
- gtk_popover_update_position (popover);
- gtk_widget_queue_allocate (GTK_WIDGET (priv->window));
-
- if (gtk_progress_tracker_get_state (&priv->tracker) == GTK_PROGRESS_STATE_AFTER)
- {
- if (priv->state == STATE_SHOWING)
- {
- gtk_popover_set_state (popover, STATE_SHOWN);
-
- if (!priv->visible)
- gtk_popover_set_state (popover, STATE_HIDING);
- }
- else
- {
- gtk_widget_hide (widget);
- }
-
- priv->tick_id = 0;
- return G_SOURCE_REMOVE;
- }
- else
- return G_SOURCE_CONTINUE;
-}
-
-static void
-gtk_popover_stop_transition (GtkPopover *popover)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- if (priv->tick_id != 0)
- {
- gtk_widget_remove_tick_callback (GTK_WIDGET (popover), priv->tick_id);
- priv->tick_id = 0;
- }
-}
-
-static void
-gtk_popover_start_transition (GtkPopover *popover)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- if (priv->tick_id != 0)
- return;
-
- priv->first_frame_skipped = FALSE;
- gtk_progress_tracker_start (&priv->tracker, TRANSITION_DURATION, 0, 1.0);
- priv->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (popover),
- show_animate_cb,
- popover, NULL);
-}
-
-static void
-gtk_popover_set_state (GtkPopover *popover,
- guint state)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- if (!transitions_enabled (popover) ||
- !gtk_widget_get_realized (GTK_WIDGET (popover)))
- {
- if (state == STATE_SHOWING)
- state = STATE_SHOWN;
- else if (state == STATE_HIDING)
- state = STATE_HIDDEN;
- }
-
- priv->state = state;
-
- if (state == STATE_SHOWING || state == STATE_HIDING)
- gtk_popover_start_transition (popover);
- else
- {
- gtk_popover_stop_transition (popover);
-
- gtk_widget_set_visible (GTK_WIDGET (popover), state == STATE_SHOWN);
- }
-}
-
-static void
-gtk_popover_map (GtkWidget *widget)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (GTK_POPOVER (widget));
-
- priv->prev_default = gtk_window_get_default_widget (priv->window);
- if (priv->prev_default)
- g_object_ref (priv->prev_default);
-
- GTK_WIDGET_CLASS (gtk_popover_parent_class)->map (widget);
-
- gdk_surface_show (gtk_widget_get_surface (widget));
- gtk_popover_update_position (GTK_POPOVER (widget));
-
- gtk_window_set_default (priv->window, priv->default_widget);
-}
-
-static void
-gtk_popover_unmap (GtkWidget *widget)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (GTK_POPOVER (widget));
-
- priv->button_pressed = FALSE;
-
- gdk_surface_hide (gtk_widget_get_surface (widget));
- GTK_WIDGET_CLASS (gtk_popover_parent_class)->unmap (widget);
-
- if (gtk_window_get_default_widget (priv->window) == priv->default_widget)
- gtk_window_set_default (priv->window, priv->prev_default);
- g_clear_object (&priv->prev_default);
-}
-
-static GtkPositionType
-get_effective_position (GtkPopover *popover,
- GtkPositionType pos)
-{
- if (_gtk_widget_get_direction (GTK_WIDGET (popover)) == GTK_TEXT_DIR_RTL)
- {
- if (pos == GTK_POS_LEFT)
- pos = GTK_POS_RIGHT;
- else if (pos == GTK_POS_RIGHT)
- pos = GTK_POS_LEFT;
- }
-
- return pos;
-}
-
-static void
-get_margin (GtkWidget *widget,
- GtkBorder *border)
-{
- GtkStyleContext *context;
-
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_get_margin (context,
- border);
-}
-
-static void
-gtk_popover_get_gap_coords (GtkPopover *popover,
- gint *initial_x_out,
- gint *initial_y_out,
- gint *tip_x_out,
- gint *tip_y_out,
- gint *final_x_out,
- gint *final_y_out)
-{
- GtkWidget *widget = GTK_WIDGET (popover);
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GdkRectangle rect = { 0 };
- gint base, tip, tip_pos;
- gint initial_x, initial_y;
- gint tip_x, tip_y;
- gint final_x, final_y;
- GtkPositionType pos;
- gint border_radius;
- GtkStyleContext *context;
- GtkBorder border;
- int popover_width, popover_height;
-
- gtk_popover_get_pointing_to (popover, &rect);
- popover_width = gtk_widget_get_width (widget);
- popover_height = gtk_widget_get_height (widget);
-
-#ifdef GDK_WINDOWING_WAYLAND
- if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget)))
- {
- gint win_x, win_y;
-
- gtk_widget_translate_coordinates (priv->widget, GTK_WIDGET (priv->window),
- rect.x, rect.y, &rect.x, &rect.y);
- gdk_surface_get_origin (gtk_widget_get_surface (GTK_WIDGET (popover)),
- &win_x, &win_y);
- rect.x -= win_x;
- rect.y -= win_y;
- }
- else
-#endif
- gtk_widget_translate_coordinates (priv->widget, widget,
- rect.x, rect.y, &rect.x, &rect.y);
-
- context = gtk_widget_get_style_context (priv->contents_widget);
- gtk_style_context_get_border (context, &border);
-
- pos = get_effective_position (popover, priv->final_position);
-
- gtk_style_context_get_border (context, &border);
- gtk_style_context_get (context,
- GTK_STYLE_PROPERTY_BORDER_RADIUS, &border_radius,
- NULL);
-
- if (pos == GTK_POS_BOTTOM || pos == GTK_POS_RIGHT)
- {
- tip = 0;
- base = tip + TAIL_HEIGHT + border.top;
- }
- else if (pos == GTK_POS_TOP)
- {
- base = popover_height - border.bottom - TAIL_HEIGHT;
- tip = base + TAIL_HEIGHT;
- }
- else if (pos == GTK_POS_LEFT)
- {
- base = popover_width - border.right - TAIL_HEIGHT;
- tip = base + TAIL_HEIGHT;
- }
- else
- g_assert_not_reached ();
-
- if (POS_IS_VERTICAL (pos))
- {
- tip_pos = rect.x + (rect.width / 2);
- initial_x = CLAMP (tip_pos - TAIL_GAP_WIDTH / 2,
- border_radius,
- popover_width - TAIL_GAP_WIDTH - border_radius);
- initial_y = base;
-
- tip_x = CLAMP (tip_pos, 0, popover_width);
- tip_y = tip;
-
- final_x = CLAMP (tip_pos + TAIL_GAP_WIDTH / 2,
- border_radius + TAIL_GAP_WIDTH,
- popover_width - border_radius);
- final_y = base;
- }
- else
- {
- tip_pos = rect.y + (rect.height / 2);
-
- initial_x = base;
- initial_y = CLAMP (tip_pos - TAIL_GAP_WIDTH / 2,
- border_radius,
- popover_height - TAIL_GAP_WIDTH - border_radius);
-
- tip_x = tip;
- tip_y = CLAMP (tip_pos, 0, popover_height);
-
- final_x = base;
- final_y = CLAMP (tip_pos + TAIL_GAP_WIDTH / 2,
- border_radius + TAIL_GAP_WIDTH,
- popover_height - border_radius);
- }
-
- *initial_x_out = initial_x;
- *initial_y_out = initial_y;
-
- *tip_x_out = tip_x;
- *tip_y_out = tip_y;
-
- *final_x_out = final_x;
- *final_y_out = final_y;
-}
-
-static void
-gtk_popover_get_rect_for_size (GtkPopover *popover,
- int popover_width,
- int popover_height,
- GdkRectangle *rect)
-{
- GtkWidget *widget = GTK_WIDGET (popover);
- int x, y, w, h;
- GtkBorder margin;
-
- get_margin (widget, &margin);
-
- x = 0;
- y = 0;
- w = popover_width;
- h = popover_height;
-
- x += MAX (TAIL_HEIGHT, margin.left);
- y += MAX (TAIL_HEIGHT, margin.top);
- w -= x + MAX (TAIL_HEIGHT, margin.right);
- h -= y + MAX (TAIL_HEIGHT, margin.bottom);
-
- rect->x = x;
- rect->y = y;
- rect->width = w;
- rect->height = h;
-}
-
-static void
-gtk_popover_get_rect_coords (GtkPopover *popover,
- int *x_out,
- int *y_out,
- int *w_out,
- int *h_out)
-{
- GtkWidget *widget = GTK_WIDGET (popover);
- GdkRectangle rect;
- GtkAllocation allocation;
-
- gtk_widget_get_allocation (widget, &allocation);
- gtk_popover_get_rect_for_size (popover, allocation.width, allocation.height, &rect);
-
- *x_out = rect.x;
- *y_out = rect.y;
- *w_out = rect.width;
- *h_out = rect.height;
-}
-
-static void
-gtk_popover_apply_tail_path (GtkPopover *popover,
- cairo_t *cr)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- gint initial_x, initial_y;
- gint tip_x, tip_y;
- gint final_x, final_y;
- GtkStyleContext *context;
- GtkBorder border;
-
- if (!priv->widget)
- return;
-
- context = gtk_widget_get_style_context (priv->contents_widget);
- gtk_style_context_get_border (context, &border);
-
- cairo_set_line_width (cr, 1);
- gtk_popover_get_gap_coords (popover,
- &initial_x, &initial_y,
- &tip_x, &tip_y,
- &final_x, &final_y);
-
- cairo_move_to (cr, initial_x, initial_y);
- cairo_line_to (cr, tip_x, tip_y);
- cairo_line_to (cr, final_x, final_y);
-}
-
-static void
-gtk_popover_fill_border_path (GtkPopover *popover,
- cairo_t *cr)
-{
- GtkWidget *widget = GTK_WIDGET (popover);
- GtkAllocation allocation;
- GtkStyleContext *context;
- int x, y, w, h;
- GskRoundedRect box;
-
- context = gtk_widget_get_style_context (widget);
- gtk_widget_get_allocation (widget, &allocation);
-
- cairo_set_source_rgba (cr, 0, 0, 0, 1);
-
- gtk_popover_apply_tail_path (popover, cr);
- cairo_close_path (cr);
- cairo_fill (cr);
-
- gtk_popover_get_rect_coords (popover, &x, &y, &w, &h);
-
- gtk_rounded_boxes_init_for_style (&box,
- NULL, NULL,
- gtk_style_context_lookup_style (context),
- x, y, w, h);
- gsk_rounded_rect_path (&box, cr);
- cairo_fill (cr);
-}
-
-static void
-gtk_popover_update_shape (GtkPopover *popover)
-{
- GtkWidget *widget = GTK_WIDGET (popover);
- cairo_surface_t *cairo_surface;
- cairo_region_t *region;
- GdkSurface *surface;
- cairo_t *cr;
-
-#ifdef GDK_WINDOWING_WAYLAND
- if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget)))
- return;
-#endif
-
- surface = gtk_widget_get_surface (widget);
- cairo_surface =
- gdk_surface_create_similar_surface (surface,
- CAIRO_CONTENT_COLOR_ALPHA,
- gdk_surface_get_width (surface),
- gdk_surface_get_height (surface));
-
- cr = cairo_create (cairo_surface);
- gtk_popover_fill_border_path (popover, cr);
- cairo_destroy (cr);
-
- region = gdk_cairo_region_create_from_surface (cairo_surface);
- cairo_surface_destroy (cairo_surface);
-
- gtk_widget_input_shape_combine_region (widget, region);
- cairo_region_destroy (region);
-
- gdk_surface_set_child_input_shapes (gtk_widget_get_surface (widget));
-}
-
-static void
-_gtk_popover_update_child_visible (GtkPopover *popover)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkWidget *widget = GTK_WIDGET (popover);
- GdkRectangle rect;
- GtkAllocation allocation;
- GtkWidget *parent;
-
- if (!priv->parent_scrollable)
- {
- gtk_widget_set_child_visible (widget, TRUE);
- return;
- }
-
- parent = gtk_widget_get_parent (GTK_WIDGET (priv->parent_scrollable));
- gtk_popover_get_pointing_to (popover, &rect);
-
- gtk_widget_translate_coordinates (priv->widget, parent,
- rect.x, rect.y, &rect.x, &rect.y);
-
- gtk_widget_get_allocation (GTK_WIDGET (parent), &allocation);
-
- if (rect.x + rect.width < 0 || rect.x > allocation.width ||
- rect.y + rect.height < 0 || rect.y > allocation.height)
- gtk_widget_set_child_visible (widget, FALSE);
- else
- gtk_widget_set_child_visible (widget, TRUE);
-}
-
-static GtkPositionType
-opposite_position (GtkPositionType pos)
-{
- switch (pos)
- {
- default:
- case GTK_POS_LEFT: return GTK_POS_RIGHT;
- case GTK_POS_RIGHT: return GTK_POS_LEFT;
- case GTK_POS_TOP: return GTK_POS_BOTTOM;
- case GTK_POS_BOTTOM: return GTK_POS_TOP;
- }
-}
-
-void
-gtk_popover_update_position (GtkPopover *popover)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkWidget *widget = GTK_WIDGET (popover);
- GtkAllocation window_alloc;
- GtkBorder window_shadow;
- GdkRectangle rect = { 0 };
- GtkRequisition req;
- GtkPositionType pos;
- gint overshoot[4];
- gint i, j;
- gint best;
-
- if (!priv->window || !gtk_widget_get_mapped (widget))
- return;
-
- gtk_widget_get_preferred_size (widget, NULL, &req);
- gtk_widget_get_allocation (GTK_WIDGET (priv->window), &window_alloc);
- _gtk_window_get_shadow_width (priv->window, &window_shadow);
- priv->final_position = priv->preferred_position;
-
- gtk_popover_get_pointing_to (popover, &rect);
- gtk_widget_translate_coordinates (priv->widget, GTK_WIDGET (priv->window),
- rect.x, rect.y, &rect.x, &rect.y);
-
- pos = get_effective_position (popover, priv->preferred_position);
-
- overshoot[GTK_POS_TOP] = req.height - rect.y + window_shadow.top;
- overshoot[GTK_POS_BOTTOM] = rect.y + rect.height + req.height - window_alloc.height
- + window_shadow.bottom;
- overshoot[GTK_POS_LEFT] = req.width - rect.x + window_shadow.left;
- overshoot[GTK_POS_RIGHT] = rect.x + rect.width + req.width - window_alloc.width
- + window_shadow.right;
-
-#ifdef GDK_WINDOWING_WAYLAND
- if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget)) &&
- priv->constraint == GTK_POPOVER_CONSTRAINT_NONE)
- {
- priv->final_position = priv->preferred_position;
- }
- else
-#endif
- if (overshoot[pos] <= 0)
- {
- priv->final_position = priv->preferred_position;
- }
- else if (overshoot[opposite_position (pos)] <= 0)
- {
- priv->final_position = opposite_position (priv->preferred_position);
- }
- else
- {
- best = G_MAXINT;
- pos = 0;
- for (i = 0; i < 4; i++)
- {
- j = get_effective_position (popover, i);
- if (overshoot[j] < best)
- {
- pos = i;
- best = overshoot[j];
- }
- }
- priv->final_position = pos;
- }
-
- switch (priv->final_position)
- {
- case GTK_POS_TOP:
- rect.y += priv->transition_diff;
- break;
- case GTK_POS_BOTTOM:
- rect.y -= priv->transition_diff;
- break;
- case GTK_POS_LEFT:
- rect.x += priv->transition_diff;
- break;
- case GTK_POS_RIGHT:
- rect.x -= priv->transition_diff;
- break;
- default:
- break;
- }
-
- _gtk_window_set_popover_position (priv->window, widget,
- priv->final_position, &rect);
-
- if (priv->final_position != priv->current_position)
- {
- if (gtk_widget_is_drawable (widget))
- gtk_popover_update_shape (popover);
-
- priv->current_position = priv->final_position;
- }
+static void
+gtk_popover_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline)
+{
+ GtkPopover *popover = GTK_POPOVER (widget);
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- _gtk_popover_update_child_visible (popover);
+ gtk_widget_measure (priv->contents_widget,
+ orientation, for_size,
+ minimum, natural,
+ minimum_baseline, natural_baseline);
}
-GtkWidget *
-gtk_popover_get_contents_widget (GtkPopover *popover)
+static void
+gtk_popover_size_allocate (GtkWidget *widget,
+ int width,
+ int height,
+ int baseline)
{
+ GtkPopover *popover = GTK_POPOVER (widget);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- return priv->contents_widget;
+ if (priv->surface)
+ gtk_popover_move_resize (popover);
+
+ gtk_widget_size_allocate (priv->contents_widget,
+ &(GtkAllocation) { 0, 0, width, height },
+ baseline);
}
static void
@@ -1272,253 +636,141 @@ gtk_popover_snapshot (GtkWidget *widget,
{
GtkPopover *popover = GTK_POPOVER (widget);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkStyleContext *context;
- GtkBorder border;
- cairo_t *cr;
- /* Draw the child first so we can draw the arrow (partially) over it */
gtk_widget_snapshot_child (widget, priv->contents_widget, snapshot);
-
- cr = gtk_snapshot_append_cairo (snapshot,
- &GRAPHENE_RECT_INIT (
- 0, 0,
- gtk_widget_get_width (widget),
- gtk_widget_get_height (widget)
- ));
-
- /* Clip to the arrow shape */
- cairo_save (cr);
-
- gtk_popover_apply_tail_path (popover, cr);
-
- cairo_clip (cr);
-
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_save_to_node (context, priv->arrow_node);
- gtk_style_context_get_border (context, &border);
-
- /* Render the arrow background */
- gtk_render_background (context, cr,
- 0, 0,
- gtk_widget_get_width (widget),
- gtk_widget_get_height (widget));
-
- /* Render the border of the arrow tip */
- if (border.bottom > 0)
- {
- GdkRGBA *border_color;
-
- gtk_style_context_get (context, "border-color", &border_color, NULL);
- gtk_popover_apply_tail_path (popover, cr);
- gdk_cairo_set_source_rgba (cr, border_color);
-
- cairo_set_line_width (cr, border.bottom + 1);
- cairo_stroke (cr);
- gdk_rgba_free (border_color);
- }
-
- cairo_restore (cr);
- /* We're done */
- cairo_destroy (cr);
-
- gtk_style_context_restore (context);
-}
-
-static gint
-get_border_radius (GtkWidget *widget)
-{
- GtkStyleContext *context;
- gint border_radius;
-
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_get (context,
- GTK_STYLE_PROPERTY_BORDER_RADIUS, &border_radius,
- NULL);
- return border_radius;
}
-static gint
-get_minimal_size (GtkPopover *popover,
- GtkOrientation orientation)
+static void
+gtk_popover_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkPositionType pos;
- gint minimal_size;
-
- minimal_size = 2 * get_border_radius (GTK_WIDGET (popover));
- pos = get_effective_position (popover, priv->preferred_position);
-
- if ((orientation == GTK_ORIENTATION_HORIZONTAL && POS_IS_VERTICAL (pos)) ||
- (orientation == GTK_ORIENTATION_VERTICAL && !POS_IS_VERTICAL (pos)))
- minimal_size += TAIL_GAP_WIDTH;
+ GtkPopover *popover = GTK_POPOVER (object);
- return minimal_size;
-}
+ switch (prop_id)
+ {
+ case PROP_RELATIVE_TO:
+ gtk_popover_set_relative_to (popover, g_value_get_object (value));
+ break;
-static void
-gtk_popover_measure (GtkWidget *widget,
- GtkOrientation orientation,
- int for_size,
- int *minimum,
- int *natural,
- int *minimum_baseline,
- int *natural_baseline)
-{
- GtkPopover *popover = GTK_POPOVER (widget);
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- int minimal_size;
+ case PROP_POINTING_TO:
+ gtk_popover_set_pointing_to (popover, g_value_get_boxed (value));
+ break;
- *minimum = 0;
- *natural = 0;
+ case PROP_POSITION:
+ gtk_popover_set_position (popover, g_value_get_enum (value));
+ break;
- if (for_size >= 0)
- for_size -= TAIL_HEIGHT;
+ case PROP_MODAL:
+ gtk_popover_set_modal (popover, g_value_get_boolean (value));
+ break;
- gtk_widget_measure (priv->contents_widget, orientation, for_size, minimum, natural, NULL, NULL);
+ case NUM_PROPERTIES + GTK_ROOT_PROP_FOCUS_WIDGET:
+ gtk_popover_set_focus (popover, g_value_get_object (value));
+ break;
- minimal_size = get_minimal_size (popover, orientation);
- *minimum = MAX (*minimum, minimal_size);
- *natural = MAX (*natural, minimal_size);
+ case NUM_PROPERTIES + GTK_ROOT_PROP_DEFAULT_WIDGET:
+ gtk_popover_set_default (popover, g_value_get_object (value));
+ break;
- *minimum += TAIL_HEIGHT;
- *natural += TAIL_HEIGHT;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
static void
-gtk_popover_size_allocate (GtkWidget *widget,
- int width,
- int height,
- int baseline)
+gtk_popover_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- GtkPopover *popover = GTK_POPOVER (widget);
+ GtkPopover *popover = GTK_POPOVER (object);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkAllocation child_alloc = (GtkAllocation) {0, 0, width, height};
-
- /* Note that we in measure() we add TAIL_HEIGHT in both directions, regardless
- * of the popovers position. This is to ensure that we get enough space
- * even priv->current_position changes between measure and size-allocate.
- */
- child_alloc.height -= TAIL_HEIGHT;
- child_alloc.width -= TAIL_HEIGHT;
- switch (priv->current_position)
+ switch (prop_id)
{
- case GTK_POS_TOP:
- child_alloc.x += TAIL_HEIGHT / 2;
+ case PROP_RELATIVE_TO:
+ g_value_set_object (value, priv->relative_to);
break;
- case GTK_POS_BOTTOM:
- child_alloc.x += TAIL_HEIGHT / 2;
- child_alloc.y += TAIL_HEIGHT;
+
+ case PROP_POINTING_TO:
+ g_value_set_boxed (value, &priv->pointing_to);
break;
- case GTK_POS_LEFT:
- child_alloc.y += TAIL_HEIGHT / 2;
+
+ case PROP_POSITION:
+ g_value_set_enum (value, priv->position);
break;
- case GTK_POS_RIGHT:
- child_alloc.x += TAIL_HEIGHT;
- child_alloc.y += TAIL_HEIGHT / 2;
+
+ case PROP_MODAL:
+ g_value_set_boolean (value, priv->modal);
break;
- default:
+
+ case NUM_PROPERTIES + GTK_ROOT_PROP_FOCUS_WIDGET:
+ g_value_set_object (value, priv->focus_widget);
break;
- }
- gtk_widget_size_allocate (priv->contents_widget, &child_alloc, -1);
+ case NUM_PROPERTIES + GTK_ROOT_PROP_DEFAULT_WIDGET:
+ g_value_set_object (value, priv->default_widget);
+ break;
- if (gtk_widget_get_realized (widget))
- {
- GtkAllocation a;
- gtk_widget_get_surface_allocation (widget, &a);
- gdk_surface_move_resize (gtk_widget_get_surface (widget),
- a.x, a.y, a.width, a.height);
- gtk_popover_update_shape (popover);
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
}
}
static void
-gtk_popover_grab_focus (GtkWidget *widget)
+gtk_popover_activate_default (GtkPopover *popover)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (GTK_POPOVER (widget));
- GtkWidget *child;
-
- if (!priv->visible)
- return;
-
- /* Focus the first natural child */
- child = gtk_bin_get_child (GTK_BIN (widget));
-
- if (child)
- gtk_widget_child_focus (child, GTK_DIR_TAB_FORWARD);
+ gtk_root_activate_default (GTK_ROOT (popover));
}
-static gboolean
-gtk_popover_focus (GtkWidget *widget,
- GtkDirectionType direction)
+static void
+gtk_popover_activate_focus (GtkPopover *popover)
{
- GtkPopover *popover = GTK_POPOVER (widget);
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- if (!priv->visible)
- return FALSE;
-
- if (!GTK_WIDGET_CLASS (gtk_popover_parent_class)->focus (widget, direction))
- {
- GtkWidget *focus;
-
- focus = gtk_window_get_focus (priv->window);
- focus = gtk_widget_get_parent (focus);
-
- /* Unset focus child through children, so it is next stepped from
- * scratch.
- */
- while (focus && focus != widget)
- {
- gtk_widget_set_focus_child (focus, NULL);
- focus = gtk_widget_get_parent (focus);
- }
-
- return gtk_widget_child_focus (gtk_bin_get_child (GTK_BIN (widget)),
- direction);
- }
-
- return TRUE;
+ gtk_root_activate_focus (GTK_ROOT (popover));
}
static void
-gtk_popover_show (GtkWidget *widget)
+gtk_popover_close (GtkPopover *popover)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (GTK_POPOVER (widget));
-
- if (priv->window)
- _gtk_window_raise_popover (priv->window, widget);
-
- priv->visible = TRUE;
-
- GTK_WIDGET_CLASS (gtk_popover_parent_class)->show (widget);
-
- if (priv->modal)
- gtk_popover_apply_modality (GTK_POPOVER (widget), TRUE);
-
- priv->state = STATE_SHOWN;
-
- if (gtk_widget_get_realized (widget))
- gdk_surface_input_shape_combine_region (gtk_widget_get_surface (widget),
- NULL, 0, 0);
+ gtk_widget_hide (GTK_WIDGET (popover));
}
static void
-gtk_popover_hide (GtkWidget *widget)
+add_tab_bindings (GtkBindingSet *binding_set,
+ GdkModifierType modifiers,
+ GtkDirectionType direction)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (GTK_POPOVER (widget));
-
- gtk_popover_hide_internal (GTK_POPOVER (widget));
-
- gtk_popover_stop_transition (GTK_POPOVER (widget));
- priv->state = STATE_HIDDEN;
- priv->transition_diff = 0;
- gtk_progress_tracker_finish (&priv->tracker);
- gtk_widget_set_opacity (widget, 1.0);
-
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+}
- GTK_WIDGET_CLASS (gtk_popover_parent_class)->hide (widget);
+static void
+add_arrow_bindings (GtkBindingSet *binding_set,
+ guint keysym,
+ GtkDirectionType direction)
+{
+ guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
+
+ gtk_binding_entry_add_signal (binding_set, keysym, 0,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
}
static void
@@ -1529,10 +781,9 @@ gtk_popover_add (GtkContainer *container,
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
_gtk_bin_set_child (GTK_BIN (popover), child);
-
gtk_widget_set_parent (child, priv->contents_widget);
}
-
+
static void
gtk_popover_remove (GtkContainer *container,
GtkWidget *child)
@@ -1543,52 +794,41 @@ gtk_popover_remove (GtkContainer *container,
gtk_widget_unparent (child);
}
-static void
-gtk_popover_state_flags_changed (GtkWidget *widget,
- GtkStateFlags previous_state)
-{
- GtkPopover *popover = GTK_POPOVER (widget);
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkStateFlags state;
-
- state = gtk_widget_get_state_flags (widget);
- gtk_css_node_set_state (priv->arrow_node, state);
-
- GTK_WIDGET_CLASS (gtk_popover_parent_class)->state_flags_changed (widget, previous_state);
-}
-
static void
gtk_popover_class_init (GtkPopoverClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+ GtkBindingSet *binding_set;
+
+ if (popover_list == NULL)
+ popover_list = g_list_store_new (GTK_TYPE_WIDGET);
+ object_class->constructed = gtk_popover_constructed;
+ object_class->dispose = gtk_popover_dispose;
+ object_class->finalize = gtk_popover_finalize;
object_class->set_property = gtk_popover_set_property;
object_class->get_property = gtk_popover_get_property;
- object_class->finalize = gtk_popover_finalize;
- object_class->dispose = gtk_popover_dispose;
widget_class->realize = gtk_popover_realize;
+ widget_class->unrealize = gtk_popover_unrealize;
widget_class->map = gtk_popover_map;
widget_class->unmap = gtk_popover_unmap;
+ widget_class->show = gtk_popover_show;
+ widget_class->hide = gtk_popover_hide;
widget_class->measure = gtk_popover_measure;
widget_class->size_allocate = gtk_popover_size_allocate;
widget_class->snapshot = gtk_popover_snapshot;
- widget_class->grab_focus = gtk_popover_grab_focus;
- widget_class->focus = gtk_popover_focus;
- widget_class->show = gtk_popover_show;
- widget_class->hide = gtk_popover_hide;
- widget_class->state_flags_changed = gtk_popover_state_flags_changed;
+ widget_class->move_focus = gtk_popover_move_focus;
container_class->add = gtk_popover_add;
container_class->remove = gtk_popover_remove;
- /**
- * GtkPopover:relative-to:
- *
- * Sets the attached widget.
- */
+ klass->activate_default = gtk_popover_activate_default;
+ klass->activate_focus = gtk_popover_activate_focus;
+ klass->close = gtk_popover_close;
+
properties[PROP_RELATIVE_TO] =
g_param_spec_object ("relative-to",
P_("Relative to"),
@@ -1596,11 +836,6 @@ gtk_popover_class_init (GtkPopoverClass *klass)
GTK_TYPE_WIDGET,
GTK_PARAM_READWRITE);
- /**
- * GtkPopover:pointing-to:
- *
- * Marks a specific rectangle to be pointed.
- */
properties[PROP_POINTING_TO] =
g_param_spec_boxed ("pointing-to",
P_("Pointing to"),
@@ -1608,11 +843,6 @@ gtk_popover_class_init (GtkPopoverClass *klass)
GDK_TYPE_RECTANGLE,
GTK_PARAM_READWRITE);
- /**
- * GtkPopover:position
- *
- * Sets the preferred position of the popover.
- */
properties[PROP_POSITION] =
g_param_spec_enum ("position",
P_("Position"),
@@ -1620,12 +850,6 @@ gtk_popover_class_init (GtkPopoverClass *klass)
GTK_TYPE_POSITION_TYPE, GTK_POS_TOP,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
- /**
- * GtkPopover:modal
- *
- * Sets whether the popover is modal (so other elements in the window do not
- * receive input while the popover is visible).
- */
properties[PROP_MODAL] =
g_param_spec_boolean ("modal",
P_("Modal"),
@@ -1633,420 +857,549 @@ gtk_popover_class_init (GtkPopoverClass *klass)
TRUE,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
- /**
- * GtkPopover:constrain-to:
- *
- * Sets a constraint for the popover position.
- */
- properties[PROP_CONSTRAIN_TO] =
- g_param_spec_enum ("constrain-to",
- P_("Constraint"),
- P_("Constraint for the popover position"),
- GTK_TYPE_POPOVER_CONSTRAINT, GTK_POPOVER_CONSTRAINT_WINDOW,
- GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
-
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
+ gtk_root_install_properties (object_class, NUM_PROPERTIES);
+
+ signals[ACTIVATE_FOCUS] =
+ g_signal_new (I_("activate-focus"),
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkPopoverClass, activate_focus),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 0);
+
+ signals[ACTIVATE_DEFAULT] =
+ g_signal_new (I_("activate-default"),
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkPopoverClass, activate_default),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 0);
+
+ signals[CLOSE] =
+ g_signal_new (I_("close"),
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkPopoverClass, close),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 0);
- /**
- * GtkPopover::closed:
- *
- * This signal is emitted when the popover is dismissed either through
- * API or user interaction.
- */
signals[CLOSED] =
g_signal_new (I_("closed"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkPopoverClass, closed),
- NULL, NULL, NULL,
- G_TYPE_NONE, 0);
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 0);
+
+ binding_set = gtk_binding_set_by_class (klass);
+
+ add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
+ add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
+ add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
+ add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
+
+ add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
+ add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0, "activate-focus", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0, "activate-focus", 0);
- quark_widget_popovers = g_quark_from_static_string ("gtk-quark-widget-popovers");
- gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_POPOVER_ACCESSIBLE);
- gtk_widget_class_set_css_name (widget_class, I_("popover"));
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0, "activate-default", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0, "activate-default", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0, "activate-default", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "close", 0);
+
+ gtk_widget_class_set_css_name (widget_class, "popover");
+}
+
+GtkWidget *
+gtk_popover_new (GtkWidget *relative_to)
+{
+ return GTK_WIDGET (g_object_new (GTK_TYPE_POPOVER,
+ "relative-to", relative_to,
+ NULL));
}
static void
-gtk_popover_update_scrollable (GtkPopover *popover)
+size_changed (GtkWidget *widget,
+ int width,
+ int height,
+ int baseline,
+ GtkPopover *popover)
{
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkScrollable *scrollable;
- scrollable = GTK_SCROLLABLE (gtk_widget_get_ancestor (priv->widget,
- GTK_TYPE_SCROLLABLE));
- gtk_popover_set_scrollable_full (popover, scrollable);
+ if (priv->surface)
+ gtk_popover_move_resize (popover);
}
static void
-_gtk_popover_parent_hierarchy_changed (GtkWidget *widget,
- GParamSpec *pspec,
- GtkPopover *popover)
+gtk_popover_set_focus (GtkPopover *popover,
+ GtkWidget *focus)
{
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkWindow *new_window;
+ GtkWidget *old_focus = NULL;
+ GdkSeat *seat;
+ GdkDevice *device;
+ GdkEvent *event;
- new_window = GTK_WINDOW (gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW));
-
- if (priv->window == new_window)
+ if (focus && !gtk_widget_is_sensitive (focus))
return;
- g_object_ref (popover);
+ if (priv->focus_widget)
+ old_focus = g_object_ref (priv->focus_widget);
+ g_set_object (&priv->focus_widget, NULL);
- if (gtk_widget_has_grab (GTK_WIDGET (popover)))
- gtk_popover_apply_modality (popover, FALSE);
+ seat = gdk_display_get_default_seat (gtk_widget_get_display (GTK_WIDGET (popover)));
+ device = gdk_seat_get_keyboard (seat);
- if (priv->window)
- _gtk_window_remove_popover (priv->window, GTK_WIDGET (popover));
+ event = gdk_event_new (GDK_FOCUS_CHANGE);
+ gdk_event_set_display (event, gtk_widget_get_display (GTK_WIDGET (popover)));
+ gdk_event_set_device (event, device);
+ event->any.surface = _gtk_widget_get_surface (GTK_WIDGET (popover));
+ if (event->any.surface)
+ g_object_ref (event->any.surface);
- if (priv->parent_scrollable)
- gtk_popover_set_scrollable_full (popover, NULL);
+ gtk_synthesize_crossing_events (GTK_ROOT (popover), old_focus, focus, event, GDK_CROSSING_NORMAL);
- priv->window = new_window;
+ g_object_unref (event);
- if (new_window)
- {
- _gtk_window_add_popover (new_window, GTK_WIDGET (popover), priv->widget, TRUE);
- gtk_popover_update_scrollable (popover);
- gtk_popover_update_position (popover);
- }
+ g_set_object (&priv->focus_widget, focus);
- if (gtk_widget_is_visible (GTK_WIDGET (popover)))
- gtk_widget_queue_resize (GTK_WIDGET (popover));
+ g_clear_object (&old_focus);
- g_object_unref (popover);
+ g_object_notify (G_OBJECT (popover), "focus-widget");
}
static void
-_popover_propagate_state (GtkPopover *popover,
- GtkStateFlags state,
- GtkStateFlags old_state,
- GtkStateFlags flag)
+do_focus_change (GtkWidget *widget,
+ gboolean in)
{
- if ((state & flag) != (old_state & flag))
- {
- if ((state & flag) == flag)
- gtk_widget_set_state_flags (GTK_WIDGET (popover), flag, FALSE);
- else
- gtk_widget_unset_state_flags (GTK_WIDGET (popover), flag);
- }
+ GdkSeat *seat;
+ GdkDevice *device;
+ GdkEvent *event;
+
+ seat = gdk_display_get_default_seat (gtk_widget_get_display (widget));
+ device = gdk_seat_get_keyboard (seat);
+
+ event = gdk_event_new (GDK_FOCUS_CHANGE);
+ gdk_event_set_display (event, gtk_widget_get_display (widget));
+ gdk_event_set_device (event, device);
+
+ event->any.type = GDK_FOCUS_CHANGE;
+ event->any.surface = _gtk_widget_get_surface (widget);
+ if (event->any.surface)
+ g_object_ref (event->any.surface);
+ event->focus_change.in = in;
+ event->focus_change.mode = GDK_CROSSING_STATE_CHANGED;
+ event->focus_change.detail = GDK_NOTIFY_ANCESTOR;
+
+ gtk_widget_set_has_focus (widget, in);
+ gtk_widget_event (widget, event);
+
+ g_object_unref (event);
}
static void
-_gtk_popover_parent_state_changed (GtkWidget *widget,
- GtkStateFlags old_state,
- GtkPopover *popover)
+gtk_popover_set_is_active (GtkPopover *popover,
+ gboolean active)
+{
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
+ if (priv->active == active)
+ return;
+
+ priv->active = active;
+
+ if (priv->focus_widget &&
+ priv->focus_widget != GTK_WIDGET (popover) &&
+ gtk_widget_has_focus (priv->focus_widget) != active)
+ do_focus_change (priv->focus_widget, active);
+}
+
+GListModel *
+gtk_popover_get_popovers (void)
{
- guint state;
+ if (popover_list == NULL)
+ popover_list = g_list_store_new (GTK_TYPE_WIDGET);
- state = gtk_widget_get_state_flags (widget);
- _popover_propagate_state (popover, state, old_state,
- GTK_STATE_FLAG_INSENSITIVE);
- _popover_propagate_state (popover, state, old_state,
- GTK_STATE_FLAG_BACKDROP);
+ return G_LIST_MODEL (popover_list);
}
static void
-_gtk_popover_parent_grab_notify (GtkWidget *widget,
- gboolean was_shadowed,
- GtkPopover *popover)
+gtk_popover_set_default (GtkPopover *popover,
+ GtkWidget *widget)
{
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- if (priv->modal &&
- gtk_widget_is_visible (GTK_WIDGET (popover)) &&
- !gtk_widget_has_grab (GTK_WIDGET (popover)))
+ g_return_if_fail (GTK_IS_POPOVER (popover));
+
+ if (widget && !gtk_widget_get_can_default (widget))
+ return;
+
+ if (priv->default_widget == widget)
+ return;
+
+ if (priv->default_widget)
{
- GtkWidget *grab_widget;
+ if (priv->focus_widget != priv->default_widget ||
+ !gtk_widget_get_receives_default (priv->default_widget))
+ _gtk_widget_set_has_default (priv->default_widget, FALSE);
+
+ gtk_widget_queue_draw (priv->default_widget);
+ g_object_notify (G_OBJECT (priv->default_widget), "has-default");
+ }
+
+ g_set_object (&priv->default_widget, widget);
- grab_widget = gtk_grab_get_current ();
+ if (priv->default_widget)
+ {
+ if (priv->focus_widget == NULL ||
+ !gtk_widget_get_receives_default (priv->focus_widget))
+ _gtk_widget_set_has_default (priv->default_widget, TRUE);
- if (!grab_widget || !GTK_IS_POPOVER (grab_widget))
- gtk_popover_popdown (popover);
+ gtk_widget_queue_draw (priv->default_widget);
+ g_object_notify (G_OBJECT (priv->default_widget), "has-default");
}
+
+ g_object_notify (G_OBJECT (popover), "default-widget");
}
-static void
-_gtk_popover_parent_unmap (GtkWidget *widget,
- GtkPopover *popover)
+static GtkMnemonicHash *
+gtk_popover_get_mnemonic_hash (GtkPopover *popover,
+ gboolean create)
{
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- if (priv->state == STATE_SHOWING)
- priv->visible = FALSE;
- else if (priv->state == STATE_SHOWN)
- gtk_popover_set_state (popover, STATE_HIDING);
+ if (!priv->mnemonic_hash && create)
+ priv->mnemonic_hash = _gtk_mnemonic_hash_new ();
+
+ return priv->mnemonic_hash;
}
static void
-gtk_popover_parent_size_allocate (GtkWidget *widget,
- int width,
- int height,
- int baseline,
- GtkPopover *popover)
+gtk_popover_root_add_mnemonic (GtkRoot *root,
+ guint keyval,
+ GtkWidget *target)
{
- gtk_popover_update_position (popover);
+ _gtk_mnemonic_hash_add (gtk_popover_get_mnemonic_hash (GTK_POPOVER (root), TRUE), keyval, target);
}
static void
-_unmanage_popover (GObject *object)
+gtk_popover_root_remove_mnemonic (GtkRoot *root,
+ guint keyval,
+ GtkWidget *target)
{
- gtk_popover_update_relative_to (GTK_POPOVER (object), NULL);
- g_object_unref (object);
+ _gtk_mnemonic_hash_remove (gtk_popover_get_mnemonic_hash (GTK_POPOVER (root), TRUE), keyval, target);
}
-static void
-widget_manage_popover (GtkWidget *widget,
- GtkPopover *popover)
+static gboolean
+gtk_popover_root_activate_key (GtkRoot *root,
+ GdkEventKey *event)
{
- GHashTable *popovers;
+ GdkModifierType modifier = event->state;
+ guint keyval = event->keyval;
- popovers = g_object_get_qdata (G_OBJECT (widget), quark_widget_popovers);
-
- if (G_UNLIKELY (!popovers))
+ if ((modifier & gtk_accelerator_get_default_mod_mask ()) == GDK_MOD1_MASK)
{
- popovers = g_hash_table_new_full (NULL, NULL,
- (GDestroyNotify) _unmanage_popover, NULL);
- g_object_set_qdata_full (G_OBJECT (widget),
- quark_widget_popovers, popovers,
- (GDestroyNotify) g_hash_table_unref);
+ GtkMnemonicHash *hash = gtk_popover_get_mnemonic_hash (GTK_POPOVER (root), FALSE);
+ if (hash)
+ return _gtk_mnemonic_hash_activate (hash, keyval);
}
- g_hash_table_add (popovers, g_object_ref_sink (popover));
+ return FALSE;
}
-static void
-widget_unmanage_popover (GtkWidget *widget,
- GtkPopover *popover)
+static GtkPointerFocus *
+gtk_popover_lookup_pointer_focus (GtkPopover *popover,
+ GdkDevice *device,
+ GdkEventSequence *sequence)
{
- GHashTable *popovers;
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GList *l;
- popovers = g_object_get_qdata (G_OBJECT (widget), quark_widget_popovers);
+ for (l = priv->foci; l; l = l->next)
+ {
+ GtkPointerFocus *focus = l->data;
- if (G_UNLIKELY (!popovers))
- return;
+ if (focus->device == device && focus->sequence == sequence)
+ return focus;
+ }
- g_hash_table_remove (popovers, popover);
+ return NULL;
}
static void
-adjustment_changed_cb (GtkAdjustment *adjustment,
- GtkPopover *popover)
+gtk_popover_add_pointer_focus (GtkPopover *popover,
+ GtkPointerFocus *focus)
{
- gtk_popover_update_position (popover);
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
+ priv->foci = g_list_prepend (priv->foci, gtk_pointer_focus_ref (focus));
}
static void
-_gtk_popover_set_scrollable (GtkPopover *popover,
- GtkScrollable *scrollable)
+gtk_popover_remove_pointer_focus (GtkPopover *popover,
+ GtkPointerFocus *focus)
{
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GList *pos;
+
+ pos = g_list_find (priv->foci, focus);
+ if (!pos)
+ return;
+
+ priv->foci = g_list_remove (priv->foci, focus);
+ gtk_pointer_focus_unref (focus);
+}
- if (priv->parent_scrollable)
+static void
+gtk_popover_root_update_pointer_focus (GtkRoot *root,
+ GdkDevice *device,
+ GdkEventSequence *sequence,
+ GtkWidget *target,
+ double x,
+ double y)
+{
+ GtkPopover *popover = GTK_POPOVER (root);
+ GtkPointerFocus *focus;
+
+ focus = gtk_popover_lookup_pointer_focus (popover, device, sequence);
+ if (focus)
{
- if (priv->vadj)
+ gtk_pointer_focus_ref (focus);
+
+ if (target)
+ {
+ gtk_pointer_focus_set_target (focus, target);
+ gtk_pointer_focus_set_coordinates (focus, x, y);
+ }
+ else
{
- g_signal_handlers_disconnect_by_data (priv->vadj, popover);
- g_object_unref (priv->vadj);
- priv->vadj = NULL;
+ gtk_popover_remove_pointer_focus (popover, focus);
}
- if (priv->hadj)
- {
- g_signal_handlers_disconnect_by_data (priv->hadj, popover);
- g_object_unref (priv->hadj);
- priv->hadj = NULL;
- }
+ gtk_pointer_focus_unref (focus);
+ }
+ else if (target)
+ {
+ focus = gtk_pointer_focus_new (root, target, device, sequence, x, y);
+ gtk_popover_add_pointer_focus (popover, focus);
+ gtk_pointer_focus_unref (focus);
+ }
+}
+
+static void
+gtk_popover_root_update_pointer_focus_on_state_change (GtkRoot *root,
+ GtkWidget *widget)
+{
+ GtkPopover *popover = GTK_POPOVER (root);
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GList *l = priv->foci, *cur;
+
+ while (l)
+ {
+ GtkPointerFocus *focus = l->data;
- g_object_unref (priv->parent_scrollable);
- }
+ cur = l;
+ focus = cur->data;
+ l = cur->next;
- priv->parent_scrollable = scrollable;
+ gtk_pointer_focus_ref (focus);
- if (scrollable)
- {
- g_object_ref (scrollable);
- priv->vadj = gtk_scrollable_get_vadjustment (scrollable);
- priv->hadj = gtk_scrollable_get_hadjustment (scrollable);
+ if (focus->grab_widget &&
+ (focus->grab_widget == widget ||
+ gtk_widget_is_ancestor (focus->grab_widget, widget)))
+ gtk_pointer_focus_set_implicit_grab (focus, NULL);
- if (priv->vadj)
+ if (GTK_WIDGET (focus->toplevel) == widget)
{
- g_object_ref (priv->vadj);
- g_signal_connect (priv->vadj, "changed",
- G_CALLBACK (adjustment_changed_cb), popover);
- g_signal_connect (priv->vadj, "value-changed",
- G_CALLBACK (adjustment_changed_cb), popover);
+ /* Unmapping the toplevel, remove pointer focus */
+ priv->foci = g_list_remove_link (priv->foci, cur);
+ gtk_pointer_focus_unref (focus);
}
-
- if (priv->hadj)
+ else if (focus->target == widget ||
+ gtk_widget_is_ancestor (focus->target, widget))
{
- g_object_ref (priv->hadj);
- g_signal_connect (priv->hadj, "changed",
- G_CALLBACK (adjustment_changed_cb), popover);
- g_signal_connect (priv->hadj, "value-changed",
- G_CALLBACK (adjustment_changed_cb), popover);
+ gtk_pointer_focus_repick_target (focus);
}
+
+ gtk_pointer_focus_unref (focus);
}
}
-static void
-scrollable_notify_cb (GObject *object,
- GParamSpec *pspec,
- GtkPopover *popover)
+static GtkWidget *
+gtk_popover_root_lookup_pointer_focus (GtkRoot *root,
+ GdkDevice *device,
+ GdkEventSequence *sequence)
{
- if (pspec->value_type == GTK_TYPE_ADJUSTMENT)
- _gtk_popover_set_scrollable (popover, GTK_SCROLLABLE (object));
+ GtkPopover *popover = GTK_POPOVER (root);
+ GtkPointerFocus *focus;
+
+ focus = gtk_popover_lookup_pointer_focus (popover, device, sequence);
+ return focus ? gtk_pointer_focus_get_target (focus) : NULL;
}
-static void
-gtk_popover_set_scrollable_full (GtkPopover *popover,
- GtkScrollable *scrollable)
+static GtkWidget *
+gtk_popover_root_lookup_effective_pointer_focus (GtkRoot *root,
+ GdkDevice *device,
+ GdkEventSequence *sequence)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GtkPopover *popover = GTK_POPOVER (root);
+ GtkPointerFocus *focus;
- if (priv->scrollable_notify_id != 0 &&
- g_signal_handler_is_connected (priv->parent_scrollable, priv->scrollable_notify_id))
- {
- g_signal_handler_disconnect (priv->parent_scrollable, priv->scrollable_notify_id);
- priv->scrollable_notify_id = 0;
- }
+ focus = gtk_popover_lookup_pointer_focus (popover, device, sequence);
+ return focus ? gtk_pointer_focus_get_effective_target (focus) : NULL;
+}
- _gtk_popover_set_scrollable (popover, scrollable);
+static GtkWidget *
+gtk_popover_root_lookup_pointer_focus_implicit_grab (GtkRoot *root,
+ GdkDevice *device,
+ GdkEventSequence *sequence)
+{
+ GtkPopover *popover = GTK_POPOVER (root);
+ GtkPointerFocus *focus;
- if (scrollable)
- {
- priv->scrollable_notify_id =
- g_signal_connect (priv->parent_scrollable, "notify",
- G_CALLBACK (scrollable_notify_cb), popover);
- }
+ focus = gtk_popover_lookup_pointer_focus (popover, device, sequence);
+ return focus ? gtk_pointer_focus_get_implicit_grab (focus) : NULL;
}
static void
-gtk_popover_update_relative_to (GtkPopover *popover,
- GtkWidget *relative_to)
+gtk_popover_root_set_pointer_focus_grab (GtkRoot *root,
+ GdkDevice *device,
+ GdkEventSequence *sequence,
+ GtkWidget *grab_widget)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GtkPopover *popover = GTK_POPOVER (root);
+ GtkPointerFocus *focus;
- if (priv->widget == relative_to)
+ focus = gtk_popover_lookup_pointer_focus (popover, device, sequence);
+ if (!focus && !grab_widget)
return;
+ g_assert (focus != NULL);
+ gtk_pointer_focus_set_implicit_grab (focus, grab_widget);
+}
- g_object_ref (popover);
+static void
+update_cursor (GtkRoot *root,
+ GdkDevice *device,
+ GtkWidget *grab_widget,
+ GtkWidget *target)
+{
+ GdkCursor *cursor = NULL;
- if (priv->window)
+ if (grab_widget && !gtk_widget_is_ancestor (target, grab_widget))
{
- _gtk_window_remove_popover (priv->window, GTK_WIDGET (popover));
- priv->window = NULL;
+ /* Outside the grab widget, cursor stays to whatever the grab
+ * widget says.
+ */
+ cursor = gtk_widget_get_cursor (grab_widget);
}
-
- popover_unset_prev_focus (popover);
-
- if (priv->widget)
+ else
{
- if (g_signal_handler_is_connected (priv->widget, priv->hierarchy_changed_id))
- g_signal_handler_disconnect (priv->widget, priv->hierarchy_changed_id);
- if (g_signal_handler_is_connected (priv->widget, priv->size_allocate_id))
- g_signal_handler_disconnect (priv->widget, priv->size_allocate_id);
- if (g_signal_handler_is_connected (priv->widget, priv->unmap_id))
- g_signal_handler_disconnect (priv->widget, priv->unmap_id);
- if (g_signal_handler_is_connected (priv->widget, priv->state_changed_id))
- g_signal_handler_disconnect (priv->widget, priv->state_changed_id);
- if (g_signal_handler_is_connected (priv->widget, priv->grab_notify_id))
- g_signal_handler_disconnect (priv->widget, priv->grab_notify_id);
-
- widget_unmanage_popover (priv->widget, popover);
- }
+ /* Inside the grab widget or in absence of grabs, allow walking
+ * up the hierarchy to find out the cursor.
+ */
+ while (target)
+ {
+ if (grab_widget && target == grab_widget)
+ break;
- if (priv->parent_scrollable)
- gtk_popover_set_scrollable_full (popover, NULL);
+ cursor = gtk_widget_get_cursor (target);
- priv->widget = relative_to;
- g_object_notify_by_pspec (G_OBJECT (popover), properties[PROP_RELATIVE_TO]);
+ if (cursor)
+ break;
- if (priv->widget)
- {
- priv->window =
- GTK_WINDOW (gtk_widget_get_ancestor (priv->widget, GTK_TYPE_WINDOW));
-
- priv->hierarchy_changed_id =
- g_signal_connect (priv->widget, "notify::root",
- G_CALLBACK (_gtk_popover_parent_hierarchy_changed),
- popover);
- priv->size_allocate_id =
- g_signal_connect (priv->widget, "size-allocate",
- G_CALLBACK (gtk_popover_parent_size_allocate),
- popover);
- priv->unmap_id =
- g_signal_connect (priv->widget, "unmap",
- G_CALLBACK (_gtk_popover_parent_unmap),
- popover);
- priv->state_changed_id =
- g_signal_connect (priv->widget, "state-flags-changed",
- G_CALLBACK (_gtk_popover_parent_state_changed),
- popover);
- priv->grab_notify_id =
- g_signal_connect (priv->widget, "grab-notify",
- G_CALLBACK (_gtk_popover_parent_grab_notify),
- popover);
-
- /* Give ownership of the popover to widget */
- widget_manage_popover (priv->widget, popover);
+ target = _gtk_widget_get_parent (target);
+ }
}
- if (priv->window)
- _gtk_window_add_popover (priv->window, GTK_WIDGET (popover), priv->widget, TRUE);
-
- if (priv->widget)
- gtk_popover_update_scrollable (popover);
-
- _gtk_widget_update_parent_muxer (GTK_WIDGET (popover));
- g_object_unref (popover);
+ gdk_surface_set_device_cursor (gtk_widget_get_surface (GTK_WIDGET (root)), device, cursor);
}
static void
-gtk_popover_update_pointing_to (GtkPopover *popover,
- const GdkRectangle *pointing_to)
+gtk_popover_root_maybe_update_cursor (GtkRoot *root,
+ GtkWidget *widget,
+ GdkDevice *device)
{
+ GtkPopover *popover = GTK_POPOVER (root);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GList *l;
- if (pointing_to)
+ for (l = priv->foci; l; l = l->next)
{
- priv->pointing_to = *pointing_to;
- priv->has_pointing_to = TRUE;
- }
- else
- priv->has_pointing_to = FALSE;
+ GtkPointerFocus *focus = l->data;
+ GtkWidget *grab_widget = NULL;
+ GtkWidget *target;
- g_object_notify_by_pspec (G_OBJECT (popover), properties[PROP_POINTING_TO]);
-}
+ if (focus->sequence)
+ continue;
+ if (device && device != focus->device)
+ continue;
-static void
-gtk_popover_update_preferred_position (GtkPopover *popover,
- GtkPositionType position)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+#if 0
+ {
+ GtkWindowGroup *group = gtk_window_get_group (root);
+ grab_widget = gtk_window_group_get_current_device_grab (group, focus->device);
+ if (!grab_widget)
+ grab_widget = gtk_window_group_get_current_grab (group);
+ }
+#endif
- if (priv->preferred_position == position)
- return;
+ if (!grab_widget)
+ grab_widget = gtk_pointer_focus_get_implicit_grab (focus);
- priv->preferred_position = position;
- g_object_notify_by_pspec (G_OBJECT (popover), properties[PROP_POSITION]);
-}
+ target = gtk_pointer_focus_get_target (focus);
-/**
- * gtk_popover_new:
- * @relative_to: (allow-none): #GtkWidget the popover is related to
- *
- * Creates a new popover to point to @relative_to
- *
- * Returns: a new #GtkPopover
- **/
-GtkWidget *
-gtk_popover_new (GtkWidget *relative_to)
-{
- g_return_val_if_fail (relative_to == NULL || GTK_IS_WIDGET (relative_to), NULL);
+ if (widget)
+ {
+ /* Check whether the changed widget affects the current cursor
+ * lookups.
+ */
+ if (grab_widget && grab_widget != widget &&
+ !gtk_widget_is_ancestor (widget, grab_widget))
+ continue;
+ if (target != widget &&
+ !gtk_widget_is_ancestor (target, widget))
+ continue;
+ }
+
+ update_cursor (focus->toplevel, focus->device, grab_widget, target);
+
+ if (device)
+ break;
+ }
+}
- return g_object_new (GTK_TYPE_POPOVER,
- "relative-to", relative_to,
- NULL);
+static void
+gtk_popover_root_interface_init (GtkRootInterface *iface)
+{
+ iface->get_display = gtk_popover_root_get_display;
+ iface->get_renderer = gtk_popover_root_get_renderer;
+ iface->get_surface_transform = gtk_popover_root_get_surface_transform;
+ iface->check_resize = gtk_popover_root_check_resize;
+ iface->add_mnemonic = gtk_popover_root_add_mnemonic;
+ iface->remove_mnemonic = gtk_popover_root_remove_mnemonic;
+ iface->activate_key = gtk_popover_root_activate_key;
+ iface->update_pointer_focus = gtk_popover_root_update_pointer_focus;
+ iface->update_pointer_focus_on_state_change = gtk_popover_root_update_pointer_focus_on_state_change;
+ iface->lookup_pointer_focus = gtk_popover_root_lookup_pointer_focus;
+ iface->lookup_pointer_focus_implicit_grab = gtk_popover_root_lookup_pointer_focus_implicit_grab;
+ iface->lookup_effective_pointer_focus = gtk_popover_root_lookup_effective_pointer_focus;
+ iface->set_pointer_focus_grab = gtk_popover_root_set_pointer_focus_grab;
+ iface->maybe_update_cursor = gtk_popover_root_maybe_update_cursor;
}
/**
@@ -2057,7 +1410,8 @@ gtk_popover_new (GtkWidget *relative_to)
* Sets a new widget to be attached to @popover. If @popover is
* visible, the position will be updated.
*
- * Note: the ownership of popovers is always given to their @relative_to
+ * Note: the ownership of popovers is always given to their @relative_t
+o
* widget, so if @relative_to is set to %NULL on an attached @popover, it
* will be detached from its previous widget, and consequently destroyed
* unless extra references are kept.
@@ -2066,13 +1420,32 @@ void
gtk_popover_set_relative_to (GtkPopover *popover,
GtkWidget *relative_to)
{
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
g_return_if_fail (GTK_IS_POPOVER (popover));
- g_return_if_fail (relative_to == NULL || GTK_IS_WIDGET (relative_to));
- gtk_popover_update_relative_to (popover, relative_to);
+ g_object_ref (popover);
+
+ if (priv->relative_to)
+ {
+ g_signal_handlers_disconnect_by_func (priv->relative_to, size_changed, popover);
+ gtk_widget_unparent (GTK_WIDGET (popover));
+ }
+
+ priv->relative_to = relative_to;
+
+ if (priv->relative_to)
+ {
+ g_signal_connect (priv->relative_to, "size-allocate", G_CALLBACK (size_changed), popover);
+ priv->display = gtk_widget_get_display (relative_to);
+ gtk_css_node_set_parent (gtk_widget_get_css_node (GTK_WIDGET (popover)),
+ gtk_widget_get_css_node (relative_to));
+ gtk_widget_set_parent (GTK_WIDGET (popover), relative_to);
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (popover), properties[PROP_RELATIVE_TO]);
- if (relative_to)
- gtk_popover_update_position (popover);
+ g_object_unref (popover);
}
/**
@@ -2090,7 +1463,7 @@ gtk_popover_get_relative_to (GtkPopover *popover)
g_return_val_if_fail (GTK_IS_POPOVER (popover), NULL);
- return priv->widget;
+ return priv->relative_to;
}
/**
@@ -2106,11 +1479,19 @@ void
gtk_popover_set_pointing_to (GtkPopover *popover,
const GdkRectangle *rect)
{
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
g_return_if_fail (GTK_IS_POPOVER (popover));
- g_return_if_fail (rect != NULL);
- gtk_popover_update_pointing_to (popover, rect);
- gtk_popover_update_position (popover);
+ if (rect)
+ {
+ priv->pointing_to = *rect;
+ priv->has_pointing_to = TRUE;
+ }
+ else
+ priv->has_pointing_to = FALSE;
+
+ g_object_notify_by_pspec (G_OBJECT (popover), properties[PROP_POINTING_TO]);
}
/**
@@ -2136,18 +1517,6 @@ gtk_popover_get_pointing_to (GtkPopover *popover,
if (priv->has_pointing_to)
*rect = priv->pointing_to;
- else if (priv->widget)
- {
- graphene_rect_t r;
-
- if (!gtk_widget_compute_bounds (priv->widget, priv->widget, &r))
- return FALSE;
-
- rect->x = floorf (r.origin.x);
- rect->y = floorf (r.origin.y);
- rect->width = ceilf (r.size.width);
- rect->height = ceilf (r.size.height);
- }
return priv->has_pointing_to;
}
@@ -2168,11 +1537,16 @@ void
gtk_popover_set_position (GtkPopover *popover,
GtkPositionType position)
{
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
g_return_if_fail (GTK_IS_POPOVER (popover));
- g_return_if_fail (position >= GTK_POS_LEFT && position <= GTK_POS_BOTTOM);
- gtk_popover_update_preferred_position (popover, position);
- gtk_popover_update_position (popover);
+ if (priv->position == position)
+ return;
+
+ priv->position = position;
+
+ g_object_notify_by_pspec (G_OBJECT (popover), properties[PROP_POSITION]);
}
/**
@@ -2190,7 +1564,7 @@ gtk_popover_get_position (GtkPopover *popover)
g_return_val_if_fail (GTK_IS_POPOVER (popover), GTK_POS_TOP);
- return priv->preferred_position;
+ return priv->position;
}
/**
@@ -2218,9 +1592,6 @@ gtk_popover_set_modal (GtkPopover *popover,
priv->modal = modal;
- if (gtk_widget_is_visible (GTK_WIDGET (popover)))
- gtk_popover_apply_modality (popover, priv->modal);
-
g_object_notify_by_pspec (G_OBJECT (popover), properties[PROP_MODAL]);
}
@@ -2243,6 +1614,57 @@ gtk_popover_get_modal (GtkPopover *popover)
return priv->modal;
}
+/**
+ * gtk_popover_popup:
+ * @popover: a #GtkPopover
+ *
+ * Pops @popover up. This is different than a gtk_widget_show() call
+ * in that it shows the popover with a transition. If you want to show
+ * the popover without a transition, use gtk_widget_show().
+ */
+void
+gtk_popover_popup (GtkPopover *popover)
+{
+ g_return_if_fail (GTK_IS_POPOVER (popover));
+
+ gtk_widget_show (GTK_WIDGET (popover));
+}
+
+/**
+ * gtk_popover_popdown:
+ * @popover: a #GtkPopover
+ *
+ * Pops @popover down.This is different than a gtk_widget_hide() call
+ * in that it shows the popover with a transition. If you want to hide
+ * the popover without a transition, use gtk_widget_hide().
+ */
+void
+gtk_popover_popdown (GtkPopover *popover)
+{
+ g_return_if_fail (GTK_IS_POPOVER (popover));
+
+ gtk_widget_hide (GTK_WIDGET (popover));
+}
+
+/**
+ * gtk_popover_set_default_widget:
+ * @popover: a #GtkPopover
+ * @widget: (allow-none): the new default widget, or %NULL
+ *
+ * Sets the widget that should be set as default widget while
+ * the popover is shown (see gtk_window_set_default()). #GtkPopover
+ * remembers the previous default widget and reestablishes it
+ * when the popover is dismissed.
+ */
+void
+gtk_popover_set_default_widget (GtkPopover *popover,
+ GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_POPOVER (popover));
+
+ gtk_root_set_default (GTK_ROOT (popover), widget);
+}
+
static void
back_to_main (GtkWidget *popover)
{
@@ -2289,7 +1711,6 @@ gtk_popover_bind_model (GtkPopover *popover,
GMenuModel *model,
const gchar *action_namespace)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
GtkWidget *child;
GtkWidget *stack;
GtkStyleContext *style_context;
@@ -2301,7 +1722,7 @@ gtk_popover_bind_model (GtkPopover *popover,
if (child)
gtk_widget_destroy (child);
- style_context = gtk_widget_get_style_context (priv->contents_widget);
+ style_context = gtk_widget_get_style_context (GTK_WIDGET (popover));
if (model)
{
@@ -2309,6 +1730,7 @@ gtk_popover_bind_model (GtkPopover *popover,
gtk_stack_set_vhomogeneous (GTK_STACK (stack), FALSE);
gtk_stack_set_transition_type (GTK_STACK (stack), GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT);
gtk_stack_set_interpolate_size (GTK_STACK (stack), TRUE);
+ gtk_widget_show (stack);
gtk_container_add (GTK_CONTAINER (popover), stack);
gtk_menu_section_box_new_toplevel (GTK_STACK (stack),
@@ -2361,155 +1783,11 @@ gtk_popover_new_from_model (GtkWidget *relative_to,
return popover;
}
-/**
- * gtk_popover_set_default_widget:
- * @popover: a #GtkPopover
- * @widget: (allow-none): the new default widget, or %NULL
- *
- * Sets the widget that should be set as default widget while
- * the popover is shown (see gtk_window_set_default()). #GtkPopover
- * remembers the previous default widget and reestablishes it
- * when the popover is dismissed.
- */
-void
-gtk_popover_set_default_widget (GtkPopover *popover,
- GtkWidget *widget)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- g_return_if_fail (GTK_IS_POPOVER (popover));
- g_return_if_fail (widget == NULL || gtk_widget_get_can_default (widget));
-
- if (priv->default_widget == widget)
- return;
-
- if (priv->default_widget)
- g_object_unref (priv->default_widget);
-
- priv->default_widget = widget;
-
- if (priv->default_widget)
- g_object_ref (priv->default_widget);
-
- if (gtk_widget_get_mapped (GTK_WIDGET (popover)))
- gtk_window_set_default (priv->window, priv->default_widget);
-}
-/**
- * gtk_popover_get_default_widget:
- * @popover: a #GtkPopover
- *
- * Gets the widget that should be set as the default while
- * the popover is shown.
- *
- * Returns: (nullable) (transfer none): the default widget,
- * or %NULL if there is none
- */
GtkWidget *
-gtk_popover_get_default_widget (GtkPopover *popover)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- g_return_val_if_fail (GTK_IS_POPOVER (popover), NULL);
-
- return priv->default_widget;
-}
-
-/**
- * gtk_popover_set_constrain_to:
- * @popover: a #GtkPopover
- * @constraint: the new constraint
- *
- * Sets a constraint for positioning this popover.
- *
- * Note that not all platforms support placing popovers freely,
- * and may already impose constraints.
- */
-void
-gtk_popover_set_constrain_to (GtkPopover *popover,
- GtkPopoverConstraint constraint)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- g_return_if_fail (GTK_IS_POPOVER (popover));
-
- if (priv->constraint == constraint)
- return;
-
- priv->constraint = constraint;
- gtk_popover_update_position (popover);
-
- g_object_notify_by_pspec (G_OBJECT (popover), properties[PROP_CONSTRAIN_TO]);
-}
-
-/**
- * gtk_popover_get_constrain_to:
- * @popover: a #GtkPopover
- *
- * Returns the constraint for placing this popover.
- * See gtk_popover_set_constrain_to().
- *
- * Returns: the constraint for placing this popover.
- */
-GtkPopoverConstraint
-gtk_popover_get_constrain_to (GtkPopover *popover)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- g_return_val_if_fail (GTK_IS_POPOVER (popover), GTK_POPOVER_CONSTRAINT_WINDOW);
-
- return priv->constraint;
-}
-
-/**
- * gtk_popover_popup:
- * @popover: a #GtkPopover
- *
- * Pops @popover up. This is different than a gtk_widget_show() call
- * in that it shows the popover with a transition. If you want to show
- * the popover without a transition, use gtk_widget_show().
- */
-void
-gtk_popover_popup (GtkPopover *popover)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- g_return_if_fail (GTK_IS_POPOVER (popover));
-
- if (priv->state == STATE_SHOWING ||
- priv->state == STATE_SHOWN)
- return;
-
- gtk_widget_show (GTK_WIDGET (popover));
-
- if (transitions_enabled (popover))
- gtk_popover_set_state (popover, STATE_SHOWING);
-}
-
-/**
- * gtk_popover_popdown:
- * @popover: a #GtkPopover
- *
- * Pops @popover down.This is different than a gtk_widget_hide() call
- * in that it shows the popover with a transition. If you want to hide
- * the popover without a transition, use gtk_widget_hide().
- */
-void
-gtk_popover_popdown (GtkPopover *popover)
+gtk_popover_get_contents_widget (GtkPopover *popover)
{
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- g_return_if_fail (GTK_IS_POPOVER (popover));
-
- if (priv->state == STATE_HIDING ||
- priv->state == STATE_HIDDEN)
- return;
-
-
- if (!transitions_enabled (popover))
- gtk_widget_hide (GTK_WIDGET (popover));
- else
- gtk_popover_set_state (popover, STATE_HIDING);
-
- gtk_popover_hide_internal (popover);
+ return priv->contents_widget;
}
diff --git a/gtk/gtkpopover.h b/gtk/gtkpopover.h
index 11acc02645..d628bfdf1c 100644
--- a/gtk/gtkpopover.h
+++ b/gtk/gtkpopover.h
@@ -1,5 +1,8 @@
/* GTK - The GIMP Toolkit
- * Copyright © 2013 Carlos Garnacho <carlosg gnome org>
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * Authors:
+ * - Matthias Clasen <mclasen redhat com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,95 +25,92 @@
#error "Only <gtk/gtk.h> can be included directly."
#endif
-#include <gtk/gtkwindow.h>
+#include <gtk/gtkbin.h>
G_BEGIN_DECLS
-#define GTK_TYPE_POPOVER (gtk_popover_get_type ())
-#define GTK_POPOVER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_POPOVER, GtkPopover))
-#define GTK_POPOVER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GTK_TYPE_POPOVER, GtkPopoverClass))
-#define GTK_IS_POPOVER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_POPOVER))
-#define GTK_IS_POPOVER_CLASS(o) (G_TYPE_CHECK_CLASS_TYPE ((o), GTK_TYPE_POPOVER))
-#define GTK_POPOVER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_POPOVER, GtkPopoverClass))
+#define GTK_TYPE_POPOVER (gtk_popover_get_type ())
+#define GTK_POPOVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_POPOVER, GtkPopover))
+#define GTK_POPOVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_POPOVER,
GtkPopoverClass))
+#define GTK_IS_POPOVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_POPOVER))
+#define GTK_IS_POPOVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_POPOVER))
+#define GTK_POPOVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_POPOVER,
GtkPopoverClass))
-typedef struct _GtkPopover GtkPopover;
-typedef struct _GtkPopoverClass GtkPopoverClass;
+typedef struct _GtkPopover GtkPopover;
+typedef struct _GtkPopoverClass GtkPopoverClass;
struct _GtkPopover
{
- GtkBin parent_instance;
+ GtkBin parent;
};
struct _GtkPopoverClass
{
GtkBinClass parent_class;
- void (* closed) (GtkPopover *popover);
+ /* keybinding signals */
+
+ void (* activate_focus) (GtkPopover *popover);
+ void (* activate_default) (GtkPopover *popover);
+ void (* close) (GtkPopover *popover);
- /*< private >*/
+ /* signals */
- /* Padding for future expansion */
- gpointer reserved[10];
+ void (* closed) (GtkPopover *popover);
};
GDK_AVAILABLE_IN_ALL
-GType gtk_popover_get_type (void) G_GNUC_CONST;
+GType gtk_popover_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
-GtkWidget * gtk_popover_new (GtkWidget *relative_to);
+GtkWidget * gtk_popover_new (GtkWidget *relative_to);
GDK_AVAILABLE_IN_ALL
-GtkWidget * gtk_popover_new_from_model (GtkWidget *relative_to,
- GMenuModel *model);
+GtkWidget * gtk_popover_new_from_model (GtkWidget *relative_to,
+ GMenuModel *model);
GDK_AVAILABLE_IN_ALL
-void gtk_popover_set_relative_to (GtkPopover *popover,
- GtkWidget *relative_to);
-GDK_AVAILABLE_IN_ALL
-GtkWidget * gtk_popover_get_relative_to (GtkPopover *popover);
+void gtk_popover_bind_model (GtkPopover *popover,
+ GMenuModel *model,
+ const gchar *action_namespace);
GDK_AVAILABLE_IN_ALL
-void gtk_popover_set_pointing_to (GtkPopover *popover,
- const GdkRectangle *rect);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_popover_get_pointing_to (GtkPopover *popover,
- GdkRectangle *rect);
-GDK_AVAILABLE_IN_ALL
-void gtk_popover_set_position (GtkPopover *popover,
- GtkPositionType position);
+void gtk_popover_set_relative_to (GtkPopover *popover,
+ GtkWidget *relative_to);
GDK_AVAILABLE_IN_ALL
-GtkPositionType gtk_popover_get_position (GtkPopover *popover);
+GtkWidget * gtk_popover_get_relative_to (GtkPopover *popover);
GDK_AVAILABLE_IN_ALL
-void gtk_popover_set_modal (GtkPopover *popover,
- gboolean modal);
+void gtk_popover_set_pointing_to (GtkPopover *popover,
+ const GdkRectangle *rect);
GDK_AVAILABLE_IN_ALL
-gboolean gtk_popover_get_modal (GtkPopover *popover);
-
+gboolean gtk_popover_get_pointing_to (GtkPopover *popover,
+ GdkRectangle *rect);
+GDK_AVAILABLE_IN_ALL
+void gtk_popover_set_position (GtkPopover *popover,
+ GtkPositionType position);
GDK_AVAILABLE_IN_ALL
-void gtk_popover_bind_model (GtkPopover *popover,
- GMenuModel *model,
- const gchar *action_namespace);
+GtkPositionType gtk_popover_get_position (GtkPopover *popover);
GDK_AVAILABLE_IN_ALL
-void gtk_popover_set_default_widget (GtkPopover *popover,
- GtkWidget *widget);
+void gtk_popover_set_modal (GtkPopover *popover,
+ gboolean modal);
GDK_AVAILABLE_IN_ALL
-GtkWidget * gtk_popover_get_default_widget (GtkPopover *popover);
+gboolean gtk_popover_get_modal (GtkPopover *popover);
GDK_AVAILABLE_IN_ALL
-void gtk_popover_set_constrain_to (GtkPopover *popover,
- GtkPopoverConstraint constraint);
-
+void gtk_popover_popup (GtkPopover *popover);
GDK_AVAILABLE_IN_ALL
-GtkPopoverConstraint gtk_popover_get_constrain_to (GtkPopover *popover);
+void gtk_popover_popdown (GtkPopover *popover);
GDK_AVAILABLE_IN_ALL
-void gtk_popover_popup (GtkPopover *popover);
+void
+gtk_popover_set_default_widget (GtkPopover *popover,
+ GtkWidget *widget);
-GDK_AVAILABLE_IN_ALL
-void gtk_popover_popdown (GtkPopover *popover);
+GDK_AVAILABLE_IN_ALL
+GListModel * gtk_popover_get_popovers (void);
G_END_DECLS
diff --git a/gtk/gtkpopovermenu.c b/gtk/gtkpopovermenu.c
index 241f02857d..89abd8b65e 100644
--- a/gtk/gtkpopovermenu.c
+++ b/gtk/gtkpopovermenu.c
@@ -139,8 +139,10 @@ gtk_popover_menu_init (GtkPopoverMenu *popover)
g_signal_connect (stack, "notify::visible-child-name",
G_CALLBACK (visible_submenu_changed), popover);
+#if 0
style_context = gtk_widget_get_style_context (gtk_popover_get_contents_widget (GTK_POPOVER (popover)));
gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_MENU);
+#endif
}
static void
diff --git a/gtk/gtkpopoverprivate.h b/gtk/gtkpopoverprivate.h
index fe24a5d775..db5fa6e57a 100644
--- a/gtk/gtkpopoverprivate.h
+++ b/gtk/gtkpopoverprivate.h
@@ -22,8 +22,6 @@
G_BEGIN_DECLS
-void gtk_popover_update_position (GtkPopover *popover);
-
GtkWidget *gtk_popover_get_contents_widget (GtkPopover *popover);
G_END_DECLS
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 1b6fa0eee0..b9950b5828 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -7290,10 +7290,12 @@ gtk_widget_get_scale_factor (GtkWidget *widget)
* just returning 1:
*/
display = _gtk_widget_get_display (widget);
- monitor = gdk_display_get_monitor (display, 0);
-
- if (monitor)
- return gdk_monitor_get_scale_factor (monitor);
+ if (display)
+ {
+ monitor = gdk_display_get_monitor (display, 0);
+ if (monitor)
+ return gdk_monitor_get_scale_factor (monitor);
+ }
return 1;
}
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 0e86d264a6..dd33c78fb5 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -5966,8 +5966,10 @@ popover_size_allocate (GtkWindowPopover *popover,
if (!gtk_widget_get_mapped (popover->widget))
return;
+#if 0
if (GTK_IS_POPOVER (popover->widget))
gtk_popover_update_position (GTK_POPOVER (popover->widget));
+#endif
popover_get_rect (popover, window, &rect);
gtk_widget_size_allocate (popover->widget, &rect, -1);
diff --git a/gtk/inspector/object-tree.c b/gtk/inspector/object-tree.c
index f2caf34708..f977096d69 100644
--- a/gtk/inspector/object-tree.c
+++ b/gtk/inspector/object-tree.c
@@ -41,6 +41,7 @@
#include "gtklabel.h"
#include "gtklistbox.h"
#include "gtkmenuitem.h"
+#include "gtkpopover.h"
#include "gtksettings.h"
#include "gtksizegroup.h"
#include "gtktextview.h"
@@ -1144,6 +1145,7 @@ create_root_model (void)
g_object_unref);
gtk_filter_list_model_set_model (filter, gtk_window_get_toplevels ());
g_list_store_append (list, filter);
+ g_list_store_append (list, gtk_popover_get_popovers ());
g_object_unref (filter);
flatten = gtk_flatten_list_model_new (G_TYPE_OBJECT, G_LIST_MODEL (list));
diff --git a/tests/meson.build b/tests/meson.build
index f70401b2d4..677fbb74e6 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -114,7 +114,6 @@ gtk_tests = [
['testpopover'],
['gdkgears', ['gtkgears.c']],
['listmodel'],
- ['testpopup'],
['testgaction'],
['testwidgetfocus'],
['testwidgettransforms'],
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]