From 96e1082156f8606f74c2414f7d7decf1ab6bbcda Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Thu, 15 Jul 2021 13:39:20 +0200 Subject: [PATCH] river: remove opacity command This code is complex and increases maintenance burden but doesn't add any functionality, only eye-candy. Futhermore, neither I nor any of the core contributors use it. There may be a place in river for such eye-candy down the line, in which case this code could be revived. Currently river is early enough in its development that our focus should be on core functionality instead. --- completions/bash/riverctl | 1 - completions/fish/riverctl.fish | 3 +- completions/zsh/_riverctl | 1 - doc/riverctl.1.scd | 20 ------- example/init | 3 -- river/Config.zig | 13 ----- river/Root.zig | 2 - river/Seat.zig | 14 +---- river/View.zig | 96 +--------------------------------- river/XdgToplevel.zig | 1 - river/command.zig | 1 - river/command/opacity.zig | 79 ---------------------------- river/render.zig | 12 +---- 13 files changed, 6 insertions(+), 240 deletions(-) delete mode 100644 river/command/opacity.zig diff --git a/completions/bash/riverctl b/completions/bash/riverctl index 4dec1c5..a0a429e 100644 --- a/completions/bash/riverctl +++ b/completions/bash/riverctl @@ -42,7 +42,6 @@ function __riverctl_completion () border-color-unfocused \ border-width \ focus-follows-cursor \ - opacity \ set-repeat \ set-cursor-warp \ xcursor-theme" diff --git a/completions/fish/riverctl.fish b/completions/fish/riverctl.fish index eca0c25..d9bb475 100644 --- a/completions/fish/riverctl.fish +++ b/completions/fish/riverctl.fish @@ -4,7 +4,7 @@ end function __fish_riverctl_complete_no_subcommand for i in (commandline -opc) - if contains -- $i close csd-filter-add exit float-filter-add focus-output focus-view input list-inputs list-input-configs move resize snap send-to-output spawn swap toggle-float toggle-fullscreen zoom default-layout output-layout set-layout-value mod-layout-value set-focused-tags set-view-tags toggle-focused-tags toggle-view-tags spawn-tagmask declare-mode enter-mode map map-pointer unmap unmap-pointer attach-mode background-color border-color-focused border-color-unfocused border-width focus-follows-cursor opacity set-repeat set-cursor-warp xcursor-theme + if contains -- $i close csd-filter-add exit float-filter-add focus-output focus-view input list-inputs list-input-configs move resize snap send-to-output spawn swap toggle-float toggle-fullscreen zoom default-layout output-layout set-layout-value mod-layout-value set-focused-tags set-view-tags toggle-focused-tags toggle-view-tags spawn-tagmask declare-mode enter-mode map map-pointer unmap unmap-pointer attach-mode background-color border-color-focused border-color-unfocused border-width focus-follows-cursor set-repeat set-cursor-warp xcursor-theme return 1 end end @@ -79,7 +79,6 @@ complete -c riverctl -x -n '__fish_riverctl_complete_no_subcommand' -a border-co complete -c riverctl -x -n '__fish_riverctl_complete_no_subcommand' -a border-color-unfocused -d 'Set the border color of unfocused views' complete -c riverctl -x -n '__fish_riverctl_complete_no_subcommand' -a border-width -d 'Set the border width to pixels' complete -c riverctl -x -n '__fish_riverctl_complete_no_subcommand' -a focus-follows-cursor -d 'Configure the focus behavior when moving cursor' -complete -c riverctl -x -n '__fish_riverctl_complete_no_subcommand' -a opacity -d 'Configure server-side opacity of views' complete -c riverctl -x -n '__fish_riverctl_complete_no_subcommand' -a set-repeat -d 'Set the keyboard repeat rate and repeat delay' complete -c riverctl -x -n '__fish_riverctl_complete_no_subcommand' -a set-cursor-warp -d 'Set the cursor warp mode.' complete -c riverctl -x -n '__fish_riverctl_complete_no_subcommand' -a xcursor-theme -d 'Set the xcursor theme' diff --git a/completions/zsh/_riverctl b/completions/zsh/_riverctl index e7fdaa2..625964b 100644 --- a/completions/zsh/_riverctl +++ b/completions/zsh/_riverctl @@ -48,7 +48,6 @@ _riverctl_subcommands() 'border-color-unfocused:Set the border color of unfocused views' 'border-width:Set the border width to pixels' 'focus-follows-cursor:Configure the focus behavior when moving cursor' - 'opacity:Configure server-side opacity of views' 'set-repeat:Set the keyboard repeat rate and repeat delay' 'set-cursor-warp:Set the cursor warp mode.' 'xcursor-theme:Set the xcursor theme' diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd index d8f8bca..a485a73 100644 --- a/doc/riverctl.1.scd +++ b/doc/riverctl.1.scd @@ -259,26 +259,6 @@ A complete list may be found in _/usr/include/linux/input-event-codes.h_ - _on-output-change_: When a different output is focused, the cursor will be warped to its center. -*opacity* _focused_ _unfocused_ _initial_ _step-size_ _delta-t_ - Configure server-side opacity of views, including transition - animations. A value of 0.0 is fully transparent while 1.0 is fully - opaque. By default all views are fully opaque and there are no - animations. - - - _focused_: opacity of focused views [0.0, 1.0] - - _unfocused_: opacity of unfocused views [0.0, 1.0] - - _initial_: opacity of views when they are created before immediately - transitioning to either _focused_ or _unfocused_ [0.0, 1.0] - - _step-size_: opacity change per step [0.05, 1.0] - - _delta-t_: step time in milliseconds - - A transition animation may occur when changing between states with - different opacity values configured. Instead of setting the view's - opacity to the value for the new state immediately, it is changed - incrementally in steps of _step-size_ every _delta-t_ milliseconds. - Setting _step-size_ to 1.0 disables transitions fully regardless of - the value of _delta-t_. - *set-repeat* _rate_ _delay_ Set the keyboard repeat rate to _rate_ key repeats per second and repeat delay to _delay_ milliseconds. diff --git a/example/init b/example/init index 44532c4..07e0347 100755 --- a/example/init +++ b/example/init @@ -150,9 +150,6 @@ riverctl float-filter-add "popup" # Set app-ids of views which should use client side decorations riverctl csd-filter-add "gedit" -# Set opacity and fade effect -# riverctl opacity 1.0 0.75 0.0 0.1 20 - # Set and exec into the default layout generator, rivertile. # River will send the process group of the init executable SIGTERM on exit. riverctl default-layout rivertile diff --git a/river/Config.zig b/river/Config.zig index dbc7c39..63fef65 100644 --- a/river/Config.zig +++ b/river/Config.zig @@ -76,19 +76,6 @@ default_layout_namespace: []const u8 = &[0]u8{}, /// Determines where new views will be attached to the view stack. attach_mode: AttachMode = .top, -opacity: struct { - /// The opacity of focused views - focused: f32 = 1.0, - /// The opacity of unfocused views - unfocused: f32 = 1.0, - /// The initial opacity of new views - initial: f32 = 1.0, - /// View opacity transition step - delta: f32 = 1.0, - /// Time between view opacity transition steps in milliseconds - delta_t: u31 = 20, -} = .{}, - /// Keyboard repeat rate in characters per second repeat_rate: u31 = 25, diff --git a/river/Root.zig b/river/Root.zig index f39f6f2..aad7541 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -399,8 +399,6 @@ fn commitTransaction(self: *Self) void { view.current = view.pending; view.dropSavedBuffers(); - - view.commitOpacityTransition(); } if (view_tags_changed) output.sendViewTags(); diff --git a/river/Seat.zig b/river/Seat.zig index e741617..0d25860 100644 --- a/river/Seat.zig +++ b/river/Seat.zig @@ -199,12 +199,7 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void { switch (self.focused) { .view => |view| { view.pending.focus -= 1; - if (view.pending.focus == 0) { - view.setActivated(false); - if (!view.pending.fullscreen) { - view.pending.target_opacity = server.config.opacity.unfocused; - } - } + if (view.pending.focus == 0) view.setActivated(false); }, .layer, .none => {}, } @@ -213,12 +208,7 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void { switch (new_focus) { .view => |target_view| { std.debug.assert(self.focused_output == target_view.output); - if (target_view.pending.focus == 0) { - target_view.setActivated(true); - if (!target_view.pending.fullscreen) { - target_view.pending.target_opacity = server.config.opacity.focused; - } - } + if (target_view.pending.focus == 0) target_view.setActivated(true); target_view.pending.focus += 1; }, .layer => |target_layer| std.debug.assert(self.focused_output == target_layer.output), diff --git a/river/View.zig b/river/View.zig index acc6f25..79ddc1a 100644 --- a/river/View.zig +++ b/river/View.zig @@ -71,9 +71,6 @@ const State = struct { float: bool = false, fullscreen: bool = false, - - /// Opacity the view is transitioning to - target_opacity: f32, }; const SavedBuffer = struct { @@ -124,12 +121,6 @@ float_box: Box = undefined, /// and for more intuitive behavior if there is no active layout for the output. post_fullscreen_box: Box = undefined, -/// The current opacity of this view -opacity: f32, - -/// Opacity change timer event source -opacity_timer: ?*wl.EventSource = null, - draw_borders: bool = true, /// This is created when the view is mapped and destroyed with the view @@ -144,16 +135,9 @@ foreign_close: wl.Listener(*wlr.ForeignToplevelHandleV1) = pub fn init(self: *Self, output: *Output, tags: u32, surface: anytype) void { self.* = .{ .output = output, - .current = .{ - .tags = tags, - .target_opacity = server.config.opacity.initial, - }, - .pending = .{ - .tags = tags, - .target_opacity = server.config.opacity.initial, - }, + .current = .{ .tags = tags }, + .pending = .{ .tags = tags }, .saved_buffers = std.ArrayList(SavedBuffer).init(util.gpa), - .opacity = server.config.opacity.initial, }; if (@TypeOf(surface) == *wlr.XdgSurface) { @@ -213,7 +197,6 @@ pub fn applyPending(self: *Self) void { self.setFullscreen(true); self.post_fullscreen_box = self.current.box; - self.pending.target_opacity = 1.0; const layout_box = server.root.output_layout.getBox(self.output.wlr_output).?; self.pending.box = .{ .x = 0, @@ -226,12 +209,6 @@ pub fn applyPending(self: *Self) void { if (self.current.fullscreen and !self.pending.fullscreen) { self.setFullscreen(false); self.pending.box = self.post_fullscreen_box; - - // Restore configured opacity - self.pending.target_opacity = if (self.pending.focus > 0) - server.config.opacity.focused - else - server.config.opacity.unfocused; } if (arrange_output) self.output.arrangeViews(); @@ -449,8 +426,6 @@ pub fn shouldTrackConfigure(self: Self) bool { /// Called by the impl when the surface is ready to be displayed pub fn map(self: *Self) void { - self.pending.target_opacity = server.config.opacity.unfocused; - log.debug("view '{s}' mapped", .{self.getTitle()}); if (self.foreign_toplevel_handle == null) { @@ -499,10 +474,6 @@ pub fn unmap(self: *Self) void { if (self.saved_buffers.items.len == 0) self.saveBuffers(); - if (self.opacity_timer != null) { - self.killOpacityTimer(); - } - // Inform all seats that the view has been unmapped so they can handle focus var it = server.input_manager.seats.first; while (it) |node| : (it = node.next) { @@ -540,69 +511,6 @@ pub fn notifyAppId(self: Self) void { } } -/// Change the opacity of a view by config.opacity.delta. -/// If the target opacity was reached, return true. -fn incrementOpacity(self: *Self) bool { - self.output.damage.addWhole(); - if (self.opacity < self.current.target_opacity) { - self.opacity += server.config.opacity.delta; - if (self.opacity < self.current.target_opacity) return false; - } else { - self.opacity -= server.config.opacity.delta; - if (self.opacity > self.current.target_opacity) return false; - } - self.opacity = self.current.target_opacity; - return true; -} - -/// Destroy a views opacity timer -fn killOpacityTimer(self: *Self) void { - self.opacity_timer.?.remove(); - self.opacity_timer = null; -} - -/// Set the timeout on a views opacity timer -fn armOpacityTimer(self: *Self) void { - const delta_t = server.config.opacity.delta_t; - self.opacity_timer.?.timerUpdate(delta_t) catch |err| { - log.err("failed to update opacity timer: {s}", .{err}); - self.killOpacityTimer(); - }; -} - -/// Called by the opacity timer -fn handleOpacityTimer(self: *Self) callconv(.C) c_int { - if (self.incrementOpacity()) { - self.killOpacityTimer(); - } else { - self.armOpacityTimer(); - } - return 0; -} - -/// Create an opacity timer for a view and arm it -fn attachOpacityTimer(self: *Self) void { - const event_loop = server.wl_server.getEventLoop(); - self.opacity_timer = event_loop.addTimer(*Self, handleOpacityTimer, self) catch { - log.err("failed to create opacity timer for view '{s}'", .{self.getTitle()}); - return; - }; - self.armOpacityTimer(); -} - -/// Commit an opacity transition -pub fn commitOpacityTransition(self: *Self) void { - if (self.opacity == self.current.target_opacity) return; - - // A running timer can handle a target_opacity change - if (self.opacity_timer != null) return; - - // Do the first step now, if that step was not enough, attach timer - if (!self.incrementOpacity()) { - self.attachOpacityTimer(); - } -} - /// Only honors the request if the view is already visible on the seat's /// currently focused output. TODO: consider allowing this request to switch /// output/tag focus. diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig index b56ed08..c74a0f0 100644 --- a/river/XdgToplevel.zig +++ b/river/XdgToplevel.zig @@ -280,7 +280,6 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), surface: *wlr.Surface) voi } else { const self_tags_changed = view.pending.tags != view.current.tags; view.current = view.pending; - view.commitOpacityTransition(); if (self_tags_changed) view.output.sendViewTags(); view.output.damage.addWhole(); } diff --git a/river/command.zig b/river/command.zig index 315d300..b3fc953 100644 --- a/river/command.zig +++ b/river/command.zig @@ -66,7 +66,6 @@ const str_to_impl_fn = [_]struct { .{ .name = "map-pointer", .impl = @import("command/map.zig").mapPointer }, .{ .name = "mod-layout-value", .impl = @import("command/layout.zig").modLayoutValue }, .{ .name = "move", .impl = @import("command/move.zig").move }, - .{ .name = "opacity", .impl = @import("command/opacity.zig").opacity }, .{ .name = "output-layout", .impl = @import("command/layout.zig").outputLayout }, .{ .name = "resize", .impl = @import("command/move.zig").resize }, .{ .name = "send-to-output", .impl = @import("command/output.zig").sendToOutput }, diff --git a/river/command/opacity.zig b/river/command/opacity.zig deleted file mode 100644 index c4de30b..0000000 --- a/river/command/opacity.zig +++ /dev/null @@ -1,79 +0,0 @@ -// This file is part of river, a dynamic tiling wayland compositor. -// -// Copyright 2020 The River Developers -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -const std = @import("std"); - -const server = &@import("../main.zig").server; - -const Error = @import("../command.zig").Error; -const Seat = @import("../Seat.zig"); -const View = @import("../View.zig"); -const ViewStack = @import("../view_stack.zig").ViewStack; - -fn opacityUpdateFilter(view: *View, context: void) bool { - // We want to update all views - return true; -} - -pub fn opacity( - allocator: *std.mem.Allocator, - seat: *Seat, - args: []const [:0]const u8, - out: *?[]const u8, -) Error!void { - if (args.len < 6) return Error.NotEnoughArguments; - if (args.len > 6) return Error.TooManyArguments; - - // Focused opacity - server.config.opacity.focused = try std.fmt.parseFloat(f32, args[1]); - if (server.config.opacity.focused < 0.0 or server.config.opacity.focused > 1.0) - return Error.InvalidValue; - - // Unfocused opacity - server.config.opacity.unfocused = try std.fmt.parseFloat(f32, args[2]); - if (server.config.opacity.unfocused < 0.0 or server.config.opacity.unfocused > 1.0) - return Error.InvalidValue; - - // Starting opacity for new views - server.config.opacity.initial = try std.fmt.parseFloat(f32, args[3]); - if (server.config.opacity.initial < 0.0 or server.config.opacity.initial > 1.0) - return Error.InvalidValue; - - // Opacity transition step - server.config.opacity.delta = try std.fmt.parseFloat(f32, args[4]); - if (server.config.opacity.delta < 0.0 or server.config.opacity.delta > 1.0) - return Error.InvalidValue; - - // Time between step - server.config.opacity.delta_t = try std.fmt.parseInt(u31, args[5], 10); - if (server.config.opacity.delta_t < 1) return Error.InvalidValue; - - // Update opacity of all views - // Unmapped views will be skipped, however their opacity gets updated on map anyway - var oit = server.root.outputs.first; - while (oit) |onode| : (oit = onode.next) { - var vit = ViewStack(View).iter(onode.data.views.first, .forward, {}, opacityUpdateFilter); - while (vit.next()) |vnode| { - if (vnode.current.focus > 0) { - vnode.pending.target_opacity = server.config.opacity.focused; - } else { - vnode.pending.target_opacity = server.config.opacity.unfocused; - } - } - } - server.root.startTransaction(); -} diff --git a/river/render.zig b/river/render.zig index aedeccf..2b25bde 100644 --- a/river/render.zig +++ b/river/render.zig @@ -43,8 +43,6 @@ const SurfaceRenderData = struct { output_y: i32, when: *os.timespec, - - opacity: f32, }; /// The rendering order in this function must be kept in sync with Cursor.surfaceAt() @@ -186,7 +184,6 @@ fn renderLayer( .output_x = layer_surface.box.x, .output_y = layer_surface.box.y, .when = now, - .opacity = 1.0, }; switch (role) { .toplevels => layer_surface.wlr_layer_surface.surface.forEachSurface( @@ -218,7 +215,6 @@ fn renderView(output: *const Output, view: *View, now: *os.timespec) void { .height = @intCast(c_int, saved_buffer.box.height), }, saved_buffer.transform, - view.opacity, ); } else { // Since there is no stashed buffer, we are not in the middle of @@ -228,7 +224,6 @@ fn renderView(output: *const Output, view: *View, now: *os.timespec) void { .output_x = view.current.box.x - view.surface_box.x, .output_y = view.current.box.y - view.surface_box.y, .when = now, - .opacity = view.opacity, }; view.surface.?.forEachSurface(*SurfaceRenderData, renderSurfaceIterator, &rdata); @@ -241,7 +236,6 @@ fn renderViewPopups(output: *const Output, view: *View, now: *os.timespec) void .output_x = view.current.box.x - view.surface_box.x, .output_y = view.current.box.y - view.surface_box.y, .when = now, - .opacity = view.opacity, }; view.forEachPopupSurface(*SurfaceRenderData, renderSurfaceIterator, &rdata); } @@ -260,7 +254,6 @@ fn renderDragIcons(output: *const Output, now: *os.timespec) void { .output_y = @floatToInt(i32, drag_icon.seat.cursor.wlr_cursor.y) + drag_icon.wlr_drag_icon.surface.sy - output_box.y, .when = now, - .opacity = 1.0, }; drag_icon.wlr_drag_icon.surface.forEachSurface(*SurfaceRenderData, renderSurfaceIterator, &rdata); } @@ -279,7 +272,6 @@ fn renderXwaylandUnmanaged(output: *const Output, now: *os.timespec) void { .output_x = xwayland_surface.x - output_box.x, .output_y = xwayland_surface.y - output_box.y, .when = now, - .opacity = 1.0, }; xwayland_surface.surface.?.forEachSurface(*SurfaceRenderData, renderSurfaceIterator, &rdata); } @@ -302,7 +294,6 @@ fn renderSurfaceIterator( .height = surface.current.height, }, surface.current.transform, - rdata.opacity, ); surface.sendFrameDone(rdata.when); @@ -315,7 +306,6 @@ fn renderTexture( texture: *wlr.Texture, wlr_box: wlr.Box, transform: wl.Output.Transform, - opacity: f32, ) void { var box = wlr_box; @@ -333,7 +323,7 @@ fn renderTexture( // This takes our matrix, the texture, and an alpha, and performs the actual // rendering on the GPU. const renderer = output.wlr_output.backend.getRenderer().?; - renderer.renderTextureWithMatrix(texture, &matrix, opacity) catch return; + renderer.renderTextureWithMatrix(texture, &matrix, 1.0) catch return; } fn renderBorders(output: *const Output, view: *View, now: *os.timespec) void {