diff --git a/CHANGELOG.md b/CHANGELOG.md
index 61fe3279..c69223e0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,8 @@
 All notable changes to this project will be documented in this file.
 This project adheres to [Semantic Versioning](http://semver.org/).
 
+- Support `fillRule` for `Konva.Shape` on hit graph
+
 ### 9.3.13 (2024-07-05)
 
 - Fallback for `Konva.Text.measureSize()` when 2d context doesn't return full data
diff --git a/src/Container.ts b/src/Container.ts
index efd4c2f5..d7bb5494 100644
--- a/src/Container.ts
+++ b/src/Container.ts
@@ -307,6 +307,7 @@ export abstract class Container<
    * canvas and redraw every shape inside the container, it should only be used for special situations
    * because it performs very poorly.  Please use the {@link Konva.Stage#getIntersection} method if at all possible
    * because it performs much better
+   * nodes with listening set to false will not be detected
    * @method
    * @name Konva.Container#getAllIntersections
    * @param {Object} pos
diff --git a/src/Layer.ts b/src/Layer.ts
index 9766ec21..4e5ff961 100644
--- a/src/Layer.ts
+++ b/src/Layer.ts
@@ -309,6 +309,7 @@ export class Layer extends Container<Group | Shape> {
    * get visible intersection shape. This is the preferred
    * method for determining if a point intersects a shape or not
    * also you may pass optional selector parameter to return ancestor of intersected shape
+   * nodes with listening set to false will not be detected
    * @method
    * @name Konva.Layer#getIntersection
    * @param {Object} pos
diff --git a/src/Node.ts b/src/Node.ts
index 281601c7..a26ce37b 100644
--- a/src/Node.ts
+++ b/src/Node.ts
@@ -3155,6 +3155,8 @@ addGetterSetter(Node, 'listening', true, getBooleanValidator());
 /**
  * get/set listening attr.  If you need to determine if a node is listening or not
  *   by taking into account its parents, use the isListening() method
+ *   nodes with listening set to false will not be detected in hit graph
+ *   so they will be ignored in container.getIntersection() method
  * @name Konva.Node#listening
  * @method
  * @param {Boolean} listening Can be true, or false.  The default is true.
diff --git a/src/Shape.ts b/src/Shape.ts
index 4d77de82..e34abbfd 100644
--- a/src/Shape.ts
+++ b/src/Shape.ts
@@ -128,8 +128,13 @@ function _fillFunc(this: Node, context) {
 function _strokeFunc(context) {
   context.stroke();
 }
-function _fillFuncHit(context) {
-  context.fill();
+function _fillFuncHit(this: Node, context) {
+  const fillRule = this.attrs.fillRule;
+  if (fillRule) {
+    context.fill(fillRule);
+  } else {
+    context.fill();
+  }
 }
 function _strokeFuncHit(context) {
   context.stroke();
diff --git a/src/Stage.ts b/src/Stage.ts
index 4fe8a567..b5ef1695 100644
--- a/src/Stage.ts
+++ b/src/Stage.ts
@@ -353,6 +353,7 @@ export class Stage extends Container<Layer> {
   /**
    * get visible intersection shape. This is the preferred
    *  method for determining if a point intersects a shape or not
+   * nodes with listening set to false will not be detected
    * @method
    * @name Konva.Stage#getIntersection
    * @param {Object} pos
diff --git a/test/unit/Shape-test.ts b/test/unit/Shape-test.ts
index 79d2e2d6..26758dda 100644
--- a/test/unit/Shape-test.ts
+++ b/test/unit/Shape-test.ts
@@ -2303,4 +2303,36 @@ describe('Shape', function () {
     assert.equal(callCount, 0);
     Konva.Util.warn = oldWarn;
   });
+
+  it('fill rule on hit graph', function () {
+    var stage = addStage();
+
+    var layer = new Konva.Layer();
+    stage.add(layer);
+
+    var mask = new Konva.Shape({
+      sceneFunc: function (ctx, shape) {
+        ctx.beginPath();
+        ctx.rect(0, 0, 500, 500);
+        ctx.rect(100, 100, 100, 100);
+        ctx.closePath();
+        ctx.fillShape(shape);
+      },
+      draggable: true,
+      fill: 'red',
+      fillRule: 'evenodd',
+    });
+
+    layer.add(mask);
+    layer.draw();
+    const trace = layer.getContext().getTrace();
+
+    assert.equal(
+      trace,
+      'clearRect(0,0,578,200);clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();rect(0,0,500,500);rect(100,100,100,100);closePath();fillStyle=red;fill(evenodd);restore();'
+    );
+
+    const hitShape = layer.getIntersection({ x: 150, y: 150 });
+    assert.equal(hitShape, null);
+  });
 });