Of course, the autosave function didn't work either, so I was left with the title and the first line.... *sigh* and I had pretty pictures in too *sigh*
So, this is going to be much shorter.
Mono Summit 2007: awesome
* Talking and debugging speedy-gonzalez-like with my favourite marsupial Geoff Norton about all things mac-ish;
* Discussing winforms and it's direction with Jonathan Pobst, as well as blowing up his Visual Studio 2008 with a carefully aimed HAHA;
* Meeting our awesome tester Gert Driesen, recipient of our lifetime achievement award for extreme uberness in testing everything with extreme prejudice (award which will, for sure, take physical form and reach him... :) );
* Meeting our wtf-is-wrong-with-transparency-dude/winforms designer Ivan Zlatev and making him come to dinner with us (hey, it was fun, wasn't it! ;) )
* Meeting my COM hero Jonathan Chambers!
* Watching with delighted surprise as Jim Purbrick (of Second Life fame) presented the pathfinding / tower of defense game we had been working on at Codebits Lisbon actually live in Second Life
* Watching the moonlighters work their magic;
* Watching Aaron Bockover turn his T into a portable disco by sending commands to the thinkpad acpi
* Finally meeting my good friend/asp.net master Marek Habersack
* Getting back together with all my teamsters
These are only the highlights, mind you, there was so much more, between the Boo, Debugging, MD, Mac and all the other presentations, meeting contributors and users and developers and getting together to discuss and debug and hack and having a few laughs over drinks and jamón and coffee and walking around Madrid trying to steer through the huge crowds and having our room keys deactivated every couple of days so that everyone had to meet downstairs and chat a bit more while they were reactivated (nice touch there, hotel service)... Did I mention how awesome it was?
So that was the Mono Summit 2007 in Madrid. Now that I'm back and filled with all the energy I got from this amazing event, I decided to make some changes to the way I work, because I realized that I was still carrying around some old habits from the closed-source/enterprise world that are keeping me back. Old habits are really hard to break, so this past week I've done two radical changes that will, hopefully, be the trigger to improving my whole way of working.
The first change was dumping Windows completely, and with it, Visual Studio. The past thursday marked my first Windows-free week in 10 years of work. I'm now running full time on openSuse, and it's great :)
The second change was switching to a US International layout on the keyboard. I just reached the conclusion that the PT layout is not suited to coding at all, most of the keys I hit the most are hidden away with ctrl+alt combos, while in the US layout they are readily available on the sides. Also, the accentuation marks I need when typing portuguese are very easily reachable on a US layout, funnily enough, so I can still type correctly in pt without having to switch layouts. And my fingers and wrists are oh so thankful for the change, I hadn't realized what a strain it was to code until the strain was gone :D
So that's that, went there and back again, and it was inspiring in so many ways. Can't wait for next year ;)
PS: oh yes, almost forgot, you can check out the pics I took if you're in the mood. There are also links to more albums from other monoers in the Mono project site.
Já houve muitas reacções e comentários a esta notícia. Como parte integrante da equipa do Mono, não posso deixar de frisar o seguinte aviso:
Qualquer pessoa que olhe para código Microsoft, seja através de ferramentas como o Reflector, ou através deste pacote de código que a MS irá disponibilizar, não poderá contribuir para o projecto Mono. As regras de contribuição estão aqui, e não está previsto que mudem.
O Miguel de Icaza tem alguns comentários interessantes sobre isto, btw, recomendo a leitura.
Ficam avisados. Não cedam à tentação :)
First of all, I'd like to thank him for taking the time to try this out; I'm building regularly on Windows and I try to keep things simple, but things do always slip past unnoticed (especially when trying to keep linux, win+vs2k3 and win+vs2k5 in synch), so it's great to have an external pair of eyes looking at your stuff :)
He had some problems getting things up and running, so I thought I'd leave some pointers to help out those who want to test this out on Windows. Do check out his post so it's easier to follow along.
You don't need the whole mozilla shell to setup the headers, the only thing you need is
- the xulrunner sdk
- xpidl.exe (from the xulrunner sdk)
- libIDL-0.6.dll and glib-1.2.dll (from the wintools zip)
- unzip the xulrunner sdk somewhere
- put xpidl.exe and the two dlls in the build directory
- open a command prompt, go to the build directory, and run "make [path-to-xulrunnersdk]".
The missing nsAppDirectoryDefs header has been added, so you don't need to google for it anymore. Ooopsie :)
To run an application, you always need to have in the same directory:
- the contents of the xulrunner runtime package
- your app's exe :)
- the mono.mozilla dll
- the xulbrowser.dll
Then, on the build directory, run "setup-runtime.cmd [path-to-your-application-exe], which will create some directories that are required to be where your app is.
The browser problems mentioned (unable to input text) have been fixed, so the latest version should be fine.
The Mono.Mozilla project is also fixed.
As for the TortoiseSVN problems, I use tortoise for all my work and it's always worked great :p
Of course, I've never used the _svn variant, it's too much trouble and incompatibility just to have svn with webapps on vstudio. I suggest using the regular version for fun and happiness :)
Thanks again to Alexandre, and do nag me if anything goes wrong.
First off, translation:
Top: "Citizen calling the tax service helpdesk so as not to waste the time of actually going there."
Bottom: "The good thing is you get to hear a nice lullaby while you wait."
I drew this in Photoshop, carelessly doodling, while waiting for the helpdesk callcenter to pick up my call. I think it's safe to say they weren't exactly fast.
And yes, I know, my drawing skills are, hrm, sketchy. But, I don't know, I just love this one.
Immersing myself in that weird place called a citizen's shop, where all the official stuff is gathered so it's easy to do everything in one place (you know, taxes, utilities, id renewals...), I went around looking for the proper booth or desk or whatever it's called so I could take my numbered ticket, and found it, easy enough. Actually, found two. First, there's the booth where you buy the forms. Gotta take a ticket for that and wait in line. Then there's the booth where you deliver the forms. Gotta take another ticket for that and wait in line. Yes, typical. Got both tickets before going to wait by the first booth, because, as I had guessed, the line to deliver the forms was at number 403 when I got there, and my ticket had the number 490. Typical. Cue long wait, punctuated by a trip to the photo store to take pics for the card... I had figured I would have time enough to do that, so I didn't bother doing it before going there :)
My number is up, get to the counter to deliver the forms, sign the id card.
woman: "oh oh"
me: "oh oh?
woman: "you'll have to sign the form again, the signature doesn't match the one you put in the id card"
me: *looks at both and finds no differences.*
me: "where are they different?"
woman: "can't you see? they're different!"
me: "I can't see it. Ok, maybe this one is slightly rounder, is that it?"
woman: "no, don't you see? look at it"
woman: "the G!"
me: *signs again*
woman: "they're still different! this is the id card we're talking about!"
woman: "you're missing a dot there on the i"
me: *puts the dot in*
Going smoothly so far. I get my finger all blackened up for the fingerprint, she takes my old card, I get the receipt of delivery with my data and when I can pick it up, and then...
me: "so... will this receipt serve as a standin for my id card?"
me: "so... what do I use if I need to identify myself?"
woman: "your driver's license will do"
me: "so... what if I don't have a driver's license?"
woman: *blank stare and pushes the buzzer to call up the next number*
These things are always so much fun.
Note: it's not that uncommon here for people not to have a driver's license, but you must carry your id card at all times. The id card expires every 5,7 years, while the driver's license lasts about 50 years without needing a renewal, so if you're 50 you can be carrying a license with a picture of you when you were 18... not a particularly trustworthy piece of identification if you ask me. :)
"Que interessante", pensei eu, enquanto mastigava uma noz (a propósito, spoiler warning, a resposta é Dune, é a cena quando o Duque acaba de ser apanhado e está a perder a consciência, e prepara-se para envenenar o médico, convencido que este é o Barão, até já estou a ver a cena toda na cabeça...
Mastigando mais um bocadinho de noz, lá cliquei no blog da pec, que me levou ao blog da Maria Antunes, que me apontou para o blog da clau, que citou o blog da nika_liu (mázinha mázinha, que não meteu o link, tssk tssk), que mencionou o blog da Miss K (bolas bolas também sem link), sendo que, a esta altura, já a noz era uma memória e tive que parar para caçar mais umas tantas.
"Deveras interessante", pensei eu outra vez, com novo fornecimento de nozes. Não quis perder mais tempo, e resolvi entrar também na brincadeira, pelo que estiquei o braço e... tive que me levantar porque não tinha nenhum livro à mão. :p
*saca um livro da prateleira e abre-o na página 161*
"...", pensei eu. A página inteira tem exactamente três pontos finais. Complicated. Bem, não é propriamente a quinta frase completa, mas what the heck :p
"Antes do espectáculo desta noite, quero pedir á nossa convidada, capitoa Wong, que pronuncie algumas palavras ou recite algo."
As regras são as seguintes:
1. Pegar no livro mais próximo
2. Abri-lo na página 161
3. Procurar a 5ª frase completa
4. Colocar a frase no blog
5. Não escolher a melhor frase nem o melhor livro (usar o mais próximo)
6. Passar o desafio a cinco pessoas
O desafio está lançado! Essa de passar o desafio a cinco pessoas é mais complicatida, por isso deixo a quem o apanhar :)
PS: Hei-de colocar o nome do livro num comentário a este post, para não estragar a brincadeira a quem ler isto daqui a uns tempos ^_^
The code is split up into three components: the WebBrowser and related classes inside MWF (Mono's winforms implementation); Mono.Mozilla, a new class library on the tree that gets called from MWF; and xulbrowser, a c/c++ library that actually does all the talking to mozilla.
Since a picture is worth a thousand words, the image on the right gives an overview of how these components relate to one another. I didn't want to clutter it too much with arrows, so I didn't put arrows upwards, but of course the communication goes both ways.
Mono.Mozilla is essentially a managed wrapper that exposes an interface to MWF so that the WebBrowser* classes can call methods like Navigate, and register for events coming from mozilla. This interface is the only publicly accessible way to talk to the browser windows, so that things are nice and neat and the wrapper can be free to hide those little pesky details that WebBrowser and friends don't really care about.
Although Mono.Mozilla is, well, Mozilla-oriented, it is neatly divided into two namespaces: Mono.WebBrowser, where the public interface resides, and Mono.Mozilla, where the pinvokes to the unmanaged library reside, so you'll never see the Mono.Mozilla namespace called from inside MWF directly. This has the nice side effect of making it easier (or at least doable) to plug in another browser toolkit in the future if need be.
So what's done and working right now on WebControl? Well, the easiest way to implement an API is to have test applications, so I plucked up the UsingTheWebControl sample from msdn and added it to our roster of winforms test apps. From it's description:
This sample contains three tabs. The first tab demonstrates the use of the WebBrowser control in a simple browser application.
The second tab uses the WebBrowser control as a local HTML document viewer.
The third tab demonstrates the use of the WebBrowser.Document HTMLDocument model, together with the WebBrowser.ObjectForScripting prorperty, to implement Form-to-Browser two-way communication. In this scenario, the WebBrowser control is used to load an HTML document template that is populated with data managed by the Form, as a means of supporting custom printing of application data.
The WebBrowser control on Mono is complete enough for the sample to work with the first two tabs, i.e., loading, refreshing, navigation are all there, as well as focus, activation, mouse and key events so that you can actually browse the web (as opposed to, say, just looking at it... which is a fine thing to do in itself, sure, but probably not that useful in the long run). Https support is already in as well.
This sample is particularly nice in that it hits a lot of not-so-used areas, such as manipulating the Document to load custom data. This, btw, is done on the third tab, which isn't working yet.
The sample is available from the /winforms/webbrowser/UsingWebBrowser directory on svn trunk. To get it working, you will need to use the latest mono on svn.
You will also need to get the /mozembed directory from svn, which contains the xulbrowser library. Just build mono, do the usual autogen.sh, make, make install on /mozembed, make the UsingWebBrowser-port directory, and then go to bin and run the application there.
The last blog entry spoke of a successful embedding of xulrunner into a mono winforms app, on windows, and I had hoped that one or two days later I would be blogging about it working on linux as well. Unfortunately, it turned out not to be as simple as that. It actually turned out to be really complicated.
First, while on windows I only had to feed xulrunner with the windows hwnd handle and voilá, it worked, on linux xulrunner uses gtk by default. The xlib xulrunner would be quite nice to use, as it would hopefully be just like windows, feed it a winforms handle and that's that. Unfortunately, the xlib xulrunner code has been bitrotting for quite some time, and would not work at all. :/
The Gtk adventure
Getting gtk to use a winforms handle to draw in was quite an interesting challenge in itself - it was essentially the same as getting gtk to draw in an x window (since winforms handles are essentially xid's). There are a couple of different ways to go about the problem; either use the concept of socket/plug by calling gtk_plug_new on a xid and then adding widgets to that to later pass on to xulrunner to draw in, or using gdk_window_foreign_new to "import" the xid.
gtk_plug_new creates a new GtkWidget, while gdk_window_foreign_new gives you a GdkWindow. The first would seem to be easier to get into xulrunner, as it requires passing in a GtkWidget, but it also requires reparenting the window (because the plug doesn't actually do that, it assumes the xid has a socket attached - which it hasn't, since it comes from winforms).
The second gives you a GdkWindow, which doesn't actually help much when you really want a GtkWidget and simple code. I ended up building a custom widget to wrap around an X handle, following the line of the gtkwin32embed widget that comes with gtk, so I went for the second option. The widget works wonderfully, no need for extra reparenting, no need for top level windows (since the widget is a window), just create it with the xid and you're in business! :)
|Winforms application calling the new xulbrowser library to display an|
embedded xulrunner engine (mozilla)
Those pesky initializationsWhat really made me bang my head on the walls was the fact that no matter what I did, the browser seemed to stop in the middle of loading and just stay there indefinitely! I did everything to the code; debugged it, traced it, #ifdef'd it, went step by step checking every call, every event, everything, and nothing, it refused to work! That damned loading icon kept mocking me!
To cut a long story short, after spending hours and hours and days and days on it, I finally found out that the problem was, I wasn't initializing a thing called AppShell. This AppShell (which is a frozen interface, but is not actually a part of the sdk - so you'd think it wasn't all that important, hmm?) initializes gtk on the browser so the browser widget can receive events (you'd think one gtk initialization was enough, sheesh!...)
It also seems to be an absolutely useless interface on windows, since the original code works perfectly fine and it actually catches events without it. So it's a linux only thing, as far as I can tell. Completely undocumented. Unless, of course, someone tells me that it was perfectly obvious that it needed to be there, since gtkmozembed uses it. Of course, gtkmozembed also uses a ton of private calls that are supposedly completely off-limits to us external embedding folks and that would probably earn me a ton of griefing if I actually thought of using them, but hey, I'm supposed to know the difference between an off-limits-never-use-or-we'll-send-the-mob-after-you calls, and absolute-mandatory-linux-only-initialization-calls-on-non-sdk-interfaces... right?
It's a good thing I'm a certified nutcase and I actually have fun solving these little problems. And it's not like I don't have solid walls or anything. :)
So, for your amusement, here's a couple of shots (ok, ok, one here and one above) of a Mono Winforms application running a control with an embedded xulrunner-powered browser inside.
|Gratuitous use of Xgl to show off my nice Suse desktop with a Mono Winforms |
app embedding a mozilla browser (phew!)
Anyway, great blog-worthy news today, got the Mono WebControl -> Gecko thing going, and it's alive and drawing! Check out this screeny of the mozilla engine rendering a webpage inside Mono...
The first functions of the library were only returning ints, but for the glue to work properly, I needed to return a pointer to the newly created class in C++, and since cross-platform is good, all the function exports got marked with mozilla's NS_EXPORT_(type). While I had int as a return type, all was well, but when I decided to return void*... *boom*!
Looking at the exported functions of the dll, all those marked with void* or similar (anything with *, really) were not there. Everything was happily compiled... they just weren't exported. :p
Cue 2 hours of googling and mucking about with the export syntax and going absolutely nowhere.
Now note, please, exhibit A - the NS_EXPORT_ typedef:
#define NS_EXPORT_(type) type __declspec(dllexport) __stdcall
Note, also, as exhibit B, an example signature that jchambers gave to me on the #mono channel:
__declspec(dllexport) void* STDCALL myfunc();
Well, apparently, if you put the type before the __declspec, all functions with pointer return types will not be exported. If you put the type between the declspec and the stdcall, they are exported.
I ended up doing this:
#define NS_EXPORT_(type) __declspec(dllexport) type __stdcall
Of course, I could be doing something really wrong here... if anyone can set me right, feel free! I'll just go back to doing some useful now :)
Coincidence? I think not!
But once I started tinkering with it, I forgot all about that :)
I'm tapping away at it's settings and installing stuff just to see what it can do. And since I predict a future where my little Transistor will bork dramatically for some reason, I'll just leave a note to self here when I need to reflash the thing.Reflashing the n800 - How-to
And if it gets stuck in a reboot loop:
./flasher --clear-rd-flags=no-lifeguard-reset --disable-rd-mode
Picture one from http://www.transistor.org/collection/northamerican/noram3.html. http://www.transistor.org/collection/channelmaster/chmstr10.html might make a better match for the n800, but I thought the twin pics funnier :p
Picture two from http://www.carrypad.com/gallery/v/n800jt/