shiny/driver/internal/win32: Close window correctly to be able to re-open one after closing
Closing and re-opening a window caused an error at RegisterClassW call (class already registered). This fixes the problem by correctly unregistering the class.
Change-Id: Ie6e45354096bc1245776264bec9be0c86f53d79c
GitHub-Last-Rev: 34780c27353a35240a46fe49e3b605238d8fae57
GitHub-Pull-Request: golang/exp#6
Reviewed-on: https://go-review.googlesource.com/c/exp/+/171697
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/shiny/driver/internal/win32/win32.go b/shiny/driver/internal/win32/win32.go
index deaeb37..6925085 100644
--- a/shiny/driver/internal/win32/win32.go
+++ b/shiny/driver/internal/win32/win32.go
@@ -367,6 +367,7 @@
}
const windowClass = "shiny_Window"
+const screenWindowClass = "shiny_ScreenWindow"
func initWindowClass() (err error) {
wcname, err := syscall.UTF16PtrFromString(windowClass)
@@ -385,8 +386,17 @@
return err
}
+func closeWindowClass() (err error) {
+ wcname, err := syscall.UTF16PtrFromString(windowClass)
+ if err != nil {
+ return err
+ }
+ _UnregisterClass(wcname, hThisInstance)
+
+ return nil
+}
+
func initScreenWindow() (err error) {
- const screenWindowClass = "shiny_ScreenWindow"
swc, err := syscall.UTF16PtrFromString(screenWindowClass)
if err != nil {
return err
@@ -419,6 +429,20 @@
return nil
}
+func closeScreenWindow() (err error) {
+ // first destroy window
+ _DestroyWindow(screenHWND)
+
+ // then unregister class
+ swc, err := syscall.UTF16PtrFromString(screenWindowClass)
+ if err != nil {
+ return err
+ }
+ _UnregisterClass(swc, hThisInstance)
+
+ return nil
+}
+
var (
hDefaultIcon syscall.Handle
hDefaultCursor syscall.Handle
@@ -461,13 +485,16 @@
}
defer func() {
// TODO(andlabs): log an error if this fails?
- _DestroyWindow(screenHWND)
- // TODO(andlabs): unregister window class
+ closeScreenWindow()
}()
if err := initWindowClass(); err != nil {
return err
}
+ defer func() {
+ // TODO(andlabs): log an error if this fails?
+ closeWindowClass()
+ }()
// Prime the pump.
mainCallback = f
diff --git a/shiny/driver/internal/win32/zsyscall_windows.go b/shiny/driver/internal/win32/zsyscall_windows.go
index 1759c01..26999f6 100644
--- a/shiny/driver/internal/win32/zsyscall_windows.go
+++ b/shiny/driver/internal/win32/zsyscall_windows.go
@@ -62,6 +62,7 @@
procScreenToClient = moduser32.NewProc("ScreenToClient")
procToUnicodeEx = moduser32.NewProc("ToUnicodeEx")
procTranslateMessage = moduser32.NewProc("TranslateMessage")
+ procUnregisterClassW = moduser32.NewProc("UnregisterClassW")
)
func GetDC(hwnd syscall.Handle) (dc syscall.Handle, err error) {
@@ -284,3 +285,9 @@
done = r0 != 0
return
}
+
+func _UnregisterClass(lpClassName *uint16, hInstance syscall.Handle) (done bool) {
+ r0, _, _ := syscall.Syscall(procUnregisterClassW.Addr(), 2, uintptr(unsafe.Pointer(lpClassName)), uintptr(hInstance), 0)
+ done = r0 != 0
+ return
+}