I just implemented complete <marquee> support! Let the flames begin!
comment (6) -Looks like XUL and XAML have become the topic of an interesting cross-blog conversation recently. It started with a blog entry from Ryan Dawson, who mentioned XUL and XAML together. Eric Meyer responded here. Robert Scoble then clarified that Ryan does not work for Microsoft here.
More responses followed from Dave Shea and from Simon Willison.
I know nothing about XAML yet, so I think comparisons with XUL are perhaps premature. I can, however, talk about XUL itself, since people are starting to ask questions about both Mozilla XUL and about the "XUL-like" features that have been implemented in Safari on Panther.
So what is XUL anyway? It is an XML language whose tags consist of:
(1) layout primitives (tags like hbox, vbox, grid and stack)
(2) widgets (tags like menulist, menubar, toolbar, and button)
(3) commands, keyboard accelerators (tags like command and keyset)
(4) xul templates (for UI binding to back-end data, represented as RDF)
Rendering a XUL file in Mozilla is just like displaying an HTML Web page, albeit without any surrounding Window chrome, in that the XML is parsed, a tree representation of the tags (called the Document Object Model or DOM for short) is constructed, associated CSS is used to define the presentation for the tags, layout objects that represent the visual on-screen boxes are built, and the result is rendered on your screen as a dialog or window.
In other words, XUL at its core is actually pretty simple. It's nothing more than an XML description of the GUI elements in your dialog or window, along with presentational hints for how to position those elements.
A whole slew of acronyms come into play in Mozilla to bring the XUL to life. They are (in no particular order): CSS, DOM, RDF, XML, XBL, JS, and XPCOM.
Loading a XUL file goes something like this:
(1) XML is parsed into a DOM tree.
(2) CSS is used to define the rendering of the DOM tree.
(3) XBL is attached via CSS to define implementations of the widgets. Some widgets are defined in C++, others are defined purely in XBL/JS, and still others a mixture of the two. XBL is essentially an implementation detail (unless you're designing your own custom widgets).
(4) JS can be used in the XUL file to attach event handlers and execute scripts. Many services are available in JS via XPCOM wrappers. This is where the "core" of the Mozilla toolkit is defined, in APIs for file i/o, network loading, drag and drop, etc.
(5) RDF provides the means of binding back end data to user interface. Think of it as a glue layer between information you might store in a database (or anywhere you want) and the user interface.
Mozilla has a binary representation of both XML and scripts that avoids reparsing the raw XUL across launches, CSS style resolution is extremely quick (and at this point highly optimized), and JS is nice and speedy, primarily being used as glue to connect the UI to back-end services implemented in C++ anyway.
Of course one problem with using an XML+CSS layout engine is that people expect GUI windows to be available instantly, while they're more tolerant of Web pages taking a second or two to load. At this point, however, machines have gotten fast enough (and layout engines have improved enough) to handle the additional cost of rendering user interface this way.
Also, don't let the issue of native widgets sidetrack you when considering the "new window time" cost of XUL. Using native widgets or non-native widgets really has no effect on this time. The cost is in the construction of the XML, the DOM, the style resolution, and the layout, and native widgets don't really do anything to obviate that cost. (CSS still has to tell that native widget how big to be, or whether its visible, etc. The DOM still has to bind event handlers that say what to do for that widget, etc. The DOM still has a tree structure that has to be mapped into the widget itself.)
So to implement XUL, you have to:
(a) build an XML+CSS+DOM+JS layout engine
(b) implement additional layout primitives (like a spring and strut model and popups) that interoperate with the standard CSS-defined layout primitives
(c) implement a binary format cache for the XML and JS so that it can be loaded really quickly even across launches of the app
(d) implement a component/tag extension model like XBL to allow XML tags to be defined as components and reused easily in different pages, windows, and dialogs
(e) implement XML tag support for all the remaining OS widgets that HTML has been missing for years (tree widget anyone?)
(f) provide a binding from the GUI XML to backend data, via some form of data binding (Mozilla chose RDF)
(g) expose an entire SDK for file I/O, networking, etc to JS in addition to your preferred native language formats
(h) implement support for a command infrastructure for command execution and command updating
(i) implement very smart memory caching for CSS and XML that allows lightweight prototypes to be cloned and shared (with copy-on-write semantics)
Then all you have to do is put it in a blender for three years. See? It's easy. :)
The piece of XUL that Safari implements is "(b) implement some additional layout primitives." XUL basically introduces four new layout primitives to CSS: the flexible box, the grid (flexible boxes in 2 dimensions), rich popups/tooltips, and stacks. Safari in Panther has implemented the first (and most useful) of those layout primitives, the flexible box model. Since the box layout primitives are defined via CSS, you can even use them in HTML (in either Safari or Mozilla).
Responding to some of the trackbacks from the previous blog entry...
The first mentions a bug in 1.1, and the test page is found here. In Safari post-Panther, the rendering is actually different (but still broken). I'm not sure what the problem is at first glance, but I'll take a look.
The second trackback asks for complete navigation of bookmarks from the keyboard. Since that isn't part of WebCore, I can't comment. Several trackbacks also ask about Safari 1.1 on Jaguar. As I've mentioned in previous blog entries, I can't comment on future Safari releases.
I can whet your appetite with more WebCore stuff that we've implemented since Safari 1.1: small-caps support, fixes for first-letter and text-transform (the ugly doubling text effect is gone), fixes to first-line, and speed improvements to DHTML.
Safari 1.1 is here. Those of you who picked up Panther can take it for a spin. This release is big step forward from 1.0, chock full of bugs fixes, improvements and UI refinements.
As far as new WebCore features, here's a few highlights:
(1) Better standards support. You'll find fixes for positioning bugs, overflow bugs, floats, tables, gzip support, generated content using ::before and ::after, DHTML. You name it, we've improved it.
(2) Speed. We're still fast, and we're only going to get faster.
(3) CSS2 support. In addition to all of the bug fixes to be more standards-compliant, we also added support for CSS2 properties like text-shadow and new display values like inline-block. Try using text-shadow in conjunction with ::selection. It's cool. :)
(3) Safari on Panther supports rgba values in CSS for specifying border, background, foreground and shadow colors.
(4) Support for the CSS3 opacity (using -khtml-opacity) property. Make entire blocks and inlines transparent without resorting to transparent PNGs.
(5) A complete implementation of the XUL box model. Safari on Panther supports the complete XUL box model, including horizontal and vertical boxes, the ability to flex, and the ability to reorder content and reverse content. If you're building canned content that you control using WebKit, you'll find a whole new range of layout possibilities at your disposal. Need to create dynamically sized headers and footers and flexible center content? The XUL box model can do that. Need to center an object within the viewport? The XUL box model can do that too.
And in case you're curious, here's what we've already got working post 1.1 in WebCore that you can look forward to:
(1) Support for the title attribute using tooltips
(2) The ability to tab to all controls in a Web page and to manipulate them from the keyboard.
(3) Support for table border collapsing.
(4) Support for the CSS cursor property.
... and a whole lot more ...
Enjoy the upgrade and as always send us your feedback (trackbacks preferred). We're listening.
First read the previous blog entry, and then read this response.
Responding to that trackback, the horizontal overlap when using list-style-position: inside with ordered lists has been fixed in Safari on Panther, and so I wasn't really concerned with that problem.
The real rendering problem I was referring to was the negative vertical margin being treated differently by Safari. To make a long story short (too late) I'm wrong. I totally missed the list-style-position: inside style in the test case.
The inside style causes the marker box to generate an inline box, a box that then has to be wrapped in an anonymous block. Safari generates the marker box within the first nested line box it can find, a behavior that - although incorrect according to CSS2.1 and the CSS3 draft - actually makes more sense to me. Nevertheless, to match the specification, it looks like I'll need to fix Safari's behavior. :)
In other words, Safari is "smart enough" (ha ha) to keep your bullet properly aligned vertically even when you place block elements as children of the list item. It will drill down as far as it needs to in order to find the correct first line, and it will generate the marker box there. Note that this is essentially how outside list bullets are positioned vertically, so IMO it's actually more consistent (albeit wrong according to the spec) to do this for inside bullets as well.
Ignoring the spec for a second, which behavior is better? Having to put an artificial negative margin on blocks in a list item in order to compensate for a line generated by the list bullet (other browsers) or having the marker just place itself correctly automatically (Safari)? You can tell by now which behavior I favor. ;)
Maybe it's not too late to change the spec. :)
In the trackback for my previous entry, Anton complains about Safari's misrendering of the list items at this URL.
As far as I can tell, Safari's rendering is correct. Mozilla seems to be ignoring the negative margin placed on the divs with class="title". If you change the display of the list items to block, Mozilla stops ignoring the negative margin and behaves like Safari.
This appears to be a bug in Mozilla to me, and I believe Safari's rendering is correct.
I've been working on implementing incremental repainting in Safari. With the exception of some hacks that I threw in for overflow:hidden elements, Safari 1.0 will repaint the entire visible area of a Web page whenever any object changes size. (Turn on paint flashing using Quartz debug and you'll see what I mean.)
This is obviously a big problem for DHTML sites.
Anyway, I've fixed this problem in my own build (which makes DHTML easily 5-10 times faster for affected pages), and now I'm looking for tests. What I'm looking for are any pages/tests you've got that do really cool dynamic stuff with DHTML and CSS. I want to know about pages that mostly work in Safari now. The point of this exercise is not to hear about current DHTML bugs, but to make sure I haven't regressed any behavior, so please stay on topic.
Post links to cool demos that do anything from dynamically changing clip to sliding elements around on screen to animating using all sorts of different techniques (changing margins, position, overflow, background, etc.).
| Sun | Mon | Tue | Wed | Thu | Fri | Sat |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 |