Right-click popups can display far offscreen under certain conditions

**EDIT: Fixed a few minutes after posting, solution for anyone else unhinged enough to run FMOD within a WM setup. The issue still happens, but this is what a guard would look like in my case. Not sure if this is something that’d show up on other compositors under their own multi monitor / XWayland handling.

Within a .lua file read by hyprland):

function helpers.monitorLogicalBox(mon)
	local w, h = mon.width, mon.height
	if mon.transform % 2 == 1 then
		w, h = h, w
	end
	w, h = w / mon.scale, h / mon.scale
	return { x = mon.x, y = mon.y, right = mon.x + w, bottom = mon.y + h }
end

local FMOD_CLASSES = { ["fmodstudio"] = true, ["fmod-studio"] = true }

-- force move popups (bare window titles within FMOD) whose position is detected
-- outside of the monitor we clicked on to snap to cursor, to fix positioning bug
-- where some right-hand side popups would display on an adjacent monitor due to
-- some kind of transform / compositor oddity.
hl.on("window.open", function(w)
if not w or not FMOD_CLASSES[w.class] then
return
end

if w.title ~= w.class or not w.floating then
	return
end

local mon = hl.get_monitor_at_cursor()
local cur = hl.get_cursor_pos()
if not mon or not cur then
	return
end

local box = helpers.monitorLogicalBox(mon)
local px, py = w.at.x, w.at.y
local pw, ph = w.size.x, w.size.y

if px >= box.x and px + pw <= box.right and py >= box.y and py + ph <= box.bottom then
	return
end

local nx = (cur.x + pw <= box.right) and cur.x or (cur.x - pw)
local ny = (cur.y + ph <= box.bottom) and cur.y or (cur.y - ph)

hl.dispatch(hl.dsp.window.move({
	x = nx,
	y = ny,
	relative = false,
	window = "address:" .. w.address,
}))

end)

Hello folks! FMOD 2.2.34 user.

Like many of us, I’ve been exploring Linux for the first time this year. And first off, I just wanted to say how thrilled I am that you all have packaged a native Linux build, it was a delight to see when I first started setting things up a few months ago.

I’m running under Hyprland as a compositor, so Wayland only with Xwayland translation for FMOD’s GUI. Setting the scale factor to 1.5 makes everything work just about perfectly.

One weird bug: if I have multiple monitors running (I usually do), right-clicking an element and spawning a pop-up right-click menu from within the Overview dock on the right hand edge of the event editor (e.g. to choose “Replace with parameter”) while the FMOD client is positioned within the right half of the screen (fullscreen also counts), will cause the popup to spawn on the left monitor instead, free floating in space. This does not happen when:

  • I’m using only a single monitor
  • The FMOD window containing the element I’m right-clicking (let’s just say, an event editor) is on the left half-ish of the screen
  • On most right-click popups. Just the ones that would appear under the cursor at the right edge of the screen

I chalked this up to a Wayland window positioning quirk or translation issue with the compositor’s handling of Xwayland, but have drilled into it a bunch (caveat, with AI, optimistically trying many, many angles) and can’t resolve it. Changing xwayland scaling behavior doesn’t seem to make a difference. Monitor enumeration order and compositor scaling translation were both ruled out as factors, too: the popup’s raw X11 position matches what should be given the x2 scaling translation logic in place for my whole monitor (my eyes aren’t great anymore, need it zoomed a bit). And anyways, it’s ONLY this specific type of popup! Maddening.

AI’s best working theory is that this could be a bug in the Qt widget code you’re using. I’ve just tried the latest FMOD 2.3.14 build, and the same thing happens, so I don’t think it’s that.

I realize this is a tiny little rabbit hole, but if you’re interested in smoothing edge cases for folks exploring window managers / Wayland generally, let me know and I’d be happy to share my experiences so far, I’m collecting data points.

Attached are two screenshots showing the scenario where the popup lands outside my monitor, and one where it works normally. The difference seems to be in where the baseline FMOD window is positioned so I do suspect it’s something having to do with overflow position calculation.

Thanks again!!

Thank you for bringing this to our attention and sharing your workaround. Could I grab as much info about your set up as possible? Would you be able to check if the issue is present in 2.03 as well?

Of course! Yeah, it was present on the latest FMOD as well as the one we’re using for my project. I am learning how quirky the x to wayland transition is going at the moment and finding that there seem to be a ridiculous number of ways to try to address mundane issues until specs and adaptation settle more.

Relevant info for this particular issue might be:

Compositor: Hyprland (wayland), was on 0.55 at the time of noticing this.
In terms of flags I feel would’ve contributed to this display issue:

I have a global setting that is:

xwayland = {
force_zero_scaling = true,
},

is set to true prevent Xwayland windows from doing any of their own scaling and letting the compositor handle it. I have a pretty hidpi monitor and things look incredibly tiny without me setting my global compositor scale to 2 (the config snippet for this looks like this

hl.monitor({
output = monitors.center,
mode = "3840x2160@120",
position = "720x0",
scale = "2",
...

I also have a three monitor setup. The side ones are transformed and vertical.

I think their very existence plays a role in this problem as I couldn’t reproduce the same bug on a single monitor; the right click dialog doesn’t jump off-screen or anything, so what I suspect is happening is some window start coordinate gets messed up and wayland ends up anchoring or parenting it to the wrong monitor.

Not sure what else you’d like to know about the setup, I think those are prob the main factors at play and I know this is quite niche, but I’m happy to answer anything. As I said, that manual positioning override in a config file is currently working as a hack to grab and position those errant popups.

Thank you for the info. I will work on reproducing the issue on my end and let you know how I go.

Of course!

I realized I forgot to include the monitorLogicalBox() helper function referenced in my initial workaround and will edit the post to include that, too. I believe it’s just accounting for the scale factor of the monitors in determining raw expected pixel placement, nothing fancy. Sorry for the slop:

function helpers.monitorLogicalBox(mon)
local w, h = mon.width, mon.height
if mon.transform % 2 == 1 then
w, h = h, w
end
w, h = w / mon.scale, h / mon.scale
return { x = mon.x, y = mon.y, right = mon.x + w, bottom = mon.y + h }
end