github.com/secoba/wails/v2@v2.6.4/internal/frontend/desktop/linux/invoke.go (about) 1 //go:build linux 2 // +build linux 3 4 package linux 5 6 /* 7 #cgo linux pkg-config: gtk+-3.0 8 9 #include <stdio.h> 10 #include "gtk/gtk.h" 11 12 extern gboolean invokeCallbacks(void *); 13 14 static inline void triggerInvokesOnMainThread() { 15 g_idle_add((GSourceFunc)invokeCallbacks, NULL); 16 } 17 */ 18 import "C" 19 import ( 20 "runtime" 21 "sync" 22 "unsafe" 23 24 "golang.org/x/sys/unix" 25 ) 26 27 var ( 28 m sync.Mutex 29 mainTid int 30 dispatchq []func() 31 ) 32 33 func invokeOnMainThread(f func()) { 34 if tryInvokeOnCurrentGoRoutine(f) { 35 return 36 } 37 38 m.Lock() 39 dispatchq = append(dispatchq, f) 40 m.Unlock() 41 42 C.triggerInvokesOnMainThread() 43 } 44 45 func tryInvokeOnCurrentGoRoutine(f func()) bool { 46 m.Lock() 47 mainThreadID := mainTid 48 m.Unlock() 49 50 runtime.LockOSThread() 51 defer runtime.UnlockOSThread() 52 53 if mainThreadID != unix.Gettid() { 54 return false 55 } 56 f() 57 return true 58 } 59 60 //export invokeCallbacks 61 func invokeCallbacks(_ unsafe.Pointer) C.gboolean { 62 runtime.LockOSThread() 63 defer runtime.UnlockOSThread() 64 65 m.Lock() 66 if mainTid == 0 { 67 mainTid = unix.Gettid() 68 } 69 70 q := append([]func(){}, dispatchq...) 71 dispatchq = []func(){} 72 m.Unlock() 73 74 for _, v := range q { 75 v() 76 } 77 return C.G_SOURCE_REMOVE 78 }