summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2006-07-16 01:37:05 -0400
committerKristian Høgsberg <krh@redhat.com>2006-07-16 01:37:05 -0400
commitf7170206654348e7b1f6dfd7588d7de4ef4d5c91 (patch)
tree998fd78113166e956a10222742b9dcf60d209318
parent86a22797c7970393095ac678619dbad042d0a81b (diff)
Make the dock draggable.
-rw-r--r--dock.c83
1 files changed, 69 insertions, 14 deletions
diff --git a/dock.c b/dock.c
index f6df955..b34f749 100644
--- a/dock.c
+++ b/dock.c
@@ -12,6 +12,7 @@
#include <string.h>
#include <sys/time.h>
#include <math.h>
+#include <limits.h>
#include <gconf/gconf-client.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
@@ -74,6 +75,7 @@ struct _KibaDock
int drag_distance;
KibaLauncher *dragging_launcher;
int dx, dy;
+ gboolean dragging_dock;
GConfClient *gconf_client;
};
@@ -141,21 +143,22 @@ typedef struct {
GtkOrientation orientation;
int halignment;
int valignment;
+ GdkPoint anchor;
} KibaDockLayoutData;
static const KibaDockLayoutData kiba_dock_layout_data[] = {
- { "left-edge-top", GTK_ORIENTATION_VERTICAL, 0, 0 },
- { "left-edge-center", GTK_ORIENTATION_VERTICAL, 0, 1 },
- { "left-edge-bottom", GTK_ORIENTATION_VERTICAL, 0, 2 },
- { "right-edge-top", GTK_ORIENTATION_VERTICAL, 2, 0 },
- { "right-edge-center", GTK_ORIENTATION_VERTICAL, 2, 1 },
- { "right-edge-bottom", GTK_ORIENTATION_VERTICAL, 2, 2 },
- { "top-edge-left", GTK_ORIENTATION_HORIZONTAL, 0, 0 },
- { "top-edge-center", GTK_ORIENTATION_HORIZONTAL, 1, 0 },
- { "top-edge-right", GTK_ORIENTATION_HORIZONTAL, 2, 0 },
- { "bottom-edge-left", GTK_ORIENTATION_HORIZONTAL, 0, 2 },
- { "bottom-edge-center", GTK_ORIENTATION_HORIZONTAL, 1, 2 },
- { "bottom-edge-right", GTK_ORIENTATION_HORIZONTAL, 2, 2 }
+ { "left-edge-top", GTK_ORIENTATION_VERTICAL, 0, 0, { 0, 1 } },
+ { "left-edge-center", GTK_ORIENTATION_VERTICAL, 0, 1, { 0, 2 } },
+ { "left-edge-bottom", GTK_ORIENTATION_VERTICAL, 0, 2, { 0, 3 } },
+ { "right-edge-top", GTK_ORIENTATION_VERTICAL, 2, 0, { 4, 1 } },
+ { "right-edge-center", GTK_ORIENTATION_VERTICAL, 2, 1, { 4, 2 } },
+ { "right-edge-bottom", GTK_ORIENTATION_VERTICAL, 2, 2, { 4, 3 } },
+ { "top-edge-left", GTK_ORIENTATION_HORIZONTAL, 0, 0, { 1, 0 } },
+ { "top-edge-center", GTK_ORIENTATION_HORIZONTAL, 1, 0, { 2, 0 } },
+ { "top-edge-right", GTK_ORIENTATION_HORIZONTAL, 2, 0, { 3, 0 } },
+ { "bottom-edge-left", GTK_ORIENTATION_HORIZONTAL, 0, 2, { 1, 4 } },
+ { "bottom-edge-center", GTK_ORIENTATION_HORIZONTAL, 1, 2, { 2, 4 } },
+ { "bottom-edge-right", GTK_ORIENTATION_HORIZONTAL, 2, 2, { 3, 4 } }
};
static void
@@ -349,7 +352,15 @@ kiba_dock_realize (GtkWidget *widget)
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.visual = gdk_screen_get_rgba_visual (screen);
attributes.colormap = gdk_screen_get_rgba_colormap (screen);
- attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
+ attributes.event_mask = gtk_widget_get_events (widget) |
+ 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;
if (attributes.visual != NULL && attributes.colormap != NULL)
attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP;
@@ -521,6 +532,12 @@ kiba_dock_button_press_event (GtkWidget *widget,
dock->drag_offset_y = event->y;
dock->drag_distance = 0;
+ if (widget->window == event->window)
+ {
+ dock->dragging_dock = TRUE;
+ return TRUE;
+ }
+
launcher = kiba_dock_get_launcher_for_window (dock, event->window);
if (launcher == NULL)
return FALSE;
@@ -606,6 +623,12 @@ kiba_dock_button_release_event (GtkWidget *widget,
{
KibaDock *dock = KIBA_DOCK (widget);
+ if (dock->dragging_dock)
+ {
+ dock->dragging_dock = FALSE;
+ return TRUE;
+ }
+
if (dock->dragging_launcher && dock->drag_distance <= 1)
g_idle_add (kiba_launcher_exec, dock->dragging_launcher);
else
@@ -620,15 +643,47 @@ kiba_dock_button_release_event (GtkWidget *widget,
return TRUE;
}
+static int
+kiba_dock_find_closest_position (KibaDock *dock, int x, int y)
+{
+ int i, min_d, d, position;
+ int dx, dy;
+
+ min_d = INT_MAX;
+ for (i = 0; i < G_N_ELEMENTS (kiba_dock_layout_data); i++)
+ {
+ dx = x - dock->geometry.width * kiba_dock_layout_data[i].anchor.x / 4;
+ dy = y - dock->geometry.height * kiba_dock_layout_data[i].anchor.y / 4;
+ d = dx * dx + dy * dy;
+ if (d < min_d)
+ {
+ min_d = d;
+ position = i;
+ }
+ }
+
+ return position;
+}
+
static gboolean
kiba_dock_motion_notify_event (GtkWidget *widget,
GdkEventMotion *event)
{
KibaDock *dock = KIBA_DOCK (widget);
GdkModifierType state;
- int x, y, new_x, new_y, dx, dy;
+ int x, y, new_x, new_y, dx, dy, position;
gdk_window_get_pointer (gdk_get_default_root_window(), &x, &y, &state);
+
+ if (dock->dragging_dock)
+ {
+ position = kiba_dock_find_closest_position (dock, x, y);
+ gconf_client_set_string (dock->gconf_client,
+ KIBA_GCONF_PATH "/options/position",
+ kiba_dock_layout_data[position].name, NULL);
+ return TRUE;
+ }
+
new_x = x - dock->drag_offset_x + ICON_SIZE / 2;
new_y = y - dock->drag_offset_y + ICON_SIZE / 2;
dx = new_x - dock->mouse_anchor->x;