[gtk+/wip/attachment-parameters: 3/3] gdkwindow-x11: implement gdk_x11_window_set_attachment_parameters ()
- From: William Hua <williamhua src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/attachment-parameters: 3/3] gdkwindow-x11: implement gdk_x11_window_set_attachment_parameters ()
- Date: Mon, 21 Sep 2015 18:16:19 +0000 (UTC)
commit d83dcfe9b81c54e640c0caa2c2f79fd41fe8e691
Author: William Hua <william hua canonical com>
Date: Mon Sep 21 13:54:01 2015 -0400
gdkwindow-x11: implement gdk_x11_window_set_attachment_parameters ()
gdk/x11/gdkwindow-x11.c | 436 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 436 insertions(+), 0 deletions(-)
---
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index 1ace677..81433bb 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -39,6 +39,7 @@
#include "gdkglcontext-x11.h"
#include "gdkprivate-x11.h"
#include "gdk-private.h"
+#include "gdkattachmentparametersprivate.h"
#include <stdlib.h>
#include <stdio.h>
@@ -5681,6 +5682,440 @@ gdk_x11_window_show_window_menu (GdkWindow *window,
return TRUE;
}
+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:
+ 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:
+ 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;
+
+ 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
+ + parameters->window_margin.bottom
+ + parameters->window_padding.bottom
+ - height;
+ break;
+
+ case GDK_ATTACHMENT_ATTACH_LEFT_EDGE:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ - parameters->attachment_margin.left
+ + parameters->window_margin.right
+ + parameters->window_padding.right
+ - width;
+ 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;
+ 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;
+ break;
+
+ case GDK_ATTACHMENT_ALIGN_TOP_EDGES:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ - parameters->window_margin.top
+ - parameters->window_padding.top;
+ break;
+
+ case GDK_ATTACHMENT_ALIGN_LEFT_EDGES:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ - parameters->window_margin.left
+ - parameters->window_padding.left;
+ break;
+
+ case GDK_ATTACHMENT_ALIGN_RIGHT_EDGES:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ + parameters->attachment_rectangle.width
+ + parameters->window_margin.right
+ + parameters->window_padding.right
+ - width;
+ break;
+
+ case GDK_ATTACHMENT_ALIGN_BOTTOM_EDGES:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ + parameters->attachment_rectangle.height
+ + parameters->window_margin.bottom
+ + parameters->window_padding.bottom
+ - height;
+ break;
+
+ case GDK_ATTACHMENT_CENTER_HORIZONTALLY:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ + parameters->attachment_rectangle.width / 2
+ - parameters->window_margin.left
+ - parameters->window_padding.left
+ - (width - parameters->window_margin.left
+ - parameters->window_margin.right
+ - parameters->window_padding.left
+ - parameters->window_padding.right) / 2;
+ break;
+
+ case GDK_ATTACHMENT_CENTER_VERTICALLY:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ + parameters->attachment_rectangle.height / 2
+ - parameters->window_margin.top
+ - parameters->window_padding.top
+ - (height - parameters->window_margin.top
+ - parameters->window_margin.bottom
+ - parameters->window_padding.top
+ - parameters->window_padding.bottom) / 2;
+ break;
+
+ case GDK_ATTACHMENT_CENTER_ON_TOP_EDGE:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ - parameters->window_margin.top
+ - parameters->window_padding.top
+ - (height - parameters->window_margin.top
+ - parameters->window_margin.bottom
+ - parameters->window_padding.top
+ - parameters->window_padding.bottom) / 2;
+ break;
+
+ case GDK_ATTACHMENT_CENTER_ON_LEFT_EDGE:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ - parameters->window_margin.left
+ - parameters->window_padding.left
+ - (width - parameters->window_margin.left
+ - parameters->window_margin.right
+ - parameters->window_padding.left
+ - parameters->window_padding.right) / 2;
+ break;
+
+ case GDK_ATTACHMENT_CENTER_ON_RIGHT_EDGE:
+ *axis = 0;
+ *value = parameters->attachment_origin.x
+ + parameters->attachment_rectangle.x
+ + parameters->attachment_rectangle.width
+ - parameters->window_margin.left
+ - parameters->window_padding.left
+ - (width - parameters->window_margin.left
+ - parameters->window_margin.right
+ - parameters->window_padding.left
+ - parameters->window_padding.right) / 2;
+ break;
+
+ case GDK_ATTACHMENT_CENTER_ON_BOTTOM_EDGE:
+ *axis = 1;
+ *value = parameters->attachment_origin.y
+ + parameters->attachment_rectangle.y
+ + parameters->attachment_rectangle.height
+ - parameters->window_margin.top
+ - parameters->window_padding.top
+ - (height - parameters->window_margin.top
+ - parameters->window_margin.bottom
+ - parameters->window_padding.top
+ - parameters->window_padding.bottom) / 2;
+ 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);
+}
+
+static void
+gdk_x11_window_set_attachment_parameters (GdkWindow *window,
+ const GdkAttachmentParameters *parameters)
+{
+ GdkScreen *screen;
+ gint monitor;
+ GdkRectangle bounds;
+ gint width;
+ gint height;
+ GList *i;
+ GList *j;
+ GList *k;
+ GdkAttachmentOption primary_option;
+ GdkAttachmentOption secondary_option;
+ gint primary_axis;
+ gint secondary_axis;
+ gboolean primary_force;
+ gboolean secondary_force;
+ gint primary_value;
+ gint secondary_value;
+ gint position[2];
+
+ if (!parameters || !parameters->has_attachment_rectangle)
+ return;
+
+ screen = gdk_window_get_screen (window);
+ monitor = gdk_screen_get_monitor_at_window (screen, window);
+ gdk_screen_get_monitor_workarea (screen, monitor, &bounds);
+ width = gdk_window_get_width (window);
+ height = gdk_window_get_height (window);
+
+ 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);
+ primary_option = GPOINTER_TO_INT (parameters->primary_options->data);
+ 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 (!i->prev)
+ {
+ g_warning ("%s (): started with GDK_ATTACHMENT_FORCE_LAST_OPTION", G_STRFUNC);
+ continue;
+ }
+
+ primary_option = GPOINTER_TO_INT (i->prev->data);
+ primary_force = TRUE;
+ }
+
+ if (is_satisfiable (parameters,
+ primary_option,
+ width,
+ height,
+ &bounds,
+ &primary_axis,
+ &primary_value) || primary_force)
+ {
+ 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;
+
+ for (k = parameters->secondary_options; k; k = k->next)
+ {
+ secondary_option = GPOINTER_TO_INT (k->data);
+ secondary_force = TRUE;
+ secondary_axis = get_axis (secondary_option);
+
+ if (secondary_axis >= 0 && secondary_axis != primary_axis)
+ break;
+ }
+
+ if (!k)
+ continue;
+ }
+ else if (secondary_option == GDK_ATTACHMENT_FORCE_LAST_OPTION ||
+ secondary_option == GDK_ATTACHMENT_FORCE_LAST_OPTION_IF_PRIMARY_FORCED)
+ {
+ 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;
+ }
+
+ if (secondary_option == GDK_ATTACHMENT_FORCE_LAST_OPTION_IF_PRIMARY_FORCED &&
!primary_force)
+ continue;
+
+ for (k = j->prev; k; k = k->prev)
+ {
+ secondary_option = GPOINTER_TO_INT (k->data);
+ secondary_force = TRUE;
+ secondary_axis = get_axis (secondary_option);
+
+ if (secondary_axis >= 0 && secondary_axis != primary_axis)
+ break;
+ }
+
+ if (!k)
+ continue;
+ }
+
+ if (is_satisfiable (parameters,
+ secondary_option,
+ width,
+ height,
+ &bounds,
+ &secondary_axis,
+ &secondary_value) || secondary_force)
+ {
+ position[primary_axis] = primary_value;
+ position[secondary_axis] = secondary_value;
+
+ break;
+ }
+ }
+
+ if (j)
+ break;
+ }
+ }
+
+ if (i)
+ gdk_window_move (window, position[0], position[1]);
+}
+
static void
gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
{
@@ -5771,4 +6206,5 @@ gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
impl_class->create_gl_context = gdk_x11_window_create_gl_context;
impl_class->invalidate_for_new_frame = gdk_x11_window_invalidate_for_new_frame;
impl_class->get_unscaled_size = gdk_x11_window_get_unscaled_size;
+ impl_class->set_attachment_parameters = gdk_x11_window_set_attachment_parameters;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]