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 using Antmicro.Renode.Extensions.Analyzers.Video.Events;
12 
13 namespace Antmicro.Renode.Extensions.Analyzers.Video.Handlers
14 {
15     internal class IOHandler
16     {
IOHandler(FrameBufferDisplayWidget widget)17         public IOHandler(FrameBufferDisplayWidget widget)
18         {
19             this.widget = widget;
20             this.source = new XWTEventSource(widget);
21             this.source.AttachHandler(this);
22         }
23 
24         public event Func<bool> GrabConfirm;
25 
26         public event Action<PointerHandler, PointerHandler> PointerInputAttached;
27 
MouseMoved(int x, int y, int dx, int dy)28         public void MouseMoved(int x, int y, int dx, int dy)
29         {
30             // The frame buffer analyzer widget must be focused
31             // in order to receive IO events.
32             // Normally pointer devices are responsible for
33             // handling focus (either by grabbing X11 events
34             //                 or by calling SetFocus() when needed).
35             // When there is no pointer device attached,
36             // we fallback to focusing the widget every
37             // time the mouse cursor is moved over it.
38             if(pointerHandler == null && !widget.HasFocus)
39             {
40                 widget.CanGetFocus = true;
41                 widget.SetFocus();
42             }
43 
44             var ph = pointerHandler;
45             if(ph != null && status != Status.NotGrabbed)
46             {
47                 ph.PointerMoved(x, y, dx, dy);
48             }
49         }
50 
ButtonPressed(PointerButton button)51         public void ButtonPressed(PointerButton button)
52         {
53             var ph = pointerHandler;
54             if(ph != null)
55             {
56                 if(status == Status.NotGrabbed && button == PointerButton.Left)
57                 {
58                     var gc = GrabConfirm;
59                     if(gc != null && !gc())
60                     {
61                         return;
62                     }
63 
64                     source.DetachHandler();
65                     source = new X11EventSource(widget);
66                     source.AttachHandler(this);
67                     status = Status.Grabbed;
68                     return;
69                 }
70 
71                 ph.ButtonPressed((int)button);
72             }
73         }
74 
ButtonReleased(PointerButton button)75         public void ButtonReleased(PointerButton button)
76         {
77             var ph = pointerHandler;
78             if(ph != null)
79             {
80                 ph.ButtonReleased((int)button);
81             }
82         }
83 
KeyPressed(KeyScanCode key)84         public void KeyPressed(KeyScanCode key)
85         {
86             var kh = keyboardHandler;
87 
88             lalt |= (key == KeyScanCode.AltL);
89             lctrl |= (key == KeyScanCode.CtrlL);
90             lshift |= (key == KeyScanCode.ShiftL);
91 
92             if(lctrl && lalt && lshift)
93             {
94                 lalt = false;
95                 lctrl = false;
96                 lshift = false;
97 
98                 if(status == Status.Grabbed)
99                 {
100                     // ask if we should grab
101                     source.DetachHandler();
102                     source = new XWTEventSource(widget);
103                     source.AttachHandler(this);
104                     status = Status.NotGrabbed;
105                 }
106 
107                 if(kh != null)
108                 {
109                     kh.Release(KeyScanCode.AltL);
110                     kh.Release(KeyScanCode.CtrlL);
111                     kh.Release(KeyScanCode.ShiftL);
112                 }
113                 return;
114             }
115 
116             if(kh != null)
117             {
118                 kh.Press(key);
119             }
120         }
121 
KeyReleased(KeyScanCode key)122         public void KeyReleased(KeyScanCode key)
123         {
124             lalt &= (key != KeyScanCode.AltL);
125             lctrl &= (key != KeyScanCode.CtrlL);
126             lshift &= (key != KeyScanCode.ShiftL);
127 
128             var kh = keyboardHandler;
129             if(kh != null)
130             {
131                 kh.Release(key);
132             }
133         }
134 
Attach(IPointerInput pointer = null, IKeyboard keyboard = null)135         public void Attach(IPointerInput pointer = null, IKeyboard keyboard = null)
136         {
137             if(pointer != null)
138             {
139                 var previousPointerHandler = pointerHandler;
140 
141                 if(pointer is IRelativePositionPointerInput)
142                 {
143                     status = Status.NotGrabbed;
144                     pointerHandler = new RelativePointerHandler((IRelativePositionPointerInput)pointer);
145                 }
146                 else if(pointer is IAbsolutePositionPointerInput)
147                 {
148                     status = Status.NotGrabbable;
149                     pointerHandler = new AbsolutePointerHandler((IAbsolutePositionPointerInput)pointer, widget);
150                 }
151 
152                 var pia = PointerInputAttached;
153                 if(pia != null)
154                 {
155                     pia(pointerHandler, previousPointerHandler);
156                 }
157             }
158 
159             if(keyboard != null)
160             {
161                 keyboardHandler = keyboard;
162             }
163         }
164 
Detach(bool pointer = false, bool keyboard = false)165         public void Detach(bool pointer = false, bool keyboard = false)
166         {
167             if(pointer)
168             {
169                 pointerHandler = null;
170             }
171 
172             if(keyboard)
173             {
174                 keyboardHandler = null;
175             }
176         }
177 
GetPosition(out Position current, out Position previous)178         public void GetPosition(out Position current, out Position previous)
179         {
180             previous = this.previous;
181 
182             var pointerHandlerAsAbsolutePointerHandler = pointerHandler as AbsolutePointerHandler;
183             if(pointerHandlerAsAbsolutePointerHandler != null)
184             {
185                 current = new Position
186                 {
187                     X = pointerHandlerAsAbsolutePointerHandler.X,
188                     Y = pointerHandlerAsAbsolutePointerHandler.Y
189                 };
190             }
191             else
192             {
193                 current = null;
194             }
195 
196             this.previous = current;
197         }
198 
Init()199         public void Init()
200         {
201             var ph = pointerHandler;
202             if(ph != null)
203             {
204                 ph.Init();
205             }
206         }
207 
208         private PointerHandler pointerHandler;
209         private IKeyboard keyboardHandler;
210 
211         private IEventSource source;
212         private FrameBufferDisplayWidget widget;
213 
214         private bool lctrl;
215         private bool lalt;
216         private bool lshift;
217 
218         private Position previous;
219 
220         private Status status;
221 
222         public class Position
223         {
224             public int X { get; set; }
225             public int Y { get; set; }
226 
Clone()227             public Position Clone()
228             {
229                 return new Position { X = this.X, Y = this.Y };
230             }
231         }
232 
233         private enum Status
234         {
235             Grabbed,
236             NotGrabbable,
237             NotGrabbed
238         }
239     }
240 }
241