Skip to content

Commit b60ade8

Browse files
authored
Merge pull request #6 from mahkoh/jorth/update-protocols-2026-01-17
Update protocols
2 parents bea8151 + b3a5339 commit b60ade8

File tree

8 files changed

+1130
-10
lines changed

8 files changed

+1130
-10
lines changed

protocols/river-protocols/river-xkb-bindings-v1.xml

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
corresponding interface version bump. Backward incompatible changes can only
3737
be done by creating a new major version of the extension.
3838
</description>
39-
<interface name="river_xkb_bindings_v1" version="1">
39+
<interface name="river_xkb_bindings_v1" version="2">
4040
<description summary="xkbcommon bindings global interface">
4141
This global interface should only be advertised to the client if the
4242
river_window_manager_v1 global is also advertised.
@@ -60,8 +60,21 @@
6060
<arg name="keysym" type="uint" summary="an xkbcommon keysym"/>
6161
<arg name="modifiers" type="uint" enum="river_seat_v1.modifiers"/>
6262
</request>
63+
<request name="get_seat" since="2">
64+
<description summary="manage seat-specific state">
65+
Create an object to manage seat-specific xkb bindings state.
66+
67+
It is a protocol error to make this request more than once for a given
68+
river_seat_v1 object.
69+
</description>
70+
<arg name="id" type="new_id" interface="river_xkb_bindings_seat_v1"/>
71+
<arg name="seat" type="object" interface="river_seat_v1"/>
72+
</request>
73+
<enum name="error" since="2">
74+
<entry name="object_already_created" value="0" since="2"/>
75+
</enum>
6376
</interface>
64-
<interface name="river_xkb_binding_v1" version="1">
77+
<interface name="river_xkb_binding_v1" version="2">
6578
<description summary="configure a xkb key binding, receive trigger events">
6679
This object allows the window manager to configure a xkbcommon key binding
6780
and receive events when the key binding is triggered.
@@ -162,5 +175,80 @@
162175
input events is finite.
163176
</description>
164177
</event>
178+
<event name="stop_repeat" since="2">
179+
<description summary="repeating should be stopped">
180+
This event indicates that repeating should be stopped for the binding if
181+
the window manager has been repeating some action since the pressed
182+
event.
183+
184+
This event is generally sent when some other (possible unbound) key is
185+
pressed after the pressed event is sent and before the released event
186+
is sent for this binding.
187+
188+
This event will be followed by a manage_start event after all other new
189+
state has been sent by the server.
190+
</description>
191+
</event>
192+
</interface>
193+
<interface name="river_xkb_bindings_seat_v1" version="2">
194+
<description summary="xkb bindings seat">
195+
This object manages xkb bindings state associated with a specific seat.
196+
</description>
197+
<request name="destroy" type="destructor" since="2">
198+
<description summary="destroy the object">
199+
This request indicates that the client will no longer use the object and
200+
that it may be safely destroyed.
201+
</description>
202+
</request>
203+
<request name="ensure_next_key_eaten" since="2">
204+
<description summary="ensure the next key press event is eaten">
205+
Ensure that the next non-modifier key press and corresponding release
206+
events for this seat are not sent to the currently focused surface.
207+
208+
If the next non-modifier key press triggers a binding, the
209+
pressed/released events are sent to the river_xkb_binding_v1 object as
210+
usual.
211+
212+
If the next non-modifier key press does not trigger a binding, the
213+
ate_unbound_key event is sent instead.
214+
215+
Rationale: the window manager may wish to implement "chorded"
216+
keybindings where triggering a binding activates a "submap" with a
217+
different set of keybindings. Without a way to eat the next key
218+
press event, there is no good way for the window manager to know that it
219+
should error out and exit the submap when a key not bound in the submap
220+
is pressed.
221+
222+
This request modifies window management state and may only be made as
223+
part of a manage sequence, see the river_window_manager_v1 description.
224+
</description>
225+
</request>
226+
<request name="cancel_ensure_next_key_eaten" since="2">
227+
<description summary="cancel an ensure_next_key_eaten request">
228+
This requests cancels the effect of the latest ensure_next_key_eaten
229+
request if no key has been eaten due to the request yet. This request
230+
has no effect if a key has already been eaten or no
231+
ensure_next_key_eaten was made.
232+
233+
Rationale: the window manager may wish cancel an uncompleted "chorded"
234+
keybinding after a timeout of a few seconds. Note that since this
235+
timeout use-case requires the window manager to trigger a manage sequence
236+
with the river_window_manager_v1.manage_dirty request it is possible that
237+
the ate_unbound_key key event may be sent before the window manager has
238+
a chance to make the cancel_ensure_next_key_eaten request.
239+
240+
This request modifies window management state and may only be made as
241+
part of a manage sequence, see the river_window_manager_v1 description.
242+
</description>
243+
</request>
244+
<event name="ate_unbound_key" since="2">
245+
<description summary="an unbound key press event was eaten">
246+
An unbound key press event was eaten due to the ensure_next_key_eaten
247+
request.
248+
249+
This event will be followed by a manage_start event after all other new
250+
state has been sent by the server.
251+
</description>
252+
</event>
165253
</interface>
166254
</protocol>

