summaryrefslogtreecommitdiffstats
path: root/toolkit/components/prompts/content
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/prompts/content')
-rw-r--r--toolkit/components/prompts/content/commonDialog.css22
-rw-r--r--toolkit/components/prompts/content/commonDialog.js62
-rw-r--r--toolkit/components/prompts/content/commonDialog.xul97
-rw-r--r--toolkit/components/prompts/content/selectDialog.js67
-rw-r--r--toolkit/components/prompts/content/selectDialog.xul22
-rw-r--r--toolkit/components/prompts/content/tabprompts.css35
-rw-r--r--toolkit/components/prompts/content/tabprompts.xml352
7 files changed, 657 insertions, 0 deletions
diff --git a/toolkit/components/prompts/content/commonDialog.css b/toolkit/components/prompts/content/commonDialog.css
new file mode 100644
index 000000000..89f88db7a
--- /dev/null
+++ b/toolkit/components/prompts/content/commonDialog.css
@@ -0,0 +1,22 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
+
+#infoContainer {
+ max-width: 45em;
+}
+
+#info\.body {
+ -moz-user-focus: normal;
+ -moz-user-select: text;
+ cursor: text !important;
+ white-space: pre-wrap;
+ unicode-bidi: plaintext;
+}
+
+#loginLabel, #password1Label {
+ text-align: right;
+}
+
diff --git a/toolkit/components/prompts/content/commonDialog.js b/toolkit/components/prompts/content/commonDialog.js
new file mode 100644
index 000000000..ef4686654
--- /dev/null
+++ b/toolkit/components/prompts/content/commonDialog.js
@@ -0,0 +1,62 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var Ci = Components.interfaces;
+var Cr = Components.results;
+var Cc = Components.classes;
+var Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/CommonDialog.jsm");
+
+var propBag, args, Dialog;
+
+function commonDialogOnLoad() {
+ propBag = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2)
+ .QueryInterface(Ci.nsIWritablePropertyBag);
+ // Convert to a JS object
+ args = {};
+ let propEnum = propBag.enumerator;
+ while (propEnum.hasMoreElements()) {
+ let prop = propEnum.getNext().QueryInterface(Ci.nsIProperty);
+ args[prop.name] = prop.value;
+ }
+
+ let dialog = document.documentElement;
+
+ let ui = {
+ prompt : window,
+ loginContainer : document.getElementById("loginContainer"),
+ loginTextbox : document.getElementById("loginTextbox"),
+ loginLabel : document.getElementById("loginLabel"),
+ password1Container : document.getElementById("password1Container"),
+ password1Textbox : document.getElementById("password1Textbox"),
+ password1Label : document.getElementById("password1Label"),
+ infoBody : document.getElementById("info.body"),
+ infoTitle : document.getElementById("info.title"),
+ infoIcon : document.getElementById("info.icon"),
+ checkbox : document.getElementById("checkbox"),
+ checkboxContainer : document.getElementById("checkboxContainer"),
+ button3 : dialog.getButton("extra2"),
+ button2 : dialog.getButton("extra1"),
+ button1 : dialog.getButton("cancel"),
+ button0 : dialog.getButton("accept"),
+ focusTarget : window,
+ };
+
+ // limit the dialog to the screen width
+ document.getElementById("filler").maxWidth = screen.availWidth;
+
+ Dialog = new CommonDialog(args, ui);
+ Dialog.onLoad(dialog);
+ // resize the window to the content
+ window.sizeToContent();
+ window.getAttention();
+}
+
+function commonDialogOnUnload() {
+ // Convert args back into property bag
+ for (let propName in args)
+ propBag.setProperty(propName, args[propName]);
+}
diff --git a/toolkit/components/prompts/content/commonDialog.xul b/toolkit/components/prompts/content/commonDialog.xul
new file mode 100644
index 000000000..990b26586
--- /dev/null
+++ b/toolkit/components/prompts/content/commonDialog.xul
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://global/content/commonDialog.css" type="text/css"?>
+<?xml-stylesheet href="chrome://global/skin/commonDialog.css" type="text/css"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://global/locale/commonDialog.dtd">
+
+<dialog id="commonDialog"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ aria-describedby="info.body"
+ onunload="commonDialogOnUnload();"
+ ondialogaccept="Dialog.onButton0(); return true;"
+ ondialogcancel="Dialog.onButton1(); return true;"
+ ondialogextra1="Dialog.onButton2(); window.close();"
+ ondialogextra2="Dialog.onButton3(); window.close();"
+ buttonpack="center">
+
+ <script type="application/javascript" src="chrome://global/content/commonDialog.js"/>
+ <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
+ <script type="application/javascript">
+ document.addEventListener("DOMContentLoaded", function() {
+ commonDialogOnLoad();
+ });
+ </script>
+
+ <commandset id="selectEditMenuItems">
+ <command id="cmd_copy" oncommand="goDoCommand('cmd_copy')" disabled="true"/>
+ <command id="cmd_selectAll" oncommand="goDoCommand('cmd_selectAll')"/>
+ </commandset>
+
+ <popupset id="contentAreaContextSet">
+ <menupopup id="contentAreaContextMenu"
+ onpopupshowing="goUpdateCommand('cmd_copy')">
+ <menuitem id="context-copy"
+ label="&copyCmd.label;"
+ accesskey="&copyCmd.accesskey;"
+ command="cmd_copy"
+ disabled="true"/>
+ <menuitem id="context-selectall"
+ label="&selectAllCmd.label;"
+ accesskey="&selectAllCmd.accesskey;"
+ command="cmd_selectAll"/>
+ </menupopup>
+ </popupset>
+
+ <hbox id="filler" style="min-width: 0%;">
+ <spacer style="width: 29em;"/>
+ </hbox>
+
+ <grid>
+ <columns>
+ <column/>
+ <column flex="1"/>
+ </columns>
+
+ <rows>
+ <row>
+ <hbox id="iconContainer" align="start">
+ <image id="info.icon" class="spaced"/>
+ </hbox>
+ <vbox id="infoContainer"
+#ifndef XP_MACOSX
+ pack="center"
+#endif
+ >
+ <!-- Only shown on OS X, since it has no dialog title -->
+ <description id="info.title"
+#ifndef XP_MACOSX
+ hidden="true"
+#else
+ style="margin-bottom: 1em"
+#endif
+ />
+ <description id="info.body" context="contentAreaContextMenu" noinitialfocus="true"/>
+ </vbox>
+ </row>
+ <row id="loginContainer" hidden="true" align="center">
+ <label id="loginLabel" value="&editfield0.label;" control="loginTextbox"/>
+ <textbox id="loginTextbox"/>
+ </row>
+ <row id ="password1Container" hidden="true" align="center">
+ <label id="password1Label" value="&editfield1.label;" control="password1Textbox"/>
+ <textbox type="password" id="password1Textbox"/>
+ </row>
+ <row id="checkboxContainer" hidden="true">
+ <spacer/>
+ <checkbox id="checkbox" oncommand="Dialog.onCheckbox()"/>
+ </row>
+ </rows>
+ </grid>
+
+</dialog>
diff --git a/toolkit/components/prompts/content/selectDialog.js b/toolkit/components/prompts/content/selectDialog.js
new file mode 100644
index 000000000..7628dc8d9
--- /dev/null
+++ b/toolkit/components/prompts/content/selectDialog.js
@@ -0,0 +1,67 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var Ci = Components.interfaces;
+var Cr = Components.results;
+var Cc = Components.classes;
+var Cu = Components.utils;
+
+var gArgs, listBox;
+
+function dialogOnLoad() {
+ gArgs = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2)
+ .QueryInterface(Ci.nsIWritablePropertyBag);
+
+ let promptType = gArgs.getProperty("promptType");
+ if (promptType != "select") {
+ Cu.reportError("selectDialog opened for unknown type: " + promptType);
+ window.close();
+ }
+
+ // Default to canceled.
+ gArgs.setProperty("ok", false);
+
+ document.title = gArgs.getProperty("title");
+
+ let text = gArgs.getProperty("text");
+ document.getElementById("info.txt").setAttribute("value", text);
+
+ let items = gArgs.getProperty("list");
+ listBox = document.getElementById("list");
+
+ for (let i = 0; i < items.length; i++) {
+ let str = items[i];
+ if (str == "")
+ str = "<>";
+ listBox.appendItem(str);
+ listBox.getItemAtIndex(i).addEventListener("dblclick", dialogDoubleClick, false);
+ }
+ listBox.selectedIndex = 0;
+ listBox.focus();
+
+ // resize the window to the content
+ window.sizeToContent();
+
+ // Move to the right location
+ moveToAlertPosition();
+ centerWindowOnScreen();
+
+ // play sound
+ try {
+ Cc["@mozilla.org/sound;1"].
+ createInstance(Ci.nsISound).
+ playEventSound(Ci.nsISound.EVENT_SELECT_DIALOG_OPEN);
+ } catch (e) { }
+}
+
+function dialogOK() {
+ gArgs.setProperty("selected", listBox.selectedIndex);
+ gArgs.setProperty("ok", true);
+ return true;
+}
+
+function dialogDoubleClick() {
+ dialogOK();
+ window.close();
+}
diff --git a/toolkit/components/prompts/content/selectDialog.xul b/toolkit/components/prompts/content/selectDialog.xul
new file mode 100644
index 000000000..9b72bcfb0
--- /dev/null
+++ b/toolkit/components/prompts/content/selectDialog.xul
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
+<!DOCTYPE dialog SYSTEM "chrome://global/locale/commonDialog.dtd">
+
+<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="dialogOnLoad()"
+ ondialogaccept="return dialogOK();">
+
+ <script type="application/javascript" src="chrome://global/content/selectDialog.js" />
+ <keyset id="dialogKeys"/>
+ <vbox style="width: 24em;margin: 5px;">
+ <label id="info.txt"/>
+ <vbox>
+ <listbox id="list" rows="4" flex="1"/>
+ </vbox>
+ </vbox>
+</dialog>
diff --git a/toolkit/components/prompts/content/tabprompts.css b/toolkit/components/prompts/content/tabprompts.css
new file mode 100644
index 000000000..c4b0f7593
--- /dev/null
+++ b/toolkit/components/prompts/content/tabprompts.css
@@ -0,0 +1,35 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Tab Modal Prompt boxes */
+tabmodalprompt {
+ width: 100%;
+ height: 100%;
+ -moz-box-pack: center;
+ -moz-box-orient: vertical;
+}
+
+.mainContainer {
+ min-width: 20em;
+ min-height: 12em;
+ -moz-user-focus: normal;
+}
+
+.info\.title {
+ margin-bottom: 1em !important;
+ font-weight: bold;
+}
+
+.info\.body {
+ margin: 0 !important;
+ -moz-user-focus: normal;
+ -moz-user-select: text;
+ cursor: text !important;
+ white-space: pre-wrap;
+ unicode-bidi: plaintext;
+}
+
+label[value=""] {
+ visibility: collapse;
+}
diff --git a/toolkit/components/prompts/content/tabprompts.xml b/toolkit/components/prompts/content/tabprompts.xml
new file mode 100644
index 000000000..07c6c8efb
--- /dev/null
+++ b/toolkit/components/prompts/content/tabprompts.xml
@@ -0,0 +1,352 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE bindings [
+<!ENTITY % commonDialogDTD SYSTEM "chrome://global/locale/commonDialog.dtd">
+<!ENTITY % dialogOverlayDTD SYSTEM "chrome://global/locale/dialogOverlay.dtd">
+%commonDialogDTD;
+%dialogOverlayDTD;
+]>
+
+<bindings id="tabPrompts"
+ xmlns="http://www.mozilla.org/xbl"
+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:xbl="http://www.mozilla.org/xbl">
+
+ <binding id="tabmodalprompt">
+
+ <resources>
+ <stylesheet src="chrome://global/content/tabprompts.css"/>
+ <stylesheet src="chrome://global/skin/tabprompts.css"/>
+ </resources>
+
+ <xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ role="dialog"
+ aria-describedby="info.body">
+
+ <!-- This is based on the guts of commonDialog.xul -->
+ <spacer flex="1"/>
+ <hbox pack="center">
+ <vbox anonid="mainContainer" class="mainContainer">
+ <grid class="topContainer" flex="1">
+ <columns>
+ <column/>
+ <column flex="1"/>
+ </columns>
+
+ <rows>
+ <vbox anonid="infoContainer" align="center" pack="center" flex="1">
+ <description anonid="info.title" class="info.title" hidden="true" />
+ <description anonid="info.body" class="info.body"/>
+ </vbox>
+
+ <row anonid="loginContainer" hidden="true" align="center">
+ <label anonid="loginLabel" value="&editfield0.label;" control="loginTextbox"/>
+ <textbox anonid="loginTextbox"/>
+ </row>
+
+ <row anonid="password1Container" hidden="true" align="center">
+ <label anonid="password1Label" value="&editfield1.label;" control="password1Textbox"/>
+ <textbox anonid="password1Textbox" type="password"/>
+ </row>
+
+ <row anonid="checkboxContainer" hidden="true">
+ <spacer/>
+ <checkbox anonid="checkbox"/>
+ </row>
+
+ <xbl:children includes="row"/>
+ </rows>
+ </grid>
+ <xbl:children/>
+ <hbox class="buttonContainer">
+#ifdef XP_UNIX
+ <button anonid="button3" hidden="true"/>
+ <button anonid="button2" hidden="true"/>
+ <spacer anonid="buttonSpacer" flex="1"/>
+ <button anonid="button1" label="&cancelButton.label;"/>
+ <button anonid="button0" label="&okButton.label;"/>
+#else
+ <button anonid="button3" hidden="true"/>
+ <spacer anonid="buttonSpacer" flex="1"/>
+ <button anonid="button0" label="&okButton.label;"/>
+ <button anonid="button2" hidden="true"/>
+ <button anonid="button1" label="&cancelButton.label;"/>
+#endif
+ </hbox>
+ </vbox>
+ </hbox>
+ <spacer flex="2"/>
+ </xbl:content>
+
+ <implementation implements="nsIDOMEventListener">
+ <constructor>
+ <![CDATA[
+ let self = this;
+ function getElement(anonid) {
+ return document.getAnonymousElementByAttribute(self, "anonid", anonid);
+ }
+
+ this.ui = {
+ prompt : this,
+ loginContainer : getElement("loginContainer"),
+ loginTextbox : getElement("loginTextbox"),
+ loginLabel : getElement("loginLabel"),
+ password1Container : getElement("password1Container"),
+ password1Textbox : getElement("password1Textbox"),
+ password1Label : getElement("password1Label"),
+ infoBody : getElement("info.body"),
+ infoTitle : getElement("info.title"),
+ infoIcon : null,
+ checkbox : getElement("checkbox"),
+ checkboxContainer : getElement("checkboxContainer"),
+ button3 : getElement("button3"),
+ button2 : getElement("button2"),
+ button1 : getElement("button1"),
+ button0 : getElement("button0"),
+ // focusTarget (for BUTTON_DELAY_ENABLE) not yet supported
+ };
+
+ this.ui.button0.addEventListener("command", this.onButtonClick.bind(this, 0), false);
+ this.ui.button1.addEventListener("command", this.onButtonClick.bind(this, 1), false);
+ this.ui.button2.addEventListener("command", this.onButtonClick.bind(this, 2), false);
+ this.ui.button3.addEventListener("command", this.onButtonClick.bind(this, 3), false);
+ // Anonymous wrapper used here because |Dialog| doesn't exist until init() is called!
+ this.ui.checkbox.addEventListener("command", function() { self.Dialog.onCheckbox(); }, false);
+ this.isLive = false;
+ ]]>
+ </constructor>
+ <destructor>
+ <![CDATA[
+ if (this.isLive) {
+ this.abortPrompt();
+ }
+ ]]>
+ </destructor>
+
+ <field name="ui"/>
+ <field name="args"/>
+ <field name="linkedTab"/>
+ <field name="onCloseCallback"/>
+ <field name="Dialog"/>
+ <field name="isLive"/>
+ <field name="availWidth"/>
+ <field name="availHeight"/>
+ <field name="minWidth"/>
+ <field name="minHeight"/>
+
+ <method name="init">
+ <parameter name="args"/>
+ <parameter name="linkedTab"/>
+ <parameter name="onCloseCallback"/>
+ <body>
+ <![CDATA[
+ this.args = args;
+ this.linkedTab = linkedTab;
+ this.onCloseCallback = onCloseCallback;
+
+ if (args.enableDelay)
+ throw "BUTTON_DELAY_ENABLE not yet supported for tab-modal prompts";
+
+ // We need to remove the prompt when the tab or browser window is closed or
+ // the page navigates, else we never unwind the event loop and that's sad times.
+ // Remember to cleanup in shutdownPrompt()!
+ this.isLive = true;
+ window.addEventListener("resize", this, false);
+ window.addEventListener("unload", this, false);
+ linkedTab.addEventListener("TabClose", this, false);
+ // Note:
+ // nsPrompter.js or in e10s mode browser-parent.js call abortPrompt,
+ // when the domWindow, for which the prompt was created, generates
+ // a "pagehide" event.
+
+ let tmp = {};
+ Components.utils.import("resource://gre/modules/CommonDialog.jsm", tmp);
+ this.Dialog = new tmp.CommonDialog(args, this.ui);
+ this.Dialog.onLoad(null);
+
+ // Display the tabprompt title that shows the prompt origin when
+ // the prompt origin is not the same as that of the top window.
+ if (!args.showAlertOrigin)
+ this.ui.infoTitle.removeAttribute("hidden");
+
+ // TODO: should unhide buttonSpacer on Windows when there are 4 buttons.
+ // Better yet, just drop support for 4-button dialogs. (bug 609510)
+
+ this.onResize();
+ ]]>
+ </body>
+ </method>
+
+ <method name="shutdownPrompt">
+ <body>
+ <![CDATA[
+ // remove our event listeners
+ try {
+ window.removeEventListener("resize", this, false);
+ window.removeEventListener("unload", this, false);
+ this.linkedTab.removeEventListener("TabClose", this, false);
+ } catch (e) { }
+ this.isLive = false;
+ // invoke callback
+ this.onCloseCallback();
+ ]]>
+ </body>
+ </method>
+
+ <method name="abortPrompt">
+ <body>
+ <![CDATA[
+ // Called from other code when the page changes.
+ this.Dialog.abortPrompt();
+ this.shutdownPrompt();
+ ]]>
+ </body>
+ </method>
+
+ <method name="handleEvent">
+ <parameter name="aEvent"/>
+ <body>
+ <![CDATA[
+ switch (aEvent.type) {
+ case "resize":
+ this.onResize();
+ break;
+ case "unload":
+ case "TabClose":
+ this.abortPrompt();
+ break;
+ }
+ ]]>
+ </body>
+ </method>
+
+ <method name="onResize">
+ <body>
+ <![CDATA[
+ let availWidth = this.clientWidth;
+ let availHeight = this.clientHeight;
+ if (availWidth == this.availWidth && availHeight == this.availHeight)
+ return;
+ this.availWidth = availWidth;
+ this.availHeight = availHeight;
+
+ let self = this;
+ function getElement(anonid) {
+ return document.getAnonymousElementByAttribute(self, "anonid", anonid);
+ }
+ let main = getElement("mainContainer");
+ let info = getElement("infoContainer");
+ let body = this.ui.infoBody;
+
+ // cap prompt dimensions at 60% width and 60% height of content area
+ if (!this.minWidth)
+ this.minWidth = parseInt(window.getComputedStyle(main).minWidth);
+ if (!this.minHeight)
+ this.minHeight = parseInt(window.getComputedStyle(main).minHeight);
+ let maxWidth = Math.max(Math.floor(availWidth * 0.6), this.minWidth) +
+ info.clientWidth - main.clientWidth;
+ let maxHeight = Math.max(Math.floor(availHeight * 0.6), this.minHeight) +
+ info.clientHeight - main.clientHeight;
+ body.style.maxWidth = maxWidth + "px";
+ info.style.overflow = info.style.width = info.style.height = "";
+
+ // when prompt text is too long, use scrollbars
+ if (info.clientWidth > maxWidth) {
+ info.style.overflow = "auto";
+ info.style.width = maxWidth + "px";
+ }
+ if (info.clientHeight > maxHeight) {
+ info.style.overflow = "auto";
+ info.style.height = maxHeight + "px";
+ }
+ ]]>
+ </body>
+ </method>
+
+ <method name="onButtonClick">
+ <parameter name="buttonNum"/>
+ <body>
+ <![CDATA[
+ // We want to do all the work her asynchronously off a Gecko
+ // runnable, because of situations like the one described in
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1167575#c35 : we
+ // get here off processing of an OS event and will also process
+ // one more Gecko runnable before we break out of the event loop
+ // spin whoever posted the prompt is doing. If we do all our
+ // work sync, we will exit modal state _before_ processing that
+ // runnable, and if exiting moral state posts a runnable we will
+ // incorrectly process that runnable before leaving our event
+ // loop spin.
+ Services.tm.mainThread.dispatch(() => {
+ this.Dialog["onButton" + buttonNum]();
+ this.shutdownPrompt();
+ },
+ Ci.nsIThread.DISPATCH_NORMAL);
+ ]]>
+ </body>
+ </method>
+
+ <method name="onKeyAction">
+ <parameter name="action"/>
+ <parameter name="event"/>
+ <body>
+ <![CDATA[
+ if (event.defaultPrevented)
+ return;
+
+ event.stopPropagation();
+ if (action == "default") {
+ let bnum = this.args.defaultButtonNum || 0;
+ this.onButtonClick(bnum);
+ } else { // action == "cancel"
+ this.onButtonClick(1); // Cancel button
+ }
+ ]]>
+ </body>
+ </method>
+ </implementation>
+
+ <handlers>
+ <!-- Based on dialog.xml handlers -->
+ <handler event="keypress" keycode="VK_RETURN"
+ group="system" action="this.onKeyAction('default', event);"/>
+ <handler event="keypress" keycode="VK_ESCAPE"
+ group="system" action="this.onKeyAction('cancel', event);"/>
+#ifdef XP_MACOSX
+ <handler event="keypress" key="." modifiers="meta"
+ group="system" action="this.onKeyAction('cancel', event);"/>
+#endif
+ <handler event="focus" phase="capturing">
+ let bnum = this.args.defaultButtonNum || 0;
+ let defaultButton = this.ui["button" + bnum];
+
+ let { AppConstants } =
+ Components.utils.import("resource://gre/modules/AppConstants.jsm", {});
+ if (AppConstants.platform == "macosx") {
+ // On OS X, the default button always stays marked as such (until
+ // the entire prompt blurs).
+ defaultButton.setAttribute("default", true);
+ } else {
+ // On other platforms, the default button is only marked as such
+ // when no other button has focus. XUL buttons on not-OSX will
+ // react to pressing enter as a command, so you can't trigger the
+ // default without tabbing to it or something that isn't a button.
+ let focusedDefault = (event.originalTarget == defaultButton);
+ let someButtonFocused = event.originalTarget instanceof Ci.nsIDOMXULButtonElement;
+ defaultButton.setAttribute("default", focusedDefault || !someButtonFocused);
+ }
+ </handler>
+ <handler event="blur">
+ // If focus shifted to somewhere else in the browser, don't make
+ // the default button look active.
+ let bnum = this.args.defaultButtonNum || 0;
+ let button = this.ui["button" + bnum];
+ button.setAttribute("default", false);
+ </handler>
+ </handlers>
+
+ </binding>
+</bindings>