Changeset 26624 in vbox
- Timestamp:
- Feb 18, 2010 10:35:24 AM (15 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/pdmifs.h
r26573 r26624 304 304 */ 305 305 DECLR3CALLBACKMEMBER(int, pfnPutEvent,(PPDMIMOUSEPORT pInterface, int32_t i32DeltaX, int32_t i32DeltaY, int32_t i32DeltaZ, int32_t i32DeltaW, uint32_t fButtonStates)); 306 /** 307 * Puts an absolute mouse event. 308 * This is called by the source of mouse events. The event will be passed up until the 309 * topmost driver, which then calls the registered event handler. 310 * 311 * @returns VBox status code. 312 * @param pInterface Pointer to this interface structure. 313 * @param i32cX The X value, in the range 0 to 0xffff. 314 * @param i32cY The Y value, in the range 0 to 0xffff. 315 * @thread The emulation thread. 316 */ 317 DECLR3CALLBACKMEMBER(int, pfnPutEventAbs,(PPDMIMOUSEPORT pInterface, int32_t i32cX, int32_t i32cY)); 306 318 } PDMIMOUSEPORT; 307 319 … … 316 328 317 329 330 /** Pointer to a mouse connector interface. */ 331 typedef struct PDMIMOUSECONNECTOR *PPDMIMOUSECONNECTOR; 318 332 /** 319 333 * Mouse connector interface (up). 320 334 * Pair with PDMIMOUSEPORT. 321 335 */ 322 typedef PDMIDUMMY PDMIMOUSECONNECTOR; 323 /** Pointer to a mouse connector interface. */ 324 typedef PDMIMOUSECONNECTOR *PPDMIMOUSECONNECTOR; 336 typedef struct PDMIMOUSECONNECTOR 337 { 338 /** 339 * Notifies the the downstream driver when the guest switches the device into or out of absolute mode. 340 * 341 * @param pInterface Pointer to the this interface. 342 * @param fAbs Whether absolute mode is currently enabled 343 */ 344 DECLR3CALLBACKMEMBER(void, pfnAbsModeChange,(PPDMIMOUSECONNECTOR pInterface, bool fAbs)); 345 346 } PDMIMOUSECONNECTOR; 347 325 348 /** PDMIMOUSECONNECTOR interface ID. */ 326 349 #define PDMIMOUSECONNECTOR_IID "847f965f-0eb8-4363-88ac-b0ee58a05bde" -
trunk/src/VBox/Devices/Input/DevPS2.cpp
r26572 r26624 57 57 #include "../Builtins.h" 58 58 59 #define PCKBD_SAVED_STATE_VERSION 359 #define PCKBD_SAVED_STATE_VERSION 4 60 60 61 61 … … 162 162 #define KBD_QUEUE_SIZE 256 163 163 164 /* Supported mouse protocols */ 165 enum 166 { 167 MOUSE_PROT_PS2 = 0, 168 MOUSE_PROT_IMPS2 = 3, 169 MOUSE_PROT_IMEX = 4, 170 MOUSE_PROT_LIFEBOOK = 5 171 }; 172 173 /* Mouse flags */ 164 174 # define MOUSE_REPORT_HORIZONTAL 0x01 165 # define MOUSE_OUTSTANDING_CLICK 0x02 175 176 /** Extended mouse button values for Lifebook mode */ 177 /** Downwards scrollwheel movement of one step. Doesn't affect the mouse 178 * buttons */ 179 # define MOUSE_EXT_VSCROLL_DN 4 180 /** Upwards scrollwheel movement of one step. */ 181 # define MOUSE_EXT_VSCROLL_UP 5 182 /** Leftwards scrollwheel movement of one step. */ 183 # define MOUSE_EXT_HSCROLL_BW 6 184 /** Rightwards scrollwheel movement of one step. */ 185 # define MOUSE_EXT_HSCROLL_FW 7 166 186 167 187 typedef struct { … … 210 230 int32_t mouse_dw; 211 231 int32_t mouse_flags; 232 int32_t mouse_cx; 233 int32_t mouse_cy; 212 234 uint8_t mouse_buttons; 235 uint8_t mouse_buttons_reported; 236 uint8_t mouse_last_button; 213 237 214 238 /** Pointer to the device instance - RC. */ … … 647 671 } 648 672 649 static void kbd_mouse_send_packet(KBDState *s, bool fToCmdQueue) 673 static void kbd_mouse_set_reported_buttons(KBDState *s, unsigned fButtons, unsigned fButtonMask) 674 { 675 s->mouse_buttons_reported |= (fButtons & fButtonMask); 676 s->mouse_buttons_reported &= (fButtons | ~fButtonMask); 677 } 678 679 static bool kbd_mouse_test_set_button(KBDState *s, unsigned cIndex) 680 { 681 unsigned fButtonMask = 1 << (cIndex - 1); 682 683 AssertReturn(3 <= cIndex && cIndex <= 5, false); 684 if ( (s->mouse_buttons & fButtonMask) 685 && !(s->mouse_buttons_reported & fButtonMask)) 686 { 687 s->mouse_last_button = cIndex; 688 kbd_mouse_set_reported_buttons(s, fButtonMask, 0x1c); 689 return true; 690 } 691 return false; 692 } 693 694 static bool kbd_mouse_test_clear_last_button(KBDState *s) 695 { 696 unsigned fButtonMask = 1 << (s->mouse_last_button - 1); 697 698 if ( s->mouse_last_button != 0 699 && !(s->mouse_buttons & fButtonMask)) 700 { 701 s->mouse_last_button = 0; 702 kbd_mouse_set_reported_buttons(s, 0, fButtonMask); 703 return true; 704 } 705 return false; 706 } 707 708 /** 709 * Send a single relative packet in 3-byte PS/2 format, optionally with our 710 * packed button protocol extension, to the PS/2 controller. 711 * @param s keyboard state object 712 * @param dx relative X value, must be between -256 and +255 713 * @param dy relative y value, must be between -256 and +255 714 * @param fButtonsLow the state of the two first mouse buttons 715 * @param fButtonsPacked the state of the upper three mouse buttons and 716 * scroll wheel movement, packed as per the 717 * MOUSE_EXT_* defines. For standard PS/2 packets 718 * only pass the value of button 3 here. 719 */ 720 static void kbd_mouse_send_rel3_packet(KBDState *s, bool fToCmdQueue) 650 721 { 651 722 int aux = fToCmdQueue ? 1 : 2; 723 int dx1 = s->mouse_dx < 0 ? RT_MAX(s->mouse_dx, -256) 724 : s->mouse_dx > 0 ? RT_MIN(s->mouse_dx, 255) : 0; 725 int dy1 = s->mouse_dy < 0 ? RT_MAX(s->mouse_dy, -256) 726 : s->mouse_dy > 0 ? RT_MIN(s->mouse_dy, 255) : 0; 652 727 unsigned int b; 653 int dx1, dy1, dz1, dw1; 654 655 dx1 = s->mouse_dx; 656 dy1 = s->mouse_dy; 657 dz1 = s->mouse_dz; 658 dw1 = s->mouse_dw; 659 LogRel3(("%s: dx=%d, dy=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__, 660 dx1, dy1, dz1, dw1)); 661 /* XXX: increase range to 8 bits ? */ 662 if (dx1 > 127) 663 dx1 = 127; 664 else if (dx1 < -127) 665 dx1 = -127; 666 if (dy1 > 127) 667 dy1 = 127; 668 else if (dy1 < -127) 669 dy1 = -127; 670 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07); 728 unsigned fButtonsPacked; 729 unsigned fButtonsLow = s->mouse_buttons & 0x03; 730 s->mouse_dx -= dx1; 731 s->mouse_dy -= dy1; 732 kbd_mouse_set_reported_buttons(s, fButtonsLow, 0x03); 733 /* When we are not in lifebook mode, we just set the third bit 734 * in the first packet byte if the middle button is pressed, 735 * as per the PS/2 protocol. */ 736 if (s->mouse_type != MOUSE_PROT_LIFEBOOK) 737 { 738 fButtonsPacked = (s->mouse_buttons & 0x04 ? 0x04 : 0); 739 kbd_mouse_set_reported_buttons(s, s->mouse_buttons, 0x04); 740 } 741 else 742 { 743 if (kbd_mouse_test_set_button(s, 3)) 744 fButtonsPacked = 1; 745 else if (kbd_mouse_test_set_button(s, 4)) 746 fButtonsPacked = 2; 747 else if (kbd_mouse_test_set_button(s, 5)) 748 fButtonsPacked = 3; 749 /* Release event for buttons in the range 3-5. */ 750 else if (kbd_mouse_test_clear_last_button(s)) 751 fButtonsPacked = 0; 752 else if (s->mouse_dz < 0) 753 { 754 ++s->mouse_dz; 755 fButtonsPacked = MOUSE_EXT_VSCROLL_DN; 756 } 757 else if (s->mouse_dz > 0) 758 { 759 --s->mouse_dz; 760 fButtonsPacked = MOUSE_EXT_VSCROLL_UP; 761 } 762 else if (s->mouse_dw < 0) 763 { 764 ++s->mouse_dw; 765 fButtonsPacked = MOUSE_EXT_HSCROLL_BW; 766 } 767 else if (s->mouse_dw > 0) 768 { 769 --s->mouse_dw; 770 fButtonsPacked = MOUSE_EXT_HSCROLL_FW; 771 } 772 else 773 fButtonsPacked = s->mouse_last_button; 774 } 775 LogRel3(("%s: dx1=%d, dy1=%d, fButtonsLow=0x%x, fButtonsPacked=0x%x\n", 776 __PRETTY_FUNCTION__, dx1, dy1, fButtonsLow, fButtonsPacked)); 777 b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | fButtonsLow 778 | (fButtonsPacked & 4) | ((fButtonsPacked & 3) << 6); 671 779 kbd_queue(s, b, aux); 672 780 kbd_queue(s, dx1 & 0xff, aux); 673 781 kbd_queue(s, dy1 & 0xff, aux); 674 /* extra byte for IMPS/2 or IMEX */ 675 switch(s->mouse_type) { 676 default: 677 break; 678 case 3: 679 if (dz1 > 127) 680 dz1 = 127; 681 else if (dz1 < -127) 682 dz1 = -127; 683 kbd_queue(s, dz1 & 0xff, aux); 684 break; 685 case 4: 686 if (dz1 > 1) 687 dz1 = 1; 688 else if (dz1 < -1) 689 dz1 = -1; 690 else if (dw1 > 1) 691 dw1 = 1; 692 else if (dw1 < -1) 693 dw1 = -1; 694 if (dz1) 695 dw1 = 0; 696 if ((s->mouse_flags & MOUSE_REPORT_HORIZONTAL) && dw1) 697 b = 0x40 | (dw1 & 0x3f); 698 else 699 { 700 b = (dz1 & 0x0f) | ((dw1 << 1) & 0x0f) 701 | ((s->mouse_buttons & 0x18) << 1); 702 s->mouse_flags &= ~MOUSE_OUTSTANDING_CLICK; 703 } 704 kbd_queue(s, b, aux); 705 break; 706 } 707 708 /* update deltas */ 709 s->mouse_dx -= dx1; 710 s->mouse_dy -= dy1; 782 } 783 784 static void kbd_mouse_send_imps2_byte4(KBDState *s, bool fToCmdQueue) 785 { 786 int aux = fToCmdQueue ? 1 : 2; 787 788 int dz1 = s->mouse_dz < 0 ? RT_MAX(s->mouse_dz, -127) 789 : s->mouse_dz > 0 ? RT_MIN(s->mouse_dz, 127) : 0; 711 790 s->mouse_dz -= dz1; 712 s->mouse_dw -= dw1; 791 kbd_queue(s, dz1 & 0xff, aux); 792 } 793 794 static void kbd_mouse_send_imex_byte4(KBDState *s, bool fToCmdQueue) 795 { 796 int aux = fToCmdQueue ? 1 : 2; 797 798 if (s->mouse_dw) 799 { 800 int dw1 = s->mouse_dw < 0 ? RT_MAX(s->mouse_dw, -32) 801 : s->mouse_dw > 0 ? RT_MIN(s->mouse_dw, 32) : 0; 802 s->mouse_dw -= dw1; 803 kbd_queue(s, 0x40 | (dw1 & 0x3f), aux); 804 } 805 else if (s->mouse_flags & MOUSE_REPORT_HORIZONTAL && s->mouse_dz) 806 { 807 int dz1 = s->mouse_dz < 0 ? RT_MAX(s->mouse_dz, -32) 808 : s->mouse_dz > 0 ? RT_MIN(s->mouse_dz, 32) : 0; 809 s->mouse_dz -= dz1; 810 kbd_queue(s, 0x80 | (dz1 & 0x3f), aux); 811 } 812 else 813 { 814 int dz1 = s->mouse_dz < 0 ? RT_MAX(s->mouse_dz, -8) 815 : s->mouse_dz > 0 ? RT_MIN(s->mouse_dz, 8) : 0; 816 s->mouse_dz -= dz1; 817 kbd_mouse_set_reported_buttons(s, s->mouse_buttons, 0x18); 818 kbd_queue(s, (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1), aux); 819 } 820 } 821 822 /** 823 * Send a single relative packet in (IM)PS/2 or IMEX format to the PS/2 824 * controller. 825 * @param s keyboard state object 826 * @param fToCmdQueue should this packet go to the command queue (or the 827 * event queue)? 828 */ 829 static void kbd_mouse_send_rel_packet(KBDState *s, bool fToCmdQueue) 830 { 831 kbd_mouse_send_rel3_packet(s, fToCmdQueue); 832 if (s->mouse_type == MOUSE_PROT_IMPS2) 833 kbd_mouse_send_imps2_byte4(s, fToCmdQueue); 834 if (s->mouse_type == MOUSE_PROT_IMEX) 835 kbd_mouse_send_imex_byte4(s, fToCmdQueue); 836 } 837 838 /** 839 * Send a single absolute packet in 6-byte lifebook format to the PS/2 840 * controller. 841 * @param s keyboard state object 842 * @param cx absolute X value 843 * @param cy absolute y value 844 * @param fButtons the state of the two first mouse buttons 845 */ 846 static void kbd_mouse_send_abs_packet(KBDState *s, bool fToCmdQueue) 847 { 848 int aux = fToCmdQueue ? 1 : 2; 849 int cx1 = s->mouse_cx * 4096 / 0xffff; 850 int cy1 = 4096 - (s->mouse_cy * 4096 / 0xffff); 851 unsigned fButtons = s->mouse_buttons & 0x03; 852 unsigned int b; 853 854 LogRel3(("%s: cx1=%d, cy1=%d, fButtons=0x%x\n", __PRETTY_FUNCTION__, 855 cx1, cy1, fButtons)); 856 b = 4 /* Screen is being touched */ | fButtons; 857 kbd_queue(s, b, aux); 858 b = ((cy1 << 2) & 0xc0) | (cx1 >> 6); 859 kbd_queue(s, b, aux); 860 b = ((cx1 << 2) & 0xc0) | (cx1 & 0x3f); 861 kbd_queue(s, b, aux); 862 kbd_queue(s, 0xc0, aux); /* This byte is really wasted in the protocol */ 863 b = ((cx1 << 2) & 0xc0) | (cy1 >> 6); 864 kbd_queue(s, b, aux); 865 b = ((cy1 << 2) & 0xc0) | (cy1 & 0x3f); 866 kbd_queue(s, b, aux); 867 } 868 869 static bool kbd_mouse_rel_unreported(KBDState *s) 870 { 871 return s->mouse_dx 872 || s->mouse_dy 873 || s->mouse_dz 874 || s->mouse_dw 875 || s->mouse_buttons != s->mouse_buttons_reported; 876 } 877 878 /** 879 * Send a single packet in (IM)PS/2, IMEX or Lifebook format to the PS/2 880 * controller. 881 * @param s keyboard state object 882 * @param fToCmdQueue is this the result of a poll on the mouse controller? 883 */ 884 static void kbd_mouse_send_packet(KBDState *s, bool fToCmdQueue) 885 { 886 if ( kbd_mouse_rel_unreported(s) 887 || (s->mouse_type != MOUSE_PROT_LIFEBOOK)) 888 kbd_mouse_send_rel_packet(s, fToCmdQueue); 889 else 890 kbd_mouse_send_abs_packet(s, fToCmdQueue); 713 891 } 714 892 715 893 #ifdef IN_RING3 716 static void pc_kbd_mouse_event(void *opaque, 717 int dx, int dy, int dz, int dw, int buttons_state) 718 { 894 static size_t kbd_mouse_event_queue_free(KBDState *s) 895 { 896 AssertReturn(s->mouse_event_queue.count <= MOUSE_EVENT_QUEUE_SIZE, 0); 897 return MOUSE_EVENT_QUEUE_SIZE - s->mouse_event_queue.count; 898 } 899 900 static void pc_kbd_mouse_event(void *opaque, int dx, int dy, int dz, int dw, 901 int buttons_state) 902 { 903 LogRel3(("%s: dx=%d, dy=%d, dz=%d, dw=%d, buttons_state=0x%x\n", 904 __PRETTY_FUNCTION__, dx, dy, dz, dw, buttons_state)); 719 905 KBDState *s = (KBDState*)opaque; 720 906 … … 722 908 if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) 723 909 return; 910 AssertReturnVoid((buttons_state & ~0x1f) == 0); 724 911 725 912 s->mouse_dx += dx; 726 913 s->mouse_dy -= dy; 727 914 s->mouse_dz += dz; 728 s->mouse_dw += dw; 729 /* In horizontal reporting mode, we may need to send an additional packet 730 * for the forth and fifth buttons, as they can't share a packet with a 731 * horizontal scroll delta. */ 732 if ( s->mouse_type == 4 733 && (s->mouse_buttons & 0x18) != (buttons_state & 0x18)) 734 s->mouse_flags |= MOUSE_OUTSTANDING_CLICK; 915 if ( ( (s->mouse_type == MOUSE_PROT_IMEX) 916 && s->mouse_flags & MOUSE_REPORT_HORIZONTAL) 917 || (s->mouse_type == MOUSE_PROT_LIFEBOOK)) 918 s->mouse_dw += dw; 735 919 s->mouse_buttons = buttons_state; 920 if (!(s->mouse_status & MOUSE_STATUS_REMOTE)) 921 /* if not remote, send event. Multiple events are sent if 922 too big deltas */ 923 while ( kbd_mouse_rel_unreported(s) 924 && kbd_mouse_event_queue_free(s) > 4) 925 kbd_mouse_send_rel_packet(s, false); 926 } 927 928 static void pc_kbd_mouse_event_abs(void *opaque, unsigned cx, unsigned cy) 929 { 930 LogRel3(("%s: cx=%d, cy=%d\n", __PRETTY_FUNCTION__, cx, cy)); 931 KBDState *s = (KBDState*)opaque; 932 933 if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) 934 return; 935 936 if (s->mouse_type != MOUSE_PROT_LIFEBOOK) 937 return; 938 939 s->mouse_cx = cx; 940 s->mouse_cy = cy; 736 941 737 942 if (!(s->mouse_status & MOUSE_STATUS_REMOTE) && 738 (s->mouse_event_queue.count < (MOUSE_EVENT_QUEUE_SIZE - 4))) { 739 for(;;) { 740 /* if not remote, send event. Multiple events are sent if 741 too big deltas */ 742 kbd_mouse_send_packet(s, false); 743 if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 && s->mouse_dw == 0 && !(s->mouse_flags & MOUSE_OUTSTANDING_CLICK)) 744 break; 745 } 746 } 943 (s->mouse_event_queue.count < (MOUSE_EVENT_QUEUE_SIZE - 4))) 944 /* if not remote, send event */ 945 kbd_mouse_send_abs_packet(s, false); 747 946 } 748 947 #endif /* IN_RING3 */ 749 948 750 static voidkbd_write_mouse(KBDState *s, int val)949 static int kbd_write_mouse(KBDState *s, int val) 751 950 { 752 951 #ifdef DEBUG_MOUSE … … 765 964 s->mouse_wrap = 0; 766 965 kbd_queue(s, AUX_ACK, 1); 767 return ;966 return VINF_SUCCESS; 768 967 } else if (val != AUX_RESET) { 769 968 kbd_queue(s, val, 1); 770 return ;969 return VINF_SUCCESS; 771 970 } 772 971 } … … 833 1032 s->mouse_resolution = 2; 834 1033 s->mouse_status = 0; 835 s->mouse_type = 0;1034 s->mouse_type = MOUSE_PROT_PS2; 836 1035 kbd_queue(s, AUX_ACK, 1); 837 1036 kbd_queue(s, 0xaa, 1); … … 879 1078 else if (val == 200) 880 1079 s->mouse_detect_state = 3; 881 else if ((val == 80) && s->mouse_type == 4 /* IMEX */)1080 else if ((val == 80) && s->mouse_type == MOUSE_PROT_IMEX) 882 1081 /* enable horizontal scrolling, byte two */ 883 1082 s->mouse_detect_state = 4; … … 889 1088 { 890 1089 LogRelFlowFunc(("switching mouse device to IMPS/2 mode\n")); 891 s->mouse_type = 3; /* IMPS/2 */1090 s->mouse_type = MOUSE_PROT_IMPS2; 892 1091 } 893 1092 s->mouse_detect_state = 0; … … 897 1096 { 898 1097 LogRelFlowFunc(("switching mouse device to IMEX mode\n")); 899 s->mouse_type = 4; /* IMEX */1098 s->mouse_type = MOUSE_PROT_IMEX; 900 1099 } 901 1100 s->mouse_detect_state = 0; … … 914 1113 break; 915 1114 case AUX_SET_RES: 916 s->mouse_resolution = val; 917 kbd_queue(s, AUX_ACK, 1); 1115 if (0 <= val && val < 4) 1116 { 1117 s->mouse_resolution = val; 1118 kbd_queue(s, AUX_ACK, 1); 1119 } 1120 else if (val == 6) /* Lifebook off magic knock */ 1121 { 1122 #ifdef IN_RING3 1123 LogRelFlowFunc(("switching mouse device to basic PS/2 mode\n")); 1124 s->mouse_type = MOUSE_PROT_PS2; 1125 s->Mouse.pDrv->pfnAbsModeChange(s->Mouse.pDrv, false); 1126 #else 1127 return VINF_IOM_HC_IOPORT_WRITE; 1128 #endif 1129 kbd_queue(s, AUX_NACK, 1); 1130 } 1131 else if (val == 8) /* Lifebook on magic knock */ 1132 { 1133 #ifdef IN_RING3 1134 LogRelFlowFunc(("switching mouse device to touch screen mode\n")); 1135 s->mouse_type = MOUSE_PROT_LIFEBOOK; 1136 s->Mouse.pDrv->pfnAbsModeChange(s->Mouse.pDrv, true); 1137 #else 1138 return VINF_IOM_HC_IOPORT_WRITE; 1139 #endif 1140 kbd_queue(s, AUX_NACK, 1); 1141 } 1142 else 1143 kbd_queue(s, AUX_NACK, 1); 918 1144 s->mouse_write_cmd = -1; 919 1145 break; 920 1146 } 1147 return VINF_SUCCESS; 921 1148 } 922 1149 … … 963 1190 break; 964 1191 case KBD_CCMD_WRITE_MOUSE: 965 kbd_write_mouse(s, val);1192 rc = kbd_write_mouse(s, val); 966 1193 break; 967 1194 default: … … 994 1221 s->mouse_sample_rate = 0; 995 1222 s->mouse_wrap = 0; 996 s->mouse_type = 0; 1223 s->mouse_type = MOUSE_PROT_PS2; 1224 s->Mouse.pDrv->pfnAbsModeChange(s->Mouse.pDrv, false); 997 1225 s->mouse_detect_state = 0; 998 1226 s->mouse_dx = 0; … … 1001 1229 s->mouse_dw = 0; 1002 1230 s->mouse_flags = 0; 1231 s->mouse_cx = 0x8000; 1232 s->mouse_cy = 0x8000; 1003 1233 s->mouse_buttons = 0; 1234 s->mouse_buttons_reported = 0; 1235 s->mouse_last_button = 0; 1004 1236 q = &s->queue; 1005 1237 q->rptr = 0; … … 1039 1271 qemu_put_be32s(f, &s->mouse_dw); 1040 1272 qemu_put_be32s(f, &s->mouse_flags); 1273 qemu_put_be32s(f, &s->mouse_cx); 1274 qemu_put_be32s(f, &s->mouse_cy); 1041 1275 qemu_put_8s(f, &s->mouse_buttons); 1276 qemu_put_8s(f, &s->mouse_buttons_reported); 1277 qemu_put_8s(f, &s->mouse_last_button); 1042 1278 1043 1279 /* XXX: s->scancode_set isn't being saved, but we only really support set 2, … … 1089 1325 qemu_get_8s(f, &s->mouse_wrap); 1090 1326 qemu_get_8s(f, &s->mouse_type); 1327 if (s->mouse_type == MOUSE_PROT_LIFEBOOK) 1328 s->Mouse.pDrv->pfnAbsModeChange(s->Mouse.pDrv, true); 1091 1329 qemu_get_8s(f, &s->mouse_detect_state); 1092 1330 qemu_get_be32s(f, (uint32_t *)&s->mouse_dx); … … 1099 1337 } 1100 1338 qemu_get_8s(f, &s->mouse_buttons); 1339 if (version_id > 3) 1340 { 1341 SSMR3GetS32(f, &s->mouse_cx); 1342 SSMR3GetS32(f, &s->mouse_cy); 1343 SSMR3GetU8(f, &s->mouse_buttons_reported); 1344 SSMR3GetU8(f, &s->mouse_last_button); 1345 } 1101 1346 s->queue.count = 0; 1102 1347 s->queue.rptr = 0; … … 1423 1668 1424 1669 pc_kbd_mouse_event(pThis, i32DeltaX, i32DeltaY, i32DeltaZ, i32DeltaW, fButtonStates); 1670 1671 PDMCritSectLeave(&pThis->CritSect); 1672 return VINF_SUCCESS; 1673 } 1674 1675 /** 1676 * Mouse event handler. 1677 * 1678 * @returns VBox status code. 1679 * @param pInterface Pointer to the mouse port interface (KBDState::Mouse.IPort). 1680 * @param i32cX The X value. 1681 * @param i32cY The Y value. 1682 */ 1683 static DECLCALLBACK(int) kbdMousePutEventAbs(PPDMIMOUSEPORT pInterface, int32_t i32cX, int32_t i32cY) 1684 { 1685 KBDState *pThis = RT_FROM_MEMBER(pInterface, KBDState, Mouse.IPort); 1686 int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY); 1687 AssertReleaseRC(rc); 1688 1689 pc_kbd_mouse_event_abs(pThis, i32cX, i32cY); 1425 1690 1426 1691 PDMCritSectLeave(&pThis->CritSect); … … 1619 1884 pThis->Mouse.IBase.pfnQueryInterface = kbdMouseQueryInterface; 1620 1885 pThis->Mouse.IPort.pfnPutEvent = kbdMousePutEvent; 1886 pThis->Mouse.IPort.pfnPutEventAbs = kbdMousePutEventAbs; 1621 1887 1622 1888 /* -
trunk/src/VBox/Devices/Input/DrvMouseQueue.cpp
r26173 r26624 69 69 /** The core part owned by the queue manager. */ 70 70 PDMQUEUEITEMCORE Core; 71 uint32_t fAbs; 71 72 int32_t i32DeltaX; 72 73 int32_t i32DeltaY; … … 74 75 int32_t i32DeltaW; 75 76 uint32_t fButtonStates; 77 int32_t i32cX; 78 int32_t i32cY; 76 79 } DRVMOUSEQUEUEITEM, *PDRVMOUSEQUEUEITEM; 77 80 … … 121 124 if (pItem) 122 125 { 126 pItem->fAbs = 0; 123 127 pItem->i32DeltaX = i32DeltaX; 124 128 pItem->i32DeltaY = i32DeltaY; … … 132 136 } 133 137 138 /** 139 * Queues an absolute mouse event. 140 * Because of the event queueing the EMT context requirement is lifted. 141 * 142 * @returns VBox status code. 143 * @param pInterface Pointer to interface structure. 144 * @param i32cX The X value. 145 * @param i32cY The Y value. 146 * @thread Any thread. 147 */ 148 static DECLCALLBACK(int) drvMouseQueuePutEventAbs(PPDMIMOUSEPORT pInterface, int32_t i32cX, int32_t i32cY) 149 { 150 PDRVMOUSEQUEUE pDrv = IMOUSEPORT_2_DRVMOUSEQUEUE(pInterface); 151 if (pDrv->fInactive) 152 return VINF_SUCCESS; 153 154 PDRVMOUSEQUEUEITEM pItem = (PDRVMOUSEQUEUEITEM)PDMQueueAlloc(pDrv->pQueue); 155 if (pItem) 156 { 157 pItem->fAbs = 1; 158 pItem->i32cX = i32cX; 159 pItem->i32cY = i32cY; 160 PDMQueueInsert(pDrv->pQueue, &pItem->Core); 161 return VINF_SUCCESS; 162 } 163 return VERR_PDM_NO_QUEUE_ITEMS; 164 } 165 166 167 /* -=-=-=-=- IConnector -=-=-=-=- */ 168 169 #define PPDMIMOUSECONNECTOR_2_DRVMOUSEQUEUE(pInterface) ( (PDRVMOUSEQUEUE)((char *)(pInterface) - RT_OFFSETOF(DRVMOUSEQUEUE, IConnector)) ) 170 171 172 /** 173 * Pass absolute mode status changes from the guest through to the frontend 174 * driver. 175 * 176 * @param pInterface Pointer to the mouse connector interface structure. 177 * @param fAbs The new absolute mode state. 178 */ 179 static DECLCALLBACK(void) drvMousePassThruAbsMode(PPDMIMOUSECONNECTOR pInterface, bool fAbs) 180 { 181 PDRVMOUSEQUEUE pDrv = PPDMIMOUSECONNECTOR_2_DRVMOUSEQUEUE(pInterface); 182 pDrv->pDownConnector->pfnAbsModeChange(pDrv->pDownConnector, fAbs); 183 } 184 185 134 186 135 187 /* -=-=-=-=- queue -=-=-=-=- */ … … 147 199 PDRVMOUSEQUEUE pThis = PDMINS_2_DATA(pDrvIns, PDRVMOUSEQUEUE); 148 200 PDRVMOUSEQUEUEITEM pItem = (PDRVMOUSEQUEUEITEM)pItemCore; 149 int rc = pThis->pUpPort->pfnPutEvent(pThis->pUpPort, pItem->i32DeltaX, pItem->i32DeltaY, pItem->i32DeltaZ, pItem->i32DeltaW, pItem->fButtonStates); 201 int rc; 202 if (!pItem->fAbs) 203 rc = pThis->pUpPort->pfnPutEvent(pThis->pUpPort, pItem->i32DeltaX, pItem->i32DeltaY, pItem->i32DeltaZ, pItem->i32DeltaW, pItem->fButtonStates); 204 else 205 rc = pThis->pUpPort->pfnPutEventAbs(pThis->pUpPort, pItem->i32cX, pItem->i32cY); 150 206 return RT_SUCCESS(rc); 151 207 } … … 241 297 /* IBase. */ 242 298 pDrvIns->IBase.pfnQueryInterface = drvMouseQueueQueryInterface; 299 /* IMouseConnector. */ 300 pDrv->IConnector.pfnAbsModeChange = drvMousePassThruAbsMode; 243 301 /* IMousePort. */ 244 302 pDrv->IPort.pfnPutEvent = drvMouseQueuePutEvent; 303 pDrv->IPort.pfnPutEventAbs = drvMouseQueuePutEventAbs; 245 304 246 305 /* -
trunk/src/VBox/Main/MouseImpl.cpp
r26235 r26624 46 46 } DRVMAINMOUSE, *PDRVMAINMOUSE; 47 47 48 48 /** Converts a PDMIMOUSECONNECTOR pointer to a DRVMAINMOUSE pointer. */ 49 #define PPDMIMOUSECONNECTOR_2_MAINMOUSE(pInterface) ( (PDRVMAINMOUSE) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINMOUSE, IConnector)) ) 49 50 50 51 // constructor / destructor … … 56 57 { 57 58 mpDrv = NULL; 58 mLastAbsX = 0; 59 mLastAbsY = 0; 59 mLastAbsX = 0x8000; 60 mLastAbsY = 0x8000; 61 mLastButtons = 0; 60 62 return S_OK; 61 63 } … … 93 95 uHostCaps = 0; 94 96 #endif 97 uDevCaps = 0; 95 98 96 99 /* Confirm a successful initialization */ … … 120 123 } 121 124 125 122 126 // IMouse properties 123 127 ///////////////////////////////////////////////////////////////////////////// 124 128 129 int Mouse::getVMMDevMouseCaps(uint32_t *pfCaps) 130 { 131 AssertPtrReturn(pfCaps, E_POINTER); 132 VMMDev *pVMMDev = mParent->getVMMDev(); 133 ComAssertRet(pVMMDev, E_FAIL); 134 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort(); 135 ComAssertRet(pVMMDevPort, E_FAIL); 136 137 int rc = pVMMDevPort->pfnQueryMouseCapabilities(pVMMDevPort, pfCaps); 138 return RT_SUCCESS(rc) ? S_OK : E_FAIL; 139 } 140 141 int Mouse::setVMMDevMouseCaps(uint32_t fCaps) 142 { 143 VMMDev *pVMMDev = mParent->getVMMDev(); 144 ComAssertRet(pVMMDev, E_FAIL); 145 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort(); 146 ComAssertRet(pVMMDevPort, E_FAIL); 147 148 int rc = pVMMDevPort->pfnSetMouseCapabilities(pVMMDevPort, fCaps); 149 return RT_SUCCESS(rc) ? S_OK : E_FAIL; 150 } 151 125 152 /** 126 153 * Returns whether the current setup can accept absolute mouse … … 140 167 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 141 168 142 CHECK_CONSOLE_DRV (mpDrv); 143 144 ComAssertRet(mParent->getVMMDev(), E_FAIL); 145 ComAssertRet(mParent->getVMMDev()->getVMMDevPort(), E_FAIL); 146 147 *absoluteSupported = FALSE; 148 uint32_t mouseCaps; 149 mParent->getVMMDev()->getVMMDevPort()->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(), &mouseCaps); 150 *absoluteSupported = mouseCaps & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE; 151 152 return S_OK; 153 } 154 155 /** 156 * Returns whether the current setup can accept relative mouse 157 * events. 169 if (uDevCaps & MOUSE_DEVCAP_ABSOLUTE) 170 *absoluteSupported = TRUE; 171 else 172 { 173 CHECK_CONSOLE_DRV (mpDrv); 174 175 uint32_t mouseCaps; 176 int rc = getVMMDevMouseCaps(&mouseCaps); 177 AssertComRCReturn(rc, rc); 178 *absoluteSupported = mouseCaps & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE; 179 } 180 181 return S_OK; 182 } 183 184 /** 185 * Returns whether the guest can currently draw the mouse cursor itself. 158 186 * 159 187 * @returns COM status code 160 188 * @param absoluteSupported address of result variable 161 189 */ 162 STDMETHODIMP Mouse::COMGETTER(NeedsHostCursor) (BOOL * needsHostCursor)163 { 164 if (! needsHostCursor)190 STDMETHODIMP Mouse::COMGETTER(NeedsHostCursor) (BOOL *pfNeedsHostCursor) 191 { 192 if (!pfNeedsHostCursor) 165 193 return E_POINTER; 166 194 … … 172 200 CHECK_CONSOLE_DRV (mpDrv); 173 201 174 ComAssertRet(mParent->getVMMDev(), E_FAIL); 175 ComAssertRet(mParent->getVMMDev()->getVMMDevPort(), E_FAIL); 176 177 *needsHostCursor = FALSE; 178 uint32_t mouseCaps; 179 mParent->getVMMDev()->getVMMDevPort()->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(), &mouseCaps); 180 *needsHostCursor = mouseCaps & VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR; 181 202 uint32_t fMouseCaps; 203 int rc = getVMMDevMouseCaps(&fMouseCaps); 204 AssertComRCReturn(rc, rc); 205 *pfNeedsHostCursor = !!( fMouseCaps 206 & VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR); 182 207 return S_OK; 183 208 } … … 186 211 ///////////////////////////////////////////////////////////////////////////// 187 212 188 /** 189 * Send a mouse event. 190 * 191 * @returns COM status code 192 * @param dx X movement 193 * @param dy Y movement 194 * @param dz Z movement 195 * @param buttonState The mouse button state 196 */ 197 STDMETHODIMP Mouse::PutMouseEvent(LONG dx, LONG dy, LONG dz, LONG dw, LONG buttonState) 198 { 199 HRESULT rc = S_OK; 200 201 AutoCaller autoCaller(this); 202 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 203 204 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 205 206 CHECK_CONSOLE_DRV (mpDrv); 207 208 ComAssertRet(mParent->getVMMDev(), E_FAIL); 209 ComAssertRet(mParent->getVMMDev()->getVMMDevPort(), E_FAIL); 210 211 uint32_t mouseCaps; 212 LogRel3(("%s: dx=%d, dy=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__, 213 dx, dy, dz, dw)); 214 mParent->getVMMDev()->getVMMDevPort() 215 ->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(), 216 &mouseCaps); 217 /* 218 * This method being called implies that the host no 219 * longer wants to use absolute coordinates. If the VMM 220 * device isn't aware of that yet, tell it. 221 */ 222 if (mouseCaps & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE) 223 { 224 mParent->getVMMDev()->getVMMDevPort()->pfnSetMouseCapabilities( 225 mParent->getVMMDev()->getVMMDevPort(), uHostCaps); 226 } 227 213 static uint32_t mouseButtonsToPDM(LONG buttonState) 214 { 228 215 uint32_t fButtons = 0; 229 216 if (buttonState & MouseButtonState_LeftButton) … … 237 224 if (buttonState & MouseButtonState_XButton2) 238 225 fButtons |= PDMIMOUSEPORT_BUTTON_X2; 239 240 int vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, dx, dy, dz, dw, fButtons); 241 if (RT_FAILURE(vrc)) 242 rc = setError(VBOX_E_IPRT_ERROR, 243 tr("Could not send the mouse event to the virtual mouse (%Rrc)"), 244 vrc); 226 return fButtons; 227 } 228 229 230 /** 231 * Send a relative event to the mouse device. 232 * 233 * @returns COM status code 234 */ 235 int Mouse::reportRelEventToMouseDev(int32_t dx, int32_t dy, int32_t dz, 236 int32_t dw, uint32_t fButtons) 237 { 238 CHECK_CONSOLE_DRV (mpDrv); 239 240 if (dx || dy || dz || dw || fButtons != mLastButtons) 241 { 242 PPDMIMOUSEPORT pUpPort = mpDrv->pUpPort; 243 int vrc = pUpPort->pfnPutEvent(pUpPort, dx, dy, dz, dw, fButtons); 244 245 if (RT_FAILURE(vrc)) 246 setError(VBOX_E_IPRT_ERROR, 247 tr("Could not send the mouse event to the virtual mouse (%Rrc)"), 248 vrc); 249 AssertRCReturn(vrc, VBOX_E_IPRT_ERROR); 250 } 251 return S_OK; 252 } 253 254 255 /** 256 * Send an absolute position event to the mouse device. 257 * 258 * @returns COM status code 259 */ 260 int Mouse::reportAbsEventToMouseDev(uint32_t mouseXAbs, uint32_t mouseYAbs) 261 { 262 CHECK_CONSOLE_DRV (mpDrv); 263 264 if (mouseXAbs != mLastAbsX || mouseYAbs != mLastAbsY) 265 { 266 int vrc = mpDrv->pUpPort->pfnPutEventAbs(mpDrv->pUpPort, mouseXAbs, 267 mouseYAbs); 268 if (RT_FAILURE(vrc)) 269 setError(VBOX_E_IPRT_ERROR, 270 tr("Could not send the mouse event to the virtual mouse (%Rrc)"), 271 vrc); 272 AssertRCReturn(vrc, VBOX_E_IPRT_ERROR); 273 } 274 return S_OK; 275 } 276 277 278 /** 279 * Send an absolute position event to the VMM device. 280 * 281 * @returns COM status code 282 */ 283 int Mouse::reportAbsEventToVMMDev(uint32_t mouseXAbs, uint32_t mouseYAbs) 284 { 285 VMMDev *pVMMDev = mParent->getVMMDev(); 286 ComAssertRet(pVMMDev, E_FAIL); 287 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort(); 288 ComAssertRet(pVMMDevPort, E_FAIL); 289 290 if (mouseXAbs != mLastAbsX || mouseYAbs != mLastAbsY) 291 { 292 int vrc = pVMMDevPort->pfnSetAbsoluteMouse(pVMMDevPort, 293 mouseXAbs, mouseYAbs); 294 if (RT_FAILURE(vrc)) 295 setError(VBOX_E_IPRT_ERROR, 296 tr("Could not send the mouse event to the virtual mouse (%Rrc)"), 297 vrc); 298 AssertRCReturn(vrc, VBOX_E_IPRT_ERROR); 299 } 300 return S_OK; 301 } 302 303 /** 304 * Send a mouse event. 305 * 306 * @returns COM status code 307 * @param dx X movement 308 * @param dy Y movement 309 * @param dz Z movement 310 * @param buttonState The mouse button state 311 */ 312 STDMETHODIMP Mouse::PutMouseEvent(LONG dx, LONG dy, LONG dz, LONG dw, LONG buttonState) 313 { 314 HRESULT rc = S_OK; 315 316 AutoCaller autoCaller(this); 317 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 318 319 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 320 321 CHECK_CONSOLE_DRV (mpDrv); 322 323 LogRel3(("%s: dx=%d, dy=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__, 324 dx, dy, dz, dw)); 325 if (!(uDevCaps & MOUSE_DEVCAP_ABSOLUTE)) 326 { 327 /* 328 * This method being called implies that the host no 329 * longer wants to use absolute coordinates. If the VMM 330 * device isn't aware of that yet, tell it. 331 */ 332 uint32_t mouseCaps; 333 rc = getVMMDevMouseCaps(&mouseCaps); 334 ComAssertComRCRet(rc, rc); 335 336 if (mouseCaps & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE) 337 setVMMDevMouseCaps(uHostCaps); 338 } 339 340 uint32_t fButtons = mouseButtonsToPDM(buttonState); 341 rc = reportRelEventToMouseDev(dx, dy, dz, dw, fButtons); 342 if (SUCCEEDED(rc)) 343 mLastButtons = fButtons; 245 344 246 345 return rc; 247 346 } 347 348 /** 349 * Convert an X value in screen co-ordinates to a value from 0 to 0xffff 350 * 351 * @returns COM status value 352 */ 353 int Mouse::convertDisplayWidth(LONG x, uint32_t *pcX) 354 { 355 AssertPtrReturn(pcX, E_POINTER); 356 Display *pDisplay = mParent->getDisplay(); 357 ComAssertRet(pDisplay, E_FAIL); 358 359 ULONG displayWidth; 360 int rc = pDisplay->COMGETTER(Width)(&displayWidth); 361 ComAssertComRCRet(rc, rc); 362 363 *pcX = displayWidth ? (x * 0xFFFF) / displayWidth: 0; 364 return S_OK; 365 } 366 367 /** 368 * Convert a Y value in screen co-ordinates to a value from 0 to 0xffff 369 * 370 * @returns COM status value 371 */ 372 int Mouse::convertDisplayHeight(LONG y, uint32_t *pcY) 373 { 374 AssertPtrReturn(pcY, E_POINTER); 375 Display *pDisplay = mParent->getDisplay(); 376 ComAssertRet(pDisplay, E_FAIL); 377 378 ULONG displayHeight; 379 int rc = pDisplay->COMGETTER(Height)(&displayHeight); 380 ComAssertComRCRet(rc, rc); 381 382 *pcY = displayHeight ? (y * 0xFFFF) / displayHeight: 0; 383 return S_OK; 384 } 385 248 386 249 387 /** … … 267 405 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 268 406 269 CHECK_CONSOLE_DRV (mpDrv);270 271 ComAssertRet(mParent->getVMMDev(), E_FAIL);272 ComAssertRet(mParent->getVMMDev()->getVMMDevPort(), E_FAIL);273 274 uint32_t mouseCaps;275 407 LogRel3(("%s: x=%d, y=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__, 276 408 x, y, dz, dw)); 277 mParent->getVMMDev()->getVMMDevPort() 278 ->pfnQueryMouseCapabilities(mParent->getVMMDev()->getVMMDevPort(), 279 &mouseCaps); 280 /* 281 * This method being called implies that the host wants 282 * to use absolute coordinates. If the VMM device isn't 283 * aware of that yet, tell it. 284 */ 285 if (!(mouseCaps & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE)) 286 { 287 mParent->getVMMDev()->getVMMDevPort()->pfnSetMouseCapabilities( 288 mParent->getVMMDev()->getVMMDevPort(), 289 uHostCaps | VMMDEV_MOUSE_HOST_CAN_ABSOLUTE); 290 } 291 292 Display *pDisplay = mParent->getDisplay(); 293 ComAssertRet(pDisplay, E_FAIL); 294 295 ULONG displayWidth; 296 ULONG displayHeight; 297 rc = pDisplay->COMGETTER(Width)(&displayWidth); 409 410 uint32_t mouseXAbs; 411 rc = convertDisplayWidth(x, &mouseXAbs); 298 412 ComAssertComRCRet(rc, rc); 299 rc = pDisplay->COMGETTER(Height)(&displayHeight); 413 uint32_t mouseYAbs; 414 rc = convertDisplayHeight(y, &mouseYAbs); 300 415 ComAssertComRCRet(rc, rc); 301 302 uint32_t mouseXAbs = displayWidth? (x * 0xFFFF) / displayWidth: 0; 303 uint32_t mouseYAbs = displayHeight? (y * 0xFFFF) / displayHeight: 0; 304 305 /* 306 * Send the absolute mouse position to the VMM device. 307 */ 308 int vrc = mParent->getVMMDev()->getVMMDevPort() 309 ->pfnSetAbsoluteMouse(mParent->getVMMDev()->getVMMDevPort(), 310 mouseXAbs, mouseYAbs); 311 ComAssertRCRet (vrc, E_FAIL); 312 313 // Check if the guest actually wants absolute mouse positions. 314 if (mouseCaps & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE) 315 { 316 uint32_t fButtons = 0; 317 if (buttonState & MouseButtonState_LeftButton) 318 fButtons |= PDMIMOUSEPORT_BUTTON_LEFT; 319 if (buttonState & MouseButtonState_RightButton) 320 fButtons |= PDMIMOUSEPORT_BUTTON_RIGHT; 321 if (buttonState & MouseButtonState_MiddleButton) 322 fButtons |= PDMIMOUSEPORT_BUTTON_MIDDLE; 323 if (buttonState & MouseButtonState_XButton1) 324 fButtons |= PDMIMOUSEPORT_BUTTON_X1; 325 if (buttonState & MouseButtonState_XButton2) 326 fButtons |= PDMIMOUSEPORT_BUTTON_X2; 327 328 /* This is a workaround. In order to alert the Guest Additions to the 329 * fact that the absolute pointer position has changed, we send a 330 * a minute movement event to the PS/2 mouse device. But in order 331 * to avoid the mouse jiggling every time the use clicks, we check to 332 * see if the position has really changed since the last mouse event. 416 uint32_t fButtons = mouseButtonsToPDM(buttonState); 417 /* Older guest additions rely on a small phony movement event on the 418 * PS/2 device to notice absolute events. */ 419 bool fNeedsJiggle = false; 420 421 if (uDevCaps & MOUSE_DEVCAP_ABSOLUTE) 422 rc = reportAbsEventToMouseDev(mouseXAbs, mouseYAbs); 423 else 424 { 425 uint32_t mouseCaps; 426 rc = getVMMDevMouseCaps(&mouseCaps); 427 ComAssertComRCRet(rc, rc); 428 /* 429 * This method being called implies that the host wants 430 * to use absolute coordinates. If the VMM device isn't 431 * aware of that yet, tell it. 333 432 */ 334 if ( ((mLastAbsX == mouseXAbs) && (mLastAbsY == mouseYAbs)) 335 || (mouseCaps & VMMDEV_MOUSE_GUEST_USES_VMMDEV)) 336 vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, 0, 0, dz, dw, 337 fButtons); 338 else 339 vrc = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, 1, 1, dz, dw, 340 fButtons); 341 mLastAbsX = mouseXAbs; 342 mLastAbsY = mouseYAbs; 343 if (RT_FAILURE(vrc)) 344 rc = setError(VBOX_E_IPRT_ERROR, 345 tr("Could not send the mouse event to the virtual mouse (%Rrc)"), 346 vrc); 347 } 348 433 if (!(mouseCaps & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE)) 434 setVMMDevMouseCaps(uHostCaps | VMMDEV_MOUSE_HOST_CAN_ABSOLUTE); 435 436 /* 437 * Send the absolute mouse position to the VMM device. 438 */ 439 rc = reportAbsEventToVMMDev(mouseXAbs, mouseYAbs); 440 fNeedsJiggle = !(mouseCaps & VMMDEV_MOUSE_GUEST_USES_VMMDEV); 441 } 442 ComAssertComRCRet (rc, rc); 443 mLastAbsX = mouseXAbs; 444 mLastAbsY = mouseYAbs; 445 /* We may need to send a relative event for button information or to 446 * wake the guest up to the changed absolute co-ordinates. */ 447 /* If the event is a pure wake up one, we make sure it contains some 448 * (possibly phony) event data to make sure it isn't just discarded on 449 * the way. Note: we ignore dw as it is optional. */ 450 if (fNeedsJiggle || fButtons != mLastButtons || dz || dw) 451 rc = reportRelEventToMouseDev(fNeedsJiggle ? 1 : 0, 0, dz, dw, 452 fButtons); 453 if (SUCCEEDED(rc)) 454 mLastButtons = fButtons; 349 455 return rc; 350 456 } … … 384 490 pData->pMouse->mpDrv = NULL; 385 491 } 492 } 493 494 495 DECLCALLBACK(void) Mouse::mouseAbsModeChange (PPDMIMOUSECONNECTOR pInterface, bool fAbs) 496 { 497 PDRVMAINMOUSE pDrv = PPDMIMOUSECONNECTOR_2_MAINMOUSE (pInterface); 498 if (fAbs) 499 pDrv->pMouse->uDevCaps |= MOUSE_DEVCAP_ABSOLUTE; 500 else 501 pDrv->pMouse->uDevCaps &= ~MOUSE_DEVCAP_ABSOLUTE; 502 /** @todo we have to hack around the fact that VMMDev may not be 503 * initialised too close to startup. The real fix is to change the 504 * protocol for onMouseCapabilityChange so that we no longer need to 505 * query VMMDev, but that requires more changes that I want to do in 506 * the next commit, so it must be put off until the followup one. */ 507 uint32_t fMouseCaps = 0; 508 int rc = S_OK; 509 if ( pDrv->pMouse->mParent->getVMMDev() 510 && pDrv->pMouse->mParent->getVMMDev()->mpDrv) 511 rc = pDrv->pMouse->getVMMDevMouseCaps(&fMouseCaps); 512 AssertComRCReturnVoid(rc); 513 pDrv->pMouse->getParent()->onMouseCapabilityChange (fAbs, fMouseCaps & VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR); 386 514 } 387 515 … … 411 539 */ 412 540 pDrvIns->IBase.pfnQueryInterface = Mouse::drvQueryInterface; 541 542 pData->IConnector.pfnAbsModeChange = Mouse::mouseAbsModeChange; 413 543 414 544 /* -
trunk/src/VBox/Main/include/MouseImpl.h
r26173 r26624 46 46 typedef ConsoleEventBuffer<MouseEvent> MouseEventBuffer; 47 47 48 enum 49 { 50 MOUSE_DEVCAP_ABSOLUTE = 1 51 }; 52 48 53 class ATL_NO_VTABLE Mouse : 49 54 public VirtualBoxBase, … … 90 95 static const PDMDRVREG DrvReg; 91 96 97 Console *getParent() const 98 { 99 return mParent; 100 } 101 92 102 private: 93 103 94 104 static DECLCALLBACK(void *) drvQueryInterface(PPDMIBASE pInterface, const char *pszIID); 105 static DECLCALLBACK(void) mouseAbsModeChange (PPDMIMOUSECONNECTOR pInterface, bool fAbs); 95 106 static DECLCALLBACK(int) drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags); 96 107 static DECLCALLBACK(void) drvDestruct(PPDMDRVINS pDrvIns); 108 109 int getVMMDevMouseCaps(uint32_t *pfCaps); 110 int setVMMDevMouseCaps(uint32_t fCaps); 111 int reportRelEventToMouseDev(int32_t dx, int32_t dy, int32_t dz, 112 int32_t dw, uint32_t fButtons); 113 int reportAbsEventToMouseDev(uint32_t mouseXAbs, uint32_t mouseYAbs); 114 int reportAbsEventToVMMDev(uint32_t mouseXAbs, uint32_t mouseYAbs); 115 int convertDisplayWidth(LONG x, uint32_t *pcX); 116 int convertDisplayHeight(LONG y, uint32_t *pcY); 117 bool needsRelativeEvent(uint32_t cXAbs, uint32_t cYAbs, int32_t dz, int32_t dw, uint32_t fButtons, uint32_t fCaps); 97 118 98 119 const ComObjPtr<Console, ComWeakRef> mParent; … … 101 122 102 123 LONG uHostCaps; 124 LONG uDevCaps; 103 125 uint32_t mLastAbsX; 104 126 uint32_t mLastAbsY; 127 uint32_t mLastButtons; 105 128 }; 106 129
Note:
See TracChangeset
for help on using the changeset viewer.