1
0
Fork 0
forked from wry/wry

config: add create-mark, jump-to-mark, and copy-mark actions

This commit is contained in:
Julian Orth 2025-07-20 15:44:50 +02:00
parent e30e2595a1
commit eb625b34cc
19 changed files with 1193 additions and 9 deletions

View file

@ -76,6 +76,7 @@ use {
window::{TileState, Window, WindowMatcher},
xwayland::XScalingMode,
},
kbvm::Keycode,
libloading::Library,
log::Level,
regex::Regex,
@ -2208,6 +2209,32 @@ impl ConfigProxyHandler {
self.state.enable_primary_selection.set(enabled);
}
fn handle_seat_create_mark(&self, seat: Seat, kc: Option<u32>) -> Result<(), CphError> {
let seat = self.get_seat(seat)?;
if let Some(kc) = kc {
seat.create_mark(Keycode::from_evdev(kc));
} else {
seat.create_mark_interactive();
}
Ok(())
}
fn handle_seat_jump_to_mark(&self, seat: Seat, kc: Option<u32>) -> Result<(), CphError> {
let seat = self.get_seat(seat)?;
if let Some(kc) = kc {
seat.jump_to_mark(Keycode::from_evdev(kc));
} else {
seat.jump_to_mark_interactive();
}
Ok(())
}
fn handle_seat_copy_mark(&self, seat: Seat, src: u32, dst: u32) -> Result<(), CphError> {
let seat = self.get_seat(seat)?;
seat.copy_mark(Keycode::from_evdev(src), Keycode::from_evdev(dst));
Ok(())
}
fn spaces_change(&self) {
struct V;
impl NodeVisitorBase for V {
@ -3071,6 +3098,15 @@ impl ConfigProxyHandler {
ClientMessage::SetMiddleClickPasteEnabled { enabled } => {
self.handle_set_middle_click_paste_enabled(enabled)
}
ClientMessage::SeatCreateMark { seat, kc } => self
.handle_seat_create_mark(seat, kc)
.wrn("seat_create_mark")?,
ClientMessage::SeatJumpToMark { seat, kc } => self
.handle_seat_jump_to_mark(seat, kc)
.wrn("seat_jump_to_mark")?,
ClientMessage::SeatCopyMark { seat, src, dst } => self
.handle_seat_copy_mark(seat, src, dst)
.wrn("seat_copy_mark")?,
}
Ok(())
}

View file

@ -106,6 +106,7 @@ use {
},
ahash::AHashMap,
jay_config::keyboard::syms::{KeySym, SYM_Escape},
kbvm::Keycode,
smallvec::SmallVec,
std::{
cell::{Cell, RefCell},
@ -232,6 +233,14 @@ pub struct WlSeatGlobal {
focus_history_rotate: NumCell<u64>,
focus_history_visible_only: Cell<bool>,
focus_history_same_workspace: Cell<bool>,
mark_mode: Cell<Option<MarkMode>>,
marks: CopyHashMap<Keycode, Rc<dyn Node>>,
}
#[derive(Copy, Clone)]
enum MarkMode {
Mark,
Jump,
}
const CHANGE_CURSOR_MOVED: u32 = 1 << 0;
@ -311,6 +320,8 @@ impl WlSeatGlobal {
focus_history_rotate: Default::default(),
focus_history_visible_only: Cell::new(false),
focus_history_same_workspace: Cell::new(false),
mark_mode: Default::default(),
marks: Default::default(),
});
slf.pointer_cursor.set_owner(slf.clone());
let seat = slf.clone();
@ -1186,6 +1197,7 @@ impl WlSeatGlobal {
self.cursor_user_group.detach();
self.tablet_clear();
self.ei_seats.clear();
self.marks.clear();
}
pub fn id(&self) -> SeatId {

View file

@ -17,7 +17,7 @@ use {
},
},
wl_seat::{
CHANGE_CURSOR_MOVED, CHANGE_TREE, Dnd, SeatId, WlSeat, WlSeatGlobal,
CHANGE_CURSOR_MOVED, CHANGE_TREE, Dnd, MarkMode, SeatId, WlSeat, WlSeatGlobal,
tablet::{TabletPad, TabletPadId, TabletTool, TabletToolId},
text_input::TextDisconnectReason,
wl_keyboard::WlKeyboard,
@ -56,7 +56,7 @@ use {
syms::KeySym,
},
},
kbvm::{ModifierMask, state_machine::Event},
kbvm::{Keycode, ModifierMask, evdev, state_machine::Event},
linearize::LinearizeExt,
smallvec::SmallVec,
std::{
@ -80,6 +80,12 @@ pub struct NodeSeatState {
tablet_pad_foci: SmallMap<TabletPadId, Rc<TabletPad>, 1>,
tablet_tool_foci: SmallMap<TabletToolId, Rc<TabletTool>, 1>,
ui_drags: SmallMap<SeatId, Rc<WlSeatGlobal>, 1>,
marks: RefCell<SmallMapMut<SeatId, Marks, 1>>,
}
struct Marks {
seat: Rc<WlSeatGlobal>,
marks: SmallMapMut<Keycode, (), 1>,
}
pub struct FocusHistoryData {
@ -217,6 +223,12 @@ impl NodeSeatState {
entry.visible.set(false);
entry.detach();
}
for (_, marks) in self.marks.borrow_mut().iter_mut() {
for (kc, _) in &marks.marks {
marks.seat.marks.remove(kc);
}
marks.marks.clear();
}
self.destroy_node2(node, true);
}
@ -870,6 +882,23 @@ impl WlSeatGlobal {
KeyState::Pressed => pk.insert(kc.to_evdev()),
}
};
if key_state == KeyState::Pressed
&& let Some(mode) = self.mark_mode.take()
{
update_pressed_keys(&mut kbvm_state);
if kc == evdev::ESC {
continue;
}
match mode {
MarkMode::Mark => self.create_mark(kc),
MarkMode::Jump => {
drop(kbvm_state);
self.jump_to_mark(kc);
kbvm_state = kbvm_state_rc.borrow_mut();
}
}
continue;
}
shortcuts.clear();
{
let mut mods = kbvm_state.kb_state.mods.mods.0 & !(CAPS.0 | NUM.0);
@ -949,6 +978,60 @@ impl WlSeatGlobal {
self.send_components(&mut components_changed, &kbvm_state);
}
pub fn create_mark_interactive(&self) {
self.mark_mode.set(Some(MarkMode::Mark));
}
pub fn create_mark(self: &Rc<Self>, kc: Keycode) {
self.create_mark_(kc, self.keyboard_node.get());
}
fn create_mark_(self: &Rc<Self>, kc: Keycode, node: Rc<dyn Node>) {
let prev = self.marks.set(kc, node.clone());
if let Some(prev) = prev {
if prev.node_id() == node.node_id() {
return;
}
if let Some(marks) = prev.node_seat_state().marks.borrow_mut().get_mut(&self.id) {
marks.marks.remove(&kc);
}
}
node.node_seat_state()
.marks
.borrow_mut()
.get_or_insert_with(self.id, || Marks {
seat: self.clone(),
marks: Default::default(),
})
.marks
.insert(kc, ());
}
pub fn jump_to_mark_interactive(&self) {
self.mark_mode.set(Some(MarkMode::Jump));
}
pub fn jump_to_mark(self: &Rc<Self>, kc: Keycode) {
if let Some(node) = self.marks.get(&kc)
&& node.node_accepts_focus()
&& node.node_id() != self.keyboard_node.get().node_id()
{
if !node.node_visible() {
node.clone().node_make_visible();
if !node.node_visible() {
return;
}
}
self.focus_node(node);
}
}
pub fn copy_mark(self: &Rc<Self>, src: Keycode, dst: Keycode) {
if let Some(node) = self.marks.get(&src) {
self.create_mark_(dst, node);
}
}
fn send_components(&self, components_changed: &mut bool, kbvm_state: &KbvmState) {
if !mem::take(components_changed) {
return;

View file

@ -198,6 +198,15 @@ impl<K: Eq, V, const N: usize> SmallMapMut<K, V, N> {
None
}
pub fn get_mut(&mut self, k: &K) -> Option<&mut V> {
for (ek, ev) in &mut self.m {
if ek == k {
return Some(ev);
}
}
None
}
pub fn get_or_default_mut(&mut self, k: K) -> &mut V
where
V: Default,