1 //
2 // Copyright (c) 2010-2018 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 Antmicro.Renode.Peripherals.Input;
10 using Xwt;
11 
12 namespace Antmicro.Renode.Extensions.Analyzers.Video.Handlers
13 {
14     internal class AbsolutePointerHandler : PointerHandler
15     {
AbsolutePointerHandler(IAbsolutePositionPointerInput tablet, FrameBufferDisplayWidget widget)16         public AbsolutePointerHandler(IAbsolutePositionPointerInput tablet, FrameBufferDisplayWidget widget) : base(tablet)
17         {
18             this.widget = widget;
19             previousCursorType = widget.Cursor;
20             // it looks strange, but without it handling cursor for the first time causes glitches
21             ShowCursor();
22         }
23 
Init()24         public override void Init()
25         {
26             // this will hide cursor and draw cross if needed
27             PointerMoved(lastX, lastY, 0, 0);
28         }
29 
ButtonReleased(int button)30         public override void ButtonReleased(int button)
31         {
32             base.ButtonReleased(button);
33             if(isCursorOverImageRectangle)
34             {
35                 HideCursor();
36             }
37         }
38 
PointerMoved(int x, int y, int dx, int dy)39         public override void PointerMoved(int x, int y, int dx, int dy)
40         {
41             lastX = x;
42             lastY = y;
43 
44             var image = widget.Image;
45             if(image == null)
46             {
47                 return;
48             }
49 
50             var ainput = (IAbsolutePositionPointerInput)input;
51             var imgRect = widget.ActualImageArea;
52 
53             // if cursor doesn't touch actual image, return
54             if(!imgRect.IntersectsWith(new Rectangle(x, y, 1, 1)))
55             {
56                 ShowCursor();
57                 isCursorOverImageRectangle = false;
58                 return;
59             }
60             if(!isCursorOverImageRectangle)
61             {
62                 widget.CanGetFocus = true;
63                 widget.SetFocus();
64                 isCursorOverImageRectangle = true;
65                 HideCursor();
66             }
67 
68             //  this fragment converts click-point coordinates:
69             //  from
70             //     FrameBufferAnalyzer coordinates system (i.e., XWT coordinates of canvas on which the buffer was drawn)
71             //  through
72             //     Buffer coordinates system (i.e., resolution set on emulated graphic card)
73             //  to
74             //     Touchscreen coordinates system
75             var maxX = (int)image.Width;
76             var maxY = (int)image.Height;
77 
78             var imageX = ((x - imgRect.X) / imgRect.Width) * maxX;
79             var imageY = ((y - imgRect.Y) / imgRect.Height) * maxY;
80 
81             X = (int)imageX;
82             Y = (int)imageY;
83 
84             var touchscreenX = (int)Math.Round(imageX * ainput.MaxX / maxX);
85             var touchscreenY = (int)Math.Round(imageY * ainput.MaxY / maxY);
86 
87             ainput.MoveTo(touchscreenX, touchscreenY);
88 
89             var opm = OnPointerMoved;
90             if(opm != null)
91             {
92                 opm(X, Y);
93             }
94         }
95 
96         public int X { get; protected set; }
97         public int Y { get; protected set; }
98 
99         public event Action<int, int> OnPointerMoved;
100 
HideCursor()101         private void HideCursor()
102         {
103             if(widget.Cursor == CursorType.Invisible)
104             {
105                 return;
106             }
107             previousCursorType = widget.Cursor;
108             widget.Cursor = CursorType.Invisible;
109         }
110 
ShowCursor()111         private void ShowCursor()
112         {
113             widget.Cursor = previousCursorType;
114         }
115 
116         private int lastX, lastY;
117         private CursorType previousCursorType;
118         private readonly FrameBufferDisplayWidget widget;
119         private bool isCursorOverImageRectangle;
120     }
121 }
122 
123