Skip to content

Commit

Permalink
fix(Udisks2): Fully restore Udisks2 and SteamRemovableMedia functiona…
Browse files Browse the repository at this point in the history
…lity.

- Restores parity for Udisks2
- Restores parity for SteamRemovableMedia
- Fixes a bug with the game loading overlay appearing after OpenGamepadUI is detected by Gamescope.
- Properly load devices and profiles in InputPlumber
  • Loading branch information
pastaq authored and ShadowApex committed Dec 22, 2024
1 parent 8537546 commit 59a8116
Show file tree
Hide file tree
Showing 22 changed files with 733 additions and 475 deletions.
20 changes: 10 additions & 10 deletions core/global/launch_manager.gd
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,16 @@ func _init() -> void:
var on_focus_changed := func(from: int, to: int):
logger.info("Window focus changed from " + str(from) + " to: " + str(to))
var last_app := _current_app

_current_app = _detect_running_app(to)

logger.debug("Last app: " + str(last_app) + " current_app: " + str(_current_app))
app_switched.emit(last_app, _current_app)

# If the app has a gamepad profile, set it
if to != _ogui_window_id and _current_app:
if _current_app:
set_app_gamepad_profile(_current_app)

# If we don't want LaunchManager to manage overlay (I.E. overlay mode), return false always.
if not should_manage_overlay:
return

_xwayland_primary.focused_window_updated.connect(on_focus_changed)

# Debug print when the focused app changed
Expand Down Expand Up @@ -326,11 +323,11 @@ func set_gamepad_profile(path: String, target_gamepad: String = "") -> void:
logger.info("Loading global gamepad profile: " + profile_path)

for gamepad in input_plumber.get_composite_devices():
gamepad.target_modify_profile(profile_path, profile_modifier)
InputPlumber.load_target_modified_profile(gamepad, profile_path, profile_modifier)

# Set the target gamepad if one was specified
if not target_gamepad.is_empty():
var target_devices := [target_gamepad, "keyboard", "mouse"]
var target_devices := PackedStringArray([target_gamepad, "keyboard", "mouse"])
match target_gamepad:
"xb360", "xbox-series", "xbox-elite", "gamepad":
target_devices.append("touchpad")
Expand All @@ -354,11 +351,11 @@ func set_gamepad_profile(path: String, target_gamepad: String = "") -> void:

# TODO: Save profiles for individual controllers?
for gamepad in input_plumber.get_composite_devices():
gamepad.target_modify_profile(path, profile_modifier)
InputPlumber.load_target_modified_profile(gamepad, path, profile_modifier)

