[gnome-shell-extensions] Revert "Remove alternate-tab extension"



commit 9900ae19dc2734a0d42df2635901d46ea0d409c6
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Tue Dec 11 00:10:00 2012 +0100

    Revert "Remove alternate-tab extension"
    
    This reverts commit 0b7c3e3dbb0f44a4e8b4b501698d591b1befbf41.
    Pushed by mistake, and we actually want the alternate-tab extension,
    just in a different form.

 configure.ac                                       |    5 +-
 extensions/alternate-tab/Makefile.am               |    6 +
 extensions/alternate-tab/extension.js              |  448 ++++++++++++++++++++
 extensions/alternate-tab/metadata.json.in          |   11 +
 ...e.shell.extensions.alternate-tab.gschema.xml.in |   26 ++
 extensions/alternate-tab/prefs.js                  |   84 ++++
 extensions/alternate-tab/stylesheet.css            |    1 +
 po/POTFILES.in                                     |    3 +
 8 files changed, 582 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 7d2d477..90f14bc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,7 +27,7 @@ fi
 AC_SUBST([SHELL_VERSION])
 
 dnl keep this in alphabetic order
-CLASSIC_EXTENSIONS="apps-menu places-menu default-min-max"
+CLASSIC_EXTENSIONS="apps-menu places-menu alternate-tab default-min-max"
 DEFAULT_EXTENSIONS="$CLASSIC_EXTENSIONS alternative-status-menu drive-menu windowsNavigator workspace-indicator"
 ALL_EXTENSIONS="$DEFAULT_EXTENSIONS auto-move-windows example native-window-placement systemMonitor user-theme xrandr-indicator"
 AC_SUBST(CLASSIC_EXTENSIONS, [$CLASSIC_EXTENSIONS])
@@ -62,7 +62,7 @@ for e in $enable_extensions; do
 					[AC_MSG_WARN([gnome-desktop-3.0 not found, disabling xrandr-indicator])])
 			;;
 dnl		keep this in alphabetic order
-                alternative-status-menu|apps-menu|auto-move-windows|default-min-max|drive-menu|example|native-window-placement|places-menu|user-theme|windowsNavigator|workspace-indicator)
+		alternate-tab|alternative-status-menu|apps-menu|auto-move-windows|default-min-max|drive-menu|example|native-window-placement|places-menu|user-theme|windowsNavigator|workspace-indicator)
 			ENABLED_EXTENSIONS="$ENABLED_EXTENSIONS $e"
 			;;
 		*)
