This commit is contained in:
LGUG2Z
2025-05-12 17:13:33 -07:00
parent eec6312a51
commit e52796c24d
16 changed files with 600 additions and 60 deletions

View File

@@ -188,6 +188,12 @@ impl KomorebiLayout {
painter.line_segment([c - vec2(r, 0.0), c + vec2(r, 0.0)], stroke);
painter.line_segment([c - vec2(0.0, r), c + vec2(0.0, r)], stroke);
}
// TODO: @CtByte can you think of a nice icon to draw here?
komorebi_client::DefaultLayout::Scrolling => {
painter.line_segment([c - vec2(r / 2.0, r), c + vec2(-r / 2.0, r)], stroke);
painter.line_segment([c - vec2(0.0, r), c + vec2(0.0, r)], stroke);
painter.line_segment([c - vec2(-r / 2.0, r), c + vec2(r / 2.0, r)], stroke);
}
},
KomorebiLayout::Monocle => {}
KomorebiLayout::Floating => {

View File

@@ -392,7 +392,7 @@ impl Border {
tracing::error!("failed to update border position {error}");
}
if !rect.is_same_size_as(&old_rect) {
if !rect.is_same_size_as(&old_rect) || !rect.has_same_position_as(&old_rect) {
if let Some(render_target) = (*border_pointer).render_target.as_ref() {
let border_width = (*border_pointer).width;
let border_offset = (*border_pointer).offset;

View File

@@ -356,7 +356,7 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
};
if !should_process_notification {
tracing::trace!("monitor state matches latest snapshot, skipping notification");
tracing::debug!("monitor state matches latest snapshot, skipping notification");
continue 'receiver;
}

View File

@@ -12,8 +12,10 @@ use super::custom_layout::ColumnSplitWithCapacity;
use super::CustomLayout;
use super::DefaultLayout;
use super::Rect;
use crate::default_layout::LayoutOptions;
pub trait Arrangement {
#[allow(clippy::too_many_arguments)]
fn calculate(
&self,
area: &Rect,
@@ -21,6 +23,9 @@ pub trait Arrangement {
container_padding: Option<i32>,
layout_flip: Option<Axis>,
resize_dimensions: &[Option<Rect>],
focused_idx: usize,
layout_options: Option<LayoutOptions>,
latest_layout: &[Rect],
) -> Vec<Rect>;
}
@@ -33,9 +38,110 @@ impl Arrangement for DefaultLayout {
container_padding: Option<i32>,
layout_flip: Option<Axis>,
resize_dimensions: &[Option<Rect>],
focused_idx: usize,
layout_options: Option<LayoutOptions>,
latest_layout: &[Rect],
) -> Vec<Rect> {
let len = usize::from(len);
let mut dimensions = match self {
Self::Scrolling => {
let column_count = layout_options
.and_then(|o| o.scrolling.map(|s| s.columns))
.unwrap_or(3);
let column_width = area.right / column_count as i32;
let mut layouts = Vec::with_capacity(len);
match len {
// treat < 3 windows the same as the columns layout
len if len < 3 => {
layouts = columns(area, len);
let adjustment = calculate_columns_adjustment(resize_dimensions);
layouts.iter_mut().zip(adjustment.iter()).for_each(
|(layout, adjustment)| {
layout.top += adjustment.top;
layout.bottom += adjustment.bottom;
layout.left += adjustment.left;
layout.right += adjustment.right;
},
);
if matches!(
layout_flip,
Some(Axis::Horizontal | Axis::HorizontalAndVertical)
) {
if let 2.. = len {
columns_reverse(&mut layouts);
}
}
}
// treat >= column_count as scrolling
len => {
let visible_columns = area.right / column_width;
let first_visible: isize = if focused_idx == 0 {
// if focused idx is 0, we are at the beginning of the scrolling strip
0
} else {
let previous_first_visible = if latest_layout.is_empty() {
0
} else {
// previous first_visible based on the left position of the first visible window
let left_edge = area.left;
latest_layout
.iter()
.position(|rect| rect.left >= left_edge)
.unwrap_or(0) as isize
};
let focused_idx = focused_idx as isize;
if focused_idx < previous_first_visible {
// focused window is off the left edge, we need to scroll left
focused_idx
} else if focused_idx
>= previous_first_visible + visible_columns as isize
{
// focused window is off the right edge, we need to scroll right
// and make sure it's the last visible window
(focused_idx + 1 - visible_columns as isize).max(0)
} else {
// focused window is already visible, we don't need to scroll
previous_first_visible
}
.min(
(len as isize)
.saturating_sub(visible_columns as isize)
.max(0),
)
};
for i in 0..len {
let position = (i as isize) - first_visible;
let left = area.left + (position as i32 * column_width);
layouts.push(Rect {
left,
top: area.top,
right: column_width,
bottom: area.bottom,
});
}
let adjustment = calculate_scrolling_adjustment(resize_dimensions);
layouts.iter_mut().zip(adjustment.iter()).for_each(
|(layout, adjustment)| {
layout.top += adjustment.top;
layout.bottom += adjustment.bottom;
layout.left += adjustment.left;
layout.right += adjustment.right;
},
);
}
}
layouts
}
Self::BSP => recursive_fibonacci(
0,
len,
@@ -487,6 +593,9 @@ impl Arrangement for CustomLayout {
container_padding: Option<i32>,
_layout_flip: Option<Axis>,
_resize_dimensions: &[Option<Rect>],
_focused_idx: usize,
_layout_options: Option<LayoutOptions>,
_latest_layout: &[Rect],
) -> Vec<Rect> {
let mut dimensions = vec![];
let container_count = len.get();
@@ -541,7 +650,7 @@ impl Arrangement for CustomLayout {
};
match column {
Column::Primary(Option::Some(_)) => {
Column::Primary(Some(_)) => {
let main_column_area = if idx == 0 {
Self::main_column_area(area, primary_right, None)
} else {
@@ -1115,6 +1224,37 @@ fn calculate_ultrawide_adjustment(resize_dimensions: &[Option<Rect>]) -> Vec<Rec
result
}
fn calculate_scrolling_adjustment(resize_dimensions: &[Option<Rect>]) -> Vec<Rect> {
let len = resize_dimensions.len();
let mut result = vec![Rect::default(); len];
if len <= 1 {
return result;
}
for (i, rect) in resize_dimensions.iter().enumerate() {
if let Some(rect) = rect {
let is_leftmost = i == 0;
let is_rightmost = i == len - 1;
resize_left(&mut result[i], rect.left);
resize_right(&mut result[i], rect.right);
resize_top(&mut result[i], rect.top);
resize_bottom(&mut result[i], rect.bottom);
if !is_leftmost && rect.left != 0 {
resize_right(&mut result[i - 1], rect.left);
}
if !is_rightmost && rect.right != 0 {
resize_left(&mut result[i + 1], rect.right);
}
}
}
result
}
fn resize_left(rect: &mut Rect, resize: i32) {
rect.left += resize / 2;
rect.right += -resize / 2;

View File

@@ -21,9 +21,24 @@ pub enum DefaultLayout {
UltrawideVerticalStack,
Grid,
RightMainVerticalStack,
Scrolling,
// NOTE: If any new layout is added, please make sure to register the same in `DefaultLayout::cycle`
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct LayoutOptions {
/// Options related to the Scrolling layout
pub scrolling: Option<ScrollingLayoutOptions>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, PartialEq)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct ScrollingLayoutOptions {
/// Desired number of visible columns (default: 3)
pub columns: usize,
}
impl DefaultLayout {
pub fn leftmost_index(&self, len: usize) -> usize {
match self {
@@ -31,6 +46,7 @@ impl DefaultLayout {
n if n > 1 => 1,
_ => 0,
},
Self::Scrolling => 0,
DefaultLayout::BSP
| DefaultLayout::Columns
| DefaultLayout::Rows
@@ -53,6 +69,7 @@ impl DefaultLayout {
_ => len.saturating_sub(1),
},
DefaultLayout::RightMainVerticalStack => 0,
DefaultLayout::Scrolling => len.saturating_sub(1),
}
}
@@ -75,6 +92,7 @@ impl DefaultLayout {
| Self::RightMainVerticalStack
| Self::HorizontalStack
| Self::UltrawideVerticalStack
| Self::Scrolling
) {
return None;
};
@@ -169,13 +187,15 @@ impl DefaultLayout {
Self::HorizontalStack => Self::UltrawideVerticalStack,
Self::UltrawideVerticalStack => Self::Grid,
Self::Grid => Self::RightMainVerticalStack,
Self::RightMainVerticalStack => Self::BSP,
Self::RightMainVerticalStack => Self::Scrolling,
Self::Scrolling => Self::BSP,
}
}
#[must_use]
pub const fn cycle_previous(self) -> Self {
match self {
Self::Scrolling => Self::RightMainVerticalStack,
Self::RightMainVerticalStack => Self::Grid,
Self::Grid => Self::UltrawideVerticalStack,
Self::UltrawideVerticalStack => Self::HorizontalStack,

View File

@@ -102,6 +102,7 @@ impl Direction for DefaultLayout {
Self::VerticalStack | Self::RightMainVerticalStack => idx != 0 && idx != 1,
Self::UltrawideVerticalStack => idx > 2,
Self::Grid => !is_grid_edge(op_direction, idx, count),
Self::Scrolling => false,
},
OperationDirection::Down => match self {
Self::BSP => idx != count - 1 && idx % 2 != 0,
@@ -111,6 +112,7 @@ impl Direction for DefaultLayout {
Self::HorizontalStack => idx == 0,
Self::UltrawideVerticalStack => idx > 1 && idx != count - 1,
Self::Grid => !is_grid_edge(op_direction, idx, count),
Self::Scrolling => false,
},
OperationDirection::Left => match self {
Self::BSP => idx != 0,
@@ -120,6 +122,7 @@ impl Direction for DefaultLayout {
Self::HorizontalStack => idx != 0 && idx != 1,
Self::UltrawideVerticalStack => idx != 1,
Self::Grid => !is_grid_edge(op_direction, idx, count),
Self::Scrolling => idx != 0,
},
OperationDirection::Right => match self {
Self::BSP => idx % 2 == 0 && idx != count - 1,
@@ -133,6 +136,7 @@ impl Direction for DefaultLayout {
_ => idx < 2,
},
Self::Grid => !is_grid_edge(op_direction, idx, count),
Self::Scrolling => idx != count - 1,
},
}
}
@@ -158,6 +162,7 @@ impl Direction for DefaultLayout {
| Self::RightMainVerticalStack => idx - 1,
Self::HorizontalStack => 0,
Self::Grid => grid_neighbor(op_direction, idx, count),
Self::Scrolling => unreachable!(),
}
}
@@ -176,6 +181,7 @@ impl Direction for DefaultLayout {
Self::Columns => unreachable!(),
Self::HorizontalStack => 1,
Self::Grid => grid_neighbor(op_direction, idx, count),
Self::Scrolling => unreachable!(),
}
}
@@ -203,6 +209,7 @@ impl Direction for DefaultLayout {
_ => 0,
},
Self::Grid => grid_neighbor(op_direction, idx, count),
Self::Scrolling => idx - 1,
}
}
@@ -223,6 +230,7 @@ impl Direction for DefaultLayout {
_ => unreachable!(),
},
Self::Grid => grid_neighbor(op_direction, idx, count),
Self::Scrolling => idx + 1,
}
}
}

View File

@@ -1,6 +1,7 @@
#![warn(clippy::all)]
#![allow(clippy::missing_errors_doc, clippy::use_self, clippy::doc_markdown)]
use std::num::NonZeroUsize;
use std::path::PathBuf;
use std::str::FromStr;
@@ -108,6 +109,7 @@ pub enum SocketMessage {
AdjustWorkspacePadding(Sizing, i32),
ChangeLayout(DefaultLayout),
CycleLayout(CycleDirection),
ScrollingLayoutColumns(NonZeroUsize),
ChangeLayoutCustom(#[serde_as(as = "ResolvedPathBuf")] PathBuf),
FlipLayout(Axis),
ToggleWorkspaceWindowContainerBehaviour,

View File

@@ -41,6 +41,10 @@ impl Rect {
pub fn is_same_size_as(&self, rhs: &Self) -> bool {
self.right == rhs.right && self.bottom == rhs.bottom
}
pub fn has_same_position_as(&self, rhs: &Self) -> bool {
self.left == rhs.left && self.top == rhs.top
}
}
impl Rect {

View File

@@ -49,6 +49,8 @@ use crate::core::StateQuery;
use crate::core::WindowContainerBehaviour;
use crate::core::WindowKind;
use crate::current_virtual_desktop;
use crate::default_layout::LayoutOptions;
use crate::default_layout::ScrollingLayoutOptions;
use crate::monitor::MonitorInformation;
use crate::notify_subscribers;
use crate::stackbar_manager;
@@ -933,6 +935,27 @@ impl WindowManager {
self.retile_all(true)?
}
SocketMessage::FlipLayout(layout_flip) => self.flip_layout(layout_flip)?,
SocketMessage::ScrollingLayoutColumns(count) => {
let focused_workspace = self.focused_workspace_mut()?;
let options = match focused_workspace.layout_options() {
Some(mut opts) => {
if let Some(scrolling) = &mut opts.scrolling {
scrolling.columns = count.into();
}
opts
}
None => LayoutOptions {
scrolling: Some(ScrollingLayoutOptions {
columns: count.into(),
}),
},
};
focused_workspace.set_layout_options(Some(options));
self.update_focused_workspace(false, false)?;
}
SocketMessage::ChangeLayout(layout) => self.change_workspace_layout_default(layout)?,
SocketMessage::CycleLayout(direction) => self.cycle_layout(direction)?,
SocketMessage::ChangeLayoutCustom(ref path) => {
@@ -1751,7 +1774,7 @@ Stop-Process -Name:komorebi-bar -ErrorAction SilentlyContinue
{
for config_file_path in &mut *display_bar_configurations {
let script = r#"Start-Process "komorebi-bar" '"--config" "CONFIGFILE"' -WindowStyle hidden"#
.replace("CONFIGFILE", &config_file_path.to_string_lossy());
.replace("CONFIGFILE", &config_file_path.to_string_lossy());
match powershell_script::run(&script) {
Ok(_) => {

View File

@@ -25,6 +25,8 @@ use crate::window_manager_event::WindowManagerEvent;
use crate::windows_api::WindowsApi;
use crate::winevent::WinEvent;
use crate::workspace::WorkspaceLayer;
use crate::DefaultLayout;
use crate::Layout;
use crate::Notification;
use crate::NotificationEvent;
use crate::State;
@@ -301,7 +303,11 @@ impl WindowManager {
// don't want to trigger the full workspace updates when there are no managed
// containers - this makes floating windows on empty workspaces go into very
// annoying focus change loops which prevents users from interacting with them
if !self.focused_workspace()?.containers().is_empty() {
if !matches!(
self.focused_workspace()?.layout(),
Layout::Default(DefaultLayout::Scrolling)
) && !self.focused_workspace()?.containers().is_empty()
{
self.update_focused_workspace(self.mouse_follows_focus, false)?;
}
@@ -328,6 +334,14 @@ impl WindowManager {
}
workspace.set_layer(WorkspaceLayer::Tiling);
if matches!(
self.focused_workspace()?.layout(),
Layout::Default(DefaultLayout::Scrolling)
) && !self.focused_workspace()?.containers().is_empty()
{
self.update_focused_workspace(self.mouse_follows_focus, false)?;
}
}
Some(idx) => {
if let Some(_window) = workspace.floating_windows().get(idx) {

View File

@@ -35,6 +35,7 @@ use crate::core::StackbarMode;
use crate::core::WindowContainerBehaviour;
use crate::core::WindowManagementBehaviour;
use crate::current_virtual_desktop;
use crate::default_layout::LayoutOptions;
use crate::monitor;
use crate::monitor::Monitor;
use crate::monitor_reconciliator;
@@ -191,6 +192,9 @@ pub struct WorkspaceConfig {
/// Layout (default: BSP)
#[serde(skip_serializing_if = "Option::is_none")]
pub layout: Option<DefaultLayout>,
/// Layout-specific options(default: None)
#[serde(skip_serializing_if = "Option::is_none")]
pub layout_options: Option<LayoutOptions>,
/// END OF LIFE FEATURE: Custom Layout (default: None)
#[serde(skip_serializing_if = "Option::is_none")]
#[serde_as(as = "Option<ResolvedPathBuf>")]
@@ -286,6 +290,7 @@ impl From<&Workspace> for WorkspaceConfig {
Layout::Custom(_) => None,
})
.flatten(),
layout_options: value.layout_options(),
custom_layout: value
.workspace_config()
.as_ref()
@@ -1331,7 +1336,7 @@ impl StaticConfig {
}
pub fn postload(path: &PathBuf, wm: &Arc<Mutex<WindowManager>>) -> Result<()> {
let value = Self::read(path)?;
let mut value = Self::read(path)?;
let mut wm = wm.lock();
let configs_with_preference: Vec<_> =
@@ -1342,6 +1347,8 @@ impl StaticConfig {
workspace_matching_rules.clear();
drop(workspace_matching_rules);
let monitor_count = wm.monitors().len();
let offset = wm.work_area_offset;
for (i, monitor) in wm.monitors_mut().iter_mut().enumerate() {
let preferred_config_idx = {
@@ -1371,8 +1378,8 @@ impl StaticConfig {
});
if let Some(monitor_config) = value
.monitors
.as_ref()
.and_then(|ms| idx.and_then(|i| ms.get(i)))
.as_mut()
.and_then(|ms| idx.and_then(|i| ms.get_mut(i)))
{
if let Some(used_config_idx) = idx {
configs_used.push(used_config_idx);
@@ -1395,7 +1402,14 @@ impl StaticConfig {
monitor.update_workspaces_globals(offset);
for (j, ws) in monitor.workspaces_mut().iter_mut().enumerate() {
if let Some(workspace_config) = monitor_config.workspaces.get(j) {
if let Some(workspace_config) = monitor_config.workspaces.get_mut(j) {
if monitor_count > 1
&& matches!(workspace_config.layout, Some(DefaultLayout::Scrolling))
{
tracing::warn!("scrolling layout is only supported for a single monitor; falling back to columns layout");
workspace_config.layout = Some(DefaultLayout::Columns);
}
ws.load_static_config(workspace_config)?;
}
}

View File

@@ -329,6 +329,7 @@ impl From<&WindowManager> for State {
maximized_window_restore_idx: workspace.maximized_window_restore_idx,
floating_windows: workspace.floating_windows.clone(),
layout: workspace.layout.clone(),
layout_options: workspace.layout_options,
layout_rules: workspace.layout_rules.clone(),
layout_flip: workspace.layout_flip,
workspace_padding: workspace.workspace_padding,
@@ -1579,6 +1580,9 @@ impl WindowManager {
workspace.container_padding(),
workspace.layout_flip(),
&[],
workspace.focused_container_idx(),
workspace.layout_options(),
workspace.latest_layout(),
);
let mut direction = direction;
@@ -3352,8 +3356,16 @@ impl WindowManager {
pub fn change_workspace_layout_default(&mut self, layout: DefaultLayout) -> Result<()> {
tracing::info!("changing layout");
let monitor_count = self.monitors().len();
let workspace = self.focused_workspace_mut()?;
if monitor_count > 1 && matches!(layout, DefaultLayout::Scrolling) {
tracing::warn!(
"scrolling layout is only supported for a single monitor; not changing layout"
);
return Ok(());
}
match workspace.layout() {
Layout::Default(_) => {}
Layout::Custom(layout) => {

View File

@@ -16,6 +16,7 @@ use crate::core::DefaultLayout;
use crate::core::Layout;
use crate::core::OperationDirection;
use crate::core::Rect;
use crate::default_layout::LayoutOptions;
use crate::locked_deque::LockedDeque;
use crate::ring::Ring;
use crate::should_act;
@@ -70,6 +71,8 @@ pub struct Workspace {
pub floating_windows: Ring<Window>,
#[getset(get = "pub", get_mut = "pub", set = "pub")]
pub layout: Layout,
#[getset(get_copy = "pub", set = "pub")]
pub layout_options: Option<LayoutOptions>,
#[getset(get = "pub", get_mut = "pub", set = "pub")]
pub layout_rules: Vec<(usize, Layout)>,
#[getset(get_copy = "pub", set = "pub")]
@@ -139,6 +142,7 @@ impl Default for Workspace {
monocle_container_restore_idx: None,
floating_windows: Ring::default(),
layout: Layout::Default(DefaultLayout::BSP),
layout_options: None,
layout_rules: vec![],
layout_flip: None,
workspace_padding: Option::from(DEFAULT_WORKSPACE_PADDING.load(Ordering::SeqCst)),
@@ -267,6 +271,7 @@ impl Workspace {
self.set_layout_flip(config.layout_flip);
self.set_floating_layer_behaviour(config.floating_layer_behaviour);
self.set_wallpaper(config.wallpaper.clone());
self.set_layout_options(config.layout_options);
self.set_workspace_config(Some(config.clone()));
@@ -583,6 +588,9 @@ impl Workspace {
Some(container_padding),
self.layout_flip(),
self.resize_dimensions(),
self.focused_container_idx(),
self.layout_options(),
self.latest_layout(),
);
let should_remove_titlebars = REMOVE_TITLEBARS.load(Ordering::SeqCst);
@@ -1194,6 +1202,9 @@ impl Workspace {
Layout::Default(DefaultLayout::UltrawideVerticalStack) => {
self.enforce_resize_for_ultrawide();
}
Layout::Default(DefaultLayout::Scrolling) => {
self.enforce_resize_for_scrolling();
}
_ => self.enforce_no_resize(),
}
}
@@ -1421,6 +1432,28 @@ impl Workspace {
}
}
fn enforce_resize_for_scrolling(&mut self) {
let resize_dimensions = self.resize_dimensions_mut();
match resize_dimensions.len() {
0 | 1 => self.enforce_no_resize(),
_ => {
let len = resize_dimensions.len();
for (i, rect) in resize_dimensions.iter_mut().enumerate() {
if let Some(rect) = rect {
rect.top = 0;
rect.bottom = 0;
if i == 0 {
rect.left = 0;
} else if i == len - 1 {
rect.right = 0;
}
}
}
}
}
}
fn enforce_no_resize(&mut self) {
for rect in self.resize_dimensions_mut().iter_mut().flatten() {
rect.left = 0;

View File

@@ -9,6 +9,7 @@ use std::fs::OpenOptions;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Write;
use std::num::NonZeroUsize;
use std::path::PathBuf;
use std::process::Command;
use std::sync::atomic::AtomicBool;
@@ -963,6 +964,12 @@ struct EagerFocus {
exe: String,
}
#[derive(Parser)]
struct ScrollingLayoutColumns {
/// Desired number of visible columns
count: NonZeroUsize,
}
#[derive(Parser)]
#[clap(author, about, version = build::CLAP_LONG_VERSION)]
struct Opts {
@@ -1202,6 +1209,9 @@ enum SubCommand {
/// Cycle between available layouts
#[clap(arg_required_else_help = true)]
CycleLayout(CycleLayout),
/// Set the number of visible columns for the Scrolling layout on the focused workspace
#[clap(arg_required_else_help = true)]
ScrollingLayoutColumns(ScrollingLayoutColumns),
/// Load a custom layout from file for the focused workspace
#[clap(hide = true)]
#[clap(arg_required_else_help = true)]
@@ -2625,6 +2635,9 @@ if (Get-Command Get-CimInstance -ErrorAction SilentlyContinue) {
SubCommand::CycleLayout(arg) => {
send_message(&SocketMessage::CycleLayout(arg.cycle_direction))?;
}
SubCommand::ScrollingLayoutColumns(arg) => {
send_message(&SocketMessage::ScrollingLayoutColumns(arg.count))?;
}
SubCommand::LoadCustomLayout(arg) => {
send_message(&SocketMessage::ChangeLayoutCustom(arg.path))?;
}

View File

@@ -616,7 +616,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
},
{
@@ -2259,7 +2260,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
},
{
@@ -4294,7 +4296,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
},
"type": {
@@ -4327,6 +4330,26 @@
}
}
},
{
"type": "object",
"required": [
"content",
"type"
],
"properties": {
"content": {
"type": "integer",
"format": "uint",
"minimum": 1.0
},
"type": {
"type": "string",
"enum": [
"ScrollingLayoutColumns"
]
}
}
},
{
"type": "object",
"required": [
@@ -5210,7 +5233,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -5248,7 +5272,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -5361,7 +5386,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -5404,7 +5430,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -10365,7 +10392,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
},
"type": {
@@ -10398,6 +10426,26 @@
}
}
},
{
"type": "object",
"required": [
"content",
"type"
],
"properties": {
"content": {
"type": "integer",
"format": "uint",
"minimum": 1.0
},
"type": {
"type": "string",
"enum": [
"ScrollingLayoutColumns"
]
}
}
},
{
"type": "object",
"required": [
@@ -11281,7 +11329,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -11319,7 +11368,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -11432,7 +11482,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -11475,7 +11526,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -16436,7 +16488,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
},
"type": {
@@ -16469,6 +16522,26 @@
}
}
},
{
"type": "object",
"required": [
"content",
"type"
],
"properties": {
"content": {
"type": "integer",
"format": "uint",
"minimum": 1.0
},
"type": {
"type": "string",
"enum": [
"ScrollingLayoutColumns"
]
}
}
},
{
"type": "object",
"required": [
@@ -17352,7 +17425,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -17390,7 +17464,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -17503,7 +17578,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -17546,7 +17622,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -22507,7 +22584,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
},
"type": {
@@ -22540,6 +22618,26 @@
}
}
},
{
"type": "object",
"required": [
"content",
"type"
],
"properties": {
"content": {
"type": "integer",
"format": "uint",
"minimum": 1.0
},
"type": {
"type": "string",
"enum": [
"ScrollingLayoutColumns"
]
}
}
},
{
"type": "object",
"required": [
@@ -23423,7 +23521,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -23461,7 +23560,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -23574,7 +23674,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -23617,7 +23718,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -28578,7 +28680,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
},
"type": {
@@ -28611,6 +28714,26 @@
}
}
},
{
"type": "object",
"required": [
"content",
"type"
],
"properties": {
"content": {
"type": "integer",
"format": "uint",
"minimum": 1.0
},
"type": {
"type": "string",
"enum": [
"ScrollingLayoutColumns"
]
}
}
},
{
"type": "object",
"required": [
@@ -29494,7 +29617,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -29532,7 +29656,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -29645,7 +29770,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -29688,7 +29814,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -34649,7 +34776,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
},
"type": {
@@ -34682,6 +34810,26 @@
}
}
},
{
"type": "object",
"required": [
"content",
"type"
],
"properties": {
"content": {
"type": "integer",
"format": "uint",
"minimum": 1.0
},
"type": {
"type": "string",
"enum": [
"ScrollingLayoutColumns"
]
}
}
},
{
"type": "object",
"required": [
@@ -35565,7 +35713,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -35603,7 +35752,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -35716,7 +35866,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -35759,7 +35910,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -40720,7 +40872,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
},
"type": {
@@ -40753,6 +40906,26 @@
}
}
},
{
"type": "object",
"required": [
"content",
"type"
],
"properties": {
"content": {
"type": "integer",
"format": "uint",
"minimum": 1.0
},
"type": {
"type": "string",
"enum": [
"ScrollingLayoutColumns"
]
}
}
},
{
"type": "object",
"required": [
@@ -41636,7 +41809,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -41674,7 +41848,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -41787,7 +41962,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -41830,7 +42006,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -46791,7 +46968,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
},
"type": {
@@ -46824,6 +47002,26 @@
}
}
},
{
"type": "object",
"required": [
"content",
"type"
],
"properties": {
"content": {
"type": "integer",
"format": "uint",
"minimum": 1.0
},
"type": {
"type": "string",
"enum": [
"ScrollingLayoutColumns"
]
}
}
},
{
"type": "object",
"required": [
@@ -47707,7 +47905,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -47745,7 +47944,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -47858,7 +48058,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -47901,7 +48102,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -52862,7 +53064,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
},
"type": {
@@ -52895,6 +53098,26 @@
}
}
},
{
"type": "object",
"required": [
"content",
"type"
],
"properties": {
"content": {
"type": "integer",
"format": "uint",
"minimum": 1.0
},
"type": {
"type": "string",
"enum": [
"ScrollingLayoutColumns"
]
}
}
},
{
"type": "object",
"required": [
@@ -53778,7 +54001,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -53816,7 +54040,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -53929,7 +54154,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -53972,7 +54198,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
],
@@ -58490,7 +58717,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
},
{

View File

@@ -1790,7 +1790,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
},
"layout_flip": {
@@ -1802,6 +1803,27 @@
"HorizontalAndVertical"
]
},
"layout_options": {
"description": "Layout-specific options(default: None)",
"type": "object",
"properties": {
"scrolling": {
"description": "Options related to the Scrolling layout",
"type": "object",
"required": [
"columns"
],
"properties": {
"columns": {
"description": "Desired number of visible columns (default: 3)",
"type": "integer",
"format": "uint",
"minimum": 0.0
}
}
}
}
},
"layout_rules": {
"description": "Layout rules in the format of threshold => layout (default: None)",
"type": "object",
@@ -1815,7 +1837,8 @@
"HorizontalStack",
"UltrawideVerticalStack",
"Grid",
"RightMainVerticalStack"
"RightMainVerticalStack",
"Scrolling"
]
}
},