diff --git a/js/build/jsroot.js b/js/build/jsroot.js
index ab78360e8c1e42a1d4aeeee893d88d9ceeebd793..dc13db82334031ae7d0438a6a43e112d819e388e 100644
--- a/js/build/jsroot.js
+++ b/js/build/jsroot.js
@@ -11,7 +11,7 @@ let version_id = 'dev';
 
 /** @summary version date
   * @desc Release date in format day/month/year like '19/11/2021' */
-let version_date = '15/11/2022';
+let version_date = '17/11/2022';
 
 /** @summary version id and date
   * @desc Produced by concatenation of {@link version_id} and {@link version_date}
@@ -7746,7 +7746,7 @@ function getElementRect(elem, sizearg) {
 /** @summary Calculate absolute position of provided element in canvas
   * @private */
 function getAbsPosInCanvas(sel, pos) {
-   while (!sel.empty() && !sel.classed('root_canvas') && pos) {
+   while (pos && !sel.empty() && !sel.classed('root_canvas')) {
       let cl = sel.attr('class');
       if (cl && ((cl.indexOf('root_frame') >= 0) || (cl.indexOf('__root_pad_') >= 0))) {
          pos.x += sel.property('draw_x') || 0;
@@ -49525,7 +49525,8 @@ const TooltipHandler = {
 
    /** @summary central function which let show selected hints for the object */
    processFrameTooltipEvent(pnt, evnt) {
-      if (pnt && pnt.handler) {
+
+      if (pnt?.handler) {
          // special use of interactive handler in the frame painter
          let rect = this.draw_g ? this.draw_g.select('.main_layer') : null;
          if (!rect || rect.empty()) {
@@ -49553,7 +49554,10 @@ const TooltipHandler = {
       // collect tooltips from pad painter - it has list of all drawn objects
       if (pp) hints = pp.processPadTooltipEvent(pnt);
 
-      if (pnt && pnt.touch) textheight = 15;
+      if (pp?._deliver_webcanvas_events && pp?.is_active_pad && pnt && isFunc(pp?.deliverWebCanvasEvent))
+         pp.deliverWebCanvasEvent('move', frame_rect.x + pnt.x, frame_rect.y + pnt.y, hints);
+
+      if (pnt?.touch) textheight = 15;
 
       for (let n = 0; n < hints.length; ++n) {
          let hint = hints[n];
@@ -49563,7 +49567,8 @@ const TooltipHandler = {
             hint.painter.provideUserTooltip(hint.user_info);
 
          if (!hint.lines || (hint.lines.length === 0)) {
-            hints[n] = null; continue;
+            hints[n] = null;
+            continue;
          }
 
          // check if fully duplicated hint already exists
@@ -49621,7 +49626,6 @@ const TooltipHandler = {
 
       this.showObjectStatus(name, title, info, coordinates);
 
-
       // end of closing tooltips
       if (!pnt || disable_tootlips || (hints.length === 0) || (maxlen === 0) || (show_only_best && !best_hint)) {
          hintsg.remove();
@@ -54096,18 +54100,18 @@ class TPadPainter extends ObjectPainter {
    }
 
    /** @summary method redirect call to pad events receiver */
-   selectObjectPainter(_painter, pos, _place) {
+   selectObjectPainter(painter, pos, place) {
       let istoppad = this.iscan || !this.has_canvas,
           canp = istoppad ? this : this.getCanvPainter();
 
-      if (_painter === undefined) _painter = this;
+      if (painter === undefined) painter = this;
 
       if (pos && !istoppad)
          pos = getAbsPosInCanvas(this.svg_this_pad(), pos);
 
       selectActivePad({ pp: this, active: true });
 
-      if (canp) canp.producePadEvent('select', this, _painter, pos, _place);
+      canp?.producePadEvent('select', this, painter, pos, place);
    }
 
    /** @summary Draw pad active border
@@ -54359,7 +54363,7 @@ class TPadPainter extends ObjectPainter {
             btns = this.getLayerSvg('btns_layer', this.this_pad_name);
       } else {
          svg_pad = svg_can.select('.primitives_layer')
-             .append('svg:svg') // here was g before, svg used to blend all drawin outside
+             .append('svg:svg') // svg used to blend all drawings outside
              .classed('__root_pad_' + this.this_pad_name, true)
              .attr('pad', this.this_pad_name) // set extra attribute  to mark pad name
              .property('pad_painter', this); // this is custom property
@@ -55140,6 +55144,9 @@ class TPadPainter extends ObjectPainter {
       let first = snap.fSnapshot;
       first.fPrimitives = null; // primitives are not interesting, they are disabled in IO
 
+      // if there are execs in the pad, deliver events to the server
+      this._deliver_webcanvas_events = first.fExecs?.arr?.length ? true : false;
+
       if (this.snapid === undefined) {
          // first time getting snap, create all gui elements first
 
@@ -55147,6 +55154,7 @@ class TPadPainter extends ObjectPainter {
 
          this.draw_object = first;
          this.pad = first;
+
          // this._fixed_size = true;
 
          // if canvas size not specified in batch mode, temporary use 900x700 size
@@ -55220,12 +55228,15 @@ class TPadPainter extends ObjectPainter {
 
       // check if frame or title was recreated, we could reassign handlers for them directly
       // while this is temporary objects, which can be recreated very often, try to catch such situation ourselfs
-      MatchPrimitive(this.painters, snap.fPrimitives, 'TFrame');
-      MatchPrimitive(this.painters, snap.fPrimitives, clTPaveText, 'title');
+      if (!snap.fWithoutPrimitives) {
+         MatchPrimitive(this.painters, snap.fPrimitives, 'TFrame');
+         MatchPrimitive(this.painters, snap.fPrimitives, clTPaveText, 'title');
+      }
 
       let isanyfound = false, isanyremove = false;
 
       // find and remove painters which no longer exists in the list
+      if (!snap.fWithoutPrimitives)
       for (let k = 0; k < this.painters.length; ++k) {
          let sub = this.painters[k];
 
@@ -55250,7 +55261,7 @@ class TPadPainter extends ObjectPainter {
       if (isanyremove)
          delete this.pads_cache;
 
-      if (!isanyfound) {
+      if (!isanyfound && !snap.fWithoutPrimitives) {
          // TODO: maybe just remove frame painter?
          let fp = this.getFramePainter();
          this.painters.forEach(objp => {
@@ -55272,10 +55283,11 @@ class TPadPainter extends ObjectPainter {
       return this.drawNextSnap(snap.fPrimitives).then(() => {
          // redraw secondaries like stat box
          let promises = [];
-         this.painters.forEach(sub => {
-            if ((sub.snapid === undefined) || sub.$secondary)
-               promises.push(sub.redraw());
-         });
+         if (!snap.fWithoutPrimitives)
+            this.painters.forEach(sub => {
+               if ((sub.snapid === undefined) || sub.$secondary)
+                  promises.push(sub.redraw());
+            });
          return Promise.all(promises);
       }).then(() => {
          this.selectCurrentPad(prev_name);
@@ -55285,6 +55297,22 @@ class TPadPainter extends ObjectPainter {
       });
    }
 
+   /** @summary Deliver mouse move or click event to the web canvas
+     * @private */
+   deliverWebCanvasEvent(kind, x, y, hints) {
+      if (!this._deliver_webcanvas_events || !this.is_active_pad || this.doingDraw() || x === undefined || y === undefined) return;
+      let cp = this.getCanvPainter();
+      if (!cp || !cp._websocket || !cp._websocket.canSend(2) || cp._readonly) return;
+
+      let selobj_snapid = '';
+      if (hints && hints[0] && hints[0].painter?.snapid)
+         selobj_snapid = hints[0].painter.snapid.toString();
+
+      let msg = JSON.stringify([this.snapid, kind, x.toString(), y.toString(), selobj_snapid]);
+
+      cp.sendWebsocket(`EVENT:${msg}`);
+   }
+
    /** @summary Create image for the pad
      * @desc Used with web-based canvas to create images for server side
      * @return {Promise} with image data, coded with btoa() function
@@ -55318,6 +55346,7 @@ class TPadPainter extends ObjectPainter {
       if (this.snapid) {
          elem = { _typename: 'TWebPadOptions', snapid: this.snapid.toString(),
                   active: !!this.is_active_pad,
+                  cw: 0, ch: 0,
                   bits: 0, primitives: [],
                   logx: this.pad.fLogx, logy: this.pad.fLogy, logz: this.pad.fLogz,
                   gridx: this.pad.fGridx, gridy: this.pad.fGridy,
@@ -55329,12 +55358,16 @@ class TPadPainter extends ObjectPainter {
 
          if (this.iscan) {
             elem.bits = this.getStatusBits();
+            elem.cw = this.getPadWidth();
+            elem.ch = this.getPadHeight();
          } else if (cp) {
             let cw = cp.getPadWidth(), ch = cp.getPadHeight(), rect = this.getPadRect();
+            elem.cw = cw;
+            elem.ch = ch;
             elem.xlow = rect.x / cw;
-            elem.ylow = rect.y / ch;
-            elem.xup = (rect.x + rect.width) / cw;
-            elem.yup = (rect.y + rect.height) / ch;
+            elem.ylow = 1 - (rect.y + rect.height) / ch;
+            elem.xup = elem.xlow + rect.width / cw;
+            elem.yup = elem.ylow + rect.height / ch;
          }
 
          if (this.getPadRanges(elem))
@@ -56137,14 +56170,15 @@ class TCanvasPainter extends TPadPainter {
          this.closeWebsocket(true);
       } else if (msg.slice(0,6) == 'SNAP6:') {
          // This is snapshot, produced with ROOT6
-
-         let snap = parse(msg.slice(6));
+         let p1 = msg.indexOf(':', 6),
+             version = msg.slice(6, p1),
+             snap = parse(msg.slice(p1+1));
 
          this.syncDraw(true).then(() => this.redrawPadSnap(snap)).then(() => {
             this.completeCanvasSnapDrawing();
             let ranges = this.getWebPadOptions(); // all data, including subpads
             if (ranges) ranges = ':' + ranges;
-            handle.send('READY6:' + snap.fVersion + ranges); // send ready message back when drawing completed
+            handle.send('READY6:' + version + ranges); // send ready message back when drawing completed
             this.confirmDraw();
          });
       } else if (msg.slice(0,5) == 'MENU:') {
@@ -56381,7 +56415,7 @@ class TCanvasPainter extends TPadPainter {
 
       if (this._last_highlight_msg != msg) {
          this._last_highlight_msg = msg;
-         this.sendWebsocket('HIGHLIGHT:' + msg);
+         this.sendWebsocket(`HIGHLIGHT:${msg}`);
       }
    }
 
@@ -94999,28 +95033,28 @@ class RPadPainter extends RObjectPainter {
    /** @summary Generate pad events, normally handled by GED
      * @desc in pad painter, while pad may be drawn without canvas
      * @private */
-   producePadEvent(_what, _padpainter, _painter, _position, _place) {
-      if ((_what == 'select') && isFunc(this.selectActivePad))
-         this.selectActivePad(_padpainter, _painter, _position);
+   producePadEvent(what, padpainter, painter, position, place) {
+      if ((what == 'select') && isFunc(this.selectActivePad))
+         this.selectActivePad(padpainter, painter, position);
 
       if (this.pad_events_receiver)
-         this.pad_events_receiver({ what: _what, padpainter:  _padpainter, painter: _painter, position: _position, place: _place });
+         this.pad_events_receiver({ what, padpainter, painter, position, place });
    }
 
    /** @summary method redirect call to pad events receiver */
-   selectObjectPainter(_painter, pos, _place) {
+   selectObjectPainter(painter, pos, place) {
 
       let istoppad = (this.iscan || !this.has_canvas),
           canp = istoppad ? this : this.getCanvPainter();
 
-      if (_painter === undefined) _painter = this;
+      if (painter === undefined) painter = this;
 
       if (pos && !istoppad)
          pos = getAbsPosInCanvas(this.svg_this_pad(), pos);
 
       selectActivePad({ pp: this, active: true });
 
-      canp.producePadEvent('select', this, _painter, pos, _place);
+      canp.producePadEvent('select', this, painter, pos, place);
    }
 
    /** @summary Create SVG element for the canvas */
diff --git a/js/modules/base/BasePainter.mjs b/js/modules/base/BasePainter.mjs
index aed72141705d1bb41b5e676b3905f6f147c301b7..79aa633ee70a893d3d3811f4f4a7fdc04fc5455c 100644
--- a/js/modules/base/BasePainter.mjs
+++ b/js/modules/base/BasePainter.mjs
@@ -47,7 +47,7 @@ function getElementRect(elem, sizearg) {
 /** @summary Calculate absolute position of provided element in canvas
   * @private */
 function getAbsPosInCanvas(sel, pos) {
-   while (!sel.empty() && !sel.classed('root_canvas') && pos) {
+   while (pos && !sel.empty() && !sel.classed('root_canvas')) {
       let cl = sel.attr('class');
       if (cl && ((cl.indexOf('root_frame') >= 0) || (cl.indexOf('__root_pad_') >= 0))) {
          pos.x += sel.property('draw_x') || 0;
diff --git a/js/modules/core.mjs b/js/modules/core.mjs
index 5eb791d0e18b8cd22320cf5bc3bb6d6778375c75..6b9872c3c44028afa5468206accc05e766249b5c 100644
--- a/js/modules/core.mjs
+++ b/js/modules/core.mjs
@@ -5,7 +5,7 @@ let version_id = 'dev';
 
 /** @summary version date
   * @desc Release date in format day/month/year like '19/11/2021' */
-let version_date = '15/11/2022';
+let version_date = '17/11/2022';
 
 /** @summary version id and date
   * @desc Produced by concatenation of {@link version_id} and {@link version_date}
diff --git a/js/modules/gpad/RPadPainter.mjs b/js/modules/gpad/RPadPainter.mjs
index fd73e62dfaae4f4b659e0b91fd0dc0774f3b923d..c700eede525784607ee376f19d4f551e0db0b74d 100644
--- a/js/modules/gpad/RPadPainter.mjs
+++ b/js/modules/gpad/RPadPainter.mjs
@@ -227,28 +227,28 @@ class RPadPainter extends RObjectPainter {
    /** @summary Generate pad events, normally handled by GED
      * @desc in pad painter, while pad may be drawn without canvas
      * @private */
-   producePadEvent(_what, _padpainter, _painter, _position, _place) {
-      if ((_what == 'select') && isFunc(this.selectActivePad))
-         this.selectActivePad(_padpainter, _painter, _position);
+   producePadEvent(what, padpainter, painter, position, place) {
+      if ((what == 'select') && isFunc(this.selectActivePad))
+         this.selectActivePad(padpainter, painter, position);
 
       if (this.pad_events_receiver)
-         this.pad_events_receiver({ what: _what, padpainter:  _padpainter, painter: _painter, position: _position, place: _place });
+         this.pad_events_receiver({ what, padpainter, painter, position, place });
    }
 
    /** @summary method redirect call to pad events receiver */
-   selectObjectPainter(_painter, pos, _place) {
+   selectObjectPainter(painter, pos, place) {
 
       let istoppad = (this.iscan || !this.has_canvas),
           canp = istoppad ? this : this.getCanvPainter();
 
-      if (_painter === undefined) _painter = this;
+      if (painter === undefined) painter = this;
 
       if (pos && !istoppad)
          pos = getAbsPosInCanvas(this.svg_this_pad(), pos);
 
       selectActivePad({ pp: this, active: true });
 
-      canp.producePadEvent('select', this, _painter, pos, _place);
+      canp.producePadEvent('select', this, painter, pos, place);
    }
 
    /** @summary Create SVG element for the canvas */
diff --git a/js/modules/gpad/TCanvasPainter.mjs b/js/modules/gpad/TCanvasPainter.mjs
index 11d711f6a031f05cb9948772298c03b10791485e..a7564f71815804a1a0c75d8cfb7caed625b4da61 100644
--- a/js/modules/gpad/TCanvasPainter.mjs
+++ b/js/modules/gpad/TCanvasPainter.mjs
@@ -306,14 +306,15 @@ class TCanvasPainter extends TPadPainter {
          this.closeWebsocket(true);
       } else if (msg.slice(0,6) == 'SNAP6:') {
          // This is snapshot, produced with ROOT6
-
-         let snap = parse(msg.slice(6));
+         let p1 = msg.indexOf(':', 6),
+             version = msg.slice(6, p1),
+             snap = parse(msg.slice(p1+1));
 
          this.syncDraw(true).then(() => this.redrawPadSnap(snap)).then(() => {
             this.completeCanvasSnapDrawing();
             let ranges = this.getWebPadOptions(); // all data, including subpads
             if (ranges) ranges = ':' + ranges;
-            handle.send('READY6:' + snap.fVersion + ranges); // send ready message back when drawing completed
+            handle.send('READY6:' + version + ranges); // send ready message back when drawing completed
             this.confirmDraw();
          });
       } else if (msg.slice(0,5) == 'MENU:') {
@@ -550,7 +551,7 @@ class TCanvasPainter extends TPadPainter {
 
       if (this._last_highlight_msg != msg) {
          this._last_highlight_msg = msg;
-         this.sendWebsocket('HIGHLIGHT:' + msg);
+         this.sendWebsocket(`HIGHLIGHT:${msg}`);
       }
    }
 
diff --git a/js/modules/gpad/TFramePainter.mjs b/js/modules/gpad/TFramePainter.mjs
index 54a68a9ae8361c7912743e56d81651bd4053a565..c783d3046087adac1326a97427d3be3a8c2fa9c0 100644
--- a/js/modules/gpad/TFramePainter.mjs
+++ b/js/modules/gpad/TFramePainter.mjs
@@ -288,7 +288,8 @@ const TooltipHandler = {
 
    /** @summary central function which let show selected hints for the object */
    processFrameTooltipEvent(pnt, evnt) {
-      if (pnt && pnt.handler) {
+
+      if (pnt?.handler) {
          // special use of interactive handler in the frame painter
          let rect = this.draw_g ? this.draw_g.select('.main_layer') : null;
          if (!rect || rect.empty()) {
@@ -316,7 +317,10 @@ const TooltipHandler = {
       // collect tooltips from pad painter - it has list of all drawn objects
       if (pp) hints = pp.processPadTooltipEvent(pnt);
 
-      if (pnt && pnt.touch) textheight = 15;
+      if (pp?._deliver_webcanvas_events && pp?.is_active_pad && pnt && isFunc(pp?.deliverWebCanvasEvent))
+         pp.deliverWebCanvasEvent('move', frame_rect.x + pnt.x, frame_rect.y + pnt.y, hints);
+
+      if (pnt?.touch) textheight = 15;
 
       for (let n = 0; n < hints.length; ++n) {
          let hint = hints[n];
@@ -326,7 +330,8 @@ const TooltipHandler = {
             hint.painter.provideUserTooltip(hint.user_info);
 
          if (!hint.lines || (hint.lines.length === 0)) {
-            hints[n] = null; continue;
+            hints[n] = null;
+            continue;
          }
 
          // check if fully duplicated hint already exists
@@ -384,7 +389,6 @@ const TooltipHandler = {
 
       this.showObjectStatus(name, title, info, coordinates);
 
-
       // end of closing tooltips
       if (!pnt || disable_tootlips || (hints.length === 0) || (maxlen === 0) || (show_only_best && !best_hint)) {
          hintsg.remove();
diff --git a/js/modules/gpad/TPadPainter.mjs b/js/modules/gpad/TPadPainter.mjs
index 882dea72b28269b9c2021ac2bae3805c8102c629..a5db203c4b86675e751bcfb8d2935574c0ba2108 100644
--- a/js/modules/gpad/TPadPainter.mjs
+++ b/js/modules/gpad/TPadPainter.mjs
@@ -354,18 +354,18 @@ class TPadPainter extends ObjectPainter {
    }
 
    /** @summary method redirect call to pad events receiver */
-   selectObjectPainter(_painter, pos, _place) {
+   selectObjectPainter(painter, pos, place) {
       let istoppad = this.iscan || !this.has_canvas,
           canp = istoppad ? this : this.getCanvPainter();
 
-      if (_painter === undefined) _painter = this;
+      if (painter === undefined) painter = this;
 
       if (pos && !istoppad)
          pos = getAbsPosInCanvas(this.svg_this_pad(), pos);
 
       selectActivePad({ pp: this, active: true });
 
-      if (canp) canp.producePadEvent('select', this, _painter, pos, _place);
+      canp?.producePadEvent('select', this, painter, pos, place);
    }
 
    /** @summary Draw pad active border
@@ -617,7 +617,7 @@ class TPadPainter extends ObjectPainter {
             btns = this.getLayerSvg('btns_layer', this.this_pad_name);
       } else {
          svg_pad = svg_can.select('.primitives_layer')
-             .append('svg:svg') // here was g before, svg used to blend all drawin outside
+             .append('svg:svg') // svg used to blend all drawings outside
              .classed('__root_pad_' + this.this_pad_name, true)
              .attr('pad', this.this_pad_name) // set extra attribute  to mark pad name
              .property('pad_painter', this); // this is custom property
@@ -1398,6 +1398,9 @@ class TPadPainter extends ObjectPainter {
       let first = snap.fSnapshot;
       first.fPrimitives = null; // primitives are not interesting, they are disabled in IO
 
+      // if there are execs in the pad, deliver events to the server
+      this._deliver_webcanvas_events = first.fExecs?.arr?.length ? true : false;
+
       if (this.snapid === undefined) {
          // first time getting snap, create all gui elements first
 
@@ -1405,6 +1408,7 @@ class TPadPainter extends ObjectPainter {
 
          this.draw_object = first;
          this.pad = first;
+
          // this._fixed_size = true;
 
          // if canvas size not specified in batch mode, temporary use 900x700 size
@@ -1478,12 +1482,15 @@ class TPadPainter extends ObjectPainter {
 
       // check if frame or title was recreated, we could reassign handlers for them directly
       // while this is temporary objects, which can be recreated very often, try to catch such situation ourselfs
-      MatchPrimitive(this.painters, snap.fPrimitives, 'TFrame');
-      MatchPrimitive(this.painters, snap.fPrimitives, clTPaveText, 'title');
+      if (!snap.fWithoutPrimitives) {
+         MatchPrimitive(this.painters, snap.fPrimitives, 'TFrame');
+         MatchPrimitive(this.painters, snap.fPrimitives, clTPaveText, 'title');
+      }
 
       let isanyfound = false, isanyremove = false;
 
       // find and remove painters which no longer exists in the list
+      if (!snap.fWithoutPrimitives)
       for (let k = 0; k < this.painters.length; ++k) {
          let sub = this.painters[k];
 
@@ -1508,7 +1515,7 @@ class TPadPainter extends ObjectPainter {
       if (isanyremove)
          delete this.pads_cache;
 
-      if (!isanyfound) {
+      if (!isanyfound && !snap.fWithoutPrimitives) {
          // TODO: maybe just remove frame painter?
          let fp = this.getFramePainter();
          this.painters.forEach(objp => {
@@ -1530,10 +1537,11 @@ class TPadPainter extends ObjectPainter {
       return this.drawNextSnap(snap.fPrimitives).then(() => {
          // redraw secondaries like stat box
          let promises = [];
-         this.painters.forEach(sub => {
-            if ((sub.snapid === undefined) || sub.$secondary)
-               promises.push(sub.redraw());
-         });
+         if (!snap.fWithoutPrimitives)
+            this.painters.forEach(sub => {
+               if ((sub.snapid === undefined) || sub.$secondary)
+                  promises.push(sub.redraw());
+            });
          return Promise.all(promises);
       }).then(() => {
          this.selectCurrentPad(prev_name);
@@ -1543,6 +1551,22 @@ class TPadPainter extends ObjectPainter {
       });
    }
 
+   /** @summary Deliver mouse move or click event to the web canvas
+     * @private */
+   deliverWebCanvasEvent(kind, x, y, hints) {
+      if (!this._deliver_webcanvas_events || !this.is_active_pad || this.doingDraw() || x === undefined || y === undefined) return;
+      let cp = this.getCanvPainter();
+      if (!cp || !cp._websocket || !cp._websocket.canSend(2) || cp._readonly) return;
+
+      let selobj_snapid = '';
+      if (hints && hints[0] && hints[0].painter?.snapid)
+         selobj_snapid = hints[0].painter.snapid.toString();
+
+      let msg = JSON.stringify([this.snapid, kind, x.toString(), y.toString(), selobj_snapid]);
+
+      cp.sendWebsocket(`EVENT:${msg}`);
+   }
+
    /** @summary Create image for the pad
      * @desc Used with web-based canvas to create images for server side
      * @return {Promise} with image data, coded with btoa() function
@@ -1576,6 +1600,7 @@ class TPadPainter extends ObjectPainter {
       if (this.snapid) {
          elem = { _typename: 'TWebPadOptions', snapid: this.snapid.toString(),
                   active: !!this.is_active_pad,
+                  cw: 0, ch: 0,
                   bits: 0, primitives: [],
                   logx: this.pad.fLogx, logy: this.pad.fLogy, logz: this.pad.fLogz,
                   gridx: this.pad.fGridx, gridy: this.pad.fGridy,
@@ -1587,12 +1612,16 @@ class TPadPainter extends ObjectPainter {
 
          if (this.iscan) {
             elem.bits = this.getStatusBits();
+            elem.cw = this.getPadWidth();
+            elem.ch = this.getPadHeight();
          } else if (cp) {
             let cw = cp.getPadWidth(), ch = cp.getPadHeight(), rect = this.getPadRect();
+            elem.cw = cw;
+            elem.ch = ch;
             elem.xlow = rect.x / cw;
-            elem.ylow = rect.y / ch;
-            elem.xup = (rect.x + rect.width) / cw;
-            elem.yup = (rect.y + rect.height) / ch;
+            elem.ylow = 1 - (rect.y + rect.height) / ch;
+            elem.xup = elem.xlow + rect.width / cw;
+            elem.yup = elem.ylow + rect.height / ch;
          }
 
          if (this.getPadRanges(elem))