@@ -152,6 +152,8 @@ export default class RFB extends EventTargetMixin {
152
152
153
153
this . _qemuExtKeyEventSupported = false ;
154
154
155
+ this . _extendedPointerEventSupported = false ;
156
+
155
157
this . _clipboardText = null ;
156
158
this . _clipboardServerCapabilitiesActions = { } ;
157
159
this . _clipboardServerCapabilitiesFormats = { } ;
@@ -1060,15 +1062,27 @@ export default class RFB extends EventTargetMixin {
1060
1062
let pos = clientToElement ( ev . clientX , ev . clientY ,
1061
1063
this . _canvas ) ;
1062
1064
1065
+ /* Map mouse back and forward mouse buttons (3 and 4) to 7 and 8
1066
+ *
1067
+ * NOTE: This only works on chromium-based browsers. There is
1068
+ * no support for firefox/safari.
1069
+ */
1070
+ let button = ev . button ;
1071
+ if ( button == 3 || button == 4 ) {
1072
+ button += 4 ;
1073
+ } else if ( button > 4 ) {
1074
+ // Unsupported mouse button
1075
+ return ;
1076
+ }
1063
1077
switch ( ev . type ) {
1064
1078
case 'mousedown' :
1065
1079
setCapture ( this . _canvas ) ;
1066
1080
this . _handleMouseButton ( pos . x , pos . y ,
1067
- true , 1 << ev . button ) ;
1081
+ true , 1 << button ) ;
1068
1082
break ;
1069
1083
case 'mouseup' :
1070
1084
this . _handleMouseButton ( pos . x , pos . y ,
1071
- false , 1 << ev . button ) ;
1085
+ false , 1 << button ) ;
1072
1086
break ;
1073
1087
case 'mousemove' :
1074
1088
this . _handleMouseMove ( pos . x , pos . y ) ;
@@ -1163,8 +1177,20 @@ export default class RFB extends EventTargetMixin {
1163
1177
if ( this . _rfbConnectionState !== 'connected' ) { return ; }
1164
1178
if ( this . _viewOnly ) { return ; } // View only, skip mouse events
1165
1179
1166
- RFB . messages . pointerEvent ( this . _sock , this . _display . absX ( x ) ,
1167
- this . _display . absY ( y ) , mask ) ;
1180
+ // Highest bit in mask is never sent to the server
1181
+ if ( mask & 0x8000 ) {
1182
+ throw new Error ( "Illegal mouse button mask (mask: " + mask + ")" ) ;
1183
+ }
1184
+
1185
+ let extendedMouseButtons = mask & 0x7f80 ;
1186
+
1187
+ if ( this . _extendedPointerEventSupported && extendedMouseButtons ) {
1188
+ RFB . messages . extendedPointerEvent ( this . _sock , this . _display . absX ( x ) ,
1189
+ this . _display . absY ( y ) , mask ) ;
1190
+ } else {
1191
+ RFB . messages . pointerEvent ( this . _sock , this . _display . absX ( x ) ,
1192
+ this . _display . absY ( y ) , mask ) ;
1193
+ }
1168
1194
}
1169
1195
1170
1196
_handleWheel ( ev ) {
@@ -2146,6 +2172,7 @@ export default class RFB extends EventTargetMixin {
2146
2172
encs . push ( encodings . pseudoEncodingContinuousUpdates ) ;
2147
2173
encs . push ( encodings . pseudoEncodingDesktopName ) ;
2148
2174
encs . push ( encodings . pseudoEncodingExtendedClipboard ) ;
2175
+ encs . push ( encodings . pseudoEncodingExtendedMouseButtons ) ;
2149
2176
2150
2177
if ( this . _fbDepth == 24 ) {
2151
2178
encs . push ( encodings . pseudoEncodingVMwareCursor ) ;
@@ -2575,6 +2602,10 @@ export default class RFB extends EventTargetMixin {
2575
2602
case encodings . pseudoEncodingExtendedDesktopSize :
2576
2603
return this . _handleExtendedDesktopSize ( ) ;
2577
2604
2605
+ case encodings . pseudoEncodingExtendedMouseButtons :
2606
+ this . _extendedPointerEventSupported = true ;
2607
+ return true ;
2608
+
2578
2609
case encodings . pseudoEncodingQEMULedEvent :
2579
2610
return this . _handleLedEvent ( ) ;
2580
2611
@@ -2983,6 +3014,10 @@ RFB.messages = {
2983
3014
pointerEvent ( sock , x , y , mask ) {
2984
3015
sock . sQpush8 ( 5 ) ; // msg-type
2985
3016
3017
+ // Marker bit must be set to 0, otherwise the server might
3018
+ // confuse the marker bit with the highest bit in a normal
3019
+ // PointerEvent message.
3020
+ mask = mask & 0x7f ;
2986
3021
sock . sQpush8 ( mask ) ;
2987
3022
2988
3023
sock . sQpush16 ( x ) ;
@@ -2991,6 +3026,27 @@ RFB.messages = {
2991
3026
sock . flush ( ) ;
2992
3027
} ,
2993
3028
3029
+ extendedPointerEvent ( sock , x , y , mask ) {
3030
+ sock . sQpush8 ( 5 ) ; // msg-type
3031
+
3032
+ let higherBits = ( mask >> 7 ) & 0xff ;
3033
+
3034
+ // Bits 2-7 are reserved
3035
+ if ( higherBits & 0xfc ) {
3036
+ throw new Error ( "Invalid mouse button mask: " + mask ) ;
3037
+ }
3038
+
3039
+ let lowerBits = mask & 0x7f ;
3040
+ lowerBits |= 0x80 ; // Set marker bit to 1
3041
+
3042
+ sock . sQpush8 ( lowerBits ) ;
3043
+ sock . sQpush16 ( x ) ;
3044
+ sock . sQpush16 ( y ) ;
3045
+ sock . sQpush8 ( higherBits ) ;
3046
+
3047
+ sock . flush ( ) ;
3048
+ } ,
3049
+
2994
3050
// Used to build Notify and Request data.
2995
3051
_buildExtendedClipboardFlags ( actions , formats ) {
2996
3052
let data = new Uint8Array ( 4 ) ;
0 commit comments