Skip navigation

Category Archives: coding

Hey there!

Well, it’s been a while since my last update– nearly two and half months, in fact! Contrary to popular rumor, I haven’t fallen off the face of the Earth (not yet at least)– I’ve just been rather busy with development, work, and school and couldn’t find a moment to blog (sorry!). It’s been rather hectic lately trying to balance university, contract work, and all my open-source development. But hooray, I’m only a year and a half away from finishing my CS degree– after that, I’ll have to choose whether to join the land of the always-working or continue on and get my masters.

As far as Awesomium goes, here are the new updates: Mac OSX support (Intel OSX 10.5 only), true transparent rendering, fully-multithreaded rendering (with update throttling), tooltip notifications, various bugfixes, and much more. Thanks a lot to Jeff Rosen who hooked me up with a Mac– couldn’t have ported it without him.

Also, I’ve been working on a new cross-platform Flash offscreen-embedding library; the Windows port is mostly completed, working on the Mac OSX implementation right now. Like my previous library, Hikari, this library will ultimately allow developers to render Flash content (for use as a GUI or 3D texture) in a game or simulation. For example, one of my favorite kart-games around, ZeroGear, used Hikari for their GUI:

Awesomium (and eventually this new project) will continue to be free for non-commercial use however I am considering charging for commercial use. I’m working out the exact licensing and pricing details and will have more information later.

Oh, and, I’m putting together a new website to host all of my various software projects and activities. I’m really excited about this because it’s been really hard for everyone, including me, to keep track of all my sites, forums, blogs, and wikis over multiple servers– having a single one-stop site for all my projects and blog will be much easier to manage.

Advertisements

Get it while it’s hot over at the download page!

Here’s an overview of the major changes since v0.5:

  • Support for Flash plugins
  • Enhanced rendering performance on multi-core machines
  • Support for mouse-wheel input (WebView::injectMouseWheel)
  • The ability to grab the contents of the current page as plain text (WebView::getContentAsText)
  • Refactoring of callbacks to use WebViewListener instead

After much deliberation, hair-pulling, and running around my wee little room screaming at the debugger, I’ve managed to put together a decently stable (as in, it now crashes less often that it used to) build that supports Flash plugins– you can check it out of the SVN now as revision six.

I also spent a bit of time on optimization to take more advantage of multi-core processors. Previously, WebView::isDirty did a synchronous query of the internal WebViewProxy object on the core thread to test for dirtiness– I realized a better way to implement this was for the internal WebViewProxy object to directly update a local member of the WebView object on the main thread via a mutex so that calling the function doesn’t cause any blocking. Also, since the mutex would only be locked if the dirtiness state was being set to true (it’s only set to false during the synchronous WebView::render), if the mutex failed to be acquired instantly, WebView::isDirty immediately returns true.

Furthermore, I implemented a compromise to issue 3 and that is that WebView::isDirty now asynchronously flags the associated WebViewProxy on the core thread to begin layout/painting of the frame if it is dirty. This allows at least part of the rendering to take place on another thread concurrently with any blitting preparations that may take place on the main thread (such as the locking of a HardwarePixelBuffer in Ogre3D).

Testing shows that these additions have significantly improved the performance of several operations (such as scrolling, javascript/canvas animation, etc.)– I was seeing about a 20% improvement in the rendering speed of Google Maps.

Success!

Turns out my guess about what why the Flash plugins weren’t continuously rendering was right– I set up a repeating timer to intermittently do a Peek/Translate/Dispatch on the internal thread and suddenly everything was animating.

Mouse/keyboard input still was having issues and so I tried a lot of elaborate solutions to try and solve it– creating off-screen dummy windows, manually injecting window messages, etcetera. I eventually emulated Chrome’s existing input-handling routines for windowless plugins and got it working.

Windowed plugins still proved to be a major problem and I wrestled a lot with it over the period of a few days. It’s embarassing to admit that the final solution was really quite simple: when loading a plugin, I override the wmode parameter to force all Flash plugins to be loaded as windowless.

There were several other complex issues I had to contend with as well such as the throttling of certain messages, the timing of the peek/translate/dispatch cycle, and destruction order but I think the majority of the implementation is there. It’s still not entirely stable yet and so I’m not going to commit the new changes to the SVN just yet.

If you’re feeling curious, you can download a demo to test out the early Flash support. A few notes:

– Try to run it in windowed mode, you may need to close manually if Esc fails to work.

