[gtksourceview/wip/chergert/snippets: 84/119] completion: port info to GTK 4
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/chergert/snippets: 84/119] completion: port info to GTK 4
- Date: Wed, 29 Jan 2020 17:33:52 +0000 (UTC)
commit 386c04db591312e3157705c736187dbbdd41ed35
Author: Christian Hergert <chergert redhat com>
Date: Wed Jan 15 14:22:11 2020 -0800
completion: port info to GTK 4
- Use GdkSurface instead of GdkWindow
- Use gdk_surface_move_to_rect() for more reliable placement
- Use :margin instead of :border-width
- Use GtkEventControllerKey for input
gtksourceview/gtksourcecompletioninfo.c | 375 +++++---------------------------
1 file changed, 57 insertions(+), 318 deletions(-)
---
diff --git a/gtksourceview/gtksourcecompletioninfo.c b/gtksourceview/gtksourcecompletioninfo.c
index 93884df5..f21ee309 100644
--- a/gtksourceview/gtksourcecompletioninfo.c
+++ b/gtksourceview/gtksourcecompletioninfo.c
@@ -68,6 +68,7 @@ struct _GtkSourceCompletionInfo
guint idle_resize;
GtkWidget *attached_to;
+ GtkEventController *key;
gulong focus_out_event_handler;
gint xoffset;
@@ -79,135 +80,17 @@ G_DEFINE_TYPE (GtkSourceCompletionInfo, gtk_source_completion_info, GTK_TYPE_WIN
/* Resize the window */
-static gboolean
-idle_resize (GtkSourceCompletionInfo *info)
-{
- GtkWidget *child = gtk_bin_get_child (GTK_BIN (info));
- GtkRequisition nat_size;
- guint border_width;
- gint window_width;
- gint window_height;
- gint cur_window_width;
- gint cur_window_height;
-
- info->idle_resize = 0;
-
- if (child == NULL)
- {
- return G_SOURCE_REMOVE;
- }
-
- gtk_widget_get_preferred_size (child, NULL, &nat_size);
-
- border_width = gtk_container_get_border_width (GTK_CONTAINER (info));
-
- window_width = nat_size.width + 2 * border_width;
- window_height = nat_size.height + 2 * border_width;
-
- gtk_window_get_size (GTK_WINDOW (info), &cur_window_width, &cur_window_height);
-
- /* Avoid an infinite loop */
- if (cur_window_width != window_width || cur_window_height != window_height)
- {
- gtk_window_resize (GTK_WINDOW (info),
- MAX (1, window_width),
- MAX (1, window_height));
- }
-
- return G_SOURCE_REMOVE;
-}
-
-static void
-queue_resize (GtkSourceCompletionInfo *info)
-{
- if (info->idle_resize == 0)
- {
- info->idle_resize = g_idle_add ((GSourceFunc)idle_resize, info);
- }
-}
-
-static void
-gtk_source_completion_info_check_resize (GtkContainer *container)
-{
- GtkSourceCompletionInfo *info = GTK_SOURCE_COMPLETION_INFO (container);
- queue_resize (info);
-
- GTK_CONTAINER_CLASS (gtk_source_completion_info_parent_class)->check_resize (container);
-}
-
-/* Geometry management */
-
-static GtkSizeRequestMode
-gtk_source_completion_info_get_request_mode (GtkWidget *widget)
-{
- return GTK_SIZE_REQUEST_CONSTANT_SIZE;
-}
-
-static void
-gtk_source_completion_info_get_preferred_width (GtkWidget *widget,
- gint *min_width,
- gint *nat_width)
-{
- GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
- gint width = 0;
-
- if (child != NULL)
- {
- GtkRequisition nat_size;
- gtk_widget_get_preferred_size (child, NULL, &nat_size);
- width = nat_size.width;
- }
-
- if (min_width != NULL)
- {
- *min_width = width;
- }
-
- if (nat_width != NULL)
- {
- *nat_width = width;
- }
-}
+/* Init, dispose, finalize, ... */
static void
-gtk_source_completion_info_get_preferred_height (GtkWidget *widget,
- gint *min_height,
- gint *nat_height)
+set_attached_to (GtkSourceCompletionInfo *info,
+ GtkWidget *attached_to)
{
- GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
- gint height = 0;
-
- if (child != NULL)
+ if (info->attached_to == attached_to)
{
- GtkRequisition nat_size;
- gtk_widget_get_preferred_size (child, NULL, &nat_size);
- height = nat_size.height;
- }
-
- if (min_height != NULL)
- {
- *min_height = height;
- }
-
- if (nat_height != NULL)
- {
- *nat_height = height;
+ return;
}
-}
-
-/* Init, dispose, finalize, ... */
-static gboolean
-focus_out_event_cb (GtkSourceCompletionInfo *info)
-{
- gtk_widget_hide (GTK_WIDGET (info));
- return FALSE;
-}
-
-static void
-set_attached_to (GtkSourceCompletionInfo *info,
- GtkWidget *attached_to)
-{
if (info->attached_to != NULL)
{
g_object_remove_weak_pointer (G_OBJECT (info->attached_to),
@@ -215,14 +98,16 @@ set_attached_to (GtkSourceCompletionInfo *info,
if (info->focus_out_event_handler != 0)
{
- g_signal_handler_disconnect (info->attached_to,
+ g_signal_handler_disconnect (info->key,
info->focus_out_event_handler);
info->focus_out_event_handler = 0;
+ info->key = NULL;
}
}
info->attached_to = attached_to;
+ info->key = NULL;
if (attached_to == NULL)
{
@@ -232,10 +117,13 @@ set_attached_to (GtkSourceCompletionInfo *info,
g_object_add_weak_pointer (G_OBJECT (attached_to),
(gpointer *) &info->attached_to);
+ info->key = gtk_event_controller_key_new ();
+ gtk_widget_add_controller (GTK_WIDGET (attached_to), info->key);
+
info->focus_out_event_handler =
- g_signal_connect_swapped (attached_to,
- "focus-out-event",
- G_CALLBACK (focus_out_event_cb),
+ g_signal_connect_swapped (info->key,
+ "focus-out",
+ G_CALLBACK (gtk_widget_hide),
info);
info->transient_set = FALSE;
@@ -250,8 +138,6 @@ update_attached_to (GtkSourceCompletionInfo *info)
static void
gtk_source_completion_info_init (GtkSourceCompletionInfo *info)
{
- info = gtk_source_completion_info_get_instance_private (info);
-
g_signal_connect (info,
"notify::attached-to",
G_CALLBACK (update_attached_to),
@@ -264,9 +150,9 @@ gtk_source_completion_info_init (GtkSourceCompletionInfo *info)
gtk_widget_set_name (GTK_WIDGET (info), "gtk-tooltip");
gtk_window_set_type_hint (GTK_WINDOW (info),
- GDK_WINDOW_TYPE_HINT_COMBO);
+ GDK_SURFACE_TYPE_HINT_COMBO);
- gtk_container_set_border_width (GTK_CONTAINER (info), 1);
+ g_object_set (info, "margin", 1, NULL);
}
static void
@@ -292,13 +178,14 @@ gtk_source_completion_info_show (GtkWidget *widget)
if (info->attached_to != NULL && !info->transient_set)
{
- GtkWidget *toplevel;
+ GtkRoot *toplevel;
+
+ toplevel = gtk_widget_get_root (GTK_WIDGET (info->attached_to));
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (info->attached_to));
- if (gtk_widget_is_toplevel (toplevel))
+ if (toplevel != NULL)
{
gtk_window_set_transient_for (GTK_WINDOW (info),
- GTK_WINDOW (toplevel));
+ GTK_WINDOW (toplevel));
info->transient_set = TRUE;
}
}
@@ -306,37 +193,15 @@ gtk_source_completion_info_show (GtkWidget *widget)
GTK_WIDGET_CLASS (gtk_source_completion_info_parent_class)->show (widget);
}
-static gboolean
-gtk_source_completion_info_draw (GtkWidget *widget,
- cairo_t *cr)
-{
- GTK_WIDGET_CLASS (gtk_source_completion_info_parent_class)->draw (widget, cr);
-
- gtk_render_frame (gtk_widget_get_style_context (widget),
- cr,
- 0, 0,
- gtk_widget_get_allocated_width (widget),
- gtk_widget_get_allocated_height (widget));
-
- return FALSE;
-}
-
static void
gtk_source_completion_info_class_init (GtkSourceCompletionInfoClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
object_class->dispose = gtk_source_completion_info_dispose;
widget_class->show = gtk_source_completion_info_show;
- widget_class->draw = gtk_source_completion_info_draw;
- widget_class->get_request_mode = gtk_source_completion_info_get_request_mode;
- widget_class->get_preferred_width = gtk_source_completion_info_get_preferred_width;
- widget_class->get_preferred_height = gtk_source_completion_info_get_preferred_height;
-
- container_class->check_resize = gtk_source_completion_info_check_resize;
}
void
@@ -348,173 +213,47 @@ _gtk_source_completion_info_set_xoffset (GtkSourceCompletionInfo *window,
window->xoffset = xoffset;
}
-/* Move to iter */
-
static void
-get_iter_pos (GtkTextView *text_view,
- GtkTextIter *iter,
- gint *x,
- gint *y,
- gint *height)
+move_to_iter (GtkSourceCompletionInfo *window,
+ GtkTextView *view,
+ GtkTextIter *iter)
{
- GdkWindow *win;
GdkRectangle location;
- gint win_x;
- gint win_y;
- gint xx;
- gint yy;
-
- gtk_text_view_get_iter_location (text_view, iter, &location);
-
- gtk_text_view_buffer_to_window_coords (text_view,
- GTK_TEXT_WINDOW_WIDGET,
- location.x,
- location.y,
- &win_x,
- &win_y);
-
- win = gtk_text_view_get_window (text_view, GTK_TEXT_WINDOW_WIDGET);
- gdk_window_get_origin (win, &xx, &yy);
-
- *x = win_x + xx;
- *y = win_y + yy + location.height;
- *height = location.height;
-}
-
-static void
-compensate_for_gravity (GtkSourceCompletionInfo *window,
- gint *x,
- gint *y,
- gint w,
- gint h)
-{
- GdkGravity gravity = gtk_window_get_gravity (GTK_WINDOW (window));
-
- /* Horizontal */
- switch (gravity)
- {
- case GDK_GRAVITY_NORTH:
- case GDK_GRAVITY_SOUTH:
- case GDK_GRAVITY_CENTER:
- *x = w / 2;
- break;
- case GDK_GRAVITY_NORTH_EAST:
- case GDK_GRAVITY_SOUTH_EAST:
- case GDK_GRAVITY_EAST:
- *x = w;
- break;
- case GDK_GRAVITY_NORTH_WEST:
- case GDK_GRAVITY_WEST:
- case GDK_GRAVITY_SOUTH_WEST:
- case GDK_GRAVITY_STATIC:
- default:
- *x = 0;
- break;
- }
-
- /* Vertical */
- switch (gravity)
- {
- case GDK_GRAVITY_WEST:
- case GDK_GRAVITY_CENTER:
- case GDK_GRAVITY_EAST:
- *y = w / 2;
- break;
- case GDK_GRAVITY_SOUTH_EAST:
- case GDK_GRAVITY_SOUTH:
- case GDK_GRAVITY_SOUTH_WEST:
- *y = w;
- break;
- case GDK_GRAVITY_NORTH:
- case GDK_GRAVITY_NORTH_EAST:
- case GDK_GRAVITY_NORTH_WEST:
- case GDK_GRAVITY_STATIC:
- default:
- *y = 0;
- break;
- }
-}
+ GdkSurface *surface;
+ GtkRoot *root;
-static void
-move_overlap (gint *y,
- gint h,
- gint oy,
- gint cy,
- gint line_height,
- gboolean move_up)
-{
- /* Test if there is overlap */
- if (*y - cy < oy && *y - cy + h > oy - line_height)
- {
- if (move_up)
- {
- *y = oy - line_height - h + cy;
- }
- else
- {
- *y = oy + cy;
- }
- }
-}
-
-static void
-move_to_iter (GtkSourceCompletionInfo *window,
- GtkTextView *view,
- GtkTextIter *iter)
-{
- GdkDisplay *display;
- GdkWindow *gdk_window;
- GdkMonitor *monitor;
- GdkRectangle geom;
- gint x, y;
- gint w, h;
- gint cx, cy;
- gint oy;
- gint height;
- gboolean overlapup;
-
- display = gtk_widget_get_display (GTK_WIDGET (view));
- gdk_window = gtk_widget_get_window (GTK_WIDGET (view));
- monitor = gdk_display_get_monitor_at_window (display, gdk_window);
- gdk_monitor_get_geometry (monitor, &geom);
-
- get_iter_pos (view, iter, &x, &y, &height);
- gtk_window_get_size (GTK_WINDOW (window), &w, &h);
-
- x += window->xoffset;
-
- oy = y;
- compensate_for_gravity (window, &cx, &cy, w, h);
-
- /* Push window inside screen */
- if (x - cx + w > geom.width)
- {
- x = (geom.width - w) + cx;
- }
- else if (x - cx < 0)
- {
- x = cx;
- }
+ if (!GTK_IS_NATIVE (window))
+ return;
- if (y - cy + h > geom.height)
- {
- y = (geom.height - h) + cy;
- overlapup = TRUE;
- }
- else if (y - cy < 0)
- {
- y = cy;
- overlapup = FALSE;
- }
- else
- {
- overlapup = TRUE;
- }
+ surface = gtk_native_get_surface (GTK_NATIVE (window));
+ if (surface == NULL)
+ return;
- /* Make sure that text is still readable */
- move_overlap (&y, h, oy, cy, height, overlapup);
+ root = gtk_widget_get_root (GTK_WIDGET (view));
+ if (root == NULL)
+ return;
- gtk_window_move (GTK_WINDOW (window), x, y);
+ gtk_text_view_get_iter_location (view, iter, &location);
+ gtk_text_view_buffer_to_window_coords (view,
+ GTK_TEXT_WINDOW_WIDGET,
+ location.x,
+ location.y,
+ &location.x,
+ &location.y);
+
+ gtk_widget_translate_coordinates (GTK_WIDGET (view),
+ GTK_WIDGET (root),
+ location.x + window->xoffset,
+ location.y,
+ &location.x,
+ &location.y);
+
+ gdk_surface_move_to_rect (surface,
+ &location,
+ GDK_GRAVITY_SOUTH_WEST,
+ GDK_GRAVITY_NORTH_WEST,
+ GDK_ANCHOR_FLIP_Y,
+ 0, 0);
}
static void
@@ -542,7 +281,7 @@ gtk_source_completion_info_new (void)
{
return g_object_new (GTK_SOURCE_TYPE_COMPLETION_INFO,
"type", GTK_WINDOW_POPUP,
- "border-width", 3,
+ "margin", 3,
NULL);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]