[gtk/wip/matthiasc/popup2: 86/126] Replace GtkPopover by GtkPopup
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/matthiasc/popup2: 86/126] Replace GtkPopover by GtkPopup
- Date: Tue, 26 Mar 2019 23:35:01 +0000 (UTC)
commit 84585940e8d0113cbd2bd4989d8d6ff77af9a360
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Mar 20 23:35:04 2019 -0400
Replace GtkPopover by GtkPopup
Rename GtkPopup to GtkPopover, and make things work.
gtk/gtk.h | 1 -
gtk/gtkmain.c | 2 +-
gtk/gtkpopover.c | 2881 ++++++++++++++-----------------------------
gtk/gtkpopover.h | 98 +-
gtk/gtkpopovermenu.c | 2 +
gtk/gtkpopoverprivate.h | 2 -
gtk/gtkpopup.c | 1300 -------------------
gtk/gtkpopup.h | 97 --
gtk/gtkwidget.c | 10 +-
gtk/gtkwindow.c | 2 +
gtk/inspector/object-tree.c | 4 +-
gtk/meson.build | 1 -
tests/meson.build | 1 -
tests/testpopup.c | 90 --
14 files changed, 1000 insertions(+), 3491 deletions(-)
---
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 6cc64406bd..6d1ca27b5f 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -170,7 +170,6 @@
#include <gtk/gtkpicture.h>
#include <gtk/gtkpopover.h>
#include <gtk/gtkpopovermenu.h>
-#include <gtk/gtkpopup.h>
#include <gtk/gtkprintcontext.h>
#include <gtk/gtkprintoperation.h>
#include <gtk/gtkprintoperationpreview.h>
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 257de5c48b..c5bc0c4eae 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -1341,7 +1341,7 @@ rewrite_event_for_grabs (GdkEvent *event)
case GDK_TOUCHPAD_SWIPE:
case GDK_TOUCHPAD_PINCH:
if (grab_surface != event->any.surface &&
- GTK_IS_POPUP (grab_widget))
+ GTK_IS_POPOVER (grab_widget))
{
gtk_widget_hide (grab_widget);
return NULL;
diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c
index a39270c5a7..f30a274cea 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
@@ -15,1514 +18,647 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-/**
- * SECTION:gtkpopover
- * @Short_description: Context dependent bubbles
- * @Title: GtkPopover
- *
- * 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(),
- * 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().
- *
- * The position of a popover relative to the widget it is attached to
- * can also be changed through gtk_popover_set_position().
- *
- * By default, #GtkPopover performs a GTK+ grab, in order to ensure
- * input events get redirected to it while it is shown, and also so
- * the popover is dismissed in the expected situations (clicks outside
- * the popover, or the Esc key being pressed). If no such modal behavior
- * is desired on a popover, gtk_popover_set_modal() may be called on it
- * to tweak its behavior.
- *
- * ## GtkPopover as menu replacement
- *
- * GtkPopover is often used to replace menus. To facilitate this, it
- * supports being populated from a #GMenuModel, using
- * gtk_popover_new_from_model(). In addition to all the regular menu
- * model features, this function supports rendering sections in the
- * model in a more compact form, as a row of icon buttons instead of
- * menu items.
- *
- * To use this rendering, set the ”display-hint” attribute of the
- * section to ”horizontal-buttons” and set the icons of your items
- * with the ”verb-icon” attribute.
- *
- * |[
- * <section>
- * <attribute name="display-hint">horizontal-buttons</attribute>
- * <item>
- * <attribute name="label">Cut</attribute>
- * <attribute name="action">app.cut</attribute>
- * <attribute name="verb-icon">edit-cut-symbolic</attribute>
- * </item>
- * <item>
- * <attribute name="label">Copy</attribute>
- * <attribute name="action">app.copy</attribute>
- * <attribute name="verb-icon">edit-copy-symbolic</attribute>
- * </item>
- * <item>
- * <attribute name="label">Paste</attribute>
- * <attribute name="action">app.paste</attribute>
- * <attribute name="verb-icon">edit-paste-symbolic</attribute>
- * </item>
- * </section>
- * ]|
- *
- * # CSS nodes
- *
- * |[<!-- language="plain" -->
- * popover
- * ├── arrow
- * ╰── contents.background[.menu]
- * ╰── <child>
- * ]|
- *
- * The contents child node always gets the .background style class and it
- * gets the .menu style class if the popover is menu-like (e.g. #GtkPopoverMenu
- * or created using gtk_popover_new_from_model()).
- *
- * Particular uses of GtkPopover, such as touch selection popups
- * or magnifiers in #GtkEntry or #GtkTextView get style classes
- * like .touch-selection or .magnifier to differentiate from
- * plain popovers.
- *
- * When styling a popover directly, the popover node should usually not have any
- * background.
- *
- * Note that, in order to accomplish appropriate arrow visuals, #GtkPopover uses
- * custom drawing for the arrow node. This makes it possible for the arrow to change
- * its shape dynamically, but it also limits the possibilities of styling it using CSS.
- * In particular, the arrow gets drawn over the content node's border so they look
- * like one shape, which means that the border-width of the content node and the arrow
- * node should be the same. The arrow also does not support any border shape other than
- * solid, no border-radius, only one border width (border-bottom-width is used) and no box-shadow.
- */
-
#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"
+
+static GListStore *popover_list = NULL;
-#include "a11y/gtkpopoveraccessible.h"
+typedef struct {
+ GdkDisplay *display;
+ GskRenderer *renderer;
+ GdkSurface *surface;
+ GtkWidget *focus_widget;
+ gboolean active;
+ GtkWidget *default_widget;
+ GtkMnemonicHash *mnemonic_hash;
+ GList *foci;
-#include "gsk/gskroundedrectprivate.h"
+ GdkSurfaceState state;
+ GtkWidget *relative_to;
+ GdkRectangle pointing_to;
+ gboolean has_pointing_to;
+ GtkPositionType position;
+ gboolean modal;
+ gboolean has_grab;
-#ifdef GDK_WINDOWING_WAYLAND
-#include "wayland/gdkwayland.h"
-#endif
+ 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
-};
-
-enum {
- STATE_SHOWING,
- STATE_SHOWN,
- STATE_HIDING,
- STATE_HIDDEN
-};
-
-typedef struct _GtkPopoverPrivate GtkPopoverPrivate;
-struct _GtkPopoverPrivate
-{
- 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;
-};
-
-static GParamSpec *properties[NUM_PROPERTIES];
-static GQuark quark_widget_popovers = 0;
-static guint signals[N_SIGNALS] = { 0 };
-
-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);
+static GParamSpec *properties[NUM_PROPERTIES] = { NULL };
-static void gtk_popover_set_scrollable_full (GtkPopover *popover,
- GtkScrollable *scrollable);
+static void gtk_popover_root_interface_init (GtkRootInterface *iface);
-G_DEFINE_TYPE_WITH_PRIVATE (GtkPopover, gtk_popover, GTK_TYPE_BIN)
+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 void
-measure_contents (GtkGizmo *gizmo,
- GtkOrientation orientation,
- int for_size,
- int *minimum,
- int *natural,
- int *minimum_baseline,
- int *natural_baseline)
-{
- GtkPopover *popover = GTK_POPOVER (gtk_widget_get_parent (GTK_WIDGET (gizmo)));
- GtkWidget *child = gtk_bin_get_child (GTK_BIN (popover));
-
- if (child)
- gtk_widget_measure (child, orientation, for_size,
- minimum, natural,
- minimum_baseline, natural_baseline);
-}
-
-static void
-allocate_contents (GtkGizmo *gizmo,
- int width,
- int height,
- int baseline)
-{
- GtkPopover *popover = GTK_POPOVER (gtk_widget_get_parent (GTK_WIDGET (gizmo)));
- GtkWidget *child = gtk_bin_get_child (GTK_BIN (popover));
-
- if (child)
- gtk_widget_size_allocate (child,
- &(GtkAllocation) {
- 0, 0,
- width, height
- }, -1);
-}
-
-static void
-node_style_changed_cb (GtkCssNode *node,
- GtkCssStyleChange *change,
- GtkWidget *widget)
-{
- if (gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_SIZE))
- gtk_widget_queue_resize (widget);
- else
- gtk_widget_queue_draw (widget);
-}
-
-static gboolean
-key_controller_key_pressed (GtkEventControllerKey *key,
- guint keyval,
- guint keycode,
- GdkModifierType modifiers,
- GtkPopover *popover)
+static GdkDisplay *
+gtk_popover_root_get_display (GtkRoot *root)
{
+ GtkPopover *popover = GTK_POPOVER (root);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkWidget *toplevel, *focus;
-
- if (keyval == GDK_KEY_Escape)
- {
- gtk_popover_popdown (popover);
- return TRUE;
- }
-
- if (priv->modal)
- {
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (popover));
-
- if (GTK_IS_WINDOW (toplevel))
- {
- focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
- if (focus && gtk_widget_is_ancestor (focus, GTK_WIDGET (popover)))
- {
- if (gtk_event_controller_key_forward (key, focus))
- return TRUE;
- }
-
- /* Piggyback on the toplevel to have it handle key navigation */
- return gtk_event_controller_key_forward (key, toplevel);
- }
- }
-
- return FALSE;
+ return priv->display;
}
-static void
-gesture_pressed (GtkGestureMultiPress *gesture,
- gint n_press,
- gdouble x,
- gdouble y,
- GtkPopover *popover)
+static GskRenderer *
+gtk_popover_root_get_renderer (GtkRoot *root)
{
+ GtkPopover *popover = GTK_POPOVER (root);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- priv->button_pressed = TRUE;
+ return priv->renderer;
}
static void
-gesture_released (GtkGestureMultiPress *gesture,
- gint n_press,
- gdouble x,
- gdouble y,
- GtkPopover *popover)
+gtk_popover_root_get_surface_transform (GtkRoot *root,
+ int *x,
+ int *y)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- graphene_rect_t child_bounds;
- GtkWidget *child;
+ GtkStyleContext *context;
+ GtkBorder margin, border, padding;
- if (!priv->button_pressed)
- return;
+ 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);
- 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);
+ *x = margin.left + border.left + padding.left;
+ *y = margin.top + border.top + padding.top;
}
static void
-gtk_popover_init (GtkPopover *popover)
+move_to_rect (GtkPopover *popover)
{
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);
-
- 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);
-
- 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);
-}
+ GdkRectangle rect;
+ GdkGravity parent_anchor;
+ GdkGravity surface_anchor;
+ GdkAnchorHints anchor_hints;
-static void
-gtk_popover_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (prop_id)
+ gtk_widget_get_surface_allocation (priv->relative_to, &rect);
+ if (priv->has_pointing_to)
{
- 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);
+ rect.x += priv->pointing_to.x;
+ rect.y += priv->pointing_to.y;
+ rect.width = priv->pointing_to.width;
+ rect.height = priv->pointing_to.height;
}
-}
-
-static void
-gtk_popover_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (GTK_POPOVER (object));
- switch (prop_id)
+ switch (priv->position)
{
- 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);
+ case GTK_POS_LEFT:
+ parent_anchor = GDK_GRAVITY_WEST;
+ surface_anchor = GDK_GRAVITY_EAST;
+ anchor_hints = GDK_ANCHOR_FLIP_X;
break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static gboolean
-transitions_enabled (GtkPopover *popover)
-{
- return gtk_settings_get_enable_animations (gtk_widget_get_settings (GTK_WIDGET (popover)));
-}
-
-static void
-gtk_popover_hide_internal (GtkPopover *popover)
-{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkWidget *widget = GTK_WIDGET (popover);
- if (!priv->visible)
- return;
+ case GTK_POS_RIGHT:
+ parent_anchor = GDK_GRAVITY_EAST;
+ surface_anchor = GDK_GRAVITY_WEST;
+ anchor_hints = GDK_ANCHOR_FLIP_X;
+ break;
- priv->visible = FALSE;
- g_signal_emit (widget, signals[CLOSED], 0);
+ case GTK_POS_TOP:
+ parent_anchor = GDK_GRAVITY_NORTH;
+ surface_anchor = GDK_GRAVITY_SOUTH;
+ anchor_hints = GDK_ANCHOR_FLIP_Y;
+ break;
- if (priv->modal)
- gtk_popover_apply_modality (popover, FALSE);
+ case GTK_POS_BOTTOM:
+ parent_anchor = GDK_GRAVITY_SOUTH;
+ surface_anchor = GDK_GRAVITY_NORTH;
+ anchor_hints = GDK_ANCHOR_FLIP_Y;
+ break;
- 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);
+ default:
+ g_assert_not_reached ();
}
-}
-static void
-gtk_popover_finalize (GObject *object)
-{
- GtkPopover *popover = GTK_POPOVER (object);
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- if (priv->widget)
- gtk_popover_update_relative_to (popover, NULL);
-
- G_OBJECT_CLASS (gtk_popover_parent_class)->finalize (object);
+ gdk_surface_move_to_rect (priv->surface,
+ &rect,
+ parent_anchor,
+ surface_anchor,
+ anchor_hints,
+ 0, 0);
}
static void
-popover_unset_prev_focus (GtkPopover *popover)
+gtk_popover_move_resize (GtkPopover *popover)
{
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- if (!priv->prev_focus_widget)
- return;
-
- if (priv->prev_focus_unmap_id)
- {
- g_signal_handler_disconnect (priv->prev_focus_widget,
- priv->prev_focus_unmap_id);
- priv->prev_focus_unmap_id = 0;
- }
-
- g_clear_object (&priv->prev_focus_widget);
+ 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_dispose (GObject *object)
+gtk_popover_root_check_resize (GtkRoot *root)
{
- GtkPopover *popover = GTK_POPOVER (object);
+ GtkPopover *popover = GTK_POPOVER (root);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GtkWidget *widget = GTK_WIDGET (popover);
- if (priv->modal)
- gtk_popover_apply_modality (popover, FALSE);
-
- if (priv->window)
- {
- g_signal_handlers_disconnect_by_data (priv->window, popover);
- _gtk_window_remove_popover (priv->window, GTK_WIDGET (object));
- }
-
- priv->window = NULL;
-
- if (priv->widget)
- gtk_popover_update_relative_to (popover, NULL);
-
- popover_unset_prev_focus (popover);
-
- g_clear_object (&priv->default_widget);
-
- if (priv->contents_widget)
+ if (!_gtk_widget_get_alloc_needed (widget))
+ gtk_widget_ensure_allocate (widget);
+ else if (gtk_widget_get_visible (widget))
{
- 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_popover_move_resize (popover);
+ gtk_widget_allocate (GTK_WIDGET (popover),
+ gdk_surface_get_width (priv->surface),
+ gdk_surface_get_height (priv->surface),
+ -1, NULL);
}
-
- G_OBJECT_CLASS (gtk_popover_parent_class)->dispose (object);
}
-static void
-gtk_popover_realize (GtkWidget *widget)
-{
- 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);
-}
+static void gtk_popover_set_is_active (GtkPopover *popover, gboolean active);
static void
-window_active_changed (GtkWindow *window,
- GParamSpec *pspec,
- GtkPopover *popover)
+gtk_popover_focus_in (GtkWidget *widget)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
-
- if (!priv->modal ||
- !gtk_widget_is_drawable (GTK_WIDGET (popover)))
- return;
-
- 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;
- }
+ gtk_popover_set_is_active (GTK_POPOVER (widget), TRUE);
}
static void
-window_set_focus (GtkWindow *window,
- GParamSpec *pspec,
- GtkPopover *popover)
+gtk_popover_focus_out (GtkWidget *widget)
{
- 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));
+ gtk_popover_set_is_active (GTK_POPOVER (widget), FALSE);
}
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)
+ensure_state_flag_backdrop (GtkWidget *widget)
{
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);
+ if ((priv->state & GDK_SURFACE_STATE_FOCUSED) != 0)
+ gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
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;
+ gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE);
}
static void
-get_margin (GtkWidget *widget,
- GtkBorder *border)
+surface_state_changed (GtkWidget *widget)
{
- 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);
+ GtkPopover *popover = GTK_POPOVER (widget);
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);
+ GdkSurfaceState new_surface_state;
+ GdkSurfaceState changed_mask;
-#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);
+ new_surface_state = gdk_surface_get_state (_gtk_widget_get_surface (widget));
+ changed_mask = new_surface_state ^ priv->state;
+ priv->state = new_surface_state;
- 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 (changed_mask & GDK_SURFACE_STATE_FOCUSED)
+ ensure_state_flag_backdrop (widget);
- if (pos == GTK_POS_BOTTOM || pos == GTK_POS_RIGHT)
+ if (changed_mask & GDK_SURFACE_STATE_WITHDRAWN)
{
- tip = 0;
- base = tip + TAIL_HEIGHT + border.top;
+ if (priv->state & GDK_SURFACE_STATE_WITHDRAWN)
+ gtk_widget_hide (widget);
}
- 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)
+surface_size_changed (GtkWindow *window,
+ guint width,
+ guint height)
{
- 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)
+measure_contents (GtkGizmo *gizmo,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline)
{
- 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);
+ GtkPopover *popover = GTK_POPOVER (gtk_widget_get_parent (GTK_WIDGET (gizmo)));
+ GtkWidget *child = gtk_bin_get_child (GTK_BIN (popover));
- gdk_surface_set_child_input_shapes (gtk_widget_get_surface (widget));
+ if (child)
+ gtk_widget_measure (child, orientation, for_size,
+ minimum, natural,
+ minimum_baseline, natural_baseline);
}
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)
+allocate_contents (GtkGizmo *gizmo,
+ int width,
+ int height,
+ int baseline)
{
- 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;
- }
+ GtkPopover *popover = GTK_POPOVER (gtk_widget_get_parent (GTK_WIDGET (gizmo)));
+ GtkWidget *child = gtk_bin_get_child (GTK_BIN (popover));
- _gtk_popover_update_child_visible (popover);
+ if (child)
+ gtk_widget_size_allocate (child,
+ &(GtkAllocation) { 0, 0, width, height
+ }, -1);
}
-GtkWidget *
-gtk_popover_get_contents_widget (GtkPopover *popover)
+static void
+gtk_popover_init (GtkPopover *popover)
{
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ GtkEventController *controller;
+ GtkStyleContext *context;
- return priv->contents_widget;
+ gtk_widget_set_has_surface (GTK_WIDGET (popover), TRUE);
+
+ priv->position = GTK_POS_TOP;
+ priv->modal = TRUE;
+
+ 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);
+ 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 void
-gtk_popover_snapshot (GtkWidget *widget,
- GtkSnapshot *snapshot)
+gtk_popover_realize (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);
+ GdkRectangle parent_rect;
- cr = gtk_snapshot_append_cairo (snapshot,
- &GRAPHENE_RECT_INIT (
- 0, 0,
- gtk_widget_get_width (widget),
- gtk_widget_get_height (widget)
- ));
+ gtk_widget_get_surface_allocation (priv->relative_to, &parent_rect);
- /* Clip to the arrow shape */
- cairo_save (cr);
+ priv->surface = gdk_surface_new_popup_full (priv->display, gtk_widget_get_surface (priv->relative_to));
- gtk_popover_apply_tail_path (popover, cr);
+ 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);
- cairo_clip (cr);
+ gtk_widget_register_surface (widget, priv->surface);
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_save_to_node (context, priv->arrow_node);
- gtk_style_context_get_border (context, &border);
+ GTK_WIDGET_CLASS (gtk_popover_parent_class)->realize (widget);
- /* Render the arrow background */
- gtk_render_background (context, cr,
- 0, 0,
- gtk_widget_get_width (widget),
- gtk_widget_get_height (widget));
+ priv->renderer = gsk_renderer_new_for_surface (priv->surface);
+}
- /* Render the border of the arrow tip */
- if (border.bottom > 0)
- {
- GdkRGBA border_color;
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- gtk_style_context_get_border_color (context, &border_color);
-G_GNUC_END_IGNORE_DEPRECATIONS
+static void
+gtk_popover_unrealize (GtkWidget *widget)
+{
+ GtkPopover *popover = GTK_POPOVER (widget);
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- gtk_popover_apply_tail_path (popover, cr);
- gdk_cairo_set_source_rgba (cr, &border_color);
+ GTK_WIDGET_CLASS (gtk_popover_parent_class)->unrealize (widget);
- cairo_set_line_width (cr, border.bottom + 1);
- cairo_stroke (cr);
- }
+ gsk_renderer_unrealize (priv->renderer);
+ g_clear_object (&priv->renderer);
- cairo_restore (cr);
- /* We're done */
- cairo_destroy (cr);
+ g_signal_handlers_disconnect_by_func (priv->surface, surface_state_changed, widget);
+ g_signal_handlers_disconnect_by_func (priv->surface, surface_size_changed, widget);
- gtk_style_context_restore (context);
+ g_clear_object (&priv->surface);
}
-static gint
-get_border_radius (GtkWidget *widget)
+static void
+gtk_popover_move_focus (GtkWidget *widget,
+ GtkDirectionType dir)
{
- GtkStyleContext *context;
- gint border_radius;
+ gtk_widget_child_focus (widget, dir);
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_get (context,
- GTK_STYLE_PROPERTY_BORDER_RADIUS, &border_radius,
- NULL);
- return border_radius;
+ if (!gtk_widget_get_focus_child (widget))
+ gtk_root_set_focus (GTK_ROOT (widget), NULL);
}
-static gint
-get_minimal_size (GtkPopover *popover,
- GtkOrientation orientation)
+static void
+gtk_popover_show (GtkWidget *widget)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkPositionType pos;
- gint minimal_size;
+ _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);
- minimal_size = 2 * get_border_radius (GTK_WIDGET (popover));
- pos = get_effective_position (popover, priv->preferred_position);
+ if (!gtk_widget_get_focus_child (widget))
+ gtk_widget_child_focus (widget, GTK_DIR_TAB_FORWARD);
+}
- if ((orientation == GTK_ORIENTATION_HORIZONTAL && POS_IS_VERTICAL (pos)) ||
- (orientation == GTK_ORIENTATION_VERTICAL && !POS_IS_VERTICAL (pos)))
- minimal_size += TAIL_GAP_WIDTH;
+static void
+gtk_popover_hide (GtkWidget *widget)
+{
+ _gtk_widget_set_visible_flag (widget, FALSE);
+ gtk_widget_unmap (widget);
+ g_signal_emit (widget, signals[CLOSED], 0);
+}
- return minimal_size;
+static void
+grab_prepare_func (GdkSeat *seat,
+ GdkSurface *surface,
+ gpointer data)
+{
+ gdk_surface_show (surface);
}
static void
-gtk_popover_measure (GtkWidget *widget,
- GtkOrientation orientation,
- int for_size,
- int *minimum,
- int *natural,
- int *minimum_baseline,
- int *natural_baseline)
+gtk_popover_map (GtkWidget *widget)
{
GtkPopover *popover = GTK_POPOVER (widget);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- int minimal_size;
-
- *minimum = 0;
- *natural = 0;
+ GtkWidget *child;
+ GdkRectangle parent_rect;
- if (for_size >= 0)
- for_size -= TAIL_HEIGHT;
+ if (priv->modal)
+ {
+ 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;
+ }
- gtk_widget_measure (priv->contents_widget, orientation, for_size, minimum, natural, NULL, NULL);
+ gtk_widget_get_surface_allocation (priv->relative_to, &parent_rect);
+ move_to_rect (popover);
- minimal_size = get_minimal_size (popover, orientation);
- *minimum = MAX (*minimum, minimal_size);
- *natural = MAX (*natural, minimal_size);
+ GTK_WIDGET_CLASS (gtk_popover_parent_class)->map (widget);
- *minimum += TAIL_HEIGHT;
- *natural += TAIL_HEIGHT;
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ if (child != NULL && gtk_widget_get_visible (child))
+ gtk_widget_map (child);
}
static void
-gtk_popover_size_allocate (GtkWidget *widget,
- int width,
- int height,
- int baseline)
+gtk_popover_unmap (GtkWidget *widget)
{
GtkPopover *popover = GTK_POPOVER (widget);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- GtkAllocation child_alloc = (GtkAllocation) {0, 0, width, height};
+ GtkWidget *child;
+
+ GTK_WIDGET_CLASS (gtk_popover_parent_class)->unmap (widget);
+
+ gdk_surface_hide (priv->surface);
+ if (priv->has_grab)
+ {
+ gdk_seat_ungrab (gdk_display_get_default_seat (priv->display));
+ priv->has_grab = FALSE;
+ }
- /* 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;
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ if (child != NULL)
+ gtk_widget_unmap (child);
+}
+
+static void
+gtk_popover_dispose (GObject *object)
+{
+ GtkPopover *popover = GTK_POPOVER (object);
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+ guint i;
+ GtkWidget *child;
- switch (priv->current_position)
+ for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (popover_list)); i++)
{
- case GTK_POS_TOP:
- child_alloc.x += TAIL_HEIGHT / 2;
- break;
- case GTK_POS_BOTTOM:
- child_alloc.x += TAIL_HEIGHT / 2;
- child_alloc.y += TAIL_HEIGHT;
- break;
- case GTK_POS_LEFT:
- child_alloc.y += TAIL_HEIGHT / 2;
- break;
- case GTK_POS_RIGHT:
- child_alloc.x += TAIL_HEIGHT;
- child_alloc.y += TAIL_HEIGHT / 2;
- break;
- default:
- break;
+ 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);
}
- gtk_widget_size_allocate (priv->contents_widget, &child_alloc, -1);
+ child = gtk_bin_get_child (GTK_BIN (popover));
- if (gtk_widget_get_realized (widget))
+ if (child)
{
- 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);
+ 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_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (gtk_popover_parent_class)->finalize (object);
}
static void
-gtk_popover_grab_focus (GtkWidget *widget)
+gtk_popover_constructed (GObject *object)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (GTK_POPOVER (widget));
- GtkWidget *child;
+ g_list_store_append (popover_list, object);
+ g_object_unref (object);
+}
- if (!priv->visible)
- return;
+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);
- /* Focus the first natural child */
- child = gtk_bin_get_child (GTK_BIN (widget));
+ gtk_widget_measure (priv->contents_widget,
+ orientation, for_size,
+ minimum, natural,
+ minimum_baseline, natural_baseline);
+}
- if (child)
- gtk_widget_child_focus (child, GTK_DIR_TAB_FORWARD);
+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);
+
+ if (priv->surface)
+ gtk_popover_move_resize (popover);
+
+ gtk_widget_size_allocate (priv->contents_widget,
+ &(GtkAllocation) { 0, 0, width, height },
+ baseline);
}
-static gboolean
-gtk_popover_focus (GtkWidget *widget,
- GtkDirectionType direction)
+static void
+gtk_popover_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
{
GtkPopover *popover = GTK_POPOVER (widget);
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
- if (!priv->visible)
- return FALSE;
+ gtk_widget_snapshot_child (widget, priv->contents_widget, snapshot);
+}
+
+static void gtk_popover_set_focus (GtkPopover *popover,
+ GtkWidget *widget);
+
+static void gtk_popover_set_default (GtkPopover *popover,
+ GtkWidget *widget);
- if (!GTK_WIDGET_CLASS (gtk_popover_parent_class)->focus (widget, direction))
+static void
+gtk_popover_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkPopover *popover = GTK_POPOVER (object);
+
+ switch (prop_id)
{
- GtkWidget *focus;
+ case PROP_RELATIVE_TO:
+ gtk_popover_set_relative_to (popover, g_value_get_object (value));
+ break;
- focus = gtk_window_get_focus (priv->window);
- focus = gtk_widget_get_parent (focus);
+ case PROP_POINTING_TO:
+ gtk_popover_set_pointing_to (popover, g_value_get_boxed (value));
+ break;
- /* 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);
- }
+ case PROP_POSITION:
+ gtk_popover_set_position (popover, g_value_get_enum (value));
+ break;
- return gtk_widget_child_focus (gtk_bin_get_child (GTK_BIN (widget)),
- direction);
- }
+ case PROP_MODAL:
+ gtk_popover_set_modal (popover, g_value_get_boolean (value));
+ break;
+
+ case NUM_PROPERTIES + GTK_ROOT_PROP_FOCUS_WIDGET:
+ gtk_popover_set_focus (popover, g_value_get_object (value));
+ break;
+
+ case NUM_PROPERTIES + GTK_ROOT_PROP_DEFAULT_WIDGET:
+ gtk_popover_set_default (popover, g_value_get_object (value));
+ break;
- return TRUE;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
static void
-gtk_popover_show (GtkWidget *widget)
+gtk_popover_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (GTK_POPOVER (widget));
+ GtkPopover *popover = GTK_POPOVER (object);
+ GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
+
+ switch (prop_id)
+ {
+ case PROP_RELATIVE_TO:
+ g_value_set_object (value, priv->relative_to);
+ break;
- if (priv->window)
- _gtk_window_raise_popover (priv->window, widget);
+ case PROP_POINTING_TO:
+ g_value_set_boxed (value, &priv->pointing_to);
+ break;
- priv->visible = TRUE;
+ case PROP_POSITION:
+ g_value_set_enum (value, priv->position);
+ break;
- GTK_WIDGET_CLASS (gtk_popover_parent_class)->show (widget);
+ case PROP_MODAL:
+ g_value_set_boolean (value, priv->modal);
+ break;
- if (priv->modal)
- gtk_popover_apply_modality (GTK_POPOVER (widget), TRUE);
+ case NUM_PROPERTIES + GTK_ROOT_PROP_FOCUS_WIDGET:
+ g_value_set_object (value, priv->focus_widget);
+ break;
- priv->state = STATE_SHOWN;
+ case NUM_PROPERTIES + GTK_ROOT_PROP_DEFAULT_WIDGET:
+ g_value_set_object (value, priv->default_widget);
+ break;
- if (gtk_widget_get_realized (widget))
- gdk_surface_input_shape_combine_region (gtk_widget_get_surface (widget),
- NULL, 0, 0);
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
static void
-gtk_popover_hide (GtkWidget *widget)
+gtk_popover_activate_default (GtkPopover *popover)
{
- GtkPopoverPrivate *priv = gtk_popover_get_instance_private (GTK_POPOVER (widget));
-
- gtk_popover_hide_internal (GTK_POPOVER (widget));
+ gtk_root_activate_default (GTK_ROOT (popover));
+}
- 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);
+static void
+gtk_popover_activate_focus (GtkPopover *popover)
+{
+ gtk_root_activate_focus (GTK_ROOT (popover));
+}
+static void
+gtk_popover_close (GtkPopover *popover)
+{
+ gtk_widget_hide (GTK_WIDGET (popover));
+}
- GTK_WIDGET_CLASS (gtk_popover_parent_class)->hide (widget);
+static void
+add_tab_bindings (GtkBindingSet *binding_set,
+ GdkModifierType modifiers,
+ GtkDirectionType direction)
+{
+ 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);
}
static void
@@ -1533,10 +669,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)
@@ -1547,52 +682,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"),
@@ -1600,11 +724,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"),
@@ -1612,11 +731,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"),
@@ -1624,12 +738,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"),
@@ -1637,456 +745,575 @@ 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_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);
- 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_space, 0, "activate-focus", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0, "activate-focus", 0);
+
+ 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;
-
- new_window = GTK_WINDOW (gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW));
+ GtkWidget *old_focus = NULL;
+ GdkSeat *seat;
+ GdkDevice *device;
+ GdkEvent *event;
- 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)))
- {
- GtkWidget *grab_widget;
+ 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)
+ {
+ 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;
-
- popovers = g_object_get_qdata (G_OBJECT (widget), quark_widget_popovers);
+ GdkModifierType modifier = event->state;
+ guint keyval = event->keyval;
- 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;
- if (priv->parent_scrollable)
+ priv->foci = g_list_remove (priv->foci, focus);
+ gtk_pointer_focus_unref (focus);
+}
+
+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)
{
- g_signal_handlers_disconnect_by_data (priv->vadj, popover);
- g_object_unref (priv->vadj);
- priv->vadj = NULL;
+ gtk_pointer_focus_set_target (focus, target);
+ gtk_pointer_focus_set_coordinates (focus, x, y);
}
-
- if (priv->hadj)
+ else
{
- g_signal_handlers_disconnect_by_data (priv->hadj, popover);
- g_object_unref (priv->hadj);
- priv->hadj = NULL;
+ gtk_popover_remove_pointer_focus (popover, focus);
}
- g_object_unref (priv->parent_scrollable);
+ 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);
}
+}
- priv->parent_scrollable = scrollable;
+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;
- if (scrollable)
+ while (l)
{
- g_object_ref (scrollable);
- priv->vadj = gtk_scrollable_get_vadjustment (scrollable);
- priv->hadj = gtk_scrollable_get_hadjustment (scrollable);
+ GtkPointerFocus *focus = l->data;
- if (priv->vadj)
+ cur = l;
+ focus = cur->data;
+ l = cur->next;
+
+ gtk_pointer_focus_ref (focus);
+
+ 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 (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;
+ }
- return g_object_new (GTK_TYPE_POPOVER,
- "relative-to", relative_to,
- NULL);
+ update_cursor (focus->toplevel, focus->device, grab_widget, target);
+
+ if (device)
+ break;
+ }
+}
+
+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;
}
-/**
- * gtk_popover_set_relative_to:
- * @popover: a #GtkPopover
- * @relative_to: (allow-none): a #GtkWidget
- *
- * 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
- * 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.
- **/
void
-gtk_popover_set_relative_to (GtkPopover *popover,
- GtkWidget *relative_to)
+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_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);
}
-/**
- * gtk_popover_get_relative_to:
- * @popover: a #GtkPopover
- *
- * Returns the widget @popover is currently attached to
- *
- * Returns: (transfer none): a #GtkWidget
- **/
GtkWidget *
gtk_popover_get_relative_to (GtkPopover *popover)
{
@@ -2094,44 +1321,31 @@ gtk_popover_get_relative_to (GtkPopover *popover)
g_return_val_if_fail (GTK_IS_POPOVER (popover), NULL);
- return priv->widget;
+ return priv->relative_to;
}
-/**
- * gtk_popover_set_pointing_to:
- * @popover: a #GtkPopover
- * @rect: rectangle to point to
- *
- * Sets the rectangle that @popover will point to, in the
- * coordinate space of the widget @popover is attached to,
- * see gtk_popover_set_relative_to().
- **/
void
-gtk_popover_set_pointing_to (GtkPopover *popover,
- const GdkRectangle *rect)
+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]);
}
-/**
- * gtk_popover_get_pointing_to:
- * @popover: a #GtkPopover
- * @rect: (out): location to store the rectangle
- *
- * If a rectangle to point to has been set, this function will
- * return %TRUE and fill in @rect with such rectangle, otherwise
- * it will return %FALSE and fill in @rect with the attached
- * widget coordinates.
- *
- * Returns: %TRUE if a rectangle to point to was set.
- **/
gboolean
-gtk_popover_get_pointing_to (GtkPopover *popover,
- GdkRectangle *rect)
+gtk_popover_get_pointing_to (GtkPopover *popover,
+ GdkRectangle *rect)
{
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
@@ -2140,53 +1354,26 @@ 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;
}
-/**
- * gtk_popover_set_position:
- * @popover: a #GtkPopover
- * @position: preferred popover position
- *
- * Sets the preferred position for @popover to appear. If the @popover
- * is currently visible, it will be immediately updated.
- *
- * This preference will be respected where possible, although
- * on lack of space (eg. if close to the window edges), the
- * #GtkPopover may choose to appear on the opposite side
- **/
void
-gtk_popover_set_position (GtkPopover *popover,
- GtkPositionType position)
+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]);
}
-/**
- * gtk_popover_get_position:
- * @popover: a #GtkPopover
- *
- * Returns the preferred position of @popover.
- *
- * Returns: The preferred position.
- **/
GtkPositionType
gtk_popover_get_position (GtkPopover *popover)
{
@@ -2194,22 +1381,12 @@ 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;
}
-/**
- * gtk_popover_set_modal:
- * @popover: a #GtkPopover
- * @modal: #TRUE to make popover claim all input within the toplevel
- *
- * Sets whether @popover is modal, a modal popover will grab all input
- * within the toplevel and grab the keyboard focus on it when being
- * displayed. Clicking outside the popover area or pressing Esc will
- * dismiss the popover and ungrab input.
- **/
void
gtk_popover_set_modal (GtkPopover *popover,
- gboolean modal)
+ gboolean modal)
{
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
@@ -2222,21 +1399,9 @@ 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]);
}
-/**
- * gtk_popover_get_modal:
- * @popover: a #GtkPopover
- *
- * Returns whether the popover is modal, see gtk_popover_set_modal to
- * see the implications of this.
- *
- * Returns: #TRUE if @popover is modal
- **/
gboolean
gtk_popover_get_modal (GtkPopover *popover)
{
@@ -2247,6 +1412,31 @@ gtk_popover_get_modal (GtkPopover *popover)
return priv->modal;
}
+void
+gtk_popover_popup (GtkPopover *popover)
+{
+ g_return_if_fail (GTK_IS_POPOVER (popover));
+
+ gtk_widget_show (GTK_WIDGET (popover));
+}
+
+void
+gtk_popover_popdown (GtkPopover *popover)
+{
+ g_return_if_fail (GTK_IS_POPOVER (popover));
+
+ gtk_widget_hide (GTK_WIDGET (popover));
+}
+
+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)
{
@@ -2256,44 +1446,11 @@ back_to_main (GtkWidget *popover)
gtk_stack_set_visible_child_name (GTK_STACK (stack), "main");
}
-/**
- * gtk_popover_bind_model:
- * @popover: a #GtkPopover
- * @model: (allow-none): the #GMenuModel to bind to or %NULL to remove
- * binding
- * @action_namespace: (allow-none): the namespace for actions in @model
- *
- * Establishes a binding between a #GtkPopover and a #GMenuModel.
- *
- * The contents of @popover are removed and then refilled with menu items
- * according to @model. When @model changes, @popover is updated.
- * Calling this function twice on @popover with different @model will
- * cause the first binding to be replaced with a binding to the new
- * model. If @model is %NULL then any previous binding is undone and
- * all children are removed.
- *
- * If @action_namespace is non-%NULL then the effect is as if all
- * actions mentioned in the @model have their names prefixed with the
- * namespace, plus a dot. For example, if the action “quit” is
- * mentioned and @action_namespace is “app” then the effective action
- * name is “app.quit”.
- *
- * This function uses #GtkActionable to define the action name and
- * target values on the created menu items. If you want to use an
- * action group other than “app” and “win”, or if you want to use a
- * #GtkMenuShell outside of a #GtkApplicationWindow, then you will need
- * to attach your own action group to the widget hierarchy using
- * gtk_widget_insert_action_group(). As an example, if you created a
- * group with a “quit” action and inserted it with the name “mygroup”
- * then you would use the action name “mygroup.quit” in your
- * #GMenuModel.
- */
void
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;
@@ -2305,7 +1462,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)
{
@@ -2313,6 +1470,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),
@@ -2332,24 +1490,6 @@ gtk_popover_bind_model (GtkPopover *popover,
}
}
-/**
- * gtk_popover_new_from_model:
- * @relative_to: (allow-none): #GtkWidget the popover is related to
- * @model: a #GMenuModel
- *
- * Creates a #GtkPopover and populates it according to
- * @model. The popover is pointed to the @relative_to widget.
- *
- * The created buttons are connected to actions found in the
- * #GtkApplicationWindow to which the popover belongs - typically
- * by means of being attached to a widget that is contained within
- * the #GtkApplicationWindows widget hierarchy.
- *
- * Actions can also be added using gtk_widget_insert_action_group()
- * on the menus attach widget or on any of its parent widgets.
- *
- * Returns: the new #GtkPopover
- */
GtkWidget *
gtk_popover_new_from_model (GtkWidget *relative_to,
GMenuModel *model)
@@ -2365,155 +1505,10 @@ 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 b5e0d47a2e..7de98bb33a 100644
--- a/gtk/gtkpopovermenu.c
+++ b/gtk/gtkpopovermenu.c
@@ -142,8 +142,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 9f28e17081..54361d1e94 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -7465,10 +7465,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 ff5021b3ff..abc2e47c84 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -6631,8 +6631,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 9a763e22a5..6f571e34d8 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"
@@ -56,7 +57,6 @@
#include "gtksearchbar.h"
#include "gtksearchentry.h"
#include "gtkeventcontrollerkey.h"
-#include "gtkpopup.h"
enum
{
@@ -1145,7 +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_popup_get_popups ());
+ 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/gtk/meson.build b/gtk/meson.build
index 14b4829f3f..fd955607b7 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -296,7 +296,6 @@ gtk_public_sources = files([
'gtkpicture.c',
'gtkpopover.c',
'gtkpopovermenu.c',
- 'gtkpopup.c',
'gtkprintcontext.c',
'gtkprintoperation.c',
'gtkprintoperationpreview.c',
diff --git a/tests/meson.build b/tests/meson.build
index fe9e09d86b..db90777a43 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -118,7 +118,6 @@ gtk_tests = [
['testpopover'],
['gdkgears', ['gtkgears.c']],
['listmodel'],
- ['testpopup'],
['testpopupat'],
['testgaction'],
['testwidgetfocus'],
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]