wl-proxy/src/baseline/versions/prototyping.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,9 @@ const river_seat_v1: u32 = 3;
7272
const river_shell_surface_v1: u32 = 3;
7373
const river_window_manager_v1: u32 = 3;
7474
const river_window_v1: u32 = 3;
75-
const river_xkb_binding_v1: u32 = 1;
76-
const river_xkb_bindings_v1: u32 = 1;
75+
const river_xkb_binding_v1: u32 = 2;
76+
const river_xkb_bindings_seat_v1: u32 = 2;
77+
const river_xkb_bindings_v1: u32 = 2;
7778
const weston_capture_source_v1: u32 = 2;
7879
const weston_capture_v1: u32 = 2;
7980
const weston_content_protection: u32 = 1;
@@ -418,6 +419,8 @@ pub(in super::super) const BASELINE: &StaticCopyMap<ObjectInterface, u32> = {
418419
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
419420
{ baseline[ObjectInterface::RiverXkbBindingV1.__linearize_d66aa8fa_6974_4651_b2b7_75291a9e7105()] = river_xkb_binding_v1; }
420421
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
422+
{ baseline[ObjectInterface::RiverXkbBindingsSeatV1.__linearize_d66aa8fa_6974_4651_b2b7_75291a9e7105()] = river_xkb_bindings_seat_v1; }
423+
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
421424
{ baseline[ObjectInterface::RiverXkbBindingsV1.__linearize_d66aa8fa_6974_4651_b2b7_75291a9e7105()] = river_xkb_bindings_v1; }
422425
#[cfg(feature = "protocol-weston_output_capture")]
423426
{ baseline[ObjectInterface::WestonCaptureSourceV1.__linearize_d66aa8fa_6974_4651_b2b7_75291a9e7105()] = weston_capture_source_v1; }

wl-proxy/src/baseline/versions/prototyping.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ river_seat_v1 = 3
6767
river_shell_surface_v1 = 3
6868
river_window_manager_v1 = 3
6969
river_window_v1 = 3
70-
river_xkb_binding_v1 = 1
71-
river_xkb_bindings_v1 = 1
70+
river_xkb_binding_v1 = 2
71+
river_xkb_bindings_seat_v1 = 2
72+
river_xkb_bindings_v1 = 2
7273
weston_capture_source_v1 = 2
7374
weston_capture_v1 = 2
7475
weston_content_protection = 1

wl-proxy/src/protocols.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,11 @@ mod all_types {
10381038
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
10391039
pub(super) use super::river_xkb_bindings_v1::river_xkb_binding_v1::RiverXkbBindingV1;
10401040
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
1041+
pub(super) use super::river_xkb_bindings_v1::river_xkb_bindings_seat_v1::RiverXkbBindingsSeatV1;
1042+
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
10411043
pub(super) use super::river_xkb_bindings_v1::river_xkb_bindings_v1::RiverXkbBindingsV1;
1044+
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
1045+
pub(super) use super::river_xkb_bindings_v1::river_xkb_bindings_v1::RiverXkbBindingsV1Error;
10421046
#[cfg(feature = "protocol-ivi_application")]
10431047
pub(super) use super::ivi_application::ivi_application::IviApplication;
10441048
#[cfg(feature = "protocol-ivi_application")]
@@ -2057,6 +2061,10 @@ mod all_types {
20572061
#[cfg(feature = "protocol-river_xkb_bindings_v1")] { Some(ObjectInterface::RiverXkbBindingV1) }
20582062
#[cfg(not(feature = "protocol-river_xkb_bindings_v1"))] { None }
20592063
},
2064+
"river_xkb_bindings_seat_v1" => {
2065+
#[cfg(feature = "protocol-river_xkb_bindings_v1")] { Some(ObjectInterface::RiverXkbBindingsSeatV1) }
2066+
#[cfg(not(feature = "protocol-river_xkb_bindings_v1"))] { None }
2067+
},
20602068
"river_xkb_bindings_v1" => {
20612069
#[cfg(feature = "protocol-river_xkb_bindings_v1")] { Some(ObjectInterface::RiverXkbBindingsV1) }
20622070
#[cfg(not(feature = "protocol-river_xkb_bindings_v1"))] { None }
@@ -3834,6 +3842,13 @@ mod all_types {
38343842
Ok(RiverXkbBindingV1::new(state, version))
38353843
}
38363844
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
3845+
Self::RiverXkbBindingsSeatV1 => {
3846+
if version > RiverXkbBindingsSeatV1::XML_VERSION {
3847+
return Err(ObjectError(ObjectErrorKind::MaxVersion(self, version)));
3848+
}
3849+
Ok(RiverXkbBindingsSeatV1::new(state, version))
3850+
}
3851+
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
38373852
Self::RiverXkbBindingsV1 => {
38383853
if version > RiverXkbBindingsV1::XML_VERSION {
38393854
return Err(ObjectError(ObjectErrorKind::MaxVersion(self, version)));
@@ -4745,6 +4760,9 @@ pub enum ObjectInterface {
47454760
/// river_xkb_binding_v1
47464761
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
47474762
RiverXkbBindingV1,
4763+
/// river_xkb_bindings_seat_v1
4764+
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
4765+
RiverXkbBindingsSeatV1,
47484766
/// river_xkb_bindings_v1
47494767
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
47504768
RiverXkbBindingsV1,
@@ -5296,6 +5314,8 @@ impl ObjectInterface {
52965314
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
52975315
Self::RiverXkbBindingV1 => "river_xkb_binding_v1",
52985316
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
5317+
Self::RiverXkbBindingsSeatV1 => "river_xkb_bindings_seat_v1",
5318+
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
52995319
Self::RiverXkbBindingsV1 => "river_xkb_bindings_v1",
53005320
#[cfg(feature = "protocol-ivi_application")]
53015321
Self::IviApplication => "ivi_application",
@@ -5814,9 +5834,11 @@ impl ObjectInterface {
58145834
#[cfg(feature = "protocol-river_window_management_v1")]
58155835
Self::RiverWindowV1 => 3,
58165836
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
5817-
Self::RiverXkbBindingV1 => 1,
5837+
Self::RiverXkbBindingV1 => 2,
5838+
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
5839+
Self::RiverXkbBindingsSeatV1 => 2,
58185840
#[cfg(feature = "protocol-river_xkb_bindings_v1")]
5819-
Self::RiverXkbBindingsV1 => 1,
5841+
Self::RiverXkbBindingsV1 => 2,
58205842
#[cfg(feature = "protocol-ivi_application")]
58215843
Self::IviApplication => 1,
58225844
#[cfg(feature = "protocol-ivi_application")]

wl-proxy/src/protocols/river_xkb_bindings_v1.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@
3030
#![allow(rustdoc::invalid_rust_codeblocks)]
3131

3232
pub mod river_xkb_binding_v1;
33+
pub mod river_xkb_bindings_seat_v1;
3334
pub mod river_xkb_bindings_v1;

wl-proxy/src/protocols/river_xkb_bindings_v1/river_xkb_binding_v1.rs

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ struct DefaultHandler;
3636
impl RiverXkbBindingV1Handler for DefaultHandler { }
3737

3838
impl ConcreteObject for RiverXkbBindingV1 {
39-
const XML_VERSION: u32 = 1;
39+
const XML_VERSION: u32 = 2;
4040
const INTERFACE: ObjectInterface = ObjectInterface::RiverXkbBindingV1;
4141
const INTERFACE_NAME: &str = "river_xkb_binding_v1";
4242
}
@@ -510,6 +510,79 @@ impl RiverXkbBindingV1 {
510510
log_send("river_xkb_binding_v1.released", &e);
511511
}
512512
}
513+
514+
/// Since when the stop_repeat message is available.
515+
pub const MSG__STOP_REPEAT__SINCE: u32 = 2;
516+
517+
/// repeating should be stopped
518+
///
519+
/// This event indicates that repeating should be stopped for the binding if
520+
/// the window manager has been repeating some action since the pressed
521+
/// event.
522+
///
523+
/// This event is generally sent when some other (possible unbound) key is
524+
/// pressed after the pressed event is sent and before the released event
525+
/// is sent for this binding.
526+
///
527+
/// This event will be followed by a manage_start event after all other new
528+
/// state has been sent by the server.
529+
#[inline]
530+
pub fn try_send_stop_repeat(
531+
&self,
532+
) -> Result<(), ObjectError> {
533+
let core = self.core();
534+
let client_ref = core.client.borrow();
535+
let Some(client) = &*client_ref else {
536+
return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
537+
};
538+
let id = core.client_obj_id.get().unwrap_or(0);
539+
#[cfg(feature = "logging")]
540+
if self.core.state.log {
541+
#[cold]
542+
fn log(state: &State, client_id: u64, id: u32) {
543+
let (millis, micros) = time_since_epoch();
544+
let prefix = &state.log_prefix;
545+
let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= river_xkb_binding_v1#{}.stop_repeat()\n", client_id, id);
546+
state.log(args);
547+
}
548+
log(&self.core.state, client.endpoint.id, id);
549+
}
550+
let endpoint = &client.endpoint;
551+
if !endpoint.flush_queued.replace(true) {
552+
self.core.state.add_flushable_endpoint(endpoint, Some(client));
553+
}
554+
let mut outgoing_ref = endpoint.outgoing.borrow_mut();
555+
let outgoing = &mut *outgoing_ref;
556+
let mut fmt = outgoing.formatter();
557+
fmt.words([
558+
id,
559+
2,
560+
]);
561+
Ok(())
562+
}
563+
564+
/// repeating should be stopped
565+
///
566+
/// This event indicates that repeating should be stopped for the binding if
567+
/// the window manager has been repeating some action since the pressed
568+
/// event.
569+
///
570+
/// This event is generally sent when some other (possible unbound) key is
571+
/// pressed after the pressed event is sent and before the released event
572+
/// is sent for this binding.
573+
///
574+
/// This event will be followed by a manage_start event after all other new
575+
/// state has been sent by the server.
576+
#[inline]
577+
pub fn send_stop_repeat(
578+
&self,
579+
) {
580+
let res = self.try_send_stop_repeat(
581+
);
582+
if let Err(e) = res {
583+
log_send("river_xkb_binding_v1.stop_repeat", &e);
584+
}
585+
}
513586
}
514587

515588
/// A message handler for [`RiverXkbBindingV1`] proxies.
@@ -683,6 +756,33 @@ pub trait RiverXkbBindingV1Handler: Any {
683756
log_forward("river_xkb_binding_v1.released", &e);
684757
}
685758
}
759+
760+
/// repeating should be stopped
761+
///
762+
/// This event indicates that repeating should be stopped for the binding if
763+
/// the window manager has been repeating some action since the pressed
764+
/// event.
765+
///
766+
/// This event is generally sent when some other (possible unbound) key is
767+
/// pressed after the pressed event is sent and before the released event
768+
/// is sent for this binding.
769+
///
770+
/// This event will be followed by a manage_start event after all other new
771+
/// state has been sent by the server.
772+
#[inline]
773+
fn handle_stop_repeat(
774+
&mut self,
775+
slf: &Rc<RiverXkbBindingV1>,
776+
) {
777+
if !slf.core.forward_to_client.get() {
778+
return;
779+
}
780+
let res = slf.try_send_stop_repeat(
781+
);
782+
if let Err(e) = res {
783+
log_forward("river_xkb_binding_v1.stop_repeat", &e);
784+
}
785+
}
686786
}
687787

688788
impl ObjectPrivate for RiverXkbBindingV1 {
@@ -857,6 +957,27 @@ impl ObjectPrivate for RiverXkbBindingV1 {
857957
DefaultHandler.handle_released(&self);
858958
}
859959
}
960+
2 => {
961+
if msg.len() != 2 {
962+
return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
963+
}
964+
#[cfg(feature = "logging")]
965+
if self.core.state.log {
966+
#[cold]
967+
fn log(state: &State, id: u32) {
968+
let (millis, micros) = time_since_epoch();
969+
let prefix = &state.log_prefix;
970+
let args = format_args!("[{millis:7}.{micros:03}] {prefix}server -> river_xkb_binding_v1#{}.stop_repeat()\n", id);
971+
state.log(args);
972+
}
973+
log(&self.core.state, msg[0]);
974+
}
975+
if let Some(handler) = handler {
976+
(**handler).handle_stop_repeat(&self);
977+
} else {
978+
DefaultHandler.handle_stop_repeat(&self);
979+
}
980+
}
860981
n => {
861982
let _ = server;
862983
let _ = msg;
@@ -883,6 +1004,7 @@ impl ObjectPrivate for RiverXkbBindingV1 {
8831004
let name = match id {
8841005
0 => "pressed",
8851006
1 => "released",
1007+
2 => "stop_repeat",
8861008
_ => return None,
8871009
};
8881010
Some(name)

0 commit comments

Comments
 (0)