forked from AuroraMiddleware/gtk
gtk: Run GtkWidgetClass event signals inside a GtkEventController
This will allow further cleanups and optimizations in capture/target/bubble event delivery. For simplicity, ATM every widget will receive its own GtkEventControllerLegacy, it could be desirable to add finer control over this in the future, so widgets that fully use event controllers for input management can do away without this legacy piece.
This commit is contained in:
parent
b350db58e0
commit
8c350459ae
56
gtk/gtkeventcontrollerlegacy.c
Normal file
56
gtk/gtkeventcontrollerlegacy.c
Normal file
@ -0,0 +1,56 @@
|
||||
/* 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/>.
|
||||
*
|
||||
* Author(s): Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "gtkeventcontrollerlegacyprivate.h"
|
||||
|
||||
G_DEFINE_TYPE (GtkEventControllerLegacy, _gtk_event_controller_legacy,
|
||||
GTK_TYPE_EVENT_CONTROLLER)
|
||||
|
||||
static gboolean
|
||||
gtk_event_controller_legacy_handle_event (GtkEventController *controller,
|
||||
const GdkEvent *event)
|
||||
{
|
||||
GtkWidget *widget = gtk_event_controller_get_widget (controller);
|
||||
|
||||
return gtk_widget_emit_event_signals (widget, event);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_event_controller_legacy_class_init (GtkEventControllerLegacyClass *klass)
|
||||
{
|
||||
GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
|
||||
|
||||
controller_class->handle_event = gtk_event_controller_legacy_handle_event;
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_event_controller_legacy_init (GtkEventControllerLegacy *controller)
|
||||
{
|
||||
}
|
||||
|
||||
GtkEventController *
|
||||
_gtk_event_controller_legacy_new (GtkWidget *widget)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_EVENT_CONTROLLER_LEGACY,
|
||||
"widget", widget,
|
||||
NULL);
|
||||
}
|
51
gtk/gtkeventcontrollerlegacyprivate.h
Normal file
51
gtk/gtkeventcontrollerlegacyprivate.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* 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/>.
|
||||
*
|
||||
* Author(s): Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_EVENT_CONTROLLER_LEGACY_H__
|
||||
#define __GTK_EVENT_CONTROLLER_LEGACY_H__
|
||||
|
||||
#include "gtkeventcontrollerprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_EVENT_CONTROLLER_LEGACY (_gtk_event_controller_legacy_get_type ())
|
||||
#define GTK_EVENT_CONTROLLER_LEGACY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_EVENT_CONTROLLER_LEGACY, GtkEventControllerLegacy))
|
||||
#define GTK_EVENT_CONTROLLER_LEGACY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_EVENT_CONTROLLER_LEGACY, GtkEventControllerLegacyClass))
|
||||
#define GTK_IS_EVENT_CONTROLLER_LEGACY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_EVENT_CONTROLLER_LEGACY))
|
||||
#define GTK_IS_EVENT_CONTROLLER_LEGACY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_EVENT_CONTROLLER_LEGACY))
|
||||
#define GTK_EVENT_CONTROLLER_LEGACY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_EVENT_CONTROLLER_LEGACY, GtkEventControllerLegacyClass))
|
||||
|
||||
typedef struct _GtkEventControllerLegacy GtkEventControllerLegacy;
|
||||
typedef struct _GtkEventControllerLegacyClass GtkEventControllerLegacyClass;
|
||||
|
||||
struct _GtkEventControllerLegacy
|
||||
{
|
||||
GtkEventController parent_instance;
|
||||
};
|
||||
|
||||
struct _GtkEventControllerLegacyClass
|
||||
{
|
||||
GtkEventControllerClass parent_class;
|
||||
};
|
||||
|
||||
GType _gtk_event_controller_legacy_get_type (void) G_GNUC_CONST;
|
||||
GtkEventController *_gtk_event_controller_legacy_new (GtkWidget *widget);
|
||||
|
||||
#endif /* __GTK_EVENT_CONTROLLER_LEGACY_H__ */
|
@ -77,6 +77,7 @@
|
||||
#include "gtkcssshadowsvalueprivate.h"
|
||||
#include "gtkdebugupdatesprivate.h"
|
||||
#include "gsk/gskdebugprivate.h"
|
||||
#include "gtkeventcontrollerlegacyprivate.h"
|
||||
|
||||
#include "inspector/window.h"
|
||||
|
||||
@ -3847,6 +3848,8 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
|
||||
gtk_css_node_set_visible (priv->cssnode, priv->visible);
|
||||
/* need to set correct type here, and only class has the correct type here */
|
||||
gtk_css_node_set_widget_type (priv->cssnode, G_TYPE_FROM_CLASS (g_class));
|
||||
|
||||
gtk_widget_init_legacy_controller (widget);
|
||||
}
|
||||
|
||||
|
||||
@ -6466,16 +6469,14 @@ static gboolean
|
||||
gtk_widget_real_button_event (GtkWidget *widget,
|
||||
GdkEventButton *event)
|
||||
{
|
||||
return _gtk_widget_run_controllers (widget, (GdkEvent *) event,
|
||||
GTK_PHASE_BUBBLE);
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_widget_real_motion_event (GtkWidget *widget,
|
||||
GdkEventMotion *event)
|
||||
{
|
||||
return _gtk_widget_run_controllers (widget, (GdkEvent *) event,
|
||||
GTK_PHASE_BUBBLE);
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -6518,10 +6519,6 @@ gtk_widget_real_touch_event (GtkWidget *widget,
|
||||
gboolean return_val;
|
||||
gint signum;
|
||||
|
||||
if (!event->emulating_pointer)
|
||||
return _gtk_widget_run_controllers (widget, (GdkEvent*) event,
|
||||
GTK_PHASE_BUBBLE);
|
||||
|
||||
if (event->type == GDK_TOUCH_BEGIN ||
|
||||
event->type == GDK_TOUCH_END)
|
||||
{
|
||||
@ -6587,8 +6584,7 @@ static gboolean
|
||||
gtk_widget_real_grab_broken_event (GtkWidget *widget,
|
||||
GdkEventGrabBroken *event)
|
||||
{
|
||||
return _gtk_widget_run_controllers (widget, (GdkEvent*) event,
|
||||
GTK_PHASE_BUBBLE);
|
||||
return GDK_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
#define WIDGET_REALIZED_FOR_EVENT(widget, event) \
|
||||
@ -6827,7 +6823,7 @@ static gint
|
||||
gtk_widget_event_internal (GtkWidget *widget,
|
||||
const GdkEvent *event)
|
||||
{
|
||||
gboolean return_val = FALSE, handled;
|
||||
gboolean return_val = FALSE;
|
||||
GdkEvent *event_copy;
|
||||
|
||||
/* We check only once for is-still-visible; if someone
|
||||
@ -6838,7 +6834,27 @@ gtk_widget_event_internal (GtkWidget *widget,
|
||||
if (!event_window_is_still_viewable (event))
|
||||
return TRUE;
|
||||
|
||||
g_object_ref (widget);
|
||||
/* Non input events get handled right away */
|
||||
switch (event->type)
|
||||
{
|
||||
case GDK_VISIBILITY_NOTIFY:
|
||||
case GDK_EXPOSE:
|
||||
case GDK_NOTHING:
|
||||
case GDK_DELETE:
|
||||
case GDK_DESTROY:
|
||||
case GDK_CONFIGURE:
|
||||
case GDK_MAP:
|
||||
case GDK_UNMAP:
|
||||
case GDK_WINDOW_STATE:
|
||||
case GDK_PROPERTY_NOTIFY:
|
||||
case GDK_SELECTION_CLEAR:
|
||||
case GDK_SELECTION_REQUEST:
|
||||
case GDK_SELECTION_NOTIFY:
|
||||
return gtk_widget_emit_event_signals (widget, event);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
event_copy = gdk_event_copy (event);
|
||||
|
||||
translate_event_coordinates (event_copy, widget);
|
||||
@ -6846,18 +6862,39 @@ gtk_widget_event_internal (GtkWidget *widget,
|
||||
if (widget == gtk_get_event_target (event_copy))
|
||||
return_val |= _gtk_widget_run_controllers (widget, event_copy, GTK_PHASE_TARGET);
|
||||
|
||||
g_signal_emit (widget, widget_signals[EVENT], 0, event_copy, &handled);
|
||||
return_val |= handled | !WIDGET_REALIZED_FOR_EVENT (widget, event_copy);
|
||||
/* XXX: Tooltips should be handled through captured events in the toplevel */
|
||||
if (event_copy->type == GDK_FOCUS_CHANGE)
|
||||
{
|
||||
if (event_copy->focus_change.in)
|
||||
_gtk_tooltip_focus_in (widget);
|
||||
else
|
||||
_gtk_tooltip_focus_out (widget);
|
||||
}
|
||||
|
||||
return_val |= _gtk_widget_run_controllers (widget, event_copy, GTK_PHASE_BUBBLE);
|
||||
gdk_event_free (event_copy);
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_widget_emit_event_signals (GtkWidget *widget,
|
||||
const GdkEvent *event)
|
||||
{
|
||||
gboolean return_val = FALSE, handled;
|
||||
|
||||
g_object_ref (widget);
|
||||
|
||||
g_signal_emit (widget, widget_signals[EVENT], 0, event, &handled);
|
||||
return_val |= handled | !WIDGET_REALIZED_FOR_EVENT (widget, event);
|
||||
if (!return_val)
|
||||
{
|
||||
gint signal_num;
|
||||
|
||||
switch (event_copy->type)
|
||||
switch (event->type)
|
||||
{
|
||||
case GDK_TOUCHPAD_SWIPE:
|
||||
case GDK_TOUCHPAD_PINCH:
|
||||
return_val |= _gtk_widget_run_controllers (widget, event_copy, GTK_PHASE_BUBBLE);
|
||||
/* Fall through */
|
||||
case GDK_PAD_BUTTON_PRESS:
|
||||
case GDK_PAD_BUTTON_RELEASE:
|
||||
case GDK_PAD_RING:
|
||||
@ -6908,11 +6945,7 @@ gtk_widget_event_internal (GtkWidget *widget,
|
||||
signal_num = LEAVE_NOTIFY_EVENT;
|
||||
break;
|
||||
case GDK_FOCUS_CHANGE:
|
||||
signal_num = event_copy->focus_change.in ? FOCUS_IN_EVENT : FOCUS_OUT_EVENT;
|
||||
if (event_copy->focus_change.in)
|
||||
_gtk_tooltip_focus_in (widget);
|
||||
else
|
||||
_gtk_tooltip_focus_out (widget);
|
||||
signal_num = event->focus_change.in ? FOCUS_IN_EVENT : FOCUS_OUT_EVENT;
|
||||
break;
|
||||
case GDK_CONFIGURE:
|
||||
signal_num = CONFIGURE_EVENT;
|
||||
@ -6948,23 +6981,22 @@ gtk_widget_event_internal (GtkWidget *widget,
|
||||
signal_num = GRAB_BROKEN_EVENT;
|
||||
break;
|
||||
default:
|
||||
g_warning ("gtk_widget_event(): unhandled event type: %d", event_copy->type);
|
||||
g_warning ("gtk_widget_event(): unhandled event type: %d", event->type);
|
||||
signal_num = -1;
|
||||
break;
|
||||
}
|
||||
if (signal_num != -1)
|
||||
{
|
||||
g_signal_emit (widget, widget_signals[signal_num], 0, event_copy, &handled);
|
||||
g_signal_emit (widget, widget_signals[signal_num], 0, event, &handled);
|
||||
return_val |= handled;
|
||||
}
|
||||
}
|
||||
if (WIDGET_REALIZED_FOR_EVENT (widget, event_copy))
|
||||
g_signal_emit (widget, widget_signals[EVENT_AFTER], 0, event_copy);
|
||||
if (WIDGET_REALIZED_FOR_EVENT (widget, event))
|
||||
g_signal_emit (widget, widget_signals[EVENT_AFTER], 0, event);
|
||||
else
|
||||
return_val = TRUE;
|
||||
|
||||
g_object_unref (widget);
|
||||
gdk_event_free (event_copy);
|
||||
|
||||
return return_val;
|
||||
}
|
||||
@ -15552,3 +15584,14 @@ gtk_widget_get_pass_through (GtkWidget *widget)
|
||||
{
|
||||
return widget->priv->pass_through;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_widget_init_legacy_controller (GtkWidget *widget)
|
||||
{
|
||||
GtkEventController *controller;
|
||||
|
||||
controller = _gtk_event_controller_legacy_new (widget);
|
||||
g_object_set_data_full (G_OBJECT (widget),
|
||||
"gtk-widget-legacy-event-controller",
|
||||
controller, g_object_unref);
|
||||
}
|
||||
|
@ -334,6 +334,12 @@ void gtk_widget_set_pass_through (GtkWidget *widget,
|
||||
gboolean pass_through);
|
||||
gboolean gtk_widget_get_pass_through (GtkWidget *widget);
|
||||
|
||||
gboolean gtk_widget_emit_event_signals (GtkWidget *widget,
|
||||
const GdkEvent *event);
|
||||
|
||||
void gtk_widget_init_legacy_controller (GtkWidget *widget);
|
||||
|
||||
|
||||
/* inline getters */
|
||||
|
||||
static inline GtkWidget *
|
||||
|
@ -146,6 +146,7 @@ gtk_public_sources = files([
|
||||
'gtkentrybuffer.c',
|
||||
'gtkentrycompletion.c',
|
||||
'gtkeventcontroller.c',
|
||||
'gtkeventcontrollerlegacy.c',
|
||||
'gtkexpander.c',
|
||||
'gtkfilechooser.c',
|
||||
'gtkfilechooserbutton.c',
|
||||
@ -364,6 +365,7 @@ gtk_public_sources = files([
|
||||
gtk_private_type_headers = files([
|
||||
'gtkcsstypesprivate.h',
|
||||
'gtktexthandleprivate.h',
|
||||
'gtkeventcontrollerlegacyprivate.h',
|
||||
])
|
||||
|
||||
gtk_private_headers = gtk_private_type_headers + files([
|
||||
|
Loading…
Reference in New Issue
Block a user