You must differenciate the Widget graphics and Widget bounding box.
The bounding box of the widget will be always expressed as a rectangle (pos + size)
So you can draw anything inside the bounding box (recommanded), like you can draw a circle, or even custom shape using image with transparency.
Then you have the collision with the widget: it's handled by the method collide_point(). You can overload it and implement a custom collisiion function using Vector.distance() for a circle, or even use Image.read_pixel (if Image(keep_data=True)) and check alpha part of the color.
And you'll have your result: drawing a custom shape button with adapted collision to the shape.
Mathieu