forked from AuroraMiddleware/gtk
b894c35008
In order to make it really sure the GtkPointerFocus is valid while being removed from a GtkWindow.
140 lines
3.4 KiB
C
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);
|
|
}
|