Skip to content

Commit

Permalink
wails3 alpha windows: fix crash when systray icon is clicked without …
Browse files Browse the repository at this point in the history
…an attached window (#3271)

* Fix: #3270

removes an unnessecary check which returned a double nil wich in turned causes a crash if systray doesn't have an attached window.

* Add iconIsInFlyout method to systray_windows

and use it to determine if the icon is in the
flyout or not when positioning an attached window.

* optimize the windows systray window positioning

we only need to get the systray bounds if
the icon is in the flyout area.

* Use correct behavior for placing the window

if the systray icon is visible in the taskbar the
window should be centered on the systray icon
otherwise the icon is in a flyout are and the
window should be placed in the corner.

Added comments to explain placement logic

* consistent placing of systray menu on right vs left click

* add PR info in changelog

---------

Co-authored-by: Lea Anthony <[email protected]>
  • Loading branch information
tw1nk and leaanthony authored Mar 24, 2024
1 parent db5553e commit 675f502
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 27 deletions.
1 change: 1 addition & 0 deletions mkdocs-website/docs/en/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix replace line in `go.mod` to use relative paths. Fixes Windows paths with spaces - @leaanthony.
- Fix MacOS systray click handling when no attached window by [thomas-senechal](https://github.com/thomas-senechal) in PR [#3207](https://github.com/wailsapp/wails/pull/3207)
- Fix failing Windows build due to unknown option by [thomas-senechal](https://github.com/thomas-senechal) in PR [#3208](https://github.com/wailsapp/wails/pull/3208)
- Fix crash on windows left clicking the systray icon when not having an attached window [tw1nk](https://github.com/tw1nk) in PR [#3271](https://github.com/wailsapp/wails/pull/3271)
- Fix wrong baseURL when open window twice by @5aaee9 in PR [#3273](https://github.com/wailsapp/wails/pull/3273)
- Fix ordering of if branches in `WebviewWindow.Restore` method by [@fbbdev](https://github.com/fbbdev) in [#3279](https://github.com/wailsapp/wails/pull/3279)
- Correctly compute `startURL` across multiple `GetStartURL` invocations when `FRONTEND_DEVSERVER_URL` is present. [#3299](https://github.com/wailsapp/wails/pull/3299)
Expand Down
74 changes: 47 additions & 27 deletions v3/pkg/application/systemtray_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ package application

import (
"fmt"
"github.com/wailsapp/wails/v3/pkg/icons"
"syscall"
"unsafe"

"github.com/wailsapp/wails/v3/pkg/icons"

"github.com/samber/lo"
"github.com/wailsapp/wails/v3/pkg/events"
"github.com/wailsapp/wails/v3/pkg/w32"
Expand Down Expand Up @@ -42,17 +43,9 @@ func (s *windowsSystemTray) openMenu() {

// Show the menu at the tray bounds
s.menu.ShowAt(trayBounds.X, trayBounds.Y)

}

func (s *windowsSystemTray) positionWindow(window *WebviewWindow, offset int) error {

// Get the trayBounds of this system tray
trayBounds, err := s.bounds()
if err != nil {
return err
}

// Get the current screen trayBounds
currentScreen, err := s.getScreen()
if err != nil {
Expand All @@ -64,25 +57,45 @@ func (s *windowsSystemTray) positionWindow(window *WebviewWindow, offset int) er
newX := screenBounds.Width - window.Width()
newY := screenBounds.Height - window.Height()

// systray icons in windows can either be in the taskbar
// or in a flyout menu.
iconIsInTrayBounds, err := s.iconIsInTrayBounds()
if err != nil {
return err
}

// we only need the traybounds if the icon is in the tray
var trayBounds *Rect
if iconIsInTrayBounds {
trayBounds, err = s.bounds()
if err != nil {
return err
}
}

taskbarBounds := w32.GetTaskbarPosition()

// Set the window position based on the icon location
// if the icon is in the taskbar (traybounds) then we need
// to adjust the position so the window is centered on the icon
switch taskbarBounds.UEdge {
case w32.ABE_LEFT:
if trayBounds != nil && trayBounds.Y-(window.Height()/2) >= 0 {
if iconIsInTrayBounds && trayBounds.Y-(window.Height()/2) >= 0 {
newY = trayBounds.Y - (window.Height() / 2)
}
window.SetRelativePosition(offset, newY)
case w32.ABE_TOP:
if trayBounds != nil && trayBounds.X-(window.Width()/2) <= newX {
if iconIsInTrayBounds && trayBounds.X-(window.Width()/2) <= newX {
newX = trayBounds.X - (window.Width() / 2)
}
window.SetRelativePosition(newX, offset)
case w32.ABE_RIGHT:
if trayBounds != nil && trayBounds.Y-(window.Height()/2) <= newY {
if iconIsInTrayBounds && trayBounds.Y-(window.Height()/2) <= newY {
newY = trayBounds.Y - (window.Height() / 2)
}
window.SetRelativePosition(screenBounds.Width-window.Width()-offset, newY)
case w32.ABE_BOTTOM:
if trayBounds != nil && trayBounds.X-(window.Width()/2) <= newX {
if iconIsInTrayBounds && trayBounds.X-(window.Width()/2) <= newX {
newX = trayBounds.X - (window.Width() / 2)
}
window.SetRelativePosition(newX, screenBounds.Height-window.Height()-offset)
Expand All @@ -101,14 +114,6 @@ func (s *windowsSystemTray) bounds() (*Rect, error) {
return nil, fmt.Errorf("failed to get monitor")
}

// Get the taskbar rect
taskbarRect := w32.GetTaskbarPosition()

flyoutOpen := !w32.RectInRect(bounds, &taskbarRect.Rc)
if flyoutOpen {
return nil, nil
}

return &Rect{
X: int(bounds.Left),
Y: int(bounds.Top),
Expand All @@ -117,6 +122,22 @@ func (s *windowsSystemTray) bounds() (*Rect, error) {
}, nil
}

func (s *windowsSystemTray) iconIsInTrayBounds() (bool, error) {
bounds, err := w32.GetSystrayBounds(s.hwnd, s.uid)
if err != nil {
return false, err
}

taskbarRect := w32.GetTaskbarPosition()

inTasksBar := w32.RectInRect(bounds, &taskbarRect.Rc)
if inTasksBar {
return true, nil
}

return false, nil
}

func (s *windowsSystemTray) getScreen() (*Screen, error) {
// Get the screen for this systray
return getScreen(s.hwnd)
Expand Down Expand Up @@ -188,7 +209,7 @@ func (s *windowsSystemTray) run() {
if s.parent.rightClickHandler == nil {
s.parent.rightClickHandler = func() {
if s.menu != nil {
s.menu.ShowAtCursor()
s.openMenu()
}
}
}
Expand All @@ -203,11 +224,9 @@ func (s *windowsSystemTray) run() {

// Register the system tray
getNativeApplication().registerSystemTray(s)

}

func (s *windowsSystemTray) updateIcon() {

var newIcon w32.HICON
if w32.IsCurrentlyDarkMode() {
newIcon = s.darkModeIcon
Expand Down Expand Up @@ -252,6 +271,7 @@ func (s *windowsSystemTray) setIcon(icon []byte) {
// Update the icon
s.updateIcon()
}

func (s *windowsSystemTray) setDarkModeIcon(icon []byte) {
var err error
s.darkModeIcon, err = w32.CreateSmallHIconFromImage(icon)
Expand Down Expand Up @@ -301,7 +321,7 @@ func (s *windowsSystemTray) wndProc(msg uint32, wParam, lParam uintptr) uintptr
s.parent.mouseLeaveHandler()
}
}
//println(w32.WMMessageToString(msg))
// println(w32.WMMessageToString(msg))

// Menu processing
case w32.WM_COMMAND:
Expand All @@ -311,8 +331,8 @@ func (s *windowsSystemTray) wndProc(msg uint32, wParam, lParam uintptr) uintptr
s.menu.ProcessCommand(cmdMsgID)
}
default:
//msg := int(wParam & 0xffff)
//println(w32.WMMessageToString(uintptr(msg)))
// msg := int(wParam & 0xffff)
// println(w32.WMMessageToString(uintptr(msg)))
}

return w32.DefWindowProc(s.hwnd, msg, wParam, lParam)
Expand Down

0 comments on commit 675f502

Please sign in to comment.