diff --git a/callback.go b/callback.go new file mode 100644 index 00000000..16ca671f --- /dev/null +++ b/callback.go @@ -0,0 +1,38 @@ +package gocv + +import ( + "sync" +) + +var CGOCallback = callback{ + fns: make(map[int]func(...interface{})), +} + +type callback struct { + mu sync.Mutex + index int + fns map[int]func(...interface{}) +} + +func (n *callback) Register(fn func(args ...interface{})) int { + n.mu.Lock() + defer n.mu.Unlock() + n.index++ + for n.fns[n.index] != nil { + n.index++ + } + n.fns[n.index] = fn + return n.index +} + +func (n *callback) Lookup(i int) func(...interface{}) { + n.mu.Lock() + defer n.mu.Unlock() + return n.fns[i] +} + +func (n *callback) Unregister(i int) { + n.mu.Lock() + defer n.mu.Unlock() + delete(n.fns, i) +} diff --git a/go.mod b/go.mod index c00a0829..acb0abc4 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module gocv.io/x/gocv -go 1.13 \ No newline at end of file +go 1.13 diff --git a/highgui.cpp b/highgui.cpp index db31181b..71d79a32 100644 --- a/highgui.cpp +++ b/highgui.cpp @@ -57,6 +57,11 @@ struct Rects Window_SelectROIs(const char* winname, Mat img) { return ret; } +// MouseCallback +void Window_SetMouseCallback(const char* winname, mouse_callback callback, void* userdata) { + cv::setMouseCallback(winname, callback, userdata); +} + // Trackbar void Trackbar_Create(const char* winname, const char* trackname, int max) { cv::createTrackbar(trackname, winname, NULL, max); diff --git a/highgui.go b/highgui.go index 84b8f6c5..edf806a5 100644 --- a/highgui.go +++ b/highgui.go @@ -194,6 +194,31 @@ func (w *Window) ResizeWindow(width, height int) { C.Window_Resize(cName, C.int(width), C.int(height)) } +//export go_MouseCallback +func go_MouseCallback(event C.int, x C.int, y C.int, flags C.int, userdata unsafe.Pointer) { + CGOCallback.Lookup(int(*(*C.int)(userdata)))(event, x, y, flags) +} + +// Sets mouse handler for the specified window. +// +// For further details, please see: +// https://docs.opencv.org/4.2.0/d7/dfc/group__highgui.html#ga89e7806b0a616f6f1d502bd8c183ad3e +// +func (w *Window) SetMouseCallback(onMouse MouseCallback) { + cName := C.CString(w.name) + defer C.free(unsafe.Pointer(cName)) + + fn := C.int(CGOCallback.Register(func(args ...interface{}) { + onMouse( + MouseEventType(args[0].(C.int)), + int(args[1].(C.int)), + int(args[2].(C.int)), + MouseEventFlag(args[3].(C.int)), + ) + })) + C.Window_SetMouseCallback(cName, (C.mouse_callback)(C.go_MouseCallback), unsafe.Pointer(&fn)) +} + // SelectROI selects a Region Of Interest (ROI) on the given image. // It creates a window and allows user to select a ROI using mouse. // @@ -321,3 +346,33 @@ func (t *Trackbar) SetMax(pos int) { C.Trackbar_SetMax(cName, tName, C.int(pos)) } + +type MouseCallback func(event MouseEventType, x, y int, flags MouseEventFlag) + +type MouseEventType int + +const ( + MouseEventMove MouseEventType = iota + MouseEventLeftButtonDown + MouseEventRightButtonDown + MouseEventMiddleButtonDown + MouseEventLeftButtonUp + MouseEventRightButtonUp + MouseEventMiddleButtonUp + MouseEventLeftButtonDoubleClick + MouseEventRightButtonDoubleClick + MouseEventMiddleButtonDoubleClick + MouseEventMouseWheel + MouseEventHorizontalMouseWheel +) + +type MouseEventFlag int + +const ( + MouseEventFlagLeftButton MouseEventFlag = 1 << iota + MouseEventFlagRightButton + MouseEventFlagMiddleButton + MouseEventFlagCtrlKey + MouseEventFlagShiftKey + MouseEventFlagAltKey +) diff --git a/highgui_gocv.h b/highgui_gocv.h index 58d97260..3c9427ea 100644 --- a/highgui_gocv.h +++ b/highgui_gocv.h @@ -28,6 +28,12 @@ void Trackbar_SetPos(const char* winname, const char* trackname, int pos); void Trackbar_SetMin(const char* winname, const char* trackname, int pos); void Trackbar_SetMax(const char* winname, const char* trackname, int pos); +// MouseCallback +typedef void (*mouse_callback)(int event, int x, int y, int flags, void* userdata); +void Window_SetMouseCallback(const char* winname, mouse_callback callback, void* userdata); +extern void go_MouseCallback(int event, int x, int y, int flags, void* userdata); + + #ifdef __cplusplus } #endif diff --git a/highgui_test.go b/highgui_test.go index 9965624f..70b2e410 100644 --- a/highgui_test.go +++ b/highgui_test.go @@ -94,3 +94,10 @@ func TestTrackbar(t *testing.T) { t.Error("Trackbar pos should have been 50") } } + +func TestSetMouseCallback(t *testing.T) { + window := NewWindow("mouse callback") + defer window.Close() + + window.SetMouseCallback(func(event MouseEventType, x, y int, flags MouseEventFlag) {}) +}