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