e8686fec5719c6f886bdaf64ad03a0931f998448 — Drew DeVault 8 months ago 53b8649
Handle pointer events for subsurfaces/popups
6 files changed, 76 insertions(+), 7 deletions(-)

M godotston/Surface.gd
M register_types.cpp
M wlr_surface.cpp
M wlr_surface.h
M wlr_xdg_shell.cpp
M wlr_xdg_shell.h
M godotston/Surface.gd => godotston/Surface.gd +11 -6
@@ 98,8 98,12 @@ func input_event_passthrough(event):
 	var notify_frame = false
 	if event is InputEventMouseMotion:
 		var position = get_surface_coords(to_local(event.position))
-		seat.pointer_notify_motion(position.x, position.y)
-		notify_frame = true
+		var surface = xdg_surface.surface_at(position.x, position.y)
+		if surface != null:
+			seat.pointer_notify_enter(surface.get_surface(),
+					surface.get_sub_x(), surface.get_sub_y())
+			seat.pointer_notify_motion(surface.get_sub_x(), surface.get_sub_y())
+			notify_frame = true
 	if event is InputEventMouseButton:
 		seat.pointer_notify_button(event.button_index, event.pressed)
 		notify_frame = true


@@ 124,8 128,9 @@ func _integrate_forces(state):
 	state.set_linear_velocity(lv)
 
 func _on_RigidBody2D_mouse_entered():
-	var position = get_surface_coords(to_local(get_viewport().get_mouse_position()))
-	# TODO: Find subsurface
-	var surface = xdg_surface.get_wlr_surface()
+	var position = get_surface_coords(
+			to_local(get_viewport().get_mouse_position()))
+	var surface = xdg_surface.surface_at(position.x, position.y)
 	if surface != null:
-		seat.pointer_notify_enter(surface, position.x, position.y)
+		seat.pointer_notify_enter(surface.get_surface(),
+				surface.get_sub_x(), surface.get_sub_y())

M register_types.cpp => register_types.cpp +1 -0
@@ 17,6 17,7 @@ void register_gdwlroots_types() {
 	ClassDB::register_class<WlrOutput>();
 	ClassDB::register_class<WlrSeat>();
 	ClassDB::register_class<WlrSurface>();
+	ClassDB::register_class<WlrSurfaceAtResult>();
 	ClassDB::register_class<WlrSurfaceState>();
 	ClassDB::register_class<WlrXdgShell>();
 	ClassDB::register_class<WlrXdgSurface>();

M wlr_surface.cpp => wlr_surface.cpp +33 -1
@@ 107,10 107,42 @@ WlrSurface::WlrSurface(struct wlr_surface *surface) {
 }
 
 WlrSurface *WlrSurface::from_wlr_surface(struct wlr_surface *surface) {
+	if (!surface) {
+		return NULL;
+	}
 	if (surface->data) {
 		auto s = (WlrSurface *)surface->data;
-		wlr_log(WLR_DEBUG, "Found surface %p for %p", s, surface);
 		return s;
 	}
 	return new WlrSurface(surface);
 }
+
+WlrSurface *WlrSurfaceAtResult::get_surface() {
+	return surface;
+}
+
+double WlrSurfaceAtResult::get_sub_x() {
+	return sub_x;
+}
+
+double WlrSurfaceAtResult::get_sub_y() {
+	return sub_y;
+}
+
+void WlrSurfaceAtResult::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("get_sub_x"), &WlrSurfaceAtResult::get_sub_x);
+	ClassDB::bind_method(D_METHOD("get_sub_y"), &WlrSurfaceAtResult::get_sub_y);
+	ClassDB::bind_method(D_METHOD("get_surface"),
+			&WlrSurfaceAtResult::get_surface);
+}
+
+WlrSurfaceAtResult::WlrSurfaceAtResult() {
+	/* Not used */
+}
+
+WlrSurfaceAtResult::WlrSurfaceAtResult(WlrSurface *surface,
+		double sub_x, double sub_y) {
+	this->surface = surface;
+	this->sub_x = sub_x;
+	this->sub_y = sub_y;
+}

M wlr_surface.h => wlr_surface.h +20 -0
@@ 52,4 52,24 @@ public:
 	void send_frame_done();
 };
 
+class WlrSurfaceAtResult : public Reference {
+	GDCLASS(WlrSurfaceAtResult, Reference);
+
+	WlrSurface *surface;
+	double sub_x, sub_y;
+
+protected:
+	static void _bind_methods();
+
+	/* Necessary for Object */
+	WlrSurfaceAtResult();
+
+public:
+	WlrSurface *get_surface();
+	double get_sub_x();
+	double get_sub_y();
+
+	WlrSurfaceAtResult(WlrSurface *surface, double sub_x, double sub_y);
+};
+
 #endif

M wlr_xdg_shell.cpp => wlr_xdg_shell.cpp +10 -0
@@ 106,6 106,14 @@ void WlrXdgSurface::for_each_surface(Variant func) {
 			wlr_xdg_surface, for_each_surface_iter, fn.ptr());
 }
 
+WlrSurfaceAtResult *WlrXdgSurface::surface_at(double sx, double sy) {
+	double sub_x, sub_y;
+	struct wlr_surface *result = wlr_xdg_surface_surface_at(
+			wlr_xdg_surface, sx, sy, &sub_x, &sub_y);
+	return new WlrSurfaceAtResult(
+			WlrSurface::from_wlr_surface(result), sub_x, sub_y);
+}
+
 void WlrXdgSurface::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_role"), &WlrXdgSurface::get_role);
 	ClassDB::bind_method(D_METHOD("get_xdg_toplevel"),


@@ 118,6 126,8 @@ void WlrXdgSurface::_bind_methods() {
 			&WlrXdgSurface::get_wlr_surface);
 	ClassDB::bind_method(D_METHOD("for_each_surface", "func"),
 			&WlrXdgSurface::for_each_surface);
+	ClassDB::bind_method(D_METHOD("surface_at", "sx", "sy"),
+			&WlrXdgSurface::surface_at);
 
 	BIND_ENUM_CONSTANT(XDG_SURFACE_ROLE_NONE);
 	BIND_ENUM_CONSTANT(XDG_SURFACE_ROLE_TOPLEVEL);

M wlr_xdg_shell.h => wlr_xdg_shell.h +1 -0
@@ 128,6 128,7 @@ public:
 	WlrSurface *get_wlr_surface() const;
 	Rect2 get_geometry();
 	void for_each_surface(Variant func);
+	WlrSurfaceAtResult *surface_at(double sx, double sy);
 
 	static WlrXdgSurface *from_wlr_xdg_surface(
 			struct wlr_xdg_surface *xdg_surface);