workaround for occasional linux window misdraw

This commit is contained in:
Drew Weymouth
2024-06-23 10:56:28 -07:00
parent 16fd76f0aa
commit 2736fe9955
6 changed files with 107 additions and 11 deletions
+7 -7
View File
@@ -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()
+9 -4
View File
@@ -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))
}
+68
View File
@@ -0,0 +1,68 @@
//go:build linux && !wayland
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <unistd.h>
#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;
}
+3
View File
@@ -0,0 +1,3 @@
//go:build linux && !wayland
int send_resize_to_pid(int pid, int w, int h);
+5
View File
@@ -0,0 +1,5 @@
//go:build !linux || wayland
package main
func SendResizeToPID(pid, w, h int) {}
+15
View File
@@ -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))
}