Compare commits
	
		
			24 Commits
		
	
	
		
			wip/fix-dr
			...
			message-tr
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					8fc9d0c8ba | ||
| 
						 | 
					803a204604 | ||
| 
						 | 
					a02e6d30f7 | ||
| 
						 | 
					a424bbbabf | ||
| 
						 | 
					4ab513ca77 | ||
| 
						 | 
					09653fbaf6 | ||
| 
						 | 
					b1791951cb | ||
| 
						 | 
					af1a3b11f5 | ||
| 
						 | 
					ef49ada575 | ||
| 
						 | 
					6c3b8e2add | ||
| 
						 | 
					3658f8a8b4 | ||
| 
						 | 
					74418f2129 | ||
| 
						 | 
					3b4e2202f7 | ||
| 
						 | 
					3b5c468cbf | ||
| 
						 | 
					b0a0ee297c | ||
| 
						 | 
					b48b21e578 | ||
| 
						 | 
					e823a3b554 | ||
| 
						 | 
					e5b12619ef | ||
| 
						 | 
					242c2bce04 | ||
| 
						 | 
					64373fe77e | ||
| 
						 | 
					f106ee7182 | ||
| 
						 | 
					56d2691c31 | ||
| 
						 | 
					f883e32f26 | ||
| 
						 | 
					c985c3cf78 | 