– F1: Print FPS to console

– F2: Navigate to Google

– F3: Toggle between forced-rendering and normal-rendering.

– Forced-rendering is useful for when the rendering freezes (it’s one of the bugs I’m working on)

I spent a bit more time working on Flash support– after fiddling around, I realized I could hook in a ‘WebPluginDelegate’ to handle the load of a plugin and duly wrap it however I want (foregoing any muckery with the NPAPI). After a few hours, I had Flash (almost) rendering! Er, well, only the first frame of any windowless (wmode=transparent) Flash movie:

As for why it stops at the first frame, it seems almost as if the plugin’s internal message loop isn’t being processed– I think it’s trying to post messages via the WinAPI but is being negated by the fact that I’m running it all in a seperate thread from the UI and am not passing any sort of HWND to the plugin. Oh well, it’s gonna take a bit more hacking to get this implemented. 😀

In an attempt to better organize discussion of Awesomium (replying to comments just isn’t cutting it), I’ve started a discussion group over at Google Groups. I normally would set up a big forum and wiki on my own webspace but users have been having trouble with e-mail confirmations (apparently my server resides in a blacklisted IP block).

Also, I’ve started using the issue tracker on the Google Code project page to coordinate and record issues/bugs/enhancements. If you spot a bug or simply want to make a suggestion about Awesomium, please feel free to add it to the issue tracker if it doesn’t already exist.

As for the future of Awesomium, there are several things I’m currently working on and hoping to get implemented. Support for true transparent backgrounds is one that tops my list as there is significant demand for such a feature. I haven’t had much luck getting this implemented natively and so I may end up altering the Chromium source– we’ll see how my hacking attempts go.

Another big thing I’ve been hearing requests for lately is support for Flash and other plugins. There’s several problems right now getting the Flash plugin to work: it requires a window handle (we have none), it renders directly to the window, and it isn’t painted with the WebView when invoking an offscreen paint. Nevertheless, I’ve got an idea: attempt to force the Flash plugin to always initialize in windowless mode (thereby it doesn’t require a window handle) and then intercept whenever it paints offscreen to its HDC (requires modification to Chromium). I’m still a noob at the NPAPI however and so to hone my skills, I’m currently working on creating a standalone plugin execution sandbox (so I can embed plugins like Flash without a browser).

The first official Awesomium SDK (v0.5) is out now for MSVC8! You can download it here.

The main header is “WebCore.h”, so include that to access the entirety of the API. Almost everything is documented using standard Javadoc commenting and so it should be pretty easy to understand (I’ll probably generate online docs later using Doxygen). If you need any tips on usage or an idea of how to embed Awesomium within your application, take a look at the ‘app’ project in the SVN source.

Good luck and have fun!

P.S., remember to copy over the ICU DLL (it’s in bin/common) into your executable’s directory as well. If you don’t, everything will probably still run however various operations (mostly text-input and unicode-related stuff) will most definitely fail, causing undefined behavior.

 

P.P.S., I’ve started a discussion group to discuss development/support of Awesomium, check it out here!

fancy awesomium logo

fancy awesomium logo

I’m very proud to announce the very first release of Awesomium!

Version: v0.5
License: LGPL
Platform: Windows & MSVC8 only (for now)
Demo: Download here *

* Try this alternative version if the demo instantly closes upon startup.

The source code is now online at its SVN repository. Please be aware that this release is really only for hardcore developers only– it lacks documentation and is a little tough gathering the necessary dependencies. Nevertheless, if you’re too impatient for an SDK release or just eager to start hacking at the source yourself, to build Awesomium you will need to first obtain Chromium and build it (I used a Sept. 6th revision so try to sync with that date). Then, check Awesomium out into the directory adjacent to your chromium distribution (the project assumes you’ve named your chromium folder “chromium”), open the solution, and compile the ‘Awesomium’ project. If you wish to build the demo (project ‘App’), you will need to have installed the Ogre3D SDK.

For the most part, this release is quite stable however I’m still working on a few issues, in no particular order: node memory leaks, support for transparent backgrounds, minor stall during a clipboard copy, and support for certain plugins.

I would write a much longer and more eloquent article detailing all of my thoughts about the current state and future plans of Awesomium but I’m frankly exhausted due to my pulling an all-nighter to get this release out. Anyways, I hope yall have fun trying out the demo and good luck to those who wish to try compiling it from source!

