1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Robert TIMM (rti) <mail@rtti.de>
6 // Copyright (C) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "nel/misc/events.h"
24 #include "nel/misc/event_emitter.h"
25 #include "nel/misc/win_event_emitter.h"
26 #include "nel/misc/event_server.h"
27 #include "nel/misc/utf_string_view.h"
33 * Needed for definition of WM_MOUSEWHEEL. It should be in winuser.h
34 * but not under win98.. strange..
44 /*------------------------------------------------------------------*\
46 \*------------------------------------------------------------------*/
47 void CWinEventEmitter::submitEvents(CEventServer
& server
, bool allWindows
)
50 while ( PeekMessageW(&msg
,allWindows
?NULL
:_HWnd
,0,0,PM_REMOVE
) )
52 TranslateMessage(&msg
);
53 DispatchMessageW(&msg
);
56 // Dispatch sent messages
57 _InternalServer
.setServer (&server
);
58 _InternalServer
.pump (allWindows
);
61 /*------------------------------------------------------------------*\
63 \*------------------------------------------------------------------*/
66 TKeyButton
getKeyButton (bool _altButton
, bool _shiftButton
, bool _ctrlButton
)
68 TKeyButton button
=noKeyButton
;
70 (int&)button
|=altKeyButton
;
72 (int&)button
|=shiftKeyButton
;
74 (int&)button
|=ctrlKeyButton
;
79 /*TMouseButton getMouseButton (uint32 wParam, bool _altButton)
81 TMouseButton button=noButton;
82 if (wParam&MK_CONTROL)
83 (int&)button|=ctrlButton;
84 if (wParam&MK_LBUTTON)
85 (int&)button|=leftButton;
86 if (wParam&MK_RBUTTON)
87 (int&)button|=rightButton;
88 if (wParam&MK_MBUTTON)
89 (int&)button|=middleButton;
91 (int&)button|=shiftButton;
93 (int&)button|=altButton;
97 TMouseButton
CWinEventEmitter::getButtons() const
99 uint result
= (_CtrlButton
? ctrlButton
: 0)
100 | (_AltButton
? altButton
: 0)
101 | (_ShiftButton
? shiftButton
: 0)
102 | (_CtrlButton
? ctrlButton
: 0)
103 | (_MouseButtons
[0] ? leftButton
: 0)
104 | (_MouseButtons
[1] ? rightButton
: 0)
105 | (_MouseButtons
[2] ? middleButton
: 0);
106 return (TMouseButton
) result
;
110 bool CWinEventEmitter::processMessage (HWND hWnd
, uint32 msg
, WPARAM wParam
, LPARAM lParam
, CEventServer
*server
)
113 server
=&_InternalServer
;
115 /// Process IME messages
116 /*if ( _IMEEventsEnabled && (ImmIsUIMessage( ImmGetDefaultIMEWnd((HWND)_HWnd), msg, wParam, lParam) == TRUE) )
118 server->postEvent( new CEventIME(msg, wParam, lParam, this) );
119 return true; // trap message (however DefWindowProc will still be called in some instances by the event listener)
126 if (_KeyboardEventsEnabled
)
128 // Ctrl, shit or alt ?
129 if ((sint
)wParam
==VK_MENU
)
131 if ((sint
)wParam
==VK_CONTROL
)
133 if ((sint
)wParam
==VK_SHIFT
)
137 if (wParam
< KeyCount
)
138 server
->postEvent (new CEventKeyDown ((NLMISC::TKey
)wParam
, getKeyButton(_AltButton
, _ShiftButton
, _CtrlButton
), (((int) lParam
)&(1<<30))==0, this));
144 if (_KeyboardEventsEnabled
)
146 // Ctrl, shit or alt ?
147 if ((int)wParam
==VK_MENU
)
149 if ((int)wParam
==VK_CONTROL
)
151 if ((int)wParam
==VK_SHIFT
)
154 // As Print Screen button does not trigger a WM_KEYDOWN msg, simulate it here
155 if ((int)wParam
==VK_SNAPSHOT
)
157 if (wParam
< KeyCount
)
158 server
->postEvent (new CEventKeyDown ((NLMISC::TKey
)wParam
, getKeyButton(_AltButton
, _ShiftButton
, _CtrlButton
), true, this));
162 if (wParam
< KeyCount
)
163 server
->postEvent (new CEventKeyUp ((NLMISC::TKey
)wParam
, getKeyButton(_AltButton
, _ShiftButton
, _CtrlButton
), this));
168 if (wParam
!= UNICODE_NOCHAR
&& _KeyboardEventsEnabled
)
170 //if (wParam < KeyCount)
171 //nlinfo("WM_UNICHAR with %u", wParam);
172 server
->postEvent (new CEventChar ((u32char
)wParam
, getKeyButton(_AltButton
, _ShiftButton
, _CtrlButton
), this));
177 if (_KeyboardEventsEnabled
)
179 //if (wParam < KeyCount)
180 //nlinfo("WM_CHAR with %u", wParam);
181 wchar_t c
= (wchar_t)wParam
;
182 if ((c
& 0xFC00) == 0xD800)
186 else if (_Utf16Pair
&& (c
& 0xFC00) == 0xDC00)
188 wchar_t cc
[] = { _Utf16Pair
, c
, 0 };
190 CUtfStringView cv
= CUtfStringView(cc
);
191 for (CUtfStringView::iterator
it(cv
.begin()), end(cv
.end()); it
!= end
; ++it
)
192 server
->postEvent(new CEventChar(*it
, getKeyButton(_AltButton
, _ShiftButton
, _CtrlButton
), this));
198 server
->postEvent(new CEventChar(_Utf16Pair
, getKeyButton(_AltButton
, _ShiftButton
, _CtrlButton
), this));
201 server
->postEvent(new CEventChar(c
, getKeyButton(_AltButton
, _ShiftButton
, _CtrlButton
), this));
206 if (_KeyboardEventsEnabled && _IMEEventsEnabled)
208 server->postEvent (new CEventChar ((ucchar)wParam, getKeyButton(_AltButton, _ShiftButton, _CtrlButton), this));
212 if (WA_INACTIVE
==LOWORD(wParam
))
213 server
->postEvent (new CEventActivate (false, this));
217 resetButtonFlagState ();
220 server
->postEvent (new CEventActivate (true, this));
224 server
->postEvent (new CEventSetFocus (false, this));
228 resetButtonFlagState ();
231 server
->postEvent (new CEventSetFocus (true, this));
240 case WM_RBUTTONDBLCLK
:
241 case WM_MBUTTONDBLCLK
:
242 case WM_LBUTTONDBLCLK
:
244 if (_MouseEventsEnabled
)
246 // MSWindows coordinates to NeL window coordinate
250 float xPos
= (float)GET_X_LPARAM(lParam
);
251 float yPos
= (float)GET_Y_LPARAM(lParam
);
253 GetClientRect (hWnd
, &client
);
254 fX
=xPos
/(float)(client
.right
-client
.left
);
255 fY
=1.f
-yPos
/(float)(client
.bottom
-client
.top
);
258 TMouseButton button
=getButtons();
264 server
->postEvent (new CEventMouseMove (fX
, fY
, button
, this));
268 _MouseButtons
[1] = true;
269 server
->postEvent (new CEventMouseDown (fX
, fY
, (TMouseButton
)(rightButton
|(button
&~(leftButton
|middleButton
|rightButton
))), this));
272 _MouseButtons
[2] = true;
273 server
->postEvent (new CEventMouseDown (fX
, fY
, (TMouseButton
)(middleButton
|(button
&~(leftButton
|middleButton
|rightButton
))), this));
276 _MouseButtons
[0] = true;
277 server
->postEvent (new CEventMouseDown (fX
, fY
, (TMouseButton
)(leftButton
|(button
&~(leftButton
|middleButton
|rightButton
))), this));
281 _MouseButtons
[1] = false;
282 server
->postEvent (new CEventMouseUp (fX
, fY
, (TMouseButton
)(rightButton
|(button
&~(leftButton
|middleButton
|rightButton
))), this));
285 _MouseButtons
[2] = false;
286 server
->postEvent (new CEventMouseUp (fX
, fY
, (TMouseButton
)(middleButton
|(button
&~(leftButton
|middleButton
|rightButton
))), this));
289 _MouseButtons
[0] = false;
290 server
->postEvent (new CEventMouseUp (fX
, fY
, (TMouseButton
)(leftButton
|(button
&~(leftButton
|middleButton
|rightButton
))), this));
293 case WM_RBUTTONDBLCLK
:
294 server
->postEvent (new CEventMouseDblClk (fX
, fY
, (TMouseButton
)(rightButton
|(button
&~(leftButton
|middleButton
|rightButton
))), this));
296 case WM_MBUTTONDBLCLK
:
297 server
->postEvent (new CEventMouseDblClk (fX
, fY
, (TMouseButton
)(middleButton
|(button
&~(leftButton
|middleButton
|rightButton
))), this));
299 case WM_LBUTTONDBLCLK
:
300 server
->postEvent (new CEventMouseDblClk (fX
, fY
, (TMouseButton
)(leftButton
|(button
&~(leftButton
|middleButton
|rightButton
))), this));
308 server
->postEvent (new CEventDestroyWindow (this));
311 server
->postEvent (new CEventCloseWindow (this));
313 case WM_DISPLAYCHANGE
:
314 server
->postEvent (new CEventDisplayChange (LOWORD(lParam
), HIWORD(lParam
), (uint
)wParam
, this));
317 if (_MouseEventsEnabled
)
319 // MSWindows coordinates to NeL window coordinate
322 GetClientRect (hWnd
, &client
);
323 if (client
.right
-client
.left
> 0)
324 fX
=(float)LOWORD(lParam
)/(float)(client
.right
-client
.left
);
327 if (client
.bottom
-client
.top
> 0)
328 fY
=1.f
-(float)HIWORD(lParam
)/(float)(client
.bottom
-client
.top
);
333 TMouseButton button
=getButtons();
335 server
->postEvent (new CEventMouseWheel (fX
, fY
, button
, (short) HIWORD(wParam
)>=0, this));
338 case WM_IME_SETCONTEXT
:
339 case WM_IME_STARTCOMPOSITION
:
340 case WM_IME_COMPOSITION
:
341 case WM_IME_ENDCOMPOSITION
:
343 //case WM_INPUTLANGCHANGEREQUEST:
344 case WM_INPUTLANGCHANGE
:
345 if ( _IMEEventsEnabled
)
347 // wParam = Specifies the character set of the new locale.
348 // lParam = Input locale identifier.
349 server
->postEvent( new CEventIME( msg
, (uint32
)wParam
, (uint32
)lParam
, this ) );
350 return true; // trap message
357 //==========================================================
358 void CWinEventEmitter::resetButtonFlagState ()
360 _CtrlButton
=( (GetAsyncKeyState(VK_CONTROL
)&0x8000) != 0);
361 _ShiftButton
=( (GetAsyncKeyState(VK_SHIFT
)&0x8000) != 0);
362 _AltButton
=( (GetAsyncKeyState(VK_MENU
)&0x8000) != 0);
364 _MouseButtons
[0]=( (GetAsyncKeyState(VK_LBUTTON
)&0x8000) != 0);
365 _MouseButtons
[1]=( (GetAsyncKeyState(VK_RBUTTON
)&0x8000) != 0);
366 _MouseButtons
[2]=( (GetAsyncKeyState(VK_MBUTTON
)&0x8000) != 0);
372 //==========================================================
373 TMouseButton
CWinEventEmitter::buildFlags() const
375 uint flags
= (_CtrlButton
? ctrlButton
: 0)
376 | (_ShiftButton
? shiftButton
: 0)
377 | (_AltButton
? altButton
: 0)
378 | (_MouseButtons
[0] ? leftButton
: 0)
379 | (_MouseButtons
[1] ? rightButton
: 0)
380 | (_MouseButtons
[2] ? middleButton
: 0);
381 return (TMouseButton
) flags
;
387 #endif // NL_OS_WINDOWS