toolkit/content/widgets/notification.xml

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 <?xml version="1.0"?>
michael@0 2 <!-- This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 - License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
michael@0 5
michael@0 6
michael@0 7 <!DOCTYPE bindings [
michael@0 8 <!ENTITY % notificationDTD SYSTEM "chrome://global/locale/notification.dtd">
michael@0 9 %notificationDTD;
michael@0 10 ]>
michael@0 11
michael@0 12 <bindings id="notificationBindings"
michael@0 13 xmlns="http://www.mozilla.org/xbl"
michael@0 14 xmlns:xbl="http://www.mozilla.org/xbl"
michael@0 15 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
michael@0 16
michael@0 17 <binding id="notificationbox">
michael@0 18 <content>
michael@0 19 <xul:stack xbl:inherits="hidden=notificationshidden"
michael@0 20 class="notificationbox-stack">
michael@0 21 <xul:spacer/>
michael@0 22 <children includes="notification"/>
michael@0 23 </xul:stack>
michael@0 24 <children/>
michael@0 25 </content>
michael@0 26
michael@0 27 <implementation>
michael@0 28 <field name="PRIORITY_INFO_LOW" readonly="true">1</field>
michael@0 29 <field name="PRIORITY_INFO_MEDIUM" readonly="true">2</field>
michael@0 30 <field name="PRIORITY_INFO_HIGH" readonly="true">3</field>
michael@0 31 <field name="PRIORITY_WARNING_LOW" readonly="true">4</field>
michael@0 32 <field name="PRIORITY_WARNING_MEDIUM" readonly="true">5</field>
michael@0 33 <field name="PRIORITY_WARNING_HIGH" readonly="true">6</field>
michael@0 34 <field name="PRIORITY_CRITICAL_LOW" readonly="true">7</field>
michael@0 35 <field name="PRIORITY_CRITICAL_MEDIUM" readonly="true">8</field>
michael@0 36 <field name="PRIORITY_CRITICAL_HIGH" readonly="true">9</field>
michael@0 37 <field name="PRIORITY_CRITICAL_BLOCK" readonly="true">10</field>
michael@0 38
michael@0 39 <field name="currentNotification">null</field>
michael@0 40
michael@0 41 <field name="_closedNotification">null</field>
michael@0 42 <field name="_blockingCanvas">null</field>
michael@0 43 <field name="_animating">false</field>
michael@0 44
michael@0 45 <property name="notificationsHidden"
michael@0 46 onget="return this.getAttribute('notificationshidden') == 'true';">
michael@0 47 <setter>
michael@0 48 if (val)
michael@0 49 this.setAttribute('notificationshidden', true);
michael@0 50 else this.removeAttribute('notificationshidden');
michael@0 51 return val;
michael@0 52 </setter>
michael@0 53 </property>
michael@0 54
michael@0 55 <property name="allNotifications" readonly="true">
michael@0 56 <getter>
michael@0 57 <![CDATA[
michael@0 58 var closedNotification = this._closedNotification;
michael@0 59 var notifications = this.getElementsByTagName('notification');
michael@0 60 return Array.filter(notifications, function(n) n != closedNotification);
michael@0 61 ]]>
michael@0 62 </getter>
michael@0 63 </property>
michael@0 64
michael@0 65 <method name="getNotificationWithValue">
michael@0 66 <parameter name="aValue"/>
michael@0 67 <body>
michael@0 68 <![CDATA[
michael@0 69 var notifications = this.allNotifications;
michael@0 70 for (var n = notifications.length - 1; n >= 0; n--) {
michael@0 71 if (aValue == notifications[n].getAttribute("value"))
michael@0 72 return notifications[n];
michael@0 73 }
michael@0 74 return null;
michael@0 75 ]]>
michael@0 76 </body>
michael@0 77 </method>
michael@0 78
michael@0 79 <method name="appendNotification">
michael@0 80 <parameter name="aLabel"/>
michael@0 81 <parameter name="aValue"/>
michael@0 82 <parameter name="aImage"/>
michael@0 83 <parameter name="aPriority"/>
michael@0 84 <parameter name="aButtons"/>
michael@0 85 <parameter name="aEventCallback"/>
michael@0 86 <body>
michael@0 87 <![CDATA[
michael@0 88 if (aPriority < this.PRIORITY_INFO_LOW ||
michael@0 89 aPriority > this.PRIORITY_CRITICAL_BLOCK)
michael@0 90 throw "Invalid notification priority " + aPriority;
michael@0 91
michael@0 92 // check for where the notification should be inserted according to
michael@0 93 // priority. If two are equal, the existing one appears on top.
michael@0 94 var notifications = this.allNotifications;
michael@0 95 var insertPos = null;
michael@0 96 for (var n = notifications.length - 1; n >= 0; n--) {
michael@0 97 if (notifications[n].priority < aPriority)
michael@0 98 break;
michael@0 99 insertPos = notifications[n];
michael@0 100 }
michael@0 101
michael@0 102 const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
michael@0 103 var newitem = document.createElementNS(XULNS, "notification");
michael@0 104 newitem.setAttribute("label", aLabel);
michael@0 105 newitem.setAttribute("value", aValue);
michael@0 106 if (aImage)
michael@0 107 newitem.setAttribute("image", aImage);
michael@0 108 newitem.eventCallback = aEventCallback;
michael@0 109
michael@0 110 if (aButtons) {
michael@0 111 // The notification-button-default class is added to the button
michael@0 112 // with isDefault set to true. If there is no such button, it is
michael@0 113 // added to the first button (unless that button has isDefault
michael@0 114 // set to false). There cannot be multiple default buttons.
michael@0 115 var defaultElem;
michael@0 116
michael@0 117 for (var b = 0; b < aButtons.length; b++) {
michael@0 118 var button = aButtons[b];
michael@0 119 var buttonElem = document.createElementNS(XULNS, "button");
michael@0 120 buttonElem.setAttribute("label", button.label);
michael@0 121 buttonElem.setAttribute("accesskey", button.accessKey);
michael@0 122 buttonElem.classList.add("notification-button");
michael@0 123
michael@0 124 if (button.isDefault ||
michael@0 125 b == 0 && !("isDefault" in button))
michael@0 126 defaultElem = buttonElem;
michael@0 127
michael@0 128 newitem.appendChild(buttonElem);
michael@0 129 buttonElem.buttonInfo = button;
michael@0 130 }
michael@0 131
michael@0 132 if (defaultElem)
michael@0 133 defaultElem.classList.add("notification-button-default");
michael@0 134 }
michael@0 135
michael@0 136 newitem.setAttribute("priority", aPriority);
michael@0 137 if (aPriority >= this.PRIORITY_CRITICAL_LOW)
michael@0 138 newitem.setAttribute("type", "critical");
michael@0 139 else if (aPriority <= this.PRIORITY_INFO_HIGH)
michael@0 140 newitem.setAttribute("type", "info");
michael@0 141 else
michael@0 142 newitem.setAttribute("type", "warning");
michael@0 143
michael@0 144 if (!insertPos) {
michael@0 145 newitem.style.position = "fixed";
michael@0 146 newitem.style.top = "100%";
michael@0 147 newitem.style.marginTop = "-15px";
michael@0 148 newitem.style.opacity = "0";
michael@0 149 }
michael@0 150 this.insertBefore(newitem, insertPos);
michael@0 151 if (!insertPos)
michael@0 152 this._showNotification(newitem, true);
michael@0 153
michael@0 154 // Fire event for accessibility APIs
michael@0 155 var event = document.createEvent("Events");
michael@0 156 event.initEvent("AlertActive", true, true);
michael@0 157 newitem.dispatchEvent(event);
michael@0 158
michael@0 159 return newitem;
michael@0 160 ]]>
michael@0 161 </body>
michael@0 162 </method>
michael@0 163
michael@0 164 <method name="removeNotification">
michael@0 165 <parameter name="aItem"/>
michael@0 166 <parameter name="aSkipAnimation"/>
michael@0 167 <body>
michael@0 168 <![CDATA[
michael@0 169 if (aItem == this.currentNotification)
michael@0 170 this.removeCurrentNotification(aSkipAnimation);
michael@0 171 else if (aItem != this._closedNotification)
michael@0 172 this._removeNotificationElement(aItem);
michael@0 173 return aItem;
michael@0 174 ]]>
michael@0 175 </body>
michael@0 176 </method>
michael@0 177
michael@0 178 <method name="_removeNotificationElement">
michael@0 179 <parameter name="aChild"/>
michael@0 180 <body>
michael@0 181 <![CDATA[
michael@0 182 if (aChild.eventCallback)
michael@0 183 aChild.eventCallback("removed");
michael@0 184 this.removeChild(aChild);
michael@0 185
michael@0 186 // make sure focus doesn't get lost (workaround for bug 570835)
michael@0 187 let fm = Components.classes["@mozilla.org/focus-manager;1"]
michael@0 188 .getService(Components.interfaces.nsIFocusManager);
michael@0 189 if (!fm.getFocusedElementForWindow(window, false, {}))
michael@0 190 fm.moveFocus(window, this, fm.MOVEFOCUS_FORWARD, 0);
michael@0 191 ]]>
michael@0 192 </body>
michael@0 193 </method>
michael@0 194
michael@0 195 <method name="removeCurrentNotification">
michael@0 196 <parameter name="aSkipAnimation"/>
michael@0 197 <body>
michael@0 198 <![CDATA[
michael@0 199 this._showNotification(this.currentNotification, false, aSkipAnimation);
michael@0 200 ]]>
michael@0 201 </body>
michael@0 202 </method>
michael@0 203
michael@0 204 <method name="removeAllNotifications">
michael@0 205 <parameter name="aImmediate"/>
michael@0 206 <body>
michael@0 207 <![CDATA[
michael@0 208 var notifications = this.allNotifications;
michael@0 209 for (var n = notifications.length - 1; n >= 0; n--) {
michael@0 210 if (aImmediate)
michael@0 211 this._removeNotificationElement(notifications[n]);
michael@0 212 else
michael@0 213 this.removeNotification(notifications[n]);
michael@0 214 }
michael@0 215 this.currentNotification = null;
michael@0 216
michael@0 217 // Must clear up any currently animating notification
michael@0 218 if (aImmediate)
michael@0 219 this._finishAnimation();
michael@0 220 ]]>
michael@0 221 </body>
michael@0 222 </method>
michael@0 223
michael@0 224 <method name="removeTransientNotifications">
michael@0 225 <body>
michael@0 226 <![CDATA[
michael@0 227 var notifications = this.allNotifications;
michael@0 228 for (var n = notifications.length - 1; n >= 0; n--) {
michael@0 229 var notification = notifications[n];
michael@0 230 if (notification.persistence)
michael@0 231 notification.persistence--;
michael@0 232 else if (Date.now() > notification.timeout)
michael@0 233 this.removeNotification(notification);
michael@0 234 }
michael@0 235 ]]>
michael@0 236 </body>
michael@0 237 </method>
michael@0 238
michael@0 239 <method name="_showNotification">
michael@0 240 <parameter name="aNotification"/>
michael@0 241 <parameter name="aSlideIn"/>
michael@0 242 <parameter name="aSkipAnimation"/>
michael@0 243 <body>
michael@0 244 <![CDATA[
michael@0 245 this._finishAnimation();
michael@0 246
michael@0 247 var height = aNotification.boxObject.height;
michael@0 248 var skipAnimation = aSkipAnimation || (height == 0);
michael@0 249
michael@0 250 if (aSlideIn) {
michael@0 251 this.currentNotification = aNotification;
michael@0 252 aNotification.style.removeProperty("position");
michael@0 253 aNotification.style.removeProperty("top");
michael@0 254 aNotification.style.removeProperty("margin-top");
michael@0 255 aNotification.style.removeProperty("opacity");
michael@0 256
michael@0 257 if (skipAnimation) {
michael@0 258 this._setBlockingState(this.currentNotification);
michael@0 259 return;
michael@0 260 }
michael@0 261 }
michael@0 262 else {
michael@0 263 this._closedNotification = aNotification;
michael@0 264 var notifications = this.allNotifications;
michael@0 265 var idx = notifications.length - 1;
michael@0 266 this.currentNotification = (idx >= 0) ? notifications[idx] : null;
michael@0 267
michael@0 268 if (skipAnimation) {
michael@0 269 this._removeNotificationElement(this._closedNotification);
michael@0 270 this._closedNotification = null;
michael@0 271 this._setBlockingState(this.currentNotification);
michael@0 272 return;
michael@0 273 }
michael@0 274
michael@0 275 aNotification.style.marginTop = -height + "px";
michael@0 276 aNotification.style.opacity = 0;
michael@0 277 }
michael@0 278
michael@0 279 this._animating = true;
michael@0 280 ]]>
michael@0 281 </body>
michael@0 282 </method>
michael@0 283
michael@0 284 <method name="_finishAnimation">
michael@0 285 <body><![CDATA[
michael@0 286 if (this._animating) {
michael@0 287 this._animating = false;
michael@0 288 if (this._closedNotification) {
michael@0 289 this._removeNotificationElement(this._closedNotification);
michael@0 290 this._closedNotification = null;
michael@0 291 }
michael@0 292 this._setBlockingState(this.currentNotification);
michael@0 293 }
michael@0 294 ]]></body>
michael@0 295 </method>
michael@0 296
michael@0 297 <method name="_setBlockingState">
michael@0 298 <parameter name="aNotification"/>
michael@0 299 <body>
michael@0 300 <![CDATA[
michael@0 301 var isblock = aNotification &&
michael@0 302 aNotification.priority == this.PRIORITY_CRITICAL_BLOCK;
michael@0 303 var canvas = this._blockingCanvas;
michael@0 304 if (isblock) {
michael@0 305 if (!canvas)
michael@0 306 canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
michael@0 307 const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
michael@0 308 var content = this.firstChild;
michael@0 309 if (!content ||
michael@0 310 content.namespaceURI != XULNS ||
michael@0 311 content.localName != "browser")
michael@0 312 return;
michael@0 313
michael@0 314 var width = content.boxObject.width;
michael@0 315 var height = content.boxObject.height;
michael@0 316 content.collapsed = true;
michael@0 317
michael@0 318 canvas.setAttribute("width", width);
michael@0 319 canvas.setAttribute("height", height);
michael@0 320 canvas.setAttribute("flex", "1");
michael@0 321
michael@0 322 this.appendChild(canvas);
michael@0 323 this._blockingCanvas = canvas;
michael@0 324
michael@0 325 var bgcolor = "white";
michael@0 326 try {
michael@0 327 var prefService = Components.classes["@mozilla.org/preferences-service;1"].
michael@0 328 getService(Components.interfaces.nsIPrefBranch);
michael@0 329 bgcolor = prefService.getCharPref("browser.display.background_color");
michael@0 330
michael@0 331 var win = content.contentWindow;
michael@0 332 var context = canvas.getContext("2d");
michael@0 333 context.globalAlpha = 0.5;
michael@0 334 context.drawWindow(win, win.scrollX, win.scrollY,
michael@0 335 width, height, bgcolor);
michael@0 336 }
michael@0 337 catch(ex) { };
michael@0 338 }
michael@0 339 else if (canvas) {
michael@0 340 canvas.parentNode.removeChild(canvas);
michael@0 341 this._blockingCanvas = null;
michael@0 342 var content = this.firstChild;
michael@0 343 if (content)
michael@0 344 content.collapsed = false;
michael@0 345 }
michael@0 346 ]]>
michael@0 347 </body>
michael@0 348 </method>
michael@0 349
michael@0 350 </implementation>
michael@0 351
michael@0 352 <handlers>
michael@0 353 <handler event="transitionend"><![CDATA[
michael@0 354 if (event.target.localName == "notification" &&
michael@0 355 event.propertyName == "margin-top")
michael@0 356 this._finishAnimation();
michael@0 357 ]]></handler>
michael@0 358 </handlers>
michael@0 359
michael@0 360 </binding>
michael@0 361
michael@0 362 <binding id="notification" role="xul:alert">
michael@0 363 <content>
michael@0 364 <xul:hbox class="notification-inner outset" flex="1" xbl:inherits="type">
michael@0 365 <xul:hbox anonid="details" align="center" flex="1"
michael@0 366 oncommand="this.parentNode.parentNode._doButtonCommand(event);">
michael@0 367 <xul:image anonid="messageImage" class="messageImage" xbl:inherits="src=image,type,value"/>
michael@0 368 <xul:description anonid="messageText" class="messageText" flex="1" xbl:inherits="xbl:text=label"/>
michael@0 369 <xul:spacer flex="1"/>
michael@0 370 <children/>
michael@0 371 </xul:hbox>
michael@0 372 <xul:toolbarbutton ondblclick="event.stopPropagation();"
michael@0 373 class="messageCloseButton close-icon tabbable"
michael@0 374 xbl:inherits="hidden=hideclose"
michael@0 375 tooltiptext="&closeNotification.tooltip;"
michael@0 376 oncommand="document.getBindingParent(this).close();"/>
michael@0 377 </xul:hbox>
michael@0 378 </content>
michael@0 379 <resources>
michael@0 380 <stylesheet src="chrome://global/skin/notification.css"/>
michael@0 381 </resources>
michael@0 382 <implementation>
michael@0 383 <property name="label" onset="this.setAttribute('label', val); return val;"
michael@0 384 onget="return this.getAttribute('label');"/>
michael@0 385 <property name="value" onset="this.setAttribute('value', val); return val;"
michael@0 386 onget="return this.getAttribute('value');"/>
michael@0 387 <property name="image" onset="this.setAttribute('image', val); return val;"
michael@0 388 onget="return this.getAttribute('image');"/>
michael@0 389 <property name="type" onset="this.setAttribute('type', val); return val;"
michael@0 390 onget="return this.getAttribute('type');"/>
michael@0 391 <property name="priority" onget="return parseInt(this.getAttribute('priority')) || 0;"
michael@0 392 onset="this.setAttribute('priority', val); return val;"/>
michael@0 393 <property name="persistence" onget="return parseInt(this.getAttribute('persistence')) || 0;"
michael@0 394 onset="this.setAttribute('persistence', val); return val;"/>
michael@0 395 <field name="timeout">0</field>
michael@0 396
michael@0 397 <property name="control" readonly="true">
michael@0 398 <getter>
michael@0 399 <![CDATA[
michael@0 400 var parent = this.parentNode;
michael@0 401 while (parent) {
michael@0 402 if (parent.localName == "notificationbox")
michael@0 403 return parent;
michael@0 404 parent = parent.parentNode;
michael@0 405 }
michael@0 406 return null;
michael@0 407 ]]>
michael@0 408 </getter>
michael@0 409 </property>
michael@0 410
michael@0 411 <method name="close">
michael@0 412 <body>
michael@0 413 <![CDATA[
michael@0 414 var control = this.control;
michael@0 415 if (control)
michael@0 416 control.removeNotification(this);
michael@0 417 else
michael@0 418 this.hidden = true;
michael@0 419 ]]>
michael@0 420 </body>
michael@0 421 </method>
michael@0 422
michael@0 423 <method name="_doButtonCommand">
michael@0 424 <parameter name="aEvent"/>
michael@0 425 <body>
michael@0 426 <![CDATA[
michael@0 427 if (!("buttonInfo" in aEvent.target))
michael@0 428 return;
michael@0 429
michael@0 430 var button = aEvent.target.buttonInfo;
michael@0 431 if (button.popup) {
michael@0 432 document.getElementById(button.popup).
michael@0 433 openPopup(aEvent.originalTarget, "after_start", 0, 0, false, false, aEvent);
michael@0 434 aEvent.stopPropagation();
michael@0 435 }
michael@0 436 else {
michael@0 437 var callback = button.callback;
michael@0 438 if (callback) {
michael@0 439 var result = callback(this, button);
michael@0 440 if (!result)
michael@0 441 this.close();
michael@0 442 aEvent.stopPropagation();
michael@0 443 }
michael@0 444 }
michael@0 445 ]]>
michael@0 446 </body>
michael@0 447 </method>
michael@0 448 </implementation>
michael@0 449 </binding>
michael@0 450
michael@0 451 <binding id="popup-notification">
michael@0 452 <content align="start">
michael@0 453 <xul:image class="popup-notification-icon"
michael@0 454 xbl:inherits="popupid,src=icon"/>
michael@0 455 <xul:vbox flex="1">
michael@0 456 <xul:description class="popup-notification-description"
michael@0 457 xbl:inherits="xbl:text=label"/>
michael@0 458 <children includes="popupnotificationcontent"/>
michael@0 459 <xul:label class="text-link popup-notification-learnmore-link"
michael@0 460 xbl:inherits="href=learnmoreurl">&learnMore;</xul:label>
michael@0 461 <xul:spacer flex="1"/>
michael@0 462 <xul:hbox class="popup-notification-button-container"
michael@0 463 pack="end" align="center">
michael@0 464 <xul:button anonid="button"
michael@0 465 class="popup-notification-menubutton"
michael@0 466 type="menu-button"
michael@0 467 xbl:inherits="oncommand=buttoncommand,label=buttonlabel,accesskey=buttonaccesskey">
michael@0 468 <xul:menupopup anonid="menupopup"
michael@0 469 xbl:inherits="oncommand=menucommand">
michael@0 470 <children/>
michael@0 471 <xul:menuitem class="menuitem-iconic popup-notification-closeitem"
michael@0 472 label="&closeNotificationItem.label;"
michael@0 473 xbl:inherits="oncommand=closeitemcommand,hidden=hidenotnow"/>
michael@0 474 </xul:menupopup>
michael@0 475 </xul:button>
michael@0 476 </xul:hbox>
michael@0 477 </xul:vbox>
michael@0 478 <xul:vbox pack="start">
michael@0 479 <xul:toolbarbutton anonid="closebutton"
michael@0 480 class="messageCloseButton close-icon popup-notification-closebutton tabbable"
michael@0 481 xbl:inherits="oncommand=closebuttoncommand"
michael@0 482 tooltiptext="&closeNotification.tooltip;"/>
michael@0 483 </xul:vbox>
michael@0 484 </content>
michael@0 485 <resources>
michael@0 486 <stylesheet src="chrome://global/skin/notification.css"/>
michael@0 487 </resources>
michael@0 488 <implementation>
michael@0 489 <field name="closebutton" readonly="true">
michael@0 490 document.getAnonymousElementByAttribute(this, "anonid", "closebutton");
michael@0 491 </field>
michael@0 492 <field name="button" readonly="true">
michael@0 493 document.getAnonymousElementByAttribute(this, "anonid", "button");
michael@0 494 </field>
michael@0 495 <field name="menupopup" readonly="true">
michael@0 496 document.getAnonymousElementByAttribute(this, "anonid", "menupopup");
michael@0 497 </field>
michael@0 498 </implementation>
michael@0 499 </binding>
michael@0 500 </bindings>

mercurial