[Из песочницы] Dropclock для xscreensaver или как верстальщик писал заставку под Linux
Не помню, где первый раз увидел, но был очарован заставкой DropClock, о которой уже упоминалось на Хабре.
Но вот беда: авторы собрали её только для Win и Mac. Несмотря на это, желание было сильнее ограничений, и я решил во что бы то ни стало собрать собственную реализацию.Первая мысль: попытаться реализовать программный рендер воды и брызги.Так как моё основное направление — веб, я начал искать реализации webGL и эффектов воды. В результате изысканий пришёл к WebGL Water.
Почитал немного документации, попробовал helloworld’ы, но это не моё.
Беглое чтение исходников и попытки правок не привнесли ясности в предмет исследований. Было принято решение посмотреть, а из чего же состоит оригинал.
Скачал с торрентов Win версию, на вайне не пошла, поставил на виртуалку.
На деле оказалось, что это флеш со вшитыми роликами: 10 с цифрами на чёрном фоне и 10 на белом, каждый длится минуту.Распаковщики swf их не потянули, но мне помог конвертер SWF to Video (win). Дальше уже в родной системе перекодировал в mp4/x264 ffmpeg-ом.
Далее дело оставалось за малым — заставить это работать в браузере. Для разнообразия ещё добавил подгрузку погоды с OpenWeatherMap.
Получилась вот такая разметка:
@media screen and (min-height:775 px){
.all{
top: calc ((100% — 755 px) / 2);
height: calc (100% — 202 px);
}
}
@media screen and (max-height:775 px){
.all{
top:25 px;
}
}
Скрипты (js и немного jquery)
var digits = [0,0,0,0];
var msmove = timenow ();
var city = 1485357;
var lastrequesttime = 0;
function timenow (){ return new Date * 1; }
function getRandomArbitary (min, max){return Math.random () * (max — min) + min;}
function extra0(d, e){
if (e===undefined)e=1; for (var i=0; i
$(function (){ // timer step (); $(window).mousemove (function (){ if (document.body.classList.contains ('save')) document.body.classList.remove ('save'); msmove = timenow (); }); });
В firefox видео притормаживало и дребезжало, поэтому изначально я был ориентирован на webkit.Добавил задержку падения цифр, чтобы не исчезали все сразу.Вроде работает, красиво, но нужно запускать это как самостоятельный файл.
Нашёл у себя в убунте системный мини-браузер webbrowser-app и, покапавшись в его параметрах, написал вот такой лаунчер:
#/bin/sh webbrowser-app --chromeless --fullscreen /var/www/vhosts/localhost/dropclock/index.html Но xscreensaver на него сильно ругался и я понял, что что-то делаю не так…Шло время, желание иметь красивую заставку никак не утолялось. 13 сентября, во всероссийский День Программиста, работа была отодвинута, а внимание снова сосредоточено на достижении призрачной цели. До этого видел оконные приложения на Python и выбор пал на него, как впоследствии оказалось, не зря. Раньше никогда ничего на нём не писал. Начал разбирать базовые примеры, добавил webkit.
Ура! Заработало! #!/usr/bin/env python # -*- coding: utf-8 -*-
import pygtk pygtk.require ('2.0') import os, argparse, gtk, webkit from gtk import gdk
class DropClock: def createParser (): self.parser = argparse.ArgumentParser () self.parser.add_argument ('-r', '--root', action='store_const', const=True, default=False) self.namespace = self.parser.parse_args ()
def delete_event (self, widget, event, data=None): print «Вызван сигнал удаления» return False def destroy (self, widget, data=None): print «Вызван сигнал уничтожения» gtk.main_quit ()
def __init__(self): self.parser = argparse.ArgumentParser () self.parser.add_argument ('-r', '--root', action='store_const', const=True, default=False) self.parser.add_argument ('-w', '-window-id', action='store_const', const=True, default='') self.namespace = self.parser.parse_args ()
url = 'file://' + os.path.realpath ('./index.html') self.window = gtk.Window (gtk.WINDOW_TOPLEVEL) self.window.set_default_size (1600, 768) self.window.set_position (gtk.WIN_POS_CENTER) self.window.connect («delete_event», self.delete_event) self.window.connect («destroy», self.destroy) self.browser = webkit.WebView () self.browser.props.settings.props.enable_default_context_menu = False self.browser.load_uri (url) self.window.add (self.browser) self.window.show_all () # if self.namespace.root: # self.window.fullscreen (); def main (self): gtk.main () # self.createParser ();
if __name__ == »__main__»: hello = DropClock () hello.main () А вдруг можно и к xscreensaver’у его прикрутить? Был найден пример заставки на питоне, на базе которого написан свой.Ничего сверхъестественного #!/usr/bin/python
import os import sys
import gtk, webkit from gtk import gdk
# the secret sauce is to get the «window id» out of $XSCREENSAVER_WINDOW # code comes from these two places: # 1) http://pastebin.com/nSCiq1P3 # 2) http://stackoverflow.com/questions/4598581/python-clutter-set-display
class ScreenSaverWindow (gtk.Window): def __init__(self): gtk.Window.__init__(self) pass
def delete_event (self, widget, event, data=None): return False def destroy (self, widget, data=None): gtk.main_quit ()
def realize (self): if self.flags () & gtk.REALIZED: return ident = os.environ.get ('XSCREENSAVER_WINDOW') if not ident is None: print 'if not ident is None:' self.window = gtk.gdk.window_foreign_new (int (ident, 16)) self.window.set_events (gdk.EXPOSURE_MASK | gdk.STRUCTURE_MASK) # added by aja x, y, w, h, depth = self.window.get_geometry () # self.size_allocate (gtk.gdk.Rectangle (x, y, w, h)) self.set_default_size (w, h) self.move (x, y) self.set_decorated (False) # aja — more self.window.set_user_data (self) self.style.attach (self.window) self.set_flags (self.flags () | gtk.REALIZED) #self.window.connect («destroy», self.destroy)
if self.window == None: print 'self.window == None:' self.window = gdk.Window (None, 1024, 768, gdk.WINDOW_TOPLEVEL,(gdk.EXPOSURE_MASK | gdk.STRUCTURE_MASK), gdk.INPUT_OUTPUT) # self.window.set_title («DropClock»)
if self.window!= None: print 'self.window!= None:' #self.window.add_filter (lambda *args: self.filter_event (args)) self.set_flags (self.flags () | gtk.REALIZED) self.browser = webkit.WebView () url = 'file://' + os.path.join (os.path.dirname (__file__) + '/index.html') self.browser.load_uri (url) self.add (self.browser) self.browser.show ()
window = ScreenSaverWindow () window.set_title ('DropClock') window.connect ('delete-event', gtk.main_quit) window.set_default_size (1024, 768) window.realize ()
window.modify_bg (gtk.STATE_NORMAL, gdk.color_parse («black»))
window.show ()
gtk.main () В ~/.xscreensaver под списком добавлена строка:- «Drop Clock» /var/www/vhosts/localhost/dropclock/dropclock_xss.py \n\Впоследствии ещё дорабатывал адаптивность стиля для корректного отображения в маленьком окне, получилось неплохо, мне нравится.Можно считать, что день программиста удался.Видео можно найти по магнет-ссылке.