mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-15 12:53:41 +00:00
Keep Linux WebViews on one persistent GTK UI thread
This commit is contained in:
1 parent
a5eaa6b528
commit
e2601ea9fa
3 files changed
+60
-2
No files matched your search
@@ -0,0 +1,47 @@
|
|||||||
|
//go:build linux && cgo
|
||||||
|
|
||||||
|
package goprovider
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo pkg-config: gtk+-3.0
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
static void pumpGTK(void) {
|
||||||
|
// Bound each batch so Go creation/removal requests cannot be starved.
|
||||||
|
for (int i = 0; i < 64 && g_main_context_pending(NULL); ++i)
|
||||||
|
g_main_context_iteration(NULL, FALSE);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var gtkThreadOnce sync.Once
|
||||||
|
var gtkThreadTasks = make(chan func())
|
||||||
|
|
||||||
|
func RunMainThreadLoop(run func() int) int { return run() }
|
||||||
|
|
||||||
|
func postMainThreadTask(task func()) bool {
|
||||||
|
gtkThreadOnce.Do(func() {
|
||||||
|
go func() {
|
||||||
|
runtime.LockOSThread()
|
||||||
|
// WebKit must always use its original UI thread, including after
|
||||||
|
// the last page closes. A page cannot stop this shared event loop.
|
||||||
|
ticker := time.NewTicker(10 * time.Millisecond)
|
||||||
|
defer ticker.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case task := <-gtkThreadTasks:
|
||||||
|
task()
|
||||||
|
case <-ticker.C:
|
||||||
|
}
|
||||||
|
C.pumpGTK()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
})
|
||||||
|
gtkThreadTasks <- task
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build !darwin
|
//go:build !darwin && (!linux || !cgo)
|
||||||
|
|
||||||
package goprovider
|
package goprovider
|
||||||
|
|
||||||
|
|||||||
@@ -135,12 +135,18 @@ func (p *pageWrapper) start() error {
|
|||||||
if err := w.Bind(p.callbackName, func(payload string) error {
|
if err := w.Bind(p.callbackName, func(payload string) error {
|
||||||
return p.handleCallback(payload)
|
return p.handleCallback(payload)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
w.Destroy()
|
||||||
p.ready <- err
|
p.ready <- err
|
||||||
|
close(p.done)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
applyWindowOptions(w, p.opts)
|
applyWindowOptions(w, p.opts)
|
||||||
w.SetHtml(buildBootstrapHTML(p.callbackName, p.readyID))
|
w.SetHtml(buildBootstrapHTML(p.callbackName, p.readyID))
|
||||||
|
if runtimepkg.GOOS == "linux" {
|
||||||
|
// All GTK pages share the process-wide event loop below.
|
||||||
|
return
|
||||||
|
}
|
||||||
w.Run()
|
w.Run()
|
||||||
w.Destroy()
|
w.Destroy()
|
||||||
close(p.done)
|
close(p.done)
|
||||||
@@ -326,7 +332,12 @@ func (p *pageWrapper) Close() error {
|
|||||||
// the quit message lands on the correct queue.
|
// the quit message lands on the correct queue.
|
||||||
terminateDone := make(chan struct{})
|
terminateDone := make(chan struct{})
|
||||||
w.Dispatch(func() {
|
w.Dispatch(func() {
|
||||||
w.Terminate()
|
if runtimepkg.GOOS == "linux" {
|
||||||
|
w.Destroy()
|
||||||
|
close(p.done)
|
||||||
|
} else {
|
||||||
|
w.Terminate()
|
||||||
|
}
|
||||||
close(terminateDone)
|
close(terminateDone)
|
||||||
})
|
})
|
||||||
<-terminateDone
|
<-terminateDone
|
||||||
|
|||||||
Reference in new issue
Block a user