[ Avaa Bypassed ]




Upload:

Command:

www-data@18.191.137.190: ~ $
/* Desktop Icons GNOME Shell extension
 *
 * Copyright (C) 2017 Carlos Soriano <csoriano@redhat.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

const Gtk = imports.gi.Gtk;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const St = imports.gi.St;
const Pango = imports.gi.Pango;
const Meta = imports.gi.Meta;
const GdkPixbuf = imports.gi.GdkPixbuf;
const Cogl = imports.gi.Cogl;
const GnomeDesktop = imports.gi.GnomeDesktop;

const Mainloop = imports.mainloop;

const Config = imports.misc.config;
const Background = imports.ui.background;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const Util = imports.misc.util;

const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Extension = Me.imports.extension;
const Prefs = Me.imports.prefs;
const DBusUtils = Me.imports.dbusUtils;
const DesktopIconsUtil = Me.imports.desktopIconsUtil;

const Gettext = imports.gettext.domain('desktop-icons');

const _ = Gettext.gettext;

const DRAG_TRESHOLD = 8;

var S_IXUSR = 0o00100;
var S_IWOTH = 0o00002;

var State = {
    NORMAL: 0,
    GONE: 1,
};

var FileItem = GObject.registerClass({
    GTypeName: 'DesktopIcons_FileItem',
    Signals: {
        'rename-clicked': {},
        'selected': {
            param_types: [GObject.TYPE_BOOLEAN, GObject.TYPE_BOOLEAN, GObject.TYPE_BOOLEAN]
        }
    }
}, class FileItem extends St.Bin {
    _init(file, fileInfo, fileExtra) {
        super._init({ visible: true });

        this._fileExtra = fileExtra;
        this._loadThumbnailDataCancellable = null;
        this._thumbnailScriptWatch = 0;
        this._setMetadataCancellable = null;
        this._queryFileInfoCancellable = null;
        this._isSpecial = this._fileExtra != Prefs.FileType.NONE;
        this._lastClickTime = 0;
        this._lastClickButton = 0;
        this._clickCount = 0;

        this._file = file;

        this._savedCoordinates = null;
        let savedCoordinates = fileInfo.get_attribute_as_string('metadata::nautilus-icon-position');
        if (savedCoordinates != null)
            this._savedCoordinates = savedCoordinates.split(',').map(x => Number(x));

        this._state = State.NORMAL;

        this.set_fill(true, true);
        let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
        this._delegate = this;
        this.connect('destroy', () => this._onDestroy());

        this._container = new St.BoxLayout({ reactive: true,
                                             track_hover: true,
                                             can_focus: true,
                                             style_class: 'file-item',
                                             x_expand: true,
                                             y_expand: true,
                                             x_align: Clutter.ActorAlign.FILL,
                                             vertical: true });
        this.set_child(this._container);
        this._icon = new St.Bin();
        this._icon.set_height(Prefs.get_icon_size() * scaleFactor);
        this._iconAllocationIdleId = 0;
        this._iconAllocationId = this._icon.connect("allocation-changed", () => {
            if (this._iconAllocationIdleId)
                GLib.source_remove(this._iconAllocationIdleId);
            this._iconAllocationIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
                GLib.source_remove(this._iconAllocationIdleId);
                this._iconAllocationIdleId = 0;
                this._updateIcon();
                return GLib.SOURCE_REMOVE;
            });
        });

        this._iconContainer = new St.Bin({ visible: true });
        this._iconContainer.child = this._icon;
        this._container.add_child(this._iconContainer);

        this._label = new St.Label({
            style_class: 'name-label'
        });

        this._container.add_child(this._label);
        let clutterText = this._label.get_clutter_text();
        /* TODO: Convert to gobject.set for 3.30 */
        clutterText.set_line_wrap(true);
        clutterText.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR);
        clutterText.set_ellipsize(Pango.EllipsizeMode.END);

        this._container.connect('button-press-event', (actor, event) => this._onPressButton(actor, event));
        this._container.connect('motion-event', (actor, event) => this._onMotion(actor, event));
        this._container.connect('leave-event', (actor, event) => this._onLeave(actor, event));
        this._container.connect('enter-event', (actor, event) => this._onEnter(actor, event));
        this._container.connect('button-release-event', (actor, event) => this._onReleaseButton(actor, event));

        /* Set the metadata and update relevant UI */
        this._updateMetadataFromFileInfo(fileInfo);

        this._menuManager = null;
        this._menu = null;
        this._updateIcon();

        this._isSelected = false;
        this._primaryButtonPressed = false;
        if (this._attributeCanExecute && !this._isValidDesktopFile)
            this._execLine = this.file.get_path();
        if (fileExtra == Prefs.FileType.USER_DIRECTORY_TRASH) {
            // if this icon is the trash, monitor the state of the directory to update the icon
            this._trashChanged = false;
            this._queryTrashInfoCancellable = null;
            this._scheduleTrashRefreshId = 0;
            this._monitorTrashDir = this._file.monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, null);
            this._monitorTrashId = this._monitorTrashDir.connect('changed', (obj, file, otherFile, eventType) => {
                switch(eventType) {
                    case Gio.FileMonitorEvent.DELETED:
                    case Gio.FileMonitorEvent.MOVED_OUT:
                    case Gio.FileMonitorEvent.CREATED:
                    case Gio.FileMonitorEvent.MOVED_IN:
                        if (this._queryTrashInfoCancellable || this._scheduleTrashRefreshId) {
                            if (this._scheduleTrashRefreshId)
                                GLib.source_remove(this._scheduleTrashRefreshId);
                            this._scheduleTrashRefreshId = Mainloop.timeout_add(200, () => this._refreshTrashIcon());
                        } else {
                            this._refreshTrashIcon();
                        }
                    break;
                }
            });
        }

        this._writebleByOthersId = Extension.desktopManager.connect('notify::writable-by-others', () => {
            if (!this._isValidDesktopFile)
                return;
            this._refreshMetadataAsync(true);
        });
    }

    set_margins(width, height) {
        let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
        this.set_width(Prefs.getDesiredWidth(scaleFactor, width));
        this.set_height(Prefs.getDesiredHeight(scaleFactor, height));
    }

    onAttributeChanged() {
        this._refreshMetadataAsync(this._isDesktopFile);
    }

    _onDestroy() {
        /* Regular file data */
        if (this._setMetadataCancellable)
            this._setMetadataCancellable.cancel();
        if (this._queryFileInfoCancellable)
            this._queryFileInfoCancellable.cancel();

        Extension.desktopManager.disconnect(this._writebleByOthersId);

        /* Thumbnailing */
        if (this._thumbnailScriptWatch)
            GLib.source_remove(this._thumbnailScriptWatch);
        if (this._loadThumbnailDataCancellable)
            this._loadThumbnailDataCancellable.cancel();

        /* Desktop file */
        if (this._monitorDesktopFileId) {
            this._monitorDesktopFile.disconnect(this._monitorDesktopFileId);
            this._monitorDesktopFile.cancel();
        }

        /* Trash */
        if (this._monitorTrashDir) {
            this._monitorTrashDir.disconnect(this._monitorTrashId);
            this._monitorTrashDir.cancel();
        }
        if (this._queryTrashInfoCancellable)
            this._queryTrashInfoCancellable.cancel();
        if (this._scheduleTrashRefreshId)
            GLib.source_remove(this._scheduleTrashRefreshId);

        /* Icon */
        this._icon.disconnect(this._iconAllocationId);
        if (this._iconAllocationIdleId)
            GLib.source_remove(this._iconAllocationIdleId);

        /* Menu */
        this._removeMenu();
    }

    _refreshMetadataAsync(rebuild) {
        if (this._queryFileInfoCancellable)
            this._queryFileInfoCancellable.cancel();
        this._queryFileInfoCancellable = new Gio.Cancellable();
        this._file.query_info_async(DesktopIconsUtil.DEFAULT_ATTRIBUTES,
                                    Gio.FileQueryInfoFlags.NONE,
                                    GLib.PRIORITY_DEFAULT,
                                    this._queryFileInfoCancellable,
            (source, result) => {
                try {
                    let newFileInfo = source.query_info_finish(result);
                    this._queryFileInfoCancellable = null;
                    this._updateMetadataFromFileInfo(newFileInfo);
                    if (rebuild)
                        this._recreateMenu();
                    this._updateIcon();
                } catch(error) {
                    if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
                        global.log("Error getting the file info: " + error);
                }
            });
    }

    _updateMetadataFromFileInfo(fileInfo) {
        this._fileInfo = fileInfo;

        let oldLabelText = this._label.text;

        this._displayName = fileInfo.get_attribute_as_string('standard::display-name');
        this._attributeCanExecute = fileInfo.get_attribute_boolean('access::can-execute');
        this._unixmode = fileInfo.get_attribute_uint32('unix::mode');
        this._writableByOthers = (this._unixmode & S_IWOTH) != 0;
        this._trusted = fileInfo.get_attribute_as_string('metadata::trusted') == 'true';
        this._attributeContentType = fileInfo.get_content_type();
        this._isDesktopFile = this._attributeContentType == 'application/x-desktop';

        if (this._isDesktopFile && this._writableByOthers)
            log(`desktop-icons: File ${this._displayName} is writable by others - will not allow launching`);

        if (this._isDesktopFile) {
            this._desktopFile = Gio.DesktopAppInfo.new_from_filename(this._file.get_path());
            if (!this._desktopFile) {
                log(`Couldn’t parse ${this._displayName} as a desktop file, will treat it as a regular file.`);
                this._isValidDesktopFile = false;
            } else {
                this._isValidDesktopFile = true;
            }
        } else {
            this._isValidDesktopFile = false;
        }

        if (this.displayName != oldLabelText) {
            this._label.text = this.displayName;
        }

        this._fileType = fileInfo.get_file_type();
        this._isDirectory = this._fileType == Gio.FileType.DIRECTORY;
        this._isSpecial = this._fileExtra != Prefs.FileType.NONE;
        this._isHidden = fileInfo.get_is_hidden() | fileInfo.get_is_backup();
        this._isSymlink = fileInfo.get_is_symlink();
        this._modifiedTime = this._fileInfo.get_attribute_uint64("time::modified");
        /*
         * This is a glib trick to detect broken symlinks. If a file is a symlink, the filetype
         * points to the final file, unless it is broken; thus if the file type is SYMBOLIC_LINK,
         * it must be a broken link.
         * https://developer.gnome.org/gio/stable/GFile.html#g-file-query-info
         */
        this._isBrokenSymlink = this._isSymlink && this._fileType == Gio.FileType.SYMBOLIC_LINK;
    }

    onFileRenamed(file) {
        this._file = file;
        this._refreshMetadataAsync(false);
    }

    _updateIcon() {
        if (this._fileExtra == Prefs.FileType.USER_DIRECTORY_TRASH) {
            this._icon.child = this._createEmblemedStIcon(this._fileInfo.get_icon(), null);
            return;
        }

        let thumbnailFactory = GnomeDesktop.DesktopThumbnailFactory.new(GnomeDesktop.DesktopThumbnailSize.LARGE);
        if ((Prefs.nautilusSettings.get_string('show-image-thumbnails') != 'never') &&
            (thumbnailFactory.can_thumbnail(this._file.get_uri(),
                                            this._attributeContentType,
                                            this._modifiedTime))) {
            let thumbnail = thumbnailFactory.lookup(this._file.get_uri(), this._modifiedTime);
            if (thumbnail == null) {
                if (!thumbnailFactory.has_valid_failed_thumbnail(this._file.get_uri(),
                                                                 this._modifiedTime)) {
                    let argv = [];
                    argv.push(GLib.build_filenamev([ExtensionUtils.getCurrentExtension().path,
                                                   'createThumbnail.js']));
                    argv.push(this._file.get_path());
                    let [success, pid] = GLib.spawn_async(null, argv, null,
                                                          GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, null);
                    if (this._thumbnailScriptWatch)
                        GLib.source_remove(this._thumbnailScriptWatch);
                    this._thumbnailScriptWatch = GLib.child_watch_add(GLib.PRIORITY_DEFAULT,
                                                                      pid,
                        (pid, exitCode) => {
                            this._thumbnailScriptWatch = 0;
                            if (exitCode == 0)
                                this._updateIcon();
                            else
                                global.log('Failed to generate thumbnail for ' + this._filePath);
                            GLib.spawn_close_pid(pid);
                            return false;
                        }
                    );
                }
            } else {
                if (this._loadThumbnailDataCancellable)
                    this._loadThumbnailDataCancellable.cancel();
                this._loadThumbnailDataCancellable = new Gio.Cancellable();
                let thumbnailFile = Gio.File.new_for_path(thumbnail);
                thumbnailFile.load_bytes_async(this._loadThumbnailDataCancellable,
                    (source, result) => {
                        try {
                            this._loadThumbnailDataCancellable = null;
                            let [thumbnailData, etag_out] = source.load_bytes_finish(result);
                            let thumbnailStream = Gio.MemoryInputStream.new_from_bytes(thumbnailData);
                            let thumbnailPixbuf = GdkPixbuf.Pixbuf.new_from_stream(thumbnailStream, null);

                            if (thumbnailPixbuf != null) {
                                let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
                                let thumbnailImage = new Clutter.Image();
                                thumbnailImage.set_data(thumbnailPixbuf.get_pixels(),
                                                        thumbnailPixbuf.has_alpha ? Cogl.PixelFormat.RGBA_8888 : Cogl.PixelFormat.RGB_888,
                                                        thumbnailPixbuf.width,
                                                        thumbnailPixbuf.height,
                                                        thumbnailPixbuf.rowstride
                                );
                                let icon = new Clutter.Actor();
                                icon.set_content(thumbnailImage);
                                let containerWidth = (this._icon.allocation.x2 - this._icon.allocation.x1) * scaleFactor;
                                let containerHeight = Prefs.get_icon_size() * scaleFactor;
                                let containerAspectRatio = containerWidth / containerHeight;
                                let iconAspectRatio = thumbnailPixbuf.width / thumbnailPixbuf.height;
                                if (containerAspectRatio > iconAspectRatio) {
                                    let iconWidth = containerHeight * iconAspectRatio;
                                    icon.set_size(iconWidth, containerHeight);
                                    let margin = (containerWidth - iconWidth) / 2;
                                    icon.margin_left = Math.ceil(margin);
                                    icon.margin_right = Math.floor(margin);
                                } else {
                                    let iconHeight = containerWidth / iconAspectRatio;
                                    icon.set_size(containerWidth, iconHeight);
                                    let margin = (containerHeight - iconHeight) / 2;
                                    icon.margin_top = Math.ceil(margin);
                                    icon.margin_bottom = Math.floor(margin);
                                }
                                this._icon.child = icon;
                            }
                        } catch (error) {
                            if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
                                global.log('Error while loading thumbnail: ' + error);
                                this._icon.child = this._createEmblemedStIcon(this._fileInfo.get_icon(), null);
                            }
                        }
                    }
                );
            }
        }

        if (this._isBrokenSymlink) {
            this._icon.child = this._createEmblemedStIcon(null, 'text-x-generic');
        } else {
            if (this.trustedDesktopFile && this._desktopFile.has_key('Icon'))
                this._icon.child = this._createEmblemedStIcon(null, this._desktopFile.get_string('Icon'));
            else
                this._icon.child = this._createEmblemedStIcon(this._fileInfo.get_icon(), null);
        }
    }

    _refreshTrashIcon() {
        if (this._queryTrashInfoCancellable)
            this._queryTrashInfoCancellable.cancel();
        this._queryTrashInfoCancellable = new Gio.Cancellable();

        this._file.query_info_async(DesktopIconsUtil.DEFAULT_ATTRIBUTES,
                                    Gio.FileQueryInfoFlags.NONE,
                                    GLib.PRIORITY_DEFAULT,
                                    this._queryTrashInfoCancellable,
            (source, result) => {
                try {
                    this._fileInfo = source.query_info_finish(result);
                    this._queryTrashInfoCancellable = null;
                    this._updateIcon();
                } catch(error) {
                    if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
                        global.log('Error getting the number of files in the trash: ' + error);
                }
            });

        this._scheduleTrashRefreshId = 0;
        return false;
    }

    get file() {
        return this._file;
    }

    get isHidden() {
        return this._isHidden;
    }

    _createEmblemedStIcon(icon, iconName) {
        if (icon == null) {
            if (GLib.path_is_absolute(iconName)) {
                let iconFile = Gio.File.new_for_commandline_arg(iconName);
                icon = new Gio.FileIcon({ file: iconFile });
            } else {
                icon = Gio.ThemedIcon.new_with_default_fallbacks(iconName);
            }
        }
        let itemIcon = Gio.EmblemedIcon.new(icon, null);

        if (this._isSymlink) {
            if (this._isBrokenSymlink)
                itemIcon.add_emblem(Gio.Emblem.new(Gio.ThemedIcon.new('emblem-unreadable')));
            else
                itemIcon.add_emblem(Gio.Emblem.new(Gio.ThemedIcon.new('emblem-symbolic-link')));
        } else if (this.trustedDesktopFile) {
            itemIcon.add_emblem(Gio.Emblem.new(Gio.ThemedIcon.new('emblem-symbolic-link')));
        }

        return new St.Icon({ gicon: itemIcon,
                             icon_size: Prefs.get_icon_size()
        });
    }

    doRename() {
        if (!this.canRename()) {
            log (`Error: ${this.file.get_uri()} cannot be renamed`);
            return;
        }

        this.emit('rename-clicked');
    }

    doOpen() {
        if (this._isBrokenSymlink) {
            log(`Error: Can’t open ${this.file.get_uri()} because it is a broken symlink.`);
            return;
        }

        if (this.trustedDesktopFile) {
            this._desktopFile.launch_uris_as_manager([], null, GLib.SpawnFlags.SEARCH_PATH, null, null);
            return;
        }

        if (this._attributeCanExecute &&
           !this._isDirectory &&
           !this._isValidDesktopFile &&
            Gio.content_type_can_be_executable(this._attributeContentType)) {
                if (this._execLine)
                    Util.spawnCommandLine(this._execLine);
                return;
        }

        Gio.AppInfo.launch_default_for_uri_async(this.file.get_uri(),
            null, null,
            (source, result) => {
                try {
                    Gio.AppInfo.launch_default_for_uri_finish(result);
                } catch (e) {
                    log('Error opening file ' + this.file.get_uri() + ': ' + e.message);
                }
            }
        );
    }

    _onCopyClicked() {
        Extension.desktopManager.doCopy();
    }

    _onCutClicked() {
        Extension.desktopManager.doCut();
    }

    _onShowInFilesClicked() {

        DBusUtils.FreeDesktopFileManagerProxy.ShowItemsRemote([this.file.get_uri()], '',
            (result, error) => {
                if (error)
                    log('Error showing file on desktop: ' + error.message);
            }
        );
    }

    _onPropertiesClicked() {

        DBusUtils.FreeDesktopFileManagerProxy.ShowItemPropertiesRemote([this.file.get_uri()], '',
            (result, error) => {
                if (error)
                    log('Error showing properties: ' + error.message);
            }
        );
    }

    _onMoveToTrashClicked() {
        Extension.desktopManager.doTrash();
    }

    _onEmptyTrashClicked() {
        Extension.desktopManager.doEmptyTrash();
    }

    get _allowLaunchingText() {
        if (this.trustedDesktopFile)
            return _("Don’t Allow Launching");

        return _("Allow Launching");
    }

    get metadataTrusted() {
        return this._trusted;
    }

    set metadataTrusted(value) {
        this._trusted = value;

        let info = new Gio.FileInfo();
        info.set_attribute_string('metadata::trusted',
                                  value ? 'true' : 'false');
        this._file.set_attributes_async(info,
                                        Gio.FileQueryInfoFlags.NONE,
                                        GLib.PRIORITY_LOW,
                                        null,
            (source, result) => {
                try {
                    source.set_attributes_finish(result);
                    this._refreshMetadataAsync(true);
                } catch(e) {
                    log(`Failed to set metadata::trusted: ${e.message}`);
                }
        });
    }

    _onAllowDisallowLaunchingClicked() {
        this.metadataTrusted = !this.trustedDesktopFile;

        /*
         * we're marking as trusted, make the file executable too. note that we
         * do not ever remove the executable bit, since we don't know who set
         * it.
         */
        if (this.metadataTrusted && !this._attributeCanExecute) {
            let info = new Gio.FileInfo();
            let newUnixMode = this._unixmode | S_IXUSR;
            info.set_attribute_uint32(Gio.FILE_ATTRIBUTE_UNIX_MODE, newUnixMode);
            this._file.set_attributes_async(info,
                                            Gio.FileQueryInfoFlags.NONE,
                                            GLib.PRIORITY_LOW,
                                            null,
                (source, result) => {
                    try {
                        source.set_attributes_finish (result);
                    } catch(e) {
                        log(`Failed to set unix mode: ${e.message}`);
                    }
            });
        }
    }

    canRename() {
        return !this.trustedDesktopFile && this._fileExtra == Prefs.FileType.NONE;
    }

    _doOpenWith() {
        DBusUtils.openFileWithOtherApplication(this.file.get_path());
    }

    _getSelectionStyle() {
        let rgba = DesktopIconsUtil.getGtkClassBackgroundColor('view', Gtk.StateFlags.SELECTED);
        let background_color =
            'rgba(' + rgba.red * 255 + ', ' + rgba.green * 255 + ', ' + rgba.blue * 255 + ', 0.6)';
        let border_color =
            'rgba(' + rgba.red * 255 + ', ' + rgba.green * 255 + ', ' + rgba.blue * 255 + ', 0.8)';

        return 'background-color: ' + background_color + ';' +
               'border-color: ' + border_color + ';';
    }

    get menu() {
        return this._menu;
    }

    _removeMenu() {
        if (this._menu != null) {
            if (this._menuManager != null)
                this._menuManager.removeMenu(this._menu);

            Main.layoutManager.uiGroup.remove_child(this._menu.actor);
            this._menu.destroy();
            this._menu = null;
        }

        this._menuManager = null;
    }

    _recreateMenu() {
        this._removeMenu();
        this._menuManager = new PopupMenu.PopupMenuManager(this);
        let side = St.Side.LEFT;
        if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
            side = St.Side.RIGHT;
        this._menu = new PopupMenu.PopupMenu(this, 0.5, side);
        this._menu.addAction(_('Open'), () => this.doOpen());
        switch (this._fileExtra) {
        case Prefs.FileType.NONE:
            if (!this._isDirectory)
                this._actionOpenWith = this._menu.addAction(_('Open With Other Application'), () => this._doOpenWith());
            else
                this._actionOpenWith = null;
            this._menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
            this._actionCut = this._menu.addAction(_('Cut'), () => this._onCutClicked());
            this._actionCopy = this._menu.addAction(_('Copy'), () => this._onCopyClicked());
            if (this.canRename())
                this._menu.addAction(_('Rename…'), () => this.doRename());
            this._actionTrash = this._menu.addAction(_('Move to Trash'), () => this._onMoveToTrashClicked());
            if (this._isValidDesktopFile && !Extension.desktopManager.writableByOthers && !this._writableByOthers) {
                this._menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
                this._allowLaunchingMenuItem = this._menu.addAction(this._allowLaunchingText,
                                                                    () => this._onAllowDisallowLaunchingClicked());

            }
            break;
        case Prefs.FileType.USER_DIRECTORY_TRASH:
            this._menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
            this._menu.addAction(_('Empty Trash'), () => this._onEmptyTrashClicked());
            break;
        default:
            break;
        }
        this._menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
        this._menu.addAction(_('Properties'), () => this._onPropertiesClicked());
        this._menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
        this._menu.addAction(_('Show in Files'), () => this._onShowInFilesClicked());
        if (this._isDirectory && this.file.get_path() != null)
            this._actionOpenInTerminal = this._menu.addAction(_('Open in Terminal'), () => this._onOpenTerminalClicked());

        this._menuManager.addMenu(this._menu);

        Main.layoutManager.uiGroup.add_child(this._menu.actor);
        this._menu.actor.hide();
    }

    _ensureMenu() {
        if (this._menu == null)
            this._recreateMenu();

        return this._menu;
    }

    _onOpenTerminalClicked () {
        DesktopIconsUtil.launchTerminal(this.file.get_path());
    }

    _updateClickState(event) {
        let settings = Clutter.Settings.get_default();
        if ((event.get_button() == this._lastClickButton) &&
            ((event.get_time() - this._lastClickTime) < settings.double_click_time))
            this._clickCount++;
        else
            this._clickCount = 1;

        this._lastClickTime = event.get_time();
        this._lastClickButton = event.get_button();
    }

    _getClickCount() {
        return this._clickCount;
    }

    _onPressButton(actor, event) {
        this._updateClickState(event);
        let button = event.get_button();
        if (button == 3) {
            if (!this.isSelected)
                this.emit('selected', false, false, true);
            this._ensureMenu().toggle();
            if (this._actionOpenWith) {
                let allowOpenWith = (Extension.desktopManager.getNumberOfSelectedItems() == 1);
                this._actionOpenWith.setSensitive(allowOpenWith);
            }
            let specialFilesSelected = Extension.desktopManager.checkIfSpecialFilesAreSelected();
            if (this._actionCut)
                this._actionCut.setSensitive(!specialFilesSelected);
            if (this._actionCopy)
                this._actionCopy.setSensitive(!specialFilesSelected);
            if (this._actionTrash)
                this._actionTrash.setSensitive(!specialFilesSelected);
            return Clutter.EVENT_STOP;
        } else if (button == 1) {
            if (this._getClickCount() == 1) {
                let [x, y] = event.get_coords();
                this._primaryButtonPressed = true;
                this._buttonPressInitialX = x;
                this._buttonPressInitialY = y;
                let shiftPressed = !!(event.get_state() & Clutter.ModifierType.SHIFT_MASK);
                let controlPressed = !!(event.get_state() & Clutter.ModifierType.CONTROL_MASK);
                if (controlPressed || shiftPressed)
                    this.emit('selected', true, false, !this._isSelected);
                else
                    this.emit('selected', false, false, true);
            }
            return Clutter.EVENT_STOP;
        }

        return Clutter.EVENT_PROPAGATE;
    }

    _onEnter(actor, event) {
        if (Prefs.CLICK_POLICY_SINGLE)
            global.display.set_cursor(Meta.Cursor.POINTING_HAND);
        else
            global.display.set_cursor(Meta.Cursor.DEFAULT);
    }

    _onLeave(actor, event) {
        this._primaryButtonPressed = false;
        if (Prefs.CLICK_POLICY_SINGLE)
           global.display.set_cursor(Meta.Cursor.DEFAULT);
    }

    _onMotion(actor, event) {
        let [x, y] = event.get_coords();
        if (this._primaryButtonPressed) {
            let xDiff = x - this._buttonPressInitialX;
            let yDiff = y - this._buttonPressInitialY;
            let distance = Math.sqrt(Math.pow(xDiff, 2) + Math.pow(yDiff, 2));
            if (distance > DRAG_TRESHOLD) {
                // Don't need to track anymore this if we start drag, and also
                // avoids reentrance here
                this._primaryButtonPressed = false;
                let event = Clutter.get_current_event();
                let [x, y] = event.get_coords();
                Extension.desktopManager.dragStart();
            }
        }

        return Clutter.EVENT_PROPAGATE;
    }

    _onReleaseButton(actor, event) {
        let button = event.get_button();
        if (button == 1) {
            // primaryButtonPressed is TRUE only if the user has pressed the button
            // over an icon, and if (s)he has not started a drag&drop operation
            if (this._primaryButtonPressed) {
                this._primaryButtonPressed = false;
                let shiftPressed = !!(event.get_state() & Clutter.ModifierType.SHIFT_MASK);
                let controlPressed = !!(event.get_state() & Clutter.ModifierType.CONTROL_MASK);
                if ((this._getClickCount() == 1) && Prefs.CLICK_POLICY_SINGLE && !shiftPressed && !controlPressed)
                    this.doOpen();
                return Clutter.EVENT_STOP;
            }
            if ((this._getClickCount() == 2) && (!Prefs.CLICK_POLICY_SINGLE))
                this.doOpen();
        }
        return Clutter.EVENT_PROPAGATE;
    }

    get savedCoordinates() {
        return this._savedCoordinates;
    }

    _onSetMetadataFileFinished(source, result) {
        try {
            let [success, info] = source.set_attributes_finish(result);
        } catch (error) {
            if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
                log('Error setting metadata to desktop files ', error);
        }
    }

    set savedCoordinates(pos) {
        if (this._setMetadataCancellable)
            this._setMetadataCancellable.cancel();

        this._setMetadataCancellable = new Gio.Cancellable();
        this._savedCoordinates = [pos[0], pos[1]];
        let info = new Gio.FileInfo();
        info.set_attribute_string('metadata::nautilus-icon-position',
                                  `${pos[0]},${pos[1]}`);
        this.file.set_attributes_async(info,
                                       Gio.FileQueryInfoFlags.NONE,
                                       GLib.PRIORITY_DEFAULT,
                                       this._setMetadataCancellable,
            (source, result) => {
                this._setMetadataCancellable = null;
                this._onSetMetadataFileFinished(source, result);
            }
        );
    }

    intersectsWith(argX, argY, argWidth, argHeight) {
        let rect = new Meta.Rectangle({ x: argX, y: argY, width: argWidth, height: argHeight });
        let [containerX, containerY] = this._container.get_transformed_position();
        let boundingBox = new Meta.Rectangle({ x: containerX,
                                               y: containerY,
                                               width: this._container.allocation.x2 - this._container.allocation.x1,
                                               height: this._container.allocation.y2 - this._container.allocation.y1 });
        let [intersects, _] = rect.intersect(boundingBox);

        return intersects;
    }

    set isSelected(isSelected) {
        isSelected = !!isSelected;
        if (isSelected == this._isSelected)
            return;

        if (isSelected) {
            this._container.set_style(this._getSelectionStyle());
        } else {
            this._container.set_style('background-color: transparent');
            this._container.set_style('border-color: transparent');
        }

        this._isSelected = isSelected;
    }

    get isSelected() {
        return this._isSelected;
    }

    get isSpecial() {
        return this._isSpecial;
    }

    get state() {
        return this._state;
    }

    set state(state) {
        if (state == this._state)
            return;

        this._state = state;
    }

    get isDirectory() {
        return this._isDirectory;
    }

    get trustedDesktopFile() {
        return this._isValidDesktopFile &&
               this._attributeCanExecute &&
               this.metadataTrusted &&
               !Extension.desktopManager.writableByOthers &&
               !this._writableByOthers;
    }

    get fileName() {
        return this._fileInfo.get_name();
    }

    get displayName() {
        if (this.trustedDesktopFile)
            return this._desktopFile.get_name();

        return this._displayName || null;
    }

    acceptDrop() {
        return Extension.desktopManager.selectionDropOnFileItem(this);
    }
});

Filemanager

Name Type Size Permission Actions
createFolderDialog.js File 6.13 KB 0644
createThumbnail.js File 1.45 KB 0755
dbusUtils.js File 3.74 KB 0644
desktopGrid.js File 25.46 KB 0644
desktopIconsUtil.js File 4.66 KB 0644
desktopManager.js File 27.92 KB 0644
extension.js File 2.44 KB 0644
fileItem.js File 35.64 KB 0644
metadata.json File 150 B 0644
prefs.js File 5.96 KB 0644
stylesheet.css File 694 B 0644