Despite being sick these past few days and my having to help put up part of our fence (we’re still missing big sections due to the hurricane), I was able to irk out some time to work on Javascript integration.

Obviously, if you plan to manipulate your embedded web content in any meaningful way (besides simple loading of pages/URL’s), you need a way to pass data and events to and from the page. I’ve implemented three methods to help achieve this:

Javascript execution

You can directly execute arbitrary strings of Javascript from the C++ API. For example:

myWebView->executeJavasript("document.body.bgColor = 'blue'");

This is obviously incredibly useful however there is a catch: you can only execute Javascript that interacts with the DOM (document-object-model) after the DOM has loaded. This can be circumvented by subscribing a listener to the WebView and handling your Javascript execution within ‘onFinishLoading’.

Client Properties

Javascript execution is pretty cool but when all you need to do is pass a few values to your page for initialization purposes, it’s just too much of a headache. That’s where ‘Client Properties’ comes in.

Basically, using WebView::setProperty, you are able to set a Javascript variable that will persist on that WebView (accessible via the ‘Client’ object from your page). You can then design your page to be initialized using these ‘Client properties’. For example:

myWebView->setProperty("message", "Hello world!");
myWebView->setProperty("secretNumber", 42);
myWebView->loadFile("coolPage.html");

and the contents of ‘coolPage.html’:

<html>
<body>
<h1>Welcome to my page</h2>
<p>
<script type='text/javascript'>
document.write(Client.message);
</script>
</p>
<p>The secret number is: <br/>
<script type='text/javascript'>
document.write(Client.secretNumber);
</script>
</p>
</body>
</html>

Client Callbacks

The above two methods are great for passing data from the application to the web page but we still need a way to pass events and data from the web page to the application.

To handle this, you may register named callbacks to receive notification of certain Javascript method calls from the Client object. For example:

void onLoginClick(const JSArguments& args)
{
// handle stuff here
}

myWebView->setCallback("loginClick", Callback(this, &MyApp::onLoginClick));
myWebView->loadFile("myPage.html");

then, you can invoke this callback from your page using Javascript:

Client.loginClick(username, password);

Okay, enough about the hurricane– let’s talk shop.

Last week, I was having some problems with keyboard input and random freezes during certain interactions. A little tracing found that a global timer was being instantiated and would greedily respawn itself during a single cycle of the browser’s message loop.

Me, in my brilliance (or rather, my unwillingness to spawn a separate thread), decided to kill the global timer every time we cycled through the message loop. This solved all of the hangs but it still didn’t fix keyboard input and caused some secondary problems (like utter failure of all Javascript timers).

It was then I realized that I couldn’t implement this thing correctly without dipping my toes into the deep, dark depths of multi-threaded programming. I needed to encapsulate the core and components of Awesomium within a separate thread, run a dedicated message loop within said thread, and handle inter-thread communication and synchronization.

It took me five days of banzai, headache-inducing coding to implement but I’m proud to declare that Awesomium is multi-threaded (and stable!). It was one of the most complex tasks I’ve ever achieved as a programmer but it’s so cool seeing both of my laptop’s cores work at the same time.

Despite the multi-threading, I still wasn’t able to get keyboard input working. I finally went code diving (about 2 hours of tracing) and realized that the problem was linked with some assertions about the unicode text encoding: as I had suspected earlier, ICU wasn’t being initialized correctly. Upon inspection of the ICU initialization source, it had seemed to be attempting to load a DLL that it had assumed would be in the working directory. I located the ICU DLL, copied it to my working directory and voila– keyboard input worked and the runtime text encoding assertions disappeared. Unfortunately, this means that my previous statement about the total dependency size was incorrect: the ICU DLL is about 8 MB and the Awesomium DLL (release) is about 7 MB, so together, that’s a total dependency size of about 15 MB. It’s not too bad I suppose– people who need the absolute tiniest dependency size can always gzip the DLL’s and load them at runtime.

But hooray! Almost everything critical now works and is pretty stable. Popup-widgets (such as drop-down combo-boxes) are now supported by compositing them with the main web-view texture. Event listeners are also implemented– you can currently receive notifications for the beginnings of navigations, title receptions, and finishing of loads. Dirty-rectangle optimization and querying for ‘dirty’ render state is implemented. The only other ‘big’ point left on my to-do list is support for Javascript evaluation/callbacks. Getting that working seems to be a little more tricky than I thought and so I may put it off for later.

Oh and yes, in true ninja style, I’ve written this latest post using Awesomium.