@@ -410,6 +410,23 @@ function vtkRenderWindowInteractor(publicAPI, model) {
410410 }
411411 } ;
412412
413+ function handleChordedButtons ( callData , previous , current ) {
414+ /* eslint-disable no-bitwise */
415+ if ( ( previous & ~ current & 1 ) !== 0 )
416+ publicAPI . leftButtonReleaseEvent ( callData ) ;
417+ if ( ( previous & ~ current & 4 ) !== 0 )
418+ publicAPI . middleButtonReleaseEvent ( callData ) ;
419+ if ( ( previous & ~ current & 2 ) !== 0 )
420+ publicAPI . rightButtonReleaseEvent ( callData ) ;
421+ if ( ( ~ previous & current & 1 ) !== 0 )
422+ publicAPI . leftButtonPressEvent ( callData ) ;
423+ if ( ( ~ previous & current & 4 ) !== 0 )
424+ publicAPI . middleButtonPressEvent ( callData ) ;
425+ if ( ( ~ previous & current & 2 ) !== 0 )
426+ publicAPI . rightButtonPressEvent ( callData ) ;
427+ /* eslint-enable no-bitwise */
428+ }
429+
413430 publicAPI . handlePointerUp = ( event ) => {
414431 if ( pointerCache . has ( event . pointerId ) ) {
415432 if ( model . preventDefaultOnPointerUp ) {
@@ -426,33 +443,26 @@ function vtkRenderWindowInteractor(publicAPI, model) {
426443 break ;
427444 case 'mouse' :
428445 default : {
429- // Detect chorded button releases: when pointerup fires, additional
430- // buttons may have been released simultaneously. Fire release events
431- // for those chorded buttons before handling the primary button.
432- const currentButtons = event . buttons ;
433- if ( currentButtons !== previousMouseButtons ) {
434- const callData = {
435- ...getModifierKeysFor ( event ) ,
436- position : getScreenEventPositionFor ( event ) ,
437- deviceType : getDeviceTypeFor ( event ) ,
438- } ;
439- const wasLeft = ( previousMouseButtons & 1 ) !== 0 ; // eslint-disable-line no-bitwise
440- const wasRight = ( previousMouseButtons & 2 ) !== 0 ; // eslint-disable-line no-bitwise
441- const wasMiddle = ( previousMouseButtons & 4 ) !== 0 ; // eslint-disable-line no-bitwise
442- const isLeft = ( currentButtons & 1 ) !== 0 ; // eslint-disable-line no-bitwise
443- const isRight = ( currentButtons & 2 ) !== 0 ; // eslint-disable-line no-bitwise
444- const isMiddle = ( currentButtons & 4 ) !== 0 ; // eslint-disable-line no-bitwise
445- // Only fire for chorded buttons; the primary button (event.button)
446- // is handled by handleMouseUp below.
447- if ( ! isLeft && wasLeft && event . button !== 0 )
448- publicAPI . leftButtonReleaseEvent ( callData ) ;
449- if ( ! isMiddle && wasMiddle && event . button !== 1 )
450- publicAPI . middleButtonReleaseEvent ( callData ) ;
451- if ( ! isRight && wasRight && event . button !== 2 )
452- publicAPI . rightButtonReleaseEvent ( callData ) ;
453- }
446+ // buttons bitmask: 1=left, 4=middle, 2=right
447+ // eslint-disable-next-line no-bitwise
448+ const buttonBitMap = [ 1 , 4 , 2 ] ;
449+ // eslint-disable-next-line no-bitwise
450+ const buttonBit = buttonBitMap [ event . button ] ?? 0 ;
451+ const callData = {
452+ ...getModifierKeysFor ( event ) ,
453+ position : getScreenEventPositionFor ( event ) ,
454+ deviceType : getDeviceTypeFor ( event ) ,
455+ } ;
456+ // Mask out the primary button — handleMouseUp handles it below.
457+ /* eslint-disable no-bitwise */
458+ handleChordedButtons (
459+ callData ,
460+ previousMouseButtons & ~ buttonBit ,
461+ event . buttons & ~ buttonBit
462+ ) ;
463+ /* eslint-enable no-bitwise */
454464 publicAPI . handleMouseUp ( event ) ;
455- previousMouseButtons = currentButtons ;
465+ previousMouseButtons = event . buttons ;
456466 break ;
457467 }
458468 }
@@ -470,22 +480,12 @@ function vtkRenderWindowInteractor(publicAPI, model) {
470480 break ;
471481 case 'mouse' :
472482 default : {
473- // Fire release events for all buttons that were held when the
474- // pointer interaction was cancelled.
475483 const callData = {
476484 ...getModifierKeysFor ( event ) ,
477485 position : getScreenEventPositionFor ( event ) ,
478486 deviceType : getDeviceTypeFor ( event ) ,
479487 } ;
480- // eslint-disable-next-line no-bitwise
481- if ( ( previousMouseButtons & 1 ) !== 0 )
482- publicAPI . leftButtonReleaseEvent ( callData ) ;
483- // eslint-disable-next-line no-bitwise
484- if ( ( previousMouseButtons & 4 ) !== 0 )
485- publicAPI . middleButtonReleaseEvent ( callData ) ;
486- // eslint-disable-next-line no-bitwise
487- if ( ( previousMouseButtons & 2 ) !== 0 )
488- publicAPI . rightButtonReleaseEvent ( callData ) ;
488+ handleChordedButtons ( callData , previousMouseButtons , 0 ) ;
489489 previousMouseButtons = 0 ;
490490 break ;
491491 }
@@ -517,21 +517,7 @@ function vtkRenderWindowInteractor(publicAPI, model) {
517517 position : getScreenEventPositionFor ( event ) ,
518518 deviceType : getDeviceTypeFor ( event ) ,
519519 } ;
520- // buttons bitmask: 1=left, 2=right, 4=middle
521- const wasLeft = ( previousMouseButtons & 1 ) !== 0 ; // eslint-disable-line no-bitwise
522- const wasRight = ( previousMouseButtons & 2 ) !== 0 ; // eslint-disable-line no-bitwise
523- const wasMiddle = ( previousMouseButtons & 4 ) !== 0 ; // eslint-disable-line no-bitwise
524- const isLeft = ( currentButtons & 1 ) !== 0 ; // eslint-disable-line no-bitwise
525- const isRight = ( currentButtons & 2 ) !== 0 ; // eslint-disable-line no-bitwise
526- const isMiddle = ( currentButtons & 4 ) !== 0 ; // eslint-disable-line no-bitwise
527- if ( isLeft && ! wasLeft ) publicAPI . leftButtonPressEvent ( callData ) ;
528- if ( isMiddle && ! wasMiddle )
529- publicAPI . middleButtonPressEvent ( callData ) ;
530- if ( isRight && ! wasRight ) publicAPI . rightButtonPressEvent ( callData ) ;
531- if ( ! isLeft && wasLeft ) publicAPI . leftButtonReleaseEvent ( callData ) ;
532- if ( ! isMiddle && wasMiddle )
533- publicAPI . middleButtonReleaseEvent ( callData ) ;
534- if ( ! isRight && wasRight ) publicAPI . rightButtonReleaseEvent ( callData ) ;
520+ handleChordedButtons ( callData , previousMouseButtons , currentButtons ) ;
535521 previousMouseButtons = currentButtons ;
536522 }
537523 publicAPI . handleMouseMove ( event ) ;
0 commit comments