@@ -672,7 +672,6 @@ function setupSensorsBlocks(activity) {
672672 return parseInt ( Number ( obj [ 0 ] ) / 2.55 ) ;
673673 }
674674 }
675-
676675 /**
677676 * Represents a block that returns the color of the pixel under the mouse or turtle.
678677 * @extends {ValueBlock }
@@ -710,7 +709,7 @@ function setupSensorsBlocks(activity) {
710709 updateParameter ( logo , turtle , blk ) {
711710 return toFixed2 ( activity . blocks . blockList [ blk ] . value ) ;
712711 }
713-
712+
714713 arg ( logo , turtle ) {
715714 let requiredTurtle ;
716715
@@ -730,38 +729,71 @@ function setupSensorsBlocks(activity) {
730729 const originalVisibility = requiredTurtle . container . visible ;
731730
732731 try {
732+ // Hide turtle temporarily
733733 requiredTurtle . container . visible = false ;
734734 activity . refreshCanvas ( ) ;
735735
736- const globalCoords = this . convertToPageCoordinates ( x , y ) ;
737- console . log ( "Global coordinates:" , globalCoords ) ;
738-
739- const canvases = Array . from ( document . getElementById ( "canvasHolder" ) . getElementsByTagName ( "canvas" ) ) ;
736+ // Get canvas holder
737+ const canvasHolder = document . getElementById ( "canvasHolder" ) ;
738+ if ( ! canvasHolder ) {
739+ throw new Error ( "Canvas holder not found" ) ;
740+ }
741+
742+ // Get all canvases
743+ const canvases = Array . from ( canvasHolder . getElementsByTagName ( "canvas" ) ) ;
740744 console . log ( "Found canvases:" , canvases . length ) ;
741-
745+
746+ // Get the bounding rectangle of canvas holder
747+ const holderRect = canvasHolder . getBoundingClientRect ( ) ;
748+
749+ // Get global coordinates (adjusted for platform differences)
750+ const globalCoords = this . getPlatformAdjustedCoordinates ( x , y , holderRect ) ;
751+ console . log ( "Platform-adjusted global coordinates:" , globalCoords ) ;
752+
742753 let detectedColor = null ;
743754
755+ // Iterate through canvases from top to bottom
744756 for ( let i = canvases . length - 1 ; i >= 0 ; i -- ) {
745757 const canvas = canvases [ i ] ;
746- const context = canvas . getContext ( "2d" ) ;
758+ const context = canvas . getContext ( "2d" , { willReadFrequently : true } ) ;
747759
748- // Convert global page coordinates to canvas-relative
749- const rect = canvas . getBoundingClientRect ( ) ;
750- const localX = globalCoords . x - rect . left ;
751- const localY = globalCoords . y - rect . top ;
752-
753- // Skip if outside bounds
754- if ( localX < 0 || localY < 0 || localX >= canvas . width || localY >= canvas . height ) continue ;
760+ // Get canvas position relative to viewport
761+ const canvasRect = canvas . getBoundingClientRect ( ) ;
762+
763+ // Calculate local coordinates within this canvas
764+ // Adjust calculation based on platform detection
765+ const localCoords = this . calculateLocalCoordinates ( globalCoords , canvasRect ) ;
766+ const localX = localCoords . x ;
767+ const localY = localCoords . y ;
768+
769+ console . log ( `Canvas ${ i } local coordinates:` , localX , localY ) ;
770+
771+ // Skip if outside canvas bounds
772+ if ( localX < 0 || localY < 0 || localX >= canvas . width || localY >= canvas . height ) {
773+ console . log ( `Canvas ${ i } : Out of bounds` ) ;
774+ continue ;
775+ }
755776
756- const pixelData = context . getImageData ( localX , localY , 1 , 1 ) . data ;
757- console . log ( `Canvas ${ i } : RGBA =` , pixelData ) ;
777+ try {
778+ // Get pixel data - handle slight differences between platforms
779+ const safeX = Math . floor ( Math . max ( 0 , Math . min ( localX , canvas . width - 1 ) ) ) ;
780+ const safeY = Math . floor ( Math . max ( 0 , Math . min ( localY , canvas . height - 1 ) ) ) ;
781+
782+ const pixelData = context . getImageData ( safeX , safeY , 1 , 1 ) . data ;
783+ console . log ( `Canvas ${ i } : RGBA =` , pixelData ) ;
758784
759- if ( pixelData [ 3 ] !== 0 ) { // Found non-transparent pixel
760- detectedColor = pixelData ;
761- break ;
785+ if ( pixelData [ 3 ] !== 0 ) { // Found non-transparent pixel
786+ detectedColor = pixelData ;
787+ break ;
788+ }
789+ } catch ( pixelError ) {
790+ console . warn ( `Error getting pixel data from canvas ${ i } :` , pixelError ) ;
791+ // Continue to next canvas if this one fails
792+ continue ;
762793 }
763794 }
764795
796+ // Restore turtle visibility
765797 requiredTurtle . container . visible = originalVisibility ;
766798
767799 if ( ! detectedColor ) {
@@ -782,71 +814,110 @@ function setupSensorsBlocks(activity) {
782814 }
783815
784816 /**
785- * Converts turtle coordinates to match absolute page coordinates.
786- * @param {number } x - The turtle's x-coordinate.
787- * @param {number } y - The turtle's y-coordinate.
788- * @returns {{x: number, y: number} } - Transformed coordinates.
817+ * Detects the platform and returns appropriate coordinates
818+ * @param {number } x - The turtle's x-coordinate
819+ * @param {number } y - The turtle's y-coordinate
820+ * @param {DOMRect } holderRect - The bounding rectangle of canvas holder
821+ * @returns {{x: number, y: number} } - Platform-adjusted coordinates
789822 */
790- convertToPageCoordinates ( x , y ) {
791- const canvasHolder = document . getElementById ( "canvasHolder" ) ;
792- if ( ! canvasHolder ) {
793- console . error ( "Canvas holder not found." ) ;
794- return { x, y } ;
823+ getPlatformAdjustedCoordinates ( x , y , holderRect ) {
824+ // Detect the platform
825+ const platform = this . detectPlatform ( ) ;
826+ console . log ( "Detected platform:" , platform ) ;
827+
828+ // Center of canvas holder
829+ const centerX = holderRect . width / 2 ;
830+ const centerY = holderRect . height / 2 ;
831+
832+ // Platform-specific adjustments
833+ switch ( platform ) {
834+ case 'macOS' :
835+ // For macOS, we need to adjust relative to the center
836+ return {
837+ x : holderRect . left + centerX + x ,
838+ y : holderRect . top + centerY + y
839+ } ;
840+ case 'Linux' :
841+ // Linux might need additional offset adjustments
842+ return {
843+ x : holderRect . left + centerX + x ,
844+ y : holderRect . top + centerY + y
845+ } ;
846+ case 'Windows' :
847+ default :
848+ // Keep original Windows calculation
849+ return {
850+ x : Math . floor ( x + holderRect . left ) ,
851+ y : Math . floor ( y + holderRect . top )
852+ } ;
795853 }
796-
797- const rect = canvasHolder . getBoundingClientRect ( ) ;
798- return {
799- x : Math . floor ( x - rect . left ) ,
800- y : Math . floor ( y - rect . top ) ,
801- } ;
802854 }
803-
855+
804856 /**
805- * Reads pixel data from a given canvas.
806- * @param {number } x - The x-coordinate.
807- * @param {number } y - The y-coordinate.
808- * @param {HTMLCanvasElement } canvas - The canvas element.
809- * @returns {Uint8ClampedArray } - The RGBA values of the pixel.
857+ * Calculate local coordinates within a specific canvas
858+ * @param {Object } globalCoords - Global coordinates
859+ * @param {DOMRect } canvasRect - Canvas bounding rectangle
860+ * @returns {{x: number, y: number} } - Local coordinates
810861 */
811- getPixelData ( x , y , canvas ) {
812- if ( ! canvas ) {
813- console . error ( "Canvas not found." ) ;
814- return new Uint8ClampedArray ( [ 0 , 0 , 0 , 0 ] ) ; // Default to transparent
862+ calculateLocalCoordinates ( globalCoords , canvasRect ) {
863+ const platform = this . detectPlatform ( ) ;
864+
865+ // Basic calculation that works on all platforms
866+ let localX = globalCoords . x - canvasRect . left ;
867+ let localY = globalCoords . y - canvasRect . top ;
868+
869+ // Platform-specific adjustments for coordinates
870+ if ( platform === 'macOS' ) {
871+ // macOS might need pixel density adjustment
872+ const pixelRatio = window . devicePixelRatio || 1 ;
873+ localX = localX * pixelRatio ;
874+ localY = localY * pixelRatio ;
875+ } else if ( platform === 'Linux' ) {
876+ // Linux might need different adjustment
877+ // This might need fine-tuning based on testing
815878 }
816- const ctx = canvas . getContext ( "2d" , { willReadFrequently : true } ) ;
817- if ( ! ctx ) {
818- throw new Error ( `Canvas context unavailable` ) ;
819- }
820- // Clamp coordinates to prevent out-of-bounds errors
821- const safeX = Math . max ( 0 , Math . min ( x , canvas . width - 1 ) ) ;
822- const safeY = Math . max ( 0 , Math . min ( y , canvas . height - 1 ) ) ;
823-
824- return ctx . getImageData ( safeX , safeY , 1 , 1 ) . data ;
879+
880+ return { x : localX , y : localY } ;
825881 }
826882
827883 /**
828- * Determines the color based on pixel data.
829- * @param {Uint8ClampedArray } pixelData - The RGBA values of the pixel.
830- * @returns {number } - The color index from searchColors.
884+ * Detects the operating system platform
885+ * @returns {string } - The detected platform ('Windows', 'macOS', 'Linux', or 'Unknown')
831886 */
832- detectColor ( pixelData ) {
833- if ( pixelData . length !== 4 ) {
834- throw new Error ( "Invalid pixel data" ) ;
887+ detectPlatform ( ) {
888+ const userAgent = navigator . userAgent . toLowerCase ( ) ;
889+
890+ if ( userAgent . indexOf ( 'mac' ) !== - 1 ) {
891+ return 'macOS' ;
892+ } else if ( userAgent . indexOf ( 'win' ) !== - 1 ) {
893+ return 'Windows' ;
894+ } else if ( userAgent . indexOf ( 'linux' ) !== - 1 ) {
895+ return 'Linux' ;
896+ } else {
897+ return 'Unknown' ;
835898 }
836- const [ r , g , b , a ] = pixelData ;
837- return a === 0 ? this . getBackgroundColor ( ) : searchColors ( r , g , b ) ;
838899 }
839900
840901 /**
841902 * Retrieves the background color as a fallback.
842903 * @returns {number } - The background color index.
843904 */
844905 getBackgroundColor ( ) {
845- const [ r , g , b ] = platformColor . background
846- . match ( / \( ( [ ^ ) ] + ) \) / ) [ 1 ]
847- . split ( / , \s * / )
848- . map ( Number ) ;
849- return searchColors ( r , g , b ) ;
906+ try {
907+ const bgColor = platformColor . background ;
908+ const matches = bgColor . match ( / \( ( [ ^ ) ] + ) \) / ) ;
909+
910+ if ( matches && matches [ 1 ] ) {
911+ const [ r , g , b ] = matches [ 1 ] . split ( / , \s * / ) . map ( Number ) ;
912+ return searchColors ( r , g , b ) ;
913+ } else {
914+ // Fallback if the regex fails
915+ return this . getFallbackColor ( ) ;
916+ }
917+ } catch ( error ) {
918+ console . error ( "Error parsing background color:" , error ) ;
919+ return this . getFallbackColor ( ) ;
920+ }
850921 }
851922
852923 /**
@@ -857,7 +928,6 @@ function setupSensorsBlocks(activity) {
857928 return searchColors ( 128 , 128 , 128 ) ;
858929 }
859930 }
860-
861931 /**
862932 * Represents a block that returns the number of seconds that the program has been running.
863933 * @extends {ValueBlock }
0 commit comments