Add basic sway maximize command using patch
diff --git a/src/apps/personal/sway.nix b/src/apps/personal/sway.nix
index ed43929..012d4a9 100644
--- a/src/apps/personal/sway.nix
+++ b/src/apps/personal/sway.nix
@@ -40,62 +40,62 @@
   wlogoutJson = (builtins.toJSON wlogoutConfig);
   wlogoutConfigFile = pkgs.writeText "wlogout-layout.layout" (builtins.substring 1 ((builtins.stringLength wlogoutJson) - 2) wlogoutJson);
 in {
-    wayland.windowManager.sway = {
-        enable = true;
-        wrapperFeatures.gtk = true;
+  wayland.windowManager.sway = {
+    enable = true;
+    wrapperFeatures.gtk = true;
 
-        config = rec {
-            assigns = {};
-            bars = [];
-            colors = {};
-            defaultWorkspace = null;
-            down = "j";
-            floating = {};
-            focus = {};
-            fonts = {};
-            gaps = {
-                inner = 10;
-                top = -10;
-                outer = 0;
-                smartGaps = false;
-            };
-            input = {
-                "type:touchpad" = {
-                    dwt = "enabled";
-                    tap = "enabled";
-                    natural_scroll = "enabled";
-                    middle_emulation = "enabled";
-                    events = "disabled_on_external_mouse";
-                };
-                "type:keyboard" = {
-                    xkb_layout = "gb";
-                };
-                "type:tablet_tool" = {
-                    map_to_output = "eDP-1";
-                };
-            };
-            keybindings = lib.mkOptionDefault {
-                "${modifier}+l" = "exec /usr/bin/env wlogout -c 5 -r 5 -p layer-shell -l ${wlogoutConfigFile}"; # "exec /usr/bin/env swaylock -c 000000";
-                "XF86AudioRaiseVolume" = "exec pamixer -ui 5 && ( pamixer --get-mute && expr \"$(pamixer --get-volume)\" + 100 > $WOBSOCK ) || pamixer --get-volume > $WOBSOCK";
-                "XF86AudioLowerVolume" = "exec pamixer -ud 5 && ( pamixer --get-mute && expr \"$(pamixer --get-volume)\" + 100 > $WOBSOCK ) || pamixer --get-volume > $WOBSOCK";
-                "XF86AudioMute" = "exec pamixer --toggle-mute && ( pamixer --get-mute && expr \"$(pamixer --get-volume)\" + 100 > $WOBSOCK ) || pamixer --get-volume > $WOBSOCK";
-                "XF86AudioMicMute" = "exec pamixer --toggle-mute --default-source && ( pamixer --get-mute --default-source && expr \"$(pamixer --default-source --get-volume)\" + 100 > $WOBSOCK ) || pamixer --default-source --get-volume > $WOBSOCK";
-                "XF86MonBrightnessUp" = "exec light -A 3 && light -G | cut -d'.' -f1 > $WOBSOCK";
-                "XF86MonBrightnessDown" = "exec light -U 3 && light -G | cut -d'.' -f1 > $WOBSOCK";
-                "${modifier}+XF86AudioRaiseVolume" = "exec pamixer --default-source -ui 5 && ( pamixer --get-mute --default-source && expr \"$(pamixer --default-source --get-volume)\" + 100 > $WOBSOCK ) || pamixer --default-source --get-volume > $WOBSOCK";
-                "${modifier}+XF86AudioLowerVolume" = "exec pamixer --default-source -ud 5 && ( pamixer --get-mute --default-source && expr \"$(pamixer --default-source --get-volume)\" + 100 > $WOBSOCK ) || pamixer --get-volume --default-source > $WOBSOCK";
-                "${modifier}+XF86AudioMute" = "exec pamixer --toggle-mute --default-source && ( pamixer --get-mute --default-source && expr \"$(pamixer --default-source --get-volume)\" + 100 > $WOBSOCK ) || pamixer --default-source --get-volume > $WOBSOCK";
-                "${modifier}+XF86MonBrightnessUp" = "exec light -A 6 && light -G | cut -d'.' -f1 > $WOBSOCK";
-                "${modifier}+XF86MonBrightnessDown" = "exec light -U 6 && light -G | cut -d'.' -f1 > $WOBSOCK";
-                "${modifier}+Shift+s" = "exec grim -g \"$(slurp)\" - | tee ~/Screenshots/\"$(date --rfc-3339=seconds)\".png | wl-copy";
-                "${modifier}+g" = "sticky toggle";
-                "${modifier}+k" = "exec wl-copy -c";
-                "${modifier}+minus" = "exec ${./sway/show-menu.sh}";
-                "Print" = "exec grim - | tee ~/Screenshots/\"$(date --rfc-3339=seconds)\".png | wl-copy";
-                "${modifier}+Print" = "exec ${./sway/toggle-backlight.sh}";
-            };
-            keycodebindings = {};
-            left = "h";
+    config = rec {
+      assigns = {};
+      bars = [];
+      colors = {};
+      defaultWorkspace = null;
+      down = "j";
+      floating = {};
+      focus = {};
+      fonts = {};
+      gaps = {
+        inner = 10;
+        top = -10;
+        outer = 0;
+        smartGaps = false;
+      };
+      input = {
+        "type:touchpad" = {
+        dwt = "enabled";
+        tap = "enabled";
+        natural_scroll = "enabled";
+        middle_emulation = "enabled";
+        events = "disabled_on_external_mouse";
+        };
+        "type:keyboard" = {
+        xkb_layout = "gb";
+        };
+        "type:tablet_tool" = {
+        map_to_output = "eDP-1";
+        };
+        };
+        keybindings = lib.mkOptionDefault {
+        "${modifier}+l" = "exec /usr/bin/env wlogout -c 5 -r 5 -p layer-shell -l ${wlogoutConfigFile}"; # "exec /usr/bin/env swaylock -c 000000";
+        "XF86AudioRaiseVolume" = "exec pamixer -ui 5 && ( pamixer --get-mute && expr \"$(pamixer --get-volume)\" + 100 > $WOBSOCK ) || pamixer --get-volume > $WOBSOCK";
+        "XF86AudioLowerVolume" = "exec pamixer -ud 5 && ( pamixer --get-mute && expr \"$(pamixer --get-volume)\" + 100 > $WOBSOCK ) || pamixer --get-volume > $WOBSOCK";
+        "XF86AudioMute" = "exec pamixer --toggle-mute && ( pamixer --get-mute && expr \"$(pamixer --get-volume)\" + 100 > $WOBSOCK ) || pamixer --get-volume > $WOBSOCK";
+        "XF86AudioMicMute" = "exec pamixer --toggle-mute --default-source && ( pamixer --get-mute --default-source && expr \"$(pamixer --default-source --get-volume)\" + 100 > $WOBSOCK ) || pamixer --default-source --get-volume > $WOBSOCK";
+        "XF86MonBrightnessUp" = "exec light -A 3 && light -G | cut -d'.' -f1 > $WOBSOCK";
+        "XF86MonBrightnessDown" = "exec light -U 3 && light -G | cut -d'.' -f1 > $WOBSOCK";
+        "${modifier}+XF86AudioRaiseVolume" = "exec pamixer --default-source -ui 5 && ( pamixer --get-mute --default-source && expr \"$(pamixer --default-source --get-volume)\" + 100 > $WOBSOCK ) || pamixer --default-source --get-volume > $WOBSOCK";
+        "${modifier}+XF86AudioLowerVolume" = "exec pamixer --default-source -ud 5 && ( pamixer --get-mute --default-source && expr \"$(pamixer --default-source --get-volume)\" + 100 > $WOBSOCK ) || pamixer --get-volume --default-source > $WOBSOCK";
+        "${modifier}+XF86AudioMute" = "exec pamixer --toggle-mute --default-source && ( pamixer --get-mute --default-source && expr \"$(pamixer --default-source --get-volume)\" + 100 > $WOBSOCK ) || pamixer --default-source --get-volume > $WOBSOCK";
+        "${modifier}+XF86MonBrightnessUp" = "exec light -A 6 && light -G | cut -d'.' -f1 > $WOBSOCK";
+        "${modifier}+XF86MonBrightnessDown" = "exec light -U 6 && light -G | cut -d'.' -f1 > $WOBSOCK";
+        "${modifier}+Shift+s" = "exec grim -g \"$(slurp)\" - | tee ~/Screenshots/\"$(date --rfc-3339=seconds)\".png | wl-copy";
+        "${modifier}+g" = "sticky toggle";
+        "${modifier}+k" = "exec wl-copy -c";
+        "${modifier}+minus" = "exec ${./sway/show-menu.sh}";
+        "Print" = "exec grim - | tee ~/Screenshots/\"$(date --rfc-3339=seconds)\".png | wl-copy";
+        "${modifier}+Print" = "exec ${./sway/toggle-backlight.sh}";
+        };
+        keycodebindings = {};
+        left = "h";
             menu = "/usr/bin/env rofi -show combi";
             modes = {
                 resize = {
@@ -118,104 +118,104 @@
                     #position = "1920,0";
                     position = "0,0";
                     bg = "${./sway/background.png} fill";
-                };
-                eDP-1 = {
+                  };
+                  eDP-1 = {
                     resolution = "1920x1080";
                     #position = "0,1522";
                     position = "0,2160";
+                  };
+                  "*" = {
+                  };
                 };
-                "*" = {
-                };
-            };
-            right = "l";
-            seat = {
-                "*" = {
+                right = "l";
+                seat = {
+                  "*" = {
                     hide_cursor = "when-typing enable";
+                  };
                 };
-            };
-            startup = [
-                { command = "dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK"; }
-                { command = "\"pkill swaync; pkill waybar; ${pkgs-unstable.swaynotificationcenter}/bin/swaync & waybar\""; always = true; }
-                { command = "\"pkill glpaper; ${pkgs-unstable.glpaper}/bin/glpaper eDP-1 ${./sway/shader.glsl} -F -W 1920 -H 1080\""; always = true; }
-                { command = "light -N 1"; always = false; }
-                { command = "\"pkill wob; rm -f $WOBSOCK && mkfifo $WOBSOCK && tail -f $WOBSOCK | wob --output='*'\""; always = true; }
-            ];
-            terminal = "kitty";
-            up = "k";
-            window = {};
-            workspaceAutoBackAndForth = true;
-            workspaceLayout = "default";
-            workspaceOutputAssign = [];
-        };
+                startup = [
+                  { command = "dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK"; }
+                  { command = "\"pkill swaync; pkill waybar; ${pkgs-unstable.swaynotificationcenter}/bin/swaync & waybar\""; always = true; }
+                  { command = "\"pkill glpaper; ${pkgs-unstable.glpaper}/bin/glpaper eDP-1 ${./sway/shader.glsl} -F -W 1920 -H 1080\""; always = true; }
+                  { command = "light -N 1"; always = false; }
+                  { command = "\"pkill wob; rm -f $WOBSOCK && mkfifo $WOBSOCK && tail -f $WOBSOCK | wob --output='*'\""; always = true; }
+                ];
+                terminal = "kitty";
+                up = "k";
+                window = {};
+                workspaceAutoBackAndForth = true;
+                workspaceLayout = "default";
+                workspaceOutputAssign = [];
+              };
 
-        extraConfig = ''
-        set $WOBSOCK $XDG_RUNTIME_DIR/wob.sock
-        '';
+              extraConfig = ''
+                set $WOBSOCK $XDG_RUNTIME_DIR/wob.sock
+              '';
 
-        extraSessionCommands = ''
-        export SDL_VIDEODRIVER=wayland
+              extraSessionCommands = ''
+                export SDL_VIDEODRIVER=wayland
         # needs qt5.qtwayland in systemPackages
-        export QT_QPA_PLATFORM=wayland
-        export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
+                export QT_QPA_PLATFORM=wayland
+                export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
         # Fix for some Java AWT applications (e.g. Android Studio),
         # use this if they aren't displayed properly:
-        export _JAVA_AWT_WM_NONREPARENTING=1
-        '';
+                export _JAVA_AWT_WM_NONREPARENTING=1
+              '';
 
-        swaynag = {
-            enable = true;
-            settings = {
-                "<config>" = {
+              swaynag = {
+                enable = true;
+                settings = {
+                  "<config>" = {
                     background = "#ffffff99";
                     border-bottom = "#00000000";
                     button-background = "#ffffffcc";
                     button-padding = 10;
                     button-border-size = 0;
-                };
+                  };
 
-                warning = {
+                  warning = {
                     background = "#ffffff99";
                     border-bottom = "#00000000";
                     button-background = "#ffff00";
-                };
+                  };
 
-                error = {
+                  error = {
                     background = "#ffffff99";
                     border-bottom = "#00000000";
                     button-background = "#ff0000";
-                };
+                  };
 
-                green = {
+                  green = {
                     background = "#ffffff99";
                     border-bottom = "#00000000";
                     button-background = "#00b300";
-                };
+                  };
 
-                blue = {
+                  blue = {
                     background = "#ffffff99";
                     border-bottom = "#00000000";
                     button-background = "#0000ff";
+                  };
                 };
+              };
+
+              systemdIntegration = true;
             };
-        };
 
-        systemdIntegration = true;
-    };
+            home.packages = with pkgs; [
+              swaylock
+              swayidle
+              wl-clipboard
+              bc
+              jq
+              pulseaudio
+              pamixer
+              pkgs-unstable.glpaper
+            ];
 
-    home.packages = with pkgs; [
-        swaylock
-        swayidle
-        wl-clipboard
-        bc
-        jq
-        pulseaudio
-        pamixer
-        pkgs-unstable.glpaper
-    ];
-
-    programs.zsh.profileExtra = ''
-        if [ -z $DISPLAY ] && [ "$(tty)" = "/dev/tty1" ]; then
-            exec systemd-cat -t sway sway --unsupported-gpu
-        fi
-    '';
-}
+            programs.zsh.profileExtra = ''
+              if [ -z $DISPLAY ] && [ "$(tty)" = "/dev/tty1" ]; then
+              exec systemd-cat -t sway sway --unsupported-gpu
+              fi
+            '';
+          }
diff --git a/src/overlays/sway.nix b/src/overlays/sway.nix
new file mode 100644
index 0000000..a0488b1
--- /dev/null
+++ b/src/overlays/sway.nix
@@ -0,0 +1,7 @@
+final: prev:  {
+  sway-unwrapped = prev.sway-unwrapped.overrideAttrs (old: {
+    patches = (old.patches or []) ++ [
+      ./sway/maximize.patch
+    ];
+  });
+}
diff --git a/src/overlays/sway/maximize.patch b/src/overlays/sway/maximize.patch
new file mode 100644
index 0000000..dcab9bf
--- /dev/null
+++ b/src/overlays/sway/maximize.patch
@@ -0,0 +1,392 @@
+From e8a5fe93ef657399fa98bd69be71dbfbc14aa6d2 Mon Sep 17 00:00:00 2001
+From: Ford Smith <ford.smith@case.edu> and Skyler Grey
+<skyler3665@gmail.com>
+Date: Sat, 2 Apr 2022 20:21:47 -0400
+Subject: [PATCH] Add maximize support to sway & fix for latest version
+
+---
+ include/sway/commands.h       |   1 +
+ include/sway/tree/container.h |   4 +
+ include/sway/tree/view.h      |   1 +
+ sway/commands.c               |   2 +
+ sway/commands/maximize.c      |  59 ++++++++++
+ sway/desktop/xdg_shell.c      |   8 ++
+ sway/meson.build              |   1 +
+ sway/tree/container.c         | 201 ++++++++++++++++++++++++++++++++++
+ 8 files changed, 277 insertions(+)
+ create mode 100644 sway/commands/maximize.c
+
+diff --git a/include/sway/commands.h b/include/sway/commands.h
+index 2746ef28f1..7948be6823 100644
+--- a/include/sway/commands.h
++++ b/include/sway/commands.h
+@@ -150,6 +150,7 @@ sway_cmd cmd_kill;
+ sway_cmd cmd_layout;
+ sway_cmd cmd_log_colors;
+ sway_cmd cmd_mark;
++sway_cmd cmd_maximize;
+ sway_cmd cmd_max_render_time;
+ sway_cmd cmd_mode;
+ sway_cmd cmd_mouse_warping;
+diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
+index 751612e2c3..0a3404157b 100644
+--- a/include/sway/tree/container.h
++++ b/include/sway/tree/container.h
+@@ -257,6 +257,10 @@ void container_end_mouse_operation(struct sway_container *container);
+ void container_set_fullscreen(struct sway_container *con,
+ 		enum sway_fullscreen_mode mode);
+ 
++void container_set_maximize(struct sway_container *con,
++		enum sway_fullscreen_mode mode);
++
++
+ /**
+  * Convenience function.
+  */
+diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
+index 95708a049c..fd186c7386 100644
+--- a/include/sway/tree/view.h
++++ b/include/sway/tree/view.h
+@@ -43,6 +43,7 @@ struct sway_view_impl {
+ 	void (*set_activated)(struct sway_view *view, bool activated);
+ 	void (*set_tiled)(struct sway_view *view, bool tiled);
+ 	void (*set_fullscreen)(struct sway_view *view, bool fullscreen);
++	void (*set_maximized)(struct sway_view *view, bool maximized);
+ 	void (*set_resizing)(struct sway_view *view, bool resizing);
+ 	bool (*wants_floating)(struct sway_view *view);
+ 	void (*for_each_surface)(struct sway_view *view,
+diff --git a/sway/commands.c b/sway/commands.c
+index 5a1fd32ef9..b33788db17 100644
+--- a/sway/commands.c
++++ b/sway/commands.c
+@@ -74,6 +74,7 @@ static const struct cmd_handler handlers[] = {
+ 	{ "gaps", cmd_gaps },
+ 	{ "hide_edge_borders", cmd_hide_edge_borders },
+ 	{ "input", cmd_input },
++	{ "maximize", cmd_maximize },
+ 	{ "mode", cmd_mode },
+ 	{ "mouse_warping", cmd_mouse_warping },
+ 	{ "new_float", cmd_new_float },
+@@ -119,6 +120,7 @@ static const struct cmd_handler command_handlers[] = {
+ 	{ "kill", cmd_kill },
+ 	{ "layout", cmd_layout },
+ 	{ "mark", cmd_mark },
++	{ "maximize", cmd_maximize },
+ 	{ "max_render_time", cmd_max_render_time },
+ 	{ "move", cmd_move },
+ 	{ "nop", cmd_nop },
+diff --git a/sway/commands/maximize.c b/sway/commands/maximize.c
+new file mode 100644
+index 0000000000..5fa29f79c1
+--- /dev/null
++++ b/sway/commands/maximize.c
+@@ -0,0 +1,59 @@
++#include <strings.h>
++#include "log.h"
++#include "sway/commands.h"
++#include "sway/config.h"
++#include "sway/tree/arrange.h"
++#include "sway/tree/container.h"
++#include "sway/tree/view.h"
++#include "sway/tree/workspace.h"
++#include "util.h"
++
++// maximize [enable|disable|toggle] [global]
++struct cmd_results *cmd_maximize(int argc, char **argv) {
++	struct cmd_results *error = NULL;
++	if ((error = checkarg(argc, "maximize", EXPECTED_AT_MOST, 2))) {
++		return error;
++	}
++	if (!root->outputs->length) {
++		return cmd_results_new(CMD_FAILURE,
++				"Can't run this command while there's no outputs connected.");
++	}
++	struct sway_container *container = config->handler_context.container;
++
++	if (!container) {
++		// If the focus is not a container, do nothing successfully
++		return cmd_results_new(CMD_SUCCESS, NULL);
++	} else if (!container->pending.workspace) {
++		// If in the scratchpad, operate on the highest container
++		while (container->pending.parent) {
++			container = container->pending.parent;
++		}
++	}
++
++	bool is_fullscreen = container->pending.fullscreen_mode != FULLSCREEN_NONE;
++	bool global = false;
++	bool enable = !is_fullscreen;
++
++	if (argc >= 1) {
++		if (strcasecmp(argv[0], "global") == 0) {
++			global = true;
++		} else {
++			enable = parse_boolean(argv[0], is_fullscreen);
++		}
++	}
++
++	if (argc >= 2) {
++		global = strcasecmp(argv[1], "global") == 0;
++	}
++
++	enum sway_fullscreen_mode mode = FULLSCREEN_NONE;
++	if (enable) {
++		mode = global ? FULLSCREEN_GLOBAL : FULLSCREEN_WORKSPACE;
++	}
++
++	container_set_maximize(container, mode);
++	arrange_root();
++
++	return cmd_results_new(CMD_SUCCESS, NULL);
++}
++
+diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
+index 51168f4c61..f54db21930 100644
+--- a/sway/desktop/xdg_shell.c
++++ b/sway/desktop/xdg_shell.c
+@@ -178,6 +178,13 @@ static void set_fullscreen(struct sway_view *view, bool fullscreen) {
+ 	wlr_xdg_toplevel_set_fullscreen(view->wlr_xdg_toplevel, fullscreen);
+ }
+ 
++static void set_maximized(struct sway_view *view, bool maximized) {
++	if (xdg_shell_view_from_view(view) == NULL) {
++		return;
++	}
++	wlr_xdg_toplevel_set_maximized(view->wlr_xdg_surface, maximized);
++}
++
+ static void set_resizing(struct sway_view *view, bool resizing) {
+ 	if (xdg_shell_view_from_view(view) == NULL) {
+ 		return;
+@@ -257,6 +264,7 @@ static const struct sway_view_impl view_impl = {
+ 	.set_activated = set_activated,
+ 	.set_tiled = set_tiled,
+ 	.set_fullscreen = set_fullscreen,
++	.set_maximized = set_maximized,
+ 	.set_resizing = set_resizing,
+ 	.wants_floating = wants_floating,
+ 	.for_each_surface = for_each_surface,
+diff --git a/sway/meson.build b/sway/meson.build
+index 5f34ce6b01..05f302f49e 100644
+--- a/sway/meson.build
++++ b/sway/meson.build
+@@ -69,6 +69,7 @@ sway_sources = files(
+ 	'commands/inhibit_idle.c',
+ 	'commands/kill.c',
+ 	'commands/mark.c',
++	'commands/maximize.c',
+ 	'commands/max_render_time.c',
+ 	'commands/opacity.c',
+ 	'commands/include.c',
+diff --git a/sway/tree/container.c b/sway/tree/container.c
+index 09766ce5cc..57f65aadb6 100644
+--- a/sway/tree/container.c
++++ b/sway/tree/container.c
+@@ -1266,6 +1266,207 @@ void container_fullscreen_disable(struct sway_container *con) {
+ 	}
+ }
+ 
++static void set_maximized(struct sway_container *con, bool enable) {
++	if (!con->view) {
++		return;
++	}
++	if (con->view->impl->set_maximized) {
++		con->view->impl->set_maximized(con->view, enable);
++		if (con->view->foreign_toplevel) {
++			wlr_foreign_toplevel_handle_v1_set_fullscreen(
++				con->view->foreign_toplevel, enable);
++		}
++	}
++
++	if (!server.linux_dmabuf_v1 || !con->view->surface) {
++		return;
++	}
++	if (!enable) {
++		wlr_linux_dmabuf_v1_set_surface_feedback(server.linux_dmabuf_v1,
++			con->view->surface, NULL);
++		return;
++	}
++
++	if (!con->pending.workspace || !con->pending.workspace->output) {
++		return;
++	}
++
++	struct sway_output *output = con->pending.workspace->output;
++	struct wlr_output *wlr_output = output->wlr_output;
++
++	// TODO: add wlroots helpers for all of this stuff
++
++	const struct wlr_drm_format_set *renderer_formats =
++		wlr_renderer_get_dmabuf_texture_formats(server.renderer);
++	assert(renderer_formats);
++
++	int renderer_drm_fd = wlr_renderer_get_drm_fd(server.renderer);
++	int backend_drm_fd = wlr_backend_get_drm_fd(wlr_output->backend);
++	if (renderer_drm_fd < 0 || backend_drm_fd < 0) {
++		return;
++	}
++
++	dev_t render_dev, scanout_dev;
++	if (!devid_from_fd(renderer_drm_fd, &render_dev) ||
++			!devid_from_fd(backend_drm_fd, &scanout_dev)) {
++		return;
++	}
++
++	const struct wlr_drm_format_set *output_formats =
++		wlr_output_get_primary_formats(output->wlr_output,
++		WLR_BUFFER_CAP_DMABUF);
++	if (!output_formats) {
++		return;
++	}
++
++	struct wlr_drm_format_set scanout_formats = {0};
++	if (!wlr_drm_format_set_intersect(&scanout_formats,
++			output_formats, renderer_formats)) {
++		return;
++	}
++
++	struct wlr_linux_dmabuf_feedback_v1_tranche tranches[] = {
++		{
++			.target_device = scanout_dev,
++			.flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT,
++			.formats = &scanout_formats,
++		},
++		{
++			.target_device = render_dev,
++			.formats = renderer_formats,
++		},
++	};
++
++	const struct wlr_linux_dmabuf_feedback_v1 feedback = {
++		.main_device = render_dev,
++		.tranches = tranches,
++		.tranches_len = sizeof(tranches) / sizeof(tranches[0]),
++	};
++	wlr_linux_dmabuf_v1_set_surface_feedback(server.linux_dmabuf_v1,
++		con->view->surface, &feedback);
++
++	wlr_drm_format_set_finish(&scanout_formats);
++}
++
++static void container_maximize_workspace(struct sway_container *con) {
++	if (!sway_assert(con->pending.fullscreen_mode == FULLSCREEN_NONE,
++				"Expected a non-fullscreen container")) {
++		return;
++	}
++	set_maximized(con, true);
++	con->pending.fullscreen_mode = FULLSCREEN_WORKSPACE;
++
++	con->saved_x = con->pending.x;
++	con->saved_y = con->pending.y;
++	con->saved_width = con->pending.width;
++	con->saved_height = con->pending.height;
++
++	if (con->pending.workspace) {
++		con->pending.workspace->fullscreen = con;
++		struct sway_seat *seat;
++		struct sway_workspace *focus_ws;
++		wl_list_for_each(seat, &server.input->seats, link) {
++			focus_ws = seat_get_focused_workspace(seat);
++			if (focus_ws == con->pending.workspace) {
++				seat_set_focus_container(seat, con);
++			} else {
++				struct sway_node *focus =
++					seat_get_focus_inactive(seat, &root->node);
++				seat_set_raw_focus(seat, &con->node);
++				seat_set_raw_focus(seat, focus);
++			}
++		}
++	}
++
++	container_end_mouse_operation(con);
++	ipc_event_window(con, "fullscreen_mode");
++}
++
++void container_maximize_disable(struct sway_container *con) {
++	if (!sway_assert(con->pending.fullscreen_mode != FULLSCREEN_NONE,
++				"Expected a fullscreen container")) {
++		return;
++	}
++	set_maximized(con, false);
++
++	if (container_is_floating(con)) {
++		con->pending.x = con->saved_x;
++		con->pending.y = con->saved_y;
++		con->pending.width = con->saved_width;
++		con->pending.height = con->saved_height;
++	}
++
++	if (con->pending.fullscreen_mode == FULLSCREEN_WORKSPACE) {
++		if (con->pending.workspace) {
++			con->pending.workspace->fullscreen = NULL;
++			if (container_is_floating(con)) {
++				struct sway_output *output =
++					container_floating_find_output(con);
++				if (con->pending.workspace->output != output) {
++					container_floating_move_to_center(con);
++				}
++			}
++		}
++	} else {
++		root->fullscreen_global = NULL;
++	}
++
++	// If the container was mapped as fullscreen and set as floating by
++	// criteria, it needs to be reinitialized as floating to get the proper
++	// size and location
++	if (container_is_floating(con) && (con->pending.width == 0 || con->pending.height == 0)) {
++		container_floating_resize_and_center(con);
++	}
++
++	con->pending.fullscreen_mode = FULLSCREEN_NONE;
++	container_end_mouse_operation(con);
++	ipc_event_window(con, "fullscreen_mode");
++
++	if (con->scratchpad) {
++		struct sway_seat *seat;
++		wl_list_for_each(seat, &server.input->seats, link) {
++			struct sway_container *focus = seat_get_focused_container(seat);
++			if (focus == con || container_has_ancestor(focus, con)) {
++				seat_set_focus(seat,
++						seat_get_focus_inactive(seat, &root->node));
++			}
++		}
++	}
++}
++
++void container_set_maximize(struct sway_container *con,
++		enum sway_fullscreen_mode mode) {
++	if (con->pending.fullscreen_mode == mode) {
++		return;
++	}
++
++	switch (mode) {
++	case FULLSCREEN_NONE:
++		container_maximize_disable(con);
++		break;
++	case FULLSCREEN_WORKSPACE:
++		if (root->fullscreen_global) {
++			container_maximize_disable(root->fullscreen_global);
++		}
++		if (con->pending.workspace && con->pending.workspace->fullscreen) {
++			container_maximize_disable(con->pending.workspace->fullscreen);
++		}
++		container_maximize_workspace(con);
++		break;
++	case FULLSCREEN_GLOBAL:
++		//TODO:
++		assert(false);
++		// if (root->fullscreen_global) {
++		// 	container_maximize_disable(root->fullscreen_global);
++		// }
++		// if (con->pending.fullscreen_mode == FULLSCREEN_WORKSPACE) {
++		// 	container_maximize_disable(con);
++		// }
++		// container_fullscreen_global(con);
++		// break;
++	}
++}
++
+ void container_set_fullscreen(struct sway_container *con,
+ 		enum sway_fullscreen_mode mode) {
+ 	if (con->pending.fullscreen_mode == mode) {