/*
	Author Amax Guan. 
	This is a base 'class' for widgets. you can choose to not use this, but you have to provide the following functions in your "widget" object in order for your widget to work
		modifyState
		getIcon
		getThumbnail
	In order to use this, you have to first import windowTools.js into your window.
*/
let Ci = Components.interfaces;
let Cu = Components.utils;
let Cc = Components.classes;

Cu["import"]('resource://livemargins/3rd/log4moz.js');
Cu["import"]("resource://livemargins/utils.jsm");
Cu["import"]("resource://livemargins/appcenter.jsm");
Cu["import"]("resource://livemargins/dao.jsm");
Cu["import"]("resource://livemargins/track.jsm");

var thumbnail_vars = {
	width : 160,
	height : 90,
	aspectRatio: 0.5625, // 16:9
};

/**
* tool function makeURI
*/

function makeURI(aURL, aOriginCharset, aBaseURI){
	var ios = Components.classes["@mozilla.org/network/io-service;1"]
						.getService(Components.interfaces.nsIIOService);
	var uri = ios.newURI(aURL, aOriginCharset, aBaseURI);
	return uri;
}
widgetbase = {
	debug : false,
	args : null,
	reloader : null,
	reloadInterval : 20000,
	minWidth : 160,
	minHeight : 80,
	trace: function(msg) {
		var logger = Log4Moz.repository.getLogger('LM4.WidgetBase');	
		logger.level = Log4Moz.Level['Trace'];
		logger.trace(msg);
	},
	
	LOG : function(msg) {
		if (this.debug){
			try{
				var consoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
				consoleService.logStringMessage("livemargins: " + msg);
			} catch(e){}
		}
	},
	reportError : function(error){
		try {
			if(this.debug){
				Components.utils.reportError(error);
			}
		} catch (e){
			Components.utils.reportError(e);
		}
	},
	
	init : function() {
		this.trace("widget-base init");
		var args = window.arguments[0];
		this.args = window.arguments[0];
		document.title = args.name;
		document.getElementById("chromeTitle").value = args.name;
		document.getElementById("chromeTitle").parentNode.setAttribute("tooltiptext", args.name);
		
		if (document.getElementById("app-icon")) {
		  document.getElementById("app-icon").setAttribute("src", this.args.smallIcon);
        }		
		
		this.args.startWithFirefox = 1;
		
		//the first time a widget is created, it should not be docked
		if (args.widgetArgs == null){
			args.widgetArgs = {
				docked: false
			};
		}
		
		if (args.widgetArgs.docked == null){
			args.widgetArgs.docked = false;
		}
	
		var self = this;
		if (this.args.windowStates) {
			//found out only delayed call will function... don't know why
			window.setTimeout(function() {
				windowTools.windowStates = args.windowStates;
			}, 1000);
		} else {
			this.args.windowStates = windowTools.windowStates;
		}
		
        // if you want to change following behavior, just overwrite the functions  below in your own widget
        // for example, if you don't want to set round rgn, you can overwrite the setRoundRgn by write the following code to your widget:
        // setRoundRgn : function(){/* do nothing */}
		this.setWidgetSize();
		this.setWidgetPos();
		this.setRoundRgn();
		var browser = document.getElementById('player_browser');
		if (browser != null && browser.hasAttribute('asrc')){
			this.loadBrowser();
		} else {
			this.openLinkInTab();
		}
		this.handleBasicEvents();
		
		// Init bookmark star button.
		if (this.args.bookmark == 1) {
			this.LOG("bookmarked");
			document.getElementById("bookmark-button").setAttribute("starred","true");
		}
		
		this.LOG("widget-base init done");
		this.track();
	},
	
	track: function() {
		document.addEventListener("click", function(event) {
			if (event.originalTarget.tagName == "toolbarbutton") {
				Tracker.track(Tracker.click.type, Tracker.click.actions.CLICK_APP_WIN_BTN, event.originalTarget.id);
			}
		}, false);
	},
	
	loadBrowser: function() {
		var browser = document.getElementById('player_browser');
		this.browser = browser;
		if (browser.hasAttribute('asrc')) {
			var me = this;
			window.setTimeout(function() {
				var loaded = false;
				browser.addEventListener('load', function(evt) {
					if (!loaded && me.initBrowser) {
						loaded = true;
						me.initBrowser(evt);
					}
				}, true);
				//browser.loadURI(browser.getAttribute('asrc'));
				browser.setAttribute('src', browser.getAttribute('asrc'));
				me.LOG('Begin to load async browser URI');
			}, 0);
		}
	},
	initBrowser: function(){
		this.openLinkInTab();
	},

	setWidgetPos : function(){
		this.LOG("setWidgetPos");
		var self = this;
		window.setTimeout(function(){
				self.LOG("setWIdgetPos timeout");
				self.LOG([self.args,self.args.screenX]);
				if (self.args.screenX){
					var POS_NOT_SET = 9999;
					if (self.args.screenX == POS_NOT_SET) {
						const wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
                                                                .getService(Components.interfaces.nsIWindowMediator);
                                                var mainWin = wm.getMostRecentWindow( "navigator:browser" );
						self.LOG("POS NOT SET:"+[mainWin.screen.availWidth,mainWin.screen.availHeight]);
						self.args.screenX = mainWin.screen.availWidth - window.outerWidth;
						self.args.screenY = mainWin.screen.availHeight - window.outerHeight;
					}
					window.moveTo(self.args.screenX,self.args.screenY);
					
				}
				if (dockable) {
					if (self.args.widgetArgs != null && self.args.widgetArgs.docked != null){
						if (self.args.widgetArgs.docked == true){
							dockable.docked = dockable.guessDockedOld();
							dockable.sendUIEvent("dockChanged");
						}
					} else {
						//maybe first update
						if (dockable.guessDockedOld()){
							dockable.docked = true;
							dockable.sendUIEvent("dockChanged");
						}
					}
					dockable.moveHandler();

				}
		},0);
	},
	setWidgetSize : function(){
		var self = this;
		window.setTimeout(function(){
			if (self.args.widgetArgs != null && self.args.widgetArgs.width != null){	
				var newWidth = parseInt(self.args.widgetArgs.width)+9;
				var newHeight = parseInt(self.args.widgetArgs.height)+7 + document.getElementById('chrome-title-box').boxObject.height;
				if (document.getElementById('footer-box') != null){ newHeight += document.getElementById('footer-box').boxObject.height;}
				if (navigator.appVersion.indexOf("Mac") != -1){//Mac removed the border for it is already shadowed
					newWidth -=3;
					newHeight -=3;
				}
				window.resizeTo(newWidth,newHeight);
			}
		},0);
	},
	setRoundRgn : function() {
		windowTools.setRoundRgn(15, 15);
	},
	/*
		a function to make your links open in tab, call this when init.
		if onlyBlank is set to true, only links with target="_blank" will
	*/
	openLinkInTab : function(onlyBlank){
		this.LOG("widget-base openLinkInTab");
		var contentBrowser = document.getElementById("player_browser");
		if (contentBrowser){	//assume there is such a browser , nevermind if no:)
			contentBrowser.addEventListener("click",function(event){
					var p = event.originalTarget;
					var linkTarget = null;
					var isLink = false;
					var link = "";
					while(p){
						if (p.tagName == "A" || p.tagName == "a") {
							isLink = true;
							link = p.getAttribute("href");
							widget.LOG(link);
							if (link == "#" || link.indexOf("javascript:") >= 0){
								return; // this two types of links should be open in the current window.
							} else {
								link = p.href // this is different from p.getAttribute("href"), 
							}
							linkTarget = p.getAttribute("target");
							break;
						}
						p = p.parentNode;
					}
					if (isLink && link && link.indexOf("http://")!=-1 && !(onlyBlank && (linkTarget != "_blank"))) {
						const wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
								.getService(Components.interfaces.nsIWindowMediator);
						var mainWin = wm.getMostRecentWindow( "navigator:browser" );
						if (mainWin) {
							if (windowTools != null && windowTools.windowLayer == 2){//handle for search situation
								mainWin.focus();
							}
							var gBrowser = mainWin.getBrowser();
							gBrowser.selectedTab = gBrowser.addTab(link);
						} else {
							window.open(link);
						}
						if (widget.reportClick != null && typeof widget.reportClick == "function"){
							widget.reportClick(link);
						}
						event.stopPropagation();
						event.preventDefault();
					}
				},true);
		}

// this could be dangerous, go ask someone
/*		var oldopen = contentBrowser.contentWindow.wrappedJSObject.open;
		contentBrowser.contentWindow.wrappedJSObject.open = function(){
					const wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
										.getService(Components.interfaces.nsIWindowMediator);
					var mainWin = wm.getMostRecentWindow( "navigator:browser" );
					if (mainWin) {
						mainWin.focus();
						var gBrowser = mainWin.getBrowser();
						gBrowser.selectedTab = gBrowser.addTab(arguments[0]);
						return gBrowser.selectedBrowser.contentWindow.wrappedJSObject;
					} else {
						return oldopen.apply(contentBrowser.contentWindow.wrappedJSObject,arguments);
					}
				};*/
//		this.LOG (contentBrowser.contentWindow.wrappedJSObject.open);
/**
*   Code copied from firefox browser.js and modified
*/
		var nsBrowserAccess = {
		  QueryInterface : function(aIID)
		  {
			if (aIID.equals(Ci.nsIBrowserDOMWindow) ||
				aIID.equals(Ci.nsISupports))
			  return this;
			throw Components.results.NS_NOINTERFACE;
		  },
		  openURI : function(aURI, aOpener, aWhere, aContext)
		  {
			widget.LOG("openURI called with : "+ [aURI, aOpener, aWhere, aContext]);
			var newWindow = null;
			var isExternal = (aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);

			if (isExternal && aURI && aURI.schemeIs("chrome")) {
			  return null;
			}

			var loadflags = isExternal ?
							   Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL :
							   Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
			if (aWhere == Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW){
			  aWhere = Cc["@mozilla.org/preferences-service;1"]
                               .getService(Ci.nsIPrefBranch2)
                               .QueryInterface(Ci.nsIPrefService)
							   .getIntPref("browser.link.open_newwindow");
			}
			switch (aWhere) {
			  case Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW :
				// FIXME: Bug 408379. So how come this doesn't send the
				// referrer like the other loads do?
				var url = aURI ? aURI.spec : "about:blank";
				// Pass all params to openDialog to ensure that "url" isn't passed through
				// loadOneOrMoreURIs, which splits based on "|"
				newWindow = openDialog(getBrowserURL(), "_blank", "all,dialog=no", url, null, null, null);
				break;
			  case Ci.nsIBrowserDOMWindow.OPEN_NEWTAB :
				widget.LOG("OPEN_NEWTAB, that's right!");
				let win, needToFocusWin;

				// try the current window.  if we're in a popup, fall back on the most recent browser window
				win = Cc["@mozilla.org/browser/browserglue;1"]
						  .getService(Ci.nsIBrowserGlue)
						  .getMostRecentBrowserWindow();

				if (!win) {
				  // we couldn't find a suitable window, a new one needs to be opened.
				  widget.LOG("What! No browser window found?");
				  var url = aURI ? aURI.spec : "about:blank";
				  newWindow = openDialog(getBrowserURL(), "_blank", "all,dialog=no", url, null, null, null);
				  return newWindow;
				}
				widget.LOG("OPEN_NEWTAB, got here!");
				widget.LOG(aOpener.location.href);
				widget.LOG(makeURI(aOpener.location.href));

				let referrer = aOpener ? makeURI(aOpener.location.href) : null;
				widget.LOG("it got here");
				// If this is an external load, we need to load a blank tab first,
				// because loadflags can't be passed to loadOneTab.
				let loadBlankFirst = !aURI;
				let tab = win.gBrowser.loadOneTab(loadBlankFirst ? "about:blank" : aURI.spec,
												  referrer, null, null, false, false);
				let browser = win.gBrowser.getBrowserForTab(tab);

				if (loadBlankFirst && aURI)
				  browser.loadURIWithFlags(aURI.spec, loadflags, referrer, null, null);

				newWindow = browser.contentWindow;
				widget.LOG("Can't believe it got here");

				break;
			  default : // OPEN_CURRENTWINDOW or an illegal value
				newWindow = contentBrowser.contentWindow;
				if (aURI) {
				  let referrer = aOpener ? makeURI(aOpener.location.href) : null;
				  contentBrowser.loadURIWithFlags(aURI.spec, loadflags, referrer, null, null);
				}
			}
			return newWindow;
		  },

		  isTabContentWindow : function(aWindow)
		  {
			return contentBrowser.contentWindow == aWindow;
		  }
		};
		window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = nsBrowserAccess;
		this.LOG("Oh Yeah");
		//this.LOG(contentBrowser.contentWindow.QueryInterface(Components.interfaces.nsIDOMChromeWindow).browserDOMWindow.openURI);
	},
	close : function() {
		this.args.startWithFirefox = 0;
		window.close();
	},

	switchTopMost : function() {
		this.LOG("switchTopMost");
		if (document.getElementById("ontop-button") != null){
			if(document.getElementById("ontop-button").getAttribute("ontop") != "false"){
				windowTools.windowLayer = 1;
				this.args.windowStates.onTop = 0;
			} else {
				windowTools.windowLayer = 2;
				this.LOG(windowTools.windowLayer);
				this.args.windowStates.onTop = 1;
			}
		}
	},
	
	//reload functions
	reload : function(){
		var browser = document.getElementById("player_browser");
		browser.reload();
	},
	switchAutoReload : function(event){
		var isAutoReload = event.target.getAttribute('checkState');
		if (isAutoReload != '1'){
			this.setAutoReload(true);
		} else {
			this.setAutoReload(false);
		}
	},
	setAutoReload : function(autoReload){
		var titlebarReload = document.getElementById("titlebar-reload");
		var controlbarReload = document.getElementById("controlbar-reload");
		if (autoReload){
			this.setReloadInterval(this.reloadInterval);
			titlebarReload.checkState = 1;
			titlebarReload.checked = true;
			if (controlbarReload){
				controlbarReload.checkState = 1;
				controlbarReload.checked = true;
			}
			this.args.widgetArgs.autoReload = true;
		} else {
			this.clearReloadInterval(this.reloadInterval);
			titlebarReload.checkState = 0;
			titlebarReload.checked = false;
			if (controlbarReload){
				controlbarReload.checkState = 0;
				controlbarReload.checked = false;
			}
			this.args.widgetArgs.autoReload = false;		
		}
	},
	clearReloadInterval : function(){
		if (this.reloader != null){
			clearInterval(this.reloader);
			this.reloader = null;
		}
	},
	setReloadInterval : function(timeInMs){
		this.clearReloadInterval();
		this.reloader = setInterval("widget.reload();",timeInMs);
	},
	switchExtendedControl : function(){
		var titlebar = document.getElementById("titlebar-space");
//		var control = document.getElementById("control-panel");
		var extButton = document.getElementById("ext-button");
		if (extButton == null) return;
		var extButtonBox = document.getElementById("extended-button-box");
		if (extButton.getAttribute("extended") == "true"){
			extButton.setAttribute("extended","false");
			extButtonBox.style.display = "none";
		} else {
			extButton.setAttribute("extended","true");
			extButtonBox.maxWidth = titlebar.boxObject.width - 20;
			extButtonBox.style.display = "-moz-box";
		}
//		control.openPopup(extButton,"after_start",0,0,false,true);
	},
	
	modifyState : function (){
		try {
			if (window.screenY + window.outerHeight > 0) { //if it's not minimized
				this.args.screenX = window.screenX;
				this.args.screenY = window.screenY;
			}
			
			var browser = document.getElementById("player_browser");
			if (browser != null && this.args.widgetArgs != null) {
				this.args.widgetArgs.width = browser.boxObject.width;
				this.args.widgetArgs.height = browser.boxObject.height;
			}
			
			this.args.windowStates = windowTools.windowStates;
			AppCenter.updateAppStateWithArg({
				uid:   this.args.id,
				screen_x: this.args.screenX,
				screen_y: this.args.screenY,
				app_status: this.args.windowStates,
				app_args: {
					width: browser.boxObject.width,
					height: browser.boxObject.height,
					docked: dockable.docked,
					history: this.args.widgetArgs.history
				}
			});
		} catch (e){
			this.trace(e.toString());
		}
	},
	
	getThumbnail : function(){
//needs improvement! If refresh too much, will cause performance issue
		try {
			var browser = document.getElementById("player_browser");
			if (browser != null){
				var thumbnail = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
				thumbnail.mozOpaque = true;
				thumbnail.height = thumbnail_vars.height;
				thumbnail.width = thumbnail_vars.width;

				var ctx = thumbnail.getContext("2d");
				var win = browser.contentWindow;
				var snippetWidth = win.innerWidth;
				var scale = thumbnail_vars.width / snippetWidth;
				ctx.scale(scale, scale);
				ctx.drawWindow(win, win.scrollX, win.scrollY,
						   snippetWidth, snippetWidth * thumbnail_vars.aspectRatio, "rgb(255,255,255)");
				this.args.thumbnail = thumbnail.toDataURL("image/png", "");
				return this.args.thumbnail;
			}
		}  catch (e) {
			this.LOG(e.toString());
		}
	},
	getIcon : function(){
		try {
			var faviconService = Components.classes["@mozilla.org/browser/favicon-service;1"]
								   .getService(Components.interfaces.nsIFaviconService);
			var ios = Components.classes["@mozilla.org/network/io-service;1"]
						.getService(Components.interfaces.nsIIOService);
			var uri = ios.newURI(this.args.widgetArgs.location, null, null);
			var iconUri = faviconService.getFaviconImageForPage(uri);
			this.args.iconUrl = iconUri.spec;
			return iconUri.spec;
		} catch (e) {
			this.LOG(e.toString());
		}
	},
	
	toggleBookmark : function(){
		var bookmarkButton = document.getElementById("bookmark-button");
		var isBookmark = bookmarkButton.getAttribute('starred');
		
		if(isBookmark == null || isBookmark == "false" || isBookmark == ""){		
			this.args.bookmark = 1;
			AppCenter.bookmarkApp(this.args.id, true);
			bookmarkButton.setAttribute("starred", "true");
			if (document.getElementById("bookmark-button-panel")){
				document.getElementById("bookmark-button-panel").setAttribute("starred", "true");
			}
		} else {
			this.args.bookmark = 0;
			AppCenter.bookmarkApp(this.args.id, false);
			bookmarkButton.setAttribute("starred", "false");
			if (document.getElementById("bookmark-button-panel")){
				document.getElementById("bookmark-button-panel").setAttribute("starred", "false");
			}
		}
		this.LOG("toggleBookmark done!");
	},
	
	handleEvent: function(event) {
		switch(event.type) {
			case "windowLayerChanged":
				this.LOG("ontop-button button change");
				if(windowTools.windowLayer == 2){	
					document.getElementById("ontop-button").setAttribute('ontop',"true");
					var tooltip_clear = document.getElementById("ontop-button").getAttribute('tooltip_clear');
					document.getElementById("ontop-button").setAttribute('tooltiptext',tooltip_clear);
				} else if (windowTools.windowLayer == 1){
					document.getElementById("ontop-button").setAttribute('ontop',"false");
					var tooltip_set = document.getElementById("ontop-button").getAttribute('tooltip_set');
					document.getElementById("ontop-button").setAttribute('tooltiptext',tooltip_set);

				}
				break;
				
			case "transparentChanged":
				this.LOG("transparent button change");
				if(windowTools.transparent == true){	
					document.getElementById("transparent").checkState = 1;
					document.getElementById("transparent").checked = true;
					document.getElementById("opaque-panel").openPopup(document.getElementById("transparent"),"overlap",4,5);
				} else {
					document.getElementById("transparent").checkState = 0;
					document.getElementById("transparent").checked = false;
					document.getElementById("opaque-panel").hidePopup();
				}
				break;
			
			case "unload":
				if (event.originalTarget == document) {
					AppCenter.appPref.removeObserver(widget.appObserver);
					this.modifyState();
				}
				break;
			// window active handling
			case "blur":
				document.getElementById("widget-box").setAttribute("activate","false");
				break;
			case "focus":
				document.getElementById("widget-box").setAttribute("activate","true");
				// "setTopMost" will not work if window is minimized
				// so set windowLayer again when window is focused.
				windowTools.windowLayer = windowTools.windowLayer;
				break;
			case "resize":
				if (window.innerWidth <= widget.minWidth || window.innerHeight <= widget.minHeight){
					var width = window.innerWidth < widget.minWidth? widget.minWidth : window.innerWidth;
					var height = window.innerHeight < widget.minHeight? widget.minHeight : window.innerHeight;
					window.resizeTo(width,height);
				}
				var extButtonBox = document.getElementById("extended-button-box");
				if (extButtonBox == null) return;
				var titlebar = document.getElementById("titlebar-space");
				if (extButtonBox.style.display == "-moz-box"){
					extButtonBox.maxWidth = titlebar.boxObject.width + extButtonBox.boxObject.width - 20;
				}
				break;
			case "dockChanged":
				var titlebar = document.getElementById("titlebar-space");
				if (titlebar!= null && dockable!= null){
					if (dockable.docked){
						titlebar.setAttribute("docked","true");
						titlebar.setAttribute("dockDirection",dockable.dockDirection);
						if (widget.args){
							if (widget.args.widgetArgs == null){
								widget.args.widgetArgs = {};
							}
							widget.args.widgetArgs.docked = true;
							
						}
					} else {
						titlebar.setAttribute("docked","false");
						if (widget.args){
							if (widget.args.widgetArgs == null){
								widget.args.widgetArgs = {};
							}
							widget.args.widgetArgs.docked = false;
						}
					}
				}
		}
	},
//these two functions are not used anymore, but in case anything changed... who knows
/* 	hideTitlebar : function(ev){
		if (this.showhideTimeoutID) window.clearTimeout(this.showhideTimeoutID);
		this.showhideTimeoutID = window.setTimeout(function(){
						var titlebar = document.getElementById("chrome-title-box");
						if (titlebar.style.display == "none") return;
						var panel = document.getElementById("modify-panel");
						panel.hidePopup();
						window.resizeBy(0,-titlebar.boxObject.height);
						window.moveBy(0,titlebar.boxObject.height);
						titlebar.style.display="none";
					},1000);
	},
	showTitlebar : function(ev){
		if (this.showhideTimeoutID) window.clearTimeout(this.showhideTimeoutID);
		this.showhideTimeoutID = window.setTimeout(function(){
						var titlebar = document.getElementById("chrome-title-box");
						if (titlebar.style.display != "none") return;
						titlebar.style.display="-moz-box";
						window.resizeBy(0,titlebar.boxObject.height);
						window.moveBy(0,-titlebar.boxObject.height);
					},100);
	}, */
	
	appObserver: {
		onBookmark: function(uid) {
			if (widget.args.id == uid) {
				if (widget.args.bookmark != AppCenterDAO.getAppBookmarkFlag(uid)) {
					widget.toggleBookmark();
				}
			}
		},
		
		onUnbookmark: function(uid) {
			if (widget.args.id == uid) {
				if (widget.args.bookmark != AppCenterDAO.getAppBookmarkFlag(uid)) {
					widget.toggleBookmark();
				}
			}
		},
		
		onChangeName: function(uid) {
			widget.args.name = AppCenterDAO.getAppName(uid);
			document.title = widget.args.name;
			document.getElementById("chromeTitle").value = widget.args.name;
		}
	},
	
	handleBasicEvents : function() {
		AppCenter.appPref.addObserver(this.appObserver);
		window.addEventListener("windowLayerChanged",this,false);
		window.addEventListener("transparentChanged",this,false);
		window.addEventListener("dockChanged",this,false);
		window.addEventListener("unload",this,true);
		window.addEventListener("blur", this, true);
		window.addEventListener("focus", this, true);
		window.addEventListener("resize", this, true); //title scrollbox handling
		var titlebar = document.getElementById("titlebar-space");
		if (titlebar != null && dockable != null){
			titlebar.addEventListener("mousedown",function(event){if (event.button == 0){this.onDrag = true; window.titlebarMovingTimeout = window.setTimeout(function(){titlebar.setAttribute("moving","true");},200)}},false);
			titlebar.addEventListener("mouseup",function(event){if (event.button == 0){this.onDrag = false; window.clearTimeout(window.titlebarMovingTimeout);}},false);
			titlebar.addEventListener("mousemove",function(event){if (this.onDrag == true){ dockable.mouseMoveHandler(event);}},false);
			titlebar.addEventListener("command",function(event){if (titlebar.getAttribute("moving") == "true"){titlebar.setAttribute("moving","false"); dockable.moveHandler(event);}},false);
		}
	},
};
