mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-12 21:38:38 +00:00
638 lines
21 KiB
C#
638 lines
21 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using Artemis.Core.DeviceProviders;
|
|
using Artemis.Core.Services;
|
|
using Artemis.Storage.Entities.Surface;
|
|
using RGB.NET.Core;
|
|
using SkiaSharp;
|
|
|
|
namespace Artemis.Core;
|
|
|
|
/// <summary>
|
|
/// Represents an RGB device usable by Artemis, provided by a <see cref="DeviceProviders.DeviceProvider" />
|
|
/// </summary>
|
|
public class ArtemisDevice : CorePropertyChanged
|
|
{
|
|
private readonly List<OriginalLed> _originalLeds;
|
|
private readonly Size _originalSize;
|
|
private SKPath? _path;
|
|
private SKRect _rectangle;
|
|
|
|
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider)
|
|
{
|
|
_originalLeds = new List<OriginalLed>(rgbDevice.Select(l => new OriginalLed(l)));
|
|
Rectangle ledRectangle = new(rgbDevice.Select(x => x.Boundary));
|
|
_originalSize = ledRectangle.Size + new Size(ledRectangle.Location.X, ledRectangle.Location.Y);
|
|
|
|
Identifier = rgbDevice.GetDeviceIdentifier();
|
|
DeviceEntity = new DeviceEntity();
|
|
RgbDevice = rgbDevice;
|
|
DeviceProvider = deviceProvider;
|
|
|
|
Rotation = 0;
|
|
Scale = 1;
|
|
ZIndex = 1;
|
|
RedScale = 1;
|
|
GreenScale = 1;
|
|
BlueScale = 1;
|
|
IsEnabled = true;
|
|
|
|
LedIds = new ReadOnlyDictionary<LedId, ArtemisLed>(new Dictionary<LedId, ArtemisLed>());
|
|
Leds = new ReadOnlyCollection<ArtemisLed>(new List<ArtemisLed>());
|
|
InputIdentifiers = new List<ArtemisDeviceInputIdentifier>();
|
|
InputMappings = new Dictionary<ArtemisLed, ArtemisLed>();
|
|
Categories = new HashSet<DeviceCategory>();
|
|
|
|
UpdateLeds();
|
|
ApplyKeyboardLayout();
|
|
ApplyToEntity();
|
|
ApplyDefaultCategories();
|
|
CalculateRenderProperties();
|
|
}
|
|
|
|
internal ArtemisDevice(IRGBDevice rgbDevice, DeviceProvider deviceProvider, DeviceEntity deviceEntity)
|
|
{
|
|
_originalLeds = new List<OriginalLed>(rgbDevice.Select(l => new OriginalLed(l)));
|
|
Rectangle ledRectangle = new(rgbDevice.Select(x => x.Boundary));
|
|
_originalSize = ledRectangle.Size + new Size(ledRectangle.Location.X, ledRectangle.Location.Y);
|
|
|
|
Identifier = rgbDevice.GetDeviceIdentifier();
|
|
DeviceEntity = deviceEntity;
|
|
RgbDevice = rgbDevice;
|
|
DeviceProvider = deviceProvider;
|
|
|
|
LedIds = new ReadOnlyDictionary<LedId, ArtemisLed>(new Dictionary<LedId, ArtemisLed>());
|
|
Leds = new ReadOnlyCollection<ArtemisLed>(new List<ArtemisLed>());
|
|
InputIdentifiers = new List<ArtemisDeviceInputIdentifier>();
|
|
InputMappings = new Dictionary<ArtemisLed, ArtemisLed>();
|
|
Categories = new HashSet<DeviceCategory>();
|
|
|
|
foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers)
|
|
InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier));
|
|
|
|
UpdateLeds();
|
|
ApplyKeyboardLayout();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the (hopefully unique and persistent) ID of this device
|
|
/// </summary>
|
|
public string Identifier { get; }
|
|
|
|
/// <summary>
|
|
/// Gets the rectangle covering the device
|
|
/// </summary>
|
|
public SKRect Rectangle
|
|
{
|
|
get => _rectangle;
|
|
private set => SetAndNotify(ref _rectangle, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the path surrounding the device
|
|
/// </summary>
|
|
public SKPath? Path
|
|
{
|
|
get => _path;
|
|
private set => SetAndNotify(ref _path, value);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the RGB.NET device backing this Artemis device
|
|
/// </summary>
|
|
public IRGBDevice RgbDevice { get; }
|
|
|
|
/// <summary>
|
|
/// Gets the device type of the ArtemisDevice
|
|
/// </summary>
|
|
public RGBDeviceType DeviceType => RgbDevice.DeviceInfo.DeviceType;
|
|
|
|
/// <summary>
|
|
/// Gets the device provider that provided this device
|
|
/// </summary>
|
|
public DeviceProvider DeviceProvider { get; }
|
|
|
|
/// <summary>
|
|
/// Gets a read only collection containing the LEDs of this device
|
|
/// </summary>
|
|
public ReadOnlyCollection<ArtemisLed> Leds { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Gets a dictionary containing all the LEDs of this device with their corresponding RGB.NET <see cref="LedId" /> as
|
|
/// key
|
|
/// </summary>
|
|
public ReadOnlyDictionary<LedId, ArtemisLed> LedIds { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Gets a list of input identifiers associated with this device
|
|
/// </summary>
|
|
public List<ArtemisDeviceInputIdentifier> InputIdentifiers { get; }
|
|
|
|
/// <summary>
|
|
/// Gets a list of input mappings configured on the device
|
|
/// </summary>
|
|
public Dictionary<ArtemisLed, ArtemisLed> InputMappings { get; }
|
|
|
|
/// <summary>
|
|
/// Gets a list containing the categories of this device
|
|
/// </summary>
|
|
public HashSet<DeviceCategory> Categories { get; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the X-position of the device
|
|
/// </summary>
|
|
public float X
|
|
{
|
|
get => DeviceEntity.X;
|
|
set
|
|
{
|
|
DeviceEntity.X = value;
|
|
OnPropertyChanged(nameof(X));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the Y-position of the device
|
|
/// </summary>
|
|
public float Y
|
|
{
|
|
get => DeviceEntity.Y;
|
|
set
|
|
{
|
|
DeviceEntity.Y = value;
|
|
OnPropertyChanged(nameof(Y));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the rotation of the device
|
|
/// </summary>
|
|
public float Rotation
|
|
{
|
|
get => DeviceEntity.Rotation;
|
|
set
|
|
{
|
|
DeviceEntity.Rotation = value;
|
|
OnPropertyChanged(nameof(Rotation));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the scale of the device
|
|
/// </summary>
|
|
public float Scale
|
|
{
|
|
get => DeviceEntity.Scale;
|
|
set
|
|
{
|
|
DeviceEntity.Scale = value;
|
|
OnPropertyChanged(nameof(Scale));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the Z-index of the device
|
|
/// </summary>
|
|
public int ZIndex
|
|
{
|
|
get => DeviceEntity.ZIndex;
|
|
set
|
|
{
|
|
DeviceEntity.ZIndex = value;
|
|
OnPropertyChanged(nameof(ZIndex));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the scale of the red color component used for calibration
|
|
/// </summary>
|
|
public float RedScale
|
|
{
|
|
get => DeviceEntity.RedScale;
|
|
set
|
|
{
|
|
DeviceEntity.RedScale = value;
|
|
OnPropertyChanged(nameof(RedScale));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the scale of the green color component used for calibration
|
|
/// </summary>
|
|
public float GreenScale
|
|
{
|
|
get => DeviceEntity.GreenScale;
|
|
set
|
|
{
|
|
DeviceEntity.GreenScale = value;
|
|
OnPropertyChanged(nameof(GreenScale));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the scale of the blue color component used for calibration
|
|
/// </summary>
|
|
public float BlueScale
|
|
{
|
|
get => DeviceEntity.BlueScale;
|
|
set
|
|
{
|
|
DeviceEntity.BlueScale = value;
|
|
OnPropertyChanged(nameof(BlueScale));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a boolean indicating whether this devices is enabled or not
|
|
/// <para>Note: To enable/disable a device use the methods provided by <see cref="IRgbService" /></para>
|
|
/// </summary>
|
|
public bool IsEnabled
|
|
{
|
|
get => DeviceEntity.IsEnabled;
|
|
internal set
|
|
{
|
|
DeviceEntity.IsEnabled = value;
|
|
OnPropertyChanged(nameof(IsEnabled));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the physical layout of the device e.g. ISO or ANSI.
|
|
/// <para>Only applicable to keyboards</para>
|
|
/// </summary>
|
|
public KeyboardLayoutType PhysicalLayout
|
|
{
|
|
get => (KeyboardLayoutType) DeviceEntity.PhysicalLayout;
|
|
set
|
|
{
|
|
DeviceEntity.PhysicalLayout = (int) value;
|
|
OnPropertyChanged(nameof(PhysicalLayout));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets a boolean indicating whether falling back to default layouts is enabled or not
|
|
/// </summary>
|
|
public bool DisableDefaultLayout
|
|
{
|
|
get => DeviceEntity.DisableDefaultLayout;
|
|
set
|
|
{
|
|
DeviceEntity.DisableDefaultLayout = value;
|
|
OnPropertyChanged(nameof(DisableDefaultLayout));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the logical layout of the device e.g. DE, UK or US.
|
|
/// <para>Only applicable to keyboards</para>
|
|
/// </summary>
|
|
public string? LogicalLayout
|
|
{
|
|
get => DeviceEntity.LogicalLayout;
|
|
set
|
|
{
|
|
DeviceEntity.LogicalLayout = value;
|
|
OnPropertyChanged(nameof(LogicalLayout));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the path of the custom layout to load when calling <see cref="IRgbService.ApplyBestDeviceLayout" />
|
|
/// for this device
|
|
/// </summary>
|
|
public string? CustomLayoutPath
|
|
{
|
|
get => DeviceEntity.CustomLayoutPath;
|
|
set
|
|
{
|
|
DeviceEntity.CustomLayoutPath = value;
|
|
OnPropertyChanged(nameof(CustomLayoutPath));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the layout of the device expanded with Artemis-specific data
|
|
/// </summary>
|
|
public ArtemisLayout? Layout { get; internal set; }
|
|
|
|
internal DeviceEntity DeviceEntity { get; }
|
|
|
|
/// <inheritdoc />
|
|
public override string ToString()
|
|
{
|
|
return $"[{RgbDevice.DeviceInfo.DeviceType}] {RgbDevice.DeviceInfo.DeviceName} - {X}.{Y}.{ZIndex}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Attempts to retrieve the <see cref="ArtemisLed" /> that corresponds the provided RGB.NET <see cref="Led" />
|
|
/// </summary>
|
|
/// <param name="led">The RGB.NET <see cref="Led" /> to find the corresponding <see cref="ArtemisLed" /> for </param>
|
|
/// <param name="applyInputMapping">
|
|
/// If <see langword="true" />, LEDs mapped to different LEDs <see cref="InputMappings" />
|
|
/// are taken into consideration
|
|
/// </param>
|
|
/// <returns>If found, the corresponding <see cref="ArtemisLed" />; otherwise <see langword="null" />.</returns>
|
|
public ArtemisLed? GetLed(Led led, bool applyInputMapping)
|
|
{
|
|
return GetLed(led.Id, applyInputMapping);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Attempts to retrieve the <see cref="ArtemisLed" /> that corresponds the provided RGB.NET <see cref="LedId" />
|
|
/// </summary>
|
|
/// <param name="ledId">The RGB.NET <see cref="LedId" /> to find the corresponding <see cref="ArtemisLed" /> for </param>
|
|
/// <param name="applyInputMapping">
|
|
/// If <see langword="true" />, LEDs mapped to different LEDs <see cref="InputMappings" />
|
|
/// are taken into consideration
|
|
/// </param>
|
|
/// <returns>If found, the corresponding <see cref="ArtemisLed" />; otherwise <see langword="null" />.</returns>
|
|
public ArtemisLed? GetLed(LedId ledId, bool applyInputMapping)
|
|
{
|
|
LedIds.TryGetValue(ledId, out ArtemisLed? artemisLed);
|
|
if (artemisLed == null)
|
|
return null;
|
|
|
|
if (applyInputMapping && InputMappings.TryGetValue(artemisLed, out ArtemisLed? mappedLed))
|
|
return mappedLed;
|
|
return artemisLed;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the most preferred device layout for this device.
|
|
/// </summary>
|
|
/// <returns>The most preferred device layout for this device.</returns>
|
|
public ArtemisLayout? GetBestDeviceLayout()
|
|
{
|
|
ArtemisLayout? layout;
|
|
|
|
// Configured layout path takes precedence over all other options
|
|
if (CustomLayoutPath != null)
|
|
{
|
|
layout = new ArtemisLayout(CustomLayoutPath, LayoutSource.Configured);
|
|
if (layout.IsValid)
|
|
return layout;
|
|
}
|
|
|
|
// Look for a layout provided by the user
|
|
layout = DeviceProvider.LoadUserLayout(this);
|
|
if (layout.IsValid)
|
|
return layout;
|
|
|
|
if (DisableDefaultLayout)
|
|
return null;
|
|
|
|
// Look for a layout provided by the plugin
|
|
layout = DeviceProvider.LoadLayout(this);
|
|
if (layout.IsValid)
|
|
return layout;
|
|
|
|
// Finally fall back to a default layout
|
|
layout = ArtemisLayout.GetDefaultLayout(this);
|
|
return layout;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when the underlying RGB.NET device was updated
|
|
/// </summary>
|
|
public event EventHandler? DeviceUpdated;
|
|
|
|
/// <summary>
|
|
/// Applies the default categories for this device to the <see cref="Categories" /> list
|
|
/// </summary>
|
|
public void ApplyDefaultCategories()
|
|
{
|
|
switch (RgbDevice.DeviceInfo.DeviceType)
|
|
{
|
|
case RGBDeviceType.Keyboard:
|
|
case RGBDeviceType.Mouse:
|
|
case RGBDeviceType.Headset:
|
|
case RGBDeviceType.Mousepad:
|
|
case RGBDeviceType.HeadsetStand:
|
|
case RGBDeviceType.Keypad:
|
|
if (!Categories.Contains(DeviceCategory.Peripherals))
|
|
Categories.Add(DeviceCategory.Peripherals);
|
|
break;
|
|
case RGBDeviceType.Mainboard:
|
|
case RGBDeviceType.GraphicsCard:
|
|
case RGBDeviceType.DRAM:
|
|
case RGBDeviceType.Fan:
|
|
case RGBDeviceType.LedStripe:
|
|
case RGBDeviceType.Cooler:
|
|
if (!Categories.Contains(DeviceCategory.Case))
|
|
Categories.Add(DeviceCategory.Case);
|
|
break;
|
|
case RGBDeviceType.Speaker:
|
|
if (!Categories.Contains(DeviceCategory.Desk))
|
|
Categories.Add(DeviceCategory.Desk);
|
|
break;
|
|
case RGBDeviceType.Monitor:
|
|
if (!Categories.Contains(DeviceCategory.Monitor))
|
|
Categories.Add(DeviceCategory.Monitor);
|
|
break;
|
|
case RGBDeviceType.LedMatrix:
|
|
if (!Categories.Contains(DeviceCategory.Room))
|
|
Categories.Add(DeviceCategory.Room);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invokes the <see cref="DeviceUpdated" /> event
|
|
/// </summary>
|
|
protected virtual void OnDeviceUpdated()
|
|
{
|
|
DeviceUpdated?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Applies the provided layout to the device
|
|
/// </summary>
|
|
/// <param name="layout">The layout to apply</param>
|
|
/// <param name="createMissingLeds">
|
|
/// A boolean indicating whether to add missing LEDs defined in the layout but missing on
|
|
/// the device
|
|
/// </param>
|
|
/// <param name="removeExcessiveLeds">
|
|
/// A boolean indicating whether to remove excess LEDs present in the device but missing
|
|
/// in the layout
|
|
/// </param>
|
|
internal void ApplyLayout(ArtemisLayout? layout, bool createMissingLeds, bool removeExcessiveLeds)
|
|
{
|
|
if (layout == null)
|
|
{
|
|
ClearLayout();
|
|
UpdateLeds();
|
|
|
|
CalculateRenderProperties();
|
|
OnDeviceUpdated();
|
|
return;
|
|
}
|
|
|
|
if (createMissingLeds && !DeviceProvider.CreateMissingLedsSupported)
|
|
throw new ArtemisCoreException($"Cannot apply layout with {nameof(createMissingLeds)} " +
|
|
"set to true because the device provider does not support it");
|
|
if (removeExcessiveLeds && !DeviceProvider.RemoveExcessiveLedsSupported)
|
|
throw new ArtemisCoreException($"Cannot apply layout with {nameof(removeExcessiveLeds)} " +
|
|
"set to true because the device provider does not support it");
|
|
|
|
ClearLayout();
|
|
if (layout.IsValid)
|
|
layout.ApplyTo(RgbDevice, createMissingLeds, removeExcessiveLeds);
|
|
UpdateLeds();
|
|
|
|
Layout = layout;
|
|
Layout.ApplyDevice(this);
|
|
|
|
CalculateRenderProperties();
|
|
OnDeviceUpdated();
|
|
}
|
|
|
|
private void ClearLayout()
|
|
{
|
|
if (Layout == null)
|
|
return;
|
|
|
|
RgbDevice.DeviceInfo.LayoutMetadata = null;
|
|
RgbDevice.Size = _originalSize;
|
|
Layout = null;
|
|
|
|
while (RgbDevice.Any())
|
|
RgbDevice.RemoveLed(RgbDevice.First().Id);
|
|
foreach (OriginalLed originalLed in _originalLeds)
|
|
RgbDevice.AddLed(originalLed.Id, originalLed.Location, originalLed.Size, originalLed.CustomData);
|
|
}
|
|
|
|
internal void ApplyToEntity()
|
|
{
|
|
// Other properties are computed
|
|
DeviceEntity.Id = Identifier;
|
|
DeviceEntity.DeviceProvider = DeviceProvider.Plugin.Guid.ToString();
|
|
|
|
DeviceEntity.InputIdentifiers.Clear();
|
|
foreach (ArtemisDeviceInputIdentifier identifier in InputIdentifiers)
|
|
{
|
|
DeviceEntity.InputIdentifiers.Add(new DeviceInputIdentifierEntity
|
|
{
|
|
InputProvider = identifier.InputProvider,
|
|
Identifier = identifier.Identifier
|
|
});
|
|
}
|
|
|
|
DeviceEntity.InputMappings.Clear();
|
|
foreach ((ArtemisLed? original, ArtemisLed? mapped) in InputMappings)
|
|
DeviceEntity.InputMappings.Add(new InputMappingEntity {OriginalLedId = (int) original.RgbLed.Id, MappedLedId = (int) mapped.RgbLed.Id});
|
|
|
|
DeviceEntity.Categories.Clear();
|
|
foreach (DeviceCategory deviceCategory in Categories)
|
|
DeviceEntity.Categories.Add((int) deviceCategory);
|
|
}
|
|
|
|
internal void ApplyToRgbDevice()
|
|
{
|
|
RgbDevice.Rotation = DeviceEntity.Rotation;
|
|
RgbDevice.Scale = DeviceEntity.Scale;
|
|
|
|
// Workaround for device rotation not applying
|
|
if (DeviceEntity.X == 0 && DeviceEntity.Y == 0)
|
|
RgbDevice.Location = new Point(1, 1);
|
|
RgbDevice.Location = new Point(DeviceEntity.X, DeviceEntity.Y);
|
|
|
|
InputIdentifiers.Clear();
|
|
foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers)
|
|
InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier));
|
|
|
|
if (!RgbDevice.ColorCorrections.Any())
|
|
RgbDevice.ColorCorrections.Add(new ScaleColorCorrection(this));
|
|
|
|
Categories.Clear();
|
|
foreach (int deviceEntityCategory in DeviceEntity.Categories)
|
|
Categories.Add((DeviceCategory) deviceEntityCategory);
|
|
if (!Categories.Any())
|
|
ApplyDefaultCategories();
|
|
|
|
CalculateRenderProperties();
|
|
OnDeviceUpdated();
|
|
}
|
|
|
|
internal void CalculateRenderProperties()
|
|
{
|
|
Rectangle = RgbDevice.Boundary.ToSKRect();
|
|
if (!Leds.Any())
|
|
return;
|
|
|
|
foreach (ArtemisLed led in Leds)
|
|
led.CalculateRectangles();
|
|
|
|
SKPath path = new() {FillType = SKPathFillType.Winding};
|
|
foreach (ArtemisLed artemisLed in Leds)
|
|
path.AddRect(artemisLed.AbsoluteRectangle);
|
|
|
|
Path = path;
|
|
}
|
|
|
|
private void UpdateLeds()
|
|
{
|
|
Leds = RgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
|
|
LedIds = new ReadOnlyDictionary<LedId, ArtemisLed>(Leds.ToDictionary(l => l.RgbLed.Id, l => l));
|
|
|
|
InputMappings.Clear();
|
|
foreach (InputMappingEntity deviceEntityInputMapping in DeviceEntity.InputMappings)
|
|
{
|
|
ArtemisLed? original = Leds.FirstOrDefault(l => l.RgbLed.Id == (LedId) deviceEntityInputMapping.OriginalLedId);
|
|
ArtemisLed? mapped = Leds.FirstOrDefault(l => l.RgbLed.Id == (LedId) deviceEntityInputMapping.MappedLedId);
|
|
if (original != null && mapped != null)
|
|
InputMappings.Add(original, mapped);
|
|
}
|
|
}
|
|
|
|
private void ApplyKeyboardLayout()
|
|
{
|
|
if (RgbDevice.DeviceInfo.DeviceType != RGBDeviceType.Keyboard)
|
|
return;
|
|
|
|
IKeyboard? keyboard = RgbDevice as IKeyboard;
|
|
// If supported, detect the device layout so that we can load the correct one
|
|
if (DeviceProvider.CanDetectPhysicalLayout && keyboard != null)
|
|
PhysicalLayout = (KeyboardLayoutType) keyboard.DeviceInfo.Layout;
|
|
else
|
|
PhysicalLayout = (KeyboardLayoutType) DeviceEntity.PhysicalLayout;
|
|
if (DeviceProvider.CanDetectLogicalLayout && keyboard != null)
|
|
LogicalLayout = DeviceProvider.GetLogicalLayout(keyboard);
|
|
else
|
|
LogicalLayout = DeviceEntity.LogicalLayout;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a device category
|
|
/// </summary>
|
|
public enum DeviceCategory
|
|
{
|
|
/// <summary>
|
|
/// A device used to light up (part of) the desk
|
|
/// </summary>
|
|
Desk,
|
|
|
|
/// <summary>
|
|
/// A device attached or embedded into the monitor
|
|
/// </summary>
|
|
Monitor,
|
|
|
|
/// <summary>
|
|
/// A device placed or embedded into the case
|
|
/// </summary>
|
|
Case,
|
|
|
|
/// <summary>
|
|
/// A device used to light up (part of) the room
|
|
/// </summary>
|
|
Room,
|
|
|
|
/// <summary>
|
|
/// A peripheral
|
|
/// </summary>
|
|
Peripherals
|
|
} |