-/* -*- mode: c; c-basic-offset: 2 -*-
+/* -*- mode: c; c-basic-offset: 8 -*-
*/
#include <gtk/gtk.h>
typedef struct Closure Closure;
struct Closure {
- Model model;
- int num_icons;
- GdkWindow **windows;
- int drag_offset_x, drag_offset_y;
- int anchor_x, anchor_y;
- int spacing;
+ Model model;
+ int num_icons;
+ GdkWindow **windows;
+ int drag_offset_x, drag_offset_y;
+ int spacing;
+ int height;
};
static gint
timeout_callback (gpointer data)
{
- Closure *closure = data;
- int i;
+ Closure *closure = data;
+ int i;
- for (i = 0; i < closure->num_icons; i++) {
- gdk_window_move (closure->windows[i],
- closure->model.objects[i + 1].position.x + 0.5,
- closure->model.objects[i + 1].position.y + 0.5);
- }
+ for (i = 0; i < closure->num_icons; i++) {
+ gdk_window_move (closure->windows[i],
+ closure->model.objects[i + 1].position.x + 0.5,
+ closure->model.objects[i + 1].position.y + 0.5);
+ }
- model_step (&closure->model, 0.1);
+ for (i = 0; i < 4; i++)
+ model_step (&closure->model, 0.03);
- return TRUE;
+ return TRUE;
}
static GdkWindow *
create_window (GdkScreen *screen, int x, int y, int width, int height)
{
- GdkWindowAttr attributes;
- gint attributes_mask;
-
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gdk_screen_get_rgba_visual (screen);
- attributes.colormap = gdk_screen_get_rgba_colormap (screen);
- attributes.window_type = GDK_WINDOW_TEMP;
-
- attributes.x = x;
- attributes.y = y;
- attributes.width = width;
- attributes.height = height;
- attributes.event_mask =
- GDK_EXPOSURE_MASK |
- GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK |
- GDK_ENTER_NOTIFY_MASK |
- GDK_LEAVE_NOTIFY_MASK |
- GDK_POINTER_MOTION_MASK |
- GDK_POINTER_MOTION_HINT_MASK;
-
- attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gdk_screen_get_rgba_visual (screen);
+ attributes.colormap = gdk_screen_get_rgba_colormap (screen);
+ attributes.window_type = GDK_WINDOW_TEMP;
+
+ attributes.x = x;
+ attributes.y = y;
+ attributes.width = width;
+ attributes.height = height;
+ attributes.event_mask =
+ GDK_EXPOSURE_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
- return gdk_window_new (gdk_screen_get_root_window (screen),
- &attributes, attributes_mask);
+ return gdk_window_new (gdk_screen_get_root_window (screen),
+ &attributes, attributes_mask);
}
static void
-model_init_dock (Model *model, int num_items, int x, int y, int spacing)
+model_init_dock (Model *model, int num_items,
+ int width, int height, int spacing)
{
- const int num_objects = num_items + 1;
- const int num_spacers = (num_objects - 1) * (num_objects - 2) / 2;
- const int num_springs = num_objects - 1;
- const int spread = spacing + 20;
- int i, j, left_edge;
- Object *object;
- Spring *spring;
- Spacer *spacer;
-
- memset (model, 0, sizeof *model);
- model->objects = g_new (Object, num_objects);
- model->num_objects = num_objects;
- model->springs = g_new (Spring, num_springs);
- model->num_springs = num_springs;
- model->spacers = g_new (Spacer, num_spacers);
- model->num_spacers = num_spacers;
- model->anchors = g_new (Anchor, 1);
- model->num_anchors = 1;
- model->k = 0.1;
-
- model->polygons = g_new (Polygon, 1);
- model->num_polygons = 1;
- polygon_init_enclosing_rectangle (&model->polygons[0], 0, 0, 1024 - 50, y);
-
- model->anchors[0].x = x;
- model->anchors[0].y = y;
- model->anchors[0].object = &model->objects[0];
-
- object_init (&model->objects[0], x, y, 0);
-
- object = &model->objects[1];
- spring = model->springs;
- spacer = model->spacers;
- left_edge = (1024 - (num_items - 1) * spread) / 2;
-
- for (i = 1; i < num_objects; i++, object++) {
- object_init (&model->objects[i], left_edge + (i - 1) * spread, y - 100, 1);
- spring_init (spring++, &model->objects[0], object, spacing);
- for (j = 1; j < num_objects - i; j++) {
- spacer_init (spacer++, object, object + j, spacing);
- }
- }
+ const int num_objects = num_items + 1;
+ const int num_spacers = (num_objects - 1) * (num_objects - 2) / 2;
+ const int num_springs = num_objects - 1;
+ const int spread = spacing + 20;
+ int i, j, left_edge;
+ Object *object;
+ Spring *spring;
+ Spacer *spacer;
+
+ memset (model, 0, sizeof *model);
+ model->objects = g_new (Object, num_objects);
+ model->num_objects = num_objects;
+ model->springs = g_new (Spring, num_springs);
+ model->num_springs = num_springs;
+ model->spacers = g_new (Spacer, num_spacers);
+ model->num_spacers = num_spacers;
+ model->anchors = g_new (Anchor, 1);
+ model->num_anchors = 1;
+ model->k = 0.1;
+
+ model->polygons = g_new (Polygon, 1);
+ model->num_polygons = 1;
+ polygon_init_enclosing_rectangle (&model->polygons[0],
+ 0, 0, width - 50, height - 50);
+
+ model->anchors[0].x = width / 2;
+ model->anchors[0].y = height - 50;
+ model->anchors[0].object = &model->objects[0];
+
+ object_init (&model->objects[0],
+ model->anchors[0].x, model->anchors[0].y, 0);
+
+ object = &model->objects[1];
+ spring = model->springs;
+ spacer = model->spacers;
+ left_edge = (width - (num_items - 1) * spread) / 2;
+
+ for (i = 1; i < num_objects; i++, object++) {
+ object_init (&model->objects[i],
+ left_edge + (i - 1) * spread, height - 100, 1);
+ spring_init (spring++, &model->objects[0], object, spacing);
+ for (j = 1; j < num_objects - i; j++) {
+ spacer_init (spacer++, object, object + j, spacing);
+ }
+ }
}
static GdkFilterReturn
window_event (GdkXEvent *xevent, GdkEvent *event, gpointer data)
{
- Closure *closure = data;
- GdkModifierType state;
- XEvent *ev = (XEvent *) xevent;
- int x, y, i;
- Object *object;
-
- switch (ev->type) {
- case ButtonPress:
- closure->drag_offset_x = ev->xbutton.x;
- closure->drag_offset_y = ev->xbutton.y;
- for (i = 0; i < closure->num_icons; i++) {
- if (closure->windows[i] == event->any.window) {
- object = &closure->model.objects[i + 1];
- closure->model.mouse_anchor.x = object->position.x;
- closure->model.mouse_anchor.y = object->position.y;
- closure->model.mouse_anchor.object = object;
- }
- }
- break;
-
- case ButtonRelease:
- closure->model.mouse_anchor.object = NULL;
- break;
-
- case MotionNotify:
- gdk_window_get_pointer (gdk_get_default_root_window(), &x, &y, &state);
- closure->model.mouse_anchor.x = x - closure->drag_offset_x;
- closure->model.mouse_anchor.y = y - closure->drag_offset_y;
- if (closure->model.mouse_anchor.y > closure->anchor_y)
- closure->model.mouse_anchor.y = closure->anchor_y;
- break;
-
- default:
- break;
- }
-
- return GDK_FILTER_CONTINUE;
+ Closure *closure = data;
+ GdkModifierType state;
+ XEvent *ev = (XEvent *) xevent;
+ int x, y, i;
+ Object *object;
+
+ switch (ev->type) {
+ case ButtonPress:
+ closure->drag_offset_x = ev->xbutton.x;
+ closure->drag_offset_y = ev->xbutton.y;
+ for (i = 0; i < closure->num_icons; i++) {
+ if (closure->windows[i] == event->any.window) {
+ object = &closure->model.objects[i + 1];
+ closure->model.mouse_anchor.x = object->position.x;
+ closure->model.mouse_anchor.y = object->position.y;
+ closure->model.mouse_anchor.object = object;
+ }
+ }
+ break;
+
+ case ButtonRelease:
+ closure->model.mouse_anchor.object = NULL;
+ break;
+
+ case MotionNotify:
+ gdk_window_get_pointer (gdk_get_default_root_window(), &x, &y, &state);
+ closure->model.mouse_anchor.x = x - closure->drag_offset_x;
+ closure->model.mouse_anchor.y = y - closure->drag_offset_y;
+ if (closure->model.mouse_anchor.y > closure->height)
+ closure->model.mouse_anchor.y = closure->height;
+ break;
+
+ default:
+ break;
+ }
+
+ return GDK_FILTER_CONTINUE;
}
static const char *icons[] = {
- "svg/applications-office.svg",
- "svg/camera-video.svg",
- "svg/email.svg",
- "svg/firefox-logo.svg",
- "svg/gnome-dev-disc-dvdrom.svg",
- "svg/gnome-terminal.svg",
- "svg/help-browser.svg",
- "svg/internet-group-chat.svg"
+ "svg/applications-office.svg",
+ "svg/camera-video.svg",
+ "svg/email.svg",
+ "svg/firefox-logo.svg",
+ "svg/gnome-dev-disc-dvdrom.svg",
+ "svg/gnome-terminal.svg",
+ "svg/help-browser.svg",
+ "svg/internet-group-chat.svg"
};
int main (int argc, char *argv[])
{
- Closure closure;
- GdkScreen *screen;
- const int num_icons = G_N_ELEMENTS (icons);
- int x, y, width, height, i;
- RsvgHandle *handle;
- RsvgDimensionData dimension;
- cairo_t *cr;
- const int screen_width = 1024, screen_height = 768, spacing = 50;
+ Closure closure;
+ GdkScreen *screen;
+ const int num_icons = G_N_ELEMENTS (icons);
+ int x, y, width, height, i;
+ RsvgHandle *handle;
+ RsvgDimensionData dimension;
+ cairo_t *cr;
+ const int spacing = 50;
- gtk_init (&argc, &argv);
+ gtk_init (&argc, &argv);
- rsvg_init ();
+ rsvg_init ();
- screen = gdk_screen_get_default ();
+ screen = gdk_screen_get_default ();
+ width = gdk_screen_get_width (screen);
+ height = gdk_screen_get_height (screen);
- closure.anchor_x = screen_width / 2;
- closure.anchor_y = screen_height - 50;
- closure.spacing = spacing;
- closure.num_icons = num_icons;
- closure.windows = g_new (GdkWindow *, num_icons);
+ closure.spacing = spacing;
+ closure.height = height - 50;
+ closure.num_icons = num_icons;
+ closure.windows = g_new (GdkWindow *, num_icons);
- model_init_dock (&closure.model, num_icons,
- closure.anchor_x, closure.anchor_y, spacing);
+ model_init_dock (&closure.model, num_icons, width, height, spacing);
- for (i = 0; i < num_icons; i++) {
+ for (i = 0; i < num_icons; i++) {
- handle = rsvg_handle_new_from_file (icons[i], NULL);
- rsvg_handle_get_dimensions (handle, &dimension);
+ handle = rsvg_handle_new_from_file (icons[i], NULL);
+ rsvg_handle_get_dimensions (handle, &dimension);
- x = closure.model.objects[i + 1].position.x;
- y = closure.model.objects[i + 1].position.y;
- width = dimension.width;
- height = dimension.height;
- closure.windows[i] = create_window (screen, x, y, width, height);
+ x = closure.model.objects[i + 1].position.x;
+ y = closure.model.objects[i + 1].position.y;
+ closure.windows[i] =
+ create_window (screen, x, y, dimension.width, dimension.height);
- gdk_window_show (closure.windows[i]);
+ gdk_window_show (closure.windows[i]);
- cr = gdk_cairo_create (closure.windows[i]);
- cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
- cairo_paint (cr);
- cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
- rsvg_handle_render_cairo (handle, cr);
- rsvg_handle_free (handle);
- cairo_destroy (cr);
+ cr = gdk_cairo_create (closure.windows[i]);
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ cairo_paint (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ rsvg_handle_render_cairo (handle, cr);
+ rsvg_handle_free (handle);
+ cairo_destroy (cr);
- gdk_window_add_filter (closure.windows[i], window_event, &closure);
- }
+ gdk_window_add_filter (closure.windows[i], window_event, &closure);
+ }
- g_timeout_add (20, timeout_callback, &closure);
+ g_timeout_add (20, timeout_callback, &closure);
- gtk_main ();
+ gtk_main ();
- rsvg_term ();
+ rsvg_term ();
- return 0;
+ return 0;
}