Merge pull request #449 from khyperia/relative-behavior-mode
implement new setting: fallback output mode
This commit is contained in:
commit
2f4543912b
29 changed files with 306 additions and 55 deletions
|
|
@ -15,8 +15,9 @@ use {
|
||||||
client::{Client, ClientCapabilities, ClientCriterion, ClientMatcher, MatchedClient},
|
client::{Client, ClientCapabilities, ClientCriterion, ClientMatcher, MatchedClient},
|
||||||
exec::Command,
|
exec::Command,
|
||||||
input::{
|
input::{
|
||||||
FocusFollowsMouseMode, InputDevice, LayerDirection, Seat, SwitchEvent, Timeline,
|
FallbackOutputMode, FocusFollowsMouseMode, InputDevice, LayerDirection, Seat,
|
||||||
acceleration::AccelProfile, capability::Capability, clickmethod::ClickMethod,
|
SwitchEvent, Timeline, acceleration::AccelProfile, capability::Capability,
|
||||||
|
clickmethod::ClickMethod,
|
||||||
},
|
},
|
||||||
keyboard::{
|
keyboard::{
|
||||||
Group, Keymap,
|
Group, Keymap,
|
||||||
|
|
@ -551,9 +552,9 @@ impl ConfigClient {
|
||||||
connector
|
connector
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_seat_workspace(&self, seat: Seat) -> Workspace {
|
pub fn get_seat_cursor_workspace(&self, seat: Seat) -> Workspace {
|
||||||
let res = self.send_with_response(&ClientMessage::GetSeatWorkspace { seat });
|
let res = self.send_with_response(&ClientMessage::GetSeatCursorWorkspace { seat });
|
||||||
get_response!(res, Workspace(0), GetSeatWorkspace { workspace });
|
get_response!(res, Workspace(0), GetSeatCursorWorkspace { workspace });
|
||||||
workspace
|
workspace
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1364,6 +1365,10 @@ impl ConfigClient {
|
||||||
self.send(&ClientMessage::SetFocusFollowsMouseMode { seat, mode })
|
self.send(&ClientMessage::SetFocusFollowsMouseMode { seat, mode })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_fallback_output_mode(&self, seat: Seat, mode: FallbackOutputMode) {
|
||||||
|
self.send(&ClientMessage::SetFallbackOutputMode { seat, mode })
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_window_management_enabled(&self, seat: Seat, enabled: bool) {
|
pub fn set_window_management_enabled(&self, seat: Seat, enabled: bool) {
|
||||||
self.send(&ClientMessage::SetWindowManagementEnabled { seat, enabled })
|
self.send(&ClientMessage::SetWindowManagementEnabled { seat, enabled })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,9 @@ use {
|
||||||
Axis, Direction, PciId, Workspace,
|
Axis, Direction, PciId, Workspace,
|
||||||
client::{Client, ClientCapabilities, ClientMatcher},
|
client::{Client, ClientCapabilities, ClientMatcher},
|
||||||
input::{
|
input::{
|
||||||
FocusFollowsMouseMode, InputDevice, LayerDirection, Seat, SwitchEvent, Timeline,
|
FallbackOutputMode, FocusFollowsMouseMode, InputDevice, LayerDirection, Seat,
|
||||||
acceleration::AccelProfile, capability::Capability, clickmethod::ClickMethod,
|
SwitchEvent, Timeline, acceleration::AccelProfile, capability::Capability,
|
||||||
|
clickmethod::ClickMethod,
|
||||||
},
|
},
|
||||||
keyboard::{Group, Keymap, mods::Modifiers, syms::KeySym},
|
keyboard::{Group, Keymap, mods::Modifiers, syms::KeySym},
|
||||||
logging::LogLevel,
|
logging::LogLevel,
|
||||||
|
|
@ -372,7 +373,7 @@ pub enum ClientMessage<'a> {
|
||||||
MakeRenderDevice {
|
MakeRenderDevice {
|
||||||
device: DrmDevice,
|
device: DrmDevice,
|
||||||
},
|
},
|
||||||
GetSeatWorkspace {
|
GetSeatCursorWorkspace {
|
||||||
seat: Seat,
|
seat: Seat,
|
||||||
},
|
},
|
||||||
SetDefaultWorkspaceCapture {
|
SetDefaultWorkspaceCapture {
|
||||||
|
|
@ -826,6 +827,10 @@ pub enum ClientMessage<'a> {
|
||||||
groups: Option<Vec<Group<'a>>>,
|
groups: Option<Vec<Group<'a>>>,
|
||||||
options: Option<Vec<&'a str>>,
|
options: Option<Vec<&'a str>>,
|
||||||
},
|
},
|
||||||
|
SetFallbackOutputMode {
|
||||||
|
seat: Seat,
|
||||||
|
mode: FallbackOutputMode,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
@ -925,7 +930,7 @@ pub enum Response {
|
||||||
width: i32,
|
width: i32,
|
||||||
height: i32,
|
height: i32,
|
||||||
},
|
},
|
||||||
GetSeatWorkspace {
|
GetSeatCursorWorkspace {
|
||||||
workspace: Workspace,
|
workspace: Workspace,
|
||||||
},
|
},
|
||||||
GetDefaultWorkspaceCapture {
|
GetDefaultWorkspaceCapture {
|
||||||
|
|
|
||||||
|
|
@ -420,7 +420,7 @@ impl Seat {
|
||||||
///
|
///
|
||||||
/// If no such workspace exists, `exists` returns `false` for the returned workspace.
|
/// If no such workspace exists, `exists` returns `false` for the returned workspace.
|
||||||
pub fn get_workspace(self) -> Workspace {
|
pub fn get_workspace(self) -> Workspace {
|
||||||
get!(Workspace(0)).get_seat_workspace(self)
|
get!(Workspace(0)).get_seat_cursor_workspace(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the workspace that is currently active on the output that contains the seat's
|
/// Returns the workspace that is currently active on the output that contains the seat's
|
||||||
|
|
@ -503,6 +503,13 @@ impl Seat {
|
||||||
get!().set_focus_follows_mouse_mode(self, mode);
|
get!().set_focus_follows_mouse_mode(self, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the fallback output mode.
|
||||||
|
///
|
||||||
|
/// The default is `Cursor`.
|
||||||
|
pub fn set_fallback_output_mode(self, mode: FallbackOutputMode) {
|
||||||
|
get!().set_fallback_output_mode(self, mode);
|
||||||
|
}
|
||||||
|
|
||||||
/// Enables or disable window management mode.
|
/// Enables or disable window management mode.
|
||||||
///
|
///
|
||||||
/// In window management mode, floating windows can be moved by pressing the left
|
/// In window management mode, floating windows can be moved by pressing the left
|
||||||
|
|
@ -650,6 +657,19 @@ pub enum FocusFollowsMouseMode {
|
||||||
False,
|
False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines which output is used when no particular output is specified.
|
||||||
|
///
|
||||||
|
/// This configures where to place a newly opened window or workspace, what window to focus when a
|
||||||
|
/// window is closed, which workspace is moved with [`Seat::move_to_output`], and similar actions.
|
||||||
|
#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum FallbackOutputMode {
|
||||||
|
/// Use the output the cursor is on.
|
||||||
|
Cursor,
|
||||||
|
/// Use the output the focus is on (highlighted window).
|
||||||
|
Focus,
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns all seats.
|
/// Returns all seats.
|
||||||
pub fn get_seats() -> Vec<Seat> {
|
pub fn get_seats() -> Vec<Seat> {
|
||||||
get!().seats()
|
get!().seats()
|
||||||
|
|
|
||||||
|
|
@ -728,6 +728,7 @@ fn create_dummy_output(state: &Rc<State>) {
|
||||||
bar_rect: Default::default(),
|
bar_rect: Default::default(),
|
||||||
bar_rect_rel: Default::default(),
|
bar_rect_rel: Default::default(),
|
||||||
bar_rect_with_separator: Default::default(),
|
bar_rect_with_separator: Default::default(),
|
||||||
|
bar_separator_rect: Default::default(),
|
||||||
bar_separator_rect_rel: Default::default(),
|
bar_separator_rect_rel: Default::default(),
|
||||||
non_exclusive_rect: Default::default(),
|
non_exclusive_rect: Default::default(),
|
||||||
render_data: Default::default(),
|
render_data: Default::default(),
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ use {
|
||||||
Axis, Direction, Workspace,
|
Axis, Direction, Workspace,
|
||||||
client::{Client as ConfigClient, ClientCapabilities, ClientMatcher},
|
client::{Client as ConfigClient, ClientCapabilities, ClientMatcher},
|
||||||
input::{
|
input::{
|
||||||
FocusFollowsMouseMode, InputDevice, LayerDirection, Seat, Timeline,
|
FallbackOutputMode, FocusFollowsMouseMode, InputDevice, LayerDirection, Seat, Timeline,
|
||||||
acceleration::{ACCEL_PROFILE_ADAPTIVE, ACCEL_PROFILE_FLAT, AccelProfile},
|
acceleration::{ACCEL_PROFILE_ADAPTIVE, ACCEL_PROFILE_FLAT, AccelProfile},
|
||||||
capability::{
|
capability::{
|
||||||
CAP_GESTURE, CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD,
|
CAP_GESTURE, CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD,
|
||||||
|
|
@ -518,6 +518,16 @@ impl ConfigProxyHandler {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_set_fallback_output_mode(
|
||||||
|
&self,
|
||||||
|
seat: Seat,
|
||||||
|
mode: FallbackOutputMode,
|
||||||
|
) -> Result<(), CphError> {
|
||||||
|
let seat = self.get_seat(seat)?;
|
||||||
|
seat.set_fallback_output_mode(mode);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_set_window_management_enabled(
|
fn handle_set_window_management_enabled(
|
||||||
&self,
|
&self,
|
||||||
seat: Seat,
|
seat: Seat,
|
||||||
|
|
@ -1012,16 +1022,16 @@ impl ConfigProxyHandler {
|
||||||
self.state.double_click_distance.set(dist);
|
self.state.double_click_distance.set(dist);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_get_seat_workspace(&self, seat: Seat) -> Result<(), CphError> {
|
fn handle_get_seat_cursor_workspace(&self, seat: Seat) -> Result<(), CphError> {
|
||||||
let seat = self.get_seat(seat)?;
|
let seat = self.get_seat(seat)?;
|
||||||
let output = seat.get_output();
|
let output = seat.get_cursor_output();
|
||||||
let mut workspace = Workspace(0);
|
let mut workspace = Workspace(0);
|
||||||
if !output.is_dummy
|
if !output.is_dummy
|
||||||
&& let Some(ws) = output.workspace.get()
|
&& let Some(ws) = output.workspace.get()
|
||||||
{
|
{
|
||||||
workspace = self.get_workspace_by_name(&ws.name);
|
workspace = self.get_workspace_by_name(&ws.name);
|
||||||
}
|
}
|
||||||
self.respond(Response::GetSeatWorkspace { workspace });
|
self.respond(Response::GetSeatCursorWorkspace { workspace });
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1056,7 +1066,7 @@ impl ConfigProxyHandler {
|
||||||
let name = self.get_workspace(ws)?;
|
let name = self.get_workspace(ws)?;
|
||||||
let workspace = match self.state.workspaces.get(name.deref()) {
|
let workspace = match self.state.workspaces.get(name.deref()) {
|
||||||
Some(ws) => ws,
|
Some(ws) => ws,
|
||||||
_ => seat.get_output().create_workspace(name.deref()),
|
_ => seat.get_fallback_output().create_workspace(name.deref()),
|
||||||
};
|
};
|
||||||
seat.set_workspace(&workspace);
|
seat.set_workspace(&workspace);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -1112,10 +1122,12 @@ impl ConfigProxyHandler {
|
||||||
Some(ws) => ws,
|
Some(ws) => ws,
|
||||||
_ => return Ok(()),
|
_ => return Ok(()),
|
||||||
},
|
},
|
||||||
WorkspaceSource::Seat(s) => match self.get_seat(s)?.get_output().workspace.get() {
|
WorkspaceSource::Seat(s) => {
|
||||||
Some(ws) => ws,
|
match self.get_seat(s)?.get_fallback_output().workspace.get() {
|
||||||
_ => return Ok(()),
|
Some(ws) => ws,
|
||||||
},
|
_ => return Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
self.state.move_ws_to_output(&ws, &output);
|
self.state.move_ws_to_output(&ws, &output);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -2935,9 +2947,9 @@ impl ConfigProxyHandler {
|
||||||
ClientMessage::MakeRenderDevice { device } => self
|
ClientMessage::MakeRenderDevice { device } => self
|
||||||
.handle_make_render_device(device)
|
.handle_make_render_device(device)
|
||||||
.wrn("make_render_device")?,
|
.wrn("make_render_device")?,
|
||||||
ClientMessage::GetSeatWorkspace { seat } => self
|
ClientMessage::GetSeatCursorWorkspace { seat } => self
|
||||||
.handle_get_seat_workspace(seat)
|
.handle_get_seat_cursor_workspace(seat)
|
||||||
.wrn("get_seat_workspace")?,
|
.wrn("get_seat_cursor_workspace")?,
|
||||||
ClientMessage::GetSeatKeyboardWorkspace { seat } => self
|
ClientMessage::GetSeatKeyboardWorkspace { seat } => self
|
||||||
.handle_get_seat_keyboard_workspace(seat)
|
.handle_get_seat_keyboard_workspace(seat)
|
||||||
.wrn("get_seat_keyboard_workspace")?,
|
.wrn("get_seat_keyboard_workspace")?,
|
||||||
|
|
@ -3354,6 +3366,9 @@ impl ConfigProxyHandler {
|
||||||
} => self
|
} => self
|
||||||
.handle_keymap_from_names(rules, model, groups, options)
|
.handle_keymap_from_names(rules, model, groups, options)
|
||||||
.wrn("keymap_from_names")?,
|
.wrn("keymap_from_names")?,
|
||||||
|
ClientMessage::SetFallbackOutputMode { seat, mode } => self
|
||||||
|
.handle_set_fallback_output_mode(seat, mode)
|
||||||
|
.wrn("set_fallback_output_mode")?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,10 @@ use {
|
||||||
wire_ei::EiSeatId,
|
wire_ei::EiSeatId,
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
jay_config::keyboard::syms::{KeySym, SYM_Escape},
|
jay_config::{
|
||||||
|
input::FallbackOutputMode,
|
||||||
|
keyboard::syms::{KeySym, SYM_Escape},
|
||||||
|
},
|
||||||
kbvm::Keycode,
|
kbvm::Keycode,
|
||||||
smallvec::SmallVec,
|
smallvec::SmallVec,
|
||||||
std::{
|
std::{
|
||||||
|
|
@ -226,6 +229,7 @@ pub struct WlSeatGlobal {
|
||||||
input_method_grab: CloneCell<Option<Rc<dyn InputMethodKeyboardGrab>>>,
|
input_method_grab: CloneCell<Option<Rc<dyn InputMethodKeyboardGrab>>>,
|
||||||
forward: Cell<bool>,
|
forward: Cell<bool>,
|
||||||
focus_follows_mouse: Cell<bool>,
|
focus_follows_mouse: Cell<bool>,
|
||||||
|
fallback_output_mode: Cell<FallbackOutputMode>,
|
||||||
swipe_bindings: PerClientBindings<ZwpPointerGestureSwipeV1>,
|
swipe_bindings: PerClientBindings<ZwpPointerGestureSwipeV1>,
|
||||||
pinch_bindings: PerClientBindings<ZwpPointerGesturePinchV1>,
|
pinch_bindings: PerClientBindings<ZwpPointerGesturePinchV1>,
|
||||||
hold_bindings: PerClientBindings<ZwpPointerGestureHoldV1>,
|
hold_bindings: PerClientBindings<ZwpPointerGestureHoldV1>,
|
||||||
|
|
@ -325,6 +329,7 @@ impl WlSeatGlobal {
|
||||||
input_method_grab: Default::default(),
|
input_method_grab: Default::default(),
|
||||||
forward: Cell::new(false),
|
forward: Cell::new(false),
|
||||||
focus_follows_mouse: Cell::new(true),
|
focus_follows_mouse: Cell::new(true),
|
||||||
|
fallback_output_mode: Cell::new(FallbackOutputMode::Cursor),
|
||||||
swipe_bindings: Default::default(),
|
swipe_bindings: Default::default(),
|
||||||
pinch_bindings: Default::default(),
|
pinch_bindings: Default::default(),
|
||||||
hold_bindings: Default::default(),
|
hold_bindings: Default::default(),
|
||||||
|
|
@ -457,7 +462,7 @@ impl WlSeatGlobal {
|
||||||
self.data_control_devices.remove(&device.id());
|
self.data_control_devices.remove(&device.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_output(&self) -> Rc<OutputNode> {
|
pub fn get_cursor_output(&self) -> Rc<OutputNode> {
|
||||||
self.cursor_user_group.latest_output()
|
self.cursor_user_group.latest_output()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -469,6 +474,15 @@ impl WlSeatGlobal {
|
||||||
self.keyboard_node.get().node_output()
|
self.keyboard_node.get().node_output()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_fallback_output(&self) -> Rc<OutputNode> {
|
||||||
|
if self.fallback_output_mode.get() == FallbackOutputMode::Focus
|
||||||
|
&& let Some(output) = self.get_keyboard_output()
|
||||||
|
{
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
self.get_cursor_output()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_workspace(&self, ws: &Rc<WorkspaceNode>) {
|
pub fn set_workspace(&self, ws: &Rc<WorkspaceNode>) {
|
||||||
let tl = match self.keyboard_node.get().node_toplevel() {
|
let tl = match self.keyboard_node.get().node_toplevel() {
|
||||||
Some(tl) => tl,
|
Some(tl) => tl,
|
||||||
|
|
@ -726,7 +740,16 @@ impl WlSeatGlobal {
|
||||||
pub fn move_focus(self: &Rc<Self>, direction: Direction) {
|
pub fn move_focus(self: &Rc<Self>, direction: Direction) {
|
||||||
let tl = match self.keyboard_node.get().node_toplevel() {
|
let tl = match self.keyboard_node.get().node_toplevel() {
|
||||||
Some(tl) => tl,
|
Some(tl) => tl,
|
||||||
_ => return,
|
_ => {
|
||||||
|
if let Some(ws) = self.keyboard_node.get().node_into_workspace()
|
||||||
|
&& let Some(target) = self
|
||||||
|
.state
|
||||||
|
.find_output_in_direction(&ws.output.get(), direction)
|
||||||
|
{
|
||||||
|
target.take_keyboard_navigation_focus(self, direction);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if direction == Direction::Down && tl.node_is_container() {
|
if direction == Direction::Down && tl.node_is_container() {
|
||||||
tl.node_do_focus(self, direction);
|
tl.node_do_focus(self, direction);
|
||||||
|
|
@ -748,6 +771,13 @@ impl WlSeatGlobal {
|
||||||
pub fn move_focused(self: &Rc<Self>, direction: Direction) {
|
pub fn move_focused(self: &Rc<Self>, direction: Direction) {
|
||||||
let kb_node = self.keyboard_node.get();
|
let kb_node = self.keyboard_node.get();
|
||||||
let Some(tl) = kb_node.node_toplevel() else {
|
let Some(tl) = kb_node.node_toplevel() else {
|
||||||
|
if let Some(ws) = self.keyboard_node.get().node_into_workspace()
|
||||||
|
&& let Some(target) = self
|
||||||
|
.state
|
||||||
|
.find_output_in_direction(&ws.output.get(), direction)
|
||||||
|
{
|
||||||
|
self.state.move_ws_to_output(&ws, &target);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let data = tl.tl_data();
|
let data = tl.tl_data();
|
||||||
|
|
@ -981,7 +1011,15 @@ impl WlSeatGlobal {
|
||||||
NodeLayer::Layer0 => handle_layer_shell(&output.layers[0]),
|
NodeLayer::Layer0 => handle_layer_shell(&output.layers[0]),
|
||||||
NodeLayer::Layer1 => handle_layer_shell(&output.layers[1]),
|
NodeLayer::Layer1 => handle_layer_shell(&output.layers[1]),
|
||||||
NodeLayer::Output => None,
|
NodeLayer::Output => None,
|
||||||
NodeLayer::Workspace => None,
|
NodeLayer::Workspace => {
|
||||||
|
if let Some(ws) = &ws
|
||||||
|
&& ws.container_visible()
|
||||||
|
{
|
||||||
|
self.focus_node(ws.clone());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
NodeLayer::Tiled => ws
|
NodeLayer::Tiled => ws
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|w| w.container.get())
|
.and_then(|w| w.container.get())
|
||||||
|
|
@ -1393,6 +1431,10 @@ impl WlSeatGlobal {
|
||||||
self.focus_follows_mouse.set(focus_follows_mouse);
|
self.focus_follows_mouse.set(focus_follows_mouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_fallback_output_mode(&self, fallback_output_mode: FallbackOutputMode) {
|
||||||
|
self.fallback_output_mode.set(fallback_output_mode);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_window_management_enabled(self: &Rc<Self>, enabled: bool) {
|
pub fn set_window_management_enabled(self: &Rc<Self>, enabled: bool) {
|
||||||
self.pointer_owner
|
self.pointer_owner
|
||||||
.set_window_management_enabled(self, enabled);
|
.set_window_management_enabled(self, enabled);
|
||||||
|
|
|
||||||
|
|
@ -213,12 +213,12 @@ impl NodeSeatState {
|
||||||
fn release_kb_focus2(&self, focus_last: bool) {
|
fn release_kb_focus2(&self, focus_last: bool) {
|
||||||
self.release_kb_grab();
|
self.release_kb_grab();
|
||||||
while let Some((_, seat)) = self.kb_foci.pop() {
|
while let Some((_, seat)) = self.kb_foci.pop() {
|
||||||
|
let output = seat.get_fallback_output();
|
||||||
seat.kb_owner
|
seat.kb_owner
|
||||||
.set_kb_node(&seat, seat.state.root.clone(), seat.state.next_serial(None));
|
.set_kb_node(&seat, seat.state.root.clone(), seat.state.next_serial(None));
|
||||||
// log::info!("keyboard_node = root");
|
// log::info!("keyboard_node = root");
|
||||||
if focus_last {
|
if focus_last {
|
||||||
seat.get_output()
|
output.node_do_focus(&seat, Direction::Unspecified);
|
||||||
.node_do_focus(&seat, Direction::Unspecified);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -486,7 +486,7 @@ impl XdgToplevel {
|
||||||
if should_be_mapped {
|
if should_be_mapped {
|
||||||
if !self.is_mapped.replace(true) {
|
if !self.is_mapped.replace(true) {
|
||||||
if let Some(seat) = drag.source.data.seat.get() {
|
if let Some(seat) = drag.source.data.seat.get() {
|
||||||
self.xdg.set_output(&seat.get_output());
|
self.xdg.set_output(&seat.get_cursor_output());
|
||||||
}
|
}
|
||||||
self.toplevel_data.broadcast(self.clone());
|
self.toplevel_data.broadcast(self.clone());
|
||||||
self.tl_set_visible(self.state.root_visible());
|
self.tl_set_visible(self.state.root_visible());
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ impl XdgToplevelDragV1 {
|
||||||
if self.source.data.was_used()
|
if self.source.data.was_used()
|
||||||
&& let Some(tl) = self.toplevel.get()
|
&& let Some(tl) = self.toplevel.get()
|
||||||
{
|
{
|
||||||
let output = seat.get_output();
|
let output = seat.get_cursor_output();
|
||||||
let (x, y) = seat.pointer_cursor().position();
|
let (x, y) = seat.pointer_cursor().position();
|
||||||
tl.drag.take();
|
tl.drag.take();
|
||||||
tl.after_toplevel_drag(
|
tl.after_toplevel_drag(
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ impl ZwlrLayerShellV1RequestHandler for ZwlrLayerShellV1 {
|
||||||
self.client.lookup(req.output)?.global.clone()
|
self.client.lookup(req.output)?.global.clone()
|
||||||
} else {
|
} else {
|
||||||
for seat in self.client.state.seat_queue.rev_iter() {
|
for seat in self.client.state.seat_queue.rev_iter() {
|
||||||
let output = seat.get_output();
|
let output = seat.get_fallback_output();
|
||||||
if !output.is_dummy {
|
if !output.is_dummy {
|
||||||
break 'get_output output.global.opt.clone();
|
break 'get_output output.global.opt.clone();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -18,6 +18,7 @@ async fn test(run: Rc<TestRun>) -> TestResult {
|
||||||
win1.set_color(255, 0, 0, 255);
|
win1.set_color(255, 0, 0, 255);
|
||||||
win1.map2().await?;
|
win1.map2().await?;
|
||||||
run.cfg.set_floating(ds.seat.id(), true)?;
|
run.cfg.set_floating(ds.seat.id(), true)?;
|
||||||
|
client.sync().await;
|
||||||
|
|
||||||
for i in ["1", "2"] {
|
for i in ["1", "2"] {
|
||||||
let (x, y) = win1.tl.server.node_absolute_position().position();
|
let (x, y) = win1.tl.server.node_absolute_position().position();
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -85,6 +85,7 @@ impl Renderer<'_> {
|
||||||
} else {
|
} else {
|
||||||
render_layer!(output.layers[0]);
|
render_layer!(output.layers[0]);
|
||||||
render_layer!(output.layers[1]);
|
render_layer!(output.layers[1]);
|
||||||
|
let ws = output.workspace.get();
|
||||||
if self.state.show_bar.get() {
|
if self.state.show_bar.get() {
|
||||||
let non_exclusive_rect_rel = output.non_exclusive_rect_rel.get();
|
let non_exclusive_rect_rel = output.non_exclusive_rect_rel.get();
|
||||||
let (mut x, mut y) = non_exclusive_rect_rel.translate_inv(x, y);
|
let (mut x, mut y) = non_exclusive_rect_rel.translate_inv(x, y);
|
||||||
|
|
@ -109,7 +110,12 @@ impl Renderer<'_> {
|
||||||
self.base
|
self.base
|
||||||
.fill_boxes2(slice::from_ref(&aw.rect), &c, srgb, x, y);
|
.fill_boxes2(slice::from_ref(&aw.rect), &c, srgb, x, y);
|
||||||
}
|
}
|
||||||
let c = theme.colors.separator.get();
|
let mut c = theme.colors.separator.get();
|
||||||
|
if let Some(ws) = &ws
|
||||||
|
&& ws.seat_state.is_active()
|
||||||
|
{
|
||||||
|
c = theme.colors.focused_title_background.get();
|
||||||
|
}
|
||||||
self.base
|
self.base
|
||||||
.fill_boxes2(slice::from_ref(&rd.bar_separator), &c, srgb, x, y);
|
.fill_boxes2(slice::from_ref(&rd.bar_separator), &c, srgb, x, y);
|
||||||
let c = theme.colors.unfocused_title_background.get();
|
let c = theme.colors.unfocused_title_background.get();
|
||||||
|
|
@ -172,7 +178,7 @@ impl Renderer<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(ws) = output.workspace.get() {
|
if let Some(ws) = &ws {
|
||||||
let ws_rect = output.workspace_rect_rel.get();
|
let ws_rect = output.workspace_rect_rel.get();
|
||||||
let (x, y) = ws_rect.translate_inv(x, y);
|
let (x, y) = ws_rect.translate_inv(x, y);
|
||||||
self.render_workspace(&ws, x, y);
|
self.render_workspace(&ws, x, y);
|
||||||
|
|
|
||||||
|
|
@ -780,7 +780,7 @@ impl State {
|
||||||
pub fn ensure_map_workspace(&self, seat: Option<&Rc<WlSeatGlobal>>) -> Rc<WorkspaceNode> {
|
pub fn ensure_map_workspace(&self, seat: Option<&Rc<WlSeatGlobal>>) -> Rc<WorkspaceNode> {
|
||||||
seat.cloned()
|
seat.cloned()
|
||||||
.or_else(|| self.seat_queue.last().map(|s| s.deref().clone()))
|
.or_else(|| self.seat_queue.last().map(|s| s.deref().clone()))
|
||||||
.map(|s| s.get_output())
|
.map(|s| s.get_fallback_output())
|
||||||
.or_else(|| self.root.outputs.lock().values().next().cloned())
|
.or_else(|| self.root.outputs.lock().values().next().cloned())
|
||||||
.or_else(|| self.dummy_output.get())
|
.or_else(|| self.dummy_output.get())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -916,7 +916,7 @@ impl State {
|
||||||
let ws = match self.workspaces.get(name) {
|
let ws = match self.workspaces.get(name) {
|
||||||
Some(ws) => ws,
|
Some(ws) => ws,
|
||||||
_ => {
|
_ => {
|
||||||
let output = output.unwrap_or_else(|| seat.get_output());
|
let output = output.unwrap_or_else(|| seat.get_fallback_output());
|
||||||
if output.is_dummy {
|
if output.is_dummy {
|
||||||
log::warn!("Not showing workspace because seat is on dummy output");
|
log::warn!("Not showing workspace because seat is on dummy output");
|
||||||
return;
|
return;
|
||||||
|
|
@ -929,7 +929,7 @@ impl State {
|
||||||
|
|
||||||
pub fn float_map_ws(&self) -> Rc<WorkspaceNode> {
|
pub fn float_map_ws(&self) -> Rc<WorkspaceNode> {
|
||||||
if let Some(seat) = self.seat_queue.last() {
|
if let Some(seat) = self.seat_queue.last() {
|
||||||
let output = seat.get_output();
|
let output = seat.get_fallback_output();
|
||||||
if !output.is_dummy {
|
if !output.is_dummy {
|
||||||
return output.ensure_workspace();
|
return output.ensure_workspace();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -235,6 +235,7 @@ impl ConnectorHandler {
|
||||||
bar_rect: Default::default(),
|
bar_rect: Default::default(),
|
||||||
bar_rect_rel: Default::default(),
|
bar_rect_rel: Default::default(),
|
||||||
bar_rect_with_separator: Default::default(),
|
bar_rect_with_separator: Default::default(),
|
||||||
|
bar_separator_rect: Default::default(),
|
||||||
bar_separator_rect_rel: Default::default(),
|
bar_separator_rect_rel: Default::default(),
|
||||||
render_data: Default::default(),
|
render_data: Default::default(),
|
||||||
state: self.state.clone(),
|
state: self.state.clone(),
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ pub struct OutputNode {
|
||||||
pub bar_rect: Cell<Rect>,
|
pub bar_rect: Cell<Rect>,
|
||||||
pub bar_rect_rel: Cell<Rect>,
|
pub bar_rect_rel: Cell<Rect>,
|
||||||
pub bar_rect_with_separator: Cell<Rect>,
|
pub bar_rect_with_separator: Cell<Rect>,
|
||||||
|
pub bar_separator_rect: Cell<Rect>,
|
||||||
pub bar_separator_rect_rel: Cell<Rect>,
|
pub bar_separator_rect_rel: Cell<Rect>,
|
||||||
pub render_data: RefCell<OutputRenderData>,
|
pub render_data: RefCell<OutputRenderData>,
|
||||||
pub state: Rc<State>,
|
pub state: Rc<State>,
|
||||||
|
|
@ -775,11 +776,11 @@ impl OutputNode {
|
||||||
let mut bar_rect = Rect::default();
|
let mut bar_rect = Rect::default();
|
||||||
let mut bar_rect_rel = Rect::default();
|
let mut bar_rect_rel = Rect::default();
|
||||||
let mut bar_rect_with_separator = Rect::default();
|
let mut bar_rect_with_separator = Rect::default();
|
||||||
|
let mut bar_separator_rect = Rect::default();
|
||||||
let mut bar_separator_rect_rel = Rect::default();
|
let mut bar_separator_rect_rel = Rect::default();
|
||||||
let mut workspace_rect = non_exclusive_rect;
|
let mut workspace_rect = non_exclusive_rect;
|
||||||
let mut workspace_rect_rel = non_exclusive_rect_rel;
|
let mut workspace_rect_rel = non_exclusive_rect_rel;
|
||||||
if self.state.show_bar.get() {
|
if self.state.show_bar.get() {
|
||||||
let bar_separator_rect;
|
|
||||||
match self.state.theme.bar_position.get() {
|
match self.state.theme.bar_position.get() {
|
||||||
BarPosition::Bottom => {
|
BarPosition::Bottom => {
|
||||||
workspace_rect = Rect::new_sized_saturating(x1, y1, width, height - bh - bsw);
|
workspace_rect = Rect::new_sized_saturating(x1, y1, width, height - bh - bsw);
|
||||||
|
|
@ -806,6 +807,7 @@ impl OutputNode {
|
||||||
self.bar_rect.set(bar_rect);
|
self.bar_rect.set(bar_rect);
|
||||||
self.bar_rect_rel.set(bar_rect_rel);
|
self.bar_rect_rel.set(bar_rect_rel);
|
||||||
self.bar_rect_with_separator.set(bar_rect_with_separator);
|
self.bar_rect_with_separator.set(bar_rect_with_separator);
|
||||||
|
self.bar_separator_rect.set(bar_separator_rect);
|
||||||
self.bar_separator_rect_rel.set(bar_separator_rect_rel);
|
self.bar_separator_rect_rel.set(bar_separator_rect_rel);
|
||||||
self.workspace_rect.set(workspace_rect);
|
self.workspace_rect.set(workspace_rect);
|
||||||
self.workspace_rect_rel.set(workspace_rect_rel);
|
self.workspace_rect_rel.set(workspace_rect_rel);
|
||||||
|
|
@ -1148,20 +1150,13 @@ impl OutputNode {
|
||||||
set_layer_visible!(self.layers[3], visible);
|
set_layer_visible!(self.layers[3], visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn button(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, id: PointerType) {
|
fn bar_button(self: &Rc<Self>, seat: &Rc<WlSeatGlobal>, x: i32, y: i32) -> bool {
|
||||||
if !self.state.show_bar.get() {
|
if !self.state.show_bar.get() {
|
||||||
return;
|
return false;
|
||||||
}
|
|
||||||
let (x, y) = match self.pointer_positions.get(&id) {
|
|
||||||
Some(p) => p,
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
if let PointerType::Seat(s) = id {
|
|
||||||
self.pointer_down.set(s, (x, y));
|
|
||||||
}
|
}
|
||||||
let bar_rect_rel = self.bar_rect_rel.get();
|
let bar_rect_rel = self.bar_rect_rel.get();
|
||||||
if bar_rect_rel.not_contains(x, y) {
|
if bar_rect_rel.not_contains(x, y) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
let (x, _) = bar_rect_rel.translate(x, y);
|
let (x, _) = bar_rect_rel.translate(x, y);
|
||||||
let ws = 'ws: {
|
let ws = 'ws: {
|
||||||
|
|
@ -1171,9 +1166,25 @@ impl OutputNode {
|
||||||
break 'ws title.ws.clone();
|
break 'ws title.ws.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return true;
|
||||||
};
|
};
|
||||||
self.state.show_workspace2(Some(seat), &self, &ws);
|
self.state.show_workspace2(Some(seat), self, &ws);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn button(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, id: PointerType) {
|
||||||
|
let (x, y) = match self.pointer_positions.get(&id) {
|
||||||
|
Some(p) => p,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
if let PointerType::Seat(s) = id {
|
||||||
|
self.pointer_down.set(s, (x, y));
|
||||||
|
}
|
||||||
|
if self.bar_button(seat, x, y) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let ws = self.ensure_workspace();
|
||||||
|
seat.focus_node(ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_presentation_type(&self) {
|
pub fn update_presentation_type(&self) {
|
||||||
|
|
@ -1490,6 +1501,10 @@ impl OutputNode {
|
||||||
if c.node_visible() {
|
if c.node_visible() {
|
||||||
c.node_do_focus(seat, direction);
|
c.node_do_focus(seat, direction);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if ws.node_visible() {
|
||||||
|
seat.focus_node(ws);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -366,17 +366,23 @@ impl Node for WorkspaceNode {
|
||||||
seat.focus_node(last);
|
seat.focus_node(last);
|
||||||
} else if let Some(container) = self.container.get() {
|
} else if let Some(container) = self.container.get() {
|
||||||
container.node_do_focus(seat, direction);
|
container.node_do_focus(seat, direction);
|
||||||
} else if let Some(float) = self
|
} else if let Some(child) = self
|
||||||
.stacked
|
.stacked
|
||||||
.rev_iter()
|
.rev_iter()
|
||||||
.find_map(|node| (*node).clone().node_into_float())
|
.filter_map(|node| (*node).clone().node_into_float())
|
||||||
|
.find_map(|float| float.child.get())
|
||||||
{
|
{
|
||||||
if let Some(child) = float.child.get() {
|
child.node_do_focus(seat, direction);
|
||||||
child.node_do_focus(seat, direction);
|
} else {
|
||||||
}
|
seat.focus_node(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_active_changed(&self, _active: bool) {
|
||||||
|
let output = self.output.get();
|
||||||
|
self.state.damage(output.bar_separator_rect.get());
|
||||||
|
}
|
||||||
|
|
||||||
fn node_find_tree_at(
|
fn node_find_tree_at(
|
||||||
&self,
|
&self,
|
||||||
x: i32,
|
x: i32,
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ use {
|
||||||
Axis, Direction, Workspace,
|
Axis, Direction, Workspace,
|
||||||
client::ClientCapabilities,
|
client::ClientCapabilities,
|
||||||
input::{
|
input::{
|
||||||
LayerDirection, SwitchEvent, Timeline, acceleration::AccelProfile,
|
FallbackOutputMode, LayerDirection, SwitchEvent, Timeline, acceleration::AccelProfile,
|
||||||
clickmethod::ClickMethod,
|
clickmethod::ClickMethod,
|
||||||
},
|
},
|
||||||
keyboard::{Keymap, ModifiedKeySym, mods::Modifiers, syms::KeySym},
|
keyboard::{Keymap, ModifiedKeySym, mods::Modifiers, syms::KeySym},
|
||||||
|
|
@ -537,6 +537,7 @@ pub struct Config {
|
||||||
pub input_modes: AHashMap<String, InputMode>,
|
pub input_modes: AHashMap<String, InputMode>,
|
||||||
pub workspace_display_order: Option<WorkspaceDisplayOrder>,
|
pub workspace_display_order: Option<WorkspaceDisplayOrder>,
|
||||||
pub simple_im: Option<SimpleIm>,
|
pub simple_im: Option<SimpleIm>,
|
||||||
|
pub fallback_output_mode: Option<FallbackOutputMode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ mod drm_device;
|
||||||
mod drm_device_match;
|
mod drm_device_match;
|
||||||
mod env;
|
mod env;
|
||||||
pub mod exec;
|
pub mod exec;
|
||||||
|
mod fallback_output_mode;
|
||||||
pub mod float;
|
pub mod float;
|
||||||
pub mod focus_history;
|
pub mod focus_history;
|
||||||
mod format;
|
mod format;
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ use {
|
||||||
drm_device::DrmDevicesParser,
|
drm_device::DrmDevicesParser,
|
||||||
drm_device_match::DrmDeviceMatchParser,
|
drm_device_match::DrmDeviceMatchParser,
|
||||||
env::EnvParser,
|
env::EnvParser,
|
||||||
|
fallback_output_mode::FallbackOutputModeParser,
|
||||||
float::FloatParser,
|
float::FloatParser,
|
||||||
focus_history::FocusHistoryParser,
|
focus_history::FocusHistoryParser,
|
||||||
gfx_api::GfxApiParser,
|
gfx_api::GfxApiParser,
|
||||||
|
|
@ -147,6 +148,7 @@ impl Parser for ConfigParser<'_> {
|
||||||
auto_reload,
|
auto_reload,
|
||||||
simple_im_val,
|
simple_im_val,
|
||||||
show_titles,
|
show_titles,
|
||||||
|
fallback_output_mode_val,
|
||||||
),
|
),
|
||||||
) = ext.extract((
|
) = ext.extract((
|
||||||
(
|
(
|
||||||
|
|
@ -204,6 +206,7 @@ impl Parser for ConfigParser<'_> {
|
||||||
recover(opt(bol("auto-reload"))),
|
recover(opt(bol("auto-reload"))),
|
||||||
opt(val("simple-im")),
|
opt(val("simple-im")),
|
||||||
recover(opt(bol("show-titles"))),
|
recover(opt(bol("show-titles"))),
|
||||||
|
opt(val("fallback-output-mode")),
|
||||||
),
|
),
|
||||||
))?;
|
))?;
|
||||||
let mut keymap = None;
|
let mut keymap = None;
|
||||||
|
|
@ -524,6 +527,18 @@ impl Parser for ConfigParser<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let mut fallback_output_mode = None;
|
||||||
|
if let Some(value) = fallback_output_mode_val {
|
||||||
|
match value.parse(&mut FallbackOutputModeParser) {
|
||||||
|
Ok(v) => fallback_output_mode = Some(v),
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!(
|
||||||
|
"Could not parse the fallback output mode: {}",
|
||||||
|
self.0.error(e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(Config {
|
Ok(Config {
|
||||||
keymap,
|
keymap,
|
||||||
repeat_rate,
|
repeat_rate,
|
||||||
|
|
@ -570,6 +585,7 @@ impl Parser for ConfigParser<'_> {
|
||||||
input_modes,
|
input_modes,
|
||||||
workspace_display_order,
|
workspace_display_order,
|
||||||
simple_im,
|
simple_im,
|
||||||
|
fallback_output_mode,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
38
toml-config/src/config/parsers/fallback_output_mode.rs
Normal file
38
toml-config/src/config/parsers/fallback_output_mode.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
config::parser::{DataType, ParseResult, Parser, UnexpectedDataType},
|
||||||
|
toml::toml_span::{Span, SpannedExt},
|
||||||
|
},
|
||||||
|
jay_config::input::FallbackOutputMode,
|
||||||
|
thiserror::Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct FallbackOutputModeParser;
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum FallbackOutputModeParserError {
|
||||||
|
#[error(transparent)]
|
||||||
|
DataType(#[from] UnexpectedDataType),
|
||||||
|
#[error("Unknown mode {0}")]
|
||||||
|
Unknown(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parser for FallbackOutputModeParser {
|
||||||
|
type Value = FallbackOutputMode;
|
||||||
|
type Error = FallbackOutputModeParserError;
|
||||||
|
const EXPECTED: &'static [DataType] = &[DataType::String];
|
||||||
|
|
||||||
|
fn parse_string(&mut self, span: Span, string: &str) -> ParseResult<Self> {
|
||||||
|
use FallbackOutputMode::*;
|
||||||
|
let api = match string.to_ascii_lowercase().as_str() {
|
||||||
|
"cursor" => Cursor,
|
||||||
|
"focus" => Focus,
|
||||||
|
_ => {
|
||||||
|
return Err(
|
||||||
|
FallbackOutputModeParserError::Unknown(string.to_string()).spanned(span)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(api)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1627,6 +1627,9 @@ fn load_config(initial_load: bool, auto_reload: bool, persistent: &Rc<Persistent
|
||||||
persistent.seat.set_simple_im_enabled(enabled);
|
persistent.seat.set_simple_im_enabled(enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(v) = config.fallback_output_mode {
|
||||||
|
persistent.seat.set_fallback_output_mode(v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_command(exec: &Exec) -> Command {
|
fn create_command(exec: &Exec) -> Command {
|
||||||
|
|
|
||||||
|
|
@ -1068,6 +1068,10 @@
|
||||||
"simple-im": {
|
"simple-im": {
|
||||||
"description": "Configures the simple, XCompose based input method.\n\nBy default, the input method is enabled. \n\nEven if the input method is enabled, it will only be used if there is no\nrunning external IM.\n\n- Example:\n\n ```toml\n [simple-im]\n enabled = false\n ```\n",
|
"description": "Configures the simple, XCompose based input method.\n\nBy default, the input method is enabled. \n\nEven if the input method is enabled, it will only be used if there is no\nrunning external IM.\n\n- Example:\n\n ```toml\n [simple-im]\n enabled = false\n ```\n",
|
||||||
"$ref": "#/$defs/SimpleIm"
|
"$ref": "#/$defs/SimpleIm"
|
||||||
|
},
|
||||||
|
"fallback-output-mode": {
|
||||||
|
"description": "Sets the fallback output mode.\n\nThe default is `cursor`.\n\n- Example:\n\n ```toml\n fallback-output-mode = \"focus\"\n ```\n",
|
||||||
|
"$ref": "#/$defs/FallbackOutputMode"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
|
|
@ -1284,6 +1288,14 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"FallbackOutputMode": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Defines which output is used when no particular output is specified.\n\nThis configures where to place a newly opened window or workspace, what window to focus when a\nwindow is closed, which workspace is moved with move-to-output, and similar actions.\n",
|
||||||
|
"enum": [
|
||||||
|
"cursor",
|
||||||
|
"focus"
|
||||||
|
]
|
||||||
|
},
|
||||||
"Float": {
|
"Float": {
|
||||||
"description": "Describes settings of floating windows.\n\n- Example:\n\n ```toml\n [float]\n show-pin-icon = true\n ```\n",
|
"description": "Describes settings of floating windows.\n\n- Example:\n\n ```toml\n [float]\n show-pin-icon = true\n ```\n",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
|
||||||
|
|
@ -2218,6 +2218,20 @@ The table has the following fields:
|
||||||
|
|
||||||
The value of this field should be a [SimpleIm](#types-SimpleIm).
|
The value of this field should be a [SimpleIm](#types-SimpleIm).
|
||||||
|
|
||||||
|
- `fallback-output-mode` (optional):
|
||||||
|
|
||||||
|
Sets the fallback output mode.
|
||||||
|
|
||||||
|
The default is `cursor`.
|
||||||
|
|
||||||
|
- Example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
fallback-output-mode = "focus"
|
||||||
|
```
|
||||||
|
|
||||||
|
The value of this field should be a [FallbackOutputMode](#types-FallbackOutputMode).
|
||||||
|
|
||||||
|
|
||||||
<a name="types-Connector"></a>
|
<a name="types-Connector"></a>
|
||||||
### `Connector`
|
### `Connector`
|
||||||
|
|
@ -2694,6 +2708,28 @@ The table has the following fields:
|
||||||
The value of this field should be a boolean.
|
The value of this field should be a boolean.
|
||||||
|
|
||||||
|
|
||||||
|
<a name="types-FallbackOutputMode"></a>
|
||||||
|
### `FallbackOutputMode`
|
||||||
|
|
||||||
|
Defines which output is used when no particular output is specified.
|
||||||
|
|
||||||
|
This configures where to place a newly opened window or workspace, what window to focus when a
|
||||||
|
window is closed, which workspace is moved with move-to-output, and similar actions.
|
||||||
|
|
||||||
|
Values of this type should be strings.
|
||||||
|
|
||||||
|
The string should have one of the following values:
|
||||||
|
|
||||||
|
- `cursor`:
|
||||||
|
|
||||||
|
Use the output the cursor is on.
|
||||||
|
|
||||||
|
- `focus`:
|
||||||
|
|
||||||
|
Use the output the focus is on (highlighted window).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="types-Float"></a>
|
<a name="types-Float"></a>
|
||||||
### `Float`
|
### `Float`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2986,6 +2986,19 @@ Config:
|
||||||
[simple-im]
|
[simple-im]
|
||||||
enabled = false
|
enabled = false
|
||||||
```
|
```
|
||||||
|
fallback-output-mode:
|
||||||
|
ref: FallbackOutputMode
|
||||||
|
required: false
|
||||||
|
description: |
|
||||||
|
Sets the fallback output mode.
|
||||||
|
|
||||||
|
The default is `cursor`.
|
||||||
|
|
||||||
|
- Example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
fallback-output-mode = "focus"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Idle:
|
Idle:
|
||||||
|
|
@ -4351,3 +4364,17 @@ BarPosition:
|
||||||
description: The bar is at the top of the output.
|
description: The bar is at the top of the output.
|
||||||
- value: bottom
|
- value: bottom
|
||||||
description: The bar is at the bottom of the output.
|
description: The bar is at the bottom of the output.
|
||||||
|
|
||||||
|
|
||||||
|
FallbackOutputMode:
|
||||||
|
kind: string
|
||||||
|
description: |
|
||||||
|
Defines which output is used when no particular output is specified.
|
||||||
|
|
||||||
|
This configures where to place a newly opened window or workspace, what window to focus when a
|
||||||
|
window is closed, which workspace is moved with move-to-output, and similar actions.
|
||||||
|
values:
|
||||||
|
- value: cursor
|
||||||
|
description: Use the output the cursor is on.
|
||||||
|
- value: focus
|
||||||
|
description: Use the output the focus is on (highlighted window).
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue