Usermode/AxWin4 - Send mouse/keyboard events to client
[tpg/acess2.git] / Usermode / Applications / axwin4_src / Server / input.cpp
1 /*
2  * Acess2 GUI v4
3  * - By John Hodge (thePowersGang)
4  *
5  * input.cpp
6  * - Input
7  */
8 #include <CConfigInput.hpp>
9 #include <input.hpp>
10 #include <CCompositor.hpp>
11 #include <algorithm>
12 #include <acess/devices/joystick.h>
13 #include <cerrno>
14 #include <system_error>
15
16 namespace AxWin {
17
18 CInput::CInput(const ::AxWin::CConfigInput& config, CCompositor& compositor):
19         m_compositor(compositor),
20         m_keyboardFD(0),
21         m_mouseFD(-1)
22 {
23         m_mouseFD = _SysOpen(config.mouse_device.c_str(), OPENFLAG_READ|OPENFLAG_WRITE);
24         if( m_mouseFD == -1 )
25                 throw ::std::system_error(errno, ::std::system_category());
26         
27         m_mouseX = 640/2;
28         m_mouseY = 480/2;
29         
30         struct mouse_attribute  attr;
31         // X : Limit + Position
32         attr.Num = 0;
33         attr.Value = 640;
34         _SysIOCtl(m_mouseFD, JOY_IOCTL_GETSETAXISLIMIT, &attr);
35         attr.Value = m_mouseX;
36         _SysIOCtl(m_mouseFD, JOY_IOCTL_GETSETAXISPOSITION, &attr);
37         // Y: Limit + Position
38         attr.Num = 1;
39         attr.Value = 480;
40         _SysIOCtl(m_mouseFD, JOY_IOCTL_GETSETAXISLIMIT, &attr);
41         attr.Value = m_mouseY;
42         _SysIOCtl(m_mouseFD, JOY_IOCTL_GETSETAXISPOSITION, &attr);
43 }
44
45 int CInput::FillSelect(::fd_set& rfds)
46 {
47         FD_SET(m_keyboardFD, &rfds);
48         if( m_mouseFD != -1 )
49                 FD_SET(m_mouseFD, &rfds);
50         return ::std::max(m_keyboardFD, m_mouseFD)+1;
51 }
52
53 void CInput::HandleSelect(::fd_set& rfds)
54 {
55         if( FD_ISSET(m_keyboardFD, &rfds) )
56         {
57                 uint32_t        codepoint;
58                 static uint32_t scancode;
59                 #define KEY_CODEPOINT_MASK      0x3FFFFFFF
60                 
61                 size_t readlen = _SysRead(m_keyboardFD, &codepoint, sizeof(codepoint));
62                 if( readlen != sizeof(codepoint) )
63                 {
64                         // oops, error
65                         _SysDebug("Terminal read failed? (%i != %i)", readlen, sizeof(codepoint));
66                 }
67         
68 //              _SysDebug("Keypress 0x%x", codepoint);
69         
70                 switch(codepoint & 0xC0000000)
71                 {
72                 case 0x00000000:        // Key pressed
73                         m_compositor.KeyState(0, scancode, true, codepoint & KEY_CODEPOINT_MASK);
74                         break;
75                 case 0x40000000:        // Key release
76                         m_compositor.KeyState(0, scancode, false, codepoint & KEY_CODEPOINT_MASK);
77                         scancode = 0;
78                         break;
79                 case 0x80000000:        // Key refire
80                         m_compositor.KeyState(0, scancode, true, codepoint & KEY_CODEPOINT_MASK);
81                         scancode = 0;
82                         break;
83                 case 0xC0000000:        // Raw scancode
84                         scancode = codepoint & KEY_CODEPOINT_MASK;
85                         break;
86                 }
87         }
88         
89         if( m_mouseFD != -1 && FD_ISSET(m_mouseFD, &rfds) )
90         {
91                 const int c_n_axies = 4;
92                 const int c_n_buttons = 5;
93                 struct mouse_axis       *axies;
94                 uint8_t *buttons;
95
96                 char data[sizeof(struct mouse_header) + sizeof(*axies)*c_n_axies + c_n_buttons];
97                 struct mouse_header     *mouseinfo = (struct mouse_header*)data;
98
99                 _SysSeek(m_mouseFD, 0, SEEK_SET);
100                 int len = _SysRead(m_mouseFD, data, sizeof(data));
101                 if( len < 0 )
102                         throw ::std::system_error(errno, ::std::system_category());
103                 
104                 len -= sizeof(*mouseinfo);
105                 if( len < 0 ) {
106                         _SysDebug("Mouse data undersized (%i bytes short on header)", len);
107                         return ;
108                 }
109                 if( mouseinfo->NAxies > c_n_axies || mouseinfo->NButtons > c_n_buttons ) {
110                         _SysDebug("%i axies, %i buttons above prealloc counts (%i, %i)",
111                                 mouseinfo->NAxies, mouseinfo->NButtons, c_n_axies, c_n_buttons
112                                 );
113                         return ;
114                 }
115                 if( len < sizeof(*axies)*mouseinfo->NAxies + mouseinfo->NButtons ) {
116                         _SysDebug("Mouse data undersized (body doesn't fit %i < %i)",
117                                 len, sizeof(*axies)*mouseinfo->NAxies + mouseinfo->NButtons
118                                 );
119                         return ;
120                 }
121
122                 // What? No X/Y?
123                 if( mouseinfo->NAxies < 2 ) {
124                         _SysDebug("Mouse data lacks X/Y");
125                         return ;
126                 }
127         
128                 axies = (struct mouse_axis*)( mouseinfo + 1 );
129                 buttons = (uint8_t*)( axies + mouseinfo->NAxies );
130
131                 // TODO: Use cursor range only to caputre motion (ignore reported position)
132                 m_compositor.MouseMove(0,
133                         m_mouseX, m_mouseY,
134                         axies[0].CursorPos - m_mouseX, axies[1].CursorPos - m_mouseY
135                         );
136                 m_mouseX = axies[0].CursorPos;
137                 m_mouseY = axies[1].CursorPos;
138
139                 for( int i = 0; i < mouseinfo->NButtons; i ++ )
140                 {
141                          int    bit = 1 << i;
142                          int    cur = buttons[i] > 128;
143                         if( !!(m_mouseBtns & bit) != cur )
144                         {
145                                 m_compositor.MouseButton(0, m_mouseX, m_mouseY, (eMouseButton)i, cur);
146                                 // Flip button state
147                                 m_mouseBtns ^= bit;
148                         }
149                 }
150         }
151 }
152
153 };      // namespace AxWin
154

UCC git Repository :: git.ucc.asn.au