/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is the Tree Style Tab. * * The Initial Developer of the Original Code is SHIMODA Hiroshi. * Portions created by the Initial Developer are Copyright (C) 2010-2012 * the Initial Developer. All Rights Reserved. * * Contributor(s): SHIMODA Hiroshi * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ******/ const EXPORTED_SYMBOLS = ['AutoHideBrowser', 'AutoHideWindow']; const Cc = Components.classes; const Ci = Components.interfaces; function AutoHideBrowser(aTabBrowser) { this.init(aTabBrowser); } AutoHideBrowser.prototype = { kMODE : 'treestyletab-tabbar-autohide-mode', kMODE_DISABLED : 0, kMODE_HIDE : 1, kMODE_SHRINK : 2, kAUTOHIDE : 'treestyletab-tabbar-autohide', kSTATE : 'treestyletab-tabbar-autohide-state', kSTATE_HIDDEN : 'hidden', kSTATE_EXPANDED : 'expanded', kSTATE_SHRUNKEN : 'shrunken', kSHOWN_BY_UNKNOWN : 0, kSHOWN_BY_SHORTCUT : 1 << 0, kSHOWN_BY_MOUSEMOVE : 1 << 1, kSHOWN_BY_FEEDBACK : 1 << 2, kKEEP_SHOWN_ON_MOUSEOVER : (1 << 0) | (1 << 1) | (1 << 2), get mode() /* PUBLIC API */ { var mode = this.browser.getAttribute(this.kMODE); return mode ? parseInt(mode) : this.kMODE_DISABLED ; }, set mode(aValue) { this.browser.setAttribute(this.kMODE, aValue); return aValue; }, getMode : function AHB_getMode(aTabBrowser) { var b = aTabBrowser || this.browser; var mode = b.getAttribute(this.kMODE); return mode ? parseInt(mode) : this.kMODE_DISABLED ; }, getModeForNormal : function AHB_getModeForNormal(aTabBrowser) { var b = aTabBrowser || this.browser; return parseInt(b.getAttribute(this.kMODE+'-normal') || this.treeStyleTab.getTreePref('tabbar.autoHide.mode')); }, getModeForFullScreen : function AHB_getModeForFullScreen(aTabBrowser) { var b = aTabBrowser || this.browser; return parseInt(b.getAttribute(this.kMODE+'-fullscreen') || this.treeStyleTab.getTreePref('tabbar.autoHide.mode.fullscreen')); }, get state() { return this.browser.getAttribute(this.kSTATE) || this.kSTATE_EXPANDED; }, get expanded() { return this.state == this.kSTATE_EXPANDED; }, get shrunken() { return this.state == this.kSTATE_SHRUNKEN; }, get hidden() { return this.state == this.kSTATE_HIDDEN; }, updateMode : function AHB_updateMode() { this.end(); // update internal property after the appearance of the tab bar is updated. var w = this.window; w.setTimeout(function(aSelf) { aSelf.mode = (w.fullScreen && aSelf.treeStyleTab.getPref('browser.fullscreen.autohide')) ? aSelf.getModeForFullScreen() : aSelf.getModeForNormal() ; if (aSelf.mode != aSelf.kMODE_DISABLED) aSelf.start(); }, 0, this); }, togglerSize : 0, sensitiveArea : 7, contentAreaScreenEnabled : true, closeButtonsMode : -1, CLOSE_BUTTONS_ONLY_ON_CURRENT_TAB : 0, CLOSE_BUTTONS_ON_ALL_TABS : 1, CLOSE_BUTTONS_DISABLED : 2, CLOSE_BUTTONS_ON_TABBAR : 3, get XOffset() { var sv = this.treeStyleTab; switch (this.mode) { case this.kMODE_DISABLED: return 0; case this.kMODE_HIDE: let offset = this.width + this.splitterWidth; let resizer = this.resizer; if (sv.position == 'left') { offset += this.togglerSize; if (resizer) offset += resizer.boxObject.width; } else if (sv.position == 'right') { offset -= this.togglerSize; if (resizer) offset -= resizer.boxObject.width; } return offset; default: case this.kMODE_SHRINK: return sv.getTreePref('tabbar.width') - sv.getTreePref('tabbar.shrunkenWidth'); } }, get YOffset() { return this.height; }, extraXOffset : 0, extraYOffset : 0, get currentXOffset() { var sv = this.treeStyleTab; return ( sv.position == 'left' && this.mode != this.kMODE_DISABLED && this.expanded ) ? this.XOffset : 0 ; }, get currentYOffset() { var sv = this.treeStyleTab; return ( sv.position == 'top' && this.mode != this.kMODE_DISABLED && this.expanded ) ? this.YOffset : 0 ; }, get screen() { return this.document.getElementById('treestyletab-autohide-content-area-screen'); }, get resizer() { return this.document.getElementById('treestyletab-tabbar-resizer-splitter'); }, start : function AHB_start() { if (this.enabled) return; this.enabled = true; var sv = this.treeStyleTab; var b = this.browser; var w = this.window; this.screen.hidePopup(); sv.setTabbrowserAttribute(this.kSTATE, this.kSTATE_EXPANDED); b.addEventListener('mousedown', this, true); b.addEventListener('mouseup', this, true); b.addEventListener('dragover', this, true); b.addEventListener('dragleave', this, true); sv.tabStrip.addEventListener('mousedown', this, true); sv.tabStrip.addEventListener('mouseup', this, true); w.addEventListener(sv.kEVENT_TYPE_PRINT_PREVIEW_ENTERED, this, false); w.addEventListener(sv.kEVENT_TYPE_PRINT_PREVIEW_EXITED, this, false); if (this.shouldListenMouseMove) this.startListenMouseMove(); if (b == w.gBrowser && sv.shouldListenKeyEventsForAutoHide) w.TreeStyleTabService.startListenKeyEventsFor(sv.LISTEN_FOR_AUTOHIDE); this.updateTransparency(); this.showHideInternal(); b.treeStyleTab.fixTooNarrowTabbar(); }, end : function AHB_end() { if (!this.enabled) return; this.enabled = false; var sv = this.treeStyleTab; var b = this.browser; var w = this.window; this.show(); this.screen.hidePopup(); b.removeEventListener('mousedown', this, true); b.removeEventListener('mouseup', this, true); b.removeEventListener('dragover', this, true); b.removeEventListener('dragleave', this, true); sv.tabStrip.removeEventListener('mousedown', this, true); sv.tabStrip.removeEventListener('mouseup', this, true); w.removeEventListener(sv.kEVENT_TYPE_PRINT_PREVIEW_ENTERED, this, false); w.removeEventListener(sv.kEVENT_TYPE_PRINT_PREVIEW_EXITED, this, false); this.endListenMouseMove(); if (b == w.gBrowser) w.TreeStyleTabService.endListenKeyEventsFor(sv.LISTEN_FOR_AUTOHIDE); this.updateTransparency(); sv.removeTabbrowserAttribute(this.kAUTOHIDE); sv.removeTabbrowserAttribute(this.kSTATE); if (sv.isVertical) sv.setTabStripAttribute('width', this.widthFromMode); }, // fullscreen startForFullScreen : function AHB_startForFullScreen() { this.mode = this.getMode(); this.end(); this.mode = this.treeStyleTab.getPref('browser.fullscreen.autohide') ? this.getModeForFullScreen() : this.kMODE_DISABLED ; if (this.mode != this.kMODE_DISABLED) { this.start(); this.treeStyleTab.removeTabbrowserAttribute('moz-collapsed'); } }, endForFullScreen : function AHB_endForFullScreen() { this.mode = this.getModeForFullScreen(); this.end(); this.mode = this.treeStyleTab.getTreePref('tabbar.autoHide.mode'); this.treeStyleTab.checkTabsIndentOverflow(); if (this.mode != this.kMODE_DISABLED) this.start(); }, // mousemove startListenMouseMove : function AHB_startListenMouseMove() { if (this.mouseMoveListening) return; this.browser.addEventListener('mousemove', this, true); this.screen.addEventListener('mousemove', this, true); this.treeStyleTab.tabStrip.addEventListener('mousemove', this, true); this.mouseMoveListening = true; }, endListenMouseMove : function AHB_endListenMouseMove() { if (!this.mouseMoveListening) return; this.browser.removeEventListener('mousemove', this, true); this.screen.removeEventListener('mousemove', this, true); this.treeStyleTab.tabStrip.removeEventListener('mousemove', this, true); this.mouseMoveListening = false; }, get shouldListenMouseMove() { return this.treeStyleTab.getTreePref('tabbar.autoShow.mousemove'); }, get shouldListenKeyEventsForAutoHide() { return this.treeStyleTab.getTreePref('tabbar.autoShow.accelKeyDown') || this.treeStyleTab.getTreePref('tabbar.autoShow.tabSwitch'); }, showHideOnMouseMove : function AHB_showHideOnMouseMove(aEvent) { var position = this.getMousePosition(aEvent); if (position == this.MOUSE_POSITION_UNKNOWN) return; this.cancelShowHideOnMouseMove(); this.showHideContentsAreaScreen(); var sv = this.treeStyleTab; var b = this.browser; var w = this.window; var shouldShow = position & this.MOUSE_POSITION_SENSITIVE; if (this.expanded) { if ( shouldShow && this.showHideReason & this.kKEEP_SHOWN_ON_MOUSEOVER && sv.getTreePref('tabbar.autoShow.keepShownOnMouseover') ) { this.showHideReason = this.kSHOWN_BY_MOUSEMOVE; this.cancelDelayedShowForShortcut(); this.cancelHideForFeedback(); } else if ( !shouldShow && sv.getTreePref('tabbar.autoShow.mousemove') ) { this.showHideOnMouseMoveTimer = w.setTimeout( function(aSelf) { aSelf.cancelDelayedShowForShortcut(); if (aSelf.showHideReason == aSelf.kSHOWN_BY_MOUSEMOVE) aSelf.hide(aSelf.kSHOWN_BY_MOUSEMOVE); }, sv.getTreePref('tabbar.autoHide.delay'), this ); } } else if (shouldShow) { this.showHideOnMouseMoveTimer = w.setTimeout( function(aSelf) { aSelf.cancelDelayedShowForShortcut(); aSelf.cancelHideForFeedback(); aSelf.show(aSelf.kSHOWN_BY_MOUSEMOVE); }, sv.getTreePref('tabbar.autoHide.delay'), this ); } b = null; }, getMousePosition : function AHB_getMousePosition(aEvent) { var w = this.window; if ('gestureInProgress' in w && w.gestureInProgress) return this.MOUSE_POSITION_UNKNOWN; var sv = this.treeStyleTab; var b = this.browser; var pos = sv.position; var box = this.getContentsAreaBox(); var sensitiveArea = this.sensitiveArea; if (this.shrunken) { let clickable; if (this.widthFromMode > 24 && (clickable = this.getNearestClickableBox(aEvent))) { /* For resizing of shrunken tab bar and clicking closeboxes, we have to shrink sensitive area. */ sensitiveArea = -(clickable.width + clickable.padding); } else if (this.resizer) sensitiveArea = -this.resizer.boxObject.width; else sensitiveArea = 0; } if ( pos == 'left' ? (aEvent.screenX > box.screenX + sensitiveArea) : pos == 'right' ? (aEvent.screenX < box.screenX + box.width - sensitiveArea) : pos == 'bottom' ? (aEvent.screenY < box.screenY + box.height - sensitiveArea) : (aEvent.screenY > box.screenY + sensitiveArea) ) { return this.MOUSE_POSITION_OUTSIDE; } if ( pos == 'left' ? (aEvent.screenX <= box.screenX - sensitiveArea) : pos == 'right' ? (aEvent.screenX >= box.screenX + box.width + sensitiveArea) : pos == 'bottom' ? (aEvent.screenY >= box.screenY + box.height + sensitiveArea) : (aEvent.screenY <= box.screenY - sensitiveArea) ) { return this.MOUSE_POSITION_INSIDE; } return this.MOUSE_POSITION_NEAR; }, getContentsAreaBox : function AHB_getContentsAreaBox() { var sv = this.treeStyleTab; var b = this.browser; var box = b.mCurrentBrowser.boxObject; var xoffset = (this.shrunken || this.hidden) ? 0 : this.XOffset ; box = { screenX : box.screenX + (sv.position == 'left' ? xoffset : 0 ), screenY : box.screenY, width : box.width - xoffset, height : box.height }; return box; }, MOUSE_POSITION_UNKNOWN : 0, MOUSE_POSITION_OUTSIDE : (1 << 0), MOUSE_POSITION_INSIDE : (1 << 1), MOUSE_POSITION_NEAR : (1 << 2), MOUSE_POSITION_SENSITIVE : (1 << 1) | (1 << 2), getNearestClickableBox : function AHB_getNearestClickableBox(aEvent) { var sv = this.treeStyleTab; var tab = sv.getTabFromCoordinate(aEvent[sv.screenPositionProp]); if (!tab) return null; var position = sv.invertedScreenPositionProp; var size = sv.invertedSizeProp; var coordinate = aEvent[sv.invertedScreenPositionProp]; var tabbox = tab.boxObject; var closebox; if (this.closeButtonsMode != this.CLOSE_BUTTONS_DISABLED && this.closeButtonsMode != this.CLOSE_BUTTONS_ON_TABBAR && (closebox = sv.getTabClosebox(tab)) && (closebox = closebox.boxObject) && closebox.width && closebox.height) { let padding = Math.min( closebox[position] - tabbox[position], (tabbox[position] + tabbox[size]) - (closebox[position] + closebox[size]) ); if (closebox[position] - padding <= coordinate && closebox[position] + closebox[size] + padding >= coordinate) return this.cloneBoxObject(closebox, { padding : padding }); } var twisty; if (sv.canCollapseSubtree(tab) && (twisty = sv.getTabTwisty(tab)) && (twisty = twisty.boxObject) && twisty.width && twisty.height) { let padding = Math.min( twisty[position] - tabbox[position], (tabbox[position] + tabbox[size]) - (twisty[position] + twisty[size]) ); if (twisty[position] - padding <= coordinate && twisty[position] + twisty[size] + padding >= coordinate) return this.cloneBoxObject(twisty, { padding : padding }); } return null; }, cloneBoxObject : function AHB_cloneBoxObject(aBoxObject, aOverride) { var box = {}; for (let i in aBoxObject) { if (typeof aBoxObject[i] != 'function') box[i] = aBoxObject[i]; } Object.keys(aOverride).forEach(function(aKey) { box[aKey] = aOverride[aKey]; }); return box; }, cancelShowHideOnMouseMove : function AHB_cancelShowHideOnMouseMove() { if (this.showHideOnMouseMoveTimer) { this.window.clearTimeout(this.showHideOnMouseMoveTimer); this.showHideOnMouseMoveTimer = null; } }, // feedback showForFeedback : function AHB_showForFeedback() { if (!this.enabled || !this.treeStyleTab.getTreePref('tabbar.autoShow.feedback')) return; var w = this.window; if (this.delayedShowForFeedbackTimer) { w.clearTimeout(this.delayedShowForFeedbackTimer); this.delayedShowForFeedbackTimer = null; } this.cancelHideForFeedback(); this.delayedShowForFeedbackTimer = w.setTimeout( function(aSelf) { aSelf.delayedShowForFeedbackTimer = null; aSelf.delayedShowForFeedback(); }, 100, this ); }, delayedShowForFeedback : function AHB_delayedShowForFeedback() { this.show(this.kSHOWN_BY_FEEDBACK); this.cancelHideForFeedback(); this.delayedHideTabbarForFeedbackTimer = this.window.setTimeout( function(aSelf) { aSelf.delayedHideTabbarForFeedbackTimer = null; if (aSelf.showHideReason == aSelf.kSHOWN_BY_FEEDBACK) aSelf.hide(); }, this.treeStyleTab.getTreePref('tabbar.autoShow.feedback.delay'), this ); }, cancelHideForFeedback : function AHB_cancelHideForFeedback() { if (this.delayedHideTabbarForFeedbackTimer) { this.window.clearTimeout(this.delayedHideTabbarForFeedbackTimer); this.delayedHideTabbarForFeedbackTimer = null; } }, setWidth : function AHB_setWidth(aWidth, aForceExpanded) { if (aForceExpanded || this.expanded || this.mode != this.kMODE_SHRINK) this.treeStyleTab.setTreePref('tabbar.width', this.treeStyleTab.maxTabbarWidth(aWidth)); else this.treeStyleTab.setTreePref('tabbar.shrunkenWidth', this.treeStyleTab.maxTabbarWidth(aWidth)); }, updateMenuItem : function AHB_updateMenuItem(aNode) { if (!aNode) return; if (this.mode != this.kMODE_DISABLED) aNode.setAttribute('checked', true); else aNode.removeAttribute('checked'); }, // show/hide tabbar get width() { if (this.expanded) { this._width = this.treeStyleTab.tabStrip.boxObject.width || this._width; } return this._width; }, set width(aNewWidth) { this._width = aNewWidth; return this._width; }, _width : 0, get widthFromMode() { return (this.shrunken) ? this.treeStyleTab.getTreePref('tabbar.shrunkenWidth') : this.treeStyleTab.getTreePref('tabbar.width') ; }, get placeHolderWidthFromMode() { return (this.mode == this.kMODE_SHRINK) ? this.treeStyleTab.getTreePref('tabbar.shrunkenWidth') : this.treeStyleTab.getTreePref('tabbar.width') ; }, get height() { if (this.expanded) { this._height = this.treeStyleTab.tabStrip.boxObject.height; } return this._height; }, set height(aNewHeight) { this._height = aNewHeight; return this._height; }, _height : 0, get splitterWidth() { if (this.expanded) { var splitter = this.document.getAnonymousElementByAttribute(this.browser, 'class', this.treeStyleTab.kSPLITTER); this._splitterWidth = (splitter ? splitter.boxObject.width : 0 ); } return this._splitterWidth; }, set splitterWidth(aNewWidth) { this._splitterWidth = aNewWidth; return this._splitterWidth; }, _splitterWidth : 0, showHideInternal : function AHB_showHideInternal(aReason) { var sv = this.treeStyleTab; var b = this.browser; var pos = sv.position; if (this.expanded) { // to be hidden or shrunken this.onHiding(); this.showHideReason = aReason || this.kSHOWN_BY_UNKNOWN; } else { // to be shown or expanded this.onShowing(); this.showHideReason = aReason || this.kSHOWN_BY_UNKNOWN; } this.fireStateChangingEvent(); if (this.expanded) sv.setTabbrowserAttribute(this.kAUTOHIDE, 'show'); b.mTabContainer.adjustTabstrip(); sv.checkTabsIndentOverflow(); this.window.setTimeout(function(aSelf) { aSelf.fireStateChangeEvent(); aSelf.showHideContentsAreaScreen(); }, 0, this); }, showHideContentsAreaScreen : function AHB_showHideContentsAreaScreen() { if ( this.expanded && this.contentAreaScreenEnabled && this.treeStyleTab.FocusManager.activeWindow && this.treeStyleTab.FocusManager.activeWindow.top == this.window && this.findPluginArea(this.browser.contentWindow) ) { let box = this.getContentsAreaBox(); let style = this.screen.style; let width = Math.min(box.width, this.window.screen.availWidth - box.screenX); let height = Math.min(box.height, this.window.screen.availHeight - box.screenY); style.width = width+'px'; style.height = height+'px'; if (this.screen.state == 'open') this.screen.moveTo(box.screenX, box.screenY); else this.screen.openPopupAtScreen(box.screenX, box.screenY, false); this.screen.setAttribute('popup-shown', true); } else { this.screen.removeAttribute('popup-shown'); if (this.screen.state != 'close') this.screen.hidePopup(); } }, findPluginArea : function AHB_findPluginArea(aFrame) { return aFrame.document.querySelector('embed, object') || Array.some(aFrame.frames, arguments.callee); }, show : function AHB_show(aReason) /* PUBLIC API */ { if (!this.expanded) this.showHideInternal(aReason); }, hide : function AHB_hide(aReason) /* PUBLIC API */ { if (this.expanded) this.showHideInternal(aReason); }, onShowing : function AHB_onShowing() { var sv = this.treeStyleTab; var b = this.browser; var pos = sv.position; sv.setTabbrowserAttribute(this.kSTATE, this.kSTATE_EXPANDED); switch (this.mode) { case this.kMODE_DISABLED: break; case this.kMODE_HIDE: sv.updateFloatingTabbar(sv.kTABBAR_UPDATE_BY_AUTOHIDE); break; default: case this.kMODE_SHRINK: if (pos == 'left' || pos == 'right') { let width = sv.maxTabbarWidth(sv.getTreePref('tabbar.width')); sv.updateFloatingTabbar(sv.kTABBAR_UPDATE_BY_AUTOHIDE); } break; } }, onHiding : function AHB_onHiding() { var sv = this.treeStyleTab; var b = this.browser; var pos = sv.position; var box = (sv.tabStripPlaceHolder || sv.tabStrip).boxObject; this.tabbarHeight = box.height; this.width = box.width || this.width; var splitter = this.document.getAnonymousElementByAttribute(b, 'class', sv.kSPLITTER); this.splitterWidth = (splitter ? splitter.boxObject.width : 0 ); switch (this.mode) { case this.kMODE_DISABLED: sv.setTabbrowserAttribute(this.kAUTOHIDE, 'hidden'); sv.setTabbrowserAttribute(this.kSTATE, this.kSTATE_HIDDEN); break; case this.kMODE_HIDE: sv.setTabbrowserAttribute(this.kAUTOHIDE, 'hidden'); sv.setTabbrowserAttribute(this.kSTATE, this.kSTATE_HIDDEN); sv.updateFloatingTabbar(sv.kTABBAR_UPDATE_BY_AUTOHIDE); break; default: case this.kMODE_SHRINK: sv.setTabbrowserAttribute(this.kAUTOHIDE, 'show'); sv.setTabbrowserAttribute(this.kSTATE, this.kSTATE_SHRUNKEN); if (pos == 'left' || pos == 'right') sv.setTabStripAttribute('width', sv.getTreePref('tabbar.shrunkenWidth')); sv.updateFloatingTabbar(sv.kTABBAR_UPDATE_BY_AUTOHIDE); break; } }, fireStateChangingEvent : function AHB_fireStateChangingEvent() { var data = { shown : this.expanded, state : this.state }; /* PUBLIC API */ this.treeStyleTab.fireDataContainerEvent(this.treeStyleTab.kEVENT_TYPE_AUTO_HIDE_STATE_CHANGING, this.browser, true, false, data); // for backward compatibility this.treeStyleTab.fireDataContainerEvent(this.treeStyleTab.kEVENT_TYPE_AUTO_HIDE_STATE_CHANGING.replace(/^nsDOM/, ''), this.browser, true, false, data); }, fireStateChangeEvent : function AHB_fireStateChangeEvent() { var data = { shown : this.expanded, state : this.state, xOffset : this.XOffset, yOffset : this.YOffset }; /* PUBLIC API */ this.treeStyleTab.fireDataContainerEvent(this.treeStyleTab.kEVENT_TYPE_AUTO_HIDE_STATE_CHANGE, this.browser, true, false, data); // for backward compatibility this.treeStyleTab.fireDataContainerEvent(this.treeStyleTab.kEVENT_TYPE_AUTO_HIDE_STATE_CHANGE.replace(/^nsDOM/, ''), this.browser, true, false, data); }, updateTransparency : function AHB_updateTransparency() { var sv = this.treeStyleTab; sv.updateFloatingTabbar(sv.kTABBAR_UPDATE_BY_APPEARANCE_CHANGE); }, // event handling observe : function AHB_observe(aSubject, aTopic, aData) { switch (aTopic) { case 'nsPref:changed': this.onPrefChange(aData); break; default: break; } }, domains : [ 'extensions.treestyletab.', 'browser.fullscreen.autohide', 'browser.tabs.closeButtons' ], onPrefChange : function AHB_onPrefChange(aPrefName) { // ignore after destruction if (!this.window || !this.window.TreeStyleTabService) return; var value = this.treeStyleTab.getPref(aPrefName); switch (aPrefName) { case 'extensions.treestyletab.tabbar.autoHide.mode': if (!this.window.TreeStyleTabService.shouldApplyNewPref) return; this.browser.setAttribute(this.kMODE+'-normal', value); this.updateMode(); return; case 'extensions.treestyletab.tabbar.autoHide.mode.fullscreen': if (!this.window.TreeStyleTabService.shouldApplyNewPref) return; this.browser.setAttribute(this.kMODE+'-fullscreen', value); this.updateMode(); return; case 'extensions.treestyletab.tabbar.autoShow.mousemove': case 'extensions.treestyletab.tabbar.autoShow.accelKeyDown': case 'extensions.treestyletab.tabbar.autoShow.feedback': if (this.enabled && this.shouldListenMouseMove) this.startListenMouseMove(); else this.endListenMouseMove(); return; case 'extensions.treestyletab.tabbar.autoHide.area': this.sensitiveArea = value; return; case 'extensions.treestyletab.tabbar.togglerSize': this.togglerSize = value; var toggler = this.document.getAnonymousElementByAttribute(this.browser, 'class', this.treeStyleTab.kTABBAR_TOGGLER); toggler.style.minWidth = toggler.style.minHeight = value+'px'; if (this.togglerSize <= 0) toggler.setAttribute('collapsed', true); else toggler.removeAttribute('collapsed'); return; case 'extensions.treestyletab.tabbar.autoHide.contentAreaScreen.enabled': return this.contentAreaScreenEnabled = value; case 'browser.fullscreen.autohide': if (!this.window.fullScreen) return; this.end(); this.mode = value ? this.getModeForFullScreen() : this.kMODE_DISABLED ; if (this.mode != this.kMODE_DISABLED) this.start(); return; case 'browser.tabs.closeButtons': return this.closeButtonsMode = value; default: return; } }, handleEvent : function AHB_handleEvent(aEvent) { switch (aEvent.type) { case 'mousedown': return this.onMouseDown(aEvent); case 'mouseup': return this.onMouseUp(aEvent); case 'mousemove': return this.handleMouseMove(aEvent); case 'TabOpen': case 'TabClose': return this.showForFeedback(); case 'TabMove': if (!this.treeStyleTab.subTreeMovingCount && !this.treeStyleTab.internallyTabMovingCount) this.showForFeedback(); return; case 'select': if (!this.window.TreeStyleTabService.accelKeyPressed) this.showForFeedback(); return; case 'dragover': return this.onDragOver(aEvent); case 'dragleave': return this.onDragLeave(aEvent); case this.treeStyleTab.kEVENT_TYPE_TABBAR_POSITION_CHANGING: this.isResizing = false; return; case this.treeStyleTab.kEVENT_TYPE_TABBAR_POSITION_CHANGED: if (this.enabled) this.window.setTimeout(function(aSelf) { aSelf.show(); aSelf.hide(); }, 0, this); this.updateTransparency(); return; case this.treeStyleTab.kEVENT_TYPE_TAB_FOCUS_SWITCHING_KEY_DOWN: return this.onKeyDown(aEvent.getData('sourceEvent')); case this.treeStyleTab.kEVENT_TYPE_TAB_FOCUS_SWITCHING_START: this.cancelDelayedShowForShortcut(); if (this.enabled && this.treeStyleTab.getTreePref('tabbar.autoShow.tabSwitch') && ( aEvent.getData('scrollDown') || aEvent.getData('scrollUp') || ( // when you release "shift" key this.expanded && aEvent.getData('standBy') && aEvent.getData('onlyShiftKey') ) )) this.show(this.kSHOWN_BY_SHORTCUT); return; case this.treeStyleTab.kEVENT_TYPE_TAB_FOCUS_SWITCHING_END: this.cancelDelayedShowForShortcut(); if (this.enabled && this.showHideReason == this.kSHOWN_BY_SHORTCUT) this.hide(); return; case this.treeStyleTab.kEVENT_TYPE_PRINT_PREVIEW_ENTERED: this.hide(); this.endListenMouseMove(); return; case this.treeStyleTab.kEVENT_TYPE_PRINT_PREVIEW_EXITED: if (this.enabled && this.shouldListenMouseMove) this.startListenMouseMove(); return; } }, onMouseDown : function AHB_onMouseDown(aEvent) { var sv = this.treeStyleTab; var w = this.window; if ( !this.isResizing && sv.evaluateXPath( 'ancestor-or-self::*[@class="'+sv.kSPLITTER+'"]', aEvent.originalTarget || aEvent.target, Ci.nsIDOMXPathResult.BOOLEAN_TYPE ).booleanValue ) { this.isResizing = true; sv.setTabbrowserAttribute(sv.kRESIZING, true); } this.cancelShowHideOnMouseMove(); if ( this.enabled && this.expanded && ( aEvent.originalTarget.ownerDocument != this.document || !sv.getTabBrowserFromChild(aEvent.originalTarget) ) ) this.hide(); this.lastMouseDownTarget = aEvent.originalTarget.localName; }, onMouseUp : function AHB_onMouseUp(aEvent) { var sv = this.treeStyleTab; if (aEvent.originalTarget && sv.evaluateXPath( 'ancestor-or-self::*[@class="'+sv.kSPLITTER+'"]', aEvent.originalTarget, Ci.nsIDOMXPathResult.BOOLEAN_TYPE ).booleanValue) { this.isResizing = false; sv.removeTabbrowserAttribute(sv.kRESIZING); } this.cancelShowHideOnMouseMove(); this.lastMouseDownTarget = null; }, handleMouseMove : function AHB_handleMouseMove(aEvent) { var sv = this.treeStyleTab; if (this.isResizing && /^(scrollbar|thumb|slider|scrollbarbutton)$/i.test(this.lastMouseDownTarget)) return true; if ( !aEvent.shiftKey && !sv.isPopupShown() && ( !this.expanded || this.showHideReason & this.kKEEP_SHOWN_ON_MOUSEOVER ) && !this.lastMouseDownTarget ) this.showHideOnMouseMove(aEvent); return true; }, onDragOver : function AHB_onDragOver(aEvent) { if (this.expanded) return; var position = this.getMousePosition(aEvent); if (!(position & this.MOUSE_POSITION_SENSITIVE)) return; var draggedTabs = this.window['piro.sakura.ne.jp'].tabsDragUtils.getSelectedTabs(aEvent); if ( draggedTabs.length || this.treeStyleTab.tabbarDNDObserver.retrieveURLsFromDataTransfer(aEvent.dataTransfer).length ) { this.show(this.kSHOWN_BY_MOUSEMOVE); if (this._autoHideOnDragLeaveTimer) { this.window.clearTimeout(this._autoHideOnDragLeaveTimer); delete this._autoHideOnDragLeaveTimer; } } }, onDragLeave : function AHB_onDragLeave(aEvent) { if (!this.expanded) return; if (this._autoHideOnDragLeaveTimer) this.window.clearTimeout(this._autoHideOnDragLeaveTimer); var position = this.getMousePosition(aEvent); if (position & this.MOUSE_POSITION_SENSITIVE) return; this._autoHideOnDragLeaveTimer = this.window.setTimeout(function(aSelf) { delete aSelf._autoHideOnDragLeaveTimer; aSelf.hide(aSelf.kSHOWN_BY_MOUSEMOVE); }, 100, this); }, onKeyDown : function AHB_onKeyDown(aEvent) { var sv = this.treeStyleTab; var b = this.browser; var w = this.window; if (this.delayedShowForShortcutDone) this.cancelDelayedShowForShortcut(); if ( sv.getTabs(b).length > 1 && !aEvent.altKey && w.TreeStyleTabService.accelKeyPressed ) { if (this.enabled && sv.getTreePref('tabbar.autoShow.accelKeyDown') && !this.expanded && !this.delayedAutoShowTimer && !this.delayedShowForShortcutTimer) { this.delayedShowForShortcutTimer = w.setTimeout( function(aSelf) { aSelf.delayedShowForShortcutDone = true; aSelf.show(aSelf.kSHOWN_BY_SHORTCUT); sv = null; b = null; }, sv.getTreePref('tabbar.autoShow.accelKeyDown.delay'), this ); this.delayedShowForShortcutDone = false; } } else { if (this.enabled && this.showHideReason == this.kSHOWN_BY_SHORTCUT) this.hide(); } }, cancelDelayedShowForShortcut : function AHB_cancelDelayedShowForShortcut() { if (this.delayedShowForShortcutTimer) { this.window.clearTimeout(this.delayedShowForShortcutTimer); this.delayedShowForShortcutTimer = null; } }, delayedShowForShortcutTimer : null, delayedShowForShortcutDone : true, init : function AHB_init(aTabBrowser) { this.browser = aTabBrowser; this.document = aTabBrowser.ownerDocument; this.window = this.document.defaultView; this.treeStyleTab = aTabBrowser.treeStyleTab; var sv = this.treeStyleTab; var b = this.browser; this.enabled = false; this.mouseMoveListening = false; this.showHideReason = 0; this.lastMouseDownTarget = null; this.isResizing = false; this.showHideOnMouseMoveTimer = null; this.delayedShowForFeedbackTimer = null; b.setAttribute(this.kMODE+'-normal', sv.getTreePref('tabbar.autoHide.mode')); b.setAttribute(this.kMODE+'-fullscreen', sv.getTreePref('tabbar.autoHide.mode.fullscreen')); sv.addPrefListener(this); this.onPrefChange('browser.tabs.closeButtons'); this.onPrefChange('extensions.treestyletab.tabbar.autoHide.area'); this.onPrefChange('extensions.treestyletab.tabbar.togglerSize'); this.onPrefChange('extensions.treestyletab.tabbar.autoHide.contentAreaScreen.enabled'); this.window.setTimeout(function(aSelf) { aSelf.onPrefChange('extensions.treestyletab.tabbar.autoHide.mode'); }, 0, this); b.mTabContainer.addEventListener('TabOpen', this, false); b.mTabContainer.addEventListener('TabClose', this, false); b.mTabContainer.addEventListener('TabMove', this, false); b.mTabContainer.addEventListener('select', this, false); b.addEventListener(sv.kEVENT_TYPE_TABBAR_POSITION_CHANGING, this, false); b.addEventListener(sv.kEVENT_TYPE_TABBAR_POSITION_CHANGED, this, false); b.addEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_KEY_DOWN, this, false); b.addEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_START, this, false); b.addEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_END, this, false); }, destroy : function AHB_destroy() { this.end(); this.treeStyleTab.removePrefListener(this); var sv = this.treeStyleTab; var b = this.browser; b.mTabContainer.removeEventListener('TabOpen', this, false); b.mTabContainer.removeEventListener('TabClose', this, false); b.mTabContainer.removeEventListener('TabMove', this, false); b.mTabContainer.removeEventListener('select', this, false); b.removeEventListener(sv.kEVENT_TYPE_TABBAR_POSITION_CHANGING, this, false); b.removeEventListener(sv.kEVENT_TYPE_TABBAR_POSITION_CHANGED, this, false); b.removeEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_KEY_DOWN, this, false); b.removeEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_START, this, false); b.removeEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_END, this, false); delete this.treeStyleTab; delete this.browser; delete this.document; delete this.window; }, saveCurrentState : function AHB_saveCurrentState() { var b = this.browser; var prefs = { 'tabbar.autoHide.mode' : this.getModeForNormal(b), 'tabbar.autoHide.mode.fullscreen' : this.getModeForFullScreen(b), }; for (var i in prefs) { if (this.treeStyleTab.getTreePref(i) != prefs[i]) this.treeStyleTab.setTreePref(i, prefs[i]); } } }; function AutoHideWindow(aWindow) { this.init(aWindow); } AutoHideWindow.prototype = { get browser() { return this.treeStyleTab.browser; }, // mode getMode : function AHW_getMode(aTabBrowser) { var b = aTabBrowser || this.browser; var mode = b.getAttribute(AutoHideBrowser.prototype.kMODE); return mode ? parseInt(mode) : AutoHideBrowser.prototype.kMODE_DISABLED ; }, get mode() /* PUBLIC API */ { var mode = this.getMode(); if (mode == AutoHideBrowser.prototype.kMODE_SHRINK && this.treeStyleTab.position != 'left' && this.treeStyleTab.position != 'right') return AutoHideBrowser.prototype.kMODE_HIDE; return mode; }, set mode(aValue) { var b = aTabBrowser || this.browser; b.setAttribute(AutoHideBrowser.prototype.kMODE, aValue); return aValue; }, toggleMode : function AHW_toggleMode(aTabBrowser) /* PUBLIC API */ { var b = aTabBrowser || this.browser; var w = this.window; var key = 'tabbar.autoHide.mode'; var toggleKey = 'tabbar.autoHide.mode.toggle'; if (w.fullScreen) { key += '.fullscreen'; toggleKey += '.fullscreen'; } var mode = this.getMode(b) == AutoHideBrowser.prototype.kMODE_DISABLED ? this.treeStyleTab.getTreePref(toggleKey) : AutoHideBrowser.prototype.kMODE_DISABLED ; this.treeStyleTab.setTreePref(key, mode); b.setAttribute(AutoHideBrowser.prototype.kMODE+'-'+(w.fullScreen ? 'fullscreen' : 'normal' ), mode); b.treeStyleTab.autoHide.updateMode(); }, // for shortcuts updateKeyListeners : function AHW_updateKeyListeners() { // ignore after destruction if (!this.window || !this.window.TreeStyleTabService) return; if ( this.getMode() && this.shouldListenKeyEvents ) { this.treeStyleTab.startListenKeyEventsFor(this.treeStyleTab.LISTEN_FOR_AUTOHIDE); } else { this.treeStyleTab.endListenKeyEventsFor(this.treeStyleTab.LISTEN_FOR_AUTOHIDE); } var w = this.window; w.setTimeout(function() { if (w.windowState != Ci.nsIDOMChromeWindow.STATE_NORMAL) return; var count = 0; var resizeTimer = w.setInterval(function(){ if (w.windowState != Ci.nsIDOMChromeWindow.STATE_NORMAL) return w.clearInterval(resizeTimer); if (++count > 100 || w.innerHeight > 0) { w.clearInterval(resizeTimer); w.resizeBy(-1,-1); w.resizeBy(1,1); } }, 250); }, 0); }, get shouldListenKeyEvents() { return !this.treeStyleTab.ctrlTabPreviewsEnabled && ( this.treeStyleTab.getTreePref('tabbar.autoShow.accelKeyDown') || this.treeStyleTab.getTreePref('tabbar.autoShow.tabSwitch') || this.treeStyleTab.getTreePref('tabbar.autoShow.feedback') ); }, init : function AHB_init(aWindow) { this.window = aWindow; this.document = aWindow.document; this.treeStyleTab = aWindow.TreeStyleTabService; }, destroy : function AHB_destroy() { delete this.treeStyleTab; delete this.document; delete this.window; } };