aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Phillips <dbphillipsnz@gmail.com>2016-02-18 19:24:32 +1300
committerDavid Phillips <dbphillipsnz@gmail.com>2016-02-18 20:54:57 +1300
commitfc3c7e2a7769dcc433e47450455f604442e88631 (patch)
treecafb1002e711682bb621cc35515bbfdf0660fd4a
downloadpetrichor-fc3c7e2a7769dcc433e47450455f604442e88631.tar.xz
Import
-rw-r--r--LICENSE23
-rw-r--r--bg.jpgbin0 -> 156967 bytes
-rw-r--r--iec5009.svg14
-rw-r--r--index.html168
-rw-r--r--index.theme7
-rw-r--r--petrichor.css134
-rw-r--r--petrichor.js150
7 files changed, 496 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f1b6c62
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,23 @@
+Copyright © 2016 David Phillips. All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/bg.jpg b/bg.jpg
new file mode 100644
index 0000000..38a07ff
--- /dev/null
+++ b/bg.jpg
Binary files differ
diff --git a/iec5009.svg b/iec5009.svg
new file mode 100644
index 0000000..ec62caa
--- /dev/null
+++ b/iec5009.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.2" baseProfile="tiny"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="177px" height="202px" viewBox="-0.8 -0.5 177 202" xml:space="preserve">
+<defs>
+</defs>
+<path fill="none" stroke="#FFFFFF" stroke-width="30" stroke-linecap="round" d="M33.7,64.3C22.1,77.2,15,94.3,15,113
+ c0,40.1,32.5,72.7,72.7,72.7c40.1,0,72.7-32.5,72.7-72.7c0-18.7-7.1-35.8-18.7-48.7"/>
+<line fill="none" stroke="#FFFFFF" stroke-width="30" stroke-linecap="round" x1="87.8" y1="15" x2="87.8" y2="113"/>
+</svg>
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..ef7ddc0
--- /dev/null
+++ b/index.html
@@ -0,0 +1,168 @@
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="petrichor.css" />
+ <script type="text/javascript">
+
+ password_prompt = false;
+ selected_user = null;
+ time_remaining = 0
+
+ function show_prompt(text, type)
+ {
+ password_prompt = true;
+ label = document.getElementById('password_label');
+ label.innerHTML = text;
+
+ users = document.getElementById('users');
+ for (i in users.children)
+ {
+ user = users.children[i];
+ if (user.id != ('user_' + selected_user) && user.style != null)
+ user.style.opacity = 0.1;
+ }
+
+ entry = document.getElementById('password_entry');
+ entry.value = '';
+
+ var selected = document.getElementById("user_" + selected_user);
+ rect = selected.getBoundingClientRect();
+ cont = document.getElementById('password_container');
+
+ cont.style.top = rect.top;
+ if (cont.style.left != rect.right)
+ cont.style.left = rect.right;
+ cont.classList.add('shown');
+
+ entry.focus();
+ }
+
+ function show_message(text, type)
+ {
+ cont = document.getElementById('message_container');
+ document.getElementById('message_label').innerHTML = text;
+
+ if (text.length > 0)
+ {
+ var selected = document.getElementById("user_" + selected_user);
+ rect = selected.getBoundingClientRect();
+
+ cont.style.top = rect.top;
+ if (cont.style.left != rect.right)
+ cont.style.left = rect.right;
+ cont.style.top = rect.top;
+ cont.classList.add("shown");
+ } else {
+ cont.classList.remove("shown");
+ }
+ }
+
+ function reset()
+ {
+ users = document.getElementById('users');
+ for (i in users.children)
+ {
+ child = users.children[i];
+ if (child.style != null)
+ child.style.opacity = 1;
+ }
+ document.getElementById('password_container').classList.remove("shown");
+ password_prompt = false;
+ }
+
+ function authentication_complete()
+ {
+// document.getElementById('password_entry').value = '';
+ if (lightdm.is_authenticated)
+ lightdm.start_session_sync(lightdm.authentication_user, lightdm.default_session);
+ else
+ show_message('<span class="error-icon">&#x26A0;</span> Authentication Failed');
+
+ reset();
+ }
+
+ function start_authentication(username)
+ {
+ document.getElementById('message_container').classList.remove("shown");
+
+ if (!password_prompt) {
+ selected_user = username;
+ lightdm.authenticate(username);
+ }
+ }
+
+ function provide_secret()
+ {
+ entry = document.getElementById('password_entry');
+ lightdm.respond(entry.value);
+ }
+
+ function autologin_timer_expired(username)
+ {
+ lightdm.authenticate(lightdm.autologin_user);
+ }
+
+ function countdown()
+ {
+ label = document.getElementById('countdown_label');
+ label.innerHTML = ' in ' + time_remaining + ' seconds';
+ time_remaining--;
+ if (time_remaining >= 0)
+ setTimeout('countdown()', 1000);
+ }
+
+ function update_time()
+ {
+ var days = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
+ var months = ["January","February","March","April","May","June","July","August","September","October","November","December"];
+ var d = new Date();
+ niceHours = d.getHours();
+ niceMinutes = d.getMinutes();
+ // I'm yearning for strftime
+ if (niceHours < 10)
+ niceHours = "0"+niceHours;
+ if (niceMinutes < 10)
+ niceMinutes = "0"+niceMinutes;
+ document.getElementById('date').innerHTML = days[d.getDay()] + ", " + d.getDate() + " " + months[d.getMonth()];
+ document.getElementById('time').innerHTML = niceHours + ":" + niceMinutes;
+ setTimeout('update_time()', 1000);
+ }
+
+ document.write('<div id="users">');
+ for (i in lightdm.users)
+ {
+ user = lightdm.users[i];
+
+ image = user.image;
+
+ document.write('<div class="user" id="user_' + user.name +'"onclick="start_authentication(\'' + user.name + '\')" style="cursor: pointer;">');
+ document.write('<img class="avatar" src="file:///' + image + '" /><span class="name">'+user.display_name+'</span>');
+ if (user.name == lightdm.autologin_user && lightdm.autologin_timeout > 0)
+ document.write('<span id="countdown_label"></span>');
+ document.write(' </div>');
+ }
+ document.write('</div>');
+
+
+ time_remaining = lightdm.autologin_timeout;
+ if (time_remaining > 0)
+ countdown();
+ </script>
+ </head>
+
+ <body onclick="reset();" onload="update_time();">
+ <div id="date-container">
+ <div id="date"></div>
+ <div id="time"></div>
+ </div>
+ <div id="password_container">
+ <form action="javascript:provide_secret()">
+ <span id="password_label"></span>
+ <input id="password_entry" type="password" />
+ </form>
+ </div>
+ <div id="message_container">
+ <span id="message_label"></span>
+ </div>
+ <img id="shutdown" src="iec5009.svg" onclick="lightdm.shutdown();" />
+ </body>
+</html>
diff --git a/index.theme b/index.theme
new file mode 100644
index 0000000..2ef8456
--- /dev/null
+++ b/index.theme
@@ -0,0 +1,7 @@
+[theme]
+name=Petrichor
+version=1.0
+description=Petrichor Theme
+engine=lightdm-webkit2-greeter
+url=index.html
+session=dwm
diff --git a/petrichor.css b/petrichor.css
new file mode 100644
index 0000000..36dc4d9
--- /dev/null
+++ b/petrichor.css
@@ -0,0 +1,134 @@
+html
+{
+ color: #FFF;
+ background-image: url('bg.jpg');
+ background-size: cover;
+ font-family: "Roboto Condensed";
+}
+
+body,html
+{
+ padding: 0px;
+ margin: 0px;
+ width: 100%;
+}
+
+#shutdown
+{
+ cursor: pointer;
+ opacity: 0.5;
+ width: 96px;
+ position: absolute;
+ right: 50px;
+ bottom: 50px;
+ transition: opacity ease 0.3s;
+}
+
+.error-icon
+{
+ font-size: 1.1em;
+ font-weight: bold;
+ color: #F00;
+}
+
+#shutdown:hover
+{
+ opacity: 1;
+}
+
+#users div.user
+{
+ transition: opacity ease 0.15s;
+}
+
+div.user
+{
+ text-align: center;
+ color: white;
+ margin-top: 2em;
+}
+
+.avatar
+{
+ object-fit: cover;
+ width: 96px;
+ height: 96px;
+ border-radius: 48px;
+}
+
+.name
+{
+ display: block;
+}
+
+#password_prompt, #password_entry
+{
+ display: block;
+ font-size: 20px;
+}
+
+#users
+{
+ position: absolute;
+ bottom: 50px;
+ left: 50px;
+}
+
+#message_container
+{
+ font-size: 20px;
+}
+
+#password_entry
+{
+ color: #333;
+ opacity: inherit;
+ background-color: rgba(255,255,255,255,0.2);
+ padding: 0.2em;
+ border: 1px solid #DDD;
+ border-radius: 5px;
+}
+
+#message_container, #password_container
+{
+ height: 96px;
+ display: table;
+ position: absolute;
+ padding-left: 2em;
+ visibility: hidden;
+ opacity: 0;
+ transition: visibility 0s linear 0.15s, opacity 0.15s linear;
+}
+
+#password_container.shown, #message_container.shown
+{
+ visibility: visible;
+ opacity: 1;
+ transition: opacity 0.15s linear 0.05s;
+}
+
+#message_label, #password_container > form
+{
+ display: table-cell;
+ vertical-align: middle;
+}
+
+#date, #time
+{
+ font-family: Roboto;
+ text-align: right;
+ color: #FFF;
+}
+
+#date
+{
+ margin-top: 50px;
+ margin-right: 65px;
+ font-size: 50px;
+}
+
+#time
+{
+ margin-right: 30px;
+ font-size: 240px;
+}
diff --git a/petrichor.js b/petrichor.js
new file mode 100644
index 0000000..c96c21e
--- /dev/null
+++ b/petrichor.js
@@ -0,0 +1,150 @@
+password_prompt = false;
+selected_user = null;
+time_remaining = 0
+
+function show_prompt(text, type)
+{
+ password_prompt = true;
+ label = document.getElementById('password_label');
+ label.innerHTML = text;
+
+ users = document.getElementById('users');
+ for (i in users.children)
+ {
+ user = users.children[i];
+ if (user.id != ('user_' + selected_user) && user.style != null)
+ user.style.opacity = 0.1;
+ }
+
+ entry = document.getElementById('password_entry');
+ entry.value = '';
+
+ var selected = document.getElementById("user_" + selected_user);
+ rect = selected.getBoundingClientRect();
+ cont = document.getElementById('password_container');
+
+ cont.style.top = rect.top;
+ if (cont.style.left != rect.right)
+ cont.style.left = rect.right;
+ cont.classList.add('shown');
+
+ entry.focus();
+}
+
+function show_message(text, type)
+{
+ cont = document.getElementById('message_container');
+ document.getElementById('message_label').innerHTML = text;
+
+ if (text.length > 0)
+ {
+ var selected = document.getElementById("user_" + selected_user);
+ rect = selected.getBoundingClientRect();
+
+ cont.style.top = rect.top;
+ if (cont.style.left != rect.right)
+ cont.style.left = rect.right;
+ cont.style.top = rect.top;
+ cont.classList.add("shown");
+ } else {
+ cont.classList.remove("shown");
+ }
+}
+
+function reset()
+{
+ users = document.getElementById('users');
+ for (i in users.children)
+ {
+ child = users.children[i];
+ if (child.style != null)
+ child.style.opacity = 1;
+ }
+ document.getElementById('password_container').classList.remove("shown");
+ password_prompt = false;
+}
+
+function authentication_complete()
+{
+ if (lightdm.is_authenticated)
+ lightdm.start_session_sync(lightdm.authentication_user, lightdm.default_session);
+ else
+ show_message('<span class="error-icon">&#x26A0;</span> Authentication Failed');
+
+ reset();
+}
+
+function start_authentication(username)
+{
+ document.getElementById('message_container').classList.remove("shown");
+
+ if (!password_prompt) {
+ selected_user = username;
+ lightdm.authenticate(username);
+ }
+}
+
+function provide_secret()
+{
+ entry = document.getElementById('password_entry');
+ lightdm.respond(entry.value);
+}
+
+function autologin_timer_expired(username)
+{
+ lightdm.authenticate(lightdm.autologin_user);
+}
+
+function countdown()
+{
+ label = document.getElementById('countdown_label');
+ label.innerHTML = ' in ' + time_remaining + ' seconds';
+ time_remaining--;
+ if (time_remaining >= 0)
+ setTimeout('countdown()', 1000);
+}
+
+function update_time()
+{
+ var days = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
+ var months = ["January","February","March","April","May","June","July","August","September","October","November","December"];
+ var d = new Date();
+ niceHours = d.getHours();
+ niceMinutes = d.getMinutes();
+ // I'm yearning for strftime
+ if (niceHours < 10)
+ niceHours = "0"+niceHours;
+ if (niceMinutes < 10)
+ niceMinutes = "0"+niceMinutes;
+ document.getElementById('date').innerHTML = days[d.getDay()] + ", " + d.getDate() + " " + months[d.getMonth()];
+ document.getElementById('time').innerHTML = niceHours + ":" + niceMinutes;
+ setTimeout('update_time()', 1000);
+}
+
+function start()
+{
+ document.write('<div id="users">');
+ for (i in lightdm.users)
+ {
+ user = lightdm.users[i];
+
+ if (user.image.match(/\.face$/))
+ image = '/usr/share/icons/Adwaita/256x256/emotes/face-laugh.png';
+ else
+ image = user.image;
+
+ document.write('<div class="user" id="user_' + user.name +'"onclick="start_authentication(\'' + user.name + '\')" style="cursor: pointer;">');
+ document.write('<img class="avatar" src="file:///' + image + '" /><span class="name">'+user.display_name+'</span>');
+
+ if (user.name == lightdm.autologin_user && lightdm.autologin_timeout > 0)
+ document.write('<span id="countdown_label"></span>');
+
+ document.write(' </div>');
+ }
+ document.write('</div>');
+
+
+ time_remaining = lightdm.autologin_timeout;
+ if (time_remaining > 0)
+ countdown();
+}