How can I make a custom gizmos to set the origin
I propose to do it with a modal operator, not a gizmo:

The principles:
Run the operator (search it using its name F3 and type set origin on boundings). Then the operator creates a sphere to display it as green point as shown above. And it register a draw handler in the 3D view, in order to display the boundings and the small green spheres.
The operator is a modal so it will continue until 'FINISHED' or  if 'CANCELED' is returned. In this case, it returns 'CANCELED' when the ESC key is hit. Now for each modal call, it does the following:

Get the view location
Get the mouse cursor location
Get the active object

And from that the bounds of the object are going to be calculated in order to display a black subdivided mesh (some kind of lattice) as well as figuring out which point to highlight in green.
Here we can use the dot product the view location/mouse location with view location/bouding point location and keep the best one. When all that done, validating the point where to set the object origin:
If you left-click (LMB) then the previously identified bounding point will be used to change the origin. It seems to work fine independently of the mode (object, edit, etc.) but I've not tested them all.
You can stop the operator using ESC. Here is the code (some comments, just ask for more information if necessary):
import bpy
import bmesh
import gpu
from gpu_extras.batch import batch_for_shader
from mathutils import Vector
from bpy_extras.view3d_utils import region_2d_to_location_3d

# indices to make cube edges from boundings
bounding_indices = (
    (0, 1), (1, 2), (2, 3), (3, 4),
    (4, 5), (5, 6), (6, 7), (7, 0),
    (8, 1), (8, 3), (8, 5), (8, 7),
    (9, 10), (10, 11), (11, 12), (12, 13),
    (13, 14), (14, 15), (15, 16), (16, 9),
    (17, 10), (17, 12), (17, 14), (17, 16),
    (18, 19), (19, 20), (20, 21), (21, 22),
    (22, 23), (23, 24), (24, 25), (25, 18),
    (26, 19), (26, 21), (26, 23), (26, 25),
    (27, 28), (28, 29), (29, 30), (30, 31),
    (31, 32), (32, 33), (33, 34), (34, 27),
    (35, 28), (35, 30), (35, 32), (35, 34),
    (36, 37), (37, 38), (38, 39), (39, 40),
    (40, 41), (41, 42), (42, 43), (43, 36),
    (44, 37), (44, 39), (44, 41), (44, 43),
    (45, 46), (46, 47), (47, 48), (48, 49),
    (49, 50), (50, 51), (51, 52), (52, 45),
    (53, 46), (53, 48), (53, 50), (53, 52))

# Cut a bounding face in half
def bounding_cuts(b_box, result, indices):
    p0 = Vector(b_box[indices[0]])
    p1 = Vector(b_box[indices[1]])
    p2 = Vector(b_box[indices[2]])
    p3 = Vector(b_box[indices[3]])
    result.append(p0)
    result.append((p0 + p1) / 2.0)
    result.append(p1)
    result.append((p1 + p2) / 2.0)
    result.append(p2)
    result.append((p2 + p3) / 2.0)
    result.append(p3)
    result.append((p3 + p0) / 2.0)
    result.append((p0 + p1 + p2 + p3) / 4.0)

# Get half parts of bounding box
def bounding_points(obj):
    b_box = obj.bound_box[:]
    result = []
    bounding_cuts(b_box, result, [0, 1, 2, 3])
    bounding_cuts(b_box, result, [4, 5, 1, 0])
    bounding_cuts(b_box, result, [7, 6, 5, 4])
    bounding_cuts(b_box, result, [3, 2, 6, 7])
    bounding_cuts(b_box, result, [5, 6, 2, 1])
    bounding_cuts(b_box, result, [3, 0, 4, 7])
    return result

def draw_callback(self, context):
    obj = context.active_object
    if obj and obj.type == 'MESH':
        # translate bounding in world co
        mat = obj.matrix_world 
        obj_coords = [mat @ Vector(c) for c in bounding_points(obj)]

        # draw boudings        
        shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
        shader.bind()
        batch = batch_for_shader(shader, 'LINES', {&quot;pos&quot;: obj_coords}, indices=bounding_indices)
        shader.uniform_float(&quot;color&quot;, (0, 0, 0, 0.5))
        batch.draw(shader)

        # if close enough to a corner        
        if self.highlight != -1:
            # draw a small sphere on it        
            scale = self.highlight_distance / 100.0
            base_coord = obj_coords[self.highlight]
            h_coords = [base_coord + (Vector(c) * scale) for c in self.highlight_coords]
            batch = batch_for_shader(shader, 'TRIS', {&quot;pos&quot;: h_coords})
            shader.uniform_float(&quot;color&quot;, (0, 1, 0, 0.5))
            batch.draw(shader)