# Set the target gamepad if one was specified
if not target_gamepad.is_empty():
var target_devices := [target_gamepad, "keyboard", "mouse"]
var target_devices := PackedStringArray([target_gamepad, "keyboard", "mouse"])
match target_gamepad:
"xb360", "xbox-series", "xbox-elite", "gamepad":
target_devices.append("touchpad")
Expand Down Expand Up @@ -407,7 +404,7 @@ func _on_app_state_changed(_from: RunningApp.STATE, to: RunningApp.STATE, app: R
_remove_running(app)
if state_machine.has_state(in_game_state) and _running.size() == 0:
logger.info("No more apps are running. Removing in-game state.")
gamescope.remove_baselayer_window()
_xwayland_primary.remove_baselayer_window()
state_machine.remove_state(in_game_state)
state_machine.remove_state(in_game_menu_state)

Expand Down Expand Up @@ -516,6 +513,9 @@ func _is_app_id_running(app_id) -> bool:
# creates a new RunningApp instance.
func _detect_running_app(window_id: int) -> RunningApp:
logger.debug("No known running app in focused window. Attempting to detect the running app.")
if window_id == _ogui_window_id:
return null

var app_name: String

# Check if this window ID is a child of an existing RunningApp
Expand Down
12 changes: 0 additions & 12 deletions core/systems/disks/steam_removable_media_manager.gd
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,6 @@ func format_drive(device: BlockDevice) -> Error:
logger.error("System is not format capable")
return ERR_UNAVAILABLE

# This should never hit if using our device tree, but the method is public so
# make sure.
if udisks2.block_device_has_protected_mount(device):
logger.error("Attempted to format device with protected mount. Illegal Operation.")
return ERR_UNAUTHORIZED

var drive = "/dev" + device.dbus_path.trim_prefix(BLOCK_PREFIX)
logger.debug("Formatting drive:", drive)
var args := ["--full", "--device", drive]
Expand All @@ -83,12 +77,6 @@ func init_steam_lib(partition: PartitionDevice) -> Error:
logger.error("System cannot initialize steam libraries")
return ERR_UNAVAILABLE

# This should never hit if using our device tree, but the method is public so
# make sure.
if udisks2.partition_has_protected_mount(partition):
logger.error("Attempted to initialize steam library on device with protected mount. Illegal Operation.")
return ERR_UNAUTHORIZED

var drive := "/dev" + partition.dbus_path.trim_prefix(BLOCK_PREFIX)
logger.debug("Intitializing partition as Steam Library: " + drive)
var args := [drive]
Expand Down
63 changes: 63 additions & 0 deletions core/systems/input/input_plumber.gd
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,66 @@ func _process(_delta: float) -> void:
if not instance:
return
instance.process()


## Load the given profile on the composite device, optionally specifying a profile
## modifier, which is a target device string (e.g. "deck", "ds5-edge", etc.) to
## adapt the profile for. This will update the profile with target-specific
## defaults, like mapping left/right pads to the DualSense center pad if no
## other mappings are defined.
static func load_target_modified_profile(device: CompositeDevice, path: String, profile_modifier: String = "") -> void:
var logger := Log.get_logger("InputPlumber", Log.LEVEL.DEBUG)
logger.debug("Loading Profile:", path)
if path == "" or not path.ends_with(".json") or not FileAccess.file_exists(path):
logger.error("Profile path:", path," is not a valid profile path.")
return
if profile_modifier.is_empty():
device.load_profile_path(path)
return

var profile := InputPlumberProfile.load(path)

var c_pad_cap = "Touchpad:CenterPad:Motion"
var l_pad_cap = "Touchpad:LeftPad:Motion"
var r_pad_cap = "Touchpad:RightPad:Motion"
var mouse_cap = "Mouse:Motion"

if !profile_modifier.is_empty():
var mapped_capabilities := profile.to_json()
logger.debug("Mapped Capabilities (before):", mapped_capabilities)
match profile_modifier:
"deck":
logger.debug("Steam Deck Profile")
if c_pad_cap not in mapped_capabilities:
logger.debug("Map", c_pad_cap)
var c_pad_map := InputPlumberMapping.from_source_capability(c_pad_cap)
var r_pad_event := InputPlumberEvent.from_capability(r_pad_cap)
c_pad_map.target_events = [r_pad_event]
profile.mapping.append(c_pad_map)

"ds5", "ds5-edge":
logger.debug("Dualsense Profile")
if l_pad_cap not in mapped_capabilities:
logger.debug("Map", l_pad_cap)
var l_pad_map := InputPlumberMapping.from_source_capability(l_pad_cap)
var c_pad_event := InputPlumberEvent.from_capability(c_pad_cap)
l_pad_map.target_events = [c_pad_event]
profile.mapping.append(l_pad_map)
if r_pad_cap not in mapped_capabilities:
logger.debug("Map", r_pad_cap)
var r_pad_map := InputPlumberMapping.from_source_capability(r_pad_cap)
var c_pad_event := InputPlumberEvent.from_capability(c_pad_cap)
r_pad_map.target_events = [c_pad_event]
profile.mapping.append(r_pad_map)

_:
logger.debug("Target device needs no modifications:", profile_modifier)

mapped_capabilities = profile.to_json()
logger.debug("Mapped Capabilities (after):", mapped_capabilities)

path = path.rstrip(".json") + profile_modifier + ".json"
if profile.save(path) != OK:
logger.error("Failed to save", profile.name, "to", path)
return
device.load_profile_path(path)
2 changes: 1 addition & 1 deletion core/systems/testing/pre_run.gd
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extends GutHookScript

var PID: int = OS.get_process_id()
var gamescope := load("res://core/global/gamescope.tres") as Gamescope
var gamescope := load("res://core/systems/gamescope/gamescope.tres") as Gamescope
var window_id = gamescope.get_window_id(PID, gamescope.XWAYLAND.OGUI)


Expand Down
4 changes: 2 additions & 2 deletions core/ui/card_ui/gamepad/gamepad_settings.gd
Original file line number Diff line number Diff line change
Expand Up @@ -612,11 +612,11 @@ func _set_gamepad_profile(gamepad: CompositeDevice, profile_path: String = "") -
profile_path = settings_manager.get_library_value(library_item, "gamepad_profile", "")

logger.debug("Setting " + gamepad.name + " to profile: " + profile_path)
#gamepad.target_modify_profile(profile_path, profile_gamepad) #TODO: fixme
InputPlumber.load_target_modified_profile(gamepad, profile_path, profile_gamepad)

# Set the target gamepad if one was specified
if not profile_gamepad.is_empty():
var target_devices := [profile_gamepad, "keyboard", "mouse"]
var target_devices := PackedStringArray([profile_gamepad, "keyboard", "mouse"])
match profile_gamepad:
"xb360", "xbox-series", "xbox-elite", "gamepad":
target_devices.append("touchpad")
Expand Down
8 changes: 6 additions & 2 deletions core/ui/card_ui/navigation/in-game_notification.gd
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ func _ready() -> void:

# Continue showing any other queued messages
var on_finished := func():
gamescope.set_notification(overlay_window_id, 0)
var xwland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
if xwland:
xwland.set_notification(overlay_window_id, 0)
_on_notification_queued(null)
effect.slide_out_finished.connect(on_finished)

Expand All @@ -43,7 +45,9 @@ func _on_notification_queued(_notify: Notification) -> void:
var notify := notification_manager.next()
if not notify:
return
gamescope.set_notification(overlay_window_id, 1)
var xwayland := gamescope.get_xwayland(gamescope.XWAYLAND_TYPE_OGUI)
if xwayland:
xwayland.set_notification(overlay_window_id, 1)
show_toast(notify.text, notify.icon, notify.timeout)


Expand Down
8 changes: 5 additions & 3 deletions core/ui/card_ui/settings/disks_settings_menu.gd
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ var logger := Log.get_logger("DisksMenu", Log.LEVEL.INFO)
@onready var focus_group: FocusGroup = $%FocusGroup
@onready var no_drive_label: Label = $%NoDisksLabel


# Called when the node enters the scene tree for the first time.
func _ready():
if not udisks2.is_running():
return
#udisks2.unprotected_devices_updated.connect(_on_drives_updated)
#_on_drives_updated(udisks2.get_unprotected_devices())

udisks2.unprotected_devices_updated.connect(_on_drives_updated)
_on_drives_updated(udisks2.get_unprotected_devices())


func _on_drives_updated(devices: Array[BlockDevice]) -> void:
Expand Down Expand Up @@ -49,7 +51,7 @@ func _on_drives_updated(devices: Array[BlockDevice]) -> void:
continue

# Create Drive Card
var drive_card := drive_card_scene.instantiate()
var drive_card := drive_card_scene.instantiate() as DriveCard
container.add_child(drive_card)
drive_card.setup(drive)
drive_card.visible = true
Expand Down
2 changes: 1 addition & 1 deletion core/ui/card_ui_overlay_mode/card_ui_overlay_mode.gd
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extends Control

var platform := preload("res://core/global/platform.tres") as Platform
var gamescope := preload("res://core/global/gamescope.tres") as Gamescope
var gamescope := preload("res://core/systems/gamescope/gamescope.tres") as Gamescope
var launch_manager := preload("res://core/global/launch_manager.tres") as LaunchManager
var settings_manager := preload("res://core/global/settings_manager.tres") as SettingsManager
var input_plumber := preload("res://core/systems/input/input_plumber.tres") as InputPlumberInstance
Expand Down
1 change: 0 additions & 1 deletion core/ui/common/game/game_loading.gd
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ extends Control
var launch_manager := load("res://core/global/launch_manager.tres") as LaunchManager



# Called when the node enters the scene tree for the first time.
func _ready() -> void:
var on_app_launched := func(app: RunningApp):
Expand Down
2 changes: 1 addition & 1 deletion core/ui/common/game/game_loading.tscn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[gd_scene load_steps=3 format=3]
[gd_scene load_steps=3 format=3 uid="uid://b1kist0rarpcy"]

[ext_resource type="Script" path="res://core/ui/common/game/game_loading.gd" id="1_1ucmh"]
[ext_resource type="PackedScene" uid="uid://2tdbi1v6qb6h" path="res://core/ui/components/loading02.tscn" id="1_jduoa"]
Expand Down
2 changes: 1 addition & 1 deletion core/ui/common/osk/on_screen_keyboard.gd
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ signal closed

const key_scene := preload("res://core/ui/components/button.tscn")

var gamescope := load("res://core/global/gamescope.tres") as GamescopeInstance
var gamescope := load("res://core/systems/gamescope/gamescope.tres") as GamescopeInstance
## State machine to use to switch menu states in response to input events.
var popup_state_machine := (
preload("res://assets/state/state_machines/popup_state_machine.tres") as StateMachine
Expand Down
7 changes: 7 additions & 0 deletions core/ui/components/battery_container.gd
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ const icon_half = preload("res://assets/ui/icons/battery-half.svg")
const icon_low = preload("res://assets/ui/icons/battery-low.svg")
const icon_empty = preload("res://assets/ui/icons/battery-empty.svg")

const no_battery_names := ["battery-missing-symbolic"]

var power_manager := load("res://core/systems/power/power_manager.tres") as UPowerInstance
var display_device := power_manager.get_display_device()

Expand All @@ -22,6 +24,11 @@ func _ready():
visible = false
return

if display_device.icon_name in no_battery_names:
logger.debug("No battery detected. nothing to do.")
visible = false
return

_on_update_device(display_device)
display_device.updated.connect(_on_update_device.bind(display_device))

Expand Down
44 changes: 27 additions & 17 deletions core/ui/components/drive_card.gd
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const sd_icon = preload("res://assets/icons/interface-sd.svg")
const ssd_icon = preload("res://assets/icons/interface-ssd.svg")
const usb_icon = preload("res://assets/icons/interface-usb.svg")

var device: BlockDevice
var block_device: BlockDevice
var device_path: String
var highlight_tween: Tween

Expand Down Expand Up @@ -39,8 +39,8 @@ var log_level:= Log.LEVEL.INFO
## Performs _ready fucntionality with the given BlockDevice
func setup(device: BlockDevice) -> void:
# Setup UDisks2 information
self.device = device
self.device_path = "/dev" + self.device.dbus_path.trim_prefix(steam_disks.BLOCK_PREFIX)
self.block_device = device
self.device_path = "/dev" + self.block_device.dbus_path.trim_prefix(steam_disks.BLOCK_PREFIX)

logger = Log.get_logger("DriveCard|"+self.device_path, log_level)
logger.debug("Setup Drive Card")
Expand Down Expand Up @@ -86,7 +86,7 @@ func _srm_format_drive() -> void:
_clear_partitions()
_on_format_started()
var note := Notification.new("Format Complete: " + self.device_path)
if await steam_disks.format_drive(device) != OK:
if await steam_disks.format_drive(block_device) != OK:
note.text = "Failed to format " + self.device_path
_on_format_complete(note)

Expand Down Expand Up @@ -132,22 +132,19 @@ func _srm_init_drive(partition: PartitionDevice) -> void:
init_partition.emit(partition)


func _clear_partitions() -> void:
# Clear the current grid of items
var keep_nodes := [partitions_focus_group]
for child in partitions_container.get_children():
if child in keep_nodes:
continue
partitions_container.remove_child(child)
child.queue_free()


func _set_icon() -> void:
if not device or not device.drive:
logger.warn("Unable to detect drive to set icon for:", device)
if not block_device:
logger.warn("Unable to detect drive to set icon for something?")
drive_icon.texture = hdd_icon
return
match device.drive.interface_type:
var drive := block_device.get_drive() as DriveDevice
if not drive:
logger.warn("Unable to detect drive to set icon for:", block_device)
drive_icon.texture = hdd_icon
return

match drive.interface_type():
DriveDevice.INTERFACE_TYPE_HDD:
drive_icon.texture = hdd_icon
DriveDevice.INTERFACE_TYPE_NVME:
Expand All @@ -158,13 +155,26 @@ func _set_icon() -> void:
drive_icon.texture = ssd_icon
DriveDevice.INTERFACE_TYPE_USB:
drive_icon.texture = usb_icon
DriveDevice.INTERFACE_TYPE_UNKNOWN:
# TODO: Assign a unique texture for this
drive_icon.texture = hdd_icon


func _clear_partitions() -> void:
# Clear the current grid of items
var keep_nodes := [partitions_focus_group]
for child in partitions_container.get_children():
if child in keep_nodes:
continue
partitions_container.remove_child(child)
child.queue_free()


## Populates the partition grid with an item for every PartitionDevice on this BlockDevice
func _populate_partitions() -> void:
_clear_partitions()
var last_focus: FocusGroup
for partition in self.device.partitions:
for partition in self.block_device.get_partitions():

# Ignore loop devices
if partition.partition_name.contains("/dev/loop"):
Expand Down
Loading

0 comments on commit 59a8116

Please sign in to comment.