diff --git a/river/Cursor.zig b/river/Cursor.zig index 69cc2dc..44cf8f3 100644 --- a/river/Cursor.zig +++ b/river/Cursor.zig @@ -423,8 +423,9 @@ fn handleRequestSetCursor( } /// Find the topmost surface under the output layout coordinates lx/ly -/// returns the surface if found and sets the sx/sy parametes to the +/// returns the surface if found and sets the sx/sy parameters to the /// surface coordinates. +/// This function must be kept in sync with the rendering order in render.zig. fn surfaceAt(self: Self, lx: f64, ly: f64, sx: *f64, sy: *f64) ?*wlr.Surface { const root = self.seat.input_manager.server.root; const wlr_output = root.output_layout.outputAt(lx, ly) orelse return null; @@ -490,15 +491,31 @@ fn layerSurfaceAt(layer: std.TailQueue(LayerSurface), ox: f64, oy: f64, sx: *f64 /// Find the topmost visible view surface (incl. popups) at ox,oy. fn viewSurfaceAt(output: Output, ox: f64, oy: f64, sx: *f64, sy: *f64) ?*wlr.Surface { - // Focused views are rendered on top, so look for them first. + // focused, floating views var it = ViewStack(View).iter(output.views.first, .forward, output.current.tags, surfaceAtFilter); while (it.next()) |view| { - if (view.current.focus == 0) continue; + if (view.current.focus == 0 or !view.current.float) continue; if (view.surfaceAt(ox, oy, sx, sy)) |found| return found; } + // non-focused, floating views it = ViewStack(View).iter(output.views.first, .forward, output.current.tags, surfaceAtFilter); while (it.next()) |view| { + if (view.current.focus != 0 or !view.current.float) continue; + if (view.surfaceAt(ox, oy, sx, sy)) |found| return found; + } + + // focused, non-floating views + it = ViewStack(View).iter(output.views.first, .forward, output.current.tags, surfaceAtFilter); + while (it.next()) |view| { + if (view.current.focus == 0 or view.current.float) continue; + if (view.surfaceAt(ox, oy, sx, sy)) |found| return found; + } + + // non-focused, non-floating views + it = ViewStack(View).iter(output.views.first, .forward, output.current.tags, surfaceAtFilter); + while (it.next()) |view| { + if (view.current.focus != 0 or view.current.float) continue; if (view.surfaceAt(ox, oy, sx, sy)) |found| return found; } diff --git a/river/render.zig b/river/render.zig index 578a685..7357ed0 100644 --- a/river/render.zig +++ b/river/render.zig @@ -45,6 +45,7 @@ const SurfaceRenderData = struct { opacity: f32, }; +/// The rendering order in this function must be kept in sync with Cursor.surfaceAt() pub fn renderOutput(output: *Output) void { const config = &output.root.server.config; const renderer = output.wlr_output.backend.getRenderer().?; @@ -76,22 +77,36 @@ pub fn renderOutput(output: *Output) void { renderLayer(output, output.getLayer(.background).*, &now, .toplevels); renderLayer(output, output.getLayer(.bottom).*, &now, .toplevels); - // The first view in the list is "on top" so iterate in reverse. + // The first view in the list is "on top" so always iterate in reverse. + + // non-focused, non-floating views it = ViewStack(View).iter(output.views.last, .reverse, output.current.tags, renderFilter); while (it.next()) |view| { - // Focused views are rendered on top of normal views, skip them for now - if (view.current.focus != 0) continue; - + if (view.current.focus != 0 or view.current.float) continue; renderView(output, view, &now); if (view.draw_borders) renderBorders(output, view, &now); } - // Render focused views + // focused, non-floating views it = ViewStack(View).iter(output.views.last, .reverse, output.current.tags, renderFilter); while (it.next()) |view| { - // Skip unfocused views since we already rendered them - if (view.current.focus == 0) continue; + if (view.current.focus == 0 or view.current.float) continue; + renderView(output, view, &now); + if (view.draw_borders) renderBorders(output, view, &now); + } + // non-focused, floating views + it = ViewStack(View).iter(output.views.last, .reverse, output.current.tags, renderFilter); + while (it.next()) |view| { + if (view.current.focus != 0 or !view.current.float) continue; + renderView(output, view, &now); + if (view.draw_borders) renderBorders(output, view, &now); + } + + // focused, floating views + it = ViewStack(View).iter(output.views.last, .reverse, output.current.tags, renderFilter); + while (it.next()) |view| { + if (view.current.focus == 0 or !view.current.float) continue; renderView(output, view, &now); if (view.draw_borders) renderBorders(output, view, &now); }