e410d82680
The built hacked binary segfaults on Linux the moment a native GTK3 dialog (file/folder browse) opens while a GLFW/OpenGL context is live: sqweek/dialog's Linux backend never calls XInitThreads() before gtk_init(), and GLFW's own X11 backend installs a process-wide Xlib error handler that collides with GTK's. Vendor a pinned copy of github.com/sqweek/dialog (New BSD) into modding/sqweek-dialog/ so it can be patched like every other vendored source here: sqweek-dialog-patches/01-xinitthreads.patch adds the missing XInitThreads() call, and hacked-patches/01-use-patched-dialog.patch adds a go.mod replace directive pointing hacked's own sqweek/dialog dependency at that local copy. build-hacked.sh now stages both hacked/ and sqweek-dialog/ into a scratch modding/build/ directory and applies their patch series before compiling, rather than building hacked/ in place; .gitignore picks up that new scratch directory. Also expand modding/README.md: number its existing sections and add a worked "Example: Editing a message" walkthrough covering Static World Data, the Messages window's clipboard-only text editing, saving the Mod Location, and the absolute-path requirement for run.sh's mod-folder argument.
74 lines
2.1 KiB
Go
74 lines
2.1 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
"image/draw"
|
|
|
|
"github.com/skelterjohn/go.wde" // nolint: goimports
|
|
_ "github.com/skelterjohn/go.wde/init"
|
|
"github.com/sqweek/dialog"
|
|
)
|
|
|
|
var loadR, saveR image.Rectangle
|
|
|
|
func events(events <-chan interface{}) {
|
|
for ei := range events {
|
|
switch e := ei.(type) {
|
|
case wde.MouseUpEvent:
|
|
switch e.Which { // nolint: gocritic
|
|
case wde.LeftButton:
|
|
var f string
|
|
var err error
|
|
/* launching dialogs within the event loop like this has
|
|
** a serious problem in practice. On Linux/Windows the
|
|
** dialog is not modal, which means events on the main
|
|
** window still get queued up.
|
|
**
|
|
** But the dialog functions are synchronous, so we don't
|
|
** process any of these events until the dialog closes. End
|
|
** result is if the user clicks multiple times they end up
|
|
** facing multiple dialogs, one after the other.
|
|
**
|
|
** For this reason, it is recommended to launch dialogs
|
|
** in a separate goroutine, and arrange modality via some
|
|
** other mechanism (if desired). */
|
|
if e.Where.In(loadR) {
|
|
f, err = dialog.File().Title("LOL").Filter("Image", "png").Filter("Audio", "mp3").Filter("All files", "*").Load()
|
|
} else {
|
|
f, err = dialog.File().Title("Hilarious").Save()
|
|
}
|
|
fmt.Println(f)
|
|
fmt.Println("Error:", err)
|
|
}
|
|
case wde.KeyTypedEvent:
|
|
switch {
|
|
case e.Glyph == "a":
|
|
fmt.Println(dialog.Message("Is this sentence false?").YesNo())
|
|
case e.Glyph == "b":
|
|
fmt.Println(dialog.Message("R U OK?").Title("Just checking").YesNo())
|
|
case e.Glyph == "c":
|
|
dialog.Message("Operation failed").Error()
|
|
}
|
|
case wde.CloseEvent:
|
|
wde.Stop()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
go func() {
|
|
w, _ := wde.NewWindow(300, 300)
|
|
loadR = image.Rect(0, 0, 300, 150)
|
|
saveR = image.Rect(0, 150, 300, 300)
|
|
w.Show()
|
|
draw.Draw(w.Screen(), loadR, &image.Uniform{color.RGBA{0, 0xff, 0, 0xff}}, image.ZP, draw.Src)
|
|
draw.Draw(w.Screen(), saveR, &image.Uniform{color.RGBA{0xff, 0, 0, 0xff}}, image.ZP, draw.Src)
|
|
w.FlushImage()
|
|
go events(w.EventChan())
|
|
}()
|
|
wde.Run()
|
|
}
|