@@ -75,6 +75,7 @@ AC_SUBST(ENABLED_EXTENSIONS, [$ENABLED_EXTENSIONS])
 dnl Please keep this sorted alphabetically
 AC_CONFIG_FILES([
   data/Makefile
+  extensions/alternate-tab/Makefile
   extensions/alternative-status-menu/Makefile
   extensions/apps-menu/Makefile
   extensions/auto-move-windows/Makefile
diff --git a/extensions/alternate-tab/Makefile.am b/extensions/alternate-tab/Makefile.am
new file mode 100644
index 0000000..1f35392
--- /dev/null
+++ b/extensions/alternate-tab/Makefile.am
@@ -0,0 +1,6 @@
+EXTENSION_ID = alternate-tab
+
+EXTRA_MODULES = prefs.js
+
+include ../../extension.mk
+include ../../settings.mk
diff --git a/extensions/alternate-tab/extension.js b/extensions/alternate-tab/extension.js
new file mode 100644
index 0000000..bfd3015
--- /dev/null
+++ b/extensions/alternate-tab/extension.js
@@ -0,0 +1,448 @@
+/* -*- mode: js; js-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+/* most of the code is borrowed from
+ * > js/ui/altTab.js <
+ * of the gnome-shell source code
+ */
+
+const Clutter = imports.gi.Clutter;
+const Gdk = imports.gi.Gdk;
+const Gio = imports.gi.Gio;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+const Mainloop = imports.mainloop;
+const Meta = imports.gi.Meta;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+
+const AltTab = imports.ui.altTab;
+const Main = imports.ui.main;
+const ModalDialog = imports.ui.modalDialog;
+const Tweener = imports.ui.tweener;
+const WindowManager = imports.ui.windowManager;
+
+const Gettext = imports.gettext.domain('gnome-shell-extensions');
+const _ = Gettext.gettext;
+const N_ = function(e) { return e };
+
+const ExtensionUtils = imports.misc.extensionUtils;
+const Me = ExtensionUtils.getCurrentExtension();
+const Convenience = Me.imports.convenience;
+
+let settings;
+
+const AppIconMode = {
+    THUMBNAIL_ONLY: 1,
+    APP_ICON_ONLY: 2,
+    BOTH: 3,
+};
+
+const SETTINGS_APP_ICON_MODE = 'app-icon-mode';
+const SETTINGS_CURRENT_WORKSPACE_ONLY = 'current-workspace-only';
+
+function mod(a, b) {
+    return ((a+b) % b);
+}
+
+const AltTabPopup = new Lang.Class({
+    Name: 'AlternateTab.AltTabPopup',
+
+    _init : function(settings) {
+	this._settings = settings;
+
+        this.actor = new Shell.GenericContainer({ name: 'altTabPopup',
+                                                  reactive: true });
+
+        this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
+        this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
+        this.actor.connect('allocate', Lang.bind(this, this._allocate));
+
+        this._haveModal = false;
+
+        this._currentWindow = 0;
+        this._motionTimeoutId = 0;
+        this._initialDelayTimeoutId = 0;
+
+        // Initially disable hover so we ignore the enter-event if
+        // the switcher appears underneath the current pointer location
+        this._disableHover();
+
+        Main.uiGroup.add_actor(this.actor);
+    },
+
+    _getPreferredWidth: function (actor, forHeight, alloc) {
+        alloc.min_size = global.screen_width;
+        alloc.natural_size = global.screen_width;
+    },
+
+    _getPreferredHeight: function (actor, forWidth, alloc) {
+        alloc.min_size = global.screen_height;
+        alloc.natural_size = global.screen_height;
+    },
+
+    _allocate: function (actor, box, flags) {
+        let childBox = new Clutter.ActorBox();
+        let primary = Main.layoutManager.primaryMonitor;
+
+        let leftPadding = this.actor.get_theme_node().get_padding(St.Side.LEFT);
+        let rightPadding = this.actor.get_theme_node().get_padding(St.Side.RIGHT);
+        let bottomPadding = this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
+        let vPadding = this.actor.get_theme_node().get_vertical_padding();
+        let hPadding = leftPadding + rightPadding;
+
+        // Allocate the appSwitcher
+        // We select a size based on an icon size that does not overflow the screen
+        let [childMinHeight, childNaturalHeight] = this._appSwitcher.actor.get_preferred_height(primary.width - hPadding);
+        let [childMinWidth, childNaturalWidth] = this._appSwitcher.actor.get_preferred_width(childNaturalHeight);
+        childBox.x1 = Math.max(primary.x + leftPadding, primary.x + Math.floor((primary.width - childNaturalWidth) / 2));
+        childBox.x2 = Math.min(primary.x + primary.width - rightPadding, childBox.x1 + childNaturalWidth);
+        childBox.y1 = primary.y + Math.floor((primary.height - childNaturalHeight) / 2);
+        childBox.y2 = childBox.y1 + childNaturalHeight;
+        this._appSwitcher.actor.allocate(childBox, flags);
+    },
+
+    show : function(backward, binding, mask) {
+	let windows;
+
+	if (!settings.get_boolean(SETTINGS_CURRENT_WORKSPACE_ONLY)) {
+	    // This is roughly what meta_display_get_tab_list does, except
+	    // that it doesn't filter on workspace
+	    // See in particular src/core/window-private.h for the filters
+	    windows = global.get_window_actors().map(function(actor) {
+		return actor.meta_window;
+	    }).filter(function(win) {
+		return !win.is_override_redirect() &&
+		    win.get_window_type() != Meta.WindowType.DESKTOP &&
+		    win.get_window_type() != Meta.WindowType.DOCK;
+	    }).sort(function(one, two) {
+		return two.get_user_time() - one.get_user_time();
+	    });
+	} else {
+	    windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, global.screen,
+						  global.screen.get_active_workspace());
+	}
+
+        // Filter away attached modal dialogs (switch to their parents instead)
+        windows = windows.filter(function(win) { return !win.is_attached_dialog(); });
+
+        if (windows.length == 0)
+            return false;
+
+        if (!Main.pushModal(this.actor)) {
+            // Probably someone else has a pointer grab, try again with keyboard only
+            if (!Main.pushModal(this.actor, global.get_current_time(), Meta.ModalOptions.POINTER_ALREADY_GRABBED)) {
+                return false;
+            }
+        }
+        this._haveModal = true;
+        this._modifierMask = AltTab.primaryModifier(mask);
+
+        this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
+        this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
+
+        this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside));
+        this.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
+
+        this._appSwitcher = new WindowList(windows, this._settings);
+        this.actor.add_actor(this._appSwitcher.actor);
+        this._appSwitcher.connect('item-activated', Lang.bind(this, this._windowActivated));
+        this._appSwitcher.connect('item-entered', Lang.bind(this, this._windowEntered));
+
+        // make the initial selection
+	this._currentWindow = 0;
+        if (backward)
+            this._select(this._previousWindow());
+        else
+            this._select(this._nextWindow());
+
+        this.actor.opacity = 0;
+        this.actor.show();
+
+        // There's a race condition; if the user released Alt before
+        // we got the grab, then we won't be notified. (See
+        // https://bugzilla.gnome.org/show_bug.cgi?id=596695 for
+        // details.) So we check now. (Have to do this after updating
+        // selection.)
+        let [x, y, mods] = global.get_pointer();
+        if (!(mods & this._modifierMask)) {
+            this._finish();
+            return false;
+        }
+
+        // We delay showing the popup so that fast Alt+Tab users aren't
+        // disturbed by the popup briefly flashing.
+        this._initialDelayTimeoutId = Mainloop.timeout_add(AltTab.POPUP_DELAY_TIMEOUT,
+                                                           Lang.bind(this, function () {
+                                                               this.actor.opacity = 255;
+                                                               this._initialDelayTimeoutId = 0;
+                                                           }));
+
+	return true
+    },
+
+    _windowActivated : function(thumbnailList, n) {
+	let win = this._appSwitcher.windows[n];
+        Main.activateWindow(win);
+        this.destroy();
+    },
+
+    _finish : function() {
+        let win = this._appSwitcher.windows[this._currentWindow];
+        Main.activateWindow(win);
+        this.destroy();
+    },
+
+    _keyPressEvent : function(actor, event) {
+        let keysym = event.get_key_symbol();
+        let event_state = event.get_state();
+        let backwards = event_state & Clutter.ModifierType.SHIFT_MASK;
+        let action = global.display.get_keybinding_action(event.get_key_code(), event_state);
+
+        this._disableHover();
+
+        if (keysym == Clutter.Escape) {
+            this.destroy();
+        } else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS ||
+		   action == Meta.KeyBindingAction.SWITCH_GROUP) {
+            this._select(backwards ? this._previousWindow() : this._nextWindow());
+        } else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD ||
+		  action == Meta.KeyBindingAction.SWITCH_GROUP_BACKWARD) {
+            this._select(this._previousWindow());
+        } else {
+	    if (keysym == Clutter.Left)
+                this._select(this._previousWindow());
+            else if (keysym == Clutter.Right)
+                this._select(this._nextWindow());
+        }
+
+        return true;
+    },
+
+    _keyReleaseEvent : function(actor, event) {
+        let [x, y, mods] = global.get_pointer();
+        let state = mods & this._modifierMask;
+
+        if (state == 0)
+            this._finish();
+
+        return true;
+    },
+
+    _onScroll : function(actor, event) {
+        let direction = event.get_scroll_direction();
+        if (direction == Clutter.ScrollDirection.UP)
+            this._select(this._previousWindow());
+	else if (direction == Clutter.ScrollDirection.DOWN)
+            this._select(this._nextWindow());
+
+	return true;
+    },
+
+    _clickedOutside : function(actor, event) {
+        this.destroy();
+    },
+
+    _windowEntered : function(windowSwitcher, n) {
+        if (!this._mouseActive)
+            return;
+
+        this._select(n);
+    },
+
+    _disableHover : function() {
+        this._mouseActive = false;
+
+        if (this._motionTimeoutId != 0)
+            Mainloop.source_remove(this._motionTimeoutId);
+
+        this._motionTimeoutId = Mainloop.timeout_add(AltTab.DISABLE_HOVER_TIMEOUT, Lang.bind(this, this._mouseTimedOut));
+    },
+
+    _mouseTimedOut : function() {
+        this._motionTimeoutId = 0;
+        this._mouseActive = true;
+    },
+
+    _popModal: function() {
+        if (this._haveModal) {
+            Main.popModal(this.actor);
+            this._haveModal = false;
+        }
+    },
+
+    destroy : function() {
+        this._popModal();
+        if (this.actor.visible) {
+            Tweener.addTween(this.actor,
+                             { opacity: 0,
+                               time: AltTab.POPUP_FADE_OUT_TIME,
+                               transition: 'easeOutQuad',
+                               onComplete: Lang.bind(this, this._finishDestroy),
+                             });
+        } else
+            this._finishDestroy();
+    },
+
+    _finishDestroy : function() {
+        if (this._motionTimeoutId != 0) {
+            Mainloop.source_remove(this._motionTimeoutId);
+            this._motionTimeoutId = 0;
+        }
+
+        if (this._initialDelayTimeoutId != 0) {
+            Mainloop.source_remove(this._initialDelayTimeoutId);
+            this._initialDelayTimeoutId = 0;
+        }
+
+        this.actor.destroy();
+    },
+
+    _select : function(window) {
+        this._currentWindow = window;
+        this._appSwitcher.highlight(window);
+    },
+
+    _nextWindow: function() {
+	return mod(this._currentWindow + 1, this._appSwitcher.windows.length);
+    },
+
+    _previousWindow: function() {
+	return mod(this._currentWindow - 1, this._appSwitcher.windows.length);
+    },
+});
+
+const WindowIcon = new Lang.Class({
+    Name: 'AlternateTab.WindowIcon',
+
+    _init: function(window, settings) {
+	this.window = window;
+	this._settings = settings;
+
+        this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
+                                        vertical: true });
+        this.icon = null;
+        this._iconBin = new St.Widget({ layout_manager: new Clutter.BinLayout() });
+
+        this.actor.add(this._iconBin, { x_fill: false, y_fill: false } );
+        this.label = new St.Label({ text: window.get_title() });
+        this.actor.add(this.label, { x_fill: false });
+
+	let tracker = Shell.WindowTracker.get_default();
+	this.app = tracker.get_window_app(window);
+
+        let mutterWindow = this.window.get_compositor_private();
+        let windowTexture = mutterWindow.get_texture();
+        let [width, height] = windowTexture.get_size();
+        let scale, size;
+
+	this._iconBin.destroy_all_children();
+
+	switch (this._settings.get_enum(SETTINGS_APP_ICON_MODE)) {
+	case AppIconMode.THUMBNAIL_ONLY:
+	    scale = Math.min(1.0, 128 / width, 128 / height);
+	    size = 128;
+            this.clone = new Clutter.Clone({ source: windowTexture,
+					     width: width * scale,
+					     height: height * scale,
+					     x_align: Clutter.ActorAlign.CENTER,
+					     y_align: Clutter.ActorAlign.CENTER,
+					     // usual hack for the usual bug in ClutterBinLayout...
+				             x_expand: true,
+					     y_expand: true });
+	    this._iconBin.add_actor(this.clone);
+	    break;
+
+	case AppIconMode.BOTH:
+	    scale = Math.min(1.0, 128 / width, 128 / height);
+	    size = 128;
+            this.clone = new Clutter.Clone({ source: windowTexture,
+					     width: width * scale,
+					     height: height * scale,
+					     x_align: Clutter.ActorAlign.CENTER,
+					     y_align: Clutter.ActorAlign.CENTER,
+					     // usual hack for the usual bug in ClutterBinLayout...
+				             x_expand: true,
+					     y_expand: true });
+	    this._iconBin.add_actor(this.clone);
+
+	    if (this.app) {
+		this.appIcon = this.app.create_icon_texture(size / 2);
+		this.appIcon.x_expand = this.appIcon.y_expand = true;
+		this.appIcon.x_align = Clutter.ActorAlign.END;
+		this.appIcon.y_align = Clutter.ActorAlign.END;
+		this._iconBin.add_actor(this.appIcon);
+	    }
+	    break;
+
+	case AppIconMode.APP_ICON_ONLY:
+	    size = 96;
+	    if (this.app) {
+		this.appIcon = this.app.create_icon_texture(size);
+		this.appIcon.x_expand = this.appIcon.y_expand = true;
+	    } else {
+		this.appIcon = new St.Icon({ icon_name: 'icon-missing',
+					     icon_size: size,
+					     x_expand: true,
+					     y_expand: true });
+	    }
+	    this._iconBin.add_actor(this.appIcon);
+	}
+
+        this._iconBin.set_size(size, size);
+    }
+});
+
+const WindowList = new Lang.Class({
+    Name: 'AlternateTab.WindowList',
+    Extends: AltTab.SwitcherList,
+
+    _init : function(windows, settings) {
+        this.parent(true);
+
+        this.windows = windows;
+        this.icons = [];
+
+	for (let i = 0; i < windows.length; i++) {
+	    let win = windows[i];
+	    let icon = new WindowIcon(win, settings);
+
+            this.addItem(icon.actor, icon.label);
+            this.icons.push(icon);
+	}
+    }
+});
+
+function doAltTab(display, screen, window, binding) {
+    if (Main.wm._workspaceSwitcherPopup)
+        Main.wm._workspaceSwitcherPopup.actor.hide();
+
+    let modifiers = binding.get_modifiers()
+    let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
+
+    let popup = new AltTabPopup(settings);
+    if (!popup.show(backwards, binding.get_name(), binding.get_mask()))
+        popup.destroy();
+}
+
+function init(metadata) {
+    Convenience.initTranslations();
+    settings = Convenience.getSettings();
+}
+
+function setKeybinding(name, func) {
+    Main.wm.setCustomKeybindingHandler(name, Main.KeybindingMode.NORMAL, func);
+}
+
+function enable() {
+    setKeybinding('switch-windows', doAltTab);
+    setKeybinding('switch-group', doAltTab);
+    setKeybinding('switch-windows-backward', doAltTab);
+    setKeybinding('switch-group-backward', doAltTab);
+}
+
+function disable() {
+    setKeybinding('switch-windows', Lang.bind(Main.wm, Main.wm._startAppSwitcher));
+    setKeybinding('switch-group', Lang.bind(Main.wm, Main.wm._startAppSwitcher));
+    setKeybinding('switch-windows-backward', Lang.bind(Main.wm, Main.wm._startAppSwitcher));
+    setKeybinding('switch-group-backward', Lang.bind(Main.wm, Main.wm._startAppSwitcher));
+}
diff --git a/extensions/alternate-tab/metadata.json.in b/extensions/alternate-tab/metadata.json.in
new file mode 100644
index 0000000..4d2f63e
--- /dev/null
+++ b/extensions/alternate-tab/metadata.json.in
@@ -0,0 +1,11 @@
+{
+"extension-id": "@extension_id@",
+"uuid": "@uuid@",
+"settings-schema": "@gschemaname@",
+"gettext-domain": "@gettext_domain@",
+"name": "AlternateTab",
+"description": "A replacement for Alt-Tab, allows to cycle between windows and does not group by application",
+"original-authors": [  "jw bargsten org", "thomas bouffon gmail com" ],
+"shell-version": [ "@shell_current@" ],
+"url": "@url@"
+}
diff --git a/extensions/alternate-tab/org.gnome.shell.extensions.alternate-tab.gschema.xml.in b/extensions/alternate-tab/org.gnome.shell.extensions.alternate-tab.gschema.xml.in
new file mode 100644
index 0000000..88ac798
--- /dev/null
+++ b/extensions/alternate-tab/org.gnome.shell.extensions.alternate-tab.gschema.xml.in
@@ -0,0 +1,26 @@
+<schemalist gettext-domain="gnome-shell-extensions">
+  <enum id="org.gnome.shell.extensions.alternate-tab.AppIconMode">
+    <value value="1" nick="thumbnail_only"/>
+    <value value="2" nick="app_icon_only"/>
+    <value value="3" nick="both"/>
+  </enum>
+  <schema id="org.gnome.shell.extensions.alternate-tab" path="/org/gnome/shell/extensions/alternate-tab/">
+    <key name="app-icon-mode" enum="org.gnome.shell.extensions.alternate-tab.AppIconMode">
+      <default>'both'</default>
+      <_summary>The application icon mode.</_summary>
+      <_description>
+	Configures how the windows are shown in the switcher. Valid possibilities
+	are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-only'
+	(shows only the application icon) or 'both'.
+      </_description>
+    </key>
+    <key type="b" name="current-workspace-only">
+      <default>false</default>
+      <summary>Limit switcher to current workspace.</summary>
+      <description>
+	If true, only windows from the current workspace are shown in the switcher.
+	Otherwise, all windows are included.
+      </description>
+    </key>
+  </schema>
+</schemalist>
diff --git a/extensions/alternate-tab/prefs.js b/extensions/alternate-tab/prefs.js
new file mode 100644
index 0000000..6f1856b
--- /dev/null
+++ b/extensions/alternate-tab/prefs.js
@@ -0,0 +1,84 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+/* most of the code is borrowed from
+ * > js/ui/altTab.js <
+ * of the gnome-shell source code
+ */
+
+const Gdk = imports.gi.Gdk;
+const Gio = imports.gi.Gio;
+const Gtk = imports.gi.Gtk;
+const GObject = imports.gi.GObject;
+const Lang = imports.lang;
+
+const Gettext = imports.gettext.domain('gnome-shell-extensions');
+const _ = Gettext.gettext;
+const N_ = function(e) { return e };
+
+const ExtensionUtils = imports.misc.extensionUtils;
+const Me = ExtensionUtils.getCurrentExtension();
+const Convenience = Me.imports.convenience;
+
+const SETTINGS_APP_ICON_MODE = 'app-icon-mode';
+const SETTINGS_CURRENT_WORKSPACE_ONLY = 'current-workspace-only';
+
+const MODES = {
+    thumbnail_only: N_("Thumbnail only"),
+    app_icon_only: N_("Application icon only"),
+    both: N_("Thumbnail and application icon"),
+};
+
+const AltTabSettingsWidget = new GObject.Class({
+    Name: 'AlternateTab.Prefs.AltTabSettingsWidget',
+    GTypeName: 'AltTabSettingsWidget',
+    Extends: Gtk.Grid,
+
+    _init : function(params) {
+        this.parent(params);
+        this.margin = 10;
+	this.orientation = Gtk.Orientation.VERTICAL;
+
+        this._settings = Convenience.getSettings();
+
+        let presentLabel = _("Present windows as");
+        this.add(new Gtk.Label({ label: presentLabel, sensitive: true,
+                                 margin_bottom: 10, margin_top: 5 }));
+
+        let top = 1;
+        let radio = null;
+        let currentMode = this._settings.get_string(SETTINGS_APP_ICON_MODE);
+        for (let mode in MODES) {
+            // copy the mode variable because it has function scope, not block scope
+            // so cannot be used in a closure
+            let modeCapture = mode;
+            let name = Gettext.gettext(MODES[mode]);
+
+            radio = new Gtk.RadioButton({ group: radio, label: name, valign: Gtk.Align.START });
+            radio.connect('toggled', Lang.bind(this, function(widget) {
+                if (widget.active)
+                    this._settings.set_string(SETTINGS_APP_ICON_MODE, modeCapture);
+            }));
+            this.add(radio);
+
+            if (mode == currentMode)
+                radio.active = true;
+            top += 1;
+        }
+
+	let check = new Gtk.CheckButton({ label: _("Show only windows in the current workspace"),
+					  margin_top: 12 });
+	this._settings.bind(SETTINGS_CURRENT_WORKSPACE_ONLY, check, 'active', Gio.SettingsBindFlags.DEFAULT);
+	this.add(check);
+    },
+});
+
+function init() {
+    Convenience.initTranslations();
+}
+
+function buildPrefsWidget() {
+    let widget = new AltTabSettingsWidget();
+    widget.show_all();
+
+    return widget;
+}
diff --git a/extensions/alternate-tab/stylesheet.css b/extensions/alternate-tab/stylesheet.css
new file mode 100644
index 0000000..25134b6
--- /dev/null
+++ b/extensions/alternate-tab/stylesheet.css
@@ -0,0 +1 @@
+/* This extensions requires no special styling */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2db1d80..01b6d6d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,6 +1,9 @@
 data/gnome-classic.desktop.in
 data/gnome-classic.session.desktop.in.in
 data/gnome-shell-classic.desktop.in.in
+extensions/alternate-tab/extension.js
+extensions/alternate-tab/org.gnome.shell.extensions.alternate-tab.gschema.xml.in
+extensions/alternate-tab/prefs.js
 extensions/alternative-status-menu/extension.js
 extensions/alternative-status-menu/org.gnome.shell.extensions.alternative-status-menu.gschema.xml.in
 extensions/apps-menu/extension.js



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]