[gtk+/wip/attachment-parameters: 1/24] gdkattachmentparameters: add GdkAttachmentParameters
- From: William Hua <williamhua src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/attachment-parameters: 1/24] gdkattachmentparameters: add GdkAttachmentParameters
- Date: Wed, 14 Oct 2015 16:33:41 +0000 (UTC)
commit 2b5691a4aae189f32d9b863960f38ed4d6b6b914
Author: William Hua <william hua canonical com>
Date: Fri Sep 18 13:40:36 2015 -0400
gdkattachmentparameters: add GdkAttachmentParameters
docs/reference/gdk/gdk-docs.sgml | 1 +
docs/reference/gdk/gdk3-sections.txt | 30 +
gdk/Makefile.am | 3 +
gdk/gdk.h | 1 +
gdk/gdkattachmentparameters.c | 1123 ++++++++++++++++++++++++++++++++++
gdk/gdkattachmentparameters.h | 210 +++++++
gdk/gdkattachmentparametersprivate.h | 79 +++
7 files changed, 1447 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/gdk/gdk-docs.sgml b/docs/reference/gdk/gdk-docs.sgml
index bdd7a7a..f55e956 100644
--- a/docs/reference/gdk/gdk-docs.sgml
+++ b/docs/reference/gdk/gdk-docs.sgml
@@ -46,6 +46,7 @@
<xi:include href="xml/wayland_interaction.xml" />
<xi:include href="xml/gdkapplaunchcontext.xml" />
<xi:include href="xml/gdktestutils.xml" />
+ <xi:include href="xml/gdkattachmentparameters.xml" />
</reference>
<reference>
diff --git a/docs/reference/gdk/gdk3-sections.txt b/docs/reference/gdk/gdk3-sections.txt
index 8309d1d..285242f 100644
--- a/docs/reference/gdk/gdk3-sections.txt
+++ b/docs/reference/gdk/gdk3-sections.txt
@@ -546,6 +546,36 @@ gdk_fullscreen_mode_get_type
</SECTION>
<SECTION>
+<TITLE>Attachment Parameters</TITLE>
+<FILE>gdkattachmentparameters</FILE>
+GdkAttachmentParameters
+GdkAttachmentOption
+GdkAttachmentBorder
+GdkAttachmentPositionCallback
+gdk_attachment_parameters_new
+gdk_attachment_parameters_copy
+gdk_attachment_parameters_free
+gdk_attachment_parameters_set_attachment_origin
+gdk_attachment_parameters_set_attachment_rectangle
+gdk_attachment_parameters_set_attachment_margin
+gdk_attachment_parameters_set_window_margin
+gdk_attachment_parameters_set_window_padding
+gdk_attachment_parameters_set_window_offset
+gdk_attachment_parameters_get_window_type_hint
+gdk_attachment_parameters_set_window_type_hint
+gdk_attachment_parameters_set_right_to_left
+gdk_attachment_parameters_add_primary_options
+gdk_attachment_parameters_add_secondary_options
+gdk_attachment_parameters_set_position_callback
+
+<SUBSECTION Private>
+_GdkAttachmentParameters
+gdk_attachment_parameters_choose_position
+gdk_attachment_parameters_choose_position_for_window
+gdk_window_move_using_attachment_parameters
+</SECTION>
+
+<SECTION>
<TITLE>Selections</TITLE>
<FILE>selections</FILE>
GDK_SELECTION_PRIMARY
diff --git a/gdk/Makefile.am b/gdk/Makefile.am
index dea10d1..c32404b 100644
--- a/gdk/Makefile.am
+++ b/gdk/Makefile.am
@@ -63,6 +63,7 @@ gdk_public_h_sources = \
gdk.h \
gdk-autocleanup.h \
gdkapplaunchcontext.h \
+ gdkattachmentparameters.h \
gdkcairo.h \
gdkcursor.h \
gdkdevice.h \
@@ -102,6 +103,7 @@ gdk_h_sources = \
gdk_private_headers = \
gdk-private.h \
gdkapplaunchcontextprivate.h \
+ gdkattachmentparametersprivate.h \
gdkcursorprivate.h \
gdkdevicemanagerprivate.h \
gdkdeviceprivate.h \
@@ -126,6 +128,7 @@ gdk_c_sources = \
gdk-private.c \
gdk.c \
gdkapplaunchcontext.c \
+ gdkattachmentparameters.c \
gdkcairo.c \
gdkcursor.c \
gdkdeprecated.c \
diff --git a/gdk/gdk.h b/gdk/gdk.h
index 65246d7..d88bfb9 100644
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -30,6 +30,7 @@
#include <gdk/gdkconfig.h>
#include <gdk/gdkversionmacros.h>
#include <gdk/gdkapplaunchcontext.h>
+#include <gdk/gdkattachmentparameters.h>
#include <gdk/gdkcairo.h>
#include <gdk/gdkcursor.h>
#include <gdk/gdkdevice.h>
diff --git a/gdk/gdkattachmentparameters.c b/gdk/gdkattachmentparameters.c
new file mode 100644
index 0000000..05dab7d
--- /dev/null
+++ b/gdk/gdkattachmentparameters.c
@@ -0,0 +1,1123 @@
+#include "config.h"
+
+#include "gdkattachmentparameters.h"
+#include "gdkattachmentparametersprivate.h"
+#include "gdkscreen.h"
+#include "gdkwindow.h"
+
+/**
+ * SECTION: gdkattachmentparameters
+ * @section_id: gdkattachmentparameters
+ * @title: Attachment Parameters
+ * @short_description: Describing relative window position
+ * @stability: Unstable
+ * @include: gdk/gdkattachmentparameters.h
+ *
+ * A full description of how a window should be positioned relative to an
+ * attachment rectangle.
+ *
+ * Since: 3.20
+ */
+
+/**
+ * gdk_attachment_parameters_new:
+ *
+ * Creates a new #GdkAttachmentParameters for describing the position of a
+ * #GdkWindow relative to an attachment #GdkRectangle.
+ *
+ * Returns: (transfer full): a new #GdkAttachmentParameters, to be freed with
+ * gdk_attachment_parameters_free()
+ *
+ * Since: 3.20
+ */
+GdkAttachmentParameters *
+gdk_attachment_parameters_new (void)
+{
+ return g_new0 (GdkAttachmentParameters, 1);
+}
+
+/**
+ * gdk_attachment_parameters_copy:
+ * @src: (transfer none) (nullable): the parameters to copy
+ * @data: (transfer none) (nullable): unused
+ *
+ * Creates a deep copy of @src.
+ *
+ * Returns: (transfer full) (nullable): a deep copy of @src, to be freed with
+ * gdk_attachment_parameters_free()
+ *
+ * Since: 3.20
+ */
+gpointer
+gdk_attachment_parameters_copy (gconstpointer src,
+ gpointer data)
+{
+ GdkAttachmentParameters *copy;
+ const GdkAttachmentParameters *parameters;
+
+ if (!src)
+ return NULL;
+
+ parameters = src;
+
+ copy = g_memdup (parameters, sizeof (*parameters));
+
+ copy->primary_options = g_list_copy (parameters->primary_options);
+ copy->secondary_options = g_list_copy (parameters->secondary_options);
+
+ return copy;
+}
+
+/**
+ * gdk_attachment_parameters_free:
+ * @data: (transfer full) (nullable): the parameters to free
+ *
+ * Releases @data.
+ *
+ * Since: 3.20
+ */
+void
+gdk_attachment_parameters_free (gpointer data)
+{
+ GdkAttachmentParameters *parameters;
+
+ if (!data)
+ return;
+
+ parameters = data;
+
+ if (parameters->position_callback_user_data && parameters->position_callback_destroy_notify)
+ parameters->position_callback_destroy_notify (parameters->position_callback_user_data);
+
+ g_list_free (parameters->secondary_options);
+ g_list_free (parameters->primary_options);
+
+ g_free (parameters);
+}
+
+/**
+ * gdk_attachment_parameters_set_attachment_origin:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ * @origin: (transfer none) (nullable): the attachment rectangle's origin
+ *
+ * Sets the origin of the attachment rectangle's coordinate system in root
+ * coordinates.
+ *
+ * Since: 3.20
+ */
+void
+gdk_attachment_parameters_set_attachment_origin (GdkAttachmentParameters *parameters,
+ const GdkPoint *origin)
+{
+ GdkPoint zero = { 0 };
+
+ g_return_if_fail (parameters);
+
+ parameters->attachment_origin = origin ? *origin : zero;
+}
+
+/**
+ * gdk_attachment_parameters_set_attachment_rectangle:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ * @rectangle: (transfer none) (nullable): the attachment rectangle
+ *
+ * Sets the attachment rectangle the window needs to be aligned relative to.
+ *
+ * Since: 3.20
+ */
+void
+gdk_attachment_parameters_set_attachment_rectangle (GdkAttachmentParameters *parameters,
+ const GdkRectangle *rectangle)
+{
+ g_return_if_fail (parameters);
+
+ if (rectangle)
+ {
+ parameters->has_attachment_rectangle = TRUE;
+ parameters->attachment_rectangle = *rectangle;
+ }
+ else
+ parameters->has_attachment_rectangle = FALSE;
+}
+
+/**
+ * gdk_attachment_parameters_set_attachment_margin:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ * @margin: (transfer none) (nullable): the space around the attachment rectangle
+ *
+ * Sets the amount of space to leave around the attachment rectangle.
+ *
+ * Since: 3.20
+ */
+void
+gdk_attachment_parameters_set_attachment_margin (GdkAttachmentParameters *parameters,
+ const GdkAttachmentBorder *margin)
+{
+ GdkAttachmentBorder zero = { 0 };
+
+ g_return_if_fail (parameters);
+
+ parameters->attachment_margin = margin ? *margin : zero;
+}
+
+/**
+ * gdk_attachment_parameters_set_window_margin:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ * @margin: (transfer none) (nullable): the space around the window
+ *
+ * Sets the amount of space to leave around the window.
+ *
+ * Since: 3.20
+ */
+void
+gdk_attachment_parameters_set_window_margin (GdkAttachmentParameters *parameters,
+ const GdkAttachmentBorder *margin)
+{
+ GdkAttachmentBorder zero = { 0 };
+
+ g_return_if_fail (parameters);
+
+ parameters->window_margin = margin ? *margin : zero;
+}
+
+/**
+ * gdk_attachment_parameters_set_window_padding:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ * @padding: (transfer none) (nullable): the space between the window and its
+ * contents.
+ *
+ * Sets the amount of space between the window and its contents.
+ *
+ * Since: 3.20
+ */
+void
+gdk_attachment_parameters_set_window_padding (GdkAttachmentParameters *parameters,
+ const GdkAttachmentBorder *padding)
+{
+ GdkAttachmentBorder zero = { 0 };
+
+ g_return_if_fail (parameters);
+
+ parameters->window_padding = padding ? *padding : zero;
+}
+
+/**
+ * gdk_attachment_parameters_set_window_offset:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ * @offset: (transfer none) (nullable): the window displacement
+ *
+ * Sets the offset to displace the window by.
+ *
+ * Since: 3.20
+ */
+void
+gdk_attachment_parameters_set_window_offset (GdkAttachmentParameters *parameters,
+ const GdkPoint *offset)
+{
+ GdkPoint zero = { 0 };
+
+ g_return_if_fail (parameters);
+
+ parameters->window_offset = offset ? *offset : zero;
+}
+
+/**
+ * gdk_attachment_parameters_get_window_type_hint:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ *
+ * Gets the window type hint set on @parameters.
+ *
+ * Returns: the window type hint set on @parameters
+ *
+ * Since: 3.20
+ */
+GdkWindowTypeHint
+gdk_attachment_parameters_get_window_type_hint (GdkAttachmentParameters *parameters)
+{
+ g_return_val_if_fail (parameters, GDK_WINDOW_TYPE_HINT_NORMAL);
+
+ return parameters->window_type_hint;
+}
+
+/**
+ * gdk_attachment_parameters_set_window_type_hint:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ * @window_type_hint: the window type hint
+ *
+ * Sets the window type hint.
+ *
+ * Since: 3.20
+ */
+void
+gdk_attachment_parameters_set_window_type_hint (GdkAttachmentParameters *parameters,
+ GdkWindowTypeHint window_type_hint)
+{
+ g_return_if_fail (parameters);
+
+ parameters->window_type_hint = window_type_hint;
+}
+
+/**
+ * gdk_attachment_parameters_set_right_to_left:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ * @is_right_to_left: %TRUE if the text direction is right to left
+ *
+ * Sets the window text direction.
+ *
+ * Since: 3.20
+ */
+void
+gdk_attachment_parameters_set_right_to_left (GdkAttachmentParameters *parameters,
+ gboolean is_right_to_left)
+{
+ g_return_if_fail (parameters);
+
+ parameters->is_right_to_left = is_right_to_left;
+}
+
+static void
+add_options (GList **list,
+ GdkAttachmentOption first_option,
+ va_list args)
+{
+ GdkAttachmentOption option;
+
+ for (option = first_option; option; option = va_arg (args, GdkAttachmentOption))
+ *list = g_list_append (*list, GINT_TO_POINTER (option));
+}
+
+/**
+ * gdk_attachment_parameters_add_primary_options:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ * @first_option: first primary option
+ * @...: a %NULL-terminated list of options
+ *
+ * Appends to the list of primary positioning options to try.
+ *
+ * A typical backend will try each primary option in the order they're added.
+ * If an option can be satisfied, it will then try each secondary option until
+ * it finds a satisfiable secondary option that doesn't conflict with the
+ * primary option. If it finds a pair of satisfiable non-conflicting options,
+ * then it will place the window there. If it cannot find a pair, it proceeds
+ * to the next primary option and tries again.
+ *
+ * If %GDK_ATTACHMENT_FORCE_FIRST_OPTION or %GDK_ATTACHMENT_FORCE_LAST_OPTION
+ * is encountered, the backend will probably retry the first or most recent
+ * option respectively, ignoring its satisfiability and forcing the window
+ * on-screen.
+ *
+ * Since: 3.20
+ */
+void
+gdk_attachment_parameters_add_primary_options (GdkAttachmentParameters *parameters,
+ GdkAttachmentOption first_option,
+ ...)
+{
+ va_list args;
+
+ g_return_if_fail (parameters);
+
+ va_start (args, first_option);
+
+ add_options (¶meters->primary_options, first_option, args);
+
+ va_end (args);
+}
+
+/**
+ * gdk_attachment_parameters_add_secondary_options:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ * @first_option: first secondary option
+ * @...: a %NULL-terminated list of options
+ *
+ * Appends to the list of secondary positioning options to try.
+ *
+ * A typical backend will try each primary option in the order they're added.
+ * If an option can be satisfied, it will then try each secondary option until
+ * it finds a satisfiable secondary option that doesn't conflict with the
+ * primary option. If it finds a pair of satisfiable non-conflicting options,
+ * then it will place the window there. If it cannot find a pair, it proceeds
+ * to the next primary option and tries again.
+ *
+ * If %GDK_ATTACHMENT_FORCE_FIRST_OPTION or %GDK_ATTACHMENT_FORCE_LAST_OPTION
+ * is encountered, the backend will probably retry the first or most recent
+ * option respectively, ignoring its satisfiability and forcing the window
+ * on-screen. If %GDK_ATTACHMENT_FORCE_FIRST_OPTION_IF_PRIMARY_FORCED or
+ * %GDK_ATTACHMENT_FORCE_LAST_OPTION_IF_PRIMARY_FORCED is encountered, the
+ * backend will probably retry it as above, but only if the current primary
+ * option is being forced. These last two flags exist for defining fallback
+ * positioning behaviour.
+ *
+ * Since: 3.20
+ */
+void
+gdk_attachment_parameters_add_secondary_options (GdkAttachmentParameters *parameters,
+ GdkAttachmentOption first_option,
+ ...)
+{
+ va_list args;
+
+ g_return_if_fail (parameters);
+
+ va_start (args, first_option);
+
+ add_options (¶meters->secondary_options, first_option, args);
+
+ va_end (args);
+}
+
+/**
+ * gdk_attachment_parameters_set_position_callback:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ * @callback: (nullable): a function to be called when the final position of
+ * the window is known
+ * @user_data: (transfer full) (nullable): additional data to pass to @callback
+ * @destroy_notify: (nullable): a function to release @user_data
+ *
+ * Sets the function to be called when the final position of the window is
+ * known. Since the position might be determined asynchronously, don't assume
+ * it will be called directly from gdk_window_set_attachment_parameters().
+ *
+ * Since: 3.20
+ */
+void
+gdk_attachment_parameters_set_position_callback (GdkAttachmentParameters *parameters,
+ GdkAttachmentPositionCallback callback,
+ gpointer user_data,
+ GDestroyNotify destroy_notify)
+{
+ g_return_if_fail (parameters);
+
+ parameters->position_callback = callback;
+
+ if (user_data != parameters->position_callback_user_data)
+ {
+ if (parameters->position_callback_user_data && parameters->position_callback_destroy_notify)
+ parameters->position_callback_destroy_notify (parameters->position_callback_user_data);
+
+ parameters->position_callback_user_data = user_data;
+ parameters->position_callback_destroy_notify = destroy_notify;
+ }
+ else if (user_data)
+ g_warning ("%s (): parameters already owns user data", G_STRFUNC);
+}
+
+static gint
+get_axis (GdkAttachmentOption option)
+{
+ switch (option)
+ {
+ case GDK_ATTACHMENT_ATTACH_LEFT_EDGE:
+ case GDK_ATTACHMENT_ATTACH_RIGHT_EDGE:
+ case GDK_ATTACHMENT_ATTACH_FORWARD_EDGE:
+ case GDK_ATTACHMENT_ATTACH_BACKWARD_EDGE:
+ case GDK_ATTACHMENT_ALIGN_LEFT_EDGES:
+ case GDK_ATTACHMENT_ALIGN_RIGHT_EDGES:
+ case GDK_ATTACHMENT_ALIGN_FORWARD_EDGES:
+ case GDK_ATTACHMENT_ALIGN_BACKWARD_EDGES:
+ case GDK_ATTACHMENT_CENTER_HORIZONTALLY:
+ case GDK_ATTACHMENT_CENTER_ON_LEFT_EDGE:
+ case GDK_ATTACHMENT_CENTER_ON_RIGHT_EDGE:
+ case GDK_ATTACHMENT_CENTER_ON_FORWARD_EDGE:
+ case GDK_ATTACHMENT_CENTER_ON_BACKWARD_EDGE:
+ case GDK_ATTACHMENT_ATTACH_LEFT_OF_CENTER:
+ case GDK_ATTACHMENT_ATTACH_RIGHT_OF_CENTER:
+ case GDK_ATTACHMENT_ATTACH_FORWARD_OF_CENTER:
+ case GDK_ATTACHMENT_ATTACH_BACKWARD_OF_CENTER:
+ return 0;
+
+ case GDK_ATTACHMENT_ATTACH_TOP_EDGE:
+ case GDK_ATTACHMENT_ATTACH_BOTTOM_EDGE:
+ case GDK_ATTACHMENT_ALIGN_TOP_EDGES:
+ case GDK_ATTACHMENT_ALIGN_BOTTOM_EDGES:
+ case GDK_ATTACHMENT_CENTER_VERTICALLY:
+ case GDK_ATTACHMENT_CENTER_ON_TOP_EDGE:
+ case GDK_ATTACHMENT_CENTER_ON_BOTTOM_EDGE:
+ case GDK_ATTACHMENT_ATTACH_ABOVE_CENTER:
+ case GDK_ATTACHMENT_ATTACH_BELOW_CENTER:
+ return 1;
+
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+static GdkAttachmentOption
+get_base_option (GdkAttachmentOption option,
+ gboolean is_right_to_left)
+{
+ switch (option)
+ {
+ case GDK_ATTACHMENT_ATTACH_FORWARD_EDGE:
+ return is_right_to_left ? GDK_ATTACHMENT_ATTACH_LEFT_EDGE : GDK_ATTACHMENT_ATTACH_RIGHT_EDGE;
+
+ case GDK_ATTACHMENT_ATTACH_BACKWARD_EDGE:
+ return is_right_to_left ? GDK_ATTACHMENT_ATTACH_RIGHT_EDGE : GDK_ATTACHMENT_ATTACH_LEFT_EDGE;
+
+ case GDK_ATTACHMENT_ALIGN_FORWARD_EDGES:
+ return is_right_to_left ? GDK_ATTACHMENT_ALIGN_LEFT_EDGES : GDK_ATTACHMENT_ALIGN_RIGHT_EDGES;
+
+ case GDK_ATTACHMENT_ALIGN_BACKWARD_EDGES:
+ return is_right_to_left ? GDK_ATTACHMENT_ALIGN_RIGHT_EDGES : GDK_ATTACHMENT_ALIGN_LEFT_EDGES;
+
+ case GDK_ATTACHMENT_CENTER_ON_FORWARD_EDGE:
+ return is_right_to_left ? GDK_ATTACHMENT_CENTER_ON_LEFT_EDGE : GDK_ATTACHMENT_CENTER_ON_RIGHT_EDGE;
+
+ case GDK_ATTACHMENT_CENTER_ON_BACKWARD_EDGE:
+ return is_right_to_left ? GDK_ATTACHMENT_CENTER_ON_RIGHT_EDGE : GDK_ATTACHMENT_CENTER_ON_LEFT_EDGE;
+
+ case GDK_ATTACHMENT_ATTACH_FORWARD_OF_CENTER:
+ return is_right_to_left ? GDK_ATTACHMENT_ATTACH_LEFT_OF_CENTER : GDK_ATTACHMENT_ATTACH_RIGHT_OF_CENTER;
+
+ case GDK_ATTACHMENT_ATTACH_BACKWARD_OF_CENTER:
+ return is_right_to_left ? GDK_ATTACHMENT_ATTACH_RIGHT_OF_CENTER : GDK_ATTACHMENT_ATTACH_LEFT_OF_CENTER;
+
+ default:
+ break;
+ }
+
+ return option;
+}
+
+static gboolean
+is_satisfiable (const GdkAttachmentParameters *parameters,
+ GdkAttachmentOption option,
+ gint width,
+ gint height,
+ const GdkRectangle *bounds,
+ gint *axis,
+ gint *value)
+{
+ gint a;
+ gint v;
+
+ g_return_val_if_fail (parameters, FALSE);
+ g_return_val_if_fail (parameters->has_attachment_rectangle, FALSE);
+
+ if (!parameters || !parameters->has_attachment_rectangle)
+ return FALSE;
+
+ if (!axis)
+ axis = &a;
+
+ if (!value)
+ value = &v;
+
+ switch (get_base_option (option, parameters->is_right_to_left))
+ {
+ case GDK_ATTACHMENT_END_OPTIONS:
+ g_warning ("%s (): unexpected GDK_ATTACHMENT_END_OPTIONS", G_STRFUNC);
+ return FALSE;
+
+ case GDK_ATTACHMENT_FORCE_FIRST_OPTION:
+ g_warning ("%s (): unexpected GDK_ATTACHMENT_FORCE_FIRST_OPTION", G_STRFUNC);
+ return FALSE;
+
+ case GDK_ATTACHMENT_FORCE_FIRST_OPTION_IF_PRIMARY_FORCED:
+ g_warning ("%s (): unexpected GDK_ATTACHMENT_FORCE_FIRST_OPTION_IF_PRIMARY_FORCED", G_STRFUNC);
+ return FALSE;
+
+ case GDK_ATTACHMENT_FORCE_LAST_OPTION:
+ g_warning ("%s (): unexpected GDK_ATTACHMENT_FORCE_LAST_OPTION", G_STRFUNC);
+ return FALSE;
+
+ case GDK_ATTACHMENT_FORCE_LAST_OPTION_IF_PRIMARY_FORCED:
+ g_warning ("%s (): unexpected GDK_ATTACHMENT_FORCE_LAST_OPTION_IF_PRIMARY_FORCED", G_STRFUNC);
+ return FALSE;
+
+ case GDK_ATTACHMENT_ATTACH_TOP_EDGE:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ - parameters->attachment_margin.top
+ - height
+ - parameters->window_margin.bottom
+ + parameters->window_padding.bottom
+ + parameters->window_offset.y;
+ break;
+
+ case GDK_ATTACHMENT_ATTACH_LEFT_EDGE:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ - parameters->attachment_margin.left
+ - width
+ - parameters->window_margin.right
+ + parameters->window_padding.right
+ + parameters->window_offset.x;
+ break;
+
+ case GDK_ATTACHMENT_ATTACH_RIGHT_EDGE:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ + parameters->attachment_rectangle.width
+ + parameters->attachment_margin.right
+ + parameters->window_margin.left
+ - parameters->window_padding.left
+ + parameters->window_offset.x;
+ break;
+
+ case GDK_ATTACHMENT_ATTACH_BOTTOM_EDGE:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ + parameters->attachment_rectangle.height
+ + parameters->attachment_margin.bottom
+ + parameters->window_margin.top
+ - parameters->window_padding.top
+ + parameters->window_offset.y;
+ break;
+
+ case GDK_ATTACHMENT_ALIGN_TOP_EDGES:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ - parameters->window_padding.top
+ + parameters->window_offset.y;
+ break;
+
+ case GDK_ATTACHMENT_ALIGN_LEFT_EDGES:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ - parameters->window_padding.left
+ + parameters->window_offset.x;
+ break;
+
+ case GDK_ATTACHMENT_ALIGN_RIGHT_EDGES:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ + parameters->attachment_rectangle.width
+ - width
+ + parameters->window_padding.right
+ + parameters->window_offset.x;
+ break;
+
+ case GDK_ATTACHMENT_ALIGN_BOTTOM_EDGES:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ + parameters->attachment_rectangle.height
+ - height
+ + parameters->window_padding.bottom
+ + parameters->window_offset.y;
+ break;
+
+ case GDK_ATTACHMENT_CENTER_HORIZONTALLY:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ + parameters->attachment_rectangle.width / 2
+ - (width - parameters->window_padding.left - parameters->window_padding.right) / 2
+ - parameters->window_padding.left
+ + parameters->window_offset.x;
+ break;
+
+ case GDK_ATTACHMENT_CENTER_VERTICALLY:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ + parameters->attachment_rectangle.height / 2
+ - (height - parameters->window_padding.top - parameters->window_padding.bottom) / 2
+ - parameters->window_padding.top
+ + parameters->window_offset.y;
+ break;
+
+ case GDK_ATTACHMENT_CENTER_ON_TOP_EDGE:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ - (height - parameters->window_padding.top - parameters->window_padding.bottom) / 2
+ - parameters->window_padding.top
+ + parameters->window_offset.y;
+ break;
+
+ case GDK_ATTACHMENT_CENTER_ON_LEFT_EDGE:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ - (width - parameters->window_padding.left - parameters->window_padding.right) / 2
+ - parameters->window_padding.left
+ + parameters->window_offset.x;
+ break;
+
+ case GDK_ATTACHMENT_CENTER_ON_RIGHT_EDGE:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ + parameters->attachment_rectangle.width
+ - (width - parameters->window_padding.left - parameters->window_padding.right) / 2
+ - parameters->window_padding.left
+ + parameters->window_offset.x;
+ break;
+
+ case GDK_ATTACHMENT_CENTER_ON_BOTTOM_EDGE:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ + parameters->attachment_rectangle.height
+ - (height - parameters->window_padding.top - parameters->window_padding.bottom) / 2
+ - parameters->window_padding.top
+ + parameters->window_offset.y;
+ break;
+
+ case GDK_ATTACHMENT_ATTACH_ABOVE_CENTER:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ + parameters->attachment_rectangle.height / 2
+ - height
+ + parameters->window_padding.bottom
+ + parameters->window_offset.y;
+ break;
+
+ case GDK_ATTACHMENT_ATTACH_BELOW_CENTER:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ + parameters->attachment_rectangle.height / 2
+ - parameters->window_padding.top
+ + parameters->window_offset.y;
+ break;
+
+ case GDK_ATTACHMENT_ATTACH_LEFT_OF_CENTER:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ + parameters->attachment_rectangle.width / 2
+ - width
+ + parameters->window_padding.right
+ + parameters->window_offset.x;
+ break;
+
+ case GDK_ATTACHMENT_ATTACH_RIGHT_OF_CENTER:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ + parameters->attachment_rectangle.width / 2
+ - parameters->window_padding.left
+ + parameters->window_offset.x;
+ break;
+
+ default:
+ g_warning ("%s (): unknown option", G_STRFUNC);
+ return FALSE;
+ }
+
+ return !bounds || (*axis == 0 && bounds->x <= *value && *value + width <= bounds->x + bounds->width)
+ || (*axis == 1 && bounds->y <= *value && *value + height <= bounds->y + bounds->height);
+}
+
+/**
+ * gdk_attachment_parameters_choose_position:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ * @width: window width
+ * @height: window height
+ * @bounds: (transfer none) (nullable): monitor geometry
+ * @position: (out) (optional): the best position for the window
+ * @offset: (out) (optional): the displacement needed to push the window
+ * on-screen
+ * @primary_option: (out) (optional): the best primary option
+ * @secondary_option: (out) (optional): the best secondary option
+ *
+ * Finds the best position for a window of size @width and @height on a screen
+ * with @bounds using the given @parameters.
+ *
+ * Returns: %TRUE if there is a pair of satisfiable primary and secondary
+ * options that do not conflict with each other
+ *
+ * Since: 3.20
+ */
+gboolean
+gdk_attachment_parameters_choose_position (const GdkAttachmentParameters *parameters,
+ gint width,
+ gint height,
+ const GdkRectangle *bounds,
+ GdkPoint *position,
+ GdkPoint *offset,
+ GdkAttachmentOption *primary_option,
+ GdkAttachmentOption *secondary_option)
+{
+ GdkPoint p;
+ GdkPoint o;
+ GdkAttachmentOption po;
+ GdkAttachmentOption so;
+ GList *i;
+ GList *j;
+ GList *k;
+ gint axis;
+ gboolean satisfiable;
+ GdkAttachmentOption first_satisfiable_primary_option[2];
+ GdkAttachmentOption last_satisfiable_primary_option[2];
+ GdkAttachmentOption first_satisfiable_secondary_option[2];
+ GdkAttachmentOption last_satisfiable_secondary_option[2];
+ gint primary_axis;
+ gint secondary_axis;
+ gboolean primary_force;
+ gboolean secondary_force;
+ gint primary_value;
+ gint secondary_value;
+
+ g_return_val_if_fail (parameters, FALSE);
+ g_return_val_if_fail (parameters->has_attachment_rectangle, FALSE);
+
+ if (!position)
+ position = &p;
+
+ if (!offset)
+ offset = &o;
+
+ if (!primary_option)
+ primary_option = &po;
+
+ if (!secondary_option)
+ secondary_option = &so;
+
+ first_satisfiable_primary_option[0] = GDK_ATTACHMENT_END_OPTIONS;
+ first_satisfiable_primary_option[1] = GDK_ATTACHMENT_END_OPTIONS;
+ last_satisfiable_primary_option[0] = GDK_ATTACHMENT_END_OPTIONS;
+ last_satisfiable_primary_option[1] = GDK_ATTACHMENT_END_OPTIONS;
+
+ for (i = parameters->primary_options; i; i = i->next)
+ {
+ *primary_option = GPOINTER_TO_INT (i->data);
+ primary_force = FALSE;
+
+ if (*primary_option == GDK_ATTACHMENT_END_OPTIONS)
+ {
+ g_warning ("%s (): unexpected GDK_ATTACHMENT_END_OPTIONS", G_STRFUNC);
+ i = NULL;
+ break;
+ }
+ else if (*primary_option == GDK_ATTACHMENT_FORCE_FIRST_OPTION ||
+ *primary_option == GDK_ATTACHMENT_FORCE_FIRST_OPTION_IF_PRIMARY_FORCED)
+ {
+ g_warn_if_fail (*primary_option != GDK_ATTACHMENT_FORCE_FIRST_OPTION_IF_PRIMARY_FORCED);
+
+ if (first_satisfiable_primary_option[0] == GDK_ATTACHMENT_END_OPTIONS)
+ *primary_option = GPOINTER_TO_INT (parameters->primary_options->data);
+ else
+ *primary_option = first_satisfiable_primary_option[0];
+
+ primary_force = TRUE;
+ }
+ else if (*primary_option == GDK_ATTACHMENT_FORCE_LAST_OPTION ||
+ *primary_option == GDK_ATTACHMENT_FORCE_LAST_OPTION_IF_PRIMARY_FORCED)
+ {
+ g_warn_if_fail (*primary_option != GDK_ATTACHMENT_FORCE_LAST_OPTION_IF_PRIMARY_FORCED);
+
+ if (last_satisfiable_primary_option[0] == GDK_ATTACHMENT_END_OPTIONS)
+ {
+ if (!i->prev)
+ {
+ g_warning ("%s (): started with GDK_ATTACHMENT_FORCE_LAST_OPTION", G_STRFUNC);
+ continue;
+ }
+
+ *primary_option = GPOINTER_TO_INT (i->prev->data);
+ }
+ else
+ *primary_option = last_satisfiable_primary_option[0];
+
+ primary_force = TRUE;
+ }
+
+ satisfiable = is_satisfiable (parameters,
+ *primary_option,
+ width,
+ height,
+ bounds,
+ &primary_axis,
+ &primary_value);
+
+ if (satisfiable && primary_axis >= 0)
+ {
+ if (first_satisfiable_primary_option[0] == GDK_ATTACHMENT_END_OPTIONS)
+ first_satisfiable_primary_option[0] = *primary_option;
+ else if (first_satisfiable_primary_option[1] == GDK_ATTACHMENT_END_OPTIONS &&
+ primary_axis != get_axis (first_satisfiable_primary_option[0]))
+ first_satisfiable_primary_option[1] = *primary_option;
+
+ if (last_satisfiable_primary_option[0] != GDK_ATTACHMENT_END_OPTIONS &&
+ primary_axis != last_satisfiable_primary_option[0])
+ last_satisfiable_primary_option[1] = last_satisfiable_primary_option[0];
+
+ last_satisfiable_primary_option[0] = *primary_option;
+ }
+
+ if (satisfiable || primary_force)
+ {
+ first_satisfiable_secondary_option[0] = GDK_ATTACHMENT_END_OPTIONS;
+ first_satisfiable_secondary_option[1] = GDK_ATTACHMENT_END_OPTIONS;
+ last_satisfiable_secondary_option[0] = GDK_ATTACHMENT_END_OPTIONS;
+ last_satisfiable_secondary_option[1] = GDK_ATTACHMENT_END_OPTIONS;
+
+ for (j = parameters->secondary_options; j; j = j->next)
+ {
+ *secondary_option = GPOINTER_TO_INT (j->data);
+ secondary_force = FALSE;
+ secondary_axis = get_axis (*secondary_option);
+
+ if (secondary_axis >= 0 && secondary_axis == primary_axis)
+ continue;
+
+ if (*secondary_option == GDK_ATTACHMENT_END_OPTIONS)
+ {
+ g_warning ("%s (): unexpected GDK_ATTACHMENT_END_OPTIONS", G_STRFUNC);
+ j = NULL;
+ break;
+ }
+ else if (*secondary_option == GDK_ATTACHMENT_FORCE_FIRST_OPTION ||
+ *secondary_option == GDK_ATTACHMENT_FORCE_FIRST_OPTION_IF_PRIMARY_FORCED)
+ {
+ if (*secondary_option == GDK_ATTACHMENT_FORCE_FIRST_OPTION_IF_PRIMARY_FORCED &&
!primary_force)
+ continue;
+
+ axis = primary_axis == 0 ? 1 : (primary_axis == 1 ? 0 : -1);
+
+ if (axis >= 0 && get_axis (first_satisfiable_secondary_option[0]) == axis)
+ *secondary_option = first_satisfiable_secondary_option[0];
+ else if (axis >= 0 && get_axis (first_satisfiable_secondary_option[1]) == axis)
+ *secondary_option = first_satisfiable_secondary_option[1];
+ else
+ {
+ for (k = parameters->secondary_options; k; k = k->next)
+ {
+ *secondary_option = GPOINTER_TO_INT (k->data);
+ secondary_axis = get_axis (*secondary_option);
+
+ if (secondary_axis >= 0 && secondary_axis != primary_axis)
+ break;
+ }
+
+ if (!k)
+ continue;
+ }
+
+ secondary_force = TRUE;
+ }
+ else if (*secondary_option == GDK_ATTACHMENT_FORCE_LAST_OPTION ||
+ *secondary_option == GDK_ATTACHMENT_FORCE_LAST_OPTION_IF_PRIMARY_FORCED)
+ {
+ if (*secondary_option == GDK_ATTACHMENT_FORCE_LAST_OPTION_IF_PRIMARY_FORCED &&
!primary_force)
+ continue;
+
+ axis = primary_axis == 0 ? 1 : (primary_axis == 1 ? 0 : -1);
+
+ if (axis >= 0 && get_axis (last_satisfiable_secondary_option[0]) == axis)
+ *secondary_option = last_satisfiable_secondary_option[0];
+ else if (axis >= 0 && get_axis (last_satisfiable_secondary_option[1]) == axis)
+ *secondary_option = last_satisfiable_secondary_option[1];
+ else
+ {
+ if (!j->prev)
+ {
+ if (*secondary_option == GDK_ATTACHMENT_FORCE_LAST_OPTION)
+ g_warning ("%s (): started with GDK_ATTACHMENT_FORCE_LAST_OPTION", G_STRFUNC);
+ else if (*secondary_option == GDK_ATTACHMENT_FORCE_LAST_OPTION_IF_PRIMARY_FORCED)
+ g_warning ("%s (): started with
GDK_ATTACHMENT_FORCE_LAST_OPTION_IF_PRIMARY_FORCED", G_STRFUNC);
+
+ continue;
+ }
+
+ for (k = j->prev; k; k = k->prev)
+ {
+ *secondary_option = GPOINTER_TO_INT (k->data);
+ secondary_axis = get_axis (*secondary_option);
+
+ if (secondary_axis >= 0 && secondary_axis != primary_axis)
+ break;
+ }
+
+ if (!k)
+ continue;
+ }
+
+ secondary_force = TRUE;
+ }
+
+ satisfiable = is_satisfiable (parameters,
+ *secondary_option,
+ width,
+ height,
+ bounds,
+ &secondary_axis,
+ &secondary_value);
+
+ if (satisfiable && secondary_axis >= 0)
+ {
+ if (first_satisfiable_secondary_option[0] == GDK_ATTACHMENT_END_OPTIONS)
+ first_satisfiable_secondary_option[0] = *secondary_option;
+ else if (first_satisfiable_secondary_option[1] == GDK_ATTACHMENT_END_OPTIONS &&
+ secondary_axis != get_axis (first_satisfiable_secondary_option[0]))
+ first_satisfiable_secondary_option[1] = *secondary_option;
+
+ if (last_satisfiable_secondary_option[0] != GDK_ATTACHMENT_END_OPTIONS &&
+ secondary_axis != last_satisfiable_secondary_option[0])
+ last_satisfiable_secondary_option[1] = last_satisfiable_secondary_option[0];
+
+ last_satisfiable_secondary_option[0] = *secondary_option;
+ }
+
+ if (satisfiable || secondary_force)
+ {
+ if (primary_axis == 0)
+ {
+ position->x = primary_value;
+ position->y = secondary_value;
+ }
+ else
+ {
+ position->x = secondary_value;
+ position->y = primary_value;
+ }
+
+ break;
+ }
+ }
+
+ if (j)
+ break;
+ }
+ }
+
+ if (i)
+ {
+ offset->x = 0;
+ offset->y = 0;
+
+ if (bounds)
+ {
+ if (position->x + width - parameters->window_padding.right > bounds->x + bounds->width)
+ {
+ offset->x += bounds->x + bounds->width - width + parameters->window_padding.right -
position->x;
+ position->x = bounds->x + bounds->width - width + parameters->window_padding.right;
+ }
+
+ if (position->x + parameters->window_padding.left < bounds->x)
+ {
+ offset->x += bounds->x - parameters->window_padding.left - position->x;
+ position->x = bounds->x - parameters->window_padding.left;
+ }
+
+ if (position->y + height - parameters->window_padding.bottom > bounds->y + bounds->height)
+ {
+ offset->y += bounds->y + bounds->height - height + parameters->window_padding.bottom -
position->y;
+ position->y = bounds->y + bounds->height - height + parameters->window_padding.bottom;
+ }
+
+ if (position->y + parameters->window_padding.top < bounds->y)
+ {
+ offset->y += bounds->y - parameters->window_padding.top - position->y;
+ position->y = bounds->y - parameters->window_padding.top;
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * gdk_attachment_parameters_choose_position_for_window:
+ * @parameters: (transfer none) (not nullable): a #GdkAttachmentParameters
+ * @window: (transfer none) (not nullable): the #GdkWindow to find the best
+ * position for
+ * @position: (out) (optional): the best position for the window
+ * @offset: (out) (optional): the displacement needed to push the window
+ * on-screen
+ * @primary_option: (out) (optional): the best primary option
+ * @secondary_option: (out) (optional): the best secondary option
+ *
+ * Finds the best position for @window according to @parameters.
+ *
+ * Returns: %TRUE if there's a best position
+ *
+ * Since: 3.20
+ */
+gboolean
+gdk_attachment_parameters_choose_position_for_window (const GdkAttachmentParameters *parameters,
+ GdkWindow *window,
+ GdkPoint *position,
+ GdkPoint *offset,
+ GdkAttachmentOption *primary_option,
+ GdkAttachmentOption *secondary_option)
+{
+ GdkScreen *screen;
+ gint x;
+ gint y;
+ gint monitor;
+ GdkRectangle bounds;
+ gint width;
+ gint height;
+
+ g_return_val_if_fail (parameters, FALSE);
+ g_return_val_if_fail (parameters->has_attachment_rectangle, FALSE);
+ g_return_val_if_fail (window, FALSE);
+
+ screen = gdk_window_get_screen (window);
+ x = parameters->attachment_origin.x + parameters->attachment_rectangle.x +
parameters->attachment_rectangle.width / 2;
+ y = parameters->attachment_origin.y + parameters->attachment_rectangle.y +
parameters->attachment_rectangle.height / 2;
+ monitor = gdk_screen_get_monitor_at_point (screen, x, y);
+ gdk_screen_get_monitor_workarea (screen, monitor, &bounds);
+ width = gdk_window_get_width (window);
+ height = gdk_window_get_height (window);
+
+ return gdk_attachment_parameters_choose_position (parameters,
+ width,
+ height,
+ &bounds,
+ position,
+ offset,
+ primary_option,
+ secondary_option);
+}
+
+/**
+ * gdk_window_move_using_attachment_parameters:
+ * @window: (transfer none) (not nullable): the #GdkWindow to position
+ * @parameters: (transfer none) (nullable): a description of how to position
+ * @window
+ *
+ * Moves @window to the best position according to @parameters.
+ *
+ * Since: 3.20
+ */
+void
+gdk_window_move_using_attachment_parameters (GdkWindow *window,
+ const GdkAttachmentParameters *parameters)
+{
+ GdkPoint position;
+ GdkPoint offset;
+ GdkAttachmentOption primary_option;
+ GdkAttachmentOption secondary_option;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (!parameters || !parameters->has_attachment_rectangle)
+ return;
+
+ if (gdk_attachment_parameters_choose_position_for_window (parameters,
+ window,
+ &position,
+ &offset,
+ &primary_option,
+ &secondary_option))
+ {
+ gdk_window_move (window, position.x, position.y);
+
+ if (parameters->position_callback)
+ parameters->position_callback (window,
+ parameters,
+ &position,
+ &offset,
+ primary_option,
+ secondary_option,
+ parameters->position_callback_user_data);
+ }
+}
diff --git a/gdk/gdkattachmentparameters.h b/gdk/gdkattachmentparameters.h
new file mode 100644
index 0000000..c1c78b8
--- /dev/null
+++ b/gdk/gdkattachmentparameters.h
@@ -0,0 +1,210 @@
+#ifndef __GDK_ATTACHMENT_PARAMETERS_H__
+#define __GDK_ATTACHMENT_PARAMETERS_H__
+
+#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdk.h> can be included directly."
+#endif
+
+#include <gdk/gdktypes.h>
+#include <gdk/gdkversionmacros.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GdkAttachmentOption:
+ * @GDK_ATTACHMENT_END_OPTIONS: no more options
+ * @GDK_ATTACHMENT_UNKNOWN_OPTION: indicates that the backend doesn't know
+ * what option was selected for GdkAttachmentPositionCallback(). Only used
+ * for GdkAttachmentPositionCallback().
+ * @GDK_ATTACHMENT_FORCE_FIRST_OPTION: retry first option, pushing on-screen if needed
+ * @GDK_ATTACHMENT_FORCE_FIRST_OPTION_IF_PRIMARY_FORCED: retry first secondary
+ * option if retrying a primary option, pushing on-screen if needed. Only use
+ * this as a secondary option.
+ * @GDK_ATTACHMENT_FORCE_LAST_OPTION: retry recent option, pushing on-screen if needed
+ * @GDK_ATTACHMENT_FORCE_LAST_OPTION_IF_PRIMARY_FORCED: retry recent secondary
+ * option if retrying a primary option, pushing on-screen if needed. Only use
+ * this as a secondary option.
+ * @GDK_ATTACHMENT_ATTACH_TOP_EDGE: attach to top edge of attachment rectangle
+ * @GDK_ATTACHMENT_ATTACH_LEFT_EDGE: attach to left edge of attachment rectangle
+ * @GDK_ATTACHMENT_ATTACH_RIGHT_EDGE: attach to right edge of attachment rectangle
+ * @GDK_ATTACHMENT_ATTACH_BOTTOM_EDGE: attach to bottom edge of attachment rectangle
+ * @GDK_ATTACHMENT_ATTACH_FORWARD_EDGE: attach to forward edge of attachment rectangle
+ * @GDK_ATTACHMENT_ATTACH_BACKWARD_EDGE: attach to backward edge of attachment rectangle
+ * @GDK_ATTACHMENT_ALIGN_TOP_EDGES: align top edges of attachment rectangle and window
+ * @GDK_ATTACHMENT_ALIGN_LEFT_EDGES: align left edges of attachment rectangle and window
+ * @GDK_ATTACHMENT_ALIGN_RIGHT_EDGES: align right edges of attachment rectangle and window
+ * @GDK_ATTACHMENT_ALIGN_BOTTOM_EDGES: align bottom edges of attachment rectangle and window
+ * @GDK_ATTACHMENT_ALIGN_FORWARD_EDGES: align forward edges of attachment rectangle and window
+ * @GDK_ATTACHMENT_ALIGN_BACKWARD_EDGES: align backward edges of attachment rectangle and window
+ * @GDK_ATTACHMENT_CENTER_HORIZONTALLY: center window horizontally on attachment rectangle
+ * @GDK_ATTACHMENT_CENTER_VERTICALLY: center window vertically on attachment rectangle
+ * @GDK_ATTACHMENT_CENTER_ON_TOP_EDGE: center window on top edge of attachment rectangle
+ * @GDK_ATTACHMENT_CENTER_ON_LEFT_EDGE: center window on left edge of attachment rectangle
+ * @GDK_ATTACHMENT_CENTER_ON_RIGHT_EDGE: center window on right edge of attachment rectangle
+ * @GDK_ATTACHMENT_CENTER_ON_BOTTOM_EDGE: center window on bottom edge of attachment rectangle
+ * @GDK_ATTACHMENT_CENTER_ON_FORWARD_EDGE: center window on forward edge of attachment rectangle
+ * @GDK_ATTACHMENT_CENTER_ON_BACKWARD_EDGE: center window on backward edge of attachment rectangle
+ * @GDK_ATTACHMENT_ATTACH_ABOVE_CENTER: align bottom edge of window with center of attachment rectangle
+ * @GDK_ATTACHMENT_ATTACH_BELOW_CENTER: align top edge of window with center of attachment rectangle
+ * @GDK_ATTACHMENT_ATTACH_LEFT_OF_CENTER: align right edge of window with center of attachment rectangle
+ * @GDK_ATTACHMENT_ATTACH_RIGHT_OF_CENTER: align left edge of window with center of attachment rectangle
+ * @GDK_ATTACHMENT_ATTACH_FORWARD_OF_CENTER: align backward edge of window with center of attachment
rectangle
+ * @GDK_ATTACHMENT_ATTACH_BACKWARD_OF_CENTER: align forward edge of window with center of attachment
rectangle
+ *
+ * Constraints on the position of the window relative to its attachment
+ * rectangle.
+ */
+typedef enum _GdkAttachmentOption
+{
+ GDK_ATTACHMENT_END_OPTIONS = 0,
+ GDK_ATTACHMENT_UNKNOWN_OPTION = 0,
+ GDK_ATTACHMENT_FORCE_FIRST_OPTION,
+ GDK_ATTACHMENT_FORCE_FIRST_OPTION_IF_PRIMARY_FORCED,
+ GDK_ATTACHMENT_FORCE_LAST_OPTION,
+ GDK_ATTACHMENT_FORCE_LAST_OPTION_IF_PRIMARY_FORCED,
+ GDK_ATTACHMENT_ATTACH_TOP_EDGE,
+ GDK_ATTACHMENT_ATTACH_LEFT_EDGE,
+ GDK_ATTACHMENT_ATTACH_RIGHT_EDGE,
+ GDK_ATTACHMENT_ATTACH_BOTTOM_EDGE,
+ GDK_ATTACHMENT_ATTACH_FORWARD_EDGE,
+ GDK_ATTACHMENT_ATTACH_BACKWARD_EDGE,
+ GDK_ATTACHMENT_ALIGN_TOP_EDGES,
+ GDK_ATTACHMENT_ALIGN_LEFT_EDGES,
+ GDK_ATTACHMENT_ALIGN_RIGHT_EDGES,
+ GDK_ATTACHMENT_ALIGN_BOTTOM_EDGES,
+ GDK_ATTACHMENT_ALIGN_FORWARD_EDGES,
+ GDK_ATTACHMENT_ALIGN_BACKWARD_EDGES,
+ GDK_ATTACHMENT_CENTER_HORIZONTALLY,
+ GDK_ATTACHMENT_CENTER_VERTICALLY,
+ GDK_ATTACHMENT_CENTER_ON_TOP_EDGE,
+ GDK_ATTACHMENT_CENTER_ON_LEFT_EDGE,
+ GDK_ATTACHMENT_CENTER_ON_RIGHT_EDGE,
+ GDK_ATTACHMENT_CENTER_ON_BOTTOM_EDGE,
+ GDK_ATTACHMENT_CENTER_ON_FORWARD_EDGE,
+ GDK_ATTACHMENT_CENTER_ON_BACKWARD_EDGE,
+ GDK_ATTACHMENT_ATTACH_ABOVE_CENTER,
+ GDK_ATTACHMENT_ATTACH_BELOW_CENTER,
+ GDK_ATTACHMENT_ATTACH_LEFT_OF_CENTER,
+ GDK_ATTACHMENT_ATTACH_RIGHT_OF_CENTER,
+ GDK_ATTACHMENT_ATTACH_FORWARD_OF_CENTER,
+ GDK_ATTACHMENT_ATTACH_BACKWARD_OF_CENTER
+} GdkAttachmentOption;
+
+/**
+ * GdkAttachmentBorder:
+ * @top: space above
+ * @left: space to the left
+ * @right: space to the right
+ * @bottom: space below
+ *
+ * The space around the perimeter of an attachment rectangle.
+ */
+struct _GdkAttachmentBorder
+{
+ gint top;
+ gint left;
+ gint right;
+ gint bottom;
+};
+
+typedef struct _GdkAttachmentBorder GdkAttachmentBorder;
+
+/**
+ * GdkAttachmentParameters:
+ *
+ * Opaque type containing the information needed to position a window relative
+ * to an attachment rectangle.
+ */
+typedef struct _GdkAttachmentParameters GdkAttachmentParameters;
+
+/**
+ * GdkAttachmentPositionCallback:
+ * @window: (transfer none) (nullable): the #GdkWindow that was moved
+ * @parameters: (transfer none) (nullable): the #GdkAttachmentParameters that was used
+ * @position: (transfer none) (nullable): the final position of @window
+ * @offset: (transfer none) (nullable): the displacement applied to keep
+ * @window on-screen
+ * @primary_option: the primary option that was used for positioning. If
+ * unknown, this will be %GDK_ATTACHMENT_UNKNOWN_OPTION
+ * @secondary_option: the secondary option that was used for positioning. If
+ * unknown, this will be %GDK_ATTACHMENT_UNKNOWN_OPTION
+ * @user_data: (transfer none) (nullable): the user data that was set on
+ * @parameters
+ *
+ * A function that can be used to receive information about the final position
+ * of a window after gdk_window_set_attachment_parameters() is called. Since
+ * the position might be determined asynchronously, don't assume it will be
+ * called directly from gdk_window_set_attachment_parameters().
+ */
+typedef void (*GdkAttachmentPositionCallback) (GdkWindow *window,
+ const GdkAttachmentParameters *parameters,
+ const GdkPoint *position,
+ const GdkPoint *offset,
+ GdkAttachmentOption primary_option,
+ GdkAttachmentOption secondary_option,
+ gpointer user_data);
+
+GDK_AVAILABLE_IN_3_20
+GdkAttachmentParameters * gdk_attachment_parameters_new (void);
+
+GDK_AVAILABLE_IN_3_20
+gpointer gdk_attachment_parameters_copy (gconstpointer
src,
+ gpointer
data);
+
+GDK_AVAILABLE_IN_3_20
+void gdk_attachment_parameters_free (gpointer
data);
+
+GDK_AVAILABLE_IN_3_20
+void gdk_attachment_parameters_set_attachment_origin (GdkAttachmentParameters
*parameters,
+ const GdkPoint
*origin);
+
+GDK_AVAILABLE_IN_3_20
+void gdk_attachment_parameters_set_attachment_rectangle (GdkAttachmentParameters
*parameters,
+ const GdkRectangle
*rectangle);
+
+GDK_AVAILABLE_IN_3_20
+void gdk_attachment_parameters_set_attachment_margin (GdkAttachmentParameters
*parameters,
+ const GdkAttachmentBorder
*margin);
+
+GDK_AVAILABLE_IN_3_20
+void gdk_attachment_parameters_set_window_margin (GdkAttachmentParameters
*parameters,
+ const GdkAttachmentBorder
*margin);
+
+GDK_AVAILABLE_IN_3_20
+void gdk_attachment_parameters_set_window_padding (GdkAttachmentParameters
*parameters,
+ const GdkAttachmentBorder
*padding);
+
+GDK_AVAILABLE_IN_3_20
+void gdk_attachment_parameters_set_window_offset (GdkAttachmentParameters
*parameters,
+ const GdkPoint
*offset);
+
+GDK_AVAILABLE_IN_3_20
+GdkWindowTypeHint gdk_attachment_parameters_get_window_type_hint (GdkAttachmentParameters
*parameters);
+
+GDK_AVAILABLE_IN_3_20
+void gdk_attachment_parameters_set_window_type_hint (GdkAttachmentParameters
*parameters,
+ GdkWindowTypeHint
window_type_hint);
+
+GDK_AVAILABLE_IN_3_20
+void gdk_attachment_parameters_set_right_to_left (GdkAttachmentParameters
*parameters,
+ gboolean
is_right_to_left);
+
+GDK_AVAILABLE_IN_3_20
+void gdk_attachment_parameters_add_primary_options (GdkAttachmentParameters
*parameters,
+ GdkAttachmentOption
first_option,
+ ...) G_GNUC_NULL_TERMINATED;
+
+GDK_AVAILABLE_IN_3_20
+void gdk_attachment_parameters_add_secondary_options (GdkAttachmentParameters
*parameters,
+ GdkAttachmentOption
first_option,
+ ...) G_GNUC_NULL_TERMINATED;
+
+GDK_AVAILABLE_IN_3_20
+void gdk_attachment_parameters_set_position_callback (GdkAttachmentParameters
*parameters,
+ GdkAttachmentPositionCallback
callback,
+ gpointer
user_data,
+ GDestroyNotify
destroy_notify);
+
+G_END_DECLS
+
+#endif /* __GDK_ATTACHMENT_PARAMETERS_H__ */
diff --git a/gdk/gdkattachmentparametersprivate.h b/gdk/gdkattachmentparametersprivate.h
new file mode 100644
index 0000000..094882f
--- /dev/null
+++ b/gdk/gdkattachmentparametersprivate.h
@@ -0,0 +1,79 @@
+#ifndef __GDK_ATTACHMENT_PARAMETERS_PRIVATE_H__
+#define __GDK_ATTACHMENT_PARAMETERS_PRIVATE_H__
+
+#include "gdkattachmentparameters.h"
+
+G_BEGIN_DECLS
+
+/*
+ * GdkAttachmentParameters:
+ * @attachment_origin: root origin of @attachment_rectangle coordinate system
+ * @has_attachment_rectangle: %TRUE if @attachment_rectangle is valid
+ * @attachment_rectangle: the attachment rectangle to attach the window to
+ * @attachment_margin: the space to leave around @attachment_rectangle
+ * @window_margin: the space to leave around the window
+ * @window_padding: the space between the window and its contents
+ * @window_offset: the offset to displace the window by
+ * @window_type_hint: the window type hint
+ * @is_right_to_left: %TRUE if the text direction is right to left
+ * @primary_options: a #GList of primary #GdkAttachmentOptions
+ * @secondary_options: a #GList of secondary #GdkAttachmentOptions
+ * @position_callback: a function to call when the final position is known
+ * @position_callback_user_data: additional data to pass to @position_callback
+ * @position_callback_destroy_notify: a function to free
+ * @position_callback_user_data
+ *
+ * Opaque type containing the information needed to position a window relative
+ * to an attachment rectangle.
+ */
+struct _GdkAttachmentParameters
+{
+ /*< private >*/
+ GdkPoint attachment_origin;
+
+ gboolean has_attachment_rectangle;
+ GdkRectangle attachment_rectangle;
+
+ GdkAttachmentBorder attachment_margin;
+ GdkAttachmentBorder window_margin;
+ GdkAttachmentBorder window_padding;
+
+ GdkPoint window_offset;
+
+ GdkWindowTypeHint window_type_hint;
+
+ gboolean is_right_to_left;
+
+ GList *primary_options;
+ GList *secondary_options;
+
+ GdkAttachmentPositionCallback position_callback;
+ gpointer position_callback_user_data;
+ GDestroyNotify position_callback_destroy_notify;
+};
+
+G_GNUC_INTERNAL
+gboolean gdk_attachment_parameters_choose_position (const GdkAttachmentParameters *parameters,
+ gint width,
+ gint height,
+ const GdkRectangle *bounds,
+ GdkPoint *position,
+ GdkPoint *offset,
+ GdkAttachmentOption *primary_option,
+ GdkAttachmentOption
*secondary_option);
+
+G_GNUC_INTERNAL
+gboolean gdk_attachment_parameters_choose_position_for_window (const GdkAttachmentParameters *parameters,
+ GdkWindow *window,
+ GdkPoint *position,
+ GdkPoint *offset,
+ GdkAttachmentOption *primary_option,
+ GdkAttachmentOption
*secondary_option);
+
+G_GNUC_INTERNAL
+void gdk_window_move_using_attachment_parameters (GdkWindow *window,
+ const GdkAttachmentParameters *parameters);
+
+G_END_DECLS
+
+#endif /* __GDK_ATTACHMENT_PARAMETERS_PRIVATE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]