golang.zx2c4.com/wireguard/windows@v0.5.4-0.20230123132234-dcc0eb72a04b/ui/raise.go (about) 1 /* SPDX-License-Identifier: MIT 2 * 3 * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. 4 */ 5 6 package ui 7 8 import ( 9 "os" 10 "runtime" 11 12 "github.com/lxn/win" 13 "golang.org/x/sys/windows" 14 15 "golang.zx2c4.com/wireguard/windows/l18n" 16 ) 17 18 func raise(hwnd win.HWND) { 19 if win.IsIconic(hwnd) { 20 win.ShowWindow(hwnd, win.SW_RESTORE) 21 } 22 23 win.SetActiveWindow(hwnd) 24 win.SetWindowPos(hwnd, win.HWND_TOPMOST, 0, 0, 0, 0, win.SWP_NOMOVE|win.SWP_NOSIZE|win.SWP_SHOWWINDOW) 25 win.SetForegroundWindow(hwnd) 26 win.SetWindowPos(hwnd, win.HWND_NOTOPMOST, 0, 0, 0, 0, win.SWP_NOMOVE|win.SWP_NOSIZE|win.SWP_SHOWWINDOW) 27 } 28 29 func raiseRemote(hwnd win.HWND) { 30 runtime.LockOSThread() 31 defer runtime.UnlockOSThread() 32 win.SendMessage(hwnd, raiseMsg, 0, 0) 33 currentForegroundHwnd := win.GetForegroundWindow() 34 currentForegroundThreadId := win.GetWindowThreadProcessId(currentForegroundHwnd, nil) 35 currentThreadId := win.GetCurrentThreadId() 36 win.AttachThreadInput(int32(currentForegroundThreadId), int32(currentThreadId), true) 37 win.SetWindowPos(hwnd, win.HWND_TOPMOST, 0, 0, 0, 0, win.SWP_NOMOVE|win.SWP_NOSIZE|win.SWP_SHOWWINDOW) 38 win.SetWindowPos(hwnd, win.HWND_NOTOPMOST, 0, 0, 0, 0, win.SWP_NOMOVE|win.SWP_NOSIZE|win.SWP_SHOWWINDOW) 39 win.SetForegroundWindow(hwnd) 40 win.AttachThreadInput(int32(currentForegroundThreadId), int32(currentThreadId), false) 41 win.SetFocus(hwnd) 42 win.SetActiveWindow(hwnd) 43 } 44 45 func RaiseUI() bool { 46 hwnd := win.FindWindow(windows.StringToUTF16Ptr(manageWindowWindowClass), nil) 47 if hwnd == 0 { 48 return false 49 } 50 raiseRemote(hwnd) 51 return true 52 } 53 54 func WaitForRaiseUIThenQuit() { 55 var handle win.HWINEVENTHOOK 56 runtime.LockOSThread() 57 defer runtime.UnlockOSThread() 58 handle, err := win.SetWinEventHook(win.EVENT_OBJECT_CREATE, win.EVENT_OBJECT_CREATE, 0, func(hWinEventHook win.HWINEVENTHOOK, event uint32, hwnd win.HWND, idObject, idChild int32, idEventThread, dwmsEventTime uint32) uintptr { 59 class := make([]uint16, len(manageWindowWindowClass)+2) /* Plus 2, one for the null terminator, and one to see if this is only a prefix */ 60 n, err := win.GetClassName(hwnd, &class[0], len(class)) 61 if err != nil || n != len(manageWindowWindowClass) || windows.UTF16ToString(class) != manageWindowWindowClass { 62 return 0 63 } 64 win.UnhookWinEvent(handle) 65 raiseRemote(hwnd) 66 os.Exit(0) 67 return 0 68 }, 0, 0, win.WINEVENT_SKIPOWNPROCESS|win.WINEVENT_OUTOFCONTEXT) 69 if err != nil { 70 showErrorCustom(nil, l18n.Sprintf("WireGuard Detection Error"), l18n.Sprintf("Unable to wait for WireGuard window to appear: %v", err)) 71 } 72 for { 73 var msg win.MSG 74 if m := win.GetMessage(&msg, 0, 0, 0); m != 0 { 75 win.TranslateMessage(&msg) 76 win.DispatchMessage(&msg) 77 } 78 } 79 }