Shallow Thoughts : : Sep
Akkana's Musings on Open Source Computing and Technology, Science, and Nature.
Fri, 30 Sep 2011
So everybody's complaining about that new Facebook ticker. You know,
the thing that sits on the right sidebar and constantly and distractingly
updates with stupid stuff you don't care about and wouldn't be able to
click on quickly enough even if you tried.
My mom forwarded me a link to a neat page she'd seen with instructions on
removing the ticker using Adblock Plus.
A good idea -- I hadn't thought about using Adblock, though it does
seem obvious in retrospect.
But I don't currently have Adblock installed in the profile I use for
Facebook -- I keep Facebook separate from my everyday browsing,
since I don't want Facebook tracking all the other sites I visit.
Could I do the same thing with userContent.css?
It turned out to be quite easy. Copying the exact pattern didn't work,
but a minute or two with Firebug told me the CSS class of the ticker.
I edited chrome/userContent.css in my profile. If you don't
have one already, just look for userContent-example.css and create
a new file in the same directory without the -example part, named
just userContent.css. I added this line:
.tickerOnTop { display: none !important; }
Restart firefox, and presto! No more ticker.
Tags: web.firefox, mozilla, annoyances, user interface
[
21:58 Sep 30, 2011
More tech/web |
permalink to this entry |
]
Tue, 27 Sep 2011
Every now and then I have to run a program that doesn't manage its
tooltips well. I mouse over some button to find out what it does,
a tooltip pops up -- but then the tooltip won't go away. Even if I
change desktops, the tooltip follows me and stays up on all desktops.
Worse, it's set to stay on top of all other windows, so it blocks
anything underneath it.
The places where I see this happen most often are XEphem (probably as an
artifact of the broken Motif libraries we're stuck with on Linux);
Adobe's acroread (Acrobat Reader), though perhaps that's gotten
better since I last used it; and Wine.
I don't use Wine much, but lately I've had to use it
for a medical imaging program that doesn't seem to have a Linux
equivalent (viewing PETscan data). Every button has a tooltip, and
once a tooltip pops up, it never goes aawy. Eventually I might have
five of six of these little floating windows getting in the way of
whatever I'm doing on other desktops, until I quit the wine program.
So how does one get rid of errant tooltips littering your screen?
Could I write an Xlib program that could nuke them?
Finding window type
First we need to know what's special about tooltip windows, so the program can
identify them. First I ran my wine program and produced some sticky tooltips.
Once they were up, I ran xwininfo and clicked on a tooltip.
It gave me a bunch of information about the windows size and location,
color depth, etc. ... but the useful part is this:
Override Redirect State: yes
In X,
override-redirect windows
are windows that are immune to being controlled by the window manager.
That's why they don't go away when you change desktops, or move when
you move the parent window.
So what if I just find all override-redirect windows and unmap (hide) them?
Or would that kill too many innocent victims?
Python-Xlib
I thought I'd have to write my little app in C, since it's doing
low-level Xlib calls. But no -- there's a nice set of Python bindings,
python-xlib. The documentation isn't great, but it was still pretty
easy to whip something up.
The first thing I needed was a window list: I wanted to make sure I
could find all the override-redirect windows. Here's how to do that:
from Xlib import display
dpy = display.Display()
screen = dpy.screen()
root = screen.root
tree = root.query_tree()
for w in tree.children :
print w
w is a
Window
(documented here). I see in the documentation that I can get_attributes().
I'd also like to know which window is which -- calling get_wm_name()
seems like a reasonable way to do that. Maybe if I print them, those
will tell me how to find the override-redirect windows:
for w in tree.children :
print w.get_wm_name(), w.get_attributes()
Window type, redux
Examining the list, I could see that override_redirect was one of
the attributes.
But there were quite a lot of override-redirect windows.
It turns out many apps, such as Firefox, use them for things like
menus. Most of the time they're not visible. But you can look at
w.get_attributes().map_state to see that.
So that greatly reduced the number of windows I needed to examine:
for w in tree.children :
att = w.get_attributes()
if att.map_state and att.override_redirect :
print w.get_wm_name(), att
I learned that tooltips from well-behaved programs like Firefox tended
to set wm_name to the contents of the tooltip. Wine doesn't -- the wine
tooltips had an empty string for wm_name. If I wanted to kill just
the wine tooltips, that might be useful to know.
But I also noticed something more important: the tooltip windows
were also "transient for" their parent windows.
Transient
for means a temporary window popped up on behalf of a parent window;
it's kept on top of its parent window, and goes away when the parent does.
Now I had a reasonable set of attributes for the windows I wanted to
unmap. I tried it:
for w in tree.children :
att = w.get_attributes()
if att.map_state and att.override_redirect and w.get_wm_transient_for():
w.unmap()
It worked! At least in my first test: I ran the wine program, made a
tooltip pop up, then ran my killtips program ... and the tooltip disappeared.
Multiple tooltips: flushing the display
But then I tried it with several tooltips showing (yes, wine will pop
up new tooltips without hiding the old ones first) and the result
wasn't so good. My program only hid the first tooltip. If I ran it again,
it would hide the second, and again for the third. How odd!
I wondered if there might be a timing problem.
Adding a time.sleep(1)
after each w.unmap()
fixed it, but sleeping surely wasn't the right solution.
But X is asynchronous: things don't necessarily happen right away.
To force (well, at least encourage) X to deal with any queued events
it might have stacked up, you can call dpy.flush().
I tried adding that after each w.unmap(), and it worked. But it turned
out I only need one
dpy.flush()
at the end of the program, just exiting. Apparently if I don't do that,
only the first unmap ever gets executed by the X server, and the rest
are discarded. Sounds like flush() is a good idea as the last line
of any python-xlib program.
killtips will hide tooltips from well-behaved programs too.
If you have any tooltips showing in Firefox or any GTK programs, or
any menus visible, killtips will unmap them.
If I wanted to make sure the
program only attacked the ones generated by wine, I could
add an extra test on whether w.get_wm_name() == "".
But in practice, it doesn't seem to be a problem. Well-behaved
programs handle having their tooltips unmapped just fine: the next
time you call up a menu or a tooltip, the program will re-map it.
Not so in wine: once you dismiss one of those wine tooltips, it's gone
forever, at least until you quit and restart the program. But that
doesn't bother me much: once I've seen the tooltip for a button and
found out what that button does, I'm probably not going to need to see
it again for a while.
So I'm happy with killtips, and I think it will solve the problem.
Here's the full script:
killtips.
Tags: X11, python, programming, tooltips, annoyances
[
11:36 Sep 27, 2011
More programming |
permalink to this entry |
]
Sat, 24 Sep 2011
I suspect all technical people -- at least those with a web presence
-- get headhunter spam. You know, email saying you're perfect for a
job opportunity at "a large Fortune 500 company" requiring ten years'
experience with technologies you've never used.
Mostly I just delete it. But this one sent me a followup --
I hadn't responded the first time, so surely I hadn't seen it and
here it was again, please respond since I was perfect for it.
Maybe I was just in a pissy mood that night. But
look, I'm a programmer, not a DBA -- I had to look it up to verify
that I knew what DBA stood for. I've never used Oracle.
A "Production DBA with extensive Oracle experience" job is right out,
and there's certainly nothing in my resume that would suggest that's
my line of work.
So I sent a brief reply, asking,
Why do you keep sending this?
Why exactly do you think I'm a DBA or an Oracle expert?
Have you looked at my resume? Do you think spamming people
with jobs completely unrelated to their field will get many
responses or help your credibility?
I didn't expect a reply. But I got one:
I must say my credibility is most important and it's unfortunate
that recruiters are thought of as less than in these regards. And, I know it
is well deserved by many of them.
In fact, Linux and SQL experience is more important than Oracle in this
situation and I got your email address through the Peninsula Linux Users
Group site which is old info and doesn't give any information about its
members' skill or experience. I only used a few addresses to experiment with
to see if their info has any value. Sorry you were one of the test cases but
I don't think this is spamming and apologize for any inconvenience it caused
you.
[name removed], PhD
A courteous reply. But it stunned me.
Harvesting names from old pages on a LUG website, then sending a
rather specific job description out to all the names harvested,
regardless of their skillset -- how could that possibly not be
considered spam? isn't that practically the definition of spam?
And how could a recruiter expect to seem credible after sending this
sort of non-targeted mass solicitation?
To technical recruiters/headhunters: if you're looking for
good technical candidates, it does not help your case to spam people
with jobs that show you haven't read or understood their resume.
All it does is get you a reputation as a spammer. Then if you do, some
day, have a job that's relevant, you'll already have lost all credibility.
Tags: spam, headhunters, tech
[
21:30 Sep 24, 2011
More tech |
permalink to this entry |
]
Sun, 18 Sep 2011
The first time I saw a
Maxbotix Ultrasonic
Rangefinder, I knew I had to have one. My mind filled with thoughts
of bats and dolphins, echolocating. I'm the kind of geek-slash-animal-lover
who, as a kid, used to swim underwater making noises trying to
echolocate like a dolphin.
(I probably shouldn't admit to that. And anyway, it never worked.)
Only in the last few years have I learned that some blind people
actually do echolocate, though not underwater.
But it takes a long time to learn, and not everyone can do it.
Wouldn't it be great (especially if you were blind)
if you could build something you attach to a
hat or glasses? You could walk around hearing pings indicating whether
you're about to walk into anything, or get walked into. How cool is that?
I already had a sonar rangefinder, which I used for a simple
proximity
webcam demo in a talk on plug computing.
With the demo over and the device known to work, I could finally try
making a sonar device.
Clicks in earbuds
I wanted to use earbuds -- no reason everyone else should need to hear
your sonar as you walk around. But how do you do that?
The obvious way works, as it turns out. Connect one earbud wire to
one of the Arduino's digital outputs (via a resistor, to reduce the volume),
the other to ground. Of course
you can connect both earbuds to the same output, or to different outputs
if you want to send different signals to each ear.
Then program the Arduino to set the line high, pause a short time, then
set it low again, like this:
#define EARBUD 1 /* pin number */
#define clicklen 10 /* milliseconds */
#define timeout 2000 /* milliseconds */
void loop()
{
while (1) {
digitalWrite(EARBUD, 1);
delay(clicklen);
digitalWrite(EARBUD, 0);
delay(timeout);
}
}
This gives a short click ever 2 seconds. Once the rangefinder is
hooked up, I'll make timeout a variable and adjust it according
to the rangefinder signal.
I used cheap earbuds: the digital output is sending a square wave and
probably isn't good for earbuds, so don't risk a set you care about.
I had to experiment to find a good resistor value to keep
the volume audible but quiet enough not to be annoying. 10k was about
right for my dollar-store earbuds.
Of course, if you were actually building this device you'd want
to use a potentiometer so you'll be able to adjust the volume as you walk,
or use earbuds that come with one.
One sound-on-arduino page I found put a capacitor inline with the resistor
... to smooth out the waveform?
I tried a 47 uF capacitor, but it didn't make any difference I could hear.
Adding the rangefinder
The rangefinder plugs in just like in my
proximity
webcam project: Power on the rangefinder to 5v on the Arduino,
Gnd to ground, and AN (analog signal) to the Arduino's analog pin 1.
Then I just need to read the rangefinder output and map it to an
appropriate delay between clicks. That took some tuning. Initially
I just made the equation linear, for simplicity, and I experimented
to see when I wanted to hear the clicks getting closer together.
Something like this, added at the beginning of loop():
#define FACTOR 15
#define MINRANGE 20
float range = analogRead(RANGEFINDER);
int timeout = FACTOR * (range-MINRANGE);
Pretty cool -- now I could hear the clicks get really close together
as I put my hand in front of the sensor.
But when I took the device outside, I found sometimes it would stop
making noise for a long time, or even forever.
Some of that was due to an earlier equation I used, where the values
could sometimes be negative. (With the equation I showed above, they
probably won't be -- I've never seen the rangefinder return single
digits.) So I added a minimum:
#define MIN_TIMEOUT 5
if (timeout < MIN_TIMEOUT) timeout = MIN_TIMEOUT;
That got rid of the "stops clicking and never starts again" problem.
But I still had delays that were too long: if you face an open area,
you might have a timeout of 6 seconds, and you could easily turn and
walk into a tree before those 6 seconds are up. So I made a maximum
timeout of 2 seconds: it will never go longer than that between checks.
#define MAX_TIMEOUT 2000
if (timeout > MAX_TIMEOUT) timeout = MAX_TIMEOUT;
Much better! Now I could walk around and -- usually -- get warned before
I got too close to obstacles.
You can grab the source and a Makefile for my test program program at
sonarduino.
It's not perfect. Sometimes it gets a spurious reading from the
rangefinder, and waits too long before warning you. It would really
be better if it continued to check during those long timeouts.
And the rangefinder really doesn't give very reliable results much
beyond a meter and a half. There are other models of rangefinder,
and you'd probably want to experiment with several models before
trying to use one of these gizmos to walk around at normal speed.
You might even want to have two different types of
So this is just a start. I'm not going to give dolphins or bats any
competition yet, and it's certainly not good enough that a blind person
could use it to walk around at full speed.
But it's a fun project, very easy to build, and I'm looking forward
to playing with it further.
Tags: arduino, hardware, sonar, echolocation, maker
[
16:54 Sep 18, 2011
More hardware |
permalink to this entry |
]
Tue, 13 Sep 2011
What do you do about all that mail -- junk and otherwise -- with
incriminating information on it? You know, the stuff with your name
and bank account numbers and such that you don't want an identity
thief to get? If you toss them in the recycling (or, worse, the trash),
who knows what might happen to them between here and the recycling plant?
Some people buy a shredder -- an electric lump of a thing that sits in
a corner and turns paper into streamers. I guess it sounds kinda fun,
but it costs money, uses electricity and takes up space. Or you can
take all the assorted bits of paper and burn them in the fireplace
or barbecue, but that's kind of a hassle and it makes a lot of ash
and smoke.
A few years ago, Dave came up with what we think is a better idea:
we make the paper into condensed paper fire-bricks, which we then burn
the fireplace. They burn much cleaner and more slowly than those
bits of paper, and they're fun to make. Here's how.
First, you collect a lot of paper -- we keep a separate wastebasket where
we crumple all the papers (no need to shred them).
When you have enough to start a batch, put the papers in a bucket
or other container, and fill with enough water that the paper is covered.
Let that sit for a while -- a week or two -- stirring occasionally
(maybe twice a day). Ideally, you want the paper to break down to a
soup in which you can't read any of the incriminating text.
But if you get impatient, you can move on to the next step little
early as long as all everything has gotten soft and the paper is
starting to break up.
Once everything's soft and soupy, you want a mold of whatever shape you
want your eventual brick to be. Cardboard ice cream containers
(pictured here) work nicely, or you can use a bowl, a small bucket,
practically anything.
Transfer the wet mush into your mold, squeezing out as much excess
water as you can. The drier you can get it, the less time it will take
to cure. Pack it into your mold as tightly as you can (understanding
that if you're using a cardboard ice cream container, it can't take
much packing of wet stuff).
Put the mold in a sunny place in the hard to dry, if possible.
You can speed the process along by using a mold that lets excess water
drain, or by compressing the mush every so often (once or twice a day)
and letting any water run out. Early on, we put weights on top to
keep the mush compressed, but it doesn't seem to make that much difference.
When it seems quite dry, remove it from the mold. (This mold is an old
microwave popcorn making bowl that cracked, so it's no longer good
for making popcorn.)
Early on, we thought it might be interesting to pack in some other
flammable material, like bits of wood and nutshells left over from
feeding squirrels.
That gives you a lumpy breccia (the lower brick in the picture)
that doesn't burn very consistently, because it's full of holes.
Not a good idea, as it turned out.
The upper brick in the photo is what you get if you let your soup
dissolve for a long time and don't add any lumpy stuff to it: a
nice smooth brick of pressed paperboard. It's okay to add a bit
of small soft stuff like dryer lint. But skip the nutshells --
those can go in the compost bin or yard waste container.
Your final brick, removed from the mold, should be a nice homogeneous
piece of paperboard. It's still fairly light and not very dense ...
but it burns smoothly and cleanly, and doesn't send sparks up the
chimmney like those original bits of paper would have.
Save on heating bills? Well, if you make paper bricks all summer, by
winter time you'll probably have saved up enough to burn for ...
maybe an hour or two. No, this isn't going to heat your home.
Still, it's an amusing, inexpensive and electricity-free way of
disposing of that pesky printed privacy-pilfering paper that plagues us all.
Tags: recycling, privacy
[
10:43 Sep 13, 2011
More misc |
permalink to this entry |
]
Fri, 09 Sep 2011
This post is, above all, a lesson in doing a web search first.
Even when what you're looking for is so obscure you're sure no one
else has wanted it. But the script I got out of it might turn out to
be useful.
It started with using
Bitlbee for Twitter.
I love bitlbee -- it turns a Twitter stream into just another IRC channel
tab in the xchat I'm normally running anyway.
The only thing I didn't love about bitlbee is that, unlike the twitter
app I'd previously used, I didn't have any way to keep track of when I
neared the 140-character limit. There were various ways around that,
mostly involving pasting the text into other apps before submitting it.
But they were all too many steps.
It occurred to me that one way around this was to select-all, then run
something that would show me the number of characters in the X selection.
That sounded like an easy app to write.
Getting the X selection from Python
I was somewhat surprised to find that Python has no way of querying the
X selection. It can do just about everything else -- even
simulate
X events. But there are several
command-line applications that can print the selection, so it's easy
enough to run xsel
or xclip
from Python and
read the output.
I ended up writing a little app that brings up a dialog showing the
current count, then hangs around until you dismiss it, querying the
selection once a second and updating the count. It's called
countsel.
Of course, if you don't want to write a Python script you can use
commandline tools directly. Here are a couple of examples, using xclip instead
of xsel:
xterm -title 'lines words chars' -geometry 25x2 -e bash -c 'xclip -o | wc; read -n 1'
pops up a terminal showing the "wc" counts of the selection once, and
xterm -title 'lines words chars' -geometry 25x1 -e watch -t 'xclip -o | wc'
loops over those counts printing them once a second.
Binding commands to a key is different for every window manager.
In Openbox, I added this to rc.xml to call up my program
whenever I type W-t (short for Twitter):
<keybind key="W-t">
<action name="Execute">
<execute>/home/akkana/bin/countsel</execute>
</action>
</keybind>
Now, any time I needed to check my character count, I could triple-click
or type Shift-Home, then hit W-t to call up the dialog and get a count.
Then I could leave the dialog up, and whenever I wanted a new count,
just Shift-Home or triple-click again, and the dialog updates automatically.
Not perfect, but not bad.
Xchat plug-in for a much more elegant solution
Only after getting countsel working did it occur to me
to wonder if anyone else had the same Bitlbee+xchat+twitter problem.
And a web search found exactly what I needed:
xchat-inputcount.pl,
a wonderful xchat script that adds a character-counter next to the
input box as you're typing. It's a teensy bit buggy, but still, it's
far better than my solution. I had no idea you could add user-interface
elements to xchat like that!
But that's okay. Countsel didn't take long to write.
And I've added word counting to countsel, so I can use it for
word counts on anything I'm writing.
Tags: x, programming, python
[
12:32 Sep 09, 2011
More programming |
permalink to this entry |
]
Sat, 03 Sep 2011
Fairly often, I want a list of subdirectories inside a
particular directory. For instance, when posting blog entries,
I may need to decide whether an entry belongs under "linux"
or some sub-category, like "linux/cmdline" -- so I need to remind
myself what categories I have under linux.
But strangely, Linux offers no straightforward way to ask that question.
The ls
command lists directories -- along with the files.
There's no way to list just the directories. You can list the directories
first, with the --group-directories-first option.
Or you can flag the directories specially: ls -F
appends a slash to each directory name, so instead of linux
you'd see linux/
. But you still have to pick the directories
out of a long list of files. You can do that with grep, of course:
ls -1F ~/web/blog/linux | grep /
That's a one, not an ell: it tells ls to list files one per line.
So now you get a list of directories, one per line, with a slash
appended to each one. Not perfect, but it's a start.
Or you can use the find
program, which has an option
-type d
that lists only directories. Perfect, right?
find ~/web/blog/linux -maxdepth 1 -type d
Except that lists everything with full pathnames:
/home/akkana/web/blog/linux, /home/akkana/web/blog/linux/editors,
/home/akkana/web/blog/linux/cmdline and so forth. Way too much noise
to read quickly.
What I'd really like is to have just a list of directory names --
no slashes, no newlines. How do we get from ls or find output to that?
Either we can start with find and strip off all the path information,
either in a loop with basename or with a sed command; or start with ls
-F, pick only the lines with slashes, then strip off those slashes.
The latter sounds easier.
So let's go back to that ls -1F ~/web/blog/linux | grep /
command. To strip off the slashes, you can use sed's s (substitute)
command. Normally the syntax is sed 's/oldpat/newpat/'. But since
slashes are the pattern we're substituting, it's better to use
something else as the separator character. I'll use an underscore.
The old pattern, the one I want to replace, is / -- but I only want to
replace the last slash on the line, so I'll add a $ after it,
representing end-of-line. The new pattern I want instead of the slash
is -- nothing.
So my sed argument is 's_/$__'
and the command becomes:
ls -1F ~/web/blog/linux | grep / | sed 's_/$__'
That does what I want. If I don't want them listed one per line, I can
fudge that using backquotes to pass the output of the whole command to
the shell's echo command:
echo `ls -1F ~/web/blog/linux | grep / | sed 's_/$__'`
If you have a lot of directories to list and you want ls's nice
columnar format, that's a little harder.
You can ls the list of directories (the names inside the backquotes),
ls `your long command`
-- except that now that you've stripped off the path information,
ls won't know where to find the files. So you'd have to change
directory first:
cd ~/web/blog/linux; ls -d `ls -1F | grep / | sed 's_/$__'`
That's not so good, though, because now you've changed directories
from wherever you were before. To get around that, use parentheses
to run the commands inside a subshell:
(cd ~/web/blog/linux; ls -d `ls -1F | grep / | sed 's_/$__'`)
Now the cd only applies within the subshell, and when the command
finishes, your own shell will still be wherever you started.
Finally, I don't want to have to go through this discovery process
every time I want a list of directories. So I turned it into a couple
of shell functions, where $* represents all the arguments I pass to
the command, and $1 is just the first argument.
lsdirs() {
(cd $1; /bin/ls -d `/bin/ls -1F | grep / | sed 's_/$__'`)
}
lsdirs2() {
echo `/bin/ls -1F $* | grep / | sed 's_/$__'`
}
I specify /bin/ls because I have a function overriding ls in my .zshrc.
Most people won't need to, but it doesn't hurt.
Now I can type lsdirs ~/web/blog/linux
and get a nice
list of directories.
Update, shortly after posting:
In zsh (which I use), there's yet another way: */
matches
only directories. It appends a trailing slash to them, but
*(/)
matches directories and omits the trailing slash.
So you can say
echo ~/web/blog/linux/*(/:t)
:t strips the directory part of each match.
To see other useful : modifiers, type
ls *(:
then hit TAB.
Thanks to Mikachu for the zsh tips. Zsh can do anything, if you can
just figure out how ...
Tags: cmdline, shell, pipelines, linux
[
11:22 Sep 03, 2011
More linux/cmdline |
permalink to this entry |
]