Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  ext-tabGroups.js

  Sprache: JAVA
 

/* 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/. */

"use strict";

ChromeUtils.defineESModuleGetters(this, {
  PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
});

var { ExtensionError } = ExtensionUtils;

const spellColour = color => (color === "grey" ? "gray" : color);

/**
 * Validates whether the tab group can move to the specified index.
 *
 * @param {MozTabbrowserTabGroup} group Group to move.
 * @param {DOMWindow} window Browser window to move to.
 * @param {integer} tabIndex The desired position of the group in the window
 */

function validateTabIndexForMove(group, window, tabIndex) {
  if (group.documentGlobal === window) {
    let group_tabs = group.tabs;
    if (tabIndex > group_tabs[0]._tPos) {
      // When group is moving to a higher index, we need to increase the
      // index to account for the fact that the act of moving tab groups
      // causes all following tabs to have a decreased index.
      tabIndex += group_tabs.length;
    }
  }
  tabIndex = Math.min(tabIndex, window.gBrowser.tabs.length);

  let prevTab = tabIndex > 0 ? window.gBrowser.tabs.at(tabIndex - 1) : null;
  let nextTab = window.gBrowser.tabs.at(tabIndex);
  if (nextTab?.pinned) {
    throw new ExtensionError(
      "Cannot move the group to an index that is in the middle of pinned tabs."
    );
  }
  if (prevTab && nextTab?.group && prevTab.group === nextTab.group) {
    throw new ExtensionError(
      "Cannot move the group to an index that is in the middle of another group."
    );
  }
}

