gtk2/gtk/gtkpointerfocus.c
Carlos Garnacho b894c35008 gtk: Make GtkPointerFocus refcounted
In order to make it really sure the GtkPointerFocus is valid while being
removed from a GtkWindow.
2017-05-25 16:25:59 +02:00

140 lines
3.4 KiB
C

/* GTK - The GIMP Toolkit
* Copyright (C) 2017 - Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gtkpointerfocusprivate.h"
#include "gtkprivate.h"
static void
target_destroyed (gpointer data,
GObject *object_location)
{
GtkPointerFocus *focus = data;
focus->target = NULL;
gtk_pointer_focus_repick_target (focus);
}
GtkPointerFocus *
gtk_pointer_focus_new (GtkWindow *toplevel,
GtkWidget *widget,
GdkDevice *device,
GdkEventSequence *sequence,
gdouble x,
gdouble y)
{
GtkPointerFocus *focus;
focus = g_new0 (GtkPointerFocus, 1);
focus->ref_count = 1;
focus->toplevel = toplevel;
focus->device = device;
focus->sequence = sequence;
gtk_pointer_focus_set_target (focus, widget);
gtk_pointer_focus_set_coordinates (focus, x, y);
return focus;
}
GtkPointerFocus *
gtk_pointer_focus_ref (GtkPointerFocus *focus)
{
focus->ref_count++;
return focus;
}
void
gtk_pointer_focus_unref (GtkPointerFocus *focus)
{
focus->ref_count--;
if (focus->ref_count == 0)
{
gtk_pointer_focus_set_target (focus, NULL);
gtk_pointer_focus_set_implicit_grab (focus, NULL);
g_free (focus);
}
}
void
gtk_pointer_focus_set_target (GtkPointerFocus *focus,
GtkWidget *target)
{
if (focus->target == target)
return;
if (focus->target)
g_object_weak_unref (G_OBJECT (focus->target), target_destroyed, focus);
focus->target = target;
if (focus->target)
g_object_weak_ref (G_OBJECT (focus->target), target_destroyed, focus);
}
GtkWidget *
gtk_pointer_focus_get_target (GtkPointerFocus *focus)
{
return focus->target;
}
void
gtk_pointer_focus_set_implicit_grab (GtkPointerFocus *focus,
GtkWidget *grab_widget)
{
focus->grab_widget = grab_widget;
}
GtkWidget *
gtk_pointer_focus_get_implicit_grab (GtkPointerFocus *focus)
{
return focus->grab_widget;
}
void
gtk_pointer_focus_set_coordinates (GtkPointerFocus *focus,
gdouble x,
gdouble y)
{
focus->x = x;
focus->y = y;
}
GtkWidget *
gtk_pointer_focus_get_effective_target (GtkPointerFocus *focus)
{
GtkWidget *target;
target = focus->target;
if (focus->grab_widget &&
focus->grab_widget != target &&
!gtk_widget_is_ancestor (target, focus->grab_widget))
target = focus->grab_widget;
return target;
}
void
gtk_pointer_focus_repick_target (GtkPointerFocus *focus)
{
GtkWidget *target;
target = _gtk_toplevel_pick (focus->toplevel, focus->x, focus->y,
NULL, NULL);
gtk_pointer_focus_set_target (focus, target);
}