Skip to content

Commit

Permalink
Force dialog to be topmost on Windows ⚓ (#87)
Browse files Browse the repository at this point in the history
- Windows: When Githooks is launched over Git processes from IDE's etc:
  dialog windows are not appearing on top. 
  Maybe because the startet subprocess does not allow it.
  Therefore, dialog windows are made topmost (always on top) which is better from a 
  user-perspective to not miss them even tough beeing a bit intrusive.

Update-Info: Improved dialog appearance on Windows.
  • Loading branch information
gabyx authored Jan 16, 2022
1 parent 7ff67ce commit 06b29e4
Show file tree
Hide file tree
Showing 9 changed files with 30 additions and 7 deletions.
4 changes: 1 addition & 3 deletions githooks/apps/dialog/gui/options-windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ func ShowOptions(ctx context.Context, opts *set.Options) (r res.Options, err err
if opts.Style == sets.OptionsStyleButtons && !opts.MultipleSelection {
return showOptionsWithButtons(
ctx, opts,
func(ctx context.Context, m *sets.Message) (res.Message, error) {
return ShowMessage(ctx, m)
})
ShowMessage)
}

return gwin.ShowOptions(ctx, opts)
Expand Down
6 changes: 6 additions & 0 deletions githooks/apps/dialog/gui/windows/dialog.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,9 @@ func centerAndSetSize(dlg *walk.Dialog, size walk.Size) {
centerOnScreen(dlg)
})
}

func forceTopMost(dlg *walk.Dialog) {
win.SetWindowPos(dlg.Handle(),
win.HWND_TOPMOST, 0, 0, 0, 0,
win.SWP_NOACTIVATE|win.SWP_NOMOVE|win.SWP_NOSIZE)
}
4 changes: 4 additions & 0 deletions githooks/apps/dialog/gui/windows/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ func ShowEntry(ctx context.Context, entry *sets.Entry) (r res.Entry, err error)

centerAndSetSize(app.Dialog, size)

if entry.ForceTopMost {
forceTopMost(app.Dialog)
}

if ctx != nil {
watchTimeout(ctx, app.Dialog)
}
Expand Down
3 changes: 3 additions & 0 deletions githooks/apps/dialog/gui/windows/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ func ShowMessage(ctx context.Context, msg *sets.Message) (r res.Message, err err
}

centerAndSetSize(app.Dialog, size)
if msg.ForceTopMost {
forceTopMost(app.Dialog)
}

if ctx != nil {
watchTimeout(ctx, app.Dialog)
Expand Down
6 changes: 3 additions & 3 deletions githooks/apps/dialog/gui/windows/open-file-ole.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func pickFolders(ctx context.Context, s *sets.FileSelection) (r res.File, err er
runtime.LockOSThread()
defer runtime.UnlockOSThread()

hr, _, _ := coInitializeEx.Call(0, 0x6) // COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE
hr, _, _ := coInitializeEx.Call(0, 0x6) //nolint: gomnd // COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE

if hr != 0x80010106 { // nolint: gomnd // RPC_E_CHANGED_MODE
if int32(hr) < 0 {
Expand All @@ -55,7 +55,7 @@ func pickFolders(ctx context.Context, s *sets.FileSelection) (r res.File, err er

var dialog *iFileOpenDialog
hr, _, _ = coCreateInstance.Call(
_CLSID_FileOpenDialog, 0, 0x17, // CLSCTX_ALL
_CLSID_FileOpenDialog, 0, 0x17, // nolint: gomnd // CLSCTX_ALL
iIDiFileOpenDialog, uintptr(unsafe.Pointer(&dialog)))

if int32(hr) < 0 {
Expand Down Expand Up @@ -169,7 +169,7 @@ func pickFolders(ctx context.Context, s *sets.FileSelection) (r res.File, err er
var ptr uintptr
hr, _, _ = item.Call(
item.vtbl.GetDisplayName,
0x80058000, // SIGDN_FILESYSPATH
0x80058000, // nolint: gomnd // SIGDN_FILESYSPATH
uintptr(unsafe.Pointer(&ptr)))
if int32(hr) < 0 {
err = cm.ErrorF("Failed call 'dialog.GetDisplayName': error '%v'", syscall.Errno(hr))
Expand Down
3 changes: 3 additions & 0 deletions githooks/apps/dialog/gui/windows/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ func ShowOptions(ctx context.Context, opts *sets.Options) (r res.Options, err er
})

centerAndSetSize(app.Dialog, size)
if opts.ForceTopMost {
forceTopMost(app.Dialog)
}

if ctx != nil {
watchTimeout(ctx, app.Dialog)
Expand Down
6 changes: 6 additions & 0 deletions githooks/apps/dialog/settings/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ type Message struct {

Style MessageStyle
Icon DialogIcon

ForceTopMost bool // Forces the window to be always on top. Only on Windows supported.
}

// OptionsStyle is the style with which the list dialog is rendered.
Expand All @@ -82,6 +84,8 @@ type Options struct {

Style OptionsStyle
MultipleSelection bool

ForceTopMost bool // Forces the window to be always on top. Only on Windows supported.
}

// Entry are options for the entry dialog.
Expand All @@ -94,6 +98,8 @@ type Entry struct {
HideDefaultEntry bool

Icon DialogIcon // Only on macOS supported.

ForceTopMost bool // Forces the window to be always on top. Only on Windows supported.
}

// Notification are options for the notification.
Expand Down
2 changes: 1 addition & 1 deletion githooks/common/path-windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func IsExecutable(path string) bool {

_, _, e := syscall.Syscall(
procGetBinaryTypeW.Addr(),
2,
2, //nolint: gomnd
uintptr(unsafe.Pointer(pPath)),
uintptr(unsafe.Pointer(&t)),
0)
Expand Down
3 changes: 3 additions & 0 deletions githooks/prompt/show-gui-impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func showEntryDialog(
opts.WindowIcon = settings.InfoIcon
opts.Icon = settings.InfoIcon
opts.Width = 400
opts.ForceTopMost = true // only for Windows this is crucial, such that it does not get ignored.

res, err := gui.ShowEntry(nil, &opts) // nolint

Expand Down Expand Up @@ -54,6 +55,7 @@ func showOptionsDialog(
opts.Style = settings.OptionsStyleButtons
opts.WindowIcon = settings.QuestionIcon
opts.Width = 400
opts.ForceTopMost = true // only for Windows this is crucial, such that it does not get ignored.

if defaultOptionIdx >= 0 {
opts.DefaultOptions = []uint{uint(defaultOptionIdx)}
Expand Down Expand Up @@ -153,6 +155,7 @@ func showMessageGUI(
opts := settings.Message{}
opts.Title = title
opts.Text = message
opts.ForceTopMost = true // only for Windows this is crucial, such that it does not get ignored.

if asError {
opts.WindowIcon = settings.InfoIcon
Expand Down

0 comments on commit 06b29e4

Please sign in to comment.