So, enjoy my code. I’m sure something good can come of it: dock-ng.zip. I’ll call it MIT-X11 licensed.
Archive for the ‘Cairo’ Category
Dock: Okay, I’m obviously not finishing this in the near future…
Posted by Brian on April 6, 2007
Posted in Cairo, Programming, XInputShape | Leave a Comment »
Dock: More technical details on scaling, XInputShape, and icon highlighting
Posted by Brian on March 18, 2007

Scaling:
While that beautiful scaling looks like it would be hard to calculate, it is actually super easy. At first glance, the curve created by the function looks like a simple Gaussian Distribution and believe it or not, that is exactly what it is. The base function for Gaussian Distribution is y = exp(-x^2), and the modified form for this is actually size[i] = normal_size + (big_size – normal_size) * exp (-((pointer.X – (x[i] + size[i]/2))^2). Since x[i] = sum(size[k]) for k = 0..i-1, and size[i] is dependent on itself, all we have to do is perform this calculation iteratively until the values converge (with a reasonable tolerance).
private void CalculateIconSizes (ref double [] sizes, double x, double pointer)
{
double x_current = x;
for (int i = 0; i < sizes.Length; i ++)
{
while (true)
{
double old_size = sizes [i];
sizes [i] = StandardSize + (HoverSize - StandardSize) * Math.Exp (-Math.Pow ((pointer - (x_current + sizes [i] / 2)) / HoverSize, 2));
if (Math.Abs (sizes [i] - old_size) <= 0.25)
break;
}
x_current += sizes [i];
}
}
Shaping:
InputShapeMask is a very nice feature, but it has a few weeknesses. The first thing that screwed me is that it doesn’t work with override redirected windows. In retrospect, that makes sense, but I don’t like it. The second thing is that you should not do any more masking than you need to. For example, if you wanted to mask an area like this:
The easiest thing to do would just be to make a pixmap with the same dimensions as the window, draw your rectangles, and set the mask. Unfortunately, this causes a funny problem. When you move over the window, in the hidden area, sometimes it focuses for a split second, causing all sorts of problems and annoyances. To overcome this, you should only render a mask for the area you’re interested in. For example, since you’re only interested in:
What I do is loop through all the rectangles finding the top-most, bottom-most, left-most, and right-most points, then create a pixmap (bottom – top) tall and (right – left) wide, rendering the pixmaps onto it offsetted by (top) and (left) so the end result looks like this:
Then I use win.InputShapeCombineMask (pixmap, left, top); to get it in the right place.
private void DrawInputMask (int width, int height, Cairo.Rectangle [] rects)
{
int top = height;
int bottom = 0;
int right = 0;
int left = width;
foreach (Cairo.Rectangle rect in rects)
{
if (rect.X right) right = (int) Math.Ceiling (rect.X + rect.Width);
if (rect.Y + rect.Height > bottom) bottom = (int) Math.Ceiling (rect.Y + rect.Height);
}
Gdk.Pixmap pixmap = new Gdk.Pixmap (null, right - left, bottom - top, 1);
Cairo.Context context = Gdk.CairoHelper.Create (pixmap);
foreach (Cairo.Rectangle rect in rects)
context.Rectangle (rect.X - left, rect.Y - top, rect.Width, rect.Height);
context.FillPreserve ();
context.Stroke ();
InputShapeCombineMask (pixmap, left, top);
}
Icon highlighting
Icon highlighting is probably one of the trickiest things to do. While it is relatively easy to render SVG onto a context, it is pretty tricky to highlight just the image. The following is my solution:
- Figure out which region you want to work with on an unscaled cairo-context. It is very important that you use an unscaled context to avoid pixilizing the icon you’re working with.
- Create a new similar surface from the context’s target. In C#, this is context.Target.CreateSimilar (Cairo.Content.ColorAlpha, width, height);
- Create a new context on the surface and save it.
- Do whatever icon rendering you want with the new context.
- Restore the context.
- Create a new rectangle over the entire canvas, using whatever color you want with whatever alpha may be appropriate.
- Use icon_context.MaskSurface (icon_context.Target, 0, 0); This function takes whatever you were about to draw, in this case a colored rectangle, and prints it using the alpha channel of the surface as a mask. Thus every pixel of image will be covered with color proportional to its transparency.
private double DrawIcon (Icon icon, Cairo.Context context, double x, double y, double size)
{
if (!LeftAligned) x -= size;
if (!TopAligned) y -= size;
context.Save ();
context.Translate (x + PaddingSize, y + PaddingSize);
Cairo.Surface icon_surface = context.Target.CreateSimilar (Cairo.Content.ColorAlpha, (int) Math.Ceiling (size - 2*PaddingSize), (int) Math.Ceiling (size - 2*PaddingSize));
Cairo.Context icon_context = new Cairo.Context (icon_surface);
icon_context.Save ();
icon_context.Scale ((size - 2*PaddingSize) / 100.0, (size - 2*PaddingSize) / 100.0);
icon.Draw (icon_context, 0, 0);
icon_context.Restore ();
if (Mode == DisplayMode.Full && PointIsInRect (pointer, x, y, size, size))
{
icon_context.Rectangle (0, 0, size - 2*PaddingSize, size - 2*PaddingSize);
icon_context.Color = new Cairo.Color (1, 1, 1, 0.6);
icon_context.MaskSurface (icon_surface, 0, 0);
}
context.SetSourceSurface (icon_surface, 0, 0);
context.Paint ();
context.Restore ();
return size;
}
Posted in Cairo, Programming, XInputShape | Leave a Comment »
Cairo-row-row your boat… Bringing sexy back!
Posted by Brian on March 16, 2007
Brief note: New TagLib# released, adds lyrics support, fixes ASF writing, speeds up MPEG-4 (Not as fast as I previously boasted in my blog, but substantially.) Check out the website for more details and downloads.
Another brief note: I have time to mess around like this because I’m on spring break, I won’t have time to work on this again most likely until summer.
Now, for what everyone loves… SCREENSHOTS!
It’s transparent, it’s scaling, it’s fast, and it’s MANAGED! (Except for some RSVG work due to an incomplete API.)
The goal is to build my own Gimmie style application based on the mockup given when Gimmie was first announced. This would include four corners (applications, documents, system, and people) which would improve access to tasks and hopefully simplify the thought process for users. Some concepts I would like to include:
- (From AWN) A DBus interface so applications could assign icons to windows, assign windows to applications, files, people, etc.
- When the mouse leaves the dock, I want it to reduce to just the corner and shrink to a small size. Then, when an application wants to grab the user’s attention/input focus, it’s icon could appear, the corner could get bigger, and some eye-candy animation could begin.
- Plugins: The library currently provides a generic Icon class which renders by receiving coordinates, dimensions, and a cairo-context. It would be pretty easy to render any sort of content
- (From Cairo-Dock) I would really like to have a patterned background like Cairo-Dock. Looking at their code, it’ll take some DllImporting due to shortcomings in Mono.Cairo, but nothing too serious.
I’ll make a more technical post on the code in a while, once I’ve got the input mask worked out.
- Brian
Posted in Cairo, Programming | Leave a Comment »














