It has been a little over a week since I committed to using a tiling window manager.
Sure, I am cheating because I am actually still using KDE plus Kröhnkite
but my windows are tiled and I am liking it a lot.
Why this and not i3 or whatever?
Because I don't want to change my lifestyle, I just want my windows to not overlap generally.
Kröhnkite provides enough tiling functionality that I get (I think) the benefits without the massive
upheaval of giving up everything I am used to in my desktop. I still use the Windows Key (ok, ok, the "Meta" key)
to launch apps. I still have a plasma panel with plasmoids at the bottom of my monitor, I can still float
the windows if I want to! I can still use most of the shortcuts from my past 24 years using KDE (yes, really)
and so on.
What are some things I had to change to adapt?
I had to change to focus-follows-mouse. BUT for the first time since I started using FVWM in 1993 I am liking
focus-follows-mouse better than click-to-focus. It turns out KDE's implementation of it is quite nice and
almost "does what I mean". As it says in the docs, "like click to focus, but just don't click".
I removed window decorations. Yes, you can keep them, but they feel out of place.
I set thicker window borders. Resizing windows via shortcuts is just not nice in general, so thicker borders help.
What are some things I have liked?
Fixed tiling layout in one monitor and floating in the other is awesome when needed. And I can get it in place
with one keypress! So, in general, dynamic, separate layouts for each screen is very, very useful.
Having a "tiling" wm that still respects most WM conventions is good. So, popups float. Yay.
The Alt+Enter shortcut to make a window the "important" one is neat.
Love how maximization/minimization works.
What are some things I have not liked?
The "tiled" layout has multiple versions you can switch between with Ctrl+I/D ... and well, sometimes none of
them is exactly what I want? Also, the higher numbered ones only are useful when you have many windows tiling,
and if you don't they don't do anything.
Since I have no window decorations, the brutal inconsistency on app-quitting shortcuts is annoying. It can be ctrl+q or ctrl+x or esc or whatever. I end up doing alt+f4 which feels like windows 3.11.
The UX of KWin scripts is a bit lacking. I installed another one a while ago, called Quarter-Tiling, and I have
removed every trace of it from my system... except for its shortcuts, which will apparently pollute my config
dialogs forever.
I was a sysadmin for a long time. I did that for money, so I never really
wanted to spend time doing the same thing in my own time, which lead to
a severe case of cobbler's children walking barefoot in my private server.
So, today at lunch, I decided to clean up my garbage. So this is what I ended
up with, which is the minimal server that is good enough to be generally
useful for me.
Hosting
This is a cheap VPS provided by the nice folks at burst.net
who are not giving me anything to speak nice things about their service. However,
I will do it anyway:
Crazy cheap ($5.50 but I have a 20% discount for life)
Good amount of monthly bandwidth
Lots of disk space
Good uptime
Fast network
Very cheap
Decent performance
Distribution
I had CentOS 5 installed, and it stays. If burst ever starts offering Ubuntu Precise, I
may switch. Or, since this works, I may not.
What's good about CentOS? It's stable and boring.
What's bad about CentOS? It's too boring. Lots of cool stuff just isn't packaged.
Web Server
I need to serve a bunch of domains, but I have a peculiarity: they are all static
sites. I want:
Low resource usage
Decent performance (that mostly involves supporting ranges and content negotiation)
Stable
Support directory indexes
Easy configuration
Virtual domains by name
Almost any server works well for this. Even Apache, except for the easy configuration
bit. I ended up with gatling because it fits those
criteria fairly well.
It uses about 1.4MB of RAM , which is always nice in a VPS
Here's the configuration: "-c /srv/www -P 2M -d -v -p 80 -F -S" (yes, there is no config file at all)
Virtual domains are just folders and symlinks inside /srv/www which is the easiest possilble way
to do it.
It supports reverse proxying for when I want to try a python web app I am working on.
Mail Server
No, I don't want a mail server. I have gmail and/or a real mail server for that. I want to get
the mails from cron. For this, I used ssmtp
and an extra gmail account. It works, and here's the whole config:
The best I can say about this configuration is that it works, and doesn't involve running
a daemon.
Misc
For when I need to be in two places at the same time: OpenVPN rules, and
there is no argument. I have a squid running occasionally, and there is a Quassel core for IRC stuff. I installed mosh
to make ssh less painful, rsync handles file deployment
and backup storage, cron schedules stuff, and that's it.
Status
Plenty of free RAM and CPU (yes, that's the full process list):
[root@burst1 ~]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 2156 664 ? Ss 22:01 0:00 init [3]
root 1135 0.0 0.1 2260 576 ? S<s 22:01 0:00 /sbin/udevd -d
root 1518 0.0 0.1 1812 572 ? Ss 22:01 0:00 syslogd -m 0
root 1594 0.0 0.1 7240 1032 ? Ss 22:01 0:00 /usr/sbin/sshd
root 1602 0.0 0.2 4492 1112 ? Ss 22:01 0:00 crond
root 1630 0.0 0.1 5684 716 ? Ss 22:01 0:00 /usr/sbin/saslauthd -m /var/run/saslauthd -a pam -n 2
root 1631 0.0 0.0 5684 444 ? S 22:01 0:00 /usr/sbin/saslauthd -m /var/run/saslauthd -a pam -n 2
root 1636 0.0 0.2 3852 1372 ? S 22:01 0:01 /opt/diet/bin/gatling -c /srv/www -P 2M -d -v -p 80 -F -S
root 1677 0.0 0.2 4284 1232 ? Ss 22:02 0:00 SCREEN /root/quasselcore-static-0.7.1
root 1678 0.0 2.1 36688 11148 pts/0 Ssl+ 22:02 0:03 /root/quasselcore-static-0.7.1
root 3228 1.0 0.7 12916 4196 ? Ss 23:28 0:13 mosh-server new -s -c 8
root 3229 0.0 0.3 3848 1588 pts/2 Ss 23:28 0:00 -bash
root 3275 0.0 0.1 2532 908 pts/2 R+ 23:48 0:00 ps aux
[root@burst1 ~]# w
23:49:03 up 1:47, 1 user, load average: 0.00, 0.01, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/2 186.153.52.253 23:28 0.00s 0.01s 0.00s w
[root@burst1 ~]# free
total used free shared buffers cached
Mem: 524800 49100 475700 0 0 0
-/+ buffers/cache: 49100 475700
Swap: 0 0 0
All things considered, fairly happy with the result.
One of the nice things about working at Canonical is that we produce open source software.
I, specifically, work in the team that does the desktop clients for Ubuntu One which is a really cool job, and a really cool piece
of software. However, one thing not enough people know, is that we offer damn nice APIs
for developers. We have to, since all our client code is open source, so we need those
APIs for ourselves.
So, here is a small tutorial about using some of those APIs. I did it using Python and
PyQt for several reasons:
Both are great tools for prototyping
Both have good support for the required stuff (DBus, HTTP, OAuth)
It's what I know and enjoy. Since I did this code on a sunday, I am
not going to use other things.
Having said that, there is nothing python-specific or Qt-specific in the code. Where
I do a HTTP request using QtNetwork, you are free to use libsoup, or whatever.
So, on to the nuts and bolts. The main pieces of Ubuntu One, from a infrastructure
perspective, are Ubuntu SSO Client, that handles user registration and login, and
SyncDaemon, which handles file synchronization.
To interact with them, on Linux, they offer DBus interfaces. So, for example, this is
a fragment of code showing a way to get the Ubuntu One credentials (this would normally
be part of an object's __init__):
# Get the session busbus=dbus.SessionBus():::# Get the credentials proxy and interfaceself.creds_proxy=bus.get_object("com.ubuntuone.Credentials","/credentials",follow_name_owner_changes=True)# Connect to signals so you get a call when something# credential-related happensself.creds_iface=dbus.Interface(self.creds_proxy,"com.ubuntuone.CredentialsManagement")self.creds_proxy.connect_to_signal('CredentialsFound',self.creds_found)self.creds_proxy.connect_to_signal('CredentialsNotFound',self.creds_not_found)self.creds_proxy.connect_to_signal('CredentialsError',self.creds_error)# Call for credentialsself._credentials=Noneself.get_credentials()
You may have noticed that get_credentials doesn't actually return the credentials. What
it does is, it tells SyncDaemon to fetch the credentials, and then, when/if they are there,
one of the signals will be emitted, and one of the connected methods will be called. This
is nice, because it means you don't have to worry about your app blocking while SyncDaemon
is doing all this.
But what's in those methods we used? Not much, really!
defget_credentials(self):# Do we have them already? If not, get'emifnotself._credentials:self.creds_proxy.find_credentials()# Return what we've got, could be Nonereturnself._credentialsdefcreds_found(self,data):# Received credentials, save them.print"creds_found",dataself._credentials=data# Don't worry about get_quota yet ;-)ifnotself._quota_info:self.get_quota()defcreds_not_found(self,data):# No credentials, remove old ones.print"creds_not_found",dataself._credentials=Nonedefcreds_error(self,data):# No credentials, remove old ones.print"creds_error",dataself._credentials=None
So, basically, self._credentials will hold a set of credentials, or None. Congratulations, we
are now logged into Ubuntu One, so to speak.
So, let's do something useful! How about asking for how much free space there is in
the account? For that, we can't use the local APIs, we have to connect to the servers, who
are, after all, the ones who decide if you are over quota or not.
Access is controlled via OAuth. So, to access the API, we need to sign our requests. Here
is how it's done. It's not particularly enlightening, and I did not write it, I just use it:
defsign_uri(self,uri,parameters=None):# Without credentials, return unsigned URLifnotself._credentials:returnuriifisinstance(uri,unicode):uri=bytes(iri2uri(uri))print"uri:",urimethod="GET"credentials=self._credentialsconsumer=oauth.OAuthConsumer(credentials["consumer_key"],credentials["consumer_secret"])token=oauth.OAuthToken(credentials["token"],credentials["token_secret"])ifnotparameters:_,_,_,_,query,_=urlparse(uri)parameters=dict(cgi.parse_qsl(query))request=oauth.OAuthRequest.from_consumer_and_token(http_url=uri,http_method=method,parameters=parameters,oauth_consumer=consumer,token=token)sig_method=oauth.OAuthSignatureMethod_HMAC_SHA1()request.sign_request(sig_method,consumer,token)print"SIGNED:",repr(request.to_url())returnrequest.to_url()
And how do we ask for the quota usage? By accessing the https://one.ubuntu.com/api/quota/ entry point
with the proper authorization, we would get a JSON dictionary with total and used space.
So, here's a simple way to do it:
# This is on __init__self.nam=QtNetwork.QNetworkAccessManager(self,finished=self.reply_finished):::defget_quota(self):"""Launch quota info request."""uri=self.sign_uri(QUOTA_API)url=QtCore.QUrl()url.setEncodedUrl(uri)self.nam.get(QtNetwork.QNetworkRequest(url))
Again, see how get_quota doesn't return the quota? What happens is that get_quota will
launch a HTTP request to the Ubuntu One servers, which will, eventually, reply with the data.
You don't want your app to block while you do that. So, QNetworkAccessManager will call
self.reply_finished when it gets the response:
What else would be nice to have? How about getting a call whenever the status of syncdaemon
changes? For example, when sync is up to date, or when you get disconnected? Again, those are
DBus signals we are connecting in our __init__:
self.status_proxy=bus.get_object('com.ubuntuone.SyncDaemon','/status')self.status_iface=dbus.Interface(self.status_proxy,dbus_interface='com.ubuntuone.SyncDaemon.Status')self.status_iface.connect_to_signal('StatusChanged',self.status_changed)# Get the status as of right nowself._last_status=self.process_status(self.status_proxy.current_status())
The process_status function is boring code to convert the info from
syncdaemon's status into a human-readable thing like "Sync is up-to-date". So we
store that in self._last_status and update the menu.
What menu? Well, a QSystemTrayIcon's context menu! What you have read are the main pieces
you need to create something useful: a Ubuntu One tray app you can use in KDE, XFCE or openbox.
Or, if you are on unity and install sni-qt, a Ubuntu One app indicator!
I have a confession to make. For the last year or so, my main operating system has been Windows 7. Yes, I know, it may come as a shock to some, specially if you have read this which is my post that had most hits in a day ever.
How did that happen? What happened to me? What was I thinking? It's a boring and uninteresting story.
I joined Canonical. My old notebook wouldn't cut it. My new one would not take Ubuntu without a fight. I said "hey, I will live in a VM!". The VM was deadly slow. I had to develop windows software (yes). Some stuff would not work right on the VM. And slowly, things just started piling up in the bare-metal OS, which was, yes Windows 7 Home Premium.
As a whole, Windows 7 is not horrible. Most things work well. What it is, is a desert for a developer. Sure, you can get a plant to grow there, but you have to put a lot of effort into it.
So, today I installed Kubuntu Oneiric (absolutely no problem now!), gathered all the data from the old notebook, the VM, the windows installation, deleted windows, and moved into Linux again, and made Windows the VM.
Since I expect Android on tablets to be a big thing in 2010, I am experimenting with the closest thing I can get: Android in my eee 701 Surf 4G:
I got the testing Android 2.0 image from http://android-x86.org. I had the 1.6 "stable" one but it was... well, it worked awful (half the key combos or menu options caused it to crash, reboot or otherwise autocombust).
So... how is it working? Slow, but it has potential!
The bad:
It boots quite fast... but my tricked full Arch Linux install boots faster.
It works sloooooow, you can see individual letters when you type in the search gadget. I read this is a temporary problem, though.
I am getting a "castrated" experience because the open android app stores are not as well stocked as the official android marketplace (and come on, why the heck can't I get free apps from there???)
I see obvious holes in the app landscape that I suppose are well covered in the market (like, is there a RadioTray replacement?)
No text editor?
No semi-decent word processor? Not even one that generates HTML?
The web browser is pathetic. It may be nice for a phone, but for a "real" system? It's awful. You get the mobile versions of all sites (obviously) and many don't let you switch to the real ones! (even google does that, for Google Reader), and of course, no flash.
The email app is terrible. You can't not-top-post!!!! "In-Reply-To" is off-spec!
The WiFi settings are way too hidden. They should pop if you click on the wifi icon.
The good:
It shuts down incredibly fast.
Some apps are quite nice, specially the Aldiko book reader is awesome (and I can share the ePub books with fbReader on the arch linux side.
The included SSH client has great ideas.
I love the "all your data is in the SD" approach. I do the same thing with Linux. In fact, I have the same exact data organization now on both OSs :-)
The home screen with the sliding app drawer: nice
The "grabbable" system notifications on the top bar: very nice
The "use the menu key to get the menu" thing? genius ;-)
The "everything fullscreen all the time", thing? works on this screen.
App installation is a solved problem here.
I know I will be able to get Qt working native... can't wait!
I am not sold yet, Arch is just so much faster right now, and it can do so much more, but...
I am getting a touchscreen for it, so I can experience it more the way it's meant to be experienced.
I am using it a lot to read at night in bed (Just finished Makers, read it, it's cool!).
I am using it for casual mail reading (I refuse to reply with that broken app).
It's a pretty nice alarm clock, so it's becoming my bedside OS.
I'll write another report once I have the touch screen or a new (hopefully faster!) version running.