@@ -472,6 +472,27 @@ StTooltip {
 | 
			
		||||
    color: #cccccc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Message Tray */
 | 
			
		||||
#message-tray {
 | 
			
		||||
    background-gradient-direction: vertical;
 | 
			
		||||
    background-gradient-start: rgba(0,0,0,0.01);
 | 
			
		||||
    background-gradient-end: rgba(0,0,0,0.95);
 | 
			
		||||
    height: 28px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#notification {
 | 
			
		||||
    border-radius: 5px;
 | 
			
		||||
    background: rgba(0,0,0,0.9);
 | 
			
		||||
    color: white;
 | 
			
		||||
    padding: 2px 10px;
 | 
			
		||||
    spacing: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#summary-mode {
 | 
			
		||||
    spacing: 10px;
 | 
			
		||||
    padding: 2px 4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* App Switcher */
 | 
			
		||||
.switcher-list {
 | 
			
		||||
    background: rgba(0,0,0,0.8);
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,8 @@ dist_jsui_DATA =		\
 | 
			
		||||
	link.js			\
 | 
			
		||||
	lookingGlass.js		\
 | 
			
		||||
	main.js			\
 | 
			
		||||
	messageTray.js          \
 | 
			
		||||
	notificationDaemon.js   \
 | 
			
		||||
	overview.js		\
 | 
			
		||||
	panel.js		\
 | 
			
		||||
	placeDisplay.js		\
 | 
			
		||||
 
 | 
			
		||||
@@ -15,11 +15,13 @@ const St = imports.gi.St;
 | 
			
		||||
const Chrome = imports.ui.chrome;
 | 
			
		||||
const Environment = imports.ui.environment;
 | 
			
		||||
const ExtensionSystem = imports.ui.extensionSystem;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
const Overview = imports.ui.overview;
 | 
			
		||||
const Panel = imports.ui.panel;
 | 
			
		||||
const PlaceDisplay = imports.ui.placeDisplay;
 | 
			
		||||
const RunDialog = imports.ui.runDialog;
 | 
			
		||||
const LookingGlass = imports.ui.lookingGlass;
 | 
			
		||||
const NotificationDaemon = imports.ui.notificationDaemon;
 | 
			
		||||
const ShellDBus = imports.ui.shellDBus;
 | 
			
		||||
const Sidebar = imports.ui.sidebar;
 | 
			
		||||
const WindowManager = imports.ui.windowManager;
 | 
			
		||||
@@ -35,6 +37,9 @@ let overview = null;
 | 
			
		||||
let runDialog = null;
 | 
			
		||||
let lookingGlass = null;
 | 
			
		||||
let wm = null;
 | 
			
		||||
let notificationDaemon = null;
 | 
			
		||||
let notificationPopup = null;
 | 
			
		||||
let messageTray = null;
 | 
			
		||||
let recorder = null;
 | 
			
		||||
let shellDBusService = null;
 | 
			
		||||
let modalCount = 0;
 | 
			
		||||
@@ -113,6 +118,9 @@ function start() {
 | 
			
		||||
    panel = new Panel.Panel();
 | 
			
		||||
    sidebar = new Sidebar.Sidebar();
 | 
			
		||||
    wm = new WindowManager.WindowManager();
 | 
			
		||||
    notificationDaemon = new NotificationDaemon.NotificationDaemon();
 | 
			
		||||
    notificationPopup = new MessageTray.Notification();
 | 
			
		||||
    messageTray = new MessageTray.MessageTray();
 | 
			
		||||
 | 
			
		||||
    _startDate = new Date();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										271
									
								
								js/ui/messageTray.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								js/ui/messageTray.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,271 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
const Pango = imports.gi.Pango;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const Tweener = imports.ui.tweener;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
 | 
			
		||||
const ANIMATION_TIME = 0.2;
 | 
			
		||||
const NOTIFICATION_TIMEOUT = 4;
 | 
			
		||||
 | 
			
		||||
const MESSAGE_TRAY_TIMEOUT = 0.2;
 | 
			
		||||
 | 
			
		||||
const ICON_SIZE = 24;
 | 
			
		||||
 | 
			
		||||
function Notification(icon, text) {
 | 
			
		||||
    this._init(icon, text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Notification.prototype = {
 | 
			
		||||
    _init: function(icon, text) {
 | 
			
		||||
        this.icon = icon;
 | 
			
		||||
        this.text = text;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function NotificationBox() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NotificationBox.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new St.BoxLayout({ name: 'notification' });
 | 
			
		||||
 | 
			
		||||
        this._iconBox = new St.Bin();
 | 
			
		||||
        this.actor.add(this._iconBox);
 | 
			
		||||
 | 
			
		||||
        this._textBox = new Shell.GenericContainer();
 | 
			
		||||
        this._textBox.connect('get-preferred-width', Lang.bind(this, this._textBoxGetPreferredWidth));
 | 
			
		||||
        this._textBox.connect('get-preferred-height', Lang.bind(this, this._textBoxGetPreferredHeight));
 | 
			
		||||
        this._textBox.connect('allocate', Lang.bind(this, this._textBoxAllocate));
 | 
			
		||||
        this.actor.add(this._textBox, { expand: true, x_fill: false, y_fill: false, y_align: St.Align.MIDDLE });
 | 
			
		||||
 | 
			
		||||
        this._text = new St.Label();
 | 
			
		||||
        this._text.clutter_text.line_wrap = true;
 | 
			
		||||
        this._text.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
 | 
			
		||||
        this._textBox.add_actor(this._text);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _textBoxGetPreferredWidth: function (actor, forHeight, alloc) {
 | 
			
		||||
        let [min, nat] = this._text.get_preferred_width(forHeight);
 | 
			
		||||
 | 
			
		||||
        alloc.min_size = alloc.nat_size = Math.min(nat, global.screen_width / 2);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _textBoxGetPreferredHeight: function (actor, forWidth, alloc) {
 | 
			
		||||
        // St.BoxLayout passes -1 for @forWidth, which isn't what we want.
 | 
			
		||||
        let prefWidth = {};
 | 
			
		||||
        this._textBoxGetPreferredWidth(this._textBox, -1, prefWidth);
 | 
			
		||||
        [alloc.min_size, alloc.nat_size] = this._text.get_preferred_height(prefWidth.nat_size);
 | 
			
		||||
        log('for width ' + prefWidth.nat_size + ', height ' + alloc.nat_size);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _textBoxAllocate: function (actor, box, flags) {
 | 
			
		||||
        let childBox = new Clutter.ActorBox();
 | 
			
		||||
        childBox.x1 = childBox.y1 = 0;
 | 
			
		||||
        childBox.x2 = box.x2 - box.x1;
 | 
			
		||||
        childBox.y2 = box.y2 - box.y1;
 | 
			
		||||
        this._text.allocate(childBox, flags);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setContent: function(notification) {
 | 
			
		||||
        this._iconBox.child = notification.icon;
 | 
			
		||||
 | 
			
		||||
        // Support <b>, <i>, and <u>, escape anything else
 | 
			
		||||
        // so it displays as raw markup.
 | 
			
		||||
        let markup = notification.text.replace(/<(\/?[^biu]>|[^>\/][^>])/g, "<$1");
 | 
			
		||||
        this._text.clutter_text.set_markup(markup);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function Source(id, createIcon) {
 | 
			
		||||
    this._init(id, createIcon);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Source.prototype = {
 | 
			
		||||
    _init: function(id, createIcon) {
 | 
			
		||||
        this.id = id;
 | 
			
		||||
        if (createIcon)
 | 
			
		||||
            this.createIcon = createIcon;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // This can be overridden by a subclass, or by the createIcon
 | 
			
		||||
    // parameter to _init()
 | 
			
		||||
    createIcon: function(size) {
 | 
			
		||||
        throw new Error('no implementation of createIcon in ' + this);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    notify: function(text) {
 | 
			
		||||
        Main.messageTray.showNotification(new Notification(this.createIcon(ICON_SIZE), text));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    clicked: function() {
 | 
			
		||||
        this.emit('clicked');
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    destroy: function() {
 | 
			
		||||
        this.emit('destroy');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
Signals.addSignalMethods(Source.prototype);
 | 
			
		||||
 | 
			
		||||
function MessageTray() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MessageTray.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this.actor = new St.BoxLayout({ name: 'message-tray',
 | 
			
		||||
                                        reactive: true });
 | 
			
		||||
 | 
			
		||||
        let primary = global.get_primary_monitor();
 | 
			
		||||
        this.actor.x = 0;
 | 
			
		||||
        this.actor.y = primary.height - 1;
 | 
			
		||||
 | 
			
		||||
        this.actor.width = primary.width;
 | 
			
		||||
 | 
			
		||||
        this._summaryBin = new St.Bin({ x_align: St.Align.END });
 | 
			
		||||
        this.actor.add(this._summaryBin, { expand: true });
 | 
			
		||||
        this._summaryBin.hide();
 | 
			
		||||
 | 
			
		||||
        this._notificationBox = new NotificationBox();
 | 
			
		||||
        this._notificationQueue = [];
 | 
			
		||||
        this.actor.add(this._notificationBox.actor);
 | 
			
		||||
        this._notificationBox.actor.hide();
 | 
			
		||||
 | 
			
		||||
        Main.chrome.addActor(this.actor, { affectsStruts: false });
 | 
			
		||||
 | 
			
		||||
        this.actor.connect('enter-event',
 | 
			
		||||
                           Lang.bind(this, this._onMessageTrayEntered));
 | 
			
		||||
        this.actor.connect('leave-event',
 | 
			
		||||
                           Lang.bind(this, this._onMessageTrayLeft));
 | 
			
		||||
        this._isShowing = false;
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
 | 
			
		||||
        this._summary = new St.BoxLayout({ name: 'summary-mode' });
 | 
			
		||||
        this._summaryBin.child = this._summary;
 | 
			
		||||
 | 
			
		||||
        this._sources = {};
 | 
			
		||||
        this._icons = {};
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    contains: function(source) {
 | 
			
		||||
        return this._sources.hasOwnProperty(source.id);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    add: function(source) {
 | 
			
		||||
        if (this.contains(source)) {
 | 
			
		||||
            log('Trying to re-add source ' + source.id);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let iconBox = new St.Bin({ reactive: true });
 | 
			
		||||
        iconBox.child = source.createIcon(ICON_SIZE);
 | 
			
		||||
        this._summary.insert_actor(iconBox, 0);
 | 
			
		||||
        this._icons[source.id] = iconBox;
 | 
			
		||||
        this._sources[source.id] = source;
 | 
			
		||||
 | 
			
		||||
        iconBox.connect('button-release-event', Lang.bind(this,
 | 
			
		||||
            function () {
 | 
			
		||||
                source.clicked();
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
        source.connect('destroy', Lang.bind(this,
 | 
			
		||||
            function () {
 | 
			
		||||
                this.remove(source);
 | 
			
		||||
            }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    remove: function(source) {
 | 
			
		||||
        if (!this.contains(source))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._summary.remove_actor(this._icons[source.id]);
 | 
			
		||||
        delete this._icons[source.id];
 | 
			
		||||
        delete this._sources[source.id];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getSource: function(id) {
 | 
			
		||||
        return this._sources[id];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onMessageTrayEntered: function() {
 | 
			
		||||
        // Don't hide the message tray after a timeout if the user has moved the mouse over it.
 | 
			
		||||
        // We might have a timeout in place if the user moved the mouse away from the message tray for a very short period of time
 | 
			
		||||
        // or if we are showing a notification.
 | 
			
		||||
        if (this._hideTimeoutId > 0)
 | 
			
		||||
            Mainloop.source_remove(this._hideTimeoutId);
 | 
			
		||||
 | 
			
		||||
        if (this._isShowing)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        // If the message tray was not already showing, we'll show it in the summary mode.
 | 
			
		||||
        this._summaryBin.show();
 | 
			
		||||
        this._show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _onMessageTrayLeft: function() {
 | 
			
		||||
        if (!this._isShowing)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        // We wait just a little before hiding the message tray in case the user will quickly move the mouse back over it.
 | 
			
		||||
        this._hideTimeoutId = Mainloop.timeout_add(MESSAGE_TRAY_TIMEOUT * 1000, Lang.bind(this, this._hide));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _show: function() {
 | 
			
		||||
        this._isShowing = true;
 | 
			
		||||
        let primary = global.get_primary_monitor();
 | 
			
		||||
        Tweener.addTween(this.actor,
 | 
			
		||||
                         { y: primary.height - this.actor.height,
 | 
			
		||||
                           time: ANIMATION_TIME,
 | 
			
		||||
                           transition: "easeOutQuad"
 | 
			
		||||
                         });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hide: function() {
 | 
			
		||||
        this._hideTimeoutId = 0;
 | 
			
		||||
 | 
			
		||||
        let primary = global.get_primary_monitor();
 | 
			
		||||
 | 
			
		||||
        Tweener.addTween(this.actor,
 | 
			
		||||
                         { y: primary.height - 1,
 | 
			
		||||
                           time: ANIMATION_TIME,
 | 
			
		||||
                           transition: "easeOutQuad",
 | 
			
		||||
                           onComplete: this._hideComplete,
 | 
			
		||||
                           onCompleteScope: this
 | 
			
		||||
                         });
 | 
			
		||||
        return false;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _hideComplete: function() {
 | 
			
		||||
        this._isShowing = false;
 | 
			
		||||
        this._summaryBin.hide();
 | 
			
		||||
        this._notificationBox.actor.hide();
 | 
			
		||||
        if (this._notificationQueue.length > 0)
 | 
			
		||||
            this.showNotification(this._notificationQueue.shift());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showNotification: function(notification) {
 | 
			
		||||
        if (this._isShowing) {
 | 
			
		||||
            this._notificationQueue.push(notification);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._notificationBox.setContent(notification);
 | 
			
		||||
 | 
			
		||||
        this._notificationBox.actor.x = Math.round((this.actor.width - this._notificationBox.actor.width) / 2);
 | 
			
		||||
        this._notificationBox.actor.show();
 | 
			
		||||
 | 
			
		||||
        // Because we set up the timeout before we do the animation, we add ANIMATION_TIME to NOTIFICATION_TIMEOUT, so that
 | 
			
		||||
        // NOTIFICATION_TIMEOUT represents the time the notifiation is fully shown.
 | 
			
		||||
        this._hideTimeoutId = Mainloop.timeout_add((NOTIFICATION_TIMEOUT + ANIMATION_TIME) * 1000, Lang.bind(this, this._hide));
 | 
			
		||||
 | 
			
		||||
        this._show();
 | 
			
		||||
     }
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										218
									
								
								js/ui/notificationDaemon.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								js/ui/notificationDaemon.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,218 @@
 | 
			
		||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 | 
			
		||||
 | 
			
		||||
const DBus = imports.dbus;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const Mainloop = imports.mainloop;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const MessageTray = imports.ui.messageTray;
 | 
			
		||||
const Params = imports.misc.params;
 | 
			
		||||
 | 
			
		||||
let nextNotificationId = 1;
 | 
			
		||||
 | 
			
		||||
const NotificationDaemonIface = {
 | 
			
		||||
    name: 'org.freedesktop.Notifications',
 | 
			
		||||
    methods: [{ name: 'Notify',
 | 
			
		||||
                inSignature: 'susssasa{sv}i',
 | 
			
		||||
                outSignature: 'u'
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'CloseNotification',
 | 
			
		||||
                inSignature: 'u',
 | 
			
		||||
                outSignature: ''
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'GetCapabilities',
 | 
			
		||||
                inSignature: '',
 | 
			
		||||
                outSignature: 'as'
 | 
			
		||||
              },
 | 
			
		||||
              { name: 'GetServerInformation',
 | 
			
		||||
                inSignature: '',
 | 
			
		||||
                outSignature: 'ssss'
 | 
			
		||||
              }],
 | 
			
		||||
    signals: [{ name: 'NotificationClosed',
 | 
			
		||||
                inSignature: 'uu' },
 | 
			
		||||
              { name: 'ActionInvoked',
 | 
			
		||||
                inSignature: 'us' }]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const NotificationClosedReason = {
 | 
			
		||||
    EXPIRED: 1,
 | 
			
		||||
    DISMISSED: 2,
 | 
			
		||||
    APP_CLOSED: 3,
 | 
			
		||||
    UNDEFINED: 4
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const Urgency = {
 | 
			
		||||
    LOW: 0,
 | 
			
		||||
    NORMAL: 1,
 | 
			
		||||
    CRITICAL: 2
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function NotificationDaemon() {
 | 
			
		||||
    this._init();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NotificationDaemon.prototype = {
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        DBus.session.exportObject('/org/freedesktop/Notifications', this);
 | 
			
		||||
 | 
			
		||||
        this._everAcquiredName = false;
 | 
			
		||||
        DBus.session.acquire_name('org.freedesktop.Notifications',
 | 
			
		||||
                                  // We pass MANY_INSTANCES so that if
 | 
			
		||||
                                  // notification-daemon is running, we'll
 | 
			
		||||
                                  // get queued behind it and then get the
 | 
			
		||||
                                  // name after killing it below
 | 
			
		||||
                                  DBus.MANY_INSTANCES,
 | 
			
		||||
                                  Lang.bind(this, this._acquiredName),
 | 
			
		||||
                                  Lang.bind(this, this._lostName));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _acquiredName: function() {
 | 
			
		||||
        this._everAcquiredName = true;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _lostName: function() {
 | 
			
		||||
        if (this._everAcquiredName)
 | 
			
		||||
            log('Lost name org.freedesktop.Notifications!');
 | 
			
		||||
        else if (GLib.getenv('GNOME_SHELL_NO_REPLACE'))
 | 
			
		||||
            log('Failed to acquire org.freedesktop.Notifications');
 | 
			
		||||
        else {
 | 
			
		||||
            log('Failed to acquire org.freedesktop.Notifications; trying again');
 | 
			
		||||
 | 
			
		||||
            // kill the notification-daemon. pkill is more portable
 | 
			
		||||
            // than killall, but on Linux at least it won't match if
 | 
			
		||||
            // you pass more than 15 characters of the process name...
 | 
			
		||||
            // However, if you use the "-f" flag to match the entire
 | 
			
		||||
            // command line, it will work, but we have to be careful
 | 
			
		||||
            // in that case that we don't match "gedit
 | 
			
		||||
            // notification-daemon.c" or whatever...
 | 
			
		||||
            let p = new Shell.Process({ args: ['pkill', '-f',
 | 
			
		||||
                                               '^([^ ]*/)?(notification-daemon|notify-osd)$']});
 | 
			
		||||
            p.run();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _sourceId: function(id) {
 | 
			
		||||
        return 'notification-' + id;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    Notify: function(appName, replacesId, icon, summary, body,
 | 
			
		||||
                     actions, hints, timeout) {
 | 
			
		||||
        let id, source = null;
 | 
			
		||||
 | 
			
		||||
        if (replacesId != 0) {
 | 
			
		||||
            id = replacesId;
 | 
			
		||||
            source = Main.messageTray.getSource(this._sourceId(id));
 | 
			
		||||
            // source may be null if the current source was destroyed
 | 
			
		||||
            // right as the client sent the new notification
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (source == null) {
 | 
			
		||||
            id = nextNotificationId++;
 | 
			
		||||
 | 
			
		||||
            source = new Source(this._sourceId(id), icon, hints);
 | 
			
		||||
            Main.messageTray.add(source);
 | 
			
		||||
 | 
			
		||||
            source.connect('clicked', Lang.bind(this,
 | 
			
		||||
                function() {
 | 
			
		||||
                    source.destroy();
 | 
			
		||||
                    this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
 | 
			
		||||
                }));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        summary = GLib.markup_escape_text(summary, -1);
 | 
			
		||||
        if (body)
 | 
			
		||||
            source.notify('<b>' + summary + '</b>: ' + body);
 | 
			
		||||
        else
 | 
			
		||||
            source.notify('<b>' + summary + '</b>');
 | 
			
		||||
        return id;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    CloseNotification: function(id) {
 | 
			
		||||
        let source = Main.messageTray.getSource(this._sourceId(id));
 | 
			
		||||
        if (source)
 | 
			
		||||
            source.destroy();
 | 
			
		||||
        this._emitNotificationClosed(id, NotificationClosedReason.APP_CLOSED);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    GetCapabilities: function() {
 | 
			
		||||
        return [
 | 
			
		||||
            // 'actions',
 | 
			
		||||
            'body',
 | 
			
		||||
            // 'body-hyperlinks',
 | 
			
		||||
            // 'body-images',
 | 
			
		||||
            'body-markup',
 | 
			
		||||
            // 'icon-multi',
 | 
			
		||||
            'icon-static'
 | 
			
		||||
            // 'sound',
 | 
			
		||||
        ];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    GetServerInformation: function() {
 | 
			
		||||
        return [
 | 
			
		||||
            'GNOME Shell',
 | 
			
		||||
            'GNOME',
 | 
			
		||||
            '0.1', // FIXME, get this from somewhere
 | 
			
		||||
            '1.0'
 | 
			
		||||
        ];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _emitNotificationClosed: function(id, reason) {
 | 
			
		||||
        DBus.session.emit_signal('/org/freedesktop/Notifications',
 | 
			
		||||
                                 'org.freedesktop.Notifications',
 | 
			
		||||
                                 'NotificationClosed', 'uu',
 | 
			
		||||
                                 [id, reason]);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
DBus.conformExport(NotificationDaemon.prototype, NotificationDaemonIface);
 | 
			
		||||
 | 
			
		||||
function Source(sourceId, icon, hints) {
 | 
			
		||||
    this._init(sourceId, icon, hints);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Source.prototype = {
 | 
			
		||||
    __proto__:  MessageTray.Source.prototype,
 | 
			
		||||
 | 
			
		||||
    _init: function(sourceId, icon, hints) {
 | 
			
		||||
        MessageTray.Source.prototype._init.call(this, sourceId);
 | 
			
		||||
 | 
			
		||||
        hints = Params.parse(hints, { urgency: Urgency.NORMAL }, true);
 | 
			
		||||
 | 
			
		||||
        this._icon = icon;
 | 
			
		||||
        this._iconData = hints.icon_data;
 | 
			
		||||
        this._urgency = hints.urgency;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    createIcon: function(size) {
 | 
			
		||||
        let textureCache = Shell.TextureCache.get_default();
 | 
			
		||||
 | 
			
		||||
        if (this._icon) {
 | 
			
		||||
            if (this._icon.substr(0, 7) == 'file://')
 | 
			
		||||
                return textureCache.load_uri_async(this._icon, size, size);
 | 
			
		||||
            else if (this._icon[0] == '/') {
 | 
			
		||||
                let uri = GLib.filename_to_uri(this._icon, null);
 | 
			
		||||
                return textureCache.load_uri_async(uri, size, size);
 | 
			
		||||
            } else
 | 
			
		||||
                return textureCache.load_icon_name(this._icon, size);
 | 
			
		||||
        } else if (this._iconData) {
 | 
			
		||||
            let [width, height, rowStride, hasAlpha,
 | 
			
		||||
                 bitsPerSample, nChannels, data] = this._iconData;
 | 
			
		||||
            return textureCache.load_from_raw(data, data.length, hasAlpha,
 | 
			
		||||
                                              width, height, rowStride, size);
 | 
			
		||||
        } else {
 | 
			
		||||
            let stockIcon;
 | 
			
		||||
            switch (this._urgency) {
 | 
			
		||||
                case Urgency.LOW:
 | 
			
		||||
                case Urgency.NORMAL:
 | 
			
		||||
                    stockIcon = 'gtk-dialog-info';
 | 
			
		||||
                    break;
 | 
			
		||||
                case Urgency.CRITICAL:
 | 
			
		||||
                    stockIcon = 'gtk-dialog-error';
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            return textureCache.load_icon_name(stockIcon, size);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										5
									
								
								src/gnome-shell.in
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										5
									
								
								src/gnome-shell.in
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -357,8 +357,9 @@ try:
 | 
			
		||||
    shell = None
 | 
			
		||||
    if options.xephyr:
 | 
			
		||||
        xephyr = start_xephyr()
 | 
			
		||||
        # This makes us not grab the org.gnome.Panel name
 | 
			
		||||
        os.environ['GNOME_SHELL_NO_REPLACE_PANEL'] = '1'
 | 
			
		||||
        # This makes us not grab the org.gnome.Panel or
 | 
			
		||||
        # org.freedesktop.Notifications D-Bus names
 | 
			
		||||
        os.environ['GNOME_SHELL_NO_REPLACE'] = '1'
 | 
			
		||||
        shell = start_shell()
 | 
			
		||||
    else:
 | 
			
		||||
        xephyr = None
 | 
			
		||||
 
 | 
			
		||||
@@ -751,7 +751,7 @@ shell_global_grab_dbus_service (ShellGlobal *global)
 | 
			
		||||
   * unless a special environment variable is passed.  The environment
 | 
			
		||||
   * variable is used by the gnome-shell (no --replace) launcher in
 | 
			
		||||
   * Xephyr */
 | 
			
		||||
  if (!g_getenv ("GNOME_SHELL_NO_REPLACE_PANEL"))
 | 
			
		||||
  if (!g_getenv ("GNOME_SHELL_NO_REPLACE"))
 | 
			
		||||
    {
 | 
			
		||||
      if (!dbus_g_proxy_call (bus, "RequestName", &error, G_TYPE_STRING,
 | 
			
		||||
                              "org.gnome.Panel", G_TYPE_UINT,
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
#define GNOME_DESKTOP_USE_UNSTABLE_API
 | 
			
		||||
#include <libgnomeui/gnome-desktop-thumbnail.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
@@ -17,6 +18,7 @@ typedef struct
 | 
			
		||||
  GIcon *icon;
 | 
			
		||||
  gchar *uri;
 | 
			
		||||
  gchar *thumbnail_uri;
 | 
			
		||||
  gchar *checksum;
 | 
			
		||||
 | 
			
		||||
  /* This one is common to all */
 | 
			
		||||
  guint size;
 | 
			
		||||
@@ -51,6 +53,8 @@ cache_key_hash (gconstpointer a)
 | 
			
		||||
    base_hash = g_str_hash (akey->uri);
 | 
			
		||||
  else if (akey->thumbnail_uri)
 | 
			
		||||
    base_hash = g_str_hash (akey->thumbnail_uri);
 | 
			
		||||
  else if (akey->checksum)
 | 
			
		||||
    base_hash = g_str_hash (akey->checksum);
 | 
			
		||||
  else
 | 
			
		||||
    g_assert_not_reached ();
 | 
			
		||||
  return base_hash + 31*akey->size;
 | 
			
		||||
@@ -76,6 +80,8 @@ cache_key_equal (gconstpointer a,
 | 
			
		||||
    return strcmp (akey->uri, bkey->uri) == 0;
 | 
			
		||||
  else if (akey->thumbnail_uri && bkey->thumbnail_uri)
 | 
			
		||||
    return strcmp (akey->thumbnail_uri, bkey->thumbnail_uri) == 0;
 | 
			
		||||
  else if (akey->checksum && bkey->checksum)
 | 
			
		||||
    return strcmp (akey->checksum, bkey->checksum) == 0;
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
@@ -89,6 +95,7 @@ cache_key_dup (CacheKey *key)
 | 
			
		||||
    ret->icon = g_object_ref (key->icon);
 | 
			
		||||
  ret->uri = g_strdup (key->uri);
 | 
			
		||||
  ret->thumbnail_uri = g_strdup (key->thumbnail_uri);
 | 
			
		||||
  ret->checksum = g_strdup (key->checksum);
 | 
			
		||||
  ret->size = key->size;
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
@@ -101,6 +108,7 @@ cache_key_destroy (gpointer a)
 | 
			
		||||
    g_object_unref (akey->icon);
 | 
			
		||||
  g_free (akey->uri);
 | 
			
		||||
  g_free (akey->thumbnail_uri);
 | 
			
		||||
  g_free (akey->checksum);
 | 
			
		||||
  g_free (akey);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -318,7 +326,8 @@ on_image_size_prepared (GdkPixbufLoader *pixbuf_loader,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GdkPixbuf *
 | 
			
		||||
impl_load_pixbuf_file (const char     *uri,
 | 
			
		||||
impl_load_pixbuf_data (const guchar   *data,
 | 
			
		||||
                       gsize           size,
 | 
			
		||||
                       int             available_width,
 | 
			
		||||
                       int             available_height,
 | 
			
		||||
                       GError        **error)
 | 
			
		||||
@@ -326,22 +335,10 @@ impl_load_pixbuf_file (const char     *uri,
 | 
			
		||||
  GdkPixbufLoader *pixbuf_loader = NULL;
 | 
			
		||||
  GdkPixbuf *rotated_pixbuf = NULL;
 | 
			
		||||
  GdkPixbuf *pixbuf;
 | 
			
		||||
  GFile *file = NULL;
 | 
			
		||||
  char *contents = NULL;
 | 
			
		||||
  gsize size;
 | 
			
		||||
  gboolean success;
 | 
			
		||||
  Dimensions available_dimensions;
 | 
			
		||||
  int width_before_rotation, width_after_rotation;
 | 
			
		||||
 | 
			
		||||
  file = g_file_new_for_uri (uri);
 | 
			
		||||
 | 
			
		||||
  success = g_file_load_contents (file, NULL, &contents, &size, NULL, error);
 | 
			
		||||
 | 
			
		||||
  if (!success)
 | 
			
		||||
    {
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  pixbuf_loader = gdk_pixbuf_loader_new ();
 | 
			
		||||
 | 
			
		||||
  available_dimensions.width = available_width;
 | 
			
		||||
@@ -349,10 +346,7 @@ impl_load_pixbuf_file (const char     *uri,
 | 
			
		||||
  g_signal_connect (pixbuf_loader, "size-prepared",
 | 
			
		||||
                    G_CALLBACK (on_image_size_prepared), &available_dimensions);
 | 
			
		||||
 | 
			
		||||
  success = gdk_pixbuf_loader_write (pixbuf_loader,
 | 
			
		||||
                                     (const guchar *) contents,
 | 
			
		||||
                                     size,
 | 
			
		||||
                                     error);
 | 
			
		||||
  success = gdk_pixbuf_loader_write (pixbuf_loader, data, size, error);
 | 
			
		||||
  if (!success)
 | 
			
		||||
    goto out;
 | 
			
		||||
  success = gdk_pixbuf_loader_close (pixbuf_loader, error);
 | 
			
		||||
@@ -384,10 +378,7 @@ impl_load_pixbuf_file (const char     *uri,
 | 
			
		||||
      g_signal_connect (pixbuf_loader, "size-prepared",
 | 
			
		||||
                        G_CALLBACK (on_image_size_prepared), &available_dimensions);
 | 
			
		||||
 | 
			
		||||
      success = gdk_pixbuf_loader_write (pixbuf_loader,
 | 
			
		||||
                                         (const guchar *) contents,
 | 
			
		||||
                                         size,
 | 
			
		||||
                                         error);
 | 
			
		||||
      success = gdk_pixbuf_loader_write (pixbuf_loader, data, size, error);
 | 
			
		||||
      if (!success)
 | 
			
		||||
        goto out;
 | 
			
		||||
 | 
			
		||||
@@ -401,14 +392,36 @@ impl_load_pixbuf_file (const char     *uri,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
  g_free (contents);
 | 
			
		||||
  if (file)
 | 
			
		||||
    g_object_unref (file);
 | 
			
		||||
  if (pixbuf_loader)
 | 
			
		||||
    g_object_unref (pixbuf_loader);
 | 
			
		||||
  return rotated_pixbuf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GdkPixbuf *
 | 
			
		||||
impl_load_pixbuf_file (const char     *uri,
 | 
			
		||||
                       int             available_width,
 | 
			
		||||
                       int             available_height,
 | 
			
		||||
                       GError        **error)
 | 
			
		||||
{
 | 
			
		||||
  GdkPixbuf *pixbuf = NULL;
 | 
			
		||||
  GFile *file;
 | 
			
		||||
  char *contents = NULL;
 | 
			
		||||
  gsize size;
 | 
			
		||||
 | 
			
		||||
  file = g_file_new_for_uri (uri);
 | 
			
		||||
  if (g_file_load_contents (file, NULL, &contents, &size, NULL, error))
 | 
			
		||||
    {
 | 
			
		||||
      pixbuf = impl_load_pixbuf_data ((const guchar *) contents, size,
 | 
			
		||||
                                      available_width, available_height,
 | 
			
		||||
                                      error);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_object_unref (file);
 | 
			
		||||
  g_free (contents);
 | 
			
		||||
 | 
			
		||||
  return pixbuf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GdkPixbuf *
 | 
			
		||||
impl_load_thumbnail (ShellTextureCache *cache,
 | 
			
		||||
                     const char        *uri,
 | 
			
		||||
@@ -655,6 +668,7 @@ typedef struct {
 | 
			
		||||
  gboolean thumbnail;
 | 
			
		||||
  char *mimetype;
 | 
			
		||||
  GtkRecentInfo *recent_info;
 | 
			
		||||
  char *checksum;
 | 
			
		||||
  GIcon *icon;
 | 
			
		||||
  GtkIconInfo *icon_info;
 | 
			
		||||
  guint width;
 | 
			
		||||
@@ -1137,6 +1151,128 @@ shell_texture_cache_load_uri_sync (ShellTextureCache *cache,
 | 
			
		||||
  return CLUTTER_ACTOR (texture);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_texture_cache_load_from_data:
 | 
			
		||||
 * @cache: The texture cache instance
 | 
			
		||||
 * @data: Image data in PNG, GIF, etc format
 | 
			
		||||
 * @len: length of @data
 | 
			
		||||
 * @size: Size in pixels to use for the resulting texture
 | 
			
		||||
 * @error: Return location for error
 | 
			
		||||
 *
 | 
			
		||||
 * Synchronously creates an image from @data. The image is scaled down
 | 
			
		||||
 * to fit the available width and height dimensions, but the image is
 | 
			
		||||
 * never scaled up beyond its actual size. The pixbuf is rotated
 | 
			
		||||
 * according to the associated orientation setting.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: (transfer none): A new #ClutterActor with the image data loaded if it was
 | 
			
		||||
 *               generated succesfully, %NULL otherwise
 | 
			
		||||
 */
 | 
			
		||||
ClutterActor *
 | 
			
		||||
shell_texture_cache_load_from_data (ShellTextureCache *cache,
 | 
			
		||||
                                    const guchar      *data,
 | 
			
		||||
                                    gsize              len,
 | 
			
		||||
                                    int                size,
 | 
			
		||||
                                    GError           **error)
 | 
			
		||||
{
 | 
			
		||||
  ClutterTexture *texture;
 | 
			
		||||
  CoglHandle texdata;
 | 
			
		||||
  GdkPixbuf *pixbuf;
 | 
			
		||||
  CacheKey key;
 | 
			
		||||
  gchar *checksum;
 | 
			
		||||
 | 
			
		||||
  texture = create_default_texture (cache);
 | 
			
		||||
  clutter_actor_set_size (CLUTTER_ACTOR (texture), size, size);
 | 
			
		||||
 | 
			
		||||
  checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA1, data, len);
 | 
			
		||||
 | 
			
		||||
  memset (&key, 0, sizeof(key));
 | 
			
		||||
  key.size = size;
 | 
			
		||||
  key.checksum = checksum;
 | 
			
		||||
 | 
			
		||||
  texdata = g_hash_table_lookup (cache->priv->keyed_cache, &key);
 | 
			
		||||
  if (texdata == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      pixbuf = impl_load_pixbuf_data (data, len, size, size, error);
 | 
			
		||||
      if (!pixbuf)
 | 
			
		||||
        {
 | 
			
		||||
          g_object_unref (texture);
 | 
			
		||||
          return NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      texdata = pixbuf_to_cogl_handle (pixbuf);
 | 
			
		||||
      g_object_unref (pixbuf);
 | 
			
		||||
 | 
			
		||||
      set_texture_cogl_texture (texture, texdata);
 | 
			
		||||
 | 
			
		||||
      g_hash_table_insert (cache->priv->keyed_cache, cache_key_dup (&key), texdata);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_free (key.checksum);
 | 
			
		||||
 | 
			
		||||
  set_texture_cogl_texture (texture, texdata);
 | 
			
		||||
  return CLUTTER_ACTOR (texture);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_texture_cache_load_from_raw:
 | 
			
		||||
 * @cache: a #ShellTextureCache
 | 
			
		||||
 * @data: raw pixel data
 | 
			
		||||
 * @len: the length of @data
 | 
			
		||||
 * @has_alpha: whether @data includes an alpha channel
 | 
			
		||||
 * @width: width in pixels of @data
 | 
			
		||||
 * @height: width in pixels of @data
 | 
			
		||||
 * @rowstride: rowstride of @data
 | 
			
		||||
 * @size: size of icon to return
 | 
			
		||||
 *
 | 
			
		||||
 * Creates (or retrieves from cache) an icon based on raw pixel data.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: (transfer none): a new #ClutterActor displaying a
 | 
			
		||||
 * pixbuf created from @data and the other parameters.
 | 
			
		||||
 **/
 | 
			
		||||
ClutterActor *
 | 
			
		||||
shell_texture_cache_load_from_raw (ShellTextureCache *cache,
 | 
			
		||||
                                   const guchar      *data,
 | 
			
		||||
                                   gsize              len,
 | 
			
		||||
                                   gboolean           has_alpha,
 | 
			
		||||
                                   int                width,
 | 
			
		||||
                                   int                height,
 | 
			
		||||
                                   int                rowstride,
 | 
			
		||||
                                   int                size,
 | 
			
		||||
                                   GError           **error)
 | 
			
		||||
{
 | 
			
		||||
  ClutterTexture *texture;
 | 
			
		||||
  CoglHandle texdata;
 | 
			
		||||
  CacheKey key;
 | 
			
		||||
  gchar *checksum;
 | 
			
		||||
 | 
			
		||||
  texture = create_default_texture (cache);
 | 
			
		||||
  clutter_actor_set_size (CLUTTER_ACTOR (texture), size, size);
 | 
			
		||||
 | 
			
		||||
  /* In theory, two images of different size could have the same
 | 
			
		||||
   * pixel data. We ignore that theory.
 | 
			
		||||
   */
 | 
			
		||||
  checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA1, data, len);
 | 
			
		||||
 | 
			
		||||
  memset (&key, 0, sizeof(key));
 | 
			
		||||
  key.size = size;
 | 
			
		||||
  key.checksum = checksum;
 | 
			
		||||
 | 
			
		||||
  texdata = g_hash_table_lookup (cache->priv->keyed_cache, &key);
 | 
			
		||||
  if (texdata == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      texdata = cogl_texture_new_from_data (width, height, COGL_TEXTURE_NONE,
 | 
			
		||||
                                            has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
 | 
			
		||||
                                            COGL_PIXEL_FORMAT_ANY,
 | 
			
		||||
                                            rowstride, data);
 | 
			
		||||
      g_hash_table_insert (cache->priv->keyed_cache, cache_key_dup (&key), texdata);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_free (key.checksum);
 | 
			
		||||
 | 
			
		||||
  set_texture_cogl_texture (texture, texdata);
 | 
			
		||||
  return CLUTTER_ACTOR (texture);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * shell_texture_cache_load_thumbnail:
 | 
			
		||||
 * @cache:
 | 
			
		||||
 
 | 
			
		||||
@@ -80,6 +80,21 @@ ClutterActor *shell_texture_cache_load_uri_sync (ShellTextureCache *cache,
 | 
			
		||||
                                                 int                available_height,
 | 
			
		||||
                                                 GError           **error);
 | 
			
		||||
 | 
			
		||||
ClutterActor *shell_texture_cache_load_from_data (ShellTextureCache *cache,
 | 
			
		||||
                                                  const guchar      *data,
 | 
			
		||||
                                                  gsize              len,
 | 
			
		||||
                                                  int                size,
 | 
			
		||||
                                                  GError           **error);
 | 
			
		||||
ClutterActor *shell_texture_cache_load_from_raw  (ShellTextureCache *cache,
 | 
			
		||||
                                                  const guchar      *data,
 | 
			
		||||
                                                  gsize              len,
 | 
			
		||||
                                                  gboolean           has_alpha,
 | 
			
		||||
                                                  int                width,
 | 
			
		||||
                                                  int                height,
 | 
			
		||||
                                                  int                rowstride,
 | 
			
		||||
                                                  int                size,
 | 
			
		||||
                                                  GError           **error);
 | 
			
		||||
 | 
			
		||||
gboolean shell_texture_cache_pixbuf_equal (ShellTextureCache *cache, GdkPixbuf *a, GdkPixbuf *b);
 | 
			
		||||
 | 
			
		||||
#endif /* __SHELL_TEXTURE_CACHE_H__ */
 | 
			
		||||
 
 | 
			
		||||
@@ -1418,3 +1418,36 @@ st_box_layout_get_n_children  (StBoxLayout *self)
 | 
			
		||||
{
 | 
			
		||||
  return g_list_length (self->priv->children);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
st_box_layout_move_child (StBoxLayout  *self,
 | 
			
		||||
                          ClutterActor *actor,
 | 
			
		||||
                          int           pos)
 | 
			
		||||
{
 | 
			
		||||
  StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (self)->priv;
 | 
			
		||||
 | 
			
		||||
  GList *item = NULL;
 | 
			
		||||
 | 
			
		||||
  item = g_list_find (priv->children, actor);
 | 
			
		||||
 | 
			
		||||
  if (item == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Actor of type '%s' is not a child of the StBoxLayout container",
 | 
			
		||||
                 g_type_name (G_OBJECT_TYPE (actor)));
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  priv->children = g_list_delete_link (priv->children, item);
 | 
			
		||||
  priv->children = g_list_insert (priv->children, actor, pos);
 | 
			
		||||
  clutter_actor_queue_relayout ((ClutterActor*) self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
st_box_layout_insert_actor (StBoxLayout  *self,
 | 
			
		||||
                            ClutterActor *actor,
 | 
			
		||||
                            int           pos)
 | 
			
		||||
{
 | 
			
		||||
  clutter_container_add_actor((ClutterContainer*) self, actor);
 | 
			
		||||
  st_box_layout_move_child(self, actor, pos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -95,6 +95,14 @@ void     st_box_layout_destroy_children (StBoxLayout *box);
 | 
			
		||||
 | 
			
		||||
guint    st_box_layout_get_n_children  (StBoxLayout *box);
 | 
			
		||||
 | 
			
		||||
void     st_box_layout_move_child (StBoxLayout  *self,
 | 
			
		||||
                                   ClutterActor *actor,
 | 
			
		||||
                                   int           pos);
 | 
			
		||||
 | 
			
		||||
void     st_box_layout_insert_actor (StBoxLayout  *self,
 | 
			
		||||
                                     ClutterActor *actor,
 | 
			
		||||
                                     int           pos);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* _ST_BOX_LAYOUT_H */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user