Skip to content

Commit

Permalink
Keyboard support
Browse files Browse the repository at this point in the history
- Wallpaper keyboard input support added; Resolved: #35
Todo: infor user msg and hide desktop icon.
- Minor clean ups.
  • Loading branch information
rocksdanister committed Jan 20, 2021
1 parent 7c9901b commit 7800045
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
xmlns:local="clr-namespace:livelywpf.Core"
mc:Ignorable="d"
Title="RawInputDX" Height="450" Width="800"
ShowInTaskbar="False" Closing="Window_Closing" Visibility="Hidden">
ShowInTaskbar="False" Closing="Window_Closing" SourceInitialized="Window_SourceInitialized" Visibility="Hidden">
<Grid>

</Grid>
Expand Down
126 changes: 54 additions & 72 deletions src/livelywpf/livelywpf/Core/InputForwarding/RawInputDX.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ namespace livelywpf.Core
/// </summary>
public partial class RawInputDX : Window
{
#region setup

private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
public InputForwardMode InputMode { get; private set; }
public RawInputDX(InputForwardMode inputMode)
{
InitializeComponent();
//Starting a hidden window outside screen region.
//todo: Other wrappers such as SharpDX:https://github.com/sharpdx/SharpDX does not require a window, could not get it to work properly globally.. investigate.
//Starting a hidden window outside screen region, rawinput receives msg through WndProc
this.WindowStartupLocation = WindowStartupLocation.Manual;
this.Left = -99999;
SourceInitialized += Window_SourceInitialized;
this.InputMode = inputMode;
}

Expand All @@ -34,6 +34,7 @@ private void Window_SourceInitialized(object sender, EventArgs e)
switch (InputMode)
{
case InputForwardMode.off:
this.Close();
break;
case InputForwardMode.mouse:
//ExInputSink flag makes it work even when not in foreground, similar to global hook.. but asynchronous, no complications and no AV false detection!
Expand Down Expand Up @@ -68,6 +69,10 @@ private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs
}
}

#endregion //setup

#region input forward

protected IntPtr Hook(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
{
// You can read inputs by processing the WM_INPUT message.
Expand All @@ -76,7 +81,7 @@ protected IntPtr Hook(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bo
// Create an RawInputData from the handle stored in lParam.
var data = RawInputData.FromHandle(lparam);

// You can identify the source device using Header.DeviceHandle or just Device.
//You can identify the source device using Header.DeviceHandle or just Device.
//var sourceDeviceHandle = data.Header.DeviceHandle;
//var sourceDevice = data.Device;

Expand Down Expand Up @@ -136,20 +141,9 @@ a very incorrect value.
}
break;
case RawInputKeyboardData keyboard:
switch (keyboard.Keyboard.Flags)
{
case Linearstar.Windows.RawInput.Native.RawKeyboardFlags.Down:
ForwardMessageKeyboard((int)NativeMethods.WM.KEYDOWN, (IntPtr)keyboard.Keyboard.VirutalKey);
break;
case Linearstar.Windows.RawInput.Native.RawKeyboardFlags.Up:
//ForwardMessageKeyboard((int)NativeMethods.WM.KEYUP, (IntPtr)keyboard.Keyboard.VirutalKey);
break;
case Linearstar.Windows.RawInput.Native.RawKeyboardFlags.LeftKey:
break;
case Linearstar.Windows.RawInput.Native.RawKeyboardFlags.RightKey:
break;
}
System.Diagnostics.Debug.WriteLine(keyboard.Keyboard);
ForwardMessageKeyboard((int)keyboard.Keyboard.WindowMessage,
(IntPtr)keyboard.Keyboard.VirutalKey, keyboard.Keyboard.ScanCode,
(keyboard.Keyboard.Flags != Linearstar.Windows.RawInput.Native.RawKeyboardFlags.Up));
break;
}
}
Expand All @@ -160,16 +154,18 @@ a very incorrect value.
/// Forwards the keyboard message to the required wallpaper window based on given cursor location.<br/>
/// Skips if desktop is not focused.
/// </summary>
/// <param name="msg">key press msg</param>
/// <param name="wParam">Virtual-Key code</param>
private static void ForwardMessageKeyboard(int msg, IntPtr wParam)
/// <param name="msg">key press msg.</param>
/// <param name="wParam">Virtual-Key code.</param>
/// <param name="scanCode">OEM code of the key.</param>
/// <param name="isPressed">Key is pressed.</param>
private static void ForwardMessageKeyboard(int msg, IntPtr wParam, int scanCode, bool isPressed)
{
try
{
//Don't forward when not on desktop.
if (Playback.IsDesktop())
{
//Detect active wp based on cursor pos.
//Better way to do this?
//Detect active wp based on cursor pos, better way to do this?
var display = Screen.FromPoint(new System.Drawing.Point(
System.Windows.Forms.Control.MousePosition.X, System.Windows.Forms.Control.MousePosition.Y));
SetupDesktop.Wallpapers.ForEach(wallpaper =>
Expand All @@ -179,22 +175,27 @@ private static void ForwardMessageKeyboard(int msg, IntPtr wParam)
if (ScreenHelper.ScreenCompare(display, wallpaper.GetScreen(), DisplayIdentificationMode.screenLayout) ||
Program.SettingsVM.Settings.WallpaperArrangement == WallpaperArrangement.span)
{
//TODO: provide lParam (check docs of wm-keydown and up), weirdly enough most keys works without it.
//Problems:
//Some keys don't work - arrow keys..
//Repeated key input when keyUp msg is sent.
//Ref:
//ref:
//https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-keydown
//https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-keyup
NativeMethods.PostMessageW(wallpaper.GetHWND(), msg, wParam, IntPtr.Zero);
uint lParam = 1u; //press
lParam |= (uint)scanCode << 16; //oem code
lParam |= 1u << 24; //extended key
lParam |= 0u << 29; //context code; Note: Alt key combos wont't work
/* Same as:
* lParam = isPressed ? (lParam |= 0u << 30) : (lParam |= 1u << 30); //prev key state
* lParam = isPressed ? (lParam |= 0u << 31) : (lParam |= 1u << 31); //transition state
*/
lParam = isPressed ? lParam : (lParam |= 3u << 30);
NativeMethods.PostMessageW(wallpaper.GetHWND(), msg, wParam, (UIntPtr)lParam);
}
}
});
}
}
catch (Exception e)
{
Logger.Error("Input Forwarding Error:" + e.Message);
Logger.Error("Keyboard Forwarding Error:" + e.Message);
}
}

Expand Down Expand Up @@ -233,17 +234,21 @@ private static void ForwardMessageMouse(int x, int y, int msg, IntPtr wParam)
uint lParam = Convert.ToUInt32(mouse.Y);
lParam <<= 16;
lParam |= Convert.ToUInt32(mouse.X);
NativeMethods.PostMessageW(wallpaper.GetHWND(), msg, wParam, (IntPtr)lParam);
NativeMethods.PostMessageW(wallpaper.GetHWND(), msg, wParam, (UIntPtr)lParam);
}
}
});
}
catch (Exception e)
{
Logger.Error("Input Forwarding Error:" + e.Message);
Logger.Error("Mouse Forwarding Error:" + e.Message);
}
}

#endregion //input forward

#region helpers

/// <summary>
/// Converts global mouse cursor position value to per display localised value.
/// </summary>
Expand Down Expand Up @@ -271,47 +276,24 @@ private static Point CalculateMousePos(int x, int y, Screen display)

private static bool IsInputAllowed(WallpaperType type)
{
bool result = false;
switch (type)
return type switch
{
case WallpaperType.app:
result = true;
break;
case WallpaperType.web:
result = true;
break;
case WallpaperType.webaudio:
result = true;
break;
case WallpaperType.url:
result = true;
break;
case WallpaperType.bizhawk:
result = true;
break;
case WallpaperType.unity:
result = true;
break;
case WallpaperType.godot:
result = true;
break;
case WallpaperType.video:
result = false;
break;
case WallpaperType.gif:
result = false;
break;
case WallpaperType.unityaudio:
result = true;
break;
case WallpaperType.videostream:
result = false;
break;
case WallpaperType.picture:
result = false;
break;
}
return result;
WallpaperType.app => true,
WallpaperType.web => true,
WallpaperType.webaudio => true,
WallpaperType.url => true,
WallpaperType.bizhawk => true,
WallpaperType.unity => true,
WallpaperType.godot => true,
WallpaperType.video => false,
WallpaperType.gif => false,
WallpaperType.unityaudio => true,
WallpaperType.videostream => false,
WallpaperType.picture => false,
_ => false,
};
}

#endregion //helpers
}
}
3 changes: 3 additions & 0 deletions src/livelywpf/livelywpf/Helpers/Pinvoke/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ public enum SHOWWINDOW : uint
, CharSet = CharSet.Unicode)]
public extern static IntPtr PostMessageW(IntPtr hWnd, Int32 Msg, IntPtr wParam, IntPtr lParam);

[DllImport("User32.dll", EntryPoint = "PostMessageW", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)]
public extern static IntPtr PostMessageW(IntPtr hWnd, Int32 Msg, IntPtr wParam, UIntPtr lParam);

/// <summary>
/// Windows Messages
/// Defined in winuser.h from Windows SDK v6.1
Expand Down
13 changes: 9 additions & 4 deletions src/livelywpf/livelywpf/Helpers/Scheduler/IScheduler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace livelywpf.Helpers
{
public enum ShedulerEventType
public enum SchedulerEventType
{
[Description("Time based wallpaper.")]
time,
Expand All @@ -15,17 +15,22 @@ public enum ShedulerEventType
acpi
}

interface IScheduler
public interface IScheduler
{
/// <summary>
/// Event type.
/// </summary>
/// <returns></returns>
public ShedulerEventType GetEventType();
SchedulerEventType GetEventType();
/// <summary>
/// Check if event is ready to fire.
/// </summary>
/// <returns></returns>
public bool IsReady();
bool IsReady();
/// <summary>
/// Livelynfo.json path.
/// </summary>
/// <returns></returns>
string GetWallpaperPath();
}
}
11 changes: 11 additions & 0 deletions src/livelywpf/livelywpf/Helpers/Scheduler/SchedulerService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace livelywpf.Helpers
{
class SchedulerService
{

}
}
24 changes: 24 additions & 0 deletions src/livelywpf/livelywpf/Helpers/Scheduler/SchedulerTimeEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace livelywpf.Helpers
{
class SchedulerTimeEvent : IScheduler
{
public SchedulerEventType GetEventType()
{
throw new NotImplementedException();
}

public string GetWallpaperPath()
{
throw new NotImplementedException();
}

public bool IsReady()
{
throw new NotImplementedException();
}
}
}
9 changes: 1 addition & 8 deletions src/livelywpf/livelywpf/Helpers/Storage/JsonStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,7 @@ public static T LoadData(string filePath)
var tmp = (T)serializer.Deserialize(file, typeof(T));

//if file is corrupted, json can return null.
if (tmp == null)
{
throw new ArgumentNullException("json null/corrupt");
}
else
{
return tmp;
}
return (tmp != null ? tmp : throw new ArgumentNullException("json null/corrupt"));
}
}

Expand Down

0 comments on commit 7800045

Please sign in to comment.