diff --git a/main.go b/main.go index 0b568ed..3f9e888 100644 --- a/main.go +++ b/main.go @@ -56,15 +56,15 @@ func main() { } else { mainWindow.Controller.DoConnectToServerWorkflow(defaultServer) } - // TODO: There is a race condition with laying out the window before the - // window creation animation on Ubuntu (and other DEs?) finishes, where - // the window will be misdrawn into a smaller area if the animation hasn't finished. - // This makes it much less likely to occur (not seen on dozens of startups) - // but is a hacky "solution"! + + // hacky workaround for https://github.com/fyne-io/fyne/issues/4964 if runtime.GOOS == "linux" { - time.Sleep(350 * time.Millisecond) - mainWindow.ForceResize() + time.Sleep(100 * time.Millisecond) + w, h := mainWindow.DesiredSize() + scale := mainWindow.Window.Canvas().Scale() + SendResizeToPID(os.Getpid(), int(w*scale), int(h*scale)) } + }() mainWindow.Show() diff --git a/ui/mainwindow.go b/ui/mainwindow.go index e645f76..81cd04a 100644 --- a/ui/mainwindow.go +++ b/ui/mainwindow.go @@ -89,7 +89,7 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string, m.BottomPanel = NewBottomPanel(app.PlaybackManager, app.ImageManager, m.Controller) m.container = container.NewBorder(nil, m.BottomPanel, nil, nil, m.BrowsingPane) m.Window.SetContent(m.container) - m.ForceResize() + m.setInitialSize() app.PlaybackManager.OnSongChange(func(item mediaprovider.MediaItem, _ *mediaprovider.Track) { if item == nil { m.Window.SetTitle(displayAppName) @@ -141,15 +141,20 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string, return m } -func (m *MainWindow) ForceResize() { - w := float32(m.App.Config.Application.WindowWidth) +func (m *MainWindow) DesiredSize() (w, h float32) { + w = float32(m.App.Config.Application.WindowWidth) if w <= 1 { w = 1000 } - h := float32(m.App.Config.Application.WindowHeight) + h = float32(m.App.Config.Application.WindowHeight) if h <= 1 { h = 800 } + return w, h +} + +func (m *MainWindow) setInitialSize() { + w, h := m.DesiredSize() m.Window.Resize(fyne.NewSize(w, h)) } diff --git a/xresize.c b/xresize.c new file mode 100644 index 0000000..a67827b --- /dev/null +++ b/xresize.c @@ -0,0 +1,68 @@ +//go:build linux && !wayland + +#include +#include +#include +#include +#include + +#include "xresize.h" + +// thanks ChatGPT ;) +int find_windows_by_pid(Display *display, Window root, pid_t pid, Window* out, int n) { + Window *children; + unsigned int nchildren; + if (!XQueryTree(display, root, &root, &root, &children, &nchildren)) { + return 0; + } + + for (unsigned int i = 0; i < nchildren; i++) { + Atom pidAtom = XInternAtom(display, "_NET_WM_PID", True); + if (pidAtom != None) { + Atom type; + int format; + unsigned long nitems, bytes_after; + unsigned char *prop_pid = NULL; + + if (XGetWindowProperty(display, children[i], pidAtom, 0, 1, False, XA_CARDINAL, + &type, &format, &nitems, &bytes_after, &prop_pid) == Success && prop_pid) { + if (pid == *((pid_t *)prop_pid)) { + out[n++] = children[i]; + } + XFree(prop_pid); + } + } + + n = find_windows_by_pid(display, children[i], pid, out, n); + } + + XFree(children); + return n; +} + +void send_resize_event(Display *display, Window window, int width, int height) { + XResizeWindow(display, window, width, height); + XFlush(display); +} + +int send_resize_to_pid(int pid, int w, int h) { + Display *display = XOpenDisplay(NULL); + if (!display) { + return 1; + } + int ret = 0; + Window windows[128]; + Window root = DefaultRootWindow(display); + + int n = find_windows_by_pid(display, root, pid, &windows, 0); + if (n > 0) { + for (int i = 0; i < n; i++) { + send_resize_event(display, windows[i], w, h); + } + } else { + ret = 1; + } + + XCloseDisplay(display); + return ret; +} diff --git a/xresize.h b/xresize.h new file mode 100644 index 0000000..a772b34 --- /dev/null +++ b/xresize.h @@ -0,0 +1,3 @@ +//go:build linux && !wayland + +int send_resize_to_pid(int pid, int w, int h); diff --git a/xresize_other.go b/xresize_other.go new file mode 100644 index 0000000..13ee3a7 --- /dev/null +++ b/xresize_other.go @@ -0,0 +1,5 @@ +//go:build !linux || wayland + +package main + +func SendResizeToPID(pid, w, h int) {} diff --git a/xresize_x11.go b/xresize_x11.go new file mode 100644 index 0000000..3a66f97 --- /dev/null +++ b/xresize_x11.go @@ -0,0 +1,15 @@ +//go:build linux && !wayland + +package main + +/* +#cgo LDFLAGS: -lX11 +#include "xresize.h" +*/ +import ( + "C" +) + +func SendResizeToPID(pid, w, h int) { + C.send_resize_to_pid(C.int(pid), C.int(w), C.int(h)) +}