Losing Battle

Illustration

Apple is screwing their customers again. This time literary - there is new screw head called “Pentalobe” that is slowly working it’s way in Apple products.

Current effect is that nobody can open iPhone without risking damage to screw but I wonder what net effect will be. There are already products that enable you to replace that “secure” screw with normal Phillips one. I wonder how long it will take for everybody to get proper pentalobe screwdriver. A week? A month?

Mono, Ubuntu and Clipboard

Reading clipboard in .NET is fairly straightforward.

   var text = Clipboard.GetText();

Once you stumble into Mono under Linux, things tend to change. Clipboard works only inside your application, rest of system works on different plane altogether. In order to get text from system clipboard we need to have following code:

    Gtk.Clipboard clippy = Gtk.Clipboard.Get(Gdk.Atom.Intern("CLIPBOARD", false));
    var text = clippy.WaitForText();

And here comes the problem. These functions need reference to both gdk-sharp and gtk-sharp. Unfortunately this also means that you cannot run it without MONO runtime. You can forget running application under Microsoft’s .NET Framework. Even if we don’t use those functions our applications will fail upon startup since it cannot resolve all references.

I solved this issue by having separate .dll for clipboard operations on Linux but I haven’t created any reference to it. In order to determine clipboard content I use reflection to load it (only if we are on Mono):

private string GetClipboardText() {
    if (IsRunningOnMono) {				
        var fullExePath = new FileInfo(Assembly.GetExecutingAssembly().Location);
        var gtkAss = Assembly.LoadFile(Path.Combine(fullExePath.DirectoryName, "GtkClipboard.dll"));
        var assMethod = gtkAss.GetTypes()[0].GetMethod("GetGtkText");
        txtClipboard.Text = assMethod.Invoke(null, new object[] { }) as string;
    } else {
       txtClipboard.Text = Clipboard.GetText();
    }
}

private static bool IsRunningOnMono {
    get {
        return (Type.GetType("Mono.Runtime") != null);
    }
}

And what should we put in our .dll? It ends up that it is quite simple code:

public static class Clipboard {
    public static String GetGtkText() {
        Gtk.Clipboard clipboard = Gtk.Clipboard.Get(Gdk.Atom.Intern("CLIPBOARD", false));
        if (clipboard != null) {
            return clipboard.WaitForText();
        } else {
            return "";
        }
    }
}

P.S. You will notice here that reflection code loads first class that comes in array. Since I only have one class in that whole .dll this is not an issue. If you add more classes to that assembly take care that you select correct one.

Showing Form in Mono

When I develop application that should be usable on Linux I usually program it in C# with Visual Studio. From time to time I test it with Mono Migration Analyzer. End result is usually runnable under Linux after some further debugging. This time I had to create application that would be used primarily under Linux so I took different approach - MonoDevelop.

Most difficult thing to get used to after transfer from Visual Studio world is lack of Windows Forms designer; everything needs to be done by hand. Doing that I stumbled upon strange behavior. Take this simple code:

private void SomeButton_Click(object Sender, EventArgs e) {
    using (var frm = new SomeForm()) {
        frm.ShowDialog(this);
    }
}
...
internal class SomeForm : Form {
}

This code is dead simple - there is no chance of error. However this code also doesn’t work properly under Mono 2.6 (I haven’t checked other versions). Form will be shown first time button is clicked but not second time. What puzzled me the most is fact that I knew that that ShowDialog should work - other .NET application that I used under Linux worked perfectly.

First rule of bug-triage is to trim code as much as possible to determine which line is problematic one - there was nothing to trim here and I still had a bug. As it turned out, this bug shows it’s ugly head only if you don’t have any controls on Form. As soon as first control is added everything works as expected. I haven’t seen this behavior in my other applications since I never had an empty form to show.

It just shows that testing smallest possible working code is not always an answer.

Pointless Mails

I just got e-mail from Microsoft with my free 30-day pass for Windows Azure. It came in mail titled “Take Advantage of a Free 30-Day Windows Azure Pass”. Last year I wanted to get into but Croatia wasn’t among supported countries. From good sources I got that this year this will change. I took this offer as good sign.

Of course, when I came to registration site, Croatia was suspiciously missing from list. Another disappointment.

I am not that much disappointed at Microsoft as such since it is their business decision whether they want Croatian money or not. I am disappointed by assholes who sent such mails to everybody everywhere. Microsoft has all my data (and that does include country). How hard was it to filter out people not in “proper” countries?

White-on-White Spinner

Illustration

As far as Android goes, I like it’s light theme much better that black one. It is matter of preference really since both are equally functional.

First time I used Spinner control I noticed interesting result - I got white text on white background. While other controls used theme that was defined application wide Spinner forced white background on it’s drop-down. Black theme defines white text on black background, Spinner forces white background - white text on white background is their bastard offspring.

Solving this took a little bit of time and single line. It was easiest to change background color for drop-down just after it is inflated:

@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {				
    if (convertView == null) {			
        View view = _inflater.inflate(android.R.layout.simple_list_item_single_choice, parent, false);
        view.setBackgroundColor(Color.BLACK);
        ((TextView)view).setSingleLine();
        ((TextView)view).setEllipsize(TruncateAt.END);
        convertView = view;
    }
    return super.getDropDownView(position, convertView, parent);
}

P.S. It might be as well that I broke something to get Spinner behave this weirdly - I haven’t investigated much further after I got the result.