config: add Window
This commit is contained in:
parent
ab095b89cf
commit
9977f9dfdf
19 changed files with 1172 additions and 203 deletions
|
|
@ -30,6 +30,7 @@ use {
|
|||
Transform, VrrMode,
|
||||
connector_type::{CON_UNKNOWN, ConnectorType},
|
||||
},
|
||||
window::{Window, WindowType},
|
||||
xwayland::XScalingMode,
|
||||
},
|
||||
bincode::Options,
|
||||
|
|
@ -342,6 +343,74 @@ impl ConfigClient {
|
|||
self.send(&ClientMessage::SeatMove { seat, direction });
|
||||
}
|
||||
|
||||
pub fn window_move(&self, window: Window, direction: Direction) {
|
||||
self.send(&ClientMessage::WindowMove { window, direction });
|
||||
}
|
||||
|
||||
pub fn window_exists(&self, window: Window) -> bool {
|
||||
let res = self.send_with_response(&ClientMessage::WindowExists { window });
|
||||
get_response!(res, false, WindowExists { exists });
|
||||
exists
|
||||
}
|
||||
|
||||
pub fn window_client(&self, window: Window) -> Client {
|
||||
let res = self.send_with_response(&ClientMessage::GetWindowClient { window });
|
||||
get_response!(res, Client(0), GetWindowClient { client });
|
||||
client
|
||||
}
|
||||
|
||||
pub fn get_workspace_window(&self, workspace: Workspace) -> Window {
|
||||
let res = self.send_with_response(&ClientMessage::GetWorkspaceWindow { workspace });
|
||||
get_response!(res, Window(0), GetWorkspaceWindow { window });
|
||||
window
|
||||
}
|
||||
|
||||
pub fn get_seat_keyboard_window(&self, seat: Seat) -> Window {
|
||||
let res = self.send_with_response(&ClientMessage::GetSeatKeyboardWindow { seat });
|
||||
get_response!(res, Window(0), GetSeatKeyboardWindow { window });
|
||||
window
|
||||
}
|
||||
|
||||
pub fn focus_window(&self, seat: Seat, window: Window) {
|
||||
self.send(&ClientMessage::SeatFocusWindow { seat, window });
|
||||
}
|
||||
|
||||
pub fn window_title(&self, window: Window) -> String {
|
||||
let res = self.send_with_response(&ClientMessage::GetWindowTitle { window });
|
||||
get_response!(res, String::new(), GetWindowTitle { title });
|
||||
title
|
||||
}
|
||||
|
||||
pub fn window_type(&self, window: Window) -> WindowType {
|
||||
let res = self.send_with_response(&ClientMessage::GetWindowType { window });
|
||||
get_response!(res, WindowType(0), GetWindowType { kind });
|
||||
kind
|
||||
}
|
||||
|
||||
pub fn window_id(&self, window: Window) -> String {
|
||||
let res = self.send_with_response(&ClientMessage::GetWindowId { window });
|
||||
get_response!(res, String::new(), GetWindowId { id });
|
||||
id
|
||||
}
|
||||
|
||||
pub fn window_parent(&self, window: Window) -> Window {
|
||||
let res = self.send_with_response(&ClientMessage::GetWindowParent { window });
|
||||
get_response!(res, Window(0), GetWindowParent { window });
|
||||
window
|
||||
}
|
||||
|
||||
pub fn window_children(&self, window: Window) -> Vec<Window> {
|
||||
let res = self.send_with_response(&ClientMessage::GetWindowChildren { window });
|
||||
get_response!(res, vec![], GetWindowChildren { windows });
|
||||
windows
|
||||
}
|
||||
|
||||
pub fn window_is_visible(&self, window: Window) -> bool {
|
||||
let res = self.send_with_response(&ClientMessage::GetWindowIsVisible { window });
|
||||
get_response!(res, false, GetWindowIsVisible { visible });
|
||||
visible
|
||||
}
|
||||
|
||||
pub fn unbind<T: Into<ModifiedKeySym>>(&self, seat: Seat, mod_sym: T) {
|
||||
let mod_sym = mod_sym.into();
|
||||
if let Entry::Occupied(mut oe) = self.key_handlers.borrow_mut().entry((seat, mod_sym)) {
|
||||
|
|
@ -374,6 +443,12 @@ impl ConfigClient {
|
|||
mono
|
||||
}
|
||||
|
||||
pub fn window_mono(&self, window: Window) -> bool {
|
||||
let res = self.send_with_response(&ClientMessage::GetWindowMono { window });
|
||||
get_response!(res, false, GetWindowMono { mono });
|
||||
mono
|
||||
}
|
||||
|
||||
pub fn get_timer(&self, name: &str) -> Timer {
|
||||
let res = self.send_with_response(&ClientMessage::GetTimer { name });
|
||||
get_response!(res, Timer(0), GetTimer { timer });
|
||||
|
|
@ -421,6 +496,12 @@ impl ConfigClient {
|
|||
workspace
|
||||
}
|
||||
|
||||
pub fn get_window_workspace(&self, window: Window) -> Workspace {
|
||||
let res = self.send_with_response(&ClientMessage::GetWindowWorkspace { window });
|
||||
get_response!(res, Workspace(0), GetWindowWorkspace { workspace });
|
||||
workspace
|
||||
}
|
||||
|
||||
pub fn get_seat_keyboard_workspace(&self, seat: Seat) -> Workspace {
|
||||
let res = self.send_with_response(&ClientMessage::GetSeatKeyboardWorkspace { seat });
|
||||
get_response!(res, Workspace(0), GetSeatKeyboardWorkspace { workspace });
|
||||
|
|
@ -455,12 +536,22 @@ impl ConfigClient {
|
|||
self.send(&ClientMessage::SetSeatWorkspace { seat, workspace });
|
||||
}
|
||||
|
||||
pub fn set_window_workspace(&self, window: Window, workspace: Workspace) {
|
||||
self.send(&ClientMessage::SetWindowWorkspace { window, workspace });
|
||||
}
|
||||
|
||||
pub fn seat_split(&self, seat: Seat) -> Axis {
|
||||
let res = self.send_with_response(&ClientMessage::GetSeatSplit { seat });
|
||||
get_response!(res, Axis::Horizontal, GetSplit { axis });
|
||||
axis
|
||||
}
|
||||
|
||||
pub fn window_split(&self, window: Window) -> Axis {
|
||||
let res = self.send_with_response(&ClientMessage::GetWindowSplit { window });
|
||||
get_response!(res, Axis::Horizontal, GetWindowSplit { axis });
|
||||
axis
|
||||
}
|
||||
|
||||
pub fn disable_pointer_constraint(&self, seat: Seat) {
|
||||
self.send(&ClientMessage::DisablePointerConstraint { seat });
|
||||
}
|
||||
|
|
@ -482,6 +573,16 @@ impl ConfigClient {
|
|||
fullscreen
|
||||
}
|
||||
|
||||
pub fn set_window_fullscreen(&self, window: Window, fullscreen: bool) {
|
||||
self.send(&ClientMessage::SetWindowFullscreen { window, fullscreen });
|
||||
}
|
||||
|
||||
pub fn get_window_fullscreen(&self, window: Window) -> bool {
|
||||
let res = self.send_with_response(&ClientMessage::GetWindowFullscreen { window });
|
||||
get_response!(res, false, GetWindowFullscreen { fullscreen });
|
||||
fullscreen
|
||||
}
|
||||
|
||||
pub fn reset_font(&self) {
|
||||
self.send(&ClientMessage::ResetFont);
|
||||
}
|
||||
|
|
@ -510,6 +611,16 @@ impl ConfigClient {
|
|||
self.set_seat_floating(seat, !self.get_seat_floating(seat));
|
||||
}
|
||||
|
||||
pub fn get_window_floating(&self, window: Window) -> bool {
|
||||
let res = self.send_with_response(&ClientMessage::GetWindowFloating { window });
|
||||
get_response!(res, false, GetWindowFloating { floating });
|
||||
floating
|
||||
}
|
||||
|
||||
pub fn set_window_floating(&self, window: Window, floating: bool) {
|
||||
self.send(&ClientMessage::SetWindowFloating { window, floating });
|
||||
}
|
||||
|
||||
pub fn reset_colors(&self) {
|
||||
self.send(&ClientMessage::ResetColors);
|
||||
}
|
||||
|
|
@ -553,6 +664,10 @@ impl ConfigClient {
|
|||
self.send(&ClientMessage::SetSeatMono { seat, mono });
|
||||
}
|
||||
|
||||
pub fn set_window_mono(&self, window: Window, mono: bool) {
|
||||
self.send(&ClientMessage::SetWindowMono { window, mono });
|
||||
}
|
||||
|
||||
pub fn set_env(&self, key: &str, val: &str) {
|
||||
self.send(&ClientMessage::SetEnv { key, val });
|
||||
}
|
||||
|
|
@ -587,14 +702,26 @@ impl ConfigClient {
|
|||
self.send(&ClientMessage::SetSeatSplit { seat, axis });
|
||||
}
|
||||
|
||||
pub fn set_window_split(&self, window: Window, axis: Axis) {
|
||||
self.send(&ClientMessage::SetWindowSplit { window, axis });
|
||||
}
|
||||
|
||||
pub fn create_seat_split(&self, seat: Seat, axis: Axis) {
|
||||
self.send(&ClientMessage::CreateSeatSplit { seat, axis });
|
||||
}
|
||||
|
||||
pub fn create_window_split(&self, window: Window, axis: Axis) {
|
||||
self.send(&ClientMessage::CreateWindowSplit { window, axis });
|
||||
}
|
||||
|
||||
pub fn seat_close(&self, seat: Seat) {
|
||||
self.send(&ClientMessage::SeatClose { seat });
|
||||
}
|
||||
|
||||
pub fn close_window(&self, window: Window) {
|
||||
self.send(&ClientMessage::WindowClose { window });
|
||||
}
|
||||
|
||||
pub fn focus_seat_parent(&self, seat: Seat) {
|
||||
self.send(&ClientMessage::FocusSeatParent { seat });
|
||||
}
|
||||
|
|
@ -802,6 +929,16 @@ impl ConfigClient {
|
|||
self.send(&ClientMessage::SetSeatFloatPinned { seat, pinned });
|
||||
}
|
||||
|
||||
pub fn get_window_pinned(&self, window: Window) -> bool {
|
||||
let res = self.send_with_response(&ClientMessage::GetWindowFloatPinned { window });
|
||||
get_response!(res, false, GetWindowFloatPinned { pinned });
|
||||
pinned
|
||||
}
|
||||
|
||||
pub fn set_window_pinned(&self, window: Window, pinned: bool) {
|
||||
self.send(&ClientMessage::SetWindowFloatPinned { window, pinned });
|
||||
}
|
||||
|
||||
pub fn connector_connected(&self, connector: Connector) -> bool {
|
||||
let res = self.send_with_response(&ClientMessage::ConnectorConnected { connector });
|
||||
get_response!(res, false, ConnectorConnected { connected });
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use {
|
|||
ColorSpace, Connector, DrmDevice, Format, GfxApi, TearingMode, TransferFunction,
|
||||
Transform, VrrMode, connector_type::ConnectorType,
|
||||
},
|
||||
window::{Window, WindowType},
|
||||
xwayland::XScalingMode,
|
||||
},
|
||||
serde::{Deserialize, Serialize},
|
||||
|
|
@ -576,6 +577,93 @@ pub enum ClientMessage<'a> {
|
|||
ClientIsXwayland {
|
||||
client: Client,
|
||||
},
|
||||
WindowExists {
|
||||
window: Window,
|
||||
},
|
||||
GetWindowClient {
|
||||
window: Window,
|
||||
},
|
||||
GetWorkspaceWindow {
|
||||
workspace: Workspace,
|
||||
},
|
||||
GetSeatKeyboardWindow {
|
||||
seat: Seat,
|
||||
},
|
||||
SeatFocusWindow {
|
||||
seat: Seat,
|
||||
window: Window,
|
||||
},
|
||||
GetWindowTitle {
|
||||
window: Window,
|
||||
},
|
||||
GetWindowType {
|
||||
window: Window,
|
||||
},
|
||||
GetWindowId {
|
||||
window: Window,
|
||||
},
|
||||
GetWindowIsVisible {
|
||||
window: Window,
|
||||
},
|
||||
GetWindowParent {
|
||||
window: Window,
|
||||
},
|
||||
GetWindowWorkspace {
|
||||
window: Window,
|
||||
},
|
||||
GetWindowChildren {
|
||||
window: Window,
|
||||
},
|
||||
GetWindowSplit {
|
||||
window: Window,
|
||||
},
|
||||
SetWindowSplit {
|
||||
window: Window,
|
||||
axis: Axis,
|
||||
},
|
||||
GetWindowMono {
|
||||
window: Window,
|
||||
},
|
||||
SetWindowMono {
|
||||
window: Window,
|
||||
mono: bool,
|
||||
},
|
||||
WindowMove {
|
||||
window: Window,
|
||||
direction: Direction,
|
||||
},
|
||||
CreateWindowSplit {
|
||||
window: Window,
|
||||
axis: Axis,
|
||||
},
|
||||
WindowClose {
|
||||
window: Window,
|
||||
},
|
||||
GetWindowFloating {
|
||||
window: Window,
|
||||
},
|
||||
SetWindowFloating {
|
||||
window: Window,
|
||||
floating: bool,
|
||||
},
|
||||
SetWindowWorkspace {
|
||||
window: Window,
|
||||
workspace: Workspace,
|
||||
},
|
||||
SetWindowFullscreen {
|
||||
window: Window,
|
||||
fullscreen: bool,
|
||||
},
|
||||
GetWindowFullscreen {
|
||||
window: Window,
|
||||
},
|
||||
GetWindowFloatPinned {
|
||||
window: Window,
|
||||
},
|
||||
SetWindowFloatPinned {
|
||||
window: Window,
|
||||
pinned: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
|
@ -748,6 +836,54 @@ pub enum Response {
|
|||
ClientIsXwayland {
|
||||
is_xwayland: bool,
|
||||
},
|
||||
WindowExists {
|
||||
exists: bool,
|
||||
},
|
||||
GetWindowClient {
|
||||
client: Client,
|
||||
},
|
||||
GetSeatKeyboardWindow {
|
||||
window: Window,
|
||||
},
|
||||
GetWorkspaceWindow {
|
||||
window: Window,
|
||||
},
|
||||
GetWindowParent {
|
||||
window: Window,
|
||||
},
|
||||
GetWindowChildren {
|
||||
windows: Vec<Window>,
|
||||
},
|
||||
GetWindowTitle {
|
||||
title: String,
|
||||
},
|
||||
GetWindowType {
|
||||
kind: WindowType,
|
||||
},
|
||||
GetWindowId {
|
||||
id: String,
|
||||
},
|
||||
GetWindowWorkspace {
|
||||
workspace: Workspace,
|
||||
},
|
||||
GetWindowFloating {
|
||||
floating: bool,
|
||||
},
|
||||
GetWindowSplit {
|
||||
axis: Axis,
|
||||
},
|
||||
GetWindowMono {
|
||||
mono: bool,
|
||||
},
|
||||
GetWindowFullscreen {
|
||||
fullscreen: bool,
|
||||
},
|
||||
GetWindowFloatPinned {
|
||||
pinned: bool,
|
||||
},
|
||||
GetWindowIsVisible {
|
||||
visible: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use {
|
|||
input::{acceleration::AccelProfile, capability::Capability},
|
||||
keyboard::{Keymap, mods::Modifiers},
|
||||
video::Connector,
|
||||
window::Window,
|
||||
},
|
||||
serde::{Deserialize, Serialize},
|
||||
std::time::Duration,
|
||||
|
|
@ -478,6 +479,20 @@ impl Seat {
|
|||
pub fn toggle_float_pinned(self) {
|
||||
self.set_float_pinned(!self.float_pinned());
|
||||
}
|
||||
|
||||
/// Returns the focused window.
|
||||
///
|
||||
/// If no window is focused, [`Window::exists`] returns false.
|
||||
pub fn window(self) -> Window {
|
||||
get!(Window(0)).get_seat_keyboard_window(self)
|
||||
}
|
||||
|
||||
/// Puts the keyboard focus on the window.
|
||||
///
|
||||
/// This has no effect if the window is not visible.
|
||||
pub fn focus_window(self, window: Window) {
|
||||
get!().focus_window(self, window)
|
||||
}
|
||||
}
|
||||
|
||||
/// A focus-follows-mouse mode.
|
||||
|
|
|
|||
|
|
@ -3,35 +3,42 @@
|
|||
use {
|
||||
crate::{ModifiedKeySym, keyboard::syms::KeySym},
|
||||
serde::{Deserialize, Serialize},
|
||||
std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign},
|
||||
std::ops::BitOr,
|
||||
};
|
||||
|
||||
/// Zero or more keyboard modifiers
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Default, Hash, Debug)]
|
||||
pub struct Modifiers(pub u32);
|
||||
bitflags! {
|
||||
/// Zero or more keyboard modifiers
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Default, Hash)]
|
||||
pub struct Modifiers(pub u32) {
|
||||
/// The Shift modifier
|
||||
pub const SHIFT = 1 << 0,
|
||||
/// The CapsLock modifier.
|
||||
pub const LOCK = 1 << 1,
|
||||
/// The Ctrl modifier.
|
||||
pub const CTRL = 1 << 2,
|
||||
/// The Mod1 modifier, i.e., Alt.
|
||||
pub const MOD1 = 1 << 3,
|
||||
/// The Mod2 modifier, i.e., NumLock.
|
||||
pub const MOD2 = 1 << 4,
|
||||
/// The Mod3 modifier.
|
||||
pub const MOD3 = 1 << 5,
|
||||
/// The Mod4 modifier, i.e., Logo.
|
||||
pub const MOD4 = 1 << 6,
|
||||
/// The Mod5 modifier.
|
||||
pub const MOD5 = 1 << 7,
|
||||
|
||||
/// Synthetic modifier matching key release events.
|
||||
///
|
||||
/// This can be used to execute a callback on key release.
|
||||
pub const RELEASE = 1 << 31,
|
||||
}
|
||||
}
|
||||
|
||||
impl Modifiers {
|
||||
/// No modifiers.
|
||||
pub const NONE: Self = Modifiers(0);
|
||||
}
|
||||
|
||||
/// The Shift modifier
|
||||
pub const SHIFT: Modifiers = Modifiers(1 << 0);
|
||||
/// The CapsLock modifier.
|
||||
pub const LOCK: Modifiers = Modifiers(1 << 1);
|
||||
/// The Ctrl modifier.
|
||||
pub const CTRL: Modifiers = Modifiers(1 << 2);
|
||||
/// The Mod1 modifier, i.e., Alt.
|
||||
pub const MOD1: Modifiers = Modifiers(1 << 3);
|
||||
/// The Mod2 modifier, i.e., NumLock.
|
||||
pub const MOD2: Modifiers = Modifiers(1 << 4);
|
||||
/// The Mod3 modifier.
|
||||
pub const MOD3: Modifiers = Modifiers(1 << 5);
|
||||
/// The Mod4 modifier, i.e., Logo.
|
||||
pub const MOD4: Modifiers = Modifiers(1 << 6);
|
||||
/// The Mod5 modifier.
|
||||
pub const MOD5: Modifiers = Modifiers(1 << 7);
|
||||
|
||||
/// Alias for `LOCK`.
|
||||
pub const CAPS: Modifiers = LOCK;
|
||||
/// Alias for `MOD1`.
|
||||
|
|
@ -41,19 +48,6 @@ pub const NUM: Modifiers = MOD2;
|
|||
/// Alias for `MOD4`.
|
||||
pub const LOGO: Modifiers = MOD4;
|
||||
|
||||
/// Synthetic modifier matching key release events.
|
||||
///
|
||||
/// This can be used to execute a callback on key release.
|
||||
pub const RELEASE: Modifiers = Modifiers(1 << 31);
|
||||
|
||||
impl BitOr for Modifiers {
|
||||
type Output = Self;
|
||||
|
||||
fn bitor(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 | rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOr<KeySym> for Modifiers {
|
||||
type Output = ModifiedKeySym;
|
||||
|
||||
|
|
@ -64,23 +58,3 @@ impl BitOr<KeySym> for Modifiers {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BitAnd for Modifiers {
|
||||
type Output = Self;
|
||||
|
||||
fn bitand(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 & rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl BitOrAssign for Modifiers {
|
||||
fn bitor_assign(&mut self, rhs: Self) {
|
||||
self.0 |= rhs.0
|
||||
}
|
||||
}
|
||||
|
||||
impl BitAndAssign for Modifiers {
|
||||
fn bitand_assign(&mut self, rhs: Self) {
|
||||
self.0 &= rhs.0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,9 @@
|
|||
#[expect(unused_imports)]
|
||||
use crate::input::Seat;
|
||||
use {
|
||||
crate::{_private::ipc::WorkspaceSource, keyboard::ModifiedKeySym, video::Connector},
|
||||
crate::{
|
||||
_private::ipc::WorkspaceSource, keyboard::ModifiedKeySym, video::Connector, window::Window,
|
||||
},
|
||||
serde::{Deserialize, Serialize},
|
||||
std::{
|
||||
fmt::{Debug, Display, Formatter},
|
||||
|
|
@ -70,6 +72,7 @@ pub mod tasks;
|
|||
pub mod theme;
|
||||
pub mod timer;
|
||||
pub mod video;
|
||||
pub mod window;
|
||||
pub mod xwayland;
|
||||
|
||||
/// A planar direction.
|
||||
|
|
@ -174,6 +177,13 @@ impl Workspace {
|
|||
pub fn move_to_output(self, output: Connector) {
|
||||
get!().move_to_output(WorkspaceSource::Explicit(self), output);
|
||||
}
|
||||
|
||||
/// Returns the root container of this workspace.
|
||||
///
|
||||
/// If no such container exists, [`Window::exists`] returns false.
|
||||
pub fn window(self) -> Window {
|
||||
get!(Window(0)).get_workspace_window(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the workspace with the given name.
|
||||
|
|
|
|||
|
|
@ -43,40 +43,89 @@ macro_rules! get {
|
|||
}};
|
||||
}
|
||||
|
||||
// #[macro_export]
|
||||
// macro_rules! log {
|
||||
// ($lvl:expr, $($arg:tt)+) => ({
|
||||
// $crate::log(
|
||||
// $lvl,
|
||||
// &format!($($args)*),
|
||||
// );
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// #[macro_export]
|
||||
// macro_rules! trace {
|
||||
// ($($arg:tt)+) => {
|
||||
// $crate::log!($crate::LogLevel::Trace, $($arg)+)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[macro_export]
|
||||
// macro_rules! debug {
|
||||
// ($($arg:tt)+) => {
|
||||
// $crate::log!($crate::LogLevel::Debug, $($arg)+)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[macro_export]
|
||||
// macro_rules! info {
|
||||
// ($($arg:tt)+) => {
|
||||
// $crate::log!($crate::LogLevel::Info, $($arg)+)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[macro_export]
|
||||
// macro_rules! info {
|
||||
// ($($arg:tt)+) => {
|
||||
// $crate::log!($crate::LogLevel::Info, $($arg)+)
|
||||
// }
|
||||
// }
|
||||
macro_rules! bitflags {
|
||||
(
|
||||
$(#[$attr1:meta])*
|
||||
$vis1:vis struct $name:ident($vis2:vis $rep:ty) {
|
||||
$(
|
||||
$(#[$attr2:meta])*
|
||||
$vis3:vis const $var:ident = $val:expr,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$(#[$attr1])*
|
||||
$vis1 struct $name($vis2 $rep);
|
||||
|
||||
$(
|
||||
$(#[$attr2])*
|
||||
$vis3 const $var: $name = $name($val);
|
||||
)*
|
||||
|
||||
impl std::ops::BitOr for $name {
|
||||
type Output = Self;
|
||||
|
||||
fn bitor(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 | rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitAnd for $name {
|
||||
type Output = Self;
|
||||
|
||||
fn bitand(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 & rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitOrAssign for $name {
|
||||
fn bitor_assign(&mut self, rhs: Self) {
|
||||
self.0 |= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitAndAssign for $name {
|
||||
fn bitand_assign(&mut self, rhs: Self) {
|
||||
self.0 &= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitXorAssign for $name {
|
||||
fn bitxor_assign(&mut self, rhs: Self) {
|
||||
self.0 ^= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Not for $name {
|
||||
type Output = Self;
|
||||
|
||||
fn not(self) -> Self::Output {
|
||||
Self(!self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for $name {
|
||||
#[allow(clippy::allow_attributes, clippy::bad_bit_mask, unused_mut)]
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let mut any = false;
|
||||
let mut v = self.0;
|
||||
$(
|
||||
if $val != 0 && v & $val == $val {
|
||||
if any {
|
||||
write!(f, "|")?;
|
||||
}
|
||||
any = true;
|
||||
write!(f, "{}", stringify!($var))?;
|
||||
v &= !$val;
|
||||
}
|
||||
)*
|
||||
if !any || v != 0 {
|
||||
if any {
|
||||
write!(f, "|")?;
|
||||
}
|
||||
write!(f, "0x{:x}", v)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
204
jay-config/src/window.rs
Normal file
204
jay-config/src/window.rs
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
//! Tools for inspecting and manipulating windows.
|
||||
|
||||
use {
|
||||
crate::{Axis, Direction, Workspace, client::Client},
|
||||
serde::{Deserialize, Serialize},
|
||||
};
|
||||
|
||||
/// A toplevel window.
|
||||
///
|
||||
/// A toplevel window is anything that can be stored within a container tile or within a
|
||||
/// floating window.
|
||||
///
|
||||
/// There are currently four types of windows:
|
||||
///
|
||||
/// - Containers
|
||||
/// - Placeholders that take the place of a window when it goes fullscreen
|
||||
/// - XDG toplevels
|
||||
/// - X windows
|
||||
///
|
||||
/// You can find out the type of a window by using the [`Window::type_`] function.
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct Window(pub u64);
|
||||
|
||||
bitflags! {
|
||||
/// The type of a window.
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq)]
|
||||
pub struct WindowType(pub u64) {
|
||||
/// A container.
|
||||
pub const CONTAINER = 1 << 0,
|
||||
/// A placeholder.
|
||||
pub const PLACEHOLDER = 1 << 1,
|
||||
/// An XDG toplevel.
|
||||
pub const XDG_TOPLEVEL = 1 << 2,
|
||||
/// An X window.
|
||||
pub const X_WINDOW = 1 << 3,
|
||||
}
|
||||
}
|
||||
|
||||
/// A window created by a client.
|
||||
///
|
||||
/// This is the same as `XDG_TOPLEVEL | X_WINDOW`.
|
||||
pub const CLIENT_WINDOW: WindowType = WindowType(XDG_TOPLEVEL.0 | X_WINDOW.0);
|
||||
|
||||
impl Window {
|
||||
/// Returns whether the window exists.
|
||||
pub fn exists(self) -> bool {
|
||||
self.0 != 0 && get!(false).window_exists(self)
|
||||
}
|
||||
|
||||
/// Returns whether the window does not exist.
|
||||
///
|
||||
/// This is a shorthand for `!self.exists()`.
|
||||
pub fn does_not_exist(self) -> bool {
|
||||
!self.exists()
|
||||
}
|
||||
|
||||
/// Returns the client of the window.
|
||||
///
|
||||
/// If the window does not have a client, [`Client::exists`] return false.
|
||||
pub fn client(self) -> Client {
|
||||
get!(Client(0)).window_client(self)
|
||||
}
|
||||
|
||||
/// Returns the title of the window.
|
||||
pub fn title(self) -> String {
|
||||
get!().window_title(self)
|
||||
}
|
||||
|
||||
/// Returns the type of the window.
|
||||
pub fn type_(self) -> WindowType {
|
||||
get!(WindowType(0)).window_type(self)
|
||||
}
|
||||
|
||||
/// Returns the identifier of the window.
|
||||
///
|
||||
/// This is the identifier used in the `ext-foreign-toplevel-list-v1` protocol.
|
||||
pub fn id(self) -> String {
|
||||
get!().window_id(self)
|
||||
}
|
||||
|
||||
/// Returns whether this window is visible.
|
||||
pub fn is_visible(self) -> bool {
|
||||
get!().window_is_visible(self)
|
||||
}
|
||||
|
||||
/// Returns the parent of this window.
|
||||
///
|
||||
/// If this window has no parent, [`Window::exists`] returns false.
|
||||
pub fn parent(self) -> Window {
|
||||
get!(Window(0)).window_parent(self)
|
||||
}
|
||||
|
||||
/// Returns the children of this window.
|
||||
///
|
||||
/// Only containers have children.
|
||||
pub fn children(self) -> Vec<Window> {
|
||||
get!().window_children(self)
|
||||
}
|
||||
|
||||
/// Moves the window in the specified direction.
|
||||
pub fn move_(self, direction: Direction) {
|
||||
get!().window_move(self, direction)
|
||||
}
|
||||
|
||||
/// Returns whether the parent-container of the window is in mono-mode.
|
||||
pub fn mono(self) -> bool {
|
||||
get!(false).window_mono(self)
|
||||
}
|
||||
|
||||
/// Sets whether the parent-container of the window is in mono-mode.
|
||||
pub fn set_mono(self, mono: bool) {
|
||||
get!().set_window_mono(self, mono)
|
||||
}
|
||||
|
||||
/// Toggles whether the parent-container of the window is in mono-mode.
|
||||
pub fn toggle_mono(self) {
|
||||
self.set_mono(!self.mono());
|
||||
}
|
||||
|
||||
/// Returns the split axis of the parent-container of the window.
|
||||
pub fn split(self) -> Axis {
|
||||
get!(Axis::Horizontal).window_split(self)
|
||||
}
|
||||
|
||||
/// Sets the split axis of the parent-container of the window.
|
||||
pub fn set_split(self, axis: Axis) {
|
||||
get!().set_window_split(self, axis)
|
||||
}
|
||||
|
||||
/// Toggles the split axis of the parent-container of the window.
|
||||
pub fn toggle_split(self) {
|
||||
self.set_split(self.split().other());
|
||||
}
|
||||
|
||||
/// Creates a new container with the specified split in place of the window.
|
||||
pub fn create_split(self, axis: Axis) {
|
||||
get!().create_window_split(self, axis);
|
||||
}
|
||||
|
||||
/// Requests the window to be closed.
|
||||
pub fn close(self) {
|
||||
get!().close_window(self);
|
||||
}
|
||||
|
||||
/// Returns whether the window is floating.
|
||||
pub fn floating(self) -> bool {
|
||||
get!().get_window_floating(self)
|
||||
}
|
||||
/// Sets whether the window is floating.
|
||||
pub fn set_floating(self, floating: bool) {
|
||||
get!().set_window_floating(self, floating);
|
||||
}
|
||||
|
||||
/// Toggles whether the window is floating.
|
||||
///
|
||||
/// You can do the same by double-clicking on the header.
|
||||
pub fn toggle_floating(self) {
|
||||
self.set_floating(!self.floating());
|
||||
}
|
||||
|
||||
/// Returns the workspace that this window belongs to.
|
||||
///
|
||||
/// If no such workspace exists, `exists` returns `false` for the returned workspace.
|
||||
pub fn workspace(self) -> Workspace {
|
||||
get!(Workspace(0)).get_window_workspace(self)
|
||||
}
|
||||
|
||||
/// Moves the window to the workspace.
|
||||
pub fn set_workspace(self, workspace: Workspace) {
|
||||
get!().set_window_workspace(self, workspace)
|
||||
}
|
||||
|
||||
/// Toggles whether the currently focused window is fullscreen.
|
||||
pub fn toggle_fullscreen(self) {
|
||||
self.set_fullscreen(!self.fullscreen())
|
||||
}
|
||||
/// Returns whether the window is fullscreen.
|
||||
pub fn fullscreen(self) -> bool {
|
||||
get!(false).get_window_fullscreen(self)
|
||||
}
|
||||
|
||||
/// Sets whether the window is fullscreen.
|
||||
pub fn set_fullscreen(self, fullscreen: bool) {
|
||||
get!().set_window_fullscreen(self, fullscreen)
|
||||
}
|
||||
|
||||
/// Gets whether the window is pinned.
|
||||
///
|
||||
/// If a floating window is pinned, it will stay visible even when switching to a
|
||||
/// different workspace.
|
||||
pub fn float_pinned(self) -> bool {
|
||||
get!().get_window_pinned(self)
|
||||
}
|
||||
|
||||
/// Sets whether the window is pinned.
|
||||
pub fn set_float_pinned(self, pinned: bool) {
|
||||
get!().set_window_pinned(self, pinned);
|
||||
}
|
||||
|
||||
/// Toggles whether the window is pinned.
|
||||
pub fn toggle_float_pinned(self) {
|
||||
self.set_float_pinned(!self.float_pinned());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue