diff --git a/TabletDriverGUI/ButtonMapping.xaml b/TabletDriverGUI/ButtonMapping.xaml
new file mode 100644
index 0000000..afac361
--- /dev/null
+++ b/TabletDriverGUI/ButtonMapping.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TabletDriverGUI/ButtonMapping.xaml.cs b/TabletDriverGUI/ButtonMapping.xaml.cs
new file mode 100644
index 0000000..e2c061c
--- /dev/null
+++ b/TabletDriverGUI/ButtonMapping.xaml.cs
@@ -0,0 +1,272 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace TabletDriverGUI
+{
+ public enum ButtonActionEnum : uint
+ {
+ DISABLED = 0,
+ MOUSE1 = 1,
+ MOUSE2 = 2,
+ MOUSE3 = 3,
+ MOUSE4 = 4,
+ MOUSE5 = 5,
+ SHORTCUT = 6
+ };
+
+ ///
+ /// Interaction logic for ButtonMapping.xaml
+ ///
+ public partial class ButtonMapping : Window
+ {
+ private Dictionary NbTabletButtonsMap;
+ public Dictionary MacroButtonMap;
+
+ public ButtonMapping(Configuration config, string tabletName)
+ {
+ NbTabletButtonsMap = new Dictionary()
+ {
+ { "Wacom CTL-470", 0 },
+ { "Wacom CTL-471", 0 },
+ { "Wacom CTL-472", 0 },
+ { "Wacom CTL-480", 4 },
+ { "Wacom CTH-480", 4 },
+ { "Wacom CTL-490", 4 },
+ { "XP Pen G430", 0 },
+ { "XP Pen G640", 0 },
+ { "Huion 420", 0 },
+ { "Huion H640P", 6 },
+ { "Gaomon S56K", 0 },
+ };
+ MacroButtonMap = new Dictionary();
+
+ if (tabletName != null && NbTabletButtonsMap.ContainsKey(tabletName))
+ {
+ InitializeComponent();
+
+ PenTipComboBox.DropDownClosed += new EventHandler(PromptShortcutWindowEvent);
+ PenBottomComboBox.DropDownClosed += new EventHandler(PromptShortcutWindowEvent);
+ PenTopComboBox.DropDownClosed += new EventHandler(PromptShortcutWindowEvent);
+
+ for (var i = 0; i < NbTabletButtonsMap[tabletName]; ++i)
+ {
+ ComboBox cb = new ComboBox
+ {
+ Name = "TabletButton" + (i + 1).ToString()
+ };
+ cb.DropDownClosed += new EventHandler(PromptShortcutWindowEvent);
+
+ GroupBox gb = new GroupBox
+ {
+ Header = "Tablet button " + (i + 1).ToString(),
+ Width = 110,
+ Margin = new Thickness(10, 0, 0, 0),
+ Content = cb
+ };
+ TabletButtonsContainer.Children.Add(gb);
+ }
+
+ // Create button map combobox items
+ var tabletButtons = TabletButtonsContainer.Children;
+
+ PenTipComboBox.Items.Add("Disabled");
+ PenBottomComboBox.Items.Add("Disabled");
+ PenTopComboBox.Items.Add("Disabled");
+ for (var j = 0; j < tabletButtons.Count; ++j)
+ {
+ var gb = tabletButtons[j] as GroupBox;
+ var cb = gb.Content as ComboBox;
+ cb.Items.Add("Disabled");
+ cb.SelectedIndex = 0;
+ }
+ for (int i = 1; i <= 5; ++i)
+ {
+ PenTipComboBox.Items.Add("Mouse " + i);
+ PenBottomComboBox.Items.Add("Mouse " + i);
+ PenTopComboBox.Items.Add("Mouse " + i);
+ for (var j = 0; j < tabletButtons.Count; ++j)
+ {
+ var gb = tabletButtons[j] as GroupBox;
+ var cb = gb.Content as ComboBox;
+ cb.Items.Add("Mouse " + i);
+ }
+ }
+ PenTipComboBox.Items.Add("Shortcut");
+ PenBottomComboBox.Items.Add("Shortcut");
+ PenTopComboBox.Items.Add("Shortcut");
+ for (var i = 0; i < tabletButtons.Count; ++i)
+ {
+ var gb = tabletButtons[i] as GroupBox;
+ var cb = gb.Content as ComboBox;
+ cb.Items.Add("Shortcut");
+ }
+
+ PenTipComboBox.SelectedIndex = 0;
+ PenBottomComboBox.SelectedIndex = 0;
+ PenTopComboBox.SelectedIndex = 0;
+
+
+ //
+ // Buttons
+ //
+ PenTipComboBox.SelectedIndex = config.ButtonMap[0];
+ PenBottomComboBox.SelectedIndex = config.ButtonMap[1];
+ PenTopComboBox.SelectedIndex = config.ButtonMap[2];
+
+ for (var i = 0; i < NbTabletButtonsMap[tabletName]; ++i)
+ {
+ for (var j = 0; j < TabletButtonsContainer.Children.Count && j + 3 < config.ButtonMap.Length; ++j)
+ {
+ var gb = TabletButtonsContainer.Children[j] as GroupBox;
+ var cb = gb.Content as ComboBox;
+
+ cb.SelectedIndex = config.ButtonMap[3 + j];
+ }
+ }
+
+ CheckBoxDisablePenButtons.IsChecked = config.DisablePenButtons;
+ CheckBoxDisableTabletButtons.IsChecked = config.DisableTabletButtons;
+ }
+ else
+ {
+ throw new TabletNotRecognizedException("Tablet not recognized");
+ }
+ }
+
+ private void ButtonSet_Click(object sender, RoutedEventArgs e)
+ {
+ DialogResult = true;
+ }
+
+ private void ButtonCancel_Click(object sender, RoutedEventArgs e)
+ {
+ DialogResult = false;
+ }
+
+ private void CheckBoxDisablePenButtons_Checked(object sender, RoutedEventArgs e)
+ {
+ PenButtonsContainer.IsEnabled = false;
+ }
+
+ private void CheckBoxDisablePenButtons_Unchecked(object sender, RoutedEventArgs e)
+ {
+ PenButtonsContainer.IsEnabled = true;
+ }
+
+ private void CheckBoxDisableTabletButtons_Checked(object sender, RoutedEventArgs e)
+ {
+ TabletButtonsContainer.IsEnabled = false;
+ }
+
+ private void CheckBoxDisableTabletButtons_Unchecked(object sender, RoutedEventArgs e)
+ {
+ TabletButtonsContainer.IsEnabled = true;
+ }
+
+ private enum MapType : uint
+ {
+ MAPVK_VK_TO_VSC = 0x0,
+ MAPVK_VSC_TO_VK = 0x1,
+ MAPVK_VK_TO_CHAR = 0x2,
+ MAPVK_VSC_TO_VK_EX = 0x3,
+ }
+
+ [DllImport("user32.dll")]
+ private static extern int ToUnicode(
+ uint wVirtKey,
+ uint wScanCode,
+ byte[] lpKeyState,
+ [Out, MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 4)]
+ StringBuilder pwszBuff,
+ int cchBuff,
+ uint wFlags);
+
+ [DllImport("user32.dll")]
+ private static extern bool GetKeyboardState(byte[] lpKeyState);
+
+ [DllImport("user32.dll")]
+ private static extern uint MapVirtualKey(uint uCode, MapType uMapType);
+
+ private int GetVKFromModifierKey(ModifierKeys modifierKey)
+ {
+ int ch = 0;
+
+ switch (modifierKey)
+ {
+ case ModifierKeys.Control:
+ ch = 0x11;
+ break;
+ case ModifierKeys.Shift:
+ ch = 0x10;
+ break;
+ case ModifierKeys.Alt:
+ ch = 0x12;
+ break;
+ case ModifierKeys.Windows:
+ ch = 0x5B;
+ break;
+ }
+
+ return (ch);
+ }
+
+ private int GetVKFromKey(Key key)
+ {
+ return (KeyInterop.VirtualKeyFromKey(key));
+ }
+
+ private void PromptShortcutWindowEvent(object sender, EventArgs e)
+ {
+ PromptShortcutWindow(sender);
+ }
+
+ private void PromptShortcutWindow(object sender)
+ {
+ ComboBox cb = sender as ComboBox;
+
+ if (cb.SelectedIndex == (uint)ButtonActionEnum.SHORTCUT)
+ {
+ ShortcutMapWindow shortcutMapWindow = new ShortcutMapWindow();
+
+ shortcutMapWindow.ShowDialog();
+
+ if (shortcutMapWindow.DialogResult == true)
+ {
+ int idx = -1;
+ if (cb.Name == "PenTipComboBox")
+ idx = 0;
+ else if (cb.Name == "PenBottomComboBox")
+ idx = 1;
+ else if (cb.Name == "PenTopComboBox")
+ idx = 2;
+ else
+ idx = Int32.Parse(cb.Name.Remove(0, 12)) + 2;
+ List l = new List();
+
+ for (var i = 0; i < shortcutMapWindow.ModifierKey.Count; ++i)
+ l.Add(GetVKFromModifierKey(shortcutMapWindow.ModifierKey[i]));
+ l.Add(GetVKFromKey(shortcutMapWindow.PressedKey));
+ if (shortcutMapWindow.PressedKey == Key.None)
+ cb.SelectedIndex = (int)ButtonActionEnum.DISABLED;
+ MacroButtonMap[idx] = l.ToArray();
+ }
+ else
+ cb.SelectedIndex = (int)ButtonActionEnum.DISABLED;
+
+ shortcutMapWindow.Close();
+ }
+ }
+ }
+}
diff --git a/TabletDriverGUI/Configuration.cs b/TabletDriverGUI/Configuration.cs
index bd98f71..2299048 100644
--- a/TabletDriverGUI/Configuration.cs
+++ b/TabletDriverGUI/Configuration.cs
@@ -4,6 +4,7 @@
using System.IO;
using System.Xml;
using System.Xml.Serialization;
+using System.Collections.Generic;
namespace TabletDriverGUI
{
@@ -36,7 +37,9 @@ public enum OutputModes
[XmlArray("ButtonMap")]
[XmlArrayItem("Button")]
public int[] ButtonMap;
- public bool DisableButtons;
+ public MacroButton[] MacroButtonMap;
+ public bool DisablePenButtons;
+ public bool DisableTabletButtons;
[XmlArray("CommandsAfter")]
[XmlArrayItem("Command")]
@@ -75,8 +78,10 @@ public Configuration()
DesktopSize = new Area(0, 0, 0, 0);
AutomaticDesktopSize = true;
- ButtonMap = new int[] { 1, 2, 3 };
- DisableButtons = false;
+ ButtonMap = new int[] { 1, 2, 3, 0, 0, 0, 0, 0, 0 };
+ MacroButtonMap = new MacroButton[] { };
+ DisablePenButtons = false;
+ DisableTabletButtons = false;
SmoothingEnabled = false;
SmoothingLatency = 0;
diff --git a/TabletDriverGUI/MacroButton.cs b/TabletDriverGUI/MacroButton.cs
new file mode 100644
index 0000000..cc410a5
--- /dev/null
+++ b/TabletDriverGUI/MacroButton.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Serialization;
+
+namespace TabletDriverGUI
+{
+ //[XmlType("MacroButton")]
+ public class MacroButton
+ {
+ public int Index;
+ [XmlArray("MacroKeys")]
+ [XmlArrayItem("Key")]
+ public int[] MacroKeys;
+
+ public MacroButton() { }
+
+ public MacroButton(int index, int[] macroKeys)
+ {
+ Index = index;
+ MacroKeys = macroKeys;
+ }
+ }
+}
diff --git a/TabletDriverGUI/MainWindow.xaml b/TabletDriverGUI/MainWindow.xaml
index 7e47861..4de32f7 100644
--- a/TabletDriverGUI/MainWindow.xaml
+++ b/TabletDriverGUI/MainWindow.xaml
@@ -272,8 +272,8 @@
-
-
+
+
@@ -286,32 +286,8 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Disable buttons
+
+
diff --git a/TabletDriverGUI/MainWindow.xaml.cs b/TabletDriverGUI/MainWindow.xaml.cs
index 19e74b7..db7936b 100644
--- a/TabletDriverGUI/MainWindow.xaml.cs
+++ b/TabletDriverGUI/MainWindow.xaml.cs
@@ -48,6 +48,7 @@ public partial class MainWindow : Window
private string configFilename;
private bool isFirstStart = false;
private bool isLoadingSettings;
+ private string TabletName;
// Screen map canvas elements
private Rectangle[] rectangleMonitors;
@@ -153,32 +154,11 @@ public MainWindow()
Interval = new TimeSpan(0, 0, 0, 0, 200)
};
timerConsoleUpdate.Tick += TimerConsoleUpdate_Tick;
-
+
// Tooltip timeout
ToolTipService.ShowDurationProperty.OverrideMetadata(
typeof(DependencyObject), new FrameworkPropertyMetadata(60000));
-
- //
- // Buttom Map ComboBoxes
- //
- comboBoxButton1.Items.Clear();
- comboBoxButton2.Items.Clear();
- comboBoxButton3.Items.Clear();
- comboBoxButton1.Items.Add("Disable");
- comboBoxButton2.Items.Add("Disable");
- comboBoxButton3.Items.Add("Disable");
- for (int i = 1; i <= 5; i++)
- {
- comboBoxButton1.Items.Add("Mouse " + i);
- comboBoxButton2.Items.Add("Mouse " + i);
- comboBoxButton3.Items.Add("Mouse " + i);
- }
- comboBoxButton1.SelectedIndex = 0;
- comboBoxButton2.SelectedIndex = 0;
- comboBoxButton3.SelectedIndex = 0;
-
-
//
// Smoothing rate ComboBox
//
@@ -191,7 +171,7 @@ public MainWindow()
// Process command line arguments
ProcessCommandLineArguments();
-
+
// Events
Closing += MainWindow_Closing;
Loaded += MainWindow_Loaded;
@@ -459,21 +439,6 @@ private void LoadSettingsFromConfiguration()
textTabletAreaY.Text = Utils.GetNumberString(config.TabletArea.Y);
- //
- // Buttons
- //
- if (config.ButtonMap.Count() == 3)
- {
- comboBoxButton1.SelectedIndex = config.ButtonMap[0];
- comboBoxButton2.SelectedIndex = config.ButtonMap[1];
- comboBoxButton3.SelectedIndex = config.ButtonMap[2];
- }
- else
- {
- config.ButtonMap = new int[] { 1, 2, 3 };
- }
- checkBoxDisableButtons.IsChecked = config.DisableButtons;
-
//
// Smoothing filter
@@ -613,10 +578,10 @@ private void UpdateSettingsToConfiguration()
// Button map
- config.ButtonMap[0] = comboBoxButton1.SelectedIndex;
- config.ButtonMap[1] = comboBoxButton2.SelectedIndex;
- config.ButtonMap[2] = comboBoxButton3.SelectedIndex;
- config.DisableButtons = (bool)checkBoxDisableButtons.IsChecked;
+ //config.ButtonMap[0] = comboBoxButton1.SelectedIndex;
+ //config.ButtonMap[1] = comboBoxButton2.SelectedIndex;
+ //config.ButtonMap[2] = comboBoxButton3.SelectedIndex;
+ //config.DisablePenButtons = (bool)checkBoxDisableButtons.IsChecked;
@@ -1172,20 +1137,6 @@ private void CheckboxChanged(object sender, RoutedEventArgs e)
}
- // Disable button map selection when buttons are disabled
- if (checkBoxDisableButtons.IsChecked == true)
- {
- comboBoxButton1.IsEnabled = false;
- comboBoxButton2.IsEnabled = false;
- comboBoxButton3.IsEnabled = false;
- }
- else
- {
- comboBoxButton1.IsEnabled = true;
- comboBoxButton2.IsEnabled = true;
- comboBoxButton3.IsEnabled = true;
- }
-
// Disable desktop size settings when automatic is checked
if (checkBoxAutomaticDesktopSize.IsChecked == true)
{
@@ -1297,13 +1248,14 @@ private void SaveSettings(object sender, RoutedEventArgs e)
SendSettingsToDriver();
SetStatus("Settings saved!");
}
- catch (Exception)
+ catch (Exception ex)
{
string dir = Directory.GetCurrentDirectory();
MessageBox.Show("Error occured while saving the configuration.\n" +
"Make sure that it is possible to create and edit files in the '" + dir + "' directory.\n",
"ERROR!", MessageBoxButton.OK, MessageBoxImage.Error
);
+ Console.WriteLine(ex.Message);
}
}
@@ -1546,9 +1498,10 @@ private void ParseDriverStatus(string line)
//
if (variableName == "tablet")
{
- Title = "TabletDriverGUI - " + stringValue;
+ TabletName = stringValue;
+ Title = "TabletDriverGUI - " + TabletName;
notifyIcon.Text = Title;
- SetStatus("Connected to " + stringValue);
+ SetStatus("Connected to " + TabletName);
}
//
@@ -1642,13 +1595,30 @@ private void SendSettingsToDriver()
// Button map
- if (config.DisableButtons)
+ if (config.DisablePenButtons)
{
- driver.SendCommand("ButtonMap 0 0 0");
+ string cmd = "ButtonMap 0 0 0 " + String.Join(" ", config.ButtonMap, 3, 6);
+ driver.SendCommand(cmd);
+ if (config.MacroButtonMap.Length != 0)
+ {
+ cmd = "TabletMacro " + string.Join(";", config.MacroButtonMap.Select(t => string.Format("{0},{1}", t.Index, string.Join(",", t.MacroKeys))));
+ driver.SendCommand(cmd);
+ }
+ }
+ else if (config.DisableTabletButtons)
+ {
+ string cmd = String.Join(" ", config.ButtonMap, 0, 3) + " 0 0 0 0 0 0";
+ driver.SendCommand(cmd);
}
else
{
- driver.SendCommand("ButtonMap " + String.Join(" ", config.ButtonMap));
+ string cmd = "ButtonMap " + String.Join(" ", config.ButtonMap);
+ driver.SendCommand(cmd);
+ if (config.MacroButtonMap.Length != 0)
+ {
+ cmd = "TabletMacro " + string.Join(";", config.MacroButtonMap.Select(t => string.Format("{0},{1}", t.Index, string.Join(",", t.MacroKeys))));
+ driver.SendCommand(cmd);
+ }
}
// Smoothing filter
@@ -2119,9 +2089,105 @@ private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref b
return IntPtr.Zero;
}
+
+ private void EditButtonMapping_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ Console.WriteLine("TabletName = " + TabletName);
+ ButtonMapping bm = new ButtonMapping(config, TabletName);
- #endregion
+ bm.ShowDialog();
+
+ if (bm.DialogResult == true)
+ {
+ List macroButtonsToRemove = new List();
+ for (var i = 0; i < 3; ++i)
+ {
+ if (config.ButtonMap[i] != 6)
+ macroButtonsToRemove.Add(i);
+ if (bm.MacroButtonMap.ContainsKey(i) && bm.MacroButtonMap[i].Length == 1 && bm.MacroButtonMap[i][0] == 0)
+ bm.MacroButtonMap.Remove(i);
+ else
+ {
+ switch (i)
+ {
+ case 0:
+ config.ButtonMap[i] = bm.PenTipComboBox.SelectedIndex;
+ break;
+ case 1:
+ config.ButtonMap[i] = bm.PenBottomComboBox.SelectedIndex;
+ break;
+ case 2:
+ config.ButtonMap[i] = bm.PenTopComboBox.SelectedIndex;
+ break;
+ }
+ }
+ }
+
+ for (var i = 0; i < bm.TabletButtonsContainer.Children.Count; ++i)
+ {
+ var gb = bm.TabletButtonsContainer.Children[i] as GroupBox;
+ var cb = gb.Content as ComboBox;
+
+ if (cb.SelectedIndex != 6)
+ macroButtonsToRemove.Add(i + 3);
+
+ if (bm.MacroButtonMap.ContainsKey(i + 3) && bm.MacroButtonMap[i + 3].Length == 1 && bm.MacroButtonMap[i + 3][0] == 0)
+ bm.MacroButtonMap.Remove(i + 3);
+ else
+ config.ButtonMap[i + 3] = cb.SelectedIndex;
+ }
+
+ //Delete removed or empty MacroButtons
+ var macroButtonList = config.MacroButtonMap.ToList();
+ for (var i = 0; i < macroButtonsToRemove.Count; ++i)
+ {
+ for (var j = 0; j < macroButtonList.Count; ++j)
+ {
+ if (macroButtonsToRemove[i] == macroButtonList[j].Index)
+ {
+ macroButtonList.RemoveAt(j);
+ break;
+ }
+ }
+ }
+ config.MacroButtonMap = macroButtonList.ToArray();
+
+ //Concat new results into the local configuration
+ foreach (var item in bm.MacroButtonMap)
+ {
+ bool added = false;
+ for (var i = 0; i < config.MacroButtonMap.Length && !added; ++i)
+ {
+ if (config.MacroButtonMap[i].Index == item.Key)
+ {
+ config.MacroButtonMap[i].MacroKeys = item.Value;
+ added = true;
+ }
+ }
+ if (!added)
+ {
+ var list = config.MacroButtonMap.ToList();
+ list.Add(new MacroButton(item.Key, item.Value));
+ config.MacroButtonMap = list.ToArray();
+ }
+ }
+
+ config.DisablePenButtons = bm.CheckBoxDisablePenButtons.IsChecked ?? false;
+ config.DisableTabletButtons = bm.CheckBoxDisableTabletButtons.IsChecked ?? false;
+ }
+
+ bm.Close();
+ }
+ catch (TabletNotRecognizedException)
+ {
+ MessageBox.Show("Your tablet needs to be recognized before changing its control mapping.", "Tablet not recognized", MessageBoxButton.OK, MessageBoxImage.Exclamation);
+ }
+ }
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/TabletDriverGUI/ShortcutMapWindow.xaml b/TabletDriverGUI/ShortcutMapWindow.xaml
new file mode 100644
index 0000000..583a6f1
--- /dev/null
+++ b/TabletDriverGUI/ShortcutMapWindow.xaml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TabletDriverGUI/ShortcutMapWindow.xaml.cs b/TabletDriverGUI/ShortcutMapWindow.xaml.cs
new file mode 100644
index 0000000..4c9411c
--- /dev/null
+++ b/TabletDriverGUI/ShortcutMapWindow.xaml.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace TabletDriverGUI
+{
+ ///
+ /// Interaction logic for ShortcutMapWindow.xaml
+ ///
+ public partial class ShortcutMapWindow : Window
+ {
+ public List ModifierKey;
+ public Key PressedKey;
+
+ public ShortcutMapWindow()
+ {
+ ModifierKey = new List();
+ InitializeComponent();
+ }
+
+ private void Window_KeyDown(object sender, KeyEventArgs e)
+ {
+ ModifierKey.Clear();
+
+ e.Handled = true;
+
+ // Fetch the actual shortcut key.
+ Key key = (e.Key == Key.System ? e.SystemKey : e.Key);
+
+ PressedKey = key;
+
+ // Ignore modifier keys.
+ if (key == Key.LeftShift || key == Key.RightShift
+ || key == Key.LeftCtrl || key == Key.RightCtrl
+ || key == Key.LeftAlt || key == Key.RightAlt
+ || key == Key.LWin || key == Key.RWin)
+ {
+ return;
+ }
+
+ // Build the shortcut key name.
+ StringBuilder shortcutText = new StringBuilder();
+ if ((Keyboard.Modifiers & ModifierKeys.Control) != 0)
+ {
+ ModifierKey.Add(ModifierKeys.Control);
+ shortcutText.Append("Ctrl+");
+ }
+ if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0)
+ {
+ ModifierKey.Add(ModifierKeys.Shift);
+ shortcutText.Append("Shift+");
+ }
+ if ((Keyboard.Modifiers & ModifierKeys.Alt) != 0)
+ {
+ ModifierKey.Add(ModifierKeys.Alt);
+ shortcutText.Append("Alt+");
+ }
+ shortcutText.Append(key.ToString());
+
+ ShortcutResult.Content = shortcutText.ToString();
+ }
+
+ private void ButtonSet_Click(object sender, RoutedEventArgs e)
+ {
+ DialogResult = true;
+ }
+
+ private void ButtonCancel_Click(object sender, RoutedEventArgs e)
+ {
+ DialogResult = false;
+ }
+ }
+}
diff --git a/TabletDriverGUI/TabletDriverGUI.csproj b/TabletDriverGUI/TabletDriverGUI.csproj
index ed30a36..6f0f10c 100644
--- a/TabletDriverGUI/TabletDriverGUI.csproj
+++ b/TabletDriverGUI/TabletDriverGUI.csproj
@@ -77,13 +77,25 @@
MSBuild:Compile
Designer
+
+ ButtonMapping.xaml
+
+
+
+ ShortcutMapWindow.xaml
+
+
WacomArea.xaml
+
+ Designer
+ MSBuild:Compile
+
MSBuild:Compile
Designer
@@ -98,6 +110,10 @@
MainWindow.xaml
Code
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/TabletDriverGUI/TabletNotRecognizedException.cs b/TabletDriverGUI/TabletNotRecognizedException.cs
new file mode 100644
index 0000000..23a815c
--- /dev/null
+++ b/TabletDriverGUI/TabletNotRecognizedException.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TabletDriverGUI
+{
+ class TabletNotRecognizedException : Exception
+ {
+ public TabletNotRecognizedException(string message) : base(message)
+ {
+
+ }
+ }
+}
diff --git a/TabletDriverGUI/WacomArea.xaml b/TabletDriverGUI/WacomArea.xaml
index 7e8b267..be2bfc0 100644
--- a/TabletDriverGUI/WacomArea.xaml
+++ b/TabletDriverGUI/WacomArea.xaml
@@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TabletDriverGUI"
mc:Ignorable="d"
- Title="Wacom Intuos/Bamboo area" Height="250" Width="350">
+ Title="Wacom Intuos/Bamboo area" Height="250" Width="350" ResizeMode="NoResize">
diff --git a/TabletDriverService/Main.cpp b/TabletDriverService/Main.cpp
index d8de81e..861cd00 100644
--- a/TabletDriverService/Main.cpp
+++ b/TabletDriverService/Main.cpp
@@ -23,6 +23,7 @@ Tablet *tablet;
VMulti *vmulti;
ScreenMapper *mapper;
thread *tabletThread;
+thread *tabletAuxThread;
//
// Init console parameters
@@ -39,7 +40,7 @@ void InitConsole() {
}
//
-// Tablet process
+// Tablet thread
//
void RunTabletThread() {
int status;
@@ -160,6 +161,56 @@ void RunTabletThread() {
}
+//
+// Tablet auxiliary thread
+//
+void RunTabletAuxThread() {
+
+ BYTE buffer[256];
+ int status;
+
+ while(true) {
+
+ //
+ // Wacom 480 aux
+ //
+ if(tablet->settings.auxType == TabletSettings::AuxWacom480) {
+
+ // Read 64 bytes from the HID device
+ status = tablet->hidDeviceAux->Read(buffer, 64);
+ if(status < 0) {
+ LOG_ERROR("HID auxiliary device error!\n");
+ break;
+ }
+
+ //LOG_DEBUGBUFFER(buffer, 16, "AUX: ");
+
+ // Report Id == 2?
+ if(buffer[0] == 0x02) {
+
+ // Loop through packet items
+ for(int offset = 2; offset < 64; offset += 8) {
+
+ // Buttons
+ if(buffer[offset] == 0x80) {
+ BYTE buttons = buffer[3];
+ LOG_DEBUG("Aux buttons: %02X\n", buttons);
+ }
+
+ // Touch (max 16 points)
+ if(buffer[offset] >= 2 && buffer[offset] <= 17) {
+ BYTE touchIndex = buffer[offset] - 1;
+
+ int touchX = (buffer[offset + 2] << 4) | (buffer[offset + 4] >> 4);
+ int touchY = (buffer[offset + 3] << 4) | (buffer[offset + 4] & 0x0f);
+ LOG_DEBUG("Aux Touch(%02X): % 5d, % 5d\n", touchIndex, touchX, touchY);
+ }
+ }
+ }
+ }
+ }
+}
+
//
// Tablet filter timer callback
//
@@ -251,6 +302,7 @@ int main(int argc, char**argv) {
vmulti = NULL;
tablet = NULL;
tabletThread = NULL;
+ tabletAuxThread = NULL;
// Init console
InitConsole();
@@ -344,6 +396,11 @@ int main(int argc, char**argv) {
// Start the tablet thread
tabletThread = new thread(RunTabletThread);
+ // Start the tablet auxiliary thread
+ if(tablet->hidDeviceAux != NULL) {
+ tabletAuxThread = new thread(RunTabletAuxThread);
+ }
+
LOG_INFO("TabletDriver started!\n");
LogStatus();
diff --git a/TabletDriverService/ProcessCommand.cpp b/TabletDriverService/ProcessCommand.cpp
index ac59dc2..8e5506b 100644
--- a/TabletDriverService/ProcessCommand.cpp
+++ b/TabletDriverService/ProcessCommand.cpp
@@ -97,22 +97,30 @@ bool ProcessCommand(CommandLine *cmd) {
}
- // HID Device 2
- else if(cmd->is("HID2")) {
+ // HID Auxiliary Device
+ else if(cmd->is("HIDAux")) {
+ if(tablet == NULL) return false;
- if(cmd->valueCount == 4) {
+ if(cmd->valueCount == 5) {
USHORT vendorID = cmd->GetInt(0, 0);
USHORT productID = cmd->GetInt(1, 0);
USHORT usagePage = cmd->GetInt(2, 0);
USHORT usage = cmd->GetInt(3, 0);
- if(tablet->hidDevice2 == NULL) {
- tablet->hidDevice2 = new HIDDevice(vendorID, productID, usagePage, usage);
- if(tablet->hidDevice2->isOpen) {
+ string auxTypeString = cmd->GetStringLower(4, "");
+ if(tablet->hidDeviceAux == NULL) {
+ tablet->hidDeviceAux = new HIDDevice(vendorID, productID, usagePage, usage);
+ if(tablet->hidDeviceAux->isOpen) {
LOG_INFO("HID Device found!\n");
+
+ // Aux Wacom 480
+ if(auxTypeString == "wacom480") {
+ tablet->settings.auxType = TabletSettings::AuxWacom480;
+ }
+
} else {
LOG_ERROR("Can't open HID device 0x%04X 0x%04X 0x%04X 0x%04X\n", vendorID, productID, usagePage, usage);
- delete tablet->hidDevice2;
- tablet->hidDevice2 = NULL;
+ delete tablet->hidDeviceAux;
+ tablet->hidDeviceAux = NULL;
}
}
}
@@ -294,7 +302,7 @@ bool ProcessCommand(CommandLine *cmd) {
if(!CheckTablet()) return true;
char buttonMapBuffer[32];
int index = 0;
- for(int i = 0; i < 8; i++) {
+ for(int i = 0; i < 9; i++) {
tablet->buttonMap[i] = cmd->GetInt(i, tablet->buttonMap[i]);
index += sprintf_s(buttonMapBuffer + index, 32 - index, "%d ", tablet->buttonMap[i]);
}
@@ -302,6 +310,41 @@ bool ProcessCommand(CommandLine *cmd) {
}
+
+ //
+ // Tablet buttons macro
+ //
+ else if (cmd->is("TabletMacro")) {
+ //LOG_INFO("is equal before check: %d\n", cmd->is("TabletMacro"));
+ //LOG_INFO("cmd->command is: %s\n", cmd->command);
+ if (!CheckTablet()) return true;
+ if (true)
+ {
+ std::vector tempSplit = Utils::split(cmd->line.substr(12).c_str(), ';');
+ std::vector> tabletMacros;
+
+ for (auto &it : tempSplit)
+ tabletMacros.push_back(Utils::split(it, ','));
+
+ for (auto &it : tabletMacros)
+ {
+ std::vector keysMacro;
+
+ for (int i = 0; i < (int)it.size(); ++i)
+ {
+ if (i != 0)
+ keysMacro.push_back(std::stoi(it[i]));
+ }
+
+ tablet->buttonMacroMap[std::stoi(it[0])] = std::make_pair(keysMacro, false);
+ LOG_INFO("Set the macro to the button [%d]\n", std::stoi(it[0]));
+ }
+ }
+ else
+ LOG_INFO("Invalid command for TabletMacro, try this instead: TabletMacro macro_string\n");
+ }
+
+
// Screen Map Area
else if(cmd->is("ScreenArea") || cmd->is("Screen")) {
if(!CheckTablet()) return true;
diff --git a/TabletDriverService/ProcessCommand.h b/TabletDriverService/ProcessCommand.h
index af58f27..993c297 100644
--- a/TabletDriverService/ProcessCommand.h
+++ b/TabletDriverService/ProcessCommand.h
@@ -1,5 +1,6 @@
#pragma once
#include "CommandLine.h"
+#include "Utils.h"
bool ProcessCommand(CommandLine *cmd);
bool ReadCommandFile(string filename);
diff --git a/TabletDriverService/Tablet.cpp b/TabletDriverService/Tablet.cpp
index e44e227..7d8006d 100644
--- a/TabletDriverService/Tablet.cpp
+++ b/TabletDriverService/Tablet.cpp
@@ -24,9 +24,10 @@ Tablet::Tablet(string usbGUID, int stringId, string stringMatch) : Tablet() {
//
Tablet::Tablet(USHORT vendorId, USHORT productId, USHORT usagePage, USHORT usage) : Tablet() {
hidDevice = new HIDDevice(vendorId, productId, usagePage, usage);
- if(hidDevice->isOpen) {
+ if (hidDevice->isOpen) {
this->isOpen = true;
- } else {
+ }
+ else {
delete hidDevice;
hidDevice = NULL;
}
@@ -40,7 +41,7 @@ Tablet::Tablet() {
name = "Unknown";
usbDevice = NULL;
hidDevice = NULL;
- hidDevice2 = NULL;
+ hidDeviceAux = NULL;
usbPipeId = 0;
@@ -86,8 +87,8 @@ Tablet::~Tablet() {
delete usbDevice;
if(hidDevice != NULL)
delete hidDevice;
- if(hidDevice2 != NULL)
- delete hidDevice2;
+ if(hidDeviceAux != NULL)
+ delete hidDeviceAux;
if(initReport != NULL)
delete initReport;
if(initFeature != NULL)
@@ -238,14 +239,25 @@ int Tablet::ReadPosition() {
state.buttons = 0;
for(buttonIndex = 0; buttonIndex < sizeof(buttonMap); buttonIndex++) {
- // Button is set
- if(buttonMap[buttonIndex] > 0) {
+ // Button is set (not a macro)
+ if(buttonMap[buttonIndex] > 0 && buttonMap[buttonIndex] < 6) {
// Button is pressed
if((reportData.buttons & (1 << buttonIndex)) > 0) {
state.buttons |= (1 << (buttonMap[buttonIndex] - 1));
}
}
+ else if (buttonMap[buttonIndex] == 6)
+ {
+ if ((reportData.buttons & (1 << buttonIndex)) > 0)
+ {
+ if (!buttonMacroMap[buttonIndex].second)
+ Utils::keyboardShortcutPress(buttonMacroMap[buttonIndex].first);
+ buttonMacroMap[buttonIndex].second = true;
+ }
+ else
+ buttonMacroMap[buttonIndex].second = false;
+ }
}
// Convert report data to state
@@ -303,6 +315,9 @@ void Tablet::CloseDevice() {
usbDevice->CloseDevice();
} else if(hidDevice != NULL) {
hidDevice->CloseDevice();
+ if(hidDeviceAux != NULL) {
+ hidDeviceAux->CloseDevice();
+ }
}
}
isOpen = false;
diff --git a/TabletDriverService/Tablet.h b/TabletDriverService/Tablet.h
index 4d482f2..6d50e04 100644
--- a/TabletDriverService/Tablet.h
+++ b/TabletDriverService/Tablet.h
@@ -1,9 +1,11 @@
#pragma once
#include
+#include
#include "USBDevice.h"
#include "HIDDevice.h"
+#include "Utils.h"
#include "TabletSettings.h"
#include "TabletFilterSmoothing.h"
#include "TabletFilterNoiseReduction.h"
@@ -17,7 +19,7 @@ class Tablet {
USBDevice * usbDevice;
HIDDevice * hidDevice;
- HIDDevice * hidDevice2;
+ HIDDevice * hidDeviceAux;
int usbPipeId;
//
@@ -77,6 +79,7 @@ class Tablet {
// Button map
BYTE buttonMap[16];
+ std::unordered_map, bool>> buttonMacroMap;
//
string name = "Unknown";
diff --git a/TabletDriverService/TabletDriverService.vcxproj b/TabletDriverService/TabletDriverService.vcxproj
index 900ca69..8f788d9 100644
--- a/TabletDriverService/TabletDriverService.vcxproj
+++ b/TabletDriverService/TabletDriverService.vcxproj
@@ -182,6 +182,7 @@ xcopy /C /Y "$(ProjectDir)config\init.cfg" "$(SolutionDir)TabletDriverGUI\bin\De
+
@@ -205,6 +206,7 @@ xcopy /C /Y "$(ProjectDir)config\init.cfg" "$(SolutionDir)TabletDriverGUI\bin\De
Create
+
diff --git a/TabletDriverService/TabletDriverService.vcxproj.filters b/TabletDriverService/TabletDriverService.vcxproj.filters
index 8e46824..5a308f9 100644
--- a/TabletDriverService/TabletDriverService.vcxproj.filters
+++ b/TabletDriverService/TabletDriverService.vcxproj.filters
@@ -45,6 +45,9 @@
Header Files
+<<<<<<< HEAD
+
+=======
Header Files
@@ -61,6 +64,7 @@
Header Files
+>>>>>>> master
Header Files
@@ -95,6 +99,9 @@
Source Files
+<<<<<<< HEAD
+
+=======
Source Files
@@ -111,6 +118,7 @@
Source Files
+>>>>>>> master
Source Files
diff --git a/TabletDriverService/TabletFilterSmoothing.cpp b/TabletDriverService/TabletFilterSmoothing.cpp
index af39330..5a155cc 100644
--- a/TabletDriverService/TabletFilterSmoothing.cpp
+++ b/TabletDriverService/TabletFilterSmoothing.cpp
@@ -68,7 +68,7 @@ void TabletFilterSmoothing::Update() {
// Set position
-double TabletFilterSmoothing::SetPosition(double x, double y) {
+void TabletFilterSmoothing::SetPosition(double x, double y) {
this->position.x = x;
this->position.y = y;
}
diff --git a/TabletDriverService/TabletFilterSmoothing.h b/TabletDriverService/TabletFilterSmoothing.h
index 9c6c70b..87a132d 100644
--- a/TabletDriverService/TabletFilterSmoothing.h
+++ b/TabletDriverService/TabletFilterSmoothing.h
@@ -21,7 +21,7 @@ class TabletFilterSmoothing : public TabletFilter {
bool GetPosition(Vector2D *outputVector);
void Update();
- double SetPosition(double x, double y);
+ void SetPosition(double x, double y);
double GetLatency(double filterWeight, double interval, double threshold);
double GetLatency(double filterWeight);
double GetLatency();
diff --git a/TabletDriverService/TabletSettings.cpp b/TabletDriverService/TabletSettings.cpp
index 228cc6c..96539c2 100644
--- a/TabletDriverService/TabletSettings.cpp
+++ b/TabletDriverService/TabletSettings.cpp
@@ -18,6 +18,7 @@ TabletSettings::TabletSettings() {
height = 1;
skew = 0;
type = TabletNormal;
+ auxType = AuxUnknown;
}
//
diff --git a/TabletDriverService/TabletSettings.h b/TabletDriverService/TabletSettings.h
index f667af7..57b0133 100644
--- a/TabletDriverService/TabletSettings.h
+++ b/TabletDriverService/TabletSettings.h
@@ -8,6 +8,12 @@ class TabletSettings {
TypeWacom4100
};
+
+ enum TabletAuxType {
+ AuxUnknown,
+ AuxWacom480
+ };
+
BYTE buttonMask;
int maxX;
int maxY;
@@ -20,6 +26,7 @@ class TabletSettings {
int reportLength;
double skew;
TabletType type;
+ TabletAuxType auxType;
TabletSettings();
~TabletSettings();
diff --git a/TabletDriverService/Utils.cpp b/TabletDriverService/Utils.cpp
new file mode 100644
index 0000000..b8b1496
--- /dev/null
+++ b/TabletDriverService/Utils.cpp
@@ -0,0 +1,73 @@
+#include "stdafx.h"
+#include "Utils.h"
+
+
+Utils::Utils()
+{
+
+}
+
+
+Utils::~Utils()
+{
+
+}
+
+template
+void Utils::split(const std::string &s, char delim, Out result, bool addEmpty) {
+ std::stringstream ss;
+ ss.str(s);
+ std::string item;
+ while (std::getline(ss, item, delim)) {
+ if (item != "" || addEmpty)
+ *(result++) = item;
+ }
+}
+
+std::vector Utils::split(const std::string &s, char delim, bool addEmpty) {
+ std::vector elems;
+ split(s, delim, std::back_inserter(elems), addEmpty);
+ return elems;
+}
+
+std::string Utils::join(std::vector v, std::string j) {
+ std::string result = "";
+ int count = 0;
+ int size = v.size();
+ for (auto it = v.begin(); it != v.end(); it++) {
+ result += *it;
+ if (count < size - 1)
+ result += j;
+ count++;
+ }
+ return result;
+}
+
+void Utils::keyboardShortcutPress(std::vector const& keys)
+{
+ std::vector keyPress;
+
+ for (auto it : keys)
+ {
+ INPUT ip;
+
+ ip.type = INPUT_KEYBOARD;
+ ip.ki.wScan = 0;
+ ip.ki.time = 0;
+ ip.ki.dwExtraInfo = 0;
+
+ ip.ki.wVk = it;
+ ip.ki.dwFlags = 0;
+
+ keyPress.push_back(ip);
+ }
+ for (auto it : keyPress)
+ {
+ SendInput(1, &it, sizeof(INPUT));
+ }
+ for (int i = 0; i < (int)keyPress.size(); ++i)
+ {
+ keyPress[i].ki.dwFlags = KEYEVENTF_KEYUP;
+ SendInput(1, &keyPress[i], sizeof(INPUT));
+ }
+}
\ No newline at end of file
diff --git a/TabletDriverService/Utils.h b/TabletDriverService/Utils.h
new file mode 100644
index 0000000..e35311c
--- /dev/null
+++ b/TabletDriverService/Utils.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include
+#include
+#include
+
+class Utils
+{
+public:
+ Utils();
+ ~Utils();
+
+ template
+ static void split(const std::string &s, char delim, Out result, bool addEmpty = false);
+ static std::vector split(const std::string &s, char delim, bool addEmpty = false);
+
+ static std::string join(std::vector, std::string);
+
+ static void keyboardShortcutPress(std::vector const& keys);
+};
+
diff --git a/TabletDriverService/config/tablet.cfg b/TabletDriverService/config/tablet.cfg
index b0646f3..6107cdb 100644
--- a/TabletDriverService/config/tablet.cfg
+++ b/TabletDriverService/config/tablet.cfg
@@ -117,6 +117,7 @@ InitFeature 0x02 0x02
# Wacom CTL-480
#
Tablet 0x056a 0x030e 0xFF0D 0x0001
+HIDAux 0x056a 0x030e 0xFF00 0x0080 Wacom480
Name "Wacom CTL-480"
ReportId 0x02
ReportLength 10
@@ -133,6 +134,7 @@ InitFeature 0x02 0x02
# Wacom CTH-480
#
Tablet 0x056a 0x0302 0xFF0D 0x0001
+HIDAux 0x056a 0x0302 0xFF00 0x0080 Wacom480
Name "Wacom CTH-480"
ReportId 0x02
ReportLength 10