Skip to content

Commit

Permalink
feat(server): add support for wp_game_controller_v1
Browse files Browse the repository at this point in the history
  • Loading branch information
colinmarc committed Sep 13, 2024
1 parent 2238751 commit 1fa16c3
Show file tree
Hide file tree
Showing 9 changed files with 447 additions and 14 deletions.
28 changes: 25 additions & 3 deletions mm-server/src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ impl Compositor {
create_global::<zwp_pointer_constraints_v1::ZwpPointerConstraintsV1>(&dh, 1);
create_global::<zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1>(&dh, 1);
create_global::<zwp_text_input_manager_v3::ZwpTextInputManagerV3>(&dh, 1);
create_global::<wp_game_controller::WpGameControllerV1>(&dh, 1);

create_global::<wl_shm::WlShm>(&dh, 1);
create_global::<zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1>(&dh, 5);
Expand Down Expand Up @@ -817,7 +818,7 @@ impl Compositor {
self.state.new_display_params = Some(params);
}
ControlMessage::KeyboardInput {
evdev_scancode,
key_code: evdev_scancode,
char,
state,
} => {
Expand Down Expand Up @@ -927,6 +928,26 @@ impl Compositor {
ControlMessage::PointerLeft => {
self.state.default_seat.lift_pointer(&self.state.serial);
}
// TODO: for now, we always assume a controller is plugged in.
// ControlMessage::GamepadAvailable(_) => (),
// ControlMessage::GamepadUnavailable(_) => (),
ControlMessage::GamepadAxis {
axis_code, value, ..
} => {
self.state.default_seat.gamepad_axis(axis_code, value);
}
ControlMessage::GamepadTrigger {
trigger_code,
value,
..
} => {
self.state.default_seat.gamepad_trigger(trigger_code, value);
}
ControlMessage::GamepadInput {
button_code, state, ..
} => {
self.state.default_seat.gamepad_input(button_code, state);
}
// Handled above.
ControlMessage::Stop | ControlMessage::Attach { .. } => unreachable!(),
}
Expand All @@ -938,10 +959,11 @@ impl Compositor {
fn create_global<G: wayland_server::Resource + 'static>(
dh: &wayland_server::DisplayHandle,
version: u32,
) where
) -> wayland_server::backend::GlobalId
where
State: wayland_server::GlobalDispatch<G, ()>,
{
let _ = dh.create_global::<State, G, ()>(version, ());
dh.create_global::<State, G, ()>(version, ())
}

fn gen_socket_name() -> OsString {
Expand Down
22 changes: 20 additions & 2 deletions mm-server/src/compositor/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crossbeam_channel::Sender;
use crate::{
codec::{AudioCodec, VideoCodec},
color::VideoProfile,
compositor::ButtonState,
pixel_scale::PixelScale,
};

Expand Down Expand Up @@ -47,7 +48,7 @@ pub enum ControlMessage {
Detach(u64),
UpdateDisplayParams(DisplayParams),
KeyboardInput {
evdev_scancode: u32,
key_code: u32,
state: super::KeyState,
char: Option<char>,
},
Expand All @@ -59,10 +60,27 @@ pub enum ControlMessage {
x: f64,
y: f64,
button_code: u32,
state: super::ButtonState,
state: ButtonState,
},
PointerAxis(f64, f64),
PointerAxisDiscrete(f64, f64),
// GamepadAvailable(u64),
// GamepadUnavailable(u64),
GamepadAxis {
_id: u64,
axis_code: u32,
value: f64,
},
GamepadTrigger {
_id: u64,
trigger_code: u32,
value: f64,
},
GamepadInput {
_id: u64,
button_code: u32,
state: ButtonState,
},
}

#[derive(Debug, Clone)]
Expand Down
1 change: 1 addition & 0 deletions mm-server/src/compositor/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod wl_drm;
mod wl_output;
mod wl_seat;
mod wl_shm;
mod wp_game_controller;
mod wp_linux_dmabuf;
mod wp_pointer_constraints;
mod wp_presentation;
Expand Down
37 changes: 37 additions & 0 deletions mm-server/src/compositor/dispatch/wp_game_controller.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2024 Colin Marc <[email protected]>
//
// SPDX-License-Identifier: BUSL-1.1

use crate::compositor::{wp_game_controller::wp_game_controller_v1, State};

impl wayland_server::GlobalDispatch<wp_game_controller_v1::WpGameControllerV1, ()> for State {
fn bind(
state: &mut Self,
_handle: &wayland_server::DisplayHandle,
_client: &wayland_server::Client,
resource: wayland_server::New<wp_game_controller_v1::WpGameControllerV1>,
_global_data: &(),
data_init: &mut wayland_server::DataInit<'_, Self>,
) {
let global = data_init.init(resource, ());
state.default_seat.add_gamepad(global);
}
}

impl wayland_server::Dispatch<wp_game_controller_v1::WpGameControllerV1, ()> for State {
fn request(
state: &mut Self,
_client: &wayland_server::Client,
resource: &wp_game_controller_v1::WpGameControllerV1,
request: wp_game_controller_v1::Request,
_data: &(),
_dhandle: &wayland_server::DisplayHandle,
_data_init: &mut wayland_server::DataInit<'_, Self>,
) {
match request {
wp_game_controller_v1::Request::Destroy => {
state.default_seat.destroy_gamepad(resource);
}
}
}
}
1 change: 1 addition & 0 deletions mm-server/src/compositor/protocols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
// SPDX-License-Identifier: BUSL-1.1

pub mod wl_drm;
pub mod wp_game_controller;
161 changes: 161 additions & 0 deletions mm-server/src/compositor/protocols/game-controller-v1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="game_controller_v1">
<copyright>
Copyright © 2023-2024 Collabora, Ltd.

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
</copyright>

<description summary="Wayland protocol for game controller devices">
TODO high level documentation about game controllers and the input source
</description>

<interface name="wp_game_controller_v1" version="1">
<description summary="game controller input device">
This interface represents a physical game controller, also known as a
gamepad, held by the user in their hands.

The wp_game_controller_v1 interface generates events for every input
sources present on the game controller. The client can also request
haptic vibration, or rumble, if the hardware supports it.
</description>

<request name="destroy" type="destructor">
<description summary="release the memory for the game controller object">
Destroy the game controller device.
</description>
</request>

<event name="name">
<description summary="name of this game controller">
User friendly device identification string. The game controller name
is a UTF-8 string that should not be NULL.
</description>
<arg name="name" type="string" summary="game controller name"/>
</event>

<enum name="theme">
<description summary="button theme">
Each vendor uses a different set of glyph on its controller's buttons.
</description>
<entry name="none" value="0" summary="default value"/>
<entry name="playstation" value="1" summary="Sony controllers"/>
<entry name="xbox" value="2" summary="Microsoft controllers"/>
<entry name="nintendo" value="3" summary="Nintendo controllers"/>
</enum>

<event name="theme_hint">
<description summary="theme the client should use">
Theme the client should follow to render the adequate glyph for matching
the button on the physical controller.
</description>
<arg name="hint" type="uint" enum="theme" summary="theme hint"/>
</event>

<event name="done">
<description summary="all properties events are sent">
This event is sent after all of the other properties event have been
sent. No more property events will be sent to the client after this.
</description>
</event>

<event name="enter">
<description summary="enter focus event">
Notification that the gamepad is focused on a given surface.
</description>
<arg name="serial" type="uint" summary="serial number of the enter evenr"/>
<arg name="surface" type="object" interface="wl_surface" summary="surface gaining gamepad focus"/>
</event>

<event name="leave">
<description summary="leave focus event">
Notification that the gamepad is no longer focused on the given surface.
</description>
<arg name="serial" type="uint" summary="serial number of the leave event"/>
<arg name="surface" type="object" interface="wl_surface" summary="surface loosing gamepad focus"/>
</event>

<enum name="button_state">
<description summary="physical input source state">
Describes the physical state of a button on the game controller.
</description>
<entry name="released" value="0" summary="the input source is not pressed"/>
<entry name="pressed" value="1" summary="the input source is pressed"/>
</enum>

<event name="button">
<description summary="game controller button event">
game controller button click and release notification.

The source is a button code as defined in the Linux kernel's
linux/input-event-codes.h header file.

The time argument is a timestamp in microseconds of the moment of the
state changes
</description>
<arg name="source" type="uint" summary="source that produced the event"/>
<arg name="state" type="uint" enum="button_state" summary="physical state of the button"/>
<arg name="time" type="uint" summary="timestamp with microsecond granularity"/>
</event>

<event name="trigger">
<description summary="game controller trigger event">
game controller trigger pressure notification, expressed with a value
varying between 0.0 and 1.0, with 0.0 being the neutral state.

The source is a button code as defined in the Linux kernel's
linux/input-event-codes.h header file.

The time argument is a timestamp in microseconds of the moment of the
state changes
</description>
<arg name="source" type="uint" summary="source that produced the event"/>
<arg name="value" type="fixed" summary="trigger value in the 0 to 1 range"/>
<arg name="time" type="uint" summary="timestamp with microsecond granularity"/>
</event>

<event name="axis">
<description summary="game controller axis event">
game controller axis position notification, expressed by a 2D
position varying from -1.0 to 1.0, with 0.0 being the neutral state.

The source is a button code as defined in the Linux kernel's
linux/input-event-codes.h header file.

The time argument is a timestamp in microseconds of the moment of the
state changes
</description>
<arg name="source" type="uint" summary="source that produced the event"/>
<arg name="value" type="fixed" summary="axis coordinate in the -1 to 1 range"/>
<arg name="time" type="uint" summary="timestamp with microsecond granularity"/>
</event>

<event name="frame">
<description summary="end of a game controller event sequence">
Indicates the end of a set of events that logically belong together.
A client is expected to accumulate the data in all events within the
frame before proceeding

All wp_game_controller_v1 events before a wp_game_controller_v1.frame
event belong together.
</description>
</event>
</interface>
</protocol>
20 changes: 20 additions & 0 deletions mm-server/src/compositor/protocols/wp_game_controller.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2024 Colin Marc <[email protected]>
//
// SPDX-License-Identifier: BUSL-1.1

#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]

use wayland_server;
use wayland_server::protocol::*;

pub mod __interfaces {
use wayland_server::backend as wayland_backend;
use wayland_server::protocol::__interfaces::*;
wayland_scanner::generate_interfaces!("src/compositor/protocols/game-controller-v1.xml");
}

use self::__interfaces::*;
wayland_scanner::generate_server_code!("src/compositor/protocols/game-controller-v1.xml");

pub use wp_game_controller_v1::*;
Loading

0 comments on commit 1fa16c3

Please sign in to comment.