Bug 1535725 - Port bug 1519948: Replace use of boxObject: .x, .y, .height, .width, .screenX, .screenY. r=me
authorJorg K <jorgk@jorgk.com>
Wed, 17 Apr 2019 23:58:15 +0200
changeset 26376 e920876482870bfc239ab3bc3ecd1514d9958382
parent 26375 268b0132591a59bddc5bcb98ea842639e0420fdb
child 26377 72eadf95a12007ee4a2c5d02951ffd7851612628
push id15808
push usermozilla@jorgk.com
push dateWed, 17 Apr 2019 21:58:54 +0000
treeherdercomm-central@e92087648287 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs1535725, 1519948
Bug 1535725 - Port bug 1519948: Replace use of boxObject: .x, .y, .height, .width, .screenX, .screenY. r=me
calendar/base/content/calendar-base-view.js
calendar/base/content/calendar-multiday-view.xml
calendar/base/content/dialogs/calendar-event-dialog-attendees-custom-elements.js
calendar/base/content/dialogs/calendar-event-dialog-attendees.js
calendar/base/content/dialogs/calendar-event-dialog-attendees.xml
calendar/base/content/dialogs/calendar-event-dialog-freebusy.xml
calendar/base/content/dialogs/calendar-event-dialog-recurrence.js
calendar/base/content/today-pane.js
calendar/base/content/widgets/calendar-list-tree.xml
calendar/base/modules/utils/calViewUtils.jsm
calendar/test/mozmill/testBasicFunctionality.js
calendar/test/mozmill/testTimezones.js
common/bindings/notificationbox.xml
common/bindings/richlistbox.xml
common/src/customizeToolbar.js
mail/base/content/folderDisplay.js
mail/base/content/mailWidgets.xml
mail/base/content/msgHdrView.js
mail/base/content/sanitizeDialog.js
mail/base/content/tabmail.xml
mail/base/modules/GlobalPopupNotifications.jsm
mail/components/compose/content/MsgComposeCommands.js
mail/components/compose/content/addressingWidgetOverlay.js
mail/components/im/content/imconversation.xml
mail/test/mozmill/attachment/test-attachment.js
mail/test/mozmill/folder-display/test-opening-messages.js
mail/test/mozmill/session-store/test-session-store.js
mail/test/mozmill/shared-modules/test-folder-display-helpers.js
mail/test/mozmill/shared-modules/test-mouse-event-helpers.js
mail/test/mozmill/shared-modules/test-quick-filter-bar-helper.js
mail/test/mozmill/tabmail/test-tabmail-dragndrop.js
mail/test/resources/mozmill/mozmill/extension/content/modules/events.jsm
mailnews/db/gloda/content/autocomplete-richlistitem.js
--- a/calendar/base/content/calendar-base-view.js
+++ b/calendar/base/content/calendar-base-view.js
@@ -98,17 +98,17 @@ class MozCalendarDayLabel extends MozXUL
         this.getLongWeekdayPixels();
         setBooleanAttribute(this.longWeekdayName, "hidden", val);
         setBooleanAttribute(this.shortWeekdayName, "hidden", !val);
         return val;
     }
 
     getLongWeekdayPixels() {
         // Only do this if the long weekdays are visible and we haven't already cached.
-        let longNameWidth = this.longWeekdayName.boxObject.width;
+        let longNameWidth = this.longWeekdayName.getBoundingClientRect().width;
 
         if (longNameWidth == 0) {
             // weekdaypixels have not yet been laid out
             return 0;
         }
 
         this.longWeekdayPixels = longNameWidth +
             getSummarizedStyleValues(this.longWeekdayName, ["margin-left", "margin-right"]);
--- a/calendar/base/content/calendar-multiday-view.xml
+++ b/calendar/base/content/calendar-multiday-view.xml
@@ -1343,21 +1343,21 @@
             // If we are at the bottom or top of the view (or left/right when
             // rotated), calculate the difference and start accelerating the
             // scrollbar.
             let diffStart, diffEnd;
             let orient = event.target.getAttribute("orient");
             let scrollbox = document.getAnonymousElementByAttribute(
                            event.target, "anonid", "scrollbox");
             if (orient == "vertical") {
-                diffStart = event.clientY - scrollbox.boxObject.y;
-                diffEnd = scrollbox.boxObject.y + scrollbox.boxObject.height - event.clientY;
+                diffStart = event.clientY - scrollbox.getBoundingClientRect().y;
+                diffEnd = scrollbox.getBoundingClientRect().y + scrollbox.getBoundingClientRect().height - event.clientY;
             } else {
-                diffStart = event.clientX - scrollbox.boxObject.x;
-                diffEnd = scrollbox.boxObject.x + scrollbox.boxObject.width - event.clientX;
+                diffStart = event.clientX - scrollbox.getBoundingClientRect().x;
+                diffEnd = scrollbox.getBoundingClientRect().x + scrollbox.getBoundingClientRect().width - event.clientX;
             }
 
             const SCROLLZONE = 55;     // Size (pixels) of the top/bottom view where the scroll starts.
             const MAXTIMEOUT = 250;    // Max and min time interval (ms) between
             const MINTIMEOUT = 30;     // two consecutive scrolls.
             const SCROLLBYHOUR = 0.33; // Part of hour to move for each scroll.
             let insideScrollZone = 0;
             let pxPerHr = event.target.mPixPerMin * 60;
@@ -1398,20 +1398,20 @@
 
             let lateralColumns = col.firstLastShadowColumns();
             let firstCol = lateralColumns.firstCol;
             let firstIndex = lateralColumns.firstIndex;
 
             // If we leave the view, then stop our internal sweeping and start a
             // real drag session. Someday we need to fix the sweep to soely be a
             // drag session, no sweeping.
-            if (event.clientX < (event.target.boxObject.x) ||
-                event.clientX > (event.target.boxObject.x + event.target.boxObject.width) ||
-                event.clientY < (event.target.boxObject.y) ||
-                event.clientY > (event.target.boxObject.y + event.target.boxObject.height)) {
+            if (event.clientX < (event.target.getBoundingClientRect().x) ||
+                event.clientX > (event.target.getBoundingClientRect().x + event.target.getBoundingClientRect().width) ||
+                event.clientY < (event.target.getBoundingClientRect().y) ||
+                event.clientY > (event.target.getBoundingClientRect().y + event.target.getBoundingClientRect().height)) {
                 // Remove the drag state
                 for (let column = firstCol, i = firstIndex;
                      column && i < col.mDragState.shadows;
                      column = column.nextSibling, i++) {
                     column.fgboxes.dragbox.removeAttribute("dragging");
                     column.fgboxes.box.removeAttribute("dragging");
                 }
 
@@ -1483,20 +1483,20 @@
                 col.onEventSweepMouseMove(event);
 
                 return;
             }
 
             let mousePos;
             let sizeattr;
             if (col.getAttribute("orient") == "vertical") {
-                mousePos = event.screenY - col.parentNode.boxObject.screenY;
+                mousePos = event.screenY - col.parentNode.screenY;
                 sizeattr = "height";
             } else {
-                mousePos = event.screenX - col.parentNode.boxObject.screenX;
+                mousePos = event.screenX - col.parentNode.screenX;
                 sizeattr = "width";
             }
             // don't let mouse position go outside the window edges
             let pos = Math.max(0, mousePos) - dragState.mouseOffset;
 
             // snap interval: 15 minutes or 1 minute if modifier key is pressed
             let snapIntMin = (event.shiftKey &&
                               !event.ctrlKey &&
@@ -1858,19 +1858,19 @@
                 let shadowElements = this.getShadowElements(this.mDragState.origMinStart,
                                                             this.mDragState.origMinEnd);
                 this.mDragState.shadows = shadowElements.shadows;
                 this.mDragState.offset = shadowElements.offset;
                 // we need to set a mouse offset, since we're not dragging from
                 // one end of the element
                 if (aEventBox) {
                     if (this.getAttribute("orient") == "vertical") {
-                        this.mDragState.mouseOffset = aMouseY - aEventBox.boxObject.screenY;
+                        this.mDragState.mouseOffset = aMouseY - aEventBox.screenY;
                     } else {
-                        this.mDragState.mouseOffset = aMouseX - aEventBox.boxObject.screenX;
+                        this.mDragState.mouseOffset = aMouseX - aEventBox.screenX;
                     }
                 }
             } else {
                 // Invalid grabbed element.
             }
 
             document.calendarEventColumnDragging = this;
 
@@ -1962,19 +1962,19 @@
             newStart.isDate = false;
             newStart.hour = 0;
 
             const ROUND_INTERVAL = 15;
 
             let interval = this.mPixPerMin * ROUND_INTERVAL;
             let pos;
             if (this.getAttribute("orient") == "vertical") {
-                pos = event.screenY - this.parentNode.boxObject.screenY;
+                pos = event.screenY - this.parentNode.screenY;
             } else {
-                pos = event.screenX - this.parentNode.boxObject.screenX;
+                pos = event.screenX - this.parentNode.screenX;
             }
             newStart.minute = (Math.round(pos / interval) * ROUND_INTERVAL) + this.mStartMin;
             event.stopPropagation();
             return newStart;
         ]]></body>
       </method>
     </implementation>
 
@@ -2032,23 +2032,23 @@
           let snapIntMin = (event.shiftKey &&
                             !event.ctrlKey &&
                             !event.altKey &&
                             !event.metaKey) ? 1 : 15;
           let interval = this.mPixPerMin * snapIntMin;
 
           if (this.getAttribute("orient") == "vertical") {
               this.mDragState.origLoc = event.screenY;
-              this.mDragState.origMin = Math.floor((event.screenY - this.parentNode.boxObject.screenY) / interval) * snapIntMin;
+              this.mDragState.origMin = Math.floor((event.screenY - this.parentNode.screenY) / interval) * snapIntMin;
               this.mDragState.limitEndMin = this.mDragState.origMin;
               this.mDragState.limitStartMin = this.mDragState.origMin;
               this.fgboxes.dragspacer.setAttribute("height", this.mDragState.origMin * this.mPixPerMin);
           } else {
               this.mDragState.origLoc = event.screenX;
-              this.mDragState.origMin = Math.floor((event.screenX - this.parentNode.boxObject.screenX) / interval) * snapIntMin;
+              this.mDragState.origMin = Math.floor((event.screenX - this.parentNode.screenX) / interval) * snapIntMin;
               this.fgboxes.dragspacer.setAttribute("width", this.mDragState.origMin * this.mPixPerMin);
           }
 
           document.calendarEventColumnDragging = this;
 
           window.addEventListener("mousemove", this.onEventSweepMouseMove);
           window.addEventListener("mouseup", this.onEventSweepMouseUp);
           window.addEventListener("keypress", this.onEventSweepKeypress);
@@ -2338,18 +2338,18 @@
 
             if (item.title && item.title != "") {
                 // Use <description> textContent so it can wrap.
                 evl.textContent = item.title;
             } else {
                 evl.textContent = cal.l10n.getCalString("eventUntitled");
             }
 