class ModalOperator(bpy.types.Operator):
    &quot;&quot;&quot;Set origin with the mouse&quot;&quot;&quot;
    bl_idname = &quot;object.set_origin_on_boundings&quot;
    bl_label = &quot;Set origin on boundings&quot;
     
    # Create highlight (corner) geometry
    def create_highlight(self):
        # it is based on UV sphere triangulated for the GPU rendering
        bm = bmesh.new()
        bmesh.ops.create_uvsphere(bm, u_segments= 6, v_segments=4, diameter=1)
        bmesh.ops.triangulate(bm, faces=bm.faces)
        self.highlight_coords = [v.co.to_tuple() for f in bm.faces for v in f.verts]

    # Update object information     
    def update_object(self, context, obj, view_loc, mouse_loc):
        prev_highlight = self.highlight
        self.highlight = -1
        if obj and obj.type == 'MESH':
            self.target = obj.name

            # Find the closest corner using a dot product from the view
            mat = obj.matrix_world 
            obj_coords = [mat @ Vector(c) for c in bounding_points(obj)]
            
            axis = (mouse_loc - view_loc).normalized()
            angles = [axis.dot((c - view_loc).normalized()) for c in obj_coords]
            min_angle = max(angles)

            # and keep it if close enough
            if min_angle &gt; 0.999:
                self.highlight = angles.index(min_angle)
                self.highlight_distance = (view_loc - obj_coords[self.highlight]).length
            else:
                self.highlight = -1

            if self.highlight != prev_highlight:
                self.redraw(context)                

    # Mouse location in 3D 
    def mouse_location(self, context, event):
        x, y = event.mouse_region_x, event.mouse_region_y
        loc = region_2d_to_location_3d(context.region, context.space_data.region_3d, (x, y), (0, 0, 0))
        return loc

    # View location in 3D
    def view_location(self, context):
        camera_info = context.space_data.region_3d.view_matrix.inverted()
        return camera_info.translation

    # Move the object origin to the wanted corner
    def set_origin(self, context, obj, index):
        mat = obj.matrix_world 
        loc = mat @ Vector(bounding_points(obj)[index])

        cursor_location = context.scene.cursor.location.copy()

        mode = obj.mode
        if mode != 'OBJECT':
            bpy.ops.object.mode_set( mode = 'OBJECT' )

        bpy.context.scene.cursor.location = loc
        bpy.ops.object.origin_set(type='ORIGIN_CURSOR')

        if mode != 'OBJECT':
            bpy.ops.object.mode_set( mode = mode )

        context.scene.cursor.location = cursor_location

    # Force the 3D view to redraw when needed
    def redraw(self, context):
        bpy.ops.wm.redraw_timer(type='DRAW_SWAP', iterations=1)
        
    def modal(self, context, event):

        mouse_loc = self.mouse_location(context, event)
        view_loc = self.view_location(context)
        obj = context.active_object

        self.update_object(context, obj, view_loc, mouse_loc)
        
        # when left click, set the origin if a highlight point is known
        if event.type in {'LEFTMOUSE'}:
            if self.highlight != -1:
                self.set_origin(context, obj, self.highlight)
                return {'RUNNING_MODAL'} #We don't want the click to be taken into account further

        # esc is used to quit and remove the draw handler
        elif event.type in {'ESC'}:
            bpy.types.SpaceView3D.draw_handler_remove(self.handle, 'WINDOW')
            self.redraw(context)
            return {'CANCELLED'}

        return {'PASS_THROUGH'}

    def invoke(self, context, event):
        self.highlight = -1
        if context.area.type == 'VIEW_3D':
            self.create_highlight()
            args = (self, context)
            self.handle = bpy.types.SpaceView3D.draw_handler_add(draw_callback, args, 'WINDOW', 'POST_VIEW')
            context.window_manager.modal_handler_add(self)
            self.redraw(context)
            return {'RUNNING_MODAL'}
        return {'FINISHED'}

keymaps = []

def register():
    bpy.utils.register_class(ModalOperator)

    wm = bpy.context.window_manager
    km = wm.keyconfigs.addon.keymaps.new(name=&quot;3D View&quot;, space_type=&quot;VIEW_3D&quot;)

    # Ctrl+Shif+B as shortcut
    kmi = km.keymap_items.new(ModalOperator.bl_idname, 'B', 'PRESS', ctrl=True, shift=True)

    keymaps.append((km, kmi))

def unregister():
    for km, kmi in keymaps:
        km.keymap_items.remove(kmi)
    keymaps.clear()

    bpy.utils.unregister_class(ModalOperator)


if __name__ == &quot;__main__&quot;:
    register()

    # test call
    bpy.ops.object.set_origin_on_boundings('INVOKE_DEFAULT')


Run the script and use ctrlshiftB to activate the operator and esc to stop it.
Note: I'm still using right click select, so I've set the trigger that position the origin on the left click. You may want to change that.