diff --git a/clutter/clutter/clutter-grab-private.h b/clutter/clutter/clutter-grab-private.h
new file mode 100644
index 000000000..26085add9
--- /dev/null
+++ b/clutter/clutter/clutter-grab-private.h
@@ -0,0 +1,45 @@
+/*
+ * Clutter.
+ *
+ * Copyright (C) 2023 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 .
+ *
+ * Author: Carlos Garnacho
+ */
+
+#pragma once
+
+#include "clutter-grab.h"
+#include "clutter-stage.h"
+
+G_BEGIN_DECLS
+
+struct _ClutterGrab
+{
+ GObject parent_instance;
+ ClutterStage *stage;
+
+ ClutterActor *actor;
+ gboolean owns_actor;
+
+ ClutterGrab *prev;
+ ClutterGrab *next;
+};
+
+ClutterGrab * clutter_grab_new (ClutterStage *stage,
+ ClutterActor *actor,
+ gboolean owns_actor);
+
+G_END_DECLS
diff --git a/clutter/clutter/clutter-grab.c b/clutter/clutter/clutter-grab.c
new file mode 100644
index 000000000..57fa0ecf9
--- /dev/null
+++ b/clutter/clutter/clutter-grab.c
@@ -0,0 +1,75 @@
+/*
+ * Clutter.
+ *
+ * Copyright (C) 2023 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 .
+ *
+ * Author: Carlos Garnacho
+ */
+
+#include "config.h"
+
+#include "clutter-grab-private.h"
+
+G_DEFINE_FINAL_TYPE (ClutterGrab, clutter_grab, G_TYPE_OBJECT)
+
+static void
+clutter_grab_dispose (GObject *object)
+{
+ clutter_grab_dismiss (CLUTTER_GRAB (object));
+ G_OBJECT_CLASS (clutter_grab_parent_class)->dispose (object);
+}
+
+static void
+clutter_grab_finalize (GObject *object)
+{
+ ClutterGrab *grab = CLUTTER_GRAB (object);
+
+ if (grab->owns_actor)
+ g_clear_pointer (&grab->actor, clutter_actor_destroy);
+
+ G_OBJECT_CLASS (clutter_grab_parent_class)->finalize (object);
+}
+
+static void
+clutter_grab_class_init (ClutterGrabClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = clutter_grab_dispose;
+ object_class->finalize = clutter_grab_finalize;
+}
+
+static void
+clutter_grab_init (ClutterGrab *grab)
+{
+}
+
+ClutterGrab *
+clutter_grab_new (ClutterStage *stage,
+ ClutterActor *actor,
+ gboolean owns_actor)
+{
+ ClutterGrab *grab;
+
+ grab = g_object_new (CLUTTER_TYPE_GRAB, NULL);
+ grab->stage = stage;
+
+ grab->actor = actor;
+ if (owns_actor)
+ grab->owns_actor = TRUE;
+
+ return grab;
+}
diff --git a/clutter/clutter/clutter-grab.h b/clutter/clutter/clutter-grab.h
index 73ac52096..1e4eb67ff 100644
--- a/clutter/clutter/clutter-grab.h
+++ b/clutter/clutter/clutter-grab.h
@@ -29,20 +29,15 @@
#include
-#define CLUTTER_TYPE_GRAB (clutter_grab_get_type ())
-typedef struct _ClutterGrab ClutterGrab;
+#include "clutter-macros.h"
+#include "clutter-enums.h"
+#define CLUTTER_TYPE_GRAB (clutter_grab_get_type ())
CLUTTER_EXPORT
-GType clutter_grab_get_type (void) G_GNUC_CONST;
+G_DECLARE_FINAL_TYPE (ClutterGrab, clutter_grab, CLUTTER, GRAB, GObject)
CLUTTER_EXPORT
void clutter_grab_dismiss (ClutterGrab *grab);
CLUTTER_EXPORT
ClutterGrabState clutter_grab_get_seat_state (ClutterGrab *grab);
-
-CLUTTER_EXPORT
-ClutterGrab * clutter_grab_ref (ClutterGrab *grab);
-
-CLUTTER_EXPORT
-void clutter_grab_unref (ClutterGrab *grab);
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 26dba059c..e1804fa88 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -50,7 +50,7 @@
#include "clutter/clutter-event-private.h"
#include "clutter/clutter-frame-clock.h"
#include "clutter/clutter-frame.h"
-#include "clutter/clutter-grab.h"
+#include "clutter/clutter-grab-private.h"
#include "clutter/clutter-input-device-private.h"
#include "clutter/clutter-input-only-actor.h"
#include "clutter/clutter-main.h"
@@ -138,18 +138,6 @@ typedef struct _ClutterStagePrivate
guint actor_needs_immediate_relayout : 1;
} ClutterStagePrivate;
-struct _ClutterGrab
-{
- grefcount ref_count;
- ClutterStage *stage;
-
- ClutterActor *actor;
- gboolean owns_actor;
-
- ClutterGrab *prev;
- ClutterGrab *next;
-};
-
enum
{
PROP_0,
@@ -3882,44 +3870,6 @@ clutter_stage_notify_grab (ClutterStage *stage,
clutter_stage_notify_grab_on_key_focus (stage, cur_actor, old_actor);
}
-ClutterGrab *
-clutter_grab_ref (ClutterGrab *grab)
-{
- g_ref_count_inc (&grab->ref_count);
- return grab;
-}
-
-void
-clutter_grab_unref (ClutterGrab *grab)
-{
- if (g_ref_count_dec (&grab->ref_count))
- {
- clutter_grab_dismiss (grab);
- g_free (grab);
- }
-}
-
-G_DEFINE_BOXED_TYPE (ClutterGrab, clutter_grab,
- clutter_grab_ref, clutter_grab_unref)
-
-static ClutterGrab *
-clutter_grab_new (ClutterStage *stage,
- ClutterActor *actor,
- gboolean owns_actor)
-{
- ClutterGrab *grab;
-
- grab = g_new0 (ClutterGrab, 1);
- g_ref_count_init (&grab->ref_count);
- grab->stage = stage;
-
- grab->actor = actor;
- if (owns_actor)
- grab->owns_actor = TRUE;
-
- return grab;
-}
-
static ClutterGrab *
clutter_stage_grab_full (ClutterStage *stage,
ClutterActor *actor,
diff --git a/clutter/clutter/meson.build b/clutter/clutter/meson.build
index d393d2c8a..55aaa30a4 100644
--- a/clutter/clutter/meson.build
+++ b/clutter/clutter/meson.build
@@ -118,6 +118,7 @@ clutter_sources = [
'clutter-frame-clock.c',
'clutter-frame.c',
'clutter-gesture-action.c',
+ 'clutter-grab.c',
'clutter-graphene.c',
'clutter-grid-layout.c',
'clutter-image.c',
diff --git a/src/compositor/meta-window-drag.c b/src/compositor/meta-window-drag.c
index 05e5ba671..53b81c348 100644
--- a/src/compositor/meta-window-drag.c
+++ b/src/compositor/meta-window-drag.c
@@ -178,7 +178,7 @@ meta_window_drag_finalize (GObject *object)
hide_tile_preview (window_drag);
g_clear_pointer (&window_drag->handler, clutter_actor_destroy);
- g_clear_pointer (&window_drag->grab, clutter_grab_unref);
+ g_clear_object (&window_drag->grab);
g_clear_object (&window_drag->effective_grab_window);
G_OBJECT_CLASS (meta_window_drag_parent_class)->finalize (object);
diff --git a/src/tests/clutter/conform/grab.c b/src/tests/clutter/conform/grab.c
index 1eb239832..c62eea6fb 100644
--- a/src/tests/clutter/conform/grab.c
+++ b/src/tests/clutter/conform/grab.c
@@ -237,7 +237,7 @@ grab_under_pointer (void)
event_log_compare ((EventLog *) &grab_log, data.events);
clutter_grab_dismiss (grab);
- clutter_grab_unref (grab);
+ g_clear_object (&grab);
event_log_compare ((EventLog *) &ungrab_log, data.events);
test_data_shutdown (&data);
@@ -264,7 +264,7 @@ grab_under_pointers_parent (void)
event_log_compare ((EventLog *) &grab_log, data.events);
clutter_grab_dismiss (grab);
- clutter_grab_unref (grab);
+ g_clear_object (&grab);
event_log_compare ((EventLog *) &ungrab_log, data.events);
test_data_shutdown (&data);
@@ -295,7 +295,7 @@ grab_outside_pointer (void)
event_log_compare ((EventLog *) &grab_log, data.events);
clutter_grab_dismiss (grab);
- clutter_grab_unref (grab);
+ g_clear_object (&grab);
event_log_compare ((EventLog *) &ungrab_log, data.events);
test_data_shutdown (&data);
@@ -320,7 +320,7 @@ grab_stage (void)
event_log_compare ((EventLog *) &grab_log, data.events);
clutter_grab_dismiss (grab);
- clutter_grab_unref (grab);
+ g_clear_object (&grab);
event_log_compare ((EventLog *) &ungrab_log, data.events);
test_data_shutdown (&data);
@@ -364,11 +364,11 @@ grab_stack_1 (void)
/* Dismiss orderly */
clutter_grab_dismiss (grab2);
- clutter_grab_unref (grab2);
+ g_clear_object (&grab2);
event_log_compare ((EventLog *) &ungrab2_log, data.events);
clutter_grab_dismiss (grab1);
- clutter_grab_unref (grab1);
+ g_clear_object (&grab1);
event_log_compare ((EventLog *) &ungrab1_log, data.events);
test_data_shutdown (&data);
@@ -414,11 +414,11 @@ grab_stack_2 (void)
/* Dismiss orderly */
clutter_grab_dismiss (grab2);
- clutter_grab_unref (grab2);
+ g_clear_object (&grab2);
event_log_compare ((EventLog *) &ungrab2_log, data.events);
clutter_grab_dismiss (grab1);
- clutter_grab_unref (grab1);
+ g_clear_object (&grab1);
event_log_compare ((EventLog *) &ungrab1_log, data.events);
test_data_shutdown (&data);
@@ -462,11 +462,11 @@ grab_unordered_ungrab_1 (void)
/* Dismiss disorderly */
clutter_grab_dismiss (grab1);
- clutter_grab_unref (grab1);
+ g_clear_object (&grab1);
event_log_compare ((EventLog *) &ungrab1_log, data.events);
clutter_grab_dismiss (grab2);
- clutter_grab_unref (grab2);
+ g_clear_object (&grab2);
event_log_compare ((EventLog *) &ungrab2_log, data.events);
test_data_shutdown (&data);
@@ -508,11 +508,11 @@ grab_unordered_ungrab_2 (void)
/* Dismiss disorderly */
clutter_grab_dismiss (grab1);
- clutter_grab_unref (grab1);
+ g_clear_object (&grab1);
event_log_compare ((EventLog *) &ungrab1_log, data.events);
clutter_grab_dismiss (grab2);
- clutter_grab_unref (grab2);
+ g_clear_object (&grab2);
event_log_compare ((EventLog *) &ungrab2_log, data.events);
test_data_shutdown (&data);
@@ -533,7 +533,7 @@ grab_key_focus_in_grab (void)
g_assert_true (clutter_actor_has_key_focus (data.b));
clutter_grab_dismiss (grab);
- clutter_grab_unref (grab);
+ g_clear_object (&grab);
g_assert_true (clutter_actor_has_key_focus (data.b));
test_data_shutdown (&data);
@@ -554,7 +554,7 @@ grab_key_focus_outside_grab (void)
g_assert_false (clutter_actor_has_key_focus (data.b));
clutter_grab_dismiss (grab);
- clutter_grab_unref (grab);
+ g_clear_object (&grab);
g_assert_true (clutter_actor_has_key_focus (data.b));
test_data_shutdown (&data);
@@ -643,7 +643,7 @@ grab_input_only (void)
g_main_context_iteration (NULL, TRUE);
event_log_compare ((EventLog *) &grab2_log, data.events);
- clutter_grab_unref (grab);
+ g_clear_object (&grab);
event_log_compare ((EventLog *) &grab3_log, data.events);
clutter_virtual_input_device_notify_button (pointer,