-            let gripbar = document.getAnonymousElementByAttribute(this, "anonid", "gripbar1").boxObject.height;
-            let height = document.getAnonymousElementByAttribute(this, "anonid", "eventbox").boxObject.height;
+            let gripbar = document.getAnonymousElementByAttribute(this, "anonid", "gripbar1").getBoundingClientRect().height;
+            let height = document.getAnonymousElementByAttribute(this, "anonid", "eventbox").getBoundingClientRect().height;
             evl.setAttribute("style", "max-height: " + Math.max(0, height-gripbar * 2) + "px");
         ]]></body>
       </method>
     </implementation>
 
     <handlers>
       <handler event="mousedown" button="0"><![CDATA[
           event.stopPropagation();
@@ -2632,19 +2632,19 @@
       <method name="onResize">
         <parameter name="aRealSelf"/>
         <body><![CDATA[
             let self = aRealSelf || this; // eslint-disable-line consistent-this
             let isARelayout = !aRealSelf;
             let scrollbox = document.getAnonymousElementByAttribute(self, "anonid", "scrollbox");
             let size;
             if (self.orient == "horizontal") {
-                size = scrollbox.boxObject.width;
+                size = scrollbox.getBoundingClientRect().width;
             } else {
-                size = scrollbox.boxObject.height;
+                size = scrollbox.getBoundingClientRect().height;
             }
             let ppm = size / self.mVisibleMinutes;
             ppm = Math.floor(ppm * 1000) / 1000;
             if (ppm < self.mMinPixelsPerMinute) {
                 ppm = self.mMinPixelsPerMinute;
             }
             let ppmChanged = (self.pixelsPerMinute != ppm);
             self.pixelsPerMinute = ppm;
@@ -3561,21 +3561,21 @@
       <method name="findColumnForClientPoint">
         <parameter name="aClientX"/>
         <parameter name="aClientY"/>
         <body><![CDATA[
             if (!this.mDateColumns) {
                 return null;
             }
             for (let col of this.mDateColumns) {
-                let boxObject = document.getAnonymousElementByAttribute(col.column, "anonid", "boxstack").boxObject;
-                if (aClientX >= boxObject.screenX &&
-                    aClientX <= (boxObject.screenX + boxObject.width) &&
-                    aClientY >= boxObject.screenY &&
-                    aClientY <= (boxObject.screenY + boxObject.height)) {
+                let element = document.getAnonymousElementByAttribute(col.column, "anonid", "boxstack");
+                if (aClientX >= element.screenX &&
+                    aClientX <= (element.screenX + element.getBoundingClientRect().width) &&
+                    aClientY >= element.screenY &&
+                    aClientY <= (element.screenY + element.getBoundingClientRect().height)) {
                     return col.column;
                 }
             }
             return null;
         ]]></body>
       </method>
 
       <method name="adjustScrollbarSpacersForAlldayEvents">
@@ -3689,17 +3689,17 @@
             let headerPropertyValue = propertyValue;
             let headerDayBox = document.getAnonymousElementByAttribute(
                                this, "anonid", "headerdaybox");
             if (headerDayBox) {
                 // Only do this when there are multiple days
                 let headerDayBoxMaxHeight = parseInt(document.defaultView.getComputedStyle(headerDayBox)
                                                              .getPropertyValue("max-height"), 10);
                 if (this.getAttribute("orient") == "vertical" &&
-                    headerDayBox.boxObject.height >= headerDayBoxMaxHeight) {
+                    headerDayBox.getBoundingClientRect().height >= headerDayBoxMaxHeight) {
                     // If the headerDayBox is just as high as the max-height, then
                     // there is already a scrollbar and we don't need to show the
                     // headerScrollbarSpacer. This is only valid for the non-rotated
                     // view.
                     headerPropertyValue = 0;
                 }
             }
 
@@ -3717,17 +3717,17 @@
       <method name="scrollToMinute">
         <parameter name="aMinute"/>
         <body><![CDATA[
             let scrollbox = document.getAnonymousElementByAttribute(this, "anonid", "scrollbox");
             // 'aMinute' will be the first minute showed in the view, so it must
             // belong to the range 0 <-> (24*60 - minutes_showed_in_the_view) but
             // we consider 25 hours instead of 24 to let the view scroll until
             // showing events that start just before 0.00
-            let maxFirstMin = 25 * 60 - Math.round(scrollbox.boxObject.height / this.mPixPerMin);
+            let maxFirstMin = 25 * 60 - Math.round(scrollbox.getBoundingClientRect().height / this.mPixPerMin);
             aMinute = Math.min(maxFirstMin, Math.max(0, aMinute));
 
             if (scrollbox.scrollHeight > 0) {
                 let pos = Math.round(aMinute * this.mPixPerMin);
                 if (scrollbox.getAttribute("orient") == "horizontal") {
                     scrollbox.scrollTo(scrollbox.scrollLeft, pos);
                 } else {
                     scrollbox.scrollTo(pos, scrollbox.scrollTop);
--- a/calendar/base/content/dialogs/calendar-event-dialog-attendees-custom-elements.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog-attendees-custom-elements.js
@@ -97,26 +97,26 @@ class MozCalendarEventFreebusyTimebar ex
 
     /**
      * Gets the difference between the x coordinate of the first two freebusy-day elements.
      *
      * @returns {Number}       X coordinate difference value
      */
     get contentWidth() {
         let template = this.getElementsByTagName("freebusy-day")[0];
-        return template.nextSibling.boxObject.x - template.boxObject.x;
+        return template.nextSibling.getBoundingClientRect().x - template.getBoundingClientRect().x;
     }
 
     /**
      * Gets parent node's width.
      *
      * @returns {Number}       Parent node's width
      */
     get containerWidth() {
-        return this.parentNode.boxObject.width;
+        return this.parentNode.getBoundingClientRect().width;
     }
 
     /**
      * Sets startDate to a new value and make it immutable.
      *
      * @param {calIDateTime} val       New startDate value
      * @returns {calIDateTime}         New startDate value
      */
@@ -1063,28 +1063,28 @@ class MozCalendarEventAttendeesList exte
      * Calculates attendee list content height.
      */
     calcContentHeight() {
         let items = this.getElementsByTagName("richlistitem");
         this.mContentHeight = 0;
         if (items.length > 0) {
             let i = 0;
             do {
-                this.mRowHeight = items[i].boxObject.height;
+                this.mRowHeight = items[i].getBoundingClientRect().height;
                 ++i;
             } while (i < items.length && !this.mRowHeight);
             this.mContentHeight = this.mRowHeight * items.length;
         }
     }
 
     /**
      * Creates or removes dummy rows from the calendar-event-attendees-list.
      */
     createOrRemoveDummyRows() {
-        let listboxHeight = this.boxObject.height;
+        let listboxHeight = this.getBoundingClientRect().height;
 
         // Remove rows to remove scrollbar.
         let kids = this.childNodes;
         for (let i = kids.length - 1; this.mContentHeight > listboxHeight && i >= 0; --i) {
             if (kids[i].hasAttribute("_isDummyRow")) {
                 this.mContentHeight -= this.mRowHeight;
                 kids[i].remove();
             }
@@ -1530,27 +1530,27 @@ class MozCalendarEventFreebusyRow extend
 
     /**
      * Gets width of the content.
      *
      * @returns {Number}        Content width
      */
     get contentWidth() {
         // Difference between the x coordinate of first and second child of hours node
-        const diffX = this.hoursNode.childNodes[1].boxObject.x - this.hoursNode.childNodes[0].boxObject.x;
+        const diffX = this.hoursNode.childNodes[1].getBoundingClientRect().x - this.hoursNode.childNodes[0].getBoundingClientRect().x;
         return diffX * this.numHours;
     }
 
     /**
      * Returns width of nearest listbox element.
      *
      * @returns {Number}        Nearest listbox width
      */
     get containerWidth() {
-        return this.closest("listbox").boxObject.width;
+        return this.closest("listbox").getBoundingClientRect().width;
     }
 
     /**
      * Sets offset value and calls showState which maps entries to the attribute of xul elements.
      *
      * @returns {Number}        New offset value
      */
     set dayOffset(val) {
--- a/calendar/base/content/dialogs/calendar-event-dialog-attendees.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog-attendees.js
@@ -559,26 +559,26 @@ function onResize() {
     // Don't do anything if we haven't been initialized.
     if (!gStartDate || !gEndDate) {
         return;
     }
 
     let grid = document.getElementById("freebusy-grid");
     let gridScrollbar = document.getElementById("horizontal-scrollbar");
     grid.fitDummyRows();
-    let gridRatio = grid.boxObject.width / grid.documentSize;
+    let gridRatio = grid.getBoundingClientRect().width / grid.documentSize;
     let gridMaxpos = gridScrollbar.getAttribute("maxpos");
     let gridInc = gridMaxpos * gridRatio / (1 - gridRatio);
     gridScrollbar.setAttribute("pageincrement", gridInc);
 
     let attendees = document.getElementById("attendees-list");
     let attendeesScrollbar = document.getElementById("vertical-scrollbar");
     let box = document.getElementById("vertical-scrollbar-box");
     attendees.fitDummyRows();
-    let attRatio = attendees.boxObject.height / attendees.documentSize;
+    let attRatio = attendees.getBoundingClientRect().height / attendees.documentSize;
     let attMaxpos = attendeesScrollbar.getAttribute("maxpos");
     if (attRatio < 1) {
         box.removeAttribute("collapsed");
         let attInc = attMaxpos * attRatio / (1 - attRatio);
         attendeesScrollbar.setAttribute("pageincrement", attInc);
     } else {
         box.setAttribute("collapsed", "true");
     }
@@ -865,17 +865,17 @@ function onMouseScroll(event) {
 /**
  * Handler function to take care of attribute changes on the window
  *
  * @param event     The DOMAttrModified event caused by this change.
  */
 function onAttrModified(event) {
     if (event.attrName == "width") {
         let selectionbar = document.getElementById("selection-bar");
-        selectionbar.setWidth(selectionbar.boxObject.width);
+        selectionbar.setWidth(selectionbar.getBoundingClientRect().width);
         return;
     }
 
     // Synchronize grid and attendee list
     let target = event.originalTarget;
     if (target.hasAttribute("anonid") &&
         target.getAttribute("anonid") == "input" &&
         event.attrName == "focused") {
@@ -928,18 +928,18 @@ function onAttrModified(event) {
  */
 function onTimebar(event) {
     document.getElementById("selection-bar").init(event.details, event.height);
 
     // we need to enforce several layout constraints which can't be modelled
     // with plain xul and css, at least as far as i know.
     let timebar = document.getElementById("timebar");
     let scrollbar = document.getElementById("horizontal-scrollbar");
-    document.documentElement.style.setProperty("--spacer-top-height", timebar.boxObject.height + "px");
-    document.documentElement.style.setProperty("--spacer-bottom-height", scrollbar.boxObject.height + "px");
+    document.documentElement.style.setProperty("--spacer-top-height", timebar.getBoundingClientRect().height + "px");
+    document.documentElement.style.setProperty("--spacer-bottom-height", scrollbar.getBoundingClientRect().height + "px");
 }
 
 /**
  * Handler function to update controls when the time has changed on the
  * selection bar.
  *
  * @param event     The "timechange" event with startDate and endDate
  *                    properties.
--- a/calendar/base/content/dialogs/calendar-event-dialog-attendees.xml
+++ b/calendar/base/content/dialogs/calendar-event-dialog-attendees.xml
@@ -145,27 +145,27 @@
 
       <property name="leftdragWidth">
         <getter><![CDATA[
             if (!this.mLeftBox) {
                 this.mLeftBox =
                     document.getAnonymousElementByAttribute(
                         this, "anonid", "leftbox");
             }
-            return this.mLeftBox.boxObject.width;
+            return this.mLeftBox.getBoundingClientRect().width;
         ]]></getter>
       </property>
       <property name="rightdragWidth">
         <getter><![CDATA[
             if (!this.mRightBox) {
                 this.mRightBox =
                     document.getAnonymousElementByAttribute(
                         this, "anonid", "rightbox");
             }
-            return this.mRightBox.boxObject.width;
+            return this.mRightBox.getBoundingClientRect().width;
         ]]></getter>
       </property>
 
       <method name="init">
         <parameter name="width"/>
         <parameter name="height"/>
         <body><![CDATA[
             this.mContentWidth = width;
@@ -222,17 +222,17 @@
             if (this.mWidth < totaldragwidths) {
                 this.mWidth = totaldragwidths;
             }
             this.mMargin = start_offset_in_hours * hour_width;
 
             // Calculate the difference between content and container in pixels.
             // The container is the window showing this control, the content is the
             // total number of pixels the selection bar can theoretically take up.
-            let total_width = this.mContentWidth * this.mRange - this.parentNode.boxObject.width;
+            let total_width = this.mContentWidth * this.mRange - this.parentNode.getBoundingClientRect().width;
 
             // Calculate the current scroll offset.
             offset = Math.floor(total_width * this.mRatio);
 
             // The final margin is the difference between the date-based margin
             // and the scroll-based margin.
             this.mMargin -= offset;
 
@@ -328,17 +328,17 @@
         ]]></body>
       </method>
     </implementation>
 
     <handlers>
       <handler event="mousedown"><![CDATA[
           let element = event.target;
           this.mMouseX = event.screenX;
-          let mouseX = event.clientX - element.boxObject.x;
+          let mouseX = event.clientX - element.getBoundingClientRect().x;
 
           if (mouseX >= this.mMargin) {
               if (mouseX <= (this.mMargin + this.mWidth)) {
                   if (mouseX <= (this.mMargin + this.leftdragWidth)) {
                       // Move the startdate only...
                       window.setCursor("w-resize");
                       this.mDragState = 2;
                   } else if (mouseX >= (this.mMargin + this.mWidth - (this.rightdragWidth))) {
@@ -372,32 +372,32 @@
 
                   this.startDate = newStart;
                   this.endDate = newEnd;
                   this.mMouseX = mouseX;
                   this.update();
               }
           } else if (this.mDragState == 2) {
               // Move the startdate only...
-              let delta = event.screenX - this.mSelectionbar.boxObject.screenX;
+              let delta = event.screenX - this.mSelectionbar.screenX;
               let newStart = this.moveTime(this.mStartDate, delta, true);
               if (newStart.compare(this.mEndDate) >= 0) {
                   if (this.mStartDate.isDate) {
                       return;
                   }
                   newStart = this.mEndDate;
               }
               if (newStart.compare(this.mStartDate) != 0) {
                   this.startDate = newStart;
                   this.update();
               }
           } else if (this.mDragState == 3) {
               // Move the enddate only..
-              let delta = mouseX - (this.mSelectionbar.boxObject.screenX +
-                                    this.mSelectionbar.boxObject.width);
+              let delta = mouseX - (this.mSelectionbar.screenX +
+                                    this.mSelectionbar.getBoundingClientRect().width);
               let newEnd = this.moveTime(this.mEndDate, delta, true);
               if (newEnd.compare(this.mStartDate) < 0) {
                   newEnd = this.mStartDate;
               }
               if (newEnd.compare(this.mEndDate) != 0) {
                   // We need to adapt this date in case we're dealing with
                   // an all-day event. This is because setting 'endDate' will
                   // automatically add one day extra for all-day events.
--- a/calendar/base/content/dialogs/calendar-event-dialog-freebusy.xml
+++ b/calendar/base/content/dialogs/calendar-event-dialog-freebusy.xml
@@ -96,17 +96,17 @@
         ]]></setter>
       </property>
 
       <property name="dayHeight">
         <getter><![CDATA[
             let day =
                 document.getAnonymousElementByAttribute(
                     this, "anonid", "day");
-            return day.boxObject.height;
+            return day.getBoundingClientRect().height;
         ]]></getter>
       </property>
 
       <property name="date">
         <setter><![CDATA[
             let date = val.clone();
             date.hour = 0;
             date.minute = 0;
@@ -605,27 +605,27 @@
 
       <method name="calcContentHeight">
         <body><![CDATA[
             let items = this.getElementsByTagName("richlistitem");
             this.mContentHeight = 0;
             if (items.length > 0) {
                 let i = 0;
                 do {
-                    this.mRowHeight = items[i].boxObject.height;
+                    this.mRowHeight = items[i].getBoundingClientRect().height;
                     ++i;
                 } while (i < items.length && !this.mRowHeight);
                 this.mContentHeight = this.mRowHeight * items.length;
             }
         ]]></body>
       </method>
 
       <method name="createOrRemoveDummyRows">
         <body><![CDATA[
-            let listboxHeight = this.boxObject.height;
+            let listboxHeight = this.getBoundingClientRect().height;
 
             // Remove rows to remove scrollbar
             let kids = this.childNodes;
             for (let i = kids.length - 1; this.mContentHeight > listboxHeight && i >= 0; --i) {
                 if (kids[i].hasAttribute("_isDummyRow")) {
                     this.mContentHeight -= this.mRowHeight;
                     kids[i].remove();
                 }
--- a/calendar/base/content/dialogs/calendar-event-dialog-recurrence.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog-recurrence.js
@@ -57,26 +57,26 @@ const RecurrencePreview = {
      * Updates #recurrence-preview node layout on window resize.
      */
     onResize() {
         let minimonth = this.node.querySelector("minimonth");
 
         let row = this.node.querySelector("row");
         let rows = row.parentNode;
 
-        let contentWidth = minimonth.boxObject.width;
-        let containerWidth = this.node.boxObject.width;
+        let contentWidth = minimonth.getBoundingClientRect().width;
+        let containerWidth = this.node.getBoundingClientRect().width;
 
         // Now find out how much elements can be displayed.
         // this is a simple division which always yields a positive integer value.
         const cWidth = containerWidth % contentWidth;
         let numHorizontal = (containerWidth - cWidth) / contentWidth;
 
-        let contentHeight = minimonth.boxObject.height;
-        let containerHeight = this.node.boxObject.height;
+        let contentHeight = minimonth.getBoundingClientRect().height;
+        let containerHeight = this.node.getBoundingClientRect().height;
 
         const cHeight = containerHeight % contentHeight;
         // Now find out how much elements can be displayed.
         // this is a simple division which always yields a positive integer value.
         let numVertical = (containerHeight - cHeight) / contentHeight;
 
         // Count the number of existing rows
         let numRows = 0;
@@ -141,17 +141,17 @@ const RecurrencePreview = {
             row = row.nextSibling;
         }
     },
     /**
      * Updates preview of #recurrence-preview node.
      */
     updatePreview(recurrenceInfo) {
         let minimonth = this.node.querySelector("minimonth");
-        this.node.style.minHeight = minimonth.boxObject.height + "px";
+        this.node.style.minHeight = minimonth.getBoundingClientRect().height + "px";
 
         this.mRecurrenceInfo = recurrenceInfo;
         let start = this.dateTime.clone();
         start.day = 1;
         start.hour = 0;
         start.minute = 0;
         start.second = 0;
         let end = start.clone();
--- a/calendar/base/content/today-pane.js
+++ b/calendar/base/content/today-pane.js
@@ -180,17 +180,17 @@ var TodayPane = {
         } else if (x * x + y * y > 9) {
             // move the mouse a bit before starting the drag session
             window.addEventListener("mouseout", TodayPane.stopSwitching);
             TodayPane.minidayDrag.session = true;
             let dragCenterImage = document.getElementById("dragCenter-image");
             dragCenterImage.removeAttribute("hidden");
             // Move the starting point in the center so we have a fixed
             // point where stopping the day switching while still dragging
-            let centerObj = dragCenterImage.boxObject;
+            let centerObj = dragCenterImage.getBoundingClientRect();
             TodayPane.minidayDrag.startX = Math.floor(centerObj.x + centerObj.width / 2);
             TodayPane.minidayDrag.startY = Math.floor(centerObj.y + centerObj.height / 2);
 
             TodayPane.updateAdvanceTimer();
         }
     },
 
     /**
--- a/calendar/base/content/widgets/calendar-list-tree.xml
+++ b/calendar/base/content/widgets/calendar-list-tree.xml
@@ -877,17 +877,17 @@
           -
           - @param event     The DOM drop event.
           - @return          Boolean indicating if the drop succeeded.
           -
           -->
         <parameter name="event"/>
         <body><![CDATA[
             let hasDropped;
-            if (event.clientY < this.tree.boxObject.y) {
+            if (event.clientY < this.tree.getBoundingClientRect().y) {
                 hasDropped = this.drop(this.treebox.getFirstVisibleRow(), -1);
             } else {
                 hasDropped = this.drop(this.treebox.getLastVisibleRow(), 1);
             }
             if (hasDropped) {
                 event.preventDefault();
             }
             return hasDropped;
@@ -898,17 +898,17 @@
         <!--
           - Similar function to foreignCanDrop but for the dragenter event
           - @see ::foreignDrop
           -->
         <parameter name="event"/>
         <body><![CDATA[
             // The dragenter/dragover events expect false to be returned when
             // dropping is allowed, therefore we return !canDrop.
-            if (event.clientY < this.tree.boxObject.y) {
+            if (event.clientY < this.tree.getBoundingClientRect().y) {
                 return !this.canDrop(this.treebox.getFirstVisibleRow(), -1);
             } else {
                 return !this.canDrop(this.treebox.getLastVisibleRow(), 1);
             }
         ]]></body>
       </method>
 
       <method name="getParentIndex">
--- a/calendar/base/modules/utils/calViewUtils.jsm
+++ b/calendar/base/modules/utils/calViewUtils.jsm
@@ -20,21 +20,21 @@ var calview = {
      * Checks if the mousepointer of an event resides over a XULBox during an event
      *
      * @param aMouseEvent   The event eg. a 'mouseout' or 'mousedown' event
      * @param aXULBox       The xul element
      * @return              true or false depending on whether the mouse pointer
      *                      resides over the xulelement
      */
     isMouseOverBox: function(aMouseEvent, aXULElement) {
-        let boxObject = aXULElement.boxObject;
-        let boxWidth = boxObject.width;
-        let boxHeight = boxObject.height;
-        let boxScreenX = boxObject.screenX;
-        let boxScreenY = boxObject.screenY;
+        let boundingRect = aXULElement.getBoundingClientRect();
+        let boxWidth = boundingRect.width;
+        let boxHeight = boundingRect.height;
+        let boxScreenX = aXULElement.screenX;
+        let boxScreenY = aXULElement.screenY;
         let mouseX = aMouseEvent.screenX;
         let mouseY = aMouseEvent.screenY;
         let xIsWithin = (mouseX >= boxScreenX) &&
                         (mouseX <= (boxScreenX + boxWidth));
         let yIsWithin = (mouseY >= boxScreenY) &&
                         (mouseY <= (boxScreenY + boxHeight));
         return (xIsWithin && yIsWithin);
     },
--- a/calendar/test/mozmill/testBasicFunctionality.js
+++ b/calendar/test/mozmill/testBasicFunctionality.js
@@ -80,15 +80,15 @@ function testSmokeTest() {
     `));
 
     // Create test calendar.
     plan_for_modal_dialog("Calendar:NewCalendarWizard", (wizard) => {
         handleNewCalendarWizard(wizard, CALENDARNAME);
     });
     let calendarList = lookup(CALENDARLIST);
     // Double click on bottom left.
-    controller.doubleClick(calendarList, 0, calendarList.getNode().boxObject.height);
+    controller.doubleClick(calendarList, 0, calendarList.getNode().getBoundingClientRect().height);
     wait_for_modal_dialog("Calendar:NewCalendarWizard", TIMEOUT_MODAL_DIALOG);
 }
 
 function teardownTest(module) {
     deleteCalendars(controller, CALENDARNAME);
 }
--- a/calendar/test/mozmill/testTimezones.js
+++ b/calendar/test/mozmill/testTimezones.js
@@ -261,34 +261,34 @@ function verify(controller, dates, timez
     for (let [selectedYear, selectedMonth, selectedDay, selectedTime] of datetimes()) {
         goToDate(controller, selectedYear, selectedMonth, selectedDay);
 
         // Find event with timezone tz.
         for (let tzIdx = 0; tzIdx < timezones.length; tzIdx++) {
             let [correctHour, minutes, day] = selectedTime[tzIdx];
 
             let timeNode = lookup(`${timeLine}/[${correctHour}]`).getNode();
-            let timeY = timeNode.boxObject.y + timeNode.boxObject.height * (minutes / 60);
+            let timeY = timeNode.getBoundingClientRect().y + timeNode.getBoundingClientRect().height * (minutes / 60);
 
             let eventNodes = [];
 
             // following day
             if (day == 1) {
                 viewForward(controller, 1);
             } else if (day == -1) {
                 viewBack(controller, 1);
             }
 
             let stackNode = lookup(dayStack);
             controller.waitForElement(stackNode);
             stackNode = stackNode.getNode();
 
             findEventsInNode(stackNode, eventNodes);
             eventNodes = eventNodes.filter(node => node.mOccurrence.title == timezones[tzIdx])
-                                   .map(node => node.boxObject.y);
+                                   .map(node => node.getBoundingClientRect().y);
 
             dump(`Looking for ${timezones[tzIdx]} at ${timeY}: found `);
             dump(eventNodes.join(", ") + "\n");
 
             if (day != undefined && day == 1) {
                 viewBack(controller, 1);
             }
 
--- a/common/bindings/notificationbox.xml
+++ b/common/bindings/notificationbox.xml
@@ -278,17 +278,17 @@
       <method name="_showNotification">
         <parameter name="aNotification"/>
         <parameter name="aSlideIn"/>
         <parameter name="aSkipAnimation"/>
         <body>
           <![CDATA[
             this._finishAnimation();
 
-            var height = aNotification.boxObject.height;
+            var height = aNotification.getBoundingClientRect().height;
             var skipAnimation = aSkipAnimation || height == 0 ||
                                 !this._allowAnimation;
             aNotification.classList.toggle("animated", !skipAnimation);
 
             if (aSlideIn) {
               this.currentNotification = aNotification;
               aNotification.style.removeProperty("position");
               aNotification.style.removeProperty("top");
@@ -346,18 +346,18 @@
                 canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
               const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
               let content = this.firstChild;
               if (!content ||
                    content.namespaceURI != XULNS ||
                    content.localName != "browser")
                 return;
 
-              var width = content.boxObject.width;
-              var height = content.boxObject.height;
+              var width = content.getBoundingClientRect().width;
+              var height = content.getBoundingClientRect().height;
               content.collapsed = true;
 
               canvas.setAttribute("width", width);
               canvas.setAttribute("height", height);
               canvas.setAttribute("flex", "1");
 
               this.appendChild(canvas);
               this._blockingCanvas = canvas;
--- a/common/bindings/richlistbox.xml
+++ b/common/bindings/richlistbox.xml
@@ -540,26 +540,26 @@
             // the existing current item.
             if (this._isItemVisible(this.currentItem))
               this.scrollBy(0, this.clientHeight * aDirection);
 
             // Figure out, how many items fully fit into the view port
             // (including the currently selected one), and determine
             // the index of the first one lying (partially) outside
             var height = this.clientHeight;
-            var startBorder = this.currentItem.boxObject.y;
+            var startBorder = this.currentItem.getBoundingClientRect().y;
             if (aDirection == -1)
               startBorder += this.currentItem.clientHeight;
 
             var index = this.currentIndex;
             for (var ix = index; 0 <= ix && ix < children.length; ix += aDirection) {
-              var boxObject = children[ix].boxObject;
-              if (boxObject.height == 0)
+              var boundingRect = children[ix].getBoundingClientRect();
+              if (boundingRect.height == 0)
                 continue; // hidden children have a y of 0
-              var endBorder = boxObject.y + (aDirection == -1 ? boxObject.height : 0);
+              var endBorder = boundingRect.y + (aDirection == -1 ? boundingRect.height : 0);
               if ((endBorder - startBorder) * aDirection > height)
                 break; // we've reached the desired distance
               index = ix;
             }
 
             return index != this.currentIndex ? index - this.currentIndex : aDirection;
           ]]>
         </body>
@@ -663,21 +663,21 @@
 
       <method name="_isItemVisible">
         <parameter name="aItem"/>
         <body>
           <![CDATA[
             if (!aItem)
               return false;
 
-            var y = this.scrollTop + this.boxObject.y;
+            var y = this.scrollTop + this.getBoundingClientRect().y;
 
             // Partially visible items are also considered visible
-            return (aItem.boxObject.y + aItem.clientHeight > y) &&
-                   (aItem.boxObject.y < y + this.clientHeight);
+            return (aItem.getBoundingClientRect().y + aItem.clientHeight > y) &&
+                   (aItem.getBoundingClientRect().y < y + this.clientHeight);
           ]]>
         </body>
       </method>
 
       <property name="suppressOnSelect"
                 onget="return this.getAttribute('suppressonselect') == 'true';"
                 onset="this.setAttribute('suppressonselect', val);"/>
 
--- a/common/src/customizeToolbar.js
+++ b/common/src/customizeToolbar.js
@@ -108,19 +108,19 @@ function repositionDialog(aWindow) {
 
   var width;
   if (aWindow != window)
     width = aWindow.getBoundingClientRect().width;
   else if (document.documentElement.hasAttribute("width"))
     width = document.documentElement.getAttribute("width");
   else
     width = parseInt(document.documentElement.style.width);
-  var screenX = gToolbox.boxObject.screenX
-                + ((gToolbox.boxObject.width - width) / 2);
-  var screenY = gToolbox.boxObject.screenY + gToolbox.boxObject.height;
+  var screenX = gToolbox.screenX
+                + ((gToolbox.getBoundingClientRect().width - width) / 2);
+  var screenY = gToolbox.screenY + gToolbox.getBoundingClientRect().height;
 
   aWindow.moveTo(screenX, screenY);
 }
 
 function removeToolboxListeners() {
   var elts = getRootElements();
   for (let i = 0; i < elts.length; i++) {
     elts[i].removeEventListener("dragstart", onToolbarDragStart, true);
@@ -669,17 +669,17 @@ function onToolbarDragOver(aEvent) {
   var previousDragItem = gCurrentDragOverItem;
 
   if (dropTarget.localName == "toolbar") {
     gCurrentDragOverItem = dropTarget;
   } else {
     gCurrentDragOverItem = null;
 
     var direction = window.getComputedStyle(dropTarget.parentNode).direction;
-    var dropTargetCenter = dropTarget.boxObject.x + (dropTarget.boxObject.width / 2);
+    var dropTargetCenter = dropTarget.getBoundingClientRect().x + (dropTarget.getBoundingClientRect().width / 2);
     var dragAfter;
     if (direction == "ltr")
       dragAfter = aEvent.clientX > dropTargetCenter;
     else
       dragAfter = aEvent.clientX < dropTargetCenter;
 
     if (dragAfter) {
       gCurrentDragOverItem = dropTarget.nextSibling;
--- a/mail/base/content/folderDisplay.js
+++ b/mail/base/content/folderDisplay.js
@@ -2622,22 +2622,22 @@ FakeTree.prototype = {
       // Nothing to do
       return;
 
     let selection = this.view.selection;
     if (selection)
       selection.adjustSelection(aIndex, aCount);
   },
   get element() { return this.domNode; },
-  get x() { return this.domNode.boxObject.x; },
-  get y() { return this.domNode.boxObject.y; },
-  get screenX() { return this.domNode.boxObject.screenX; },
-  get screenY() { return this.domNode.boxObject.screenY; },
-  get width() { return this.domNode.boxObject.width; },
-  get height() { return this.domNode.boxObject.height; },
+  get x() { return this.domNode.getBoundingClientRect().x; },
+  get y() { return this.domNode.getBoundingClientRect().y; },
+  get screenX() { return this.domNode.screenX; },
+  get screenY() { return this.domNode.screenY; },
+  get width() { return this.domNode.getBoundingClientRect().width; },
+  get height() { return this.domNode.getBoundingClientRect().height; },
   get parentBox() { return this.domNode.boxObject.parentBox; },
   get firstChild() { return this.domNode.boxObject.firstChild; },
   get lastChild() { return this.domNode.boxObject.lastChild; },
   get nextSibling() { return this.domNode.boxObject.nextSibling; },
   get previousSibling() { return this.domNode.boxObject.previousSibling; },
   getPropertyAsSupports(propertyName) {
     return this.domNode.boxObject.getPropertyAsSupports(propertyName);
   },
--- a/mail/base/content/mailWidgets.xml
+++ b/mail/base/content/mailWidgets.xml
@@ -95,41 +95,41 @@
         <body><![CDATA[
           if (this._childNodes.length == 0)
             return -1;
 
           // First try to estimate which row is visible, assuming they're all
           // the same height.
           let box = this;
           let estimatedRow = Math.floor(box.scrollTop /
-                                        this._childNodes[0].boxObject.height);
+                                        this._childNodes[0].getBoundingClientRect().height);
           let estimatedIndex = estimatedRow * this._itemsPerRow();
-          let offset = this._childNodes[estimatedIndex].boxObject.screenY -
-                       box.boxObject.screenY;
+          let offset = this._childNodes[estimatedIndex].screenY -
+                       box.screenY;
 
           if (offset > 0) {
             // We went too far! Go back until we find an item totally off-
             // screen, then return the one after that.
             for (let i = estimatedIndex - 1; i >= 0; i--) {
-              let childBoxObj = this._childNodes[i].boxObject;
-              if (childBoxObj.screenY + childBoxObj.height <=
-                  box.boxObject.screenY)
+              let element = this._childNodes[i];
+              if (element.screenY + element.getBoundingClientRect().height <=
+                  box.screenY)
                 return i + 1;
             }
 
             // If we get here, we must have gone back to the beginning of the
             // list, so just return 0.
             return 0;
           }
           // We didn't go far enough! Keep going until we find an item at
           // least partially on-screen.
           for (let i = estimatedIndex; i < this._childNodes.length; i++) {
-            let childBoxObj = this._childNodes[i].boxObject;
-            if (childBoxObj.screenY + childBoxObj.height >
-                box.boxObject.screenY > 0)
+            let element = this._childNodes[i];
+            if (element.screenY + element.getBoundingClientRect().height >
+                box.screenY > 0)
               return i;
           }
 
           // If we get here, something is very wrong.
           Cu.reportError(
             "Couldn't get index of first visible row for attachmentlist!\n");
           return -1;
         ]]></body>
@@ -141,33 +141,33 @@
         ]]></body>
       </method>
       <method name="ensureElementIsVisible">
         <parameter name="item"/>
         <body><![CDATA[
           let box = this;
 
           // Are we too far down?
-          if (item.boxObject.screenY < box.boxObject.screenY)
-            box.scrollTop = item.boxObject.y - box.boxObject.y;
+          if (item.screenY < box.screenY)
+            box.scrollTop = item.getBoundingClientRect().y - box.getBoundingClientRect().y;
           // ... or not far enough?
-          else if (item.boxObject.screenY + item.boxObject.height >
-                   box.boxObject.screenY + box.boxObject.height)
-            box.scrollTop = item.boxObject.y + item.boxObject.height -
-                            box.boxObject.y - box.boxObject.height;
+          else if (item.screenY + item.getBoundingClientRect().height >
+                   box.screenY + box.getBoundingClientRect().height)
+            box.scrollTop = item.getBoundingClientRect().y + item.getBoundingClientRect().height -
+                            box.getBoundingClientRect().y - box.getBoundingClientRect().height;
         ]]></body>
       </method>
       <method name="scrollToIndex">
         <parameter name="index"/>
         <body><![CDATA[
           let box = this;
           let item = this.getItemAtIndex(index);
           if (!item)
             return;
-          box.scrollTop = item.boxObject.y - box.boxObject.y;
+          box.scrollTop = item.getBoundingClientRect().y - box.getBoundingClientRect().y;
         ]]></body>
       </method>
       <method name="appendItem">
         <parameter name="attachment"/>
         <parameter name="name"/>
         <body><![CDATA[
           // -1 appends due to the way getItemAtIndex is implemented.
           return this.insertItemAt(-1, attachment, name);
@@ -210,19 +210,19 @@
           item.attachment = attachment;
 
           this.insertBefore(item, this.getItemAtIndex(index));
           return item;
         ]]></body>
       </method>
 
       <!-- Get the preferred height (the height that would allow us to fit
-           everything without scrollbars) of the attachmentlist's boxObject. -->
+           everything without scrollbars) of the attachmentlist's bounding rectangle. -->
       <property name="preferredHeight" readonly="true"
-                onget="return this.scrollbox.scrollHeight - this.scrollbox.clientHeight + this.boxObject.height;"/>
+                onget="return this.scrollbox.scrollHeight - this.scrollbox.clientHeight + this.getBoundingClientRect().height;"/>
 
       <!-- Find the attachmentitem node for the specified nsIMsgAttachment. -->
       <method name="findItemForAttachment">
         <parameter name="aAttachment"/>
         <body><![CDATA[
           for (let i = 0; i < this.itemCount; i++) {
             let item = this.getItemAtIndex(i);
             if (item.attachment == aAttachment)
@@ -255,18 +255,18 @@
       </method>
 
       <method name="_itemsPerRow">
         <body><![CDATA[
           // For 0 or 1 children, we can assume that they all fit in one row.
           if (this._childNodes.length < 2)
             return this._childNodes.length;
 
-          let itemWidth = this._childNodes[1].boxObject.x -
-                          this._childNodes[0].boxObject.x;
+          let itemWidth = this._childNodes[1].getBoundingClientRect().x -
+                          this._childNodes[0].getBoundingClientRect().x;
 
           if (itemWidth == 0) // Each item takes up a full row
             return 1;
           return Math.floor(this.clientWidth / itemWidth);
         ]]></body>
       </method>
 
       <method name="_itemsPerCol">
@@ -274,18 +274,18 @@
         <body><![CDATA[
           let itemsPerRow = aItemsPerRow || this._itemsPerRow();
 
           if (this._childNodes.length == 0)
             return 0;
           else if (this._childNodes.length <= itemsPerRow)
             return 1;
 
-          let itemHeight = this._childNodes[itemsPerRow].boxObject.y -
-                           this._childNodes[0].boxObject.y;
+          let itemHeight = this._childNodes[itemsPerRow].getBoundingClientRect().y -
+                           this._childNodes[0].getBoundingClientRect().y;
 
           return Math.floor(this.clientHeight / itemHeight);
         ]]></body>
       </method>
 
       <method name="_setImageSize">
         <body><![CDATA[
           let size = this.sizes[this.view] || 16;
@@ -332,17 +332,17 @@
     </content>
     <implementation>
       <method name="setOptimumWidth">
         <body><![CDATA[
           if (this._childNodes.length == 0)
             return;
 
           let width = 0;
-          let border = this._childNodes[0].boxObject.width -
+          let border = this._childNodes[0].getBoundingClientRect().width -
                        this._childNodes[0].clientWidth;
 
           // If widths have changed after the initial calculation (updated
           // size string), clear each item's prior hardcoded width so
           // scrollwidth is natural, then get the width for the widest item
           // and set it on all the items again.
           for (let child of this._childNodes) {
             child.width = "";
--- a/mail/base/content/msgHdrView.js
+++ b/mail/base/content/msgHdrView.js
@@ -2596,22 +2596,22 @@ function toggleAttachmentList(expanded, 
     attachmentList.collapsed = false;
     if (!attachmentView.collapsed)
       attachmentSplitter.collapsed = false;
     attachmentBar.setAttribute("tooltiptext", bundle.getString(
       "collapseAttachmentPaneTooltip"));
 
     attachmentList.setOptimumWidth();
 
-    var attachmentHeight = attachmentView.boxObject.height -
-      attachmentList.boxObject.height + attachmentList.preferredHeight;
+    var attachmentHeight = attachmentView.getBoundingClientRect().height -
+      attachmentList.getBoundingClientRect().height + attachmentList.preferredHeight;
 
     // If the attachments box takes up too much of the message pane, downsize:
     var maxAttachmentHeight = document.getElementById("messagepanebox")
-                                      .boxObject.height / 4;
+                                      .getBoundingClientRect().height / 4;
 
     attachmentView.setAttribute("height", Math.min(attachmentHeight,
                                                    maxAttachmentHeight));
     attachmentView.setAttribute("maxheight", attachmentHeight);
 
     if (updateFocus)
       attachmentList.focus();
   } else {
--- a/mail/base/content/sanitizeDialog.js
+++ b/mail/base/content/sanitizeDialog.js
@@ -67,26 +67,26 @@ var gSanitizePromptDialog = {
 
     var warningBox = this.warningBox;
 
     // If clearing everything
     if (this.selectedTimespan === Sanitizer.TIMESPAN_EVERYTHING) {
       this.prepareWarning();
       if (warningBox.hidden) {
         warningBox.hidden = false;
-        window.resizeBy(0, warningBox.boxObject.height);
+        window.resizeBy(0, warningBox.getBoundingClientRect().height);
       }
       window.document.title =
         this.bundleBrowser.getString("sanitizeDialog2.everything.title");
       return;
     }
 
     // If clearing a specific time range
     if (!warningBox.hidden) {
-      window.resizeBy(0, -warningBox.boxObject.height);
+      window.resizeBy(0, -warningBox.getBoundingClientRect().height);
       warningBox.hidden = true;
     }
     window.document.title =
       window.document.documentElement.getAttribute("noneverythingtitle");
   },
 
   sanitize() {
     // Update pref values before handing off to the sanitizer (bug 453440)
@@ -194,31 +194,31 @@ var gSanitizePromptDialog = {
    */
   showItemList() {
     var itemList = document.getElementById("itemList");
     var expanderButton = document.getElementById("detailsExpander");
 
     if (itemList.collapsed) {
       expanderButton.className = "expander-up";
       itemList.setAttribute("collapsed", "false");
-      if (document.documentElement.boxObject.height)
-        window.resizeBy(0, itemList.boxObject.height);
+      if (document.documentElement.getBoundingClientRect().height)
+        window.resizeBy(0, itemList.getBoundingClientRect().height);
     }
   },
 
   /**
    * Hide the history items list.
    */
   hideItemList() {
     var itemList = document.getElementById("itemList");
     var expanderButton = document.getElementById("detailsExpander");
 
     if (!itemList.collapsed) {
       expanderButton.className = "expander-down";
-      window.resizeBy(0, -itemList.boxObject.height);
+      window.resizeBy(0, -itemList.getBoundingClientRect().height);
       itemList.setAttribute("collapsed", "true");
     }
   },
 
   /**
    * Called by the item list expander button to toggle the list's visibility.
    */
   toggleItemList() {
--- a/mail/base/content/tabmail.xml
+++ b/mail/base/content/tabmail.xml
@@ -2148,17 +2148,17 @@
           // 1 - alltabs    = close buttons on all tabs
           // 2 - noclose    = no close buttons at all
           // 3 - closeatend = close button at the end of the tabstrip
           switch (this.mCloseButtons) {
           case 0:
             this.setAttribute("closebuttons", "activetab");
             break;
           case 1:
-            var width = this.firstChild.boxObject.width;
+            var width = this.firstChild.getBoundingClientRect().width;
             // 0 width is an invalid value and indicates
             // an item without display, so ignore.
             if (width > this.mTabClipWidth || width == 0)
               this.setAttribute("closebuttons", "alltabs");
             else
               this.setAttribute("closebuttons", "activetab");
             break;
           case 2:
@@ -2181,17 +2181,17 @@
         <body><![CDATA[
           switch (aEvent.type) {
             case "overflow":
               this.arrowScrollbox.ensureElementIsVisible(this.selectedItem);
               break;
             case "underflow":
               break;
             case "resize":
-              var width = this.arrowScrollbox.boxObject.width;
+              var width = this.arrowScrollbox.getBoundingClientRect().width;
               if (width != this.arrowScrollboxWidth) {
                 this._updateCloseButtons();
                 // XXX without this line the tab bar won't budge
                 this.arrowScrollbox.scrollByPixels(1);
                 this._handleTabSelect();
                 this.arrowScrollboxWidth = width;
               }
               break;
@@ -2240,23 +2240,22 @@
             this.mDownBoxAnimate.style.opacity = 0.0;
           }
         ]]></body>
       </method>
 
       <method name="_notifyBackgroundTab">
         <parameter name="aTab"/>
         <body><![CDATA[
-          var tsbo = this.arrowScrollbox.boxObject;
+          var tsbo = this.arrowScrollbox;
           var tsboStart = tsbo.screenX;
-          var tsboEnd = tsboStart + tsbo.width;
-
-          var ctbo = aTab.boxObject;
-          var ctboStart = ctbo.screenX;
-          var ctboEnd = ctboStart + ctbo.width;
+          var tsboEnd = tsboStart + tsbo.getBoundingClientRect().width;
+
+          var ctboStart = aTab.screenX;
+          var ctboEnd = ctboStart + aTab.getBoundingClientRect().width;
 
           // only start the flash timer if the new tab (which was loaded in
           // the background) is not completely visible
           if (tsboStart > ctboStart || ctboEnd > tsboEnd) {
             this._animateStep = 0;
 
             if (!this._animateTimer)
               this._animateTimer =
@@ -2296,41 +2295,39 @@
           if (event.target.localName != "tab")
             return null;
 
           let tab = event.target;
 
           if ((event.type != "drop") && (event.type != "dragover"))
             return tab;
 
-          let boxObject = tab.boxObject;
-
-          if (event.screenX < boxObject.screenX + boxObject.width * .25)
+          if (event.screenX < tab.screenX + tab.getBoundingClientRect().width * .25)
             return null;
 
-          if (event.screenX > boxObject.screenX + boxObject.width * .75)
+          if (event.screenX > tab.screenX + tab.getBoundingClientRect().width * .75)
             return null;
 
           return tab;
         ]]></body>
       </method>
 
 
       <method name="_getDropIndex">
         <parameter name="event"/>
         <body><![CDATA[
           let tabs = this.childNodes;
 
           if (window.getComputedStyle(this).direction == "ltr") {
             for (let i = 0; i < tabs.length; i++)
-              if (event.screenX < (tabs[i].boxObject.screenX + (tabs[i].boxObject.width / 2)))
+              if (event.screenX < (tabs[i].screenX + (tabs[i].getBoundingClientRect().width / 2)))
                 return i;
           } else {
             for (let i = 0; i < tabs.length; i++)
-              if (event.screenX > (tabs[i].boxObject.screenX + (tabs[i].boxObject.width / 2)))
+              if (event.screenX > (tabs[i].screenX + (tabs[i].getBoundingClientRect().width / 2)))
                 return i;
           }
 
            return tabs.length;
         ]]></body>
       </method>
     </implementation>
     <handlers>
@@ -2380,26 +2377,26 @@
 
         // Create Drag Image
         let panel = document.getElementById("tabpanelcontainer");
 
         let thumbnail = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
         thumbnail.width = Math.ceil(screen.availWidth / 5.75);
         thumbnail.height = Math.round(thumbnail.width * 0.5625);
 
-        let snippetWidth = panel.boxObject.width * .6;
+        let snippetWidth = panel.getBoundingClientRect().width * .6;
         let scale = thumbnail.width / snippetWidth;
 
         let ctx = thumbnail.getContext("2d");
 
         ctx.scale(scale, scale);
 
         ctx.drawWindow(window,
-                panel.boxObject.screenX - window.mozInnerScreenX,
-                panel.boxObject.screenY - window.mozInnerScreenY,
+                panel.screenX - window.mozInnerScreenX,
+                panel.screenY - window.mozInnerScreenY,
                 snippetWidth,
                 snippetWidth * 0.5625,
                 "rgb(255,255,255)");
 
         dt = event.dataTransfer;
         dt.setDragImage(thumbnail, 0, 0);
 
         event.stopPropagation();
@@ -2636,20 +2633,20 @@
           return;
 
         // Disable detach within the browser toolbox
         var eX = event.screenX;
         var wX = window.screenX;
 
         // check if the drop point is horizontally within the window
         if (eX > wX && eX < (wX + window.outerWidth)) {
-          let bo = this.arrowScrollbox.boxObject;
+          let bo = this.arrowScrollbox;
           // also avoid detaching if the the tab was dropped too close to
           // the tabbar (half a tab)
-          let endScreenY = bo.screenY + 1.5 * bo.height;
+          let endScreenY = bo.screenY + 1.5 * bo.getBoundingClientRect().height;
           let eY = event.screenY;
 
           if (eY < endScreenY && eY > window.screenY)
             return;
         }
 
         // user wants to deatach tab from window...
         if (dt.mozItemCount != 1)
@@ -2751,21 +2748,21 @@
 
       <method name="_updateTabsVisibilityStatus">
         <body><![CDATA[
           var tabContainer = document.getElementById("tabmail").tabContainer;
           // We don't want menu item decoration unless there is overflow.
           if (tabContainer.getAttribute("overflow") != "true")
             return;
 
-          var tabstripBO = tabContainer.arrowScrollbox.boxObject;
+          var tabstripBO = tabContainer.arrowScrollbox;
           for (var i = 0; i < this.childNodes.length; i++) {
-            var curTabBO = this.childNodes[i].tab.boxObject;
+            var curTabBO = this.childNodes[i].tab;
             if (curTabBO.screenX >= tabstripBO.screenX &&
-                curTabBO.screenX + curTabBO.width <= tabstripBO.screenX + tabstripBO.width)
+                curTabBO.screenX + curTabBO.getBoundingClientRect().width <= tabstripBO.screenX + tabstripBO.getBoundingClientRect().width)
               this.childNodes[i].setAttribute("tabIsVisible", "true");
             else
               this.childNodes[i].removeAttribute("tabIsVisible");
           }
         ]]></body>
       </method>
 
       <method name="_createTabMenuItem">
--- a/mail/base/modules/GlobalPopupNotifications.jsm
+++ b/mail/base/modules/GlobalPopupNotifications.jsm
@@ -828,32 +828,32 @@ PopupNotifications.prototype = {
     if (!notificationsToShow.length) {
       return;
     }
     let notificationIds = notificationsToShow.map(n => n.id);
 
     this._refreshPanel(notificationsToShow);
 
     // If the anchor element is hidden or null, fall back to the identity icon.
-    if (!anchorElement || (anchorElement.boxObject.height == 0 &&
-                           anchorElement.boxObject.width == 0)) {
+    if (!anchorElement || (anchorElement.getBoundingClientRect().height == 0 &&
+                           anchorElement.getBoundingClientRect().width == 0)) {
       anchorElement = this.window.document.getElementById("identity-icon");
 
       // If the identity icon is not available in this window, or maybe the
       // entire location bar is hidden for any reason, use the tab as the
       // anchor. We only ever show notifications for the current browser, so we
       // can just use the current tab.
-      if (!anchorElement || (anchorElement.boxObject.height == 0 &&
-                             anchorElement.boxObject.width == 0)) {
+      if (!anchorElement || (anchorElement.getBoundingClientRect().height == 0 &&
+                             anchorElement.getBoundingClientRect().width == 0)) {
         anchorElement = this.tabbrowser.selectedTab;
 
         // If we're in an entirely chromeless environment, set the anchorElement
         // to null and let openPopup show the notification at (0,0) later.
-        if (!anchorElement || (anchorElement.boxObject.height == 0 &&
-                               anchorElement.boxObject.width == 0)) {
+        if (!anchorElement || (anchorElement.getBoundingClientRect().height == 0 &&
+                               anchorElement.getBoundingClientRect().width == 0)) {
           anchorElement = null;
         }
       }
     }
 
     if (this.isPanelOpen && this._currentAnchorElement == anchorElement) {
       notificationsToShow.forEach(function(n) {
         this._fireCallback(n, NOTIFICATION_EVENT_SHOWN);
--- a/mail/components/compose/content/MsgComposeCommands.js
+++ b/mail/components/compose/content/MsgComposeCommands.js
@@ -5653,43 +5653,40 @@ var envelopeDragObserver = {
    *                                   bottom of the list.
    */
   _adjustDropTarget(aEvent) {
     let target = aEvent.target;
     let bucket = document.getElementById("attachmentBucket");
 
     if (target == bucket) {
       // Dragging or dropping at top/bottom border of the listbox
-      let box = target.boxObject;
-      if ((aEvent.screenY - box.screenY) / box.height < 0.5) {
+      if ((aEvent.screenY - target.screenY) / target.getBoundingClientRect().height < 0.5) {
         target = bucket.firstChild;
       } else {
         target = bucket.lastChild;
       }
       // We'll check below if this is a valid target.
     } else if (target.id == "attachmentBucketCount") {
       // Dragging or dropping at top border of the listbox.
       // Allow bottom half of attachment list header as extended drop target
       // for top of list, because otherwise it would be too small.
-      let box = target.boxObject;
-      if ((aEvent.screenY - box.screenY) / box.height >= 0.5) {
+      if ((aEvent.screenY - target.screenY) / target.getBoundingClientRect().height >= 0.5) {
         target = bucket.firstChild;
         // We'll check below if this is a valid target.
       } else {
         // Top half of attachment list header: sorry, can't drop here.
         return "none";
       }
     }
 
     // Target is an attachmentitem.
     if (target.matches("richlistitem.attachmentItem")) {
       // If we're dragging/dropping in bottom half of attachmentitem,
       // adjust target to target.nextSibling (to show dropmarker above that).
-      let box = target.boxObject;
-      if ((aEvent.screenY - box.screenY) / box.height >= 0.5) {
+      if ((aEvent.screenY - target.screenY) / target.getBoundingClientRect().height >= 0.5) {
         target = target.nextSibling;
 
         // If there's no target.nextSibling, we're dragging/dropping
         // to the bottom of the list.
         if (!target) {
           // We can't move a bottom block selection to the bottom.
           if (attachmentsSelectionIsBlock("bottom"))
             return "none";
--- a/mail/components/compose/content/addressingWidgetOverlay.js
+++ b/mail/components/compose/content/addressingWidgetOverlay.js
@@ -56,20 +56,20 @@ function awInitializeNumberOfRowsShown()
   let extraHeight = 2;
 
   // Set minimum number of rows shown for address widget, per hardwired
   // rows="1" attribute of addressingWidget, to prevent resizing the
   // subject and format toolbar over the address widget.
   // This lets users shrink the address widget to one row (with delicate UX)
   // and thus maximize the space available for composition body,
   // especially on small screens.
-  msgHeadersToolbar.minHeight = msgHeadersToolbar.boxObject.height;
+  msgHeadersToolbar.minHeight = msgHeadersToolbar.getBoundingClientRect().height;
 
-  msgHeadersToolbar.height = msgHeadersToolbar.boxObject.height +
-    addressingWidget.boxObject.height * (awNumRowsShownDefault - 1) +
+  msgHeadersToolbar.height = msgHeadersToolbar.getBoundingClientRect().height +
+    addressingWidget.getBoundingClientRect().height * (awNumRowsShownDefault - 1) +
     extraHeight;
 
   // Update addressingWidget internals.
   awCreateOrRemoveDummyRows();
 }
 
 function awInputElementName() {
   if (inputElementType == "")
@@ -876,17 +876,17 @@ var gAWRowHeight = 0;
 
 function awFitDummyRows() {
   awCalcContentHeight();
   awCreateOrRemoveDummyRows();
 }
 
 function awCreateOrRemoveDummyRows() {
   let listbox = document.getElementById("addressingWidget");
-  let listboxHeight = listbox.boxObject.height;
+  let listboxHeight = listbox.getBoundingClientRect().height;
 
   // remove rows to remove scrollbar
   let kids = listbox.querySelectorAll("[_isDummyRow]");
   for (let i = kids.length - 1; gAWContentHeight > listboxHeight && i >= 0; --i) {
     gAWContentHeight -= gAWRowHeight;
     kids[i].remove();
   }
 
@@ -904,31 +904,31 @@ function awCalcContentHeight() {
   var items = listbox.getElementsByTagName("richlistitem");
 
   gAWContentHeight = 0;
   if (items.length > 0) {
     // all rows are forced to a uniform height in xul listboxes, so
     // find the first listitem with a boxObject and use it as precedent
     var i = 0;
     do {
-      gAWRowHeight = items[i].boxObject.height;
+      gAWRowHeight = items[i].getBoundingClientRect().height;
       ++i;
     } while (i < items.length && !gAWRowHeight);
     gAWContentHeight = gAWRowHeight * items.length;
   }
 }
 
 function awCreateDummyItem(aParent) {
   var listbox = document.getElementById("addressingWidget");
   var item = listbox.getElementsByTagName("richlistitem")[0];
 
   var titem = document.createElement("richlistitem");
   titem.setAttribute("_isDummyRow", "true");
   titem.setAttribute("class", "dummy-row");
-  titem.style.height = item.boxObject.height + "px";
+  titem.style.height = item.getBoundingClientRect().height + "px";
 
   for (let i = 0; i < awGetNumberOfCols(); i++) {
     let cell = awCreateDummyCell(titem);
     if (item.children[i].hasAttribute("style")) {
       cell.setAttribute("style", item.children[i].getAttribute("style"));
     }
     if (item.children[i].hasAttribute("flex")) {
       cell.setAttribute("flex", item.children[i].getAttribute("flex"));
--- a/mail/components/im/content/imconversation.xml
+++ b/mail/components/im/content/imconversation.xml
@@ -375,17 +375,17 @@
         let totalSpace = parseInt(window.getComputedStyle(this)
                                         .getPropertyValue("height"));
         let textbox = this.editor;
         let textboxStyle = window.getComputedStyle(textbox);
         let lineHeight = parseInt(textboxStyle.getPropertyValue("line-height"));
 
         // Compute the overhead size.
         let textboxHeight = textbox.clientHeight;
-        let deckHeight = textbox.parentNode.boxObject.height;
+        let deckHeight = textbox.parentNode.getBoundingClientRect().height;
         this._TEXTBOX_VERTICAL_OVERHEAD = deckHeight - textboxHeight;
 
         // Calculate the number of lines to display.
         let numberOfLines =
           Math.round(totalSpace * this._TEXTBOX_RATIO / lineHeight);
         if (numberOfLines <= 0)
           numberOfLines = 1;
 
--- a/mail/test/mozmill/attachment/test-attachment.js
+++ b/mail/test/mozmill/attachment/test-attachment.js
@@ -189,17 +189,17 @@ function test_long_attachment_name() {
   be_in_folder(folder);
 
   select_click_row(4);
   assert_selected_and_displayed(4);
 
   let messagepaneBox = mc.e("messagepanebox");
   let attachmentBar = mc.e("attachmentBar");
 
-  assert_true(messagepaneBox.boxObject.width >= attachmentBar.boxObject.width,
+  assert_true(messagepaneBox.getBoundingClientRect().width >= attachmentBar.getBoundingClientRect().width,
               "Attachment bar has expanded off the edge of the window!");
 }
 
 /**
  * Make sure that, when opening attached messages, we only show the attachments
  * "beneath" the attached message (as opposed to all attachments for the root
  * message).
  */
--- a/mail/test/mozmill/folder-display/test-opening-messages.js
+++ b/mail/test/mozmill/folder-display/test-opening-messages.js
@@ -163,42 +163,42 @@ function test_open_message_in_existing_w
 }
 
 /**
  * Check if the message pane in a new tab has the full height, so no
  * empty box is visible below it.
  */
 
 function check_message_pane_in_tab_full_height() {
-  let messagesBoxHeight = mc.e("messagesBox").boxObject.height;
-  let displayDeckHeight = mc.e("displayDeck").boxObject.height;
-  let messagePaneBoxWrapperHeight = mc.e("messagepaneboxwrapper").boxObject.height;
-  let notificationBoxHeight = mc.e("msg-footer-notification-box").boxObject.height;
+  let messagesBoxHeight = mc.e("messagesBox").getBoundingClientRect().height;
+  let displayDeckHeight = mc.e("displayDeck").getBoundingClientRect().height;
+  let messagePaneBoxWrapperHeight = mc.e("messagepaneboxwrapper").getBoundingClientRect().height;
+  let notificationBoxHeight = mc.e("msg-footer-notification-box").getBoundingClientRect().height;
 
   assert_equals(messagesBoxHeight, displayDeckHeight + messagePaneBoxWrapperHeight + notificationBoxHeight,
       "messanges box height (" + messagesBoxHeight +
       ") not equal to the sum of displayDeck height (" + displayDeckHeight +
       ") and message pane box wrapper height (" + messagePaneBoxWrapperHeight +
       ") and message notification box height (" + notificationBoxHeight +
       ")");
 }
 
 /**
  * Check if the message pane in a new window has the full height, so no
  * empty box is visible below it.
  */
 
 function check_message_pane_in_window_full_height(aWC) {
-  let messengerWindowHeight = aWC.e("messengerWindow").boxObject.height;
+  let messengerWindowHeight = aWC.e("messengerWindow").getBoundingClientRect().height;
   let messengerChildren = aWC.e("messengerWindow").children;
   let childrenHeightsSum = 0;
   let childrenHeightsStr = "";
   for (let child of messengerChildren) {
     if ("boxObject" in child) {
-      childrenHeightsSum += child.boxObject.height;
-      childrenHeightsStr += '"' + child.id + '": ' + child.boxObject.height + ', ';
+      childrenHeightsSum += child.getBoundingClientRect().height;
+      childrenHeightsStr += '"' + child.id + '": ' + child.getBoundingClientRect().height + ', ';
     }
   }
 
   assert_equals(messengerWindowHeight, childrenHeightsSum,
     "messenger window height not equal to the sum of children heights: " +
     childrenHeightsStr);
 }
--- a/mail/test/mozmill/session-store/test-session-store.js
+++ b/mail/test/mozmill/session-store/test-session-store.js
@@ -199,30 +199,30 @@ function test_message_pane_height_persis
   be_in_folder(folderA);
   assert_message_pane_visible();
   assert_pane_layout(kClassicMailLayout);
 
   // Get the state object. This assumes there is one and only one
   // 3pane window.
   let mail3PaneWindow = Services.wm.getMostRecentWindow("mail:3pane");
 
-  let oldHeight = mc.e("messagepaneboxwrapper").boxObject.height;
+  let oldHeight = mc.e("messagepaneboxwrapper").getBoundingClientRect().height;
   let minHeight = Math.floor(mc.e("messagepaneboxwrapper").getAttribute("minheight"));
   let newHeight = Math.floor((minHeight + oldHeight) / 2);
   let diffHeight = oldHeight - newHeight;
 
   assert_not_equals(oldHeight, newHeight,
     "To really perform a test the new message pane height should be " +
     "should be different from the old one but they are the same: " +
     newHeight);
 
   _move_splitter(mc.e("threadpane-splitter"), 0, diffHeight);
 
   // Check that the moving of the threadpane-splitter resulted in the correct height.
-  let actualHeight = mc.e("messagepaneboxwrapper").boxObject.height;
+  let actualHeight = mc.e("messagepaneboxwrapper").getBoundingClientRect().height;
 
   assert_equals(newHeight, actualHeight,
     "The message pane height should be " + newHeight + ", but is actually " +
     actualHeight + ". The oldHeight was: " + oldHeight);
 
   // Make sure we have a different window open, so that we don't start shutting
   // down just because the last window was closed.
   let abwc = openAddressBook();
@@ -231,17 +231,17 @@ function test_message_pane_height_persis
   close_window(new mozmill.controller.MozMillController(mail3PaneWindow));
   // Wait for window close async session write to finish.
   controller.sleep(asyncFileWriteDelayMS);
 
   mc = open3PaneWindow();
   be_in_folder(folderA);
   assert_message_pane_visible();
 
-  actualHeight = mc.e("messagepaneboxwrapper").boxObject.height;
+  actualHeight = mc.e("messagepaneboxwrapper").getBoundingClientRect().height;
 
   assert_equals(newHeight, actualHeight,
     "The message pane height should be " + newHeight + ", but is actually " +
     actualHeight + ". The oldHeight was: " + oldHeight);
 
   // The old height is restored.
   _move_splitter(mc.e("threadpane-splitter"), 0, -diffHeight);
 
@@ -249,17 +249,17 @@ function test_message_pane_height_persis
   close_window(mc);
   // Wait for window close async session write to finish.
   controller.sleep(asyncFileWriteDelayMS);
 
   mc = open3PaneWindow();
   be_in_folder(folderA);
   assert_message_pane_visible();
 
-  actualHeight = mc.e("messagepaneboxwrapper").boxObject.height;
+  actualHeight = mc.e("messagepaneboxwrapper").getBoundingClientRect().height;
   assert_equals(oldHeight, actualHeight,
     "The message pane height should be " + oldHeight + ", but is actually " +
     actualHeight);
 
   // We don't need the address book window any more.
   plan_for_window_close(abwc);
   abwc.window.close();
   wait_for_window_close();
@@ -274,30 +274,30 @@ function test_message_pane_width_persist
   assert_pane_layout(kClassicMailLayout);
   set_pane_layout(kVerticalMailLayout);
   assert_pane_layout(kVerticalMailLayout);
 
   // Get the state object. This assumes there is one and only one
   // 3pane window.
   let mail3PaneWindow = Services.wm.getMostRecentWindow("mail:3pane");
 
-  let oldWidth = mc.e("messagepaneboxwrapper").boxObject.width;
+  let oldWidth = mc.e("messagepaneboxwrapper").getBoundingClientRect().width;
   let minWidth = Math.floor(mc.e("messagepaneboxwrapper").getAttribute("minwidth"));
   let newWidth = Math.floor((minWidth + oldWidth) / 2);
   let diffWidth = oldWidth - newWidth;
 
   assert_not_equals(newWidth, oldWidth,
     "To really perform a test the new message pane width should be " +
     "should be different from the old one but they are the same: " + newWidth);
 
   // We move the threadpane-splitter and not the folderpane_splitter because
   // we are in vertical layout.
   _move_splitter(mc.e("threadpane-splitter"), diffWidth, 0);
   // Check that the moving of the folderpane_splitter resulted in the correct width.
-  let actualWidth = mc.e("messagepaneboxwrapper").boxObject.width;
+  let actualWidth = mc.e("messagepaneboxwrapper").getBoundingClientRect().width;
 
   // FIXME: For whatever reasons the new width is off by one pixel on Mac OSX
   // But this test case is not for testing moving around a splitter but for
   // persistency. Therefore it is enough if the actual width is equal to the
   // the requested width plus/minus one pixel.
   assert_equals_fuzzy(newWidth, actualWidth, 1,
     "The message pane width should be " + newWidth + ", but is actually " +
     actualWidth + ". The oldWidth was: " + oldWidth);
@@ -312,23 +312,23 @@ function test_message_pane_width_persist
   // Wait for window close async session write to finish.
   controller.sleep(asyncFileWriteDelayMS);
 
   mc = open3PaneWindow();
   be_in_folder(folderA);
   assert_message_pane_visible();
   assert_pane_layout(kVerticalMailLayout);
 
-  actualWidth = mc.e("messagepaneboxwrapper").boxObject.width;
+  actualWidth = mc.e("messagepaneboxwrapper").getBoundingClientRect().width;
   assert_equals(newWidth, actualWidth, "The message pane width should be " +
     newWidth + ", but is actually " + actualWidth);
 
   // The old width is restored.
   _move_splitter(mc.e("threadpane-splitter"), -diffWidth, 0);
-  actualWidth = mc.e("messagepaneboxwrapper").boxObject.width;
+  actualWidth = mc.e("messagepaneboxwrapper").getBoundingClientRect().width;
 
   // FIXME: For whatever reasons the new width is off by two pixels on Mac OSX
   // But this test case is not for testing moving around a splitter but for
   // persistency. Therefore it is enough if the actual width is equal to the
   // the requested width plus/minus two pixels.
   assert_equals_fuzzy(oldWidth, actualWidth, 2,
     "The message pane width should be " + oldWidth + ", but is actually " +
     actualWidth);
@@ -339,17 +339,17 @@ function test_message_pane_width_persist
   // Wait for window close async session write to finish.
   controller.sleep(asyncFileWriteDelayMS);
 
   mc = open3PaneWindow();
   be_in_folder(folderA);
   assert_message_pane_visible();
   assert_pane_layout(kVerticalMailLayout);
 
-  actualWidth = mc.e("messagepaneboxwrapper").boxObject.width;
+  actualWidth = mc.e("messagepaneboxwrapper").getBoundingClientRect().width;
   assert_equals(oldWidth, actualWidth, "The message pane width should be " +
     oldWidth + ", but is actually " + actualWidth);
 
   // The layout is reset to classical mail layout.
   set_pane_layout(kClassicMailLayout);
   assert_pane_layout(kClassicMailLayout);
 
   // We don't need the address book window any more.
--- a/mail/test/mozmill/shared-modules/test-folder-display-helpers.js
+++ b/mail/test/mozmill/shared-modules/test-folder-display-helpers.js
@@ -1091,28 +1091,28 @@ function select_shift_click_row(aViewInd
  * Helper function to click on a row with a given button.
  */
 function _row_click_helper(aController, aTree, aViewIndex, aButton, aExtra) {
   // Force-focus the tree
   aTree.focus();
   // very important, gotta be able to see the row
   aTree.ensureRowIsVisible(aViewIndex);
   // coordinates of the upper left of the entire tree widget (headers included)
-  let tx = aTree.boxObject.x, ty = aTree.boxObject.y;
+  let tx = aTree.getBoundingClientRect().x, ty = aTree.getBoundingClientRect().y;
   // coordinates of the row display region of the tree (below the headers)
   let children = aController.e(aTree.id, {tagName: "treechildren"});
-  let x = children.boxObject.x, y = children.boxObject.y;
+  let x = children.getBoundingClientRect().x, y = children.getBoundingClientRect().y;
   // Click in the middle of the row by default
-  let rowX = children.boxObject.width / 2;
+  let rowX = children.getBoundingClientRect().width / 2;
   // For the thread tree, Position our click on the subject column (which cannot
   // be hidden), and far enough in that we are in no danger of clicking the
   // expand toggler unless that is explicitly requested.
   if (aTree.id == "threadTree") {
     let subjectCol = aController.e("subjectCol");
-    rowX = subjectCol.boxObject.x - tx + 8;
+    rowX = subjectCol.getBoundingClientRect().x - tx + 8;
     // click on the toggle if so requested
     if (aExtra !== "toggle")
       rowX += 32;
   }
   let rowY = aTree.rowHeight * (aViewIndex - aTree.getFirstVisibleRow()) +
     aTree.rowHeight / 2;
   if (aTree.getRowAt(x + rowX, y + rowY) != aViewIndex) {
     throw new Error("Thought we would find row " + aViewIndex + " at " +
--- a/mail/test/mozmill/shared-modules/test-mouse-event-helpers.js
+++ b/mail/test/mozmill/shared-modules/test-mouse-event-helpers.js
@@ -51,20 +51,20 @@ function drag_n_drop_element(aDragObject
                              aDropWindow, aRelDropX, aRelDropY, aListener)
 {
   let dt = synthesize_drag_start(aDragWindow, aDragObject, aListener);
   fdh.assert_true(dt, "Drag target was undefined");
 
   synthesize_drag_over(aDropWindow, aDropObject, dt);
 
   synthesize_drop(aDropWindow, aDropObject, dt,
-      { screenX : aDropObject.boxObject.screenX +
-                    (aDropObject.boxObject.width * aRelDropX),
-        screenY : aDropObject.boxObject.screenY +
-                    (aDropObject.boxObject.width * aRelDropY)
+      { screenX : aDropObject.screenX +
+                    (aDropObject.getBoundingClientRect().width * aRelDropX),
+        screenY : aDropObject.screenY +
+                    (aDropObject.getBoundingClientRect().width * aRelDropY)
       });
 }
 
 /**
  * Starts a drag new session.
  * @param {} aWindow
  * @param {XULElement} aDispatcher
  *   the element from which the drag session should be started.
@@ -166,21 +166,21 @@ function synthesize_drop(aWindow, aDispa
  *   arguments passed to the mouse event.
  */
 function _synthesizeDragEvent(aType, aWindow, aDispatcher, aDt, aArgs)
 {
   let screenX;
   if (aArgs && ("screenX" in aArgs))
     screenX = aArgs.screenX;
   else
-    screenX = aDispatcher.boxObject.ScreenX;
+    screenX = aDispatcher.ScreenX;
 
   let screenY;
   if (aArgs && ("screenY" in aArgs))
     screenY = aArgs.screenY;
   else
-    screenY = aDispatcher.boxObject.ScreenY;
+    screenY = aDispatcher.ScreenY;
 
   let event = aWindow.document.createEvent("DragEvent");
   event.initDragEvent(aType, true, true, aWindow, 0,
       screenX, screenY, 0, 0, false, false, false, false, 0, null, aDt);
   aDispatcher.dispatchEvent(event);
 }
--- a/mail/test/mozmill/shared-modules/test-quick-filter-bar-helper.js
+++ b/mail/test/mozmill/shared-modules/test-quick-filter-bar-helper.js
@@ -72,17 +72,17 @@ var nameToBarDomId = {
 function assert_quick_filter_button_enabled(aEnabled) {
   if (mc.e("qfb-show-filter-bar").disabled == aEnabled) {
     throw new Error("Quick filter bar button should be " +
                     (aEnabled ? "enabled" : "disabled"));
   }
 }
 
 function assert_quick_filter_bar_visible(aVisible) {
-  if ((mc.e("quick-filter-bar").boxObject.height > 0) != aVisible) {
+  if ((mc.e("quick-filter-bar").getBoundingClientRect().height > 0) != aVisible) {
     throw new Error("Quick filter bar should be " +
                     (aVisible ? "visible" : "collapsed"));
   }
 }
 
 /**
  * Toggle the state of the message filter bar as if by a mouse click.
  */
--- a/mail/test/mozmill/tabmail/test-tabmail-dragndrop.js
+++ b/mail/test/mozmill/tabmail/test-tabmail-dragndrop.js
@@ -223,26 +223,25 @@ function test_tab_reorder_detach(){
   plan_for_new_window("mail:3pane");
 
   // ... now start dragging
 
   mc.tabmail.switchToTab(1);
 
   let tab1 = mc.tabmail.tabContainer.childNodes[1];
   let dropContent = mc.e("tabpanelcontainer");
-  let box = dropContent.boxObject;
 
   let dt = synthesize_drag_start(mc.window, tab1, mc.tabmail.tabContainer);
 
   synthesize_drag_over(mc.window, dropContent, dt);
 
   // notify tab1 drag has ended
   synthesize_drag_end(mc.window, dropContent, tab1, dt,
-      { screenX : (box.screenX + box.width / 2 ),
-        screenY : (box.screenY + box.height / 2 ) });
+      { screenX : (dropContent.screenX + dropContent.getBoundingClientRect().width / 2 ),
+        screenY : (dropContent.screenY + dropContent.getBoundingClientRect().height / 2 ) });
 
   // ... and wait for the new window
   mc2 = wait_for_new_window("mail:3pane");
   wait_for_message_display_completion(mc2, true);
 
   assert_true(mc.tabmail.tabContainer.childNodes.length == 1,
       "Moving tab to new window failed, tab still in old window");
 
--- a/mail/test/resources/mozmill/mozmill/extension/content/modules/events.jsm
+++ b/mail/test/resources/mozmill/mozmill/extension/content/modules/events.jsm
@@ -148,18 +148,18 @@ var triggerKeyEvent = function(element, 
 
 /* Fire a mouse event in a browser-compatible manner */
 var triggerMouseEvent = function(element, eventType, canBubble, clientX, clientY, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown) {
   clientX = clientX ? clientX : 0;
   clientY = clientY ? clientY : 0;
 
   // Fixing this - make the mouse understand where it is on the screen, needed
   // for double click.
-  var screenX = element.boxObject.screenX ? element.boxObject.screenX : 0;
-  var screenY = element.boxObject.screenY ? element.boxObject.screenY : 0;
+  var screenX = element.screenX ? element.screenX : 0;
+  var screenY = element.screenY ? element.screenY : 0;
 
   canBubble = (typeof(canBubble) == undefined) ? true : canBubble;
 
   var evt = element.ownerGlobal.document.createEvent("MouseEvents");
   if (evt.initMouseEvent) {
     // LOG.info("element has initMouseEvent");
     // Safari
     evt.initMouseEvent(eventType, canBubble, true, element.ownerGlobal, 1, screenX, screenY, clientX, clientY, controlKeyDown, altKeyDown, shiftKeyDown, metaKeyDown, 0, null);
--- a/mailnews/db/gloda/content/autocomplete-richlistitem.js
+++ b/mailnews/db/gloda/content/autocomplete-richlistitem.js
@@ -149,21 +149,21 @@
 
     _setUpOverflow(aParentBox, aEllipsis) {
       // Hide the ellipsis in case there's just enough to not underflow.
       aEllipsis.hidden = true;
 
       // Start with the parent's width and subtract off its children.
       let tooltip = [];
       let children = aParentBox.childNodes;
-      let widthDiff = aParentBox.boxObject.width;
+      let widthDiff = aParentBox.getBoundingClientRect().width;
 
       for (let i = 0; i < children.length; i++) {
         // Only consider a child if it actually takes up space.
-        let childWidth = children[i].boxObject.width;
+        let childWidth = children[i].getBoundingClientRect().width;
         if (childWidth > 0) {
           // Subtract a little less to account for subpixel rounding.
           widthDiff -= childWidth - .5;
 
           // Add to the tooltip if it's not hidden and has text.
           let childText = children[i].textContent;
           if (childText) {
             tooltip.push(childText);