mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-01-01 18:23:32 +00:00
Finished CM support
Reimplemented task bar icon
This commit is contained in:
parent
6f7e24611a
commit
c172ec4c6a
@ -318,7 +318,7 @@
|
|||||||
<Compile Include="DAL\ProfileProvider.cs" />
|
<Compile Include="DAL\ProfileProvider.cs" />
|
||||||
<Compile Include="DAL\SettingsProvider.cs" />
|
<Compile Include="DAL\SettingsProvider.cs" />
|
||||||
<Compile Include="DeviceProviders\CoolerMaster\MasterkeysProL.cs" />
|
<Compile Include="DeviceProviders\CoolerMaster\MasterkeysProL.cs" />
|
||||||
<Compile Include="DeviceProviders\CoolerMaster\Utilities\CMSDK.cs" />
|
<Compile Include="DeviceProviders\CoolerMaster\Utilities\CmSdk.cs" />
|
||||||
<Compile Include="DeviceProviders\Corsair\CorsairMice.cs" />
|
<Compile Include="DeviceProviders\Corsair\CorsairMice.cs" />
|
||||||
<Compile Include="DeviceProviders\Corsair\CorsairHeadsets.cs" />
|
<Compile Include="DeviceProviders\Corsair\CorsairHeadsets.cs" />
|
||||||
<Compile Include="DeviceProviders\Corsair\CorsairMousemats.cs" />
|
<Compile Include="DeviceProviders\Corsair\CorsairMousemats.cs" />
|
||||||
@ -611,7 +611,6 @@
|
|||||||
<Compile Include="Modules\Overlays\VolumeDisplay\VolumeDisplayViewModel.cs" />
|
<Compile Include="Modules\Overlays\VolumeDisplay\VolumeDisplayViewModel.cs" />
|
||||||
<Compile Include="ViewModels\Profiles\ProfileEditorViewModel.cs" />
|
<Compile Include="ViewModels\Profiles\ProfileEditorViewModel.cs" />
|
||||||
<Compile Include="ViewModels\ShellViewModel.cs" />
|
<Compile Include="ViewModels\ShellViewModel.cs" />
|
||||||
<Compile Include="ViewModels\SystemTrayViewModel.cs" />
|
|
||||||
<Compile Include="ViewModels\WelcomeViewModel.cs" />
|
<Compile Include="ViewModels\WelcomeViewModel.cs" />
|
||||||
<Compile Include="Views\DebugView.xaml.cs">
|
<Compile Include="Views\DebugView.xaml.cs">
|
||||||
<DependentUpon>DebugView.xaml</DependentUpon>
|
<DependentUpon>DebugView.xaml</DependentUpon>
|
||||||
@ -687,6 +686,7 @@
|
|||||||
<Compile Include="Properties\AssemblyInfo.cs">
|
<Compile Include="Properties\AssemblyInfo.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<None Include="Resources\Keyboards\masterkeys-pro-l.png" />
|
||||||
<Resource Include="Resources\Kottke Silkscreen License.txt" />
|
<Resource Include="Resources\Kottke Silkscreen License.txt" />
|
||||||
<None Include="Resources\lua-placeholder.lua" />
|
<None Include="Resources\lua-placeholder.lua" />
|
||||||
<None Include="NLog.xsd">
|
<None Include="NLog.xsd">
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Threading;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Artemis.DeviceProviders.CoolerMaster.Utilities;
|
using Artemis.DeviceProviders.CoolerMaster.Utilities;
|
||||||
|
using Artemis.DeviceProviders.Logitech.Utilities;
|
||||||
using Artemis.Properties;
|
using Artemis.Properties;
|
||||||
using Artemis.Utilities;
|
using Artemis.Utilities;
|
||||||
|
|
||||||
@ -11,6 +12,8 @@ namespace Artemis.DeviceProviders.CoolerMaster
|
|||||||
{
|
{
|
||||||
public class MasterkeysProL : KeyboardProvider
|
public class MasterkeysProL : KeyboardProvider
|
||||||
{
|
{
|
||||||
|
private bool _hasControl;
|
||||||
|
|
||||||
public MasterkeysProL()
|
public MasterkeysProL()
|
||||||
{
|
{
|
||||||
Name = "CM Masterkeys Pro L";
|
Name = "CM Masterkeys Pro L";
|
||||||
@ -22,76 +25,62 @@ namespace Artemis.DeviceProviders.CoolerMaster
|
|||||||
|
|
||||||
Height = 6;
|
Height = 6;
|
||||||
Width = 22;
|
Width = 22;
|
||||||
// TODO
|
|
||||||
PreviewSettings = new PreviewSettings(665, 175, new Thickness(0, -15, 0, 0), Resources.blackwidow);
|
PreviewSettings = new PreviewSettings(670, 189, new Thickness(-2, -5, 0, 0), Resources.masterkeys_pro_l);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Disable()
|
public override void Disable()
|
||||||
|
{
|
||||||
|
if (_hasControl)
|
||||||
{
|
{
|
||||||
CmSdk.EnableLedControl(false);
|
CmSdk.EnableLedControl(false);
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
_hasControl = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CanEnable()
|
public override bool CanEnable()
|
||||||
{
|
{
|
||||||
return true;
|
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MKeys_L);
|
||||||
|
|
||||||
|
// Doesn't seem reliable but better than nothing I suppose
|
||||||
|
return CmSdk.IsDevicePlug();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Enable()
|
public override void Enable()
|
||||||
{
|
{
|
||||||
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MKeys_L);
|
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MKeys_L);
|
||||||
|
|
||||||
|
_hasControl = true;
|
||||||
CmSdk.EnableLedControl(true);
|
CmSdk.EnableLedControl(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawBitmap(Bitmap bitmap)
|
public override void DrawBitmap(Bitmap bitmap)
|
||||||
{
|
{
|
||||||
|
// Resize the bitmap
|
||||||
using (var b = ImageUtilities.ResizeImage(bitmap, Width, Height))
|
using (var b = ImageUtilities.ResizeImage(bitmap, Width, Height))
|
||||||
{
|
{
|
||||||
|
// Create an empty matrix
|
||||||
var matrix = new COLOR_MATRIX {KeyColor = new KEY_COLOR[Height, Width]};
|
var matrix = new COLOR_MATRIX {KeyColor = new KEY_COLOR[Height, Width]};
|
||||||
|
|
||||||
|
// Map the bytes to the matix
|
||||||
for (var x = 0; x < Width; x++)
|
for (var x = 0; x < Width; x++)
|
||||||
{
|
{
|
||||||
for (var y = 0; y < Height; y++)
|
for (var y = 0; y < Height; y++)
|
||||||
{
|
{
|
||||||
var color = b.GetPixel(x, y);
|
var c = b.GetPixel(x, y);
|
||||||
matrix.KeyColor[y, x] = new KEY_COLOR(color.R, color.G, color.B);
|
matrix.KeyColor[y, x] = new KEY_COLOR(c.R, c.G, c.B);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send the matrix to the keyboard
|
||||||
CmSdk.SetAllLedColor(matrix);
|
CmSdk.SetAllLedColor(matrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override KeyMatch? GetKeyPosition(Keys keyCode)
|
public override KeyMatch? GetKeyPosition(Keys keyCode)
|
||||||
{
|
{
|
||||||
return null;
|
return KeyMap.QwertyLayout.FirstOrDefault(k => k.KeyCode == keyCode);
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[,,] BitmapToBytes(Bitmap bitmap)
|
|
||||||
{
|
|
||||||
BitmapData bitmapData =
|
|
||||||
bitmap.LockBits(new Rectangle(new System.Drawing.Point(), bitmap.Size), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
|
|
||||||
byte[] bitmapBytes;
|
|
||||||
var stride = bitmapData.Stride;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int byteCount = bitmapData.Stride * bitmap.Height;
|
|
||||||
bitmapBytes = new byte[byteCount];
|
|
||||||
Marshal.Copy(bitmapData.Scan0, bitmapBytes, 0, byteCount);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
bitmap.UnlockBits(bitmapData);
|
|
||||||
}
|
|
||||||
byte[,,] result = new byte[3, bitmap.Width, bitmap.Height];
|
|
||||||
for (int k = 0; k < 3; k++)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < bitmap.Width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < bitmap.Height; j++)
|
|
||||||
{
|
|
||||||
result[k, i, j] = bitmapBytes[j * stride + i * 3 + k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace Artemis.DeviceProviders.CoolerMaster.Utilities
|
namespace Artemis.DeviceProviders.CoolerMaster.Utilities
|
||||||
{
|
{
|
||||||
|
|
||||||
public struct KEY_COLOR
|
public struct KEY_COLOR
|
||||||
{
|
{
|
||||||
public byte r;
|
public byte r;
|
||||||
@ -17,12 +16,9 @@ namespace Artemis.DeviceProviders.CoolerMaster.Utilities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up/save the whole LED color structure
|
|
||||||
|
|
||||||
public struct COLOR_MATRIX
|
public struct COLOR_MATRIX
|
||||||
{
|
{
|
||||||
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 132)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 132)] public KEY_COLOR[,] KeyColor;
|
||||||
public KEY_COLOR[,] KeyColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Enumeration of device list
|
//Enumeration of device list
|
||||||
@ -45,15 +41,52 @@ namespace Artemis.DeviceProviders.CoolerMaster.Utilities
|
|||||||
|
|
||||||
public static class CmSdk
|
public static class CmSdk
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the control device which all following actions are targetted to
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="devIndex"></param>
|
||||||
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern void SetControlDevice(DEVICE_INDEX devIndex);
|
public static extern void SetControlDevice(DEVICE_INDEX devIndex);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Obtain current device layout
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern LAYOUT_KEYBOARD GetDeviceLayout();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Verify if the currently conrolled device is plugged in
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
public static extern bool IsDevicePlug();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables led control on the currently controlled device
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bEnable"></param>
|
||||||
|
/// <returns></returns>
|
||||||
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern bool EnableLedControl(bool bEnable);
|
public static extern bool EnableLedControl(bool bEnable);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the LED of the currently controlled device
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="iRow"></param>
|
||||||
|
/// <param name="iColumn"></param>
|
||||||
|
/// <param name="r"></param>
|
||||||
|
/// <param name="g"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern bool SetLedColor(int iRow, int iColumn, byte r, byte g, byte b);
|
public static extern bool SetLedColor(int iRow, int iColumn, byte r, byte g, byte b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets all LEDS using the given color matrix
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="colorMatrix"></param>
|
||||||
|
/// <returns></returns>
|
||||||
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
|
||||||
public static extern bool SetAllLedColor(COLOR_MATRIX colorMatrix);
|
public static extern bool SetAllLedColor(COLOR_MATRIX colorMatrix);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using Artemis.DeviceProviders.Logitech.Utilities;
|
using Artemis.DeviceProviders.Logitech.Utilities;
|
||||||
|
using Artemis.Utilities;
|
||||||
using Artemis.Utilities.DataReaders;
|
using Artemis.Utilities.DataReaders;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
|||||||
@ -202,10 +202,16 @@ namespace Artemis.DeviceProviders.Logitech.Utilities
|
|||||||
{
|
{
|
||||||
graphics.CompositingMode = CompositingMode.SourceCopy;
|
graphics.CompositingMode = CompositingMode.SourceCopy;
|
||||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||||
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
|
|
||||||
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||||
|
|
||||||
|
// TODO: Make configurable
|
||||||
|
// Prevents light bleed
|
||||||
|
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||||
|
// Soft/semi-transparent keys
|
||||||
|
//graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
|
|
||||||
using (var wrapMode = new ImageAttributes())
|
using (var wrapMode = new ImageAttributes())
|
||||||
{
|
{
|
||||||
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
|
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
|
||||||
|
|||||||
@ -10,15 +10,16 @@ namespace Artemis.DeviceProviders.Razer.Utilities
|
|||||||
public static Custom BitmapColorArray(Bitmap b, int height, int width)
|
public static Custom BitmapColorArray(Bitmap b, int height, int width)
|
||||||
{
|
{
|
||||||
var keyboardGrid = Custom.Create();
|
var keyboardGrid = Custom.Create();
|
||||||
if (b.Width > width || b.Height > height)
|
// Resize the bitmap
|
||||||
b = ImageUtilities.ResizeImage(b, width, height);
|
using (b = ImageUtilities.ResizeImage(b, width, height))
|
||||||
|
|
||||||
for (var y = 0; y < b.Height; y++)
|
|
||||||
{
|
{
|
||||||
|
// Map the bytes to the grid
|
||||||
for (var x = 0; x < b.Width; x++)
|
for (var x = 0; x < b.Width; x++)
|
||||||
{
|
{
|
||||||
var pixel = b.GetPixel(x, y);
|
for (var y = 0; y < b.Height; y++)
|
||||||
keyboardGrid[y, x] = new Color(pixel.R, pixel.G, pixel.B);
|
{
|
||||||
|
var c = b.GetPixel(x, y);
|
||||||
|
keyboardGrid[y, x] = new Color(c.R, c.G, c.B);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,3 +27,4 @@ namespace Artemis.DeviceProviders.Razer.Utilities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@ -15,7 +15,6 @@ namespace Artemis.InjectionModules
|
|||||||
{
|
{
|
||||||
// ViewModels
|
// ViewModels
|
||||||
Bind<ShellViewModel>().ToSelf().InSingletonScope();
|
Bind<ShellViewModel>().ToSelf().InSingletonScope();
|
||||||
Bind<SystemTrayViewModel>().ToSelf().InSingletonScope();
|
|
||||||
Bind<ProfileViewModel>().ToSelf();
|
Bind<ProfileViewModel>().ToSelf();
|
||||||
Bind<ProfileEditorViewModel>().ToSelf();
|
Bind<ProfileEditorViewModel>().ToSelf();
|
||||||
Bind<DebugViewModel>().ToSelf().InSingletonScope();
|
Bind<DebugViewModel>().ToSelf().InSingletonScope();
|
||||||
|
|||||||
@ -73,7 +73,7 @@ namespace Artemis.Managers
|
|||||||
public async void EnableKeyboard(KeyboardProvider keyboardProvider)
|
public async void EnableKeyboard(KeyboardProvider keyboardProvider)
|
||||||
{
|
{
|
||||||
if (keyboardProvider == null)
|
if (keyboardProvider == null)
|
||||||
throw new ArgumentNullException(nameof(keyboardProvider));
|
return;
|
||||||
|
|
||||||
if (ChangingKeyboard || (ActiveKeyboard?.Name == keyboardProvider.Name))
|
if (ChangingKeyboard || (ActiveKeyboard?.Name == keyboardProvider.Name))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -177,6 +177,9 @@ namespace Artemis.Managers
|
|||||||
{
|
{
|
||||||
public RenderFrame(KeyboardProvider keyboard)
|
public RenderFrame(KeyboardProvider keyboard)
|
||||||
{
|
{
|
||||||
|
if (keyboard == null)
|
||||||
|
return;
|
||||||
|
|
||||||
KeyboardBitmap = keyboard.KeyboardBitmap(4);
|
KeyboardBitmap = keyboard.KeyboardBitmap(4);
|
||||||
KeyboardBitmap.SetResolution(96, 96);
|
KeyboardBitmap.SetResolution(96, 96);
|
||||||
|
|
||||||
@ -222,10 +225,10 @@ namespace Artemis.Managers
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
KeyboardBitmap.Dispose();
|
KeyboardBitmap?.Dispose();
|
||||||
MouseBitmap.Dispose();
|
MouseBitmap?.Dispose();
|
||||||
HeadsetBitmap.Dispose();
|
HeadsetBitmap?.Dispose();
|
||||||
GenericBitmap.Dispose();
|
GenericBitmap?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
10
Artemis/Artemis/Properties/Resources.Designer.cs
generated
10
Artemis/Artemis/Properties/Resources.Designer.cs
generated
@ -328,6 +328,16 @@ namespace Artemis.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||||
|
/// </summary>
|
||||||
|
internal static System.Drawing.Bitmap masterkeys_pro_l {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("masterkeys_pro_l", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -214,4 +214,7 @@
|
|||||||
<data name="ambilight" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="ambilight" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\ambilight.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
<value>..\Resources\ambilight.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="masterkeys_pro_l" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\Keyboards\masterkeys-pro-l.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
BIN
Artemis/Artemis/Resources/Keyboards/masterkeys-pro-l.png
Normal file
BIN
Artemis/Artemis/Resources/Keyboards/masterkeys-pro-l.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 142 KiB |
@ -40,8 +40,8 @@ namespace Artemis.Services
|
|||||||
|
|
||||||
Execute.OnUIThread(() =>
|
Execute.OnUIThread(() =>
|
||||||
{
|
{
|
||||||
window = Application.Current.Windows.OfType<MetroWindow>().FirstOrDefault(w => w.IsActive) ??
|
window = Application.Current.Windows.OfType<MetroWindow>()
|
||||||
Application.Current.Windows.OfType<MetroWindow>().FirstOrDefault();
|
.FirstOrDefault(w => w.IsActive && w.IsVisible);
|
||||||
});
|
});
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
|
using PixelFormat = System.Drawing.Imaging.PixelFormat;
|
||||||
|
using Point = System.Drawing.Point;
|
||||||
|
|
||||||
namespace Artemis.Utilities
|
namespace Artemis.Utilities
|
||||||
{
|
{
|
||||||
|
|||||||
@ -56,7 +56,7 @@ namespace Artemis.Utilities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dialogService">The dialog service to use for progress and result dialogs</param>
|
/// <param name="dialogService">The dialog service to use for progress and result dialogs</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static async Task CheckChangelog(MetroDialogService dialogService)
|
public static async void CheckChangelog(MetroDialogService dialogService)
|
||||||
{
|
{
|
||||||
var settings = SettingsProvider.Load<GeneralSettings>();
|
var settings = SettingsProvider.Load<GeneralSettings>();
|
||||||
var currentVersion = Assembly.GetExecutingAssembly().GetName().Version;
|
var currentVersion = Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
|
|||||||
@ -1,11 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using Artemis.DAL;
|
||||||
|
using Artemis.Events;
|
||||||
using Artemis.Managers;
|
using Artemis.Managers;
|
||||||
using Artemis.Services;
|
using Artemis.Services;
|
||||||
|
using Artemis.Settings;
|
||||||
|
using Artemis.Utilities;
|
||||||
using Artemis.ViewModels.Abstract;
|
using Artemis.ViewModels.Abstract;
|
||||||
using Artemis.ViewModels.Flyouts;
|
using Artemis.ViewModels.Flyouts;
|
||||||
using Caliburn.Micro;
|
using Caliburn.Micro;
|
||||||
|
using Hardcodet.Wpf.TaskbarNotification;
|
||||||
using MahApps.Metro.Controls;
|
using MahApps.Metro.Controls;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
|
|
||||||
@ -14,52 +21,130 @@ namespace Artemis.ViewModels
|
|||||||
public sealed class ShellViewModel : Conductor<IScreen>.Collection.OneActive
|
public sealed class ShellViewModel : Conductor<IScreen>.Collection.OneActive
|
||||||
{
|
{
|
||||||
private readonly IKernel _kernel;
|
private readonly IKernel _kernel;
|
||||||
|
private string _activeIcon;
|
||||||
|
private bool _checked;
|
||||||
|
private bool _enabled;
|
||||||
|
private string _toggleText;
|
||||||
|
private bool _exiting;
|
||||||
|
|
||||||
public ShellViewModel(IKernel kernel, MainManager mainManager, MetroDialogService metroDialogService,
|
public ShellViewModel(IKernel kernel, MainManager mainManager, MetroDialogService metroDialogService,
|
||||||
FlyoutSettingsViewModel flyoutSettings)
|
FlyoutSettingsViewModel flyoutSettings)
|
||||||
{
|
{
|
||||||
_kernel = kernel;
|
_kernel = kernel;
|
||||||
|
|
||||||
|
MainManager = mainManager;
|
||||||
|
MetroDialogService = metroDialogService;
|
||||||
|
|
||||||
// Setup UI
|
|
||||||
DisplayName = "Artemis";
|
DisplayName = "Artemis";
|
||||||
|
GeneralSettings = SettingsProvider.Load<GeneralSettings>();
|
||||||
Flyouts = new BindableCollection<FlyoutBaseViewModel>
|
Flyouts = new BindableCollection<FlyoutBaseViewModel>
|
||||||
{
|
{
|
||||||
flyoutSettings
|
flyoutSettings
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MainManager.OnEnabledChangedEvent += (sender, args) => Enabled = args.Enabled;
|
||||||
|
|
||||||
MainManager = mainManager;
|
// This gets updated automatically but during startup lets quickly preset it
|
||||||
MetroDialogService = metroDialogService;
|
Enabled = GeneralSettings.Suspended;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnViewReady(object view)
|
||||||
|
{
|
||||||
|
base.OnViewReady(view);
|
||||||
|
|
||||||
|
Task.Run(() => StartupHide());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartupHide()
|
||||||
|
{
|
||||||
|
// TODO: This is probably an awful idea. I can't reliably hook into the view being ready to be hidden
|
||||||
|
Thread.Sleep(500);
|
||||||
|
|
||||||
|
if (GeneralSettings.ShowOnStartup)
|
||||||
|
ShowWindow();
|
||||||
|
else
|
||||||
|
HideWindow();
|
||||||
|
|
||||||
|
if (!GeneralSettings.Suspended)
|
||||||
MainManager.EnableProgram();
|
MainManager.EnableProgram();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SystemTrayViewModel SystemTrayViewModel { get; set; }
|
public Mutex Mutex { get; set; }
|
||||||
public MainManager MainManager { get; set; }
|
public MainManager MainManager { get; set; }
|
||||||
public MetroDialogService MetroDialogService { get; set; }
|
public MetroDialogService MetroDialogService { get; set; }
|
||||||
public IObservableCollection<FlyoutBaseViewModel> Flyouts { get; set; }
|
public IObservableCollection<FlyoutBaseViewModel> Flyouts { get; set; }
|
||||||
|
public GeneralSettings GeneralSettings { get; set; }
|
||||||
private MetroWindow Window => (MetroWindow) GetView();
|
private MetroWindow Window => (MetroWindow) GetView();
|
||||||
|
|
||||||
|
public bool CanShowWindow => Window != null && (Window != null || !Window.IsVisible);
|
||||||
|
public bool CanHideWindow => Window != null && Window.IsVisible;
|
||||||
|
|
||||||
|
public bool Enabled
|
||||||
|
{
|
||||||
|
get { return _enabled; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == _enabled) return;
|
||||||
|
_enabled = value;
|
||||||
|
|
||||||
|
ToggleText = _enabled ? "Disable Artemis" : "Enable Artemis";
|
||||||
|
ActiveIcon = _enabled ? "../Resources/logo.ico" : "../Resources/logo-disabled.ico";
|
||||||
|
NotifyOfPropertyChange(() => Enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ActiveIcon
|
||||||
|
{
|
||||||
|
get { return _activeIcon; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_activeIcon = value;
|
||||||
|
NotifyOfPropertyChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ToggleText
|
||||||
|
{
|
||||||
|
get { return _toggleText; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == _toggleText) return;
|
||||||
|
_toggleText = value;
|
||||||
|
NotifyOfPropertyChange(() => ToggleText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void CanClose(Action<bool> callback)
|
public override void CanClose(Action<bool> callback)
|
||||||
{
|
{
|
||||||
if (Window.IsVisible)
|
if (CanHideWindow)
|
||||||
HideWindow();
|
HideWindow();
|
||||||
else
|
else if (!_exiting)
|
||||||
ShowWindow();
|
ShowWindow();
|
||||||
|
|
||||||
// ShellView is a strong and independent view who won't let herself get closed by the likes of anyone!
|
// Only close if ExitApplication was called
|
||||||
callback(false);
|
callback(_exiting);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanShowWindow => !Window.IsVisible;
|
|
||||||
public bool CanHideWindow => Window.IsVisible;
|
|
||||||
|
|
||||||
public void ShowWindow()
|
public void ShowWindow()
|
||||||
{
|
{
|
||||||
if (!Window.IsVisible)
|
if (CanShowWindow)
|
||||||
|
Window?.Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
Window.Show();
|
Window.Show();
|
||||||
|
Window.Activate();
|
||||||
|
});
|
||||||
|
|
||||||
|
GeneralSettings.ApplyTheme();
|
||||||
|
|
||||||
|
// Show certain dialogs if needed
|
||||||
|
CheckKeyboardState();
|
||||||
|
CheckDuplicateInstances();
|
||||||
|
Updater.CheckChangelog(MetroDialogService);
|
||||||
|
|
||||||
|
var vms = _kernel.GetAll<BaseViewModel>().ToList();
|
||||||
|
Items.Clear();
|
||||||
|
Items.AddRange(vms);
|
||||||
|
ActivateItem(vms.FirstOrDefault());
|
||||||
|
|
||||||
NotifyOfPropertyChange(() => CanShowWindow);
|
NotifyOfPropertyChange(() => CanShowWindow);
|
||||||
NotifyOfPropertyChange(() => CanHideWindow);
|
NotifyOfPropertyChange(() => CanHideWindow);
|
||||||
@ -67,26 +152,44 @@ namespace Artemis.ViewModels
|
|||||||
|
|
||||||
public void HideWindow()
|
public void HideWindow()
|
||||||
{
|
{
|
||||||
if (Window.IsVisible)
|
if (CanHideWindow)
|
||||||
Window.Hide();
|
Window?.Dispatcher.Invoke(() => { Window.Hide(); });
|
||||||
|
|
||||||
|
Items.Clear();
|
||||||
NotifyOfPropertyChange(() => CanShowWindow);
|
NotifyOfPropertyChange(() => CanShowWindow);
|
||||||
NotifyOfPropertyChange(() => CanHideWindow);
|
NotifyOfPropertyChange(() => CanHideWindow);
|
||||||
|
|
||||||
|
// Force a GC since the UI releases a lot of resources
|
||||||
|
GC.Collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnActivate()
|
public void ToggleEnabled()
|
||||||
{
|
{
|
||||||
base.OnActivate();
|
if (Enabled)
|
||||||
Items.Clear();
|
MainManager.DisableProgram();
|
||||||
|
else
|
||||||
var vms = _kernel.GetAll<BaseViewModel>();
|
MainManager.EnableProgram();
|
||||||
Items.AddRange(vms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDeactivate(bool close)
|
public void ExitApplication()
|
||||||
{
|
{
|
||||||
base.OnDeactivate(close);
|
MainManager.Dispose();
|
||||||
Items.Clear();
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var icon = (TaskbarIcon) Window.FindResource("SystemTrayIcon");
|
||||||
|
icon.Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
//ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
_exiting = true;
|
||||||
|
|
||||||
|
// TODO: CoolerMaster SDK is freezing Artemis on shutdown, dunno what to do about it yet
|
||||||
|
System.Diagnostics.Process.GetCurrentProcess().Kill();
|
||||||
|
// Application.Current.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Settings()
|
public void Settings()
|
||||||
@ -98,5 +201,42 @@ namespace Artemis.ViewModels
|
|||||||
{
|
{
|
||||||
Flyouts.First().IsOpen = false;
|
Flyouts.First().IsOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void CheckKeyboardState()
|
||||||
|
{
|
||||||
|
var dialog = await MetroDialogService.ShowProgressDialog("Enabling keyboard",
|
||||||
|
"Artemis is still busy trying to enable your last used keyboard. " +
|
||||||
|
"Please wait while the process completes");
|
||||||
|
dialog.SetIndeterminate();
|
||||||
|
|
||||||
|
while (MainManager.DeviceManager.ChangingKeyboard)
|
||||||
|
await Task.Delay(10);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await dialog.CloseAsync();
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
// Occurs when window is closed again, can't find a proper check for this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckDuplicateInstances()
|
||||||
|
{
|
||||||
|
if (_checked)
|
||||||
|
return;
|
||||||
|
_checked = true;
|
||||||
|
|
||||||
|
bool aIsNewInstance;
|
||||||
|
Mutex = new Mutex(true, "ArtemisMutex", out aIsNewInstance);
|
||||||
|
if (aIsNewInstance)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MetroDialogService.ShowMessageBox("Multiple instances found",
|
||||||
|
"It looks like there are multiple running instances of Artemis. " +
|
||||||
|
"This can cause issues, especially with CS:GO and Dota2. " +
|
||||||
|
"If so, please make sure Artemis isn't already running");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,200 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
|
||||||
using Artemis.DAL;
|
|
||||||
using Artemis.Events;
|
|
||||||
using Artemis.Managers;
|
|
||||||
using Artemis.Services;
|
|
||||||
using Artemis.Settings;
|
|
||||||
using Artemis.Utilities;
|
|
||||||
using Caliburn.Micro;
|
|
||||||
|
|
||||||
namespace Artemis.ViewModels
|
|
||||||
{
|
|
||||||
public class SystemTrayViewModel : Screen
|
|
||||||
{
|
|
||||||
private readonly WindowService _windowService;
|
|
||||||
private ShellViewModel _shellViewModel;
|
|
||||||
private string _activeIcon;
|
|
||||||
private bool _checked;
|
|
||||||
private bool _enabled;
|
|
||||||
private string _toggleText;
|
|
||||||
|
|
||||||
public SystemTrayViewModel(WindowService windowService, MetroDialogService dialogService, MainManager mainManager)
|
|
||||||
{
|
|
||||||
_windowService = windowService;
|
|
||||||
|
|
||||||
DialogService = dialogService;
|
|
||||||
MainManager = mainManager;
|
|
||||||
|
|
||||||
MainManager.EnableProgram();
|
|
||||||
MainManager.OnEnabledChangedEvent += MainManagerOnOnEnabledChangedEvent;
|
|
||||||
|
|
||||||
var generalSettings = SettingsProvider.Load<GeneralSettings>();
|
|
||||||
Enabled = !generalSettings.Suspended;
|
|
||||||
if (generalSettings.ShowOnStartup)
|
|
||||||
ShowWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MetroDialogService DialogService { get; set; }
|
|
||||||
|
|
||||||
public MainManager MainManager { get; set; }
|
|
||||||
|
|
||||||
public bool CanShowWindow
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_shellViewModel == null)
|
|
||||||
return true;
|
|
||||||
return !_shellViewModel.IsActive;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanHideWindow => (_shellViewModel?.IsActive == true) && !MainManager.DeviceManager.ChangingKeyboard;
|
|
||||||
public bool CanToggleEnabled => !MainManager.DeviceManager.ChangingKeyboard;
|
|
||||||
|
|
||||||
public bool Enabled
|
|
||||||
{
|
|
||||||
get { return _enabled; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == _enabled) return;
|
|
||||||
_enabled = value;
|
|
||||||
|
|
||||||
ToggleText = _enabled ? "Disable Artemis" : "Enable Artemis";
|
|
||||||
ActiveIcon = _enabled ? "../Resources/logo.ico" : "../Resources/logo-disabled.ico";
|
|
||||||
NotifyOfPropertyChange(() => Enabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ActiveIcon
|
|
||||||
{
|
|
||||||
get { return _activeIcon; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_activeIcon = value;
|
|
||||||
NotifyOfPropertyChange();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ToggleText
|
|
||||||
{
|
|
||||||
get { return _toggleText; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == _toggleText) return;
|
|
||||||
_toggleText = value;
|
|
||||||
NotifyOfPropertyChange(() => ToggleText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mutex Mutex { get; set; }
|
|
||||||
|
|
||||||
private void MainManagerOnOnEnabledChangedEvent(object sender, EnabledChangedEventArgs e)
|
|
||||||
{
|
|
||||||
Enabled = e.Enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ToggleEnabled()
|
|
||||||
{
|
|
||||||
if (Enabled)
|
|
||||||
MainManager.DisableProgram();
|
|
||||||
else
|
|
||||||
MainManager.EnableProgram();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnActivate()
|
|
||||||
{
|
|
||||||
base.OnActivate();
|
|
||||||
|
|
||||||
NotifyOfPropertyChange(() => CanShowWindow);
|
|
||||||
NotifyOfPropertyChange(() => CanHideWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ShowWindow()
|
|
||||||
{
|
|
||||||
if (!CanShowWindow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// manually show the next window view-model
|
|
||||||
_shellViewModel = _windowService.ShowWindow<ShellViewModel>();
|
|
||||||
|
|
||||||
NotifyOfPropertyChange(() => CanShowWindow);
|
|
||||||
NotifyOfPropertyChange(() => CanHideWindow);
|
|
||||||
|
|
||||||
SettingsProvider.Load<GeneralSettings>().ApplyTheme();
|
|
||||||
|
|
||||||
// Show certain dialogs if needed
|
|
||||||
CheckKeyboardState();
|
|
||||||
CheckDuplicateInstances();
|
|
||||||
Updater.CheckChangelog(DialogService);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CheckDuplicateInstances()
|
|
||||||
{
|
|
||||||
if (_checked)
|
|
||||||
return;
|
|
||||||
_checked = true;
|
|
||||||
|
|
||||||
bool aIsNewInstance;
|
|
||||||
Mutex = new Mutex(true, "ArtemisMutex", out aIsNewInstance);
|
|
||||||
if (aIsNewInstance)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DialogService.ShowMessageBox("Multiple instances found",
|
|
||||||
"It looks like there are multiple running instances of Artemis. " +
|
|
||||||
"This can cause issues, especially with CS:GO and Dota2. " +
|
|
||||||
"If so, please make sure Artemis isn't already running");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void CheckKeyboardState()
|
|
||||||
{
|
|
||||||
while (!_shellViewModel.IsActive)
|
|
||||||
await Task.Delay(200);
|
|
||||||
|
|
||||||
NotifyOfPropertyChange(() => CanHideWindow);
|
|
||||||
NotifyOfPropertyChange(() => CanToggleEnabled);
|
|
||||||
|
|
||||||
var dialog = await DialogService.ShowProgressDialog("Enabling keyboard",
|
|
||||||
"Artemis is still busy trying to enable your last used keyboard. " +
|
|
||||||
"Please wait while the process completes");
|
|
||||||
dialog.SetIndeterminate();
|
|
||||||
|
|
||||||
while (MainManager.DeviceManager.ChangingKeyboard)
|
|
||||||
await Task.Delay(10);
|
|
||||||
|
|
||||||
NotifyOfPropertyChange(() => CanHideWindow);
|
|
||||||
NotifyOfPropertyChange(() => CanToggleEnabled);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await dialog.CloseAsync();
|
|
||||||
}
|
|
||||||
catch (InvalidOperationException)
|
|
||||||
{
|
|
||||||
// Occurs when window is closed again, can't find a proper check for this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HideWindow()
|
|
||||||
{
|
|
||||||
if (!CanHideWindow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_shellViewModel.TryClose();
|
|
||||||
|
|
||||||
NotifyOfPropertyChange(() => CanShowWindow);
|
|
||||||
NotifyOfPropertyChange(() => CanHideWindow);
|
|
||||||
|
|
||||||
// Force a GC since the UI releases a lot of resources
|
|
||||||
GC.Collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ExitApplication()
|
|
||||||
{
|
|
||||||
MainManager.Dispose();
|
|
||||||
Application.Current.Shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user