git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit5dc96633c6874ad1f210f706c696b9cf0dfaa51b
parentfddaf7662c
authorIsaac Freund <[email protected]>
date2021-07-15 13:39
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(-)

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 <https://www.gnu.org/licenses/>.
-
-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 {