From 9f671e6ddb8e98c92736025ddf3670a4a6e1eb17 Mon Sep 17 00:00:00 2001
From: Cedric BAIL <cedric@ddlm.me>
Date: Wed, 11 May 2022 17:01:52 -0600
Subject: [PATCH] Use Windows MessageBox API for error when GLFW can't create a
 Window.

---
 internal/driver/glfw/driver.go            |  2 +-
 internal/driver/glfw/driver_notwindows.go | 10 +++++
 internal/driver/glfw/driver_windows.go    | 50 +++++++++++++++++++++++
 3 files changed, 61 insertions(+), 1 deletion(-)
 create mode 100644 internal/driver/glfw/driver_notwindows.go
 create mode 100644 internal/driver/glfw/driver_windows.go

diff --git a/internal/driver/glfw/driver.go b/internal/driver/glfw/driver.go
index 0314c006ec..5c7da9fcca 100644
--- a/internal/driver/glfw/driver.go
+++ b/internal/driver/glfw/driver.go
@@ -141,7 +141,7 @@ func (d *gLDriver) windowList() []fyne.Window {
 }
 
 func (d *gLDriver) initFailed(msg string, err error) {
-	fyne.LogError(msg, err)
+	logError(msg, err)
 
 	run.Lock()
 	if !run.flag {
diff --git a/internal/driver/glfw/driver_notwindows.go b/internal/driver/glfw/driver_notwindows.go
new file mode 100644
index 0000000000..17bcb49f46
--- /dev/null
+++ b/internal/driver/glfw/driver_notwindows.go
@@ -0,0 +1,10 @@
+//go:build !windows
+// +build !windows
+
+package glfw
+
+import "fyne.io/fyne/v2"
+
+func logError(msg string, err error) {
+	fyne.LogError(msg, err)
+}
diff --git a/internal/driver/glfw/driver_windows.go b/internal/driver/glfw/driver_windows.go
new file mode 100644
index 0000000000..51337ec256
--- /dev/null
+++ b/internal/driver/glfw/driver_windows.go
@@ -0,0 +1,50 @@
+package glfw
+
+import (
+	"fmt"
+	"runtime"
+	"syscall"
+	"unsafe"
+)
+
+type MB uint32
+
+const (
+	MB_OK        MB = 0x0000_0000
+	MB_ICONERROR MB = 0x0000_0010
+)
+
+func toNativePtr(s string) *uint16 {
+	pstr, err := syscall.UTF16PtrFromString(s)
+	if err != nil {
+		panic(fmt.Sprintf("toNativePtr() failed \"%s\": %s", s, err))
+	}
+	return pstr
+}
+
+// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw
+func messageBoxError(text, caption string) {
+	user32 := syscall.NewLazyDLL("user32.dll")
+	MessageBox := user32.NewProc("MessageBoxW")
+
+	uType := MB_OK | MB_ICONERROR
+
+	syscall.Syscall6(MessageBox.Addr(), 4,
+		uintptr(unsafe.Pointer(nil)), uintptr(unsafe.Pointer(toNativePtr(text))),
+		uintptr(unsafe.Pointer(toNativePtr(caption))), uintptr(uType),
+		0, 0)
+}
+
+func logError(msg string, err error) {
+	text := fmt.Sprintf("Fyne error: %v", msg)
+	if err != nil {
+		text = text + fmt.Sprintf("\n  Cause:%v", err)
+	}
+
+	_, file, line, ok := runtime.Caller(1)
+	if ok {
+		text = text + fmt.Sprintf("\n  At: %s:%d", file, line)
+	}
+
+	messageBoxError(text, "Fyne Error")
+}