Review of "Kiwi is not Apple" version 1.6.1 (42)

Details Page Preview

Kiwi is free open source project that brings macOS-inspired features for GNOME. *Note. This extension is tested with vanilla GNOME Adwaita theme. Be aware that other extensions may cause compatibility issues. Features: - macOS-style window control buttons with GTK theming - Firefox and Thunderbird window control theming - Move fullscreen windows to new workspaces automatically - Make windows transparent while moving - Display battery percentage when below 20% - Move calendar to the right side and customize notifications - Quick settings media and notifications tweaks - Show current window title in the top panel - Show panel on hover in fullscreen mode - Hide minimized windows in overview - Hide the Activities button - Skip overview on login (go directly to desktop) - Set panel transparency or blur based on window position - Dash-to-dock blur effect - Overview wallpaper blur - Keyboard indicator styling - Focus on newly launched windows (removes window-ready notifications) - Show Caps Lock/Num Lock indicators in the top panel - Add username display to the quick settings menu - Multilingual support and more... This extension uses a modular architecture for stability and customization. Some advanced features require native libraries (available in the advanced/ folder). Disclaimer: This extension is unofficial and not affiliated with Apple in any way.

Extension Homepage
https://github.com/kem-a/kiwi-kemma

No comments.

Diff Against

Files

Note: Binary files aren't shown on the web site. To see all files, please download the extension zipfile.

Shexli (experimental) error 2 warning 5

Shexli found 7 issues that may need reviewer attention.

EGO015 warning

signals connected by extension should be disconnected in disable()

Signals assigned in `enable()` are missing matching disconnect calls in `disable()` or its helper methods.

