1 //
2 // Copyright (c) 2010-2021 Antmicro
3 // Copyright (c) 2011-2015 Realtime Embedded
4 //
5 // This file is licensed under the MIT License.
6 // Full license text is available in 'licenses/MIT.txt'.
7 //
8 using System;
9 using System.Runtime.InteropServices;
10 using Xwt;
11 using Antmicro.Renode.Logging;
12 using Antmicro.Renode.Extensions.Analyzers.Video.Handlers;
13 
14 namespace Antmicro.Renode.Extensions.Analyzers.Video.Events
15 {
16     internal class XWTEventSource : IEventSource
17     {
XWTEventSource(Widget source)18         public XWTEventSource(Widget source)
19         {
20             this.source = source;
21         }
22 
AttachHandler(IOHandler h)23         public void AttachHandler(IOHandler h)
24         {
25             handler = h;
26 
27             source.MouseMoved += HandleMouseMoved;
28             source.ButtonPressed += HandleButtonPressed;
29             source.ButtonReleased += HandleButtonReleased;
30             source.KeyPressed += HandleKeyPressed;
31             source.KeyReleased += HandleKeyReleased;
32         }
33 
HandleKeyReleased(object sender, KeyEventArgs e)34         private void HandleKeyReleased(object sender, KeyEventArgs e)
35         {
36 #if !GUI_DISABLED
37             e.Handled = true;
38 #if PLATFORM_WINDOWS
39             var keyboardLayout = GetKeyboardLayout(0);
40             var vks = VkKeyScanEx((char)e.Key, keyboardLayout);
41             var vsc = MapVirtualKeyEx((uint)vks & 0xff, MAPVK_VK_TO_VSC, keyboardLayout);
42             var key = WPFToKeyScanCodeConverter.Instance.GetScanCode((int)vsc, e.Key);
43 #else
44             var entryKey = Gdk.Keymap.Default.GetEntriesForKeyval((uint)e.Key)[0].Keycode;
45 
46             var key = X11ToKeyScanCodeConverter.Instance.GetScanCode((int)entryKey);
47 #endif // !PLATFORM_WINDOWS
48             if(key != null)
49             {
50                 handler.KeyReleased(key.Value);
51                 return;
52             }
53 #endif // !GUI_DISABLED
54             Logger.LogAs(this, LogLevel.Warning, "Unhandled keycode: {0}", e.Key);
55         }
56 
HandleKeyPressed(object sender, KeyEventArgs e)57         private void HandleKeyPressed(object sender, KeyEventArgs e)
58         {
59 #if !GUI_DISABLED
60             e.Handled = true;
61 #if PLATFORM_WINDOWS
62             var keyboardLayout = GetKeyboardLayout(0);
63             var vks = VkKeyScanEx((char)e.Key, keyboardLayout);
64             var vsc = MapVirtualKeyEx((uint)vks & 0xff, MAPVK_VK_TO_VSC, keyboardLayout);
65             var key = WPFToKeyScanCodeConverter.Instance.GetScanCode((int)vsc, e.Key);
66 #else
67             var entryKey = Gdk.Keymap.Default.GetEntriesForKeyval((uint)e.Key)[0].Keycode;
68 
69             var key = X11ToKeyScanCodeConverter.Instance.GetScanCode((int)entryKey);
70 #endif // !PLATFORM_WINDOWS
71             if(key != null)
72             {
73                 handler.KeyPressed(key.Value);
74                 return;
75             }
76 #endif // !GUI_DISABLED
77             Logger.LogAs(this, LogLevel.Warning, "Unhandled keycode: {0}", e.Key);
78         }
79 
HandleButtonReleased(object sender, ButtonEventArgs e)80         private void HandleButtonReleased(object sender, ButtonEventArgs e)
81         {
82             if(!e.Handled)
83             {
84                 handler.ButtonReleased(e.Button);
85                 e.Handled = true;
86             }
87         }
88 
HandleButtonPressed(object sender, ButtonEventArgs e)89         private void HandleButtonPressed(object sender, ButtonEventArgs e)
90         {
91             if(!e.Handled)
92             {
93                 handler.ButtonPressed(e.Button);
94                 e.Handled = true;
95             }
96         }
97 
HandleMouseMoved(object sender, MouseMovedEventArgs e)98         private void HandleMouseMoved(object sender, MouseMovedEventArgs e)
99         {
100             if(lastX == null || lastY == null)
101             {
102                 lastX = (int)e.X;
103                 lastY = (int)e.Y;
104                 return;
105             }
106 
107             handler.MouseMoved((int)e.X, (int)e.Y, lastX.Value - (int)e.X, lastY.Value - (int)e.Y);
108             lastX = (int)e.X;
109             lastY = (int)e.Y;
110         }
111 
DetachHandler()112         public void DetachHandler()
113         {
114             source.MouseMoved -= HandleMouseMoved;
115             source.ButtonPressed -= HandleButtonPressed;
116             source.ButtonReleased -= HandleButtonReleased;
117             source.KeyPressed -= HandleKeyPressed;
118             source.KeyReleased -= HandleKeyReleased;
119 
120             handler = null;
121         }
122 
123         private Widget source;
124         private IOHandler handler;
125 
126         private int? lastX;
127         private int? lastY;
128 
129         public int X { get { return lastX ?? 0; } }
130         public int Y { get { return lastY ?? 0; } }
131 
132 #if PLATFORM_WINDOWS
133         [DllImport("user32.dll")]
MapVirtualKeyEx(uint uCode, uint uMapType, IntPtr dwhkl)134         private static extern uint MapVirtualKeyEx(uint uCode, uint uMapType, IntPtr dwhkl);
135         [DllImport("user32.dll")]
MapVirtualKeyW(uint uCode, uint uMapType)136         private static extern uint MapVirtualKeyW(uint uCode, uint uMapType);
137         [DllImport("user32.dll")]
GetKeyboardLayout(uint idThread)138         private static extern IntPtr GetKeyboardLayout(uint idThread);
139         [System.Runtime.InteropServices.DllImport("user32.dll")]
VkKeyScan(char ch)140         private static extern short VkKeyScan(char ch);
141         [System.Runtime.InteropServices.DllImport("user32.dll")]
VkKeyScanEx(char ch, IntPtr dwhkl)142         private static extern short VkKeyScanEx(char ch, IntPtr dwhkl);
143 
144         private const uint MAPVK_VK_TO_VSC = 0x00;
145         private const uint MAPVK_VSC_TO_VK = 0x01;
146         private const uint MAPVK_VK_TO_CHAR = 0x02;
147         private const uint MAPVK_VSC_TO_VK_EX = 0x03;
148         private const uint MAPVK_VK_TO_VSC_EX = 0x04;
149 #endif
150     }
151 }
152