this.tabGroups = class extends ExtensionAPIPersistent {
  queryGroups({ collapsed, color, title, windowId } = {}) {
    color = spellColour(color);
    let glob = title != null && new MatchGlob(title);
    let window =
      windowId != null && windowTracker.getWindow(windowId, nullfalse);
    return windowTracker
      .browserWindows()
      .filter(
        win =>
          this.extension.canAccessWindow(win) &&
          (windowId == null || win === window)
      )
      .flatMap(win => win.gBrowser.tabGroups)
      .filter(
        group =>
          (collapsed == null || group.collapsed === collapsed) &&
          (color == null || group.color === color) &&
          (title == null || glob.matches(group.name))
      );
  }

  get(groupId) {
    let gid = getInternalTabGroupIdForExtTabGroupId(groupId);
    if (!gid) {
      throw new ExtensionError(`No group with id: ${groupId}`);
    }
    for (let group of this.queryGroups()) {
      if (group.id === gid) {
        return group;
      }
    }
    throw new ExtensionError(`No group with id: ${groupId}`);
  }

  convert(group) {
    return {
      collapsed: !!group.collapsed,
      /** Internally we use "gray", but Chrome uses "grey" @see spellColour. */
      color: group.color === "gray" ? "grey" : group.color,
      id: getExtTabGroupIdForInternalTabGroupId(group.id),
      title: group.name,
      windowId: windowTracker.getId(group.documentGlobal),
    };
  }

  PERSISTENT_EVENTS = {
    onCreated({ fire }) {
      let onCreate = event => {
        if (event.detail.isAdoptingGroup) {
          // Tab group moved from a different window.
          return;
        }
        if (
          !this.extension.canAccessWindow(event.originalTarget.documentGlobal)
        ) {
          return;
        }
        fire.async(this.convert(event.originalTarget));
      };
      windowTracker.addListener("TabGroupCreate", onCreate);
      return {
        unregister() {
          windowTracker.removeListener("TabGroupCreate", onCreate);
        },
        convert(_fire) {
          fire = _fire;
        },
      };
    },
    onMoved({ fire }) {
      let onMove = event => {
        if (
          !this.extension.canAccessWindow(event.originalTarget.documentGlobal)
        ) {
          return;
        }
        fire.async(this.convert(event.originalTarget));
      };
      let onCreate = event => {
        if (!event.detail.isAdoptingGroup) {
          // We are only interested in tab groups moved from a different window.
          return;
        }
        if (
          !this.extension.canAccessWindow(event.originalTarget.documentGlobal)
        ) {
          return;
        }
        fire.async(this.convert(event.originalTarget));
      };
      windowTracker.addListener("TabGroupMoved", onMove);
      windowTracker.addListener("TabGroupCreate", onCreate);
      return {
        unregister() {
          windowTracker.removeListener("TabGroupMoved", onMove);
          windowTracker.removeListener("TabGroupCreate", onCreate);
        },
        convert(_fire) {
          fire = _fire;
        },
      };
    },
    onRemoved({ fire }) {
      let onRemove = event => {
        if (event.originalTarget.removedByAdoption) {
          // Tab group moved to a different window.
          return;
        }
        if (
          !this.extension.canAccessWindow(event.originalTarget.documentGlobal)
        ) {
          return;
        }
        fire.async(this.convert(event.originalTarget), {
          isWindowClosing: false,
        });
      };
      let onClosed = window => {
        if (!this.extension.canAccessWindow(window)) {
          return;
        }
        for (const group of window.gBrowser.tabGroups) {
          fire.async(this.convert(group), { isWindowClosing: true });
        }
      };
      windowTracker.addListener("TabGroupRemoved", onRemove);
      windowTracker.addListener("domwindowclosed", onClosed);
      return {
        unregister() {
          windowTracker.removeListener("TabGroupRemoved", onRemove);
          windowTracker.removeListener("domwindowclosed", onClosed);
        },
        convert(_fire) {
          fire = _fire;
        },
      };
    },
    onUpdated({ fire }) {
      let onUpdate = event => {
        if (
          !this.extension.canAccessWindow(event.originalTarget.documentGlobal)
        ) {
          return;
        }
        fire.async(this.convert(event.originalTarget));
      };
      windowTracker.addListener("TabGroupCollapse", onUpdate);
      windowTracker.addListener("TabGroupExpand", onUpdate);
      windowTracker.addListener("TabGroupUpdate", onUpdate);
      return {
        unregister() {
          windowTracker.removeListener("TabGroupCollapse", onUpdate);
          windowTracker.removeListener("TabGroupExpand", onUpdate);
          windowTracker.removeListener("TabGroupUpdate", onUpdate);
        },
        convert(_fire) {
          fire = _fire;
        },
      };
    },
  };

  getAPI(context) {
    const { windowManager } = this.extension;
    return {
      tabGroups: {
        get: groupId => {
          return this.convert(this.get(groupId));
        },

        move: (groupId, { index, windowId }) => {
          let group = this.get(groupId);
          let win = group.documentGlobal;

          if (windowId != null) {
            win = windowTracker.getWindow(windowId, context);
            if (
              PrivateBrowsingUtils.isWindowPrivate(group.documentGlobal) !==
              PrivateBrowsingUtils.isWindowPrivate(win)
            ) {
              throw new ExtensionError(
                "Can't move groups between private and non-private windows"
              );
            }
            if (windowManager.getWrapper(win).type !== "normal") {
              throw new ExtensionError(
                "Groups can only be moved to normal windows."
              );
            }
          }

          let maxIndex = win.gBrowser.tabs.length;
          let tabIndex = index === -1 ? maxIndex : Math.min(maxIndex, index);
          validateTabIndexForMove(group, win, tabIndex);
          if (win !== group.documentGlobal) {
            group = win.gBrowser.adoptTabGroup(group, { tabIndex });
          } else {
            win.gBrowser.moveTabTo(group, { tabIndex });
          }
          return this.convert(group);
        },

        query: query => {
          return Array.from(this.queryGroups(query), group =>
            this.convert(group)
          );
        },

        update: (groupId, { collapsed, color, title }) => {
          let group = this.get(groupId);
          if (collapsed != null) {
            group.collapsed = collapsed;
          }
          if (color != null) {
            group.color = spellColour(color);
          }
          if (title != null) {
            group.name = title;
          }
          return this.convert(group);
        },

        onCreated: new EventManager({
          context,
          module: "tabGroups",
          event: "onCreated",
          extensionApi: this,
        }).api(),

        onMoved: new EventManager({
          context,
          module: "tabGroups",
          event: "onMoved",
          extensionApi: this,
        }).api(),

        onRemoved: new EventManager({
          context,
          module: "tabGroups",
          event: "onRemoved",
          extensionApi: this,
        }).api(),

        onUpdated: new EventManager({
          context,
          module: "tabGroups",
          event: "onUpdated",
          extensionApi: this,
        }).api(),
      },
    };
  }
};

Messung V0.5 in Prozent
C=97 H=97 G=96

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002