Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simple compositor #116

Merged
merged 2 commits into from
Jun 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ services:
- docker

env:
- DEPENDENCY_PACKAGES="desktop-file-utils libclutter-gtk-1.0-dev libgdk-pixbuf2.0-dev libgranite-dev libgtk-3-dev liblightdm-gobject-1-dev libwingpanel-2.0-dev libx11-dev meson valac"
- DEPENDENCY_PACKAGES="desktop-file-utils libclutter-gtk-1.0-dev libgdk-pixbuf2.0-dev libgranite-dev libgtk-3-dev liblightdm-gobject-1-dev libwingpanel-2.0-dev libx11-dev meson libmutter-2-dev libgnome-desktop-3-dev valac"

install:
- docker pull elementary/docker:juno-unstable
Expand Down
66 changes: 66 additions & 0 deletions compositor/DBus.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2012-2014 Tom Beckmann, Jacob Parker
* Copyright 2018 elementary LLC. (https://elementary.io)
*
* 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/>.
*/

[DBus (name="org.pantheon.greeter")]
public class GreeterCompositor.DBus {
public static DBus? instance;
static WindowManager wm;

[DBus (visible = false)]
public static void init (WindowManager _wm) {
wm = _wm;

Bus.own_name (BusType.SESSION, "org.pantheon.greeter", BusNameOwnerFlags.NONE,
(connection) => {
if (instance == null)
instance = new DBus ();

try {
connection.register_object ("/org/pantheon/greeter", instance);
} catch (Error e) {
warning (e.message);
}
},
() => {},
() => warning ("Could not acquire name\n")
);

Bus.own_name (BusType.SESSION, "org.gnome.Shell", BusNameOwnerFlags.NONE,
(connection) => {
try {
connection.register_object ("/org/gnome/Shell", DBusAccelerator.init (wm));
} catch (Error e) {
warning (e.message);
}
},
() => {},
() => critical ("Could not acquire name")
);
}

[DBus (visible = false)]
public signal void change_wallpaper (string path);

public void set_wallpaper (string path) {
change_wallpaper (path);
}

private DBus () {

}
}
116 changes: 116 additions & 0 deletions compositor/DBusAccelerator.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Copyright 2015 Nicolas Bruguier, Corentin Noël
* Copyright 2018 elementary LLC. (https://elementary.io)
*
* 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/>.
*/

namespace GreeterCompositor {
public struct Accelerator {
public string name;
public uint flags;
}

[DBus (name="org.gnome.Shell")]
public class DBusAccelerator {
static DBusAccelerator? instance;

[DBus (visible = false)]
public static unowned DBusAccelerator init (WindowManager wm) {
if (instance == null)
instance = new DBusAccelerator (wm);

return instance;
}

public signal void accelerator_activated (uint action, GLib.HashTable<string, Variant> parameters);

WindowManager wm;
HashTable<string, uint?> grabbed_accelerators;

DBusAccelerator (WindowManager _wm) {
wm = _wm;
grabbed_accelerators = new HashTable<string, uint> (str_hash, str_equal);

wm.get_screen ().get_display ().accelerator_activated.connect (on_accelerator_activated);
}

void on_accelerator_activated (uint action, uint device_id, uint timestamp) {
foreach (string accelerator in grabbed_accelerators.get_keys ()) {
if (grabbed_accelerators[accelerator] == action) {
var parameters = new GLib.HashTable<string, Variant> (null, null);
parameters.set ("device-id", new Variant.uint32 (device_id));
parameters.set ("timestamp", new Variant.uint32 (timestamp));

accelerator_activated (action, parameters);
}
}
}

public uint grab_accelerator (string accelerator, uint flags) {
uint? action = grabbed_accelerators[accelerator];

if (action == null) {
action = wm.get_screen ().get_display ().grab_accelerator (accelerator);
if (action > 0) {
grabbed_accelerators[accelerator] = action;
}
}

return action;
}

public uint[] grab_accelerators (Accelerator[] accelerators) {
uint[] actions = {};

foreach (unowned Accelerator? accelerator in accelerators) {
actions += grab_accelerator (accelerator.name, accelerator.flags);
}

return actions;
}

public bool ungrab_accelerator (uint action) {
bool ret = false;

foreach (unowned string accelerator in grabbed_accelerators.get_keys ()) {
if (grabbed_accelerators[accelerator] == action) {
ret = wm.get_screen ().get_display ().ungrab_accelerator (action);
grabbed_accelerators.remove (accelerator);
break;
}
}

return ret;
}

[DBus (name = "ShowOSD")]
public void show_osd (GLib.HashTable<string, Variant> parameters) {
int32 monitor_index = -1;
if (parameters.contains ("monitor"))
monitor_index = parameters["monitor"].get_int32 ();
string icon = "";
if (parameters.contains ("icon"))
icon = parameters["icon"].get_string ();
string label = "";
if (parameters.contains ("label"))
label = parameters["label"].get_string ();
int32 level = 0;
if (parameters.contains ("level"))
level = parameters["level"].get_int32 ();

MediaFeedback.send (icon, level);
}
}
}
120 changes: 120 additions & 0 deletions compositor/MediaFeedback.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Copyright 2016 Rico Tzschichholz
* Copyright 2018 elementary LLC. (https://elementary.io)
*
* 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/>.
*/

namespace GreeterCompositor {
[DBus (name = "org.freedesktop.Notifications")]
interface DBusNotifications : GLib.Object {
public abstract uint32 notify (string app_name, uint32 replaces_id, string app_icon, string summary,
string body, string[] actions, HashTable<string, Variant> hints, int32 expire_timeout) throws IOError;
}

public class MediaFeedback : GLib.Object {
[Compact]
class Feedback {
public string icon;
public int32 level;

public Feedback (string _icon, int32 _level) {
icon = _icon;
level = _level;
}
}

static MediaFeedback? instance = null;
static ThreadPool<Feedback>? pool = null;

public static void init () {
if (instance == null)
instance = new MediaFeedback ();
}

public static void send (string icon, int val) requires (instance != null && pool != null) {
try {
pool.add (new Feedback (icon, val));
} catch (ThreadError e) {
critical (e.message);
}
}

DBusConnection? connection = null;
DBusNotifications? notifications = null;
uint dbus_name_owner_changed_signal_id = 0;
uint32 notification_id = 0;

MediaFeedback () {
Object ();
}

construct {
try {
pool = new ThreadPool<Feedback>.with_owned_data ((ThreadPoolFunc<Feedback>) send_feedback, 1, false);
} catch (ThreadError e) {
critical (e.message);
pool = null;
}

try {
connection = Bus.get_sync (BusType.SESSION);
dbus_name_owner_changed_signal_id = connection.signal_subscribe ("org.freedesktop.DBus", "org.freedesktop.DBus",
"NameOwnerChanged", "/org/freedesktop/DBus", null, DBusSignalFlags.NONE, (DBusSignalCallback) handle_name_owner_changed);
} catch (IOError e) {
critical (e.message);
}
}

[CCode (instance_pos = -1)]
void handle_name_owner_changed (DBusConnection connection, string sender_name, string object_path, string interface_name, string signal_name, Variant parameters) {
string name, before, after;
parameters.get ("(sss)", out name, out before, out after);

if (name != "org.freedesktop.Notifications")
return;

if (after != "" && before == "")
new Thread<void*> (null, () => {
lock (notifications) {
try {
notifications = connection.get_proxy_sync<DBusNotifications> ("org.freedesktop.Notifications",
"/org/freedesktop/Notifications", DBusProxyFlags.NONE);
} catch (Error e) {
notifications = null;
}
}
return null;
});
else if (before != "" && after == "") {
lock (notifications) {
notifications = null;
}
}
}

[CCode (instance_pos = -1)]
void send_feedback (owned Feedback feedback) {
var hints = new GLib.HashTable<string, Variant> (null, null);
hints.set ("x-canonical-private-synchronous", new Variant.string ("gala-feedback"));
hints.set ("value", new Variant.int32 (feedback.level));

try {
notification_id = notifications.notify ("gala-feedback", notification_id, feedback.icon, "", "", {}, hints, 2000);
} catch (IOError e) {
critical ("%s", e.message);
}
}
}
}