OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
PointerHandler.c
Go to the documentation of this file.
1
19#include <AppleMacEfi.h>
20
21#include <Guid/AppleVariable.h>
22
23#include <Protocol/GraphicsOutput.h>
24#include <Protocol/UgaDraw.h>
25#include <Protocol/SimplePointer.h>
26
29#include <Library/BaseLib.h>
30#include <Library/BaseMemoryLib.h>
31#include <Library/DebugLib.h>
32#include <Library/MemoryAllocationLib.h>
33#include <Library/UefiBootServicesTableLib.h>
34#include <Library/UefiLib.h>
35#include <Library/UefiRuntimeServicesTableLib.h>
36#include <Library/TimerLib.h>
37
38#include "AppleEventInternal.h"
39
40#include <Library/BaseLib.h>
41
42//
43// CHANGE: Apple polls with a frequency of 2 ms, however this is infeasible on
44// most machines. Poll with 10 ms, which matches the keyboard behaviour,
45// and also is the minimum for QEMU.
46//
47#define MIN_POINTER_POLL_PERIOD 10
48#define MAX_POINTER_POLL_PERIOD 80
49
50#define MAX_CLICK_DURATION 148 // 74 for 2 ms
51#define MAX_DOUBLE_CLICK_SPEED 748 // 374 for 2 ms
52
53#define MAX_POLL_DURATION ((MAX_UINT32 / 10000) / MAX_DOUBLE_CLICK_SPEED)
54
55GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mPointerSpeedDiv = 0;
56GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mPointerSpeedMul = 0;
57
58STATIC UINT16 mMaximumDoubleClickSpeed = 0;
59STATIC UINT16 mMaximumClickDuration = 0;
60
61// MINIMAL_MOVEMENT
62#define MINIMAL_MOVEMENT 5
63
64// POINTER_BUTTON_INFORMATION
75
76// SIMPLE_POINTER_INSTANCE
77typedef struct {
78 EFI_HANDLE Handle;
79 EFI_SIMPLE_POINTER_PROTOCOL *Interface;
80 BOOLEAN Installed;
82
83// mSimplePointerInstallNotifyEvent
84STATIC EFI_EVENT mSimplePointerInstallNotifyEvent = NULL;
85
86// mSimplePointerInstallNotifyRegistration
88
89// mSimplePointerInstances
91
92// mNoSimplePointerInstances
94
95// mSimplePointerPollEvent
96STATIC EFI_EVENT mSimplePointerPollEvent = NULL;
97
98// mSimplePointerPollTime
99STATIC UINT32 mSimplePointerPollTime = 0;
102
104
105// mUiScale
106STATIC UINT8 mUiScale = 1;
107
108// mLeftButtonInfo
111 0,
112 0,
113 0,
114 FALSE,
115 FALSE,
116 { 0, 0 },
117 { 0, 0 }
118};
119
120// mRightButtonInfo
123 0,
124 0,
125 0,
126 FALSE,
127 FALSE,
128 { 0, 0 },
129 { 0, 0 }
130};
131
132// mCursorPosition
134
135// mMouseMoved
136STATIC BOOLEAN mMouseMoved;
137
138// mScreenResolution
139STATIC DIMENSION mResolution = { 800, 600 };
140
141STATIC UINT64 mMaxPointerResolutionX = 1;
142STATIC UINT64 mMaxPointerResolutionY = 1;
143
144STATIC UINT64 mPointerRawX;
145STATIC UINT64 mPointerRawY;
146
147STATIC UINT32 mDwellClickTimeout;
151STATIC UINT32 mDwellClickTime;
152
153VOID
155 VOID
156 )
157{
158 EFI_STATUS Status;
159 UINTN DataSize;
160
161 DataSize = sizeof (mUiScale);
162 Status = gRT->GetVariable (
165 NULL,
166 &DataSize,
167 (VOID *)&mUiScale
168 );
169 if (EFI_ERROR (Status) || (mUiScale != 2)) {
170 mUiScale = 1;
171 }
172}
173
174VOID
176 IN UINT32 PointerPollMin,
177 IN UINT32 PointerPollMax,
178 IN UINT32 PointerPollMask
179 )
180{
181 if (PointerPollMin == POINTER_POLL_DEFAULT) {
182 PointerPollMin = MIN_POINTER_POLL_PERIOD;
183 } else if (PointerPollMin > MAX_POLL_DURATION) {
184 PointerPollMin = MAX_POLL_DURATION;
185 }
186
187 mSimplePointerMinPollTime = PointerPollMin * 10000;
188
189 mMaximumClickDuration = (UINT16)(MAX_CLICK_DURATION / PointerPollMin);
190 mMaximumDoubleClickSpeed = (UINT16)(MAX_DOUBLE_CLICK_SPEED / PointerPollMin);
191
192 if (PointerPollMax == POINTER_POLL_DEFAULT) {
193 PointerPollMax = MAX_POINTER_POLL_PERIOD;
194 } else if (PointerPollMax > MAX_POLL_DURATION) {
195 PointerPollMax = MAX_POLL_DURATION;
196 }
197
198 mSimplePointerMaxPollTime = PointerPollMax * 10000;
199
200 mSimplePointerPollMask = PointerPollMask;
201}
202
203VOID
205 IN UINT16 PointerSpeedDiv,
206 IN UINT16 PointerSpeedMul
207 )
208{
209 if (PointerSpeedDiv != 0) {
210 mPointerSpeedDiv = PointerSpeedDiv;
211 } else {
212 DEBUG ((
213 DEBUG_WARN,
214 "OCAE: Illegal PointerSpeedDiv value 0, using 1\n",
216 ));
218 }
219
220 mPointerSpeedMul = PointerSpeedMul;
221}
222
223VOID
225 IN UINT16 ClickTimeout,
226 IN UINT16 DoubleClickTimeout,
227 IN UINT16 Radius
228 )
229{
230 mDwellClickTimeout = (UINT32)ClickTimeout * 10000;
231 mDwellDoubleClickTimeout = (UINT32)DoubleClickTimeout * 10000;
232 mDwellClickRadiusSqr = ((UINT32)Radius * Radius) * (mUiScale * mUiScale);
233}
234
235// InternalRegisterSimplePointerInterface
236STATIC
237VOID
239 IN EFI_HANDLE Handle,
240 IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer
241 )
242{
243 SIMPLE_POINTER_INSTANCE *Instance;
244 UINTN Index;
245
246 DEBUG ((DEBUG_VERBOSE, "InternalRegisterSimplePointerInterface\n"));
247
248 Instance = AllocateZeroPool (
249 (mNumberOfPointerProtocols + 1) * sizeof (*Instance)
250 );
251
252 if (Instance != NULL) {
253 //
254 // Apple did not check against NULL here and below as of boot.efi
255 //
256 if (mPointerProtocols != NULL) {
257 CopyMem (
258 Instance,
260 (mNumberOfPointerProtocols * sizeof (*Instance))
261 );
262 }
263
265
267
268 Instance[Index].Handle = Handle;
269 Instance[Index].Interface = SimplePointer;
270 Instance[Index].Installed = TRUE;
271
272 if (mPointerProtocols != NULL) {
273 FreePool ((VOID *)mPointerProtocols);
274 }
275
276 mPointerProtocols = Instance;
277
278 if (SimplePointer->Mode->ResolutionX > mMaxPointerResolutionX) {
282 SimplePointer->Mode->ResolutionX,
283 NULL
284 );
285 mMaxPointerResolutionX = SimplePointer->Mode->ResolutionX;
286 }
287
288 if (SimplePointer->Mode->ResolutionY > mMaxPointerResolutionY) {
292 SimplePointer->Mode->ResolutionY,
293 NULL
294 );
295 mMaxPointerResolutionY = SimplePointer->Mode->ResolutionY;
296 }
297 }
298}
299
300// EventSimplePointerDesctructor
301VOID
303 VOID
304 )
305{
306 DEBUG ((DEBUG_VERBOSE, "EventSimplePointerDesctructor\n"));
307
308 if (mPointerProtocols != NULL) {
309 FreePool ((VOID *)mPointerProtocols);
310 //
311 // Apple did not null the pointer here (not an error)
312 //
313 mPointerProtocols = NULL;
314 }
315}
316
317// InternalRemoveUninstalledInstances
318STATIC
319VOID
321 IN OUT SIMPLE_POINTER_INSTANCE **InstancesPtr,
322 IN UINTN *NumberOfInstances,
323 IN EFI_GUID *Protocol
324 )
325{
326 EFI_STATUS Status;
327 UINTN NumberHandles;
328 EFI_HANDLE *Buffer;
329 SIMPLE_POINTER_INSTANCE *Instance;
330 UINTN Index;
331 UINTN Index2;
332 SIMPLE_POINTER_INSTANCE *OrgInstances;
333 SIMPLE_POINTER_INSTANCE *NewInstances;
334 UINTN NumberOfMatches;
335
336 DEBUG ((DEBUG_VERBOSE, "InternalRemoveUninstalledInstances\n"));
337
338 OrgInstances = *InstancesPtr;
339
340 Status = gBS->LocateHandleBuffer (
341 ByProtocol,
342 Protocol,
343 NULL,
344 &NumberHandles,
345 &Buffer
346 );
347
348 if (!EFI_ERROR (Status)) {
349 if (*NumberOfInstances > 0) {
350 NumberOfMatches = 0;
351
352 for (Index = 0; Index < *NumberOfInstances; ++Index) {
353 Instance = &OrgInstances[Index];
354
355 if (Instance->Installed) {
356 for (Index2 = 0; Index2 < NumberHandles; ++Index2) {
357 if (Instance->Handle == Buffer[Index2]) {
358 ++NumberOfMatches;
359 break;
360 }
361 }
362
363 if (NumberHandles == Index2) {
364 Instance->Installed = FALSE;
365 }
366 }
367 }
368
369 if (NumberOfMatches != *NumberOfInstances) {
370 //
371 // Apple did not check for NumberOfMatches being > 0.
372 //
373 NewInstances = NULL;
374 if (NumberOfMatches > 0) {
375 NewInstances = AllocateZeroPool (
376 NumberOfMatches * sizeof (*NewInstances)
377 );
378 }
379
380 if (NewInstances != NULL) {
381 Index2 = 0;
382 for (Index = 0; Index < *NumberOfInstances; ++Index) {
383 Instance = &OrgInstances[Index];
384 if (Instance->Installed) {
385 CopyMem (
386 (VOID *)&NewInstances[Index2],
387 (VOID *)Instance,
388 sizeof (*Instance)
389 );
390
391 ++Index2;
392 }
393 }
394
395 FreePool (OrgInstances);
396
397 *InstancesPtr = NewInstances;
398 *NumberOfInstances = NumberOfMatches;
399 }
400 }
401 }
402
403 FreePool (Buffer);
404 } else {
405 if (OrgInstances != NULL) {
406 FreePool (OrgInstances);
407 }
408
409 *InstancesPtr = NULL;
410 *NumberOfInstances = 0;
411 }
412}
413
414// InternalSimplePointerInstallNotifyFunction
415STATIC
416VOID
417EFIAPI
419 IN EFI_EVENT Event,
420 IN VOID *Context
421 )
422{
423 EFI_STATUS Status;
424 UINTN NumberHandles;
425 EFI_HANDLE *Buffer;
426 UINTN Index;
427 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
428
429 DEBUG ((DEBUG_VERBOSE, "InternalSimplePointerInstallNotifyFunction\n"));
430
431 if (Event != NULL) {
432 Status = gBS->LocateHandleBuffer (
433 ByRegisterNotify,
434 NULL,
436 &NumberHandles,
437 &Buffer
438 );
439 } else {
440 Status = gBS->LocateHandleBuffer (
441 ByProtocol,
443 NULL,
444 &NumberHandles,
445 &Buffer
446 );
447 }
448
449 if (!EFI_ERROR (Status)) {
450 for (Index = 0; Index < NumberHandles; ++Index) {
451 Status = gBS->HandleProtocol (
452 Buffer[Index],
454 (VOID **)&SimplePointer
455 );
456
457 if (!EFI_ERROR (Status)) {
458 InternalRegisterSimplePointerInterface (Buffer[Index], SimplePointer);
459 }
460 }
461
462 FreePool ((VOID *)Buffer);
463 }
464}
465
466// EventCreateSimplePointerInstallNotifyEvent
467EFI_STATUS
469 VOID
470 )
471{
472 EFI_STATUS Status;
473
474 DEBUG ((DEBUG_VERBOSE, "EventCreateSimplePointerInstallNotifyEvent\n"));
475
476 Status = gBS->CreateEvent (
477 EVT_NOTIFY_SIGNAL,
478 TPL_CALLBACK,
480 NULL,
482 );
483
484 if (!EFI_ERROR (Status)) {
485 Status = gBS->RegisterProtocolNotify (
489 );
490
491 if (EFI_ERROR (Status)) {
493
495 } else {
497 }
498 }
499
500 return Status;
501}
502
503// EventCreateSimplePointerInstallNotifyEvent
504VOID
506 VOID
507 )
508{
509 DEBUG ((DEBUG_VERBOSE, "EventCloseSimplePointerInstallNotifyEvent\n"));
510
513 }
514}
515
516// InternalGetScreenResolution
517STATIC
518VOID
520 VOID
521 )
522{
523 EFI_STATUS Status;
524 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
525 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
526 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
527 UINT32 HorizontalResolution;
528 UINT32 VerticalResolution;
529 UINT32 ColorDepth;
530 UINT32 RefreshRate;
531
532 DEBUG ((DEBUG_VERBOSE, "InternalGetScreenResolution\n"));
533
534 //
535 // CHANGE: Do not cache screen resolution to account for changes.
536 //
537
538 HorizontalResolution = 0;
539 VerticalResolution = 0;
540
541 Status = gBS->HandleProtocol (
542 gST->ConsoleOutHandle,
544 (VOID **)&GraphicsOutput
545 );
546 if (!EFI_ERROR (Status)) {
547 Info = GraphicsOutput->Mode->Info;
548 HorizontalResolution = Info->HorizontalResolution;
549 VerticalResolution = Info->VerticalResolution;
550 } else if (Status == EFI_UNSUPPORTED) {
551 Status = gBS->HandleProtocol (
552 gST->ConsoleOutHandle,
554 (VOID **)&UgaDraw
555 );
556 DEBUG ((
557 DEBUG_INFO,
558 "OCAE: Failed to handle GOP, discovering UGA - %r\n",
559 Status
560 ));
561
562 if (!EFI_ERROR (Status)) {
563 Status = UgaDraw->GetMode (
564 UgaDraw,
565 &HorizontalResolution,
566 &VerticalResolution,
567 &ColorDepth,
568 &RefreshRate
569 );
570 }
571 }
572
573 if (!EFI_ERROR (Status)) {
574 if ((HorizontalResolution > 0) && (VerticalResolution > 0)) {
575 mResolution.Horizontal = (INT32)HorizontalResolution;
576 mResolution.Vertical = (INT32)VerticalResolution;
577
580 }
581
584 }
585
586 DEBUG ((
587 DEBUG_INFO,
588 "OCAE: Set screen resolution to %dx%d - %r\n",
591 Status
592 ));
593 } else {
594 DEBUG ((DEBUG_INFO, "OCAE: Screen resolution has 0-dimension\n"));
595 }
596 } else {
597 DEBUG ((
598 DEBUG_INFO,
599 "OCAE: Failed to get screen resolution - %r\n",
600 Status
601 ));
602 }
603}
604
605// InternalGetUiScaleData
606STATIC
607INT64
609 IN INT64 Movement
610 )
611{
612 INT64 AbsoluteValue;
613 INTN Value;
614 INT64 Factor;
615
616 DEBUG ((DEBUG_VERBOSE, "InternalGetUiScaleData\n"));
617
618 AbsoluteValue = ABS (Movement);
619 Value = HighBitSet64 ((UINT64)(AbsoluteValue));
620 Factor = 5;
621
622 if (Value <= 3) {
623 Factor = (HighBitSet64 ((UINT64)(AbsoluteValue) + 1));
624 }
625
626 return (INT64)(MultS64x64 (
627 (INT64)(INT32)mUiScale,
628 MultS64x64 (Movement, Factor)
629 ));
630}
631
632// InternalCreatePointerEventQueueInformation
633STATIC
636 IN APPLE_EVENT_TYPE EventType,
637 IN APPLE_MODIFIER_MAP Modifiers
638 )
639{
640 UINT32 FinalEventType;
641 APPLE_EVENT_DATA EventData;
642
643 DEBUG ((DEBUG_VERBOSE, "InternalCreatePointerEventQueueInformation\n"));
644
645 FinalEventType = APPLE_EVENT_TYPE_MOUSE_MOVED;
646
647 if ((EventType & APPLE_EVENT_TYPE_MOUSE_MOVED) == 0) {
648 FinalEventType = APPLE_ALL_MOUSE_EVENTS;
649
650 if ((EventType & APPLE_CLICK_MOUSE_EVENTS) != 0) {
651 FinalEventType = APPLE_CLICK_MOUSE_EVENTS;
652 }
653 }
654
655 EventData.PointerEventType = EventType;
656
658 EventData,
659 FinalEventType,
661 Modifiers
662 );
663}
664
665// InternalHandleButtonInteraction
666STATIC
667VOID
669 IN EFI_STATUS PointerStatus,
670 IN OUT POINTER_BUTTON_INFORMATION *Pointer,
671 IN APPLE_MODIFIER_MAP Modifiers
672 )
673{
674 APPLE_EVENT_INFORMATION *Information;
675 INT32 HorizontalMovement;
676 INT32 VerticalMovement;
677 APPLE_EVENT_TYPE EventType;
678
679 DEBUG ((DEBUG_VERBOSE, "InternalHandleButtonInteraction\n"));
680
681 if (!EFI_ERROR (PointerStatus)) {
682 if (!Pointer->PreviousButton) {
683 if (Pointer->CurrentButton) {
684 Pointer->ButtonTicksHold = 0;
685 Pointer->MouseDownPosition = mCursorPosition;
686
688 (Pointer->EventType | APPLE_EVENT_TYPE_MOUSE_DOWN),
689 Modifiers
690 );
691
692 if (Information != NULL) {
693 EventAddEventToQueue (Information);
694 }
695 }
696 } else if (!Pointer->CurrentButton) {
698 (Pointer->EventType | APPLE_EVENT_TYPE_MOUSE_UP),
699 Modifiers
700 );
701
702 if (Information != NULL) {
703 EventAddEventToQueue (Information);
704 }
705
706 if (Pointer->ButtonTicksHold <= mMaximumClickDuration) {
707 HorizontalMovement = ABS (Pointer->MouseDownPosition.Horizontal - mCursorPosition.Horizontal);
708 VerticalMovement = ABS (Pointer->MouseDownPosition.Vertical - mCursorPosition.Vertical);
709 //
710 // CHANGE: Apple did not scale by UIScale.
711 //
712 if ( (HorizontalMovement <= mUiScale * MINIMAL_MOVEMENT)
713 && (VerticalMovement <= mUiScale * MINIMAL_MOVEMENT))
714 {
716
717 if ( (Pointer->PreviousClickEventType == APPLE_EVENT_TYPE_MOUSE_CLICK)
718 && (Pointer->ButtonTicksSinceClick <= mMaximumDoubleClickSpeed))
719 {
720 HorizontalMovement = ABS (Pointer->ClickPosition.Horizontal - mCursorPosition.Horizontal);
721 VerticalMovement = ABS (Pointer->ClickPosition.Vertical - mCursorPosition.Vertical);
722
723 if ( (HorizontalMovement <= mUiScale * MINIMAL_MOVEMENT)
724 && (VerticalMovement <= mUiScale * MINIMAL_MOVEMENT))
725 {
727 }
728 }
729
731 (Pointer->EventType | EventType),
732 Modifiers
733 );
734
735 if (Information != NULL) {
736 EventAddEventToQueue (Information);
737 }
738
739 if (Pointer->PreviousClickEventType == APPLE_EVENT_TYPE_MOUSE_DOUBLE_CLICK) {
740 EventType = ((Pointer->ButtonTicksSinceClick <= mMaximumDoubleClickSpeed)
743 }
744
745 Pointer->PreviousClickEventType = EventType;
746 Pointer->ClickPosition = mCursorPosition;
747 Pointer->ButtonTicksSinceClick = 0;
748 }
749 }
750 }
751
752 Pointer->PreviousButton = Pointer->CurrentButton;
753 }
754
755 if (Pointer->PreviousButton && Pointer->CurrentButton) {
756 ++Pointer->ButtonTicksHold;
757 }
758
759 ++Pointer->ButtonTicksSinceClick;
760}
761
762STATIC
763VOID
765 VOID
766 )
767{
768 mDwellClickTime = 0;
769 CopyMem (
772 sizeof (mDwellPosition)
773 );
774}
775
776STATIC
777VOID
779 IN APPLE_EVENT_TYPE EventType,
780 IN APPLE_MODIFIER_MAP Modifiers
781 )
782{
783 APPLE_EVENT_INFORMATION *Information;
784
787 Modifiers
788 );
789 if (Information != NULL) {
790 EventAddEventToQueue (Information);
791 }
792
795 Modifiers
796 );
797 if (Information != NULL) {
798 EventAddEventToQueue (Information);
799 }
800
803 Modifiers
804 );
805 if (Information != NULL) {
806 EventAddEventToQueue (Information);
807 }
808}
809
810STATIC
811VOID
813 IN APPLE_MODIFIER_MAP Modifiers
814 )
815{
816 BOOLEAN ClickDisabled;
817 BOOLEAN DoubleClickDisabled;
818 INT32 DistX;
819 INT32 DistY;
820
821 ClickDisabled = mDwellClickTimeout == 0;
822 DoubleClickDisabled = mDwellDoubleClickTimeout == 0;
823 if (ClickDisabled && DoubleClickDisabled) {
824 return;
825 }
826
829 if ((UINT32)(DistX * DistX + DistY * DistY) <= mDwellClickRadiusSqr) {
831
832 if (!DoubleClickDisabled && (mDwellClickTime >= mDwellDoubleClickTimeout)) {
835 } else if (!ClickDisabled && (mDwellClickTime >= mDwellClickTimeout)) {
837 if (DoubleClickDisabled) {
839 }
840 }
841 } else {
843 }
844}
845
846// InternalSimplePointerPollNotifyFunction
847STATIC
848VOID
849EFIAPI
851 IN EFI_EVENT Event,
852 IN VOID *Context
853 )
854{
855 APPLE_MODIFIER_MAP Modifiers;
856 UINTN Index;
857 SIMPLE_POINTER_INSTANCE *Instance;
858 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
859 EFI_STATUS Status;
860 EFI_STATUS CommonStatus;
861 EFI_SIMPLE_POINTER_STATE State;
862 INT64 UiScaleX;
863 INT64 UiScaleY;
864 INT64 ScaledY;
865 INT64 ScaledX;
866 DIMENSION NewPosition;
867 APPLE_EVENT_INFORMATION *Information;
868 APPLE_EVENT_DATA EventData;
869 UINT64 StartTime;
870 UINT64 EndTime;
871 INT64 MaxRawPointerX;
872 INT64 MaxRawPointerY;
873 UINT32 ClickTemp;
874 UINT32 DoubleClickTemp;
875 UINT64 SimplePointerPollTime;
876
877 StartTime = GetPerformanceCounter ();
878
879 DEBUG ((DEBUG_VERBOSE, "InternalSimplePointerPollNotifyFunction\n"));
880
881 Modifiers = InternalGetModifierStrokes ();
882
887 );
888
889 CommonStatus = EFI_UNSUPPORTED;
890
892 CommonStatus = EFI_NOT_READY;
893
894 for (Index = 0; Index < mNumberOfPointerProtocols; ++Index) {
896 && ((Index >= 32) || (((1U << Index) & mSimplePointerPollMask) == 0)))
897 {
898 continue;
899 }
900
901 Instance = &mPointerProtocols[Index];
902 SimplePointer = Instance->Interface;
903 Status = SimplePointer->GetState (SimplePointer, &State);
904
905 if (!EFI_ERROR (Status)) {
906 //
907 // CHANGE: Apple scaled the deltas and due to rounding errors, this is
908 // unacceptable. Changed to scale all pointer deltas to the
909 // maximum pointer resolution and scaling down to display
910 // coordinates always based on the accurate raw input value.
911 //
912
913 UiScaleX = InternalGetUiScaleData ((INT64)State.RelativeMovementX);
914 UiScaleX = MultS64x64 (UiScaleX, (INT64)mMaxPointerResolutionX);
915 UiScaleX = MultS64x64 (UiScaleX, mPointerSpeedMul);
916 UiScaleX = DivS64x64Remainder (UiScaleX, mPointerSpeedDiv, NULL);
917
918 UiScaleY = InternalGetUiScaleData ((INT64)State.RelativeMovementY);
919 UiScaleY = MultS64x64 (UiScaleY, (INT64)mMaxPointerResolutionY);
920 UiScaleY = MultS64x64 (UiScaleY, mPointerSpeedMul);
921 UiScaleY = DivS64x64Remainder (UiScaleY, mPointerSpeedDiv, NULL);
922
923 if (SimplePointer->Mode->ResolutionX > 0) {
924 UiScaleX = DivS64x64Remainder (
925 UiScaleX,
926 (INT64)SimplePointer->Mode->ResolutionX,
927 NULL
928 );
929 }
930
931 if (SimplePointer->Mode->ResolutionY > 0) {
932 UiScaleY = DivS64x64Remainder (
933 UiScaleY,
934 (INT64)SimplePointer->Mode->ResolutionY,
935 NULL
936 );
937 }
938
939 //
940 // CHANGE: Fix maximum coordinates.
941 //
942 ScaledX = mPointerRawX + UiScaleX;
943 MaxRawPointerX = MultU64x64 (
946 );
947 if (ScaledX > MaxRawPointerX) {
948 ScaledX = MaxRawPointerX;
949 } else if (ScaledX < 0) {
950 ScaledX = 0;
951 }
952
953 mPointerRawX = (UINT64)ScaledX;
954
955 ScaledY = mPointerRawY + UiScaleY;
956 MaxRawPointerY = MultS64x64 (
959 );
960 if (ScaledY > MaxRawPointerY) {
961 ScaledY = MaxRawPointerY;
962 } else if (ScaledY < 0) {
963 ScaledY = 0;
964 }
965
966 mPointerRawY = (UINT64)ScaledY;
967
968 ScaledX = DivU64x64Remainder (
969 ScaledX,
971 NULL
972 );
973
974 ScaledY = DivS64x64Remainder (
975 ScaledY,
977 NULL
978 );
979
980 NewPosition.Horizontal = (INT32)ScaledX;
981 NewPosition.Vertical = (INT32)ScaledY;
982
983 if ( (mCursorPosition.Horizontal != NewPosition.Horizontal)
984 || (mCursorPosition.Vertical != NewPosition.Vertical))
985 {
986 CopyMem (
988 &NewPosition,
989 sizeof (mCursorPosition)
990 );
991
992 mMouseMoved = TRUE;
993 }
994
996 mLeftButtonInfo.CurrentButton = State.LeftButton;
998 mRightButtonInfo.CurrentButton = State.RightButton;
999 CommonStatus = Status;
1000 }
1001 }
1002
1003 InternalHandleButtonInteraction (CommonStatus, &mLeftButtonInfo, Modifiers);
1004 InternalHandleButtonInteraction (CommonStatus, &mRightButtonInfo, Modifiers);
1005
1006 InternalHandleDwellClicking (Modifiers);
1007 }
1008
1009 if (EFI_ERROR (CommonStatus)) {
1010 if (CommonStatus == EFI_UNSUPPORTED) {
1012
1014 }
1015 } else if (mMouseMoved != FALSE) {
1016 mMouseMoved = FALSE;
1017
1019 Information = EventCreateAppleEventQueueInfo (
1020 EventData,
1023 Modifiers
1024 );
1025
1026 if (Information != NULL) {
1027 EventAddEventToQueue (Information);
1028 }
1029 }
1030
1031 //
1032 // This code is here to workaround very slow mouse polling performance on some computers,
1033 // like most of Dell laptops (one of the worst examples is Dell Latitude 3330 with ~50 ms).
1034 // Even if we try all the hacks we could make this code approximately only twice faster,
1035 // which is still far from enough. The event system on these laptops is pretty broken,
1036 // and even adding gBS->CheckEvent prior to GetState almost does not reduce the time spent.
1037 //
1039 EndTime = GetPerformanceCounter ();
1040 if (StartTime > EndTime) {
1041 EndTime = StartTime;
1042 }
1043
1044 EndTime = GetTimeInNanoSecond (EndTime - StartTime);
1045 // Maximum time allowed in this function is half the interval plus some margin (0.55 * 100ns)
1046 if (EndTime > mSimplePointerPollTime * 55) {
1049
1050 SimplePointerPollTime = DivU64x32 (EndTime, 50);
1051 if (SimplePointerPollTime <= mSimplePointerMaxPollTime) {
1052 mSimplePointerPollTime = (UINT32)SimplePointerPollTime;
1053 } else {
1055 }
1056
1057 mMaximumClickDuration = (UINT16)(ClickTemp / mSimplePointerPollTime);
1058 mMaximumDoubleClickSpeed = (UINT16)(DoubleClickTemp / mSimplePointerPollTime);
1059
1060 gBS->SetTimer (mSimplePointerPollEvent, TimerPeriodic, mSimplePointerPollTime);
1061 }
1062 }
1063}
1064
1065// EventCreateSimplePointerPollEvent
1066EFI_STATUS
1068 VOID
1069 )
1070{
1071 EFI_STATUS Status;
1072 UINTN Index;
1073
1074 DEBUG ((DEBUG_VERBOSE, "EventCreateSimplePointerPollEvent\n"));
1075
1080 );
1081
1082 for (Index = 0; Index < mNumberOfPointerProtocols; ++Index) {
1083 mPointerProtocols[Index].Interface->Reset (
1084 mPointerProtocols[Index].Interface,
1085 FALSE
1086 );
1087 }
1088
1091
1095 NULL,
1097 TRUE
1098 );
1099
1100 Status = EFI_OUT_OF_RESOURCES;
1101
1102 if (mSimplePointerPollEvent != NULL) {
1107
1108 Status = EFI_SUCCESS;
1109 }
1110
1111 return Status;
1112}
1113
1114// EventCancelSimplePointerPollEvent
1115VOID
1117 VOID
1118 )
1119{
1120 DEBUG ((DEBUG_VERBOSE, "EventCancelSimplePointerPollEvent\n"));
1121
1123
1125}
1126
1127// EventSetCursorPositionImpl
1128EFI_STATUS
1130 IN DIMENSION *Position
1131 )
1132{
1133 EFI_STATUS Status;
1134
1135 DEBUG ((DEBUG_VERBOSE, "EventSetCursorPositionImpl\n"));
1136
1138
1139 Status = EFI_INVALID_PARAMETER;
1140
1141 //
1142 // Apple did not check for negatives here.
1143 //
1144
1145 if ( (Position->Horizontal >= 0) && (Position->Vertical >= 0)
1146 && (Position->Horizontal < mResolution.Horizontal)
1147 && (Position->Vertical < mResolution.Vertical))
1148 {
1149 mCursorPosition.Horizontal = Position->Horizontal;
1150 mCursorPosition.Vertical = Position->Vertical;
1154 );
1158 );
1159 Status = EFI_SUCCESS;
1160 }
1161
1162 return Status;
1163}
#define APPLE_EVENT_TYPE_MOUSE_MOVED
Definition AppleEvent.h:21
#define APPLE_EVENT_TYPE_RIGHT_BUTTON
Definition AppleEvent.h:27
#define APPLE_EVENT_TYPE_MOUSE_CLICK
Definition AppleEvent.h:24
#define APPLE_EVENT_TYPE_LEFT_BUTTON
Definition AppleEvent.h:26
#define APPLE_CLICK_MOUSE_EVENTS
Definition AppleEvent.h:34
UINT32 APPLE_EVENT_TYPE
Definition AppleEvent.h:45
#define APPLE_EVENT_TYPE_MOUSE_DOUBLE_CLICK
Definition AppleEvent.h:25
#define APPLE_ALL_MOUSE_EVENTS
Definition AppleEvent.h:41
#define APPLE_EVENT_TYPE_MOUSE_DOWN
Definition AppleEvent.h:22
#define APPLE_EVENT_TYPE_MOUSE_UP
Definition AppleEvent.h:23
APPLE_EVENT_INFORMATION * EventCreateAppleEventQueueInfo(IN APPLE_EVENT_DATA EventData, IN APPLE_EVENT_TYPE EventType, IN DIMENSION *PointerPosition, IN APPLE_MODIFIER_MAP Modifiers)
Definition EventQueue.c:150
VOID EventAddEventToQueue(IN APPLE_EVENT_INFORMATION *Information)
Definition EventQueue.c:194
APPLE_MODIFIER_MAP InternalGetModifierStrokes(VOID)
Definition KeyHandler.c:180
EFI_EVENT EventLibCreateNotifyTimerEvent(IN EFI_EVENT_NOTIFY NotifyFunction, IN VOID *NotifyContext, IN UINT64 TriggerTime, IN BOOLEAN SignalPeriodic)
VOID EventLibCancelEvent(IN EFI_EVENT Event)
UINT16 APPLE_MODIFIER_MAP
Definition AppleHid.h:102
EFI_GUID gAppleVendorVariableGuid
#define APPLE_UI_SCALE_VARIABLE_NAME
#define POINTER_POLL_ALL_MASK
#define POINTER_POLL_DEFAULT
EFI_SYSTEM_TABLE * gST
EFI_BOOT_SERVICES * gBS
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
APPLE_EVENT_HANDLE Handle
Definition OcTypingLib.h:45
VOID InternalSetDwellClicking(IN UINT16 ClickTimeout, IN UINT16 DoubleClickTimeout, IN UINT16 Radius)
STATIC UINT32 mSimplePointerMaxPollTime
#define MAX_DOUBLE_CLICK_SPEED
STATIC VOID EFIAPI InternalSimplePointerInstallNotifyFunction(IN EFI_EVENT Event, IN VOID *Context)
STATIC INT64 InternalGetUiScaleData(IN INT64 Movement)
STATIC DIMENSION mResolution
#define MAX_POLL_DURATION
STATIC UINT16 mMaximumClickDuration
EFI_STATUS EventSetCursorPositionImpl(IN DIMENSION *Position)
STATIC VOID InternalHandleButtonInteraction(IN EFI_STATUS PointerStatus, IN OUT POINTER_BUTTON_INFORMATION *Pointer, IN APPLE_MODIFIER_MAP Modifiers)
STATIC VOID InternalGetScreenResolution(VOID)
STATIC VOID InternalResetDwellClicking(VOID)
VOID InternalSetPointerSpeed(IN UINT16 PointerSpeedDiv, IN UINT16 PointerSpeedMul)
STATIC UINT32 mSimplePointerMinPollTime
VOID EventCancelSimplePointerPollEvent(VOID)
STATIC BOOLEAN mMouseMoved
#define MINIMAL_MOVEMENT
EFI_STATUS EventCreateSimplePointerPollEvent(VOID)
STATIC VOID InternalRemoveUninstalledInstances(IN OUT SIMPLE_POINTER_INSTANCE **InstancesPtr, IN UINTN *NumberOfInstances, IN EFI_GUID *Protocol)
STATIC DIMENSION mCursorPosition
STATIC SIMPLE_POINTER_INSTANCE * mPointerProtocols
STATIC UINT64 mMaxPointerResolutionY
STATIC POINTER_BUTTON_INFORMATION mLeftButtonInfo
GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mPointerSpeedMul
STATIC UINT32 mDwellClickTime
STATIC UINT8 mUiScale
VOID InternalInitializePointerUiScale(VOID)
#define MIN_POINTER_POLL_PERIOD
STATIC UINT64 mPointerRawX
STATIC EFI_EVENT mSimplePointerInstallNotifyEvent
STATIC UINTN mNumberOfPointerProtocols
VOID InternalSetPointerPolling(IN UINT32 PointerPollMin, IN UINT32 PointerPollMax, IN UINT32 PointerPollMask)
STATIC UINT32 mDwellDoubleClickTimeout
STATIC UINT64 mPointerRawY
STATIC UINT32 mSimplePointerPollTime
GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mPointerSpeedDiv
STATIC VOID InternalRegisterSimplePointerInterface(IN EFI_HANDLE Handle, IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer)
VOID EventCloseSimplePointerInstallNotifyEvent(VOID)
VOID EventSimplePointerDesctructor(VOID)
STATIC VOID InternalHandleDwellClicking(IN APPLE_MODIFIER_MAP Modifiers)
STATIC DIMENSION mDwellPosition
EFI_STATUS EventCreateSimplePointerInstallNotifyEvent(VOID)
STATIC EFI_EVENT mSimplePointerPollEvent
STATIC VOID InternalQueueDwellClick(IN APPLE_EVENT_TYPE EventType, IN APPLE_MODIFIER_MAP Modifiers)
STATIC UINT32 mDwellClickRadiusSqr
STATIC VOID * mSimplePointerInstallNotifyRegistration
STATIC UINT16 mMaximumDoubleClickSpeed
STATIC APPLE_EVENT_INFORMATION * InternalCreatePointerEventQueueInformation(IN APPLE_EVENT_TYPE EventType, IN APPLE_MODIFIER_MAP Modifiers)
#define MAX_POINTER_POLL_PERIOD
STATIC VOID EFIAPI InternalSimplePointerPollNotifyFunction(IN EFI_EVENT Event, IN VOID *Context)
STATIC POINTER_BUTTON_INFORMATION mRightButtonInfo
#define MAX_CLICK_DURATION
STATIC UINT32 mSimplePointerPollMask
STATIC UINT64 mMaxPointerResolutionX
STATIC UINT32 mDwellClickTimeout
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_RUNTIME_SERVICES * gRT
EFI_GUID gEfiUgaDrawProtocolGuid
EFI_GUID gEfiGraphicsOutputProtocolGuid
EFI_GUID gEfiSimplePointerProtocolGuid
UINT64 EFIAPI MultU64x64(IN UINT64 Multiplicand, IN UINT64 Multiplier)
Definition UserMath.c:116
INT64 EFIAPI DivS64x64Remainder(IN INT64 Dividend, IN INT64 Divisor, OUT INT64 *Remainder OPTIONAL)
Definition UserMath.c:42
UINT64 EFIAPI DivU64x64Remainder(IN UINT64 Dividend, IN UINT64 Divisor, OUT UINT64 *Remainder OPTIONAL)
Definition UserMath.c:59
INT64 EFIAPI MultS64x64(IN INT64 Multiplicand, IN INT64 Multiplier)
Definition UserMath.c:106
UINT64 EFIAPI GetTimeInNanoSecond(IN UINT64 Ticks)
UINT64 EFIAPI GetPerformanceCounter(VOID)
#define DivU64x32(x, y, z)
INT32 Horizontal
Definition AppleEvent.h:65
INT32 Vertical
Definition AppleEvent.h:66
EFI_SIMPLE_POINTER_PROTOCOL * Interface
APPLE_POINTER_EVENT_TYPE PointerEventType
Definition AppleEvent.h:59