Disconnect all signals

  • apps/batteryPercentage.js:94
                            this._propertiesChangedId = this._batteryProxy.connect('g-properties-changed', () => {
                                this._updateBatteryPercentage();
                            })
  • apps/windowControls.js:84
            this._box.connect('leave-event', () => {
                this._isContainerHovered = false;
                this._updateAllIcons();
                return Clutter.EVENT_PROPAGATE;
            })
  • apps/windowControls.js:75
            this._box.connect('motion-event', () => {
                if (this._suppressHoverUntilPointerMove) {
                    this._suppressHoverUntilPointerMove = false;
                    this._updateAllIcons();
                }
                return Clutter.EVENT_PROPAGATE;
            })
  • apps/windowControls.js:149
            this._closeButton.connect('clicked', () => {
                const window = global.display.focus_window;
                if (window) window.delete(global.get_current_time());
            })
  • apps/windowControls.js:124
            this._maximizeButton.connect('clicked', () => {
                const window = global.display.focus_window;
                if (window) {
                    if (window.is_fullscreen()) {
                        window.unmake_fullscreen();
                    } else if (window.maximized_horizontally && window.m
  • apps/windowControls.js:119
            this._minimizeButton.connect('clicked', () => {
                const window = global.display.focus_window;
                if (window) window.minimize();
            })
  • apps/windowControls.js:93
                button.connect('button-press-event', () => {
                    button.add_style_pseudo_class('active');
                    this._updateButtonIcon(buttonType);
                })
  • apps/windowControls.js:97
                button.connect('button-release-event', () => {
                    button.remove_style_pseudo_class('active');
                    this._updateButtonIcon(buttonType);
                })
  • apps/windowControls.js:102
                button.connect('enter-event', () => {
                    if (this._suppressHoverUntilPointerMove) {
                        this._suppressHoverUntilPointerMove = false;
                    }
                    if (this._useMacosIcons) {
                        this._isContainerHovered = true;
                
  • apps/windowControls.js:111
                button.connect('leave-event', () => {
                    if (this._useMacosIcons) {
                        this._isContainerHovered = false;
                        this._updateAllIcons();
                    }
                })
  • apps/windowControls.js:92
    button.connect('notify::hover', () => this._updateButtonIcon(buttonType))
  • apps/windowTitle.js:54
            this._menu.connect('open-state-changed', (menu, isOpen) => {
                if (isOpen) {
                    this._updateRestoreMenuItem();
                    GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
                        this._syncMenuAlignment();
                        return GLib.SOURCE_REMOVE;
       

EGO014 warning

objects created by extension should be destroyed in disable()

Objects assigned in `enable()` are missing matching `.destroy()` calls in `disable()` or its helper methods.

Destroy all objects

  • apps/batteryPercentage.js:15
            this._batteryLabel = new St.Label({
                style_class: 'battery-percentage-label',
                text: '',
                opacity: 0,
                y_align: Clutter.ActorAlign.CENTER
            })

EGO027 warning

owned object references should be released in disable()

Owned references that are cleaned up in `disable()` should also be released with `null` or `undefined`.

Destroy all objects

  • apps/batteryPercentage.js:15
            this._batteryLabel = new St.Label({
                style_class: 'battery-percentage-label',
                text: '',
                opacity: 0,
                y_align: Clutter.ActorAlign.CENTER
            })

EGO030 warning

extensions should avoid synchronous file IO in shell code

Shell code should avoid synchronous file IO APIs like `GLib.file_get_contents()` and `Gio.File.load_contents()`.

File Operations

  • apps/mozillaThemeManager.js:278
    file.load_contents(null)
  • apps/overviewWallpaper.js:110
    file.load_contents(null)
  • apps/overviewWallpaper.js:151
    file.load_contents(null)

EGO-C49-003 error

extensions targeting GNOME 49 must not call maximize or unmaximize with Meta.MaximizeFlags

This extension explicitly targets GNOME Shell 49 but still passes `Meta.MaximizeFlags` to `maximize()` or `unmaximize()`.

Meta.Window

  • apps/windowControls.js:135
    window.unmaximize(Meta.MaximizeFlags.BOTH)
  • apps/windowControls.js:143
    window.maximize(Meta.MaximizeFlags.BOTH)
  • apps/windowTitle.js:199
    win.unmaximize(Meta.MaximizeFlags.BOTH)

EGO-C49-004 error

extensions targeting GNOME 49 must not call Meta.Window.get_maximized

This extension explicitly targets GNOME Shell 49 but still calls removed `Meta.Window.get_maximized()`.

Meta.Window

  • apps/windowControls.js:302
    win.get_maximized()
  • apps/windowControls.js:363
    focusWindow.get_maximized()
  • apps/windowTitle.js:174
    win.get_maximized()

EGO016 warning

main loop sources should be removed in disable()

Main loop sources assigned in `enable()` are missing matching removals in `disable()` or its helper methods.

Remove main loop sources

  • apps/windowTitle.js:151
            GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
                this._syncMenuAlignment();
                return GLib.SOURCE_REMOVE;
            })
  • apps/windowTitle.js:57
                    GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
                        this._syncMenuAlignment();
                        return GLib.SOURCE_REMOVE;
                    })

All Versions

Version Status
1.6.2 (43) Active
1.6.1 (42) Rejected
1.5.5 (41) Active
1.5.5 (40) Rejected
1.5.5 (39) Rejected
1.5.4 (38) Inactive
1.5.4 (37) Rejected
1.5.3 (36) Active
1.5.3 (35) Rejected
1.5.2 (34) Active
1.5.1 (33) Active
1.5.0 (32) Inactive
1.4.1 (31) Active
1.4.1 (30) Rejected
1.4.0 (29) Active
1.4.0 (28) Rejected
1.3.1 (27) Active
1.3.0 (26) Active
1.2.1 (25) Active
1.2.1 (24) Rejected
1.2.0 (23) Active
1.1.0 (22) Active
1.0.2 (21) Inactive
1.0.1 (20) Inactive
1.0.0 (19) Inactive
18 Inactive
17 Inactive
16 Rejected
15 Inactive
0.9.6 beta (14) Rejected
13 Inactive
12 Inactive
11 Inactive
10 Inactive
9 Inactive
8 Inactive
7 Rejected
6 Inactive
5 Rejected
4 Inactive
3 Rejected
2 Inactive
1 Rejected

Previous Reviews on this Version

Arnis K posted a review
EGO014 and EGO027 are false positives EGO-C49-004 and EGO-C49-003 flags compatibility fallbacks as errors. The code is already properly structured for multi-version support, with one minor exception in windowTitle.js.
Arnis K auto- rejected
Auto-rejected because of new version 1.6.2 (43) was uploaded