mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +01:00
wails3 alpha windows: fix crash when systray icon is clicked without 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 <lea.anthony@gmail.com>
This commit is contained in:
parent
db5553ec75
commit
675f502802
2 changed files with 48 additions and 27 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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)
|
||||
|
|
@ -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),
|
||||
|
|
@ -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)
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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:
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue