diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp
index 46fb00c..4517323 100644
--- a/src/desktop-events.cpp
+++ b/src/desktop-events.cpp
@@ -51,6 +51,26 @@ int sp_desktop_root_handler(SPCanvasItem */*item*/, GdkEvent *event, SPDesktop *
     static bool watch = false;
     static bool first = true;
 
+    SPDocument *document = sp_desktop_document(desktop);
+
+    if (event->type == GDK_KEY_PRESS) {
+        switch (get_group0_keyval (&event->key)) {
+            case GDK_P:
+                g_print ("P was pressed.\n");
+                g_print ("List of active guides:\n");
+                for (std::set<SPGuide*>::iterator i = document->guides_selected.begin();
+                     i != document->guides_selected.end(); ++i) {
+                    g_print ("   ... found a guide line: %s\n", SP_OBJECT_REPR(*i)->attribute("id"));
+                }
+                return TRUE;
+        }
+    }
+
+    if (event->type == GDK_BUTTON_PRESS) {
+        g_print ("Button was pressed outside any guide. Deselect all guides.\n");
+        document->deselect_all_guides();
+    }
+
     if ( first ) {
         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
         if ( prefs->getBool("/options/useextinput/value", true)
@@ -132,6 +152,7 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
                 }
 
                 guide = sp_guideline_new(desktop->guides, event_dt, normal);
+                g_print ("############## Setting color.\n");
                 sp_guideline_set_color(SP_GUIDELINE(guide), desktop->namedview->guidehicolor);
                 gdk_pointer_grab(widget->window, FALSE,
                                  (GdkEventMask)(GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK ),
@@ -210,6 +231,8 @@ enum SPGuideDragType {
 
 static SPGuideDragType drag_type = SP_DRAG_NONE;
 
+static bool tmp_selected = false;
+
 gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
 {
     static bool moved = false;
@@ -217,6 +240,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
 
     SPGuide *guide = SP_GUIDE(data);
     SPDesktop *desktop = static_cast<SPDesktop*>(gtk_object_get_data(GTK_OBJECT(item->canvas), "SPDesktop"));
+    SPDocument *document = sp_desktop_document(desktop);
 
     switch (event->type) {
 	case GDK_2BUTTON_PRESS:
@@ -236,6 +260,11 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                     sp_document_done(doc, SP_VERB_NONE, _("Delete guide"));
                     ret = TRUE;
                     break;
+                } else {
+                    if (!document->guide_is_selected(guide)) {
+                        tmp_selected = true;
+                    }
+                    document->select_guide(guide);
                 }
 
                 sp_canvas_set_snap_delay_active(desktop->canvas, true);
@@ -273,19 +302,22 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                 switch (drag_type) {
                     case SP_DRAG_TRANSLATE:
                     {
-                        sp_guide_moveto(*guide, guide->point_on_line + motion_dt - drag_origin, false);
+                        g_print ("SP_DRAG_TRANSLATE\n");
+                        document->selected_guides_translate(motion_dt - drag_origin, false);
                         break;
                     }
+                    /**
                     case SP_DRAG_TRANSLATE_CONSTRAINED:
                     {
                         Geom::Point pt_constr = Geom::constrain_angle(guide->point_on_line, motion_dt);
                         sp_guide_moveto(*guide, pt_constr, false);
                         break;
                     }
+                    **/
                     case SP_DRAG_ROTATE:
                     {
                         double angle = angle_between(drag_origin - guide->point_on_line, motion_dt - guide->point_on_line);
-                        sp_guide_set_normal(*guide, guide->normal_to_line * Geom::Rotate(angle), false);
+                        document->selected_guides_rotate_around(guide->point_on_line, angle, false);
                         break;
                     }
                     case SP_DRAG_MOVE_ORIGIN:
@@ -309,6 +341,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
     case GDK_BUTTON_RELEASE:
             if (drag_type != SP_DRAG_NONE && event->button.button == 1) {
                 if (moved) {
+                    g_print ("moved == true\n");
                     Geom::Point const event_w(event->button.x,
                                               event->button.y);
                     Geom::Point event_dt(desktop->w2d(event_w));
@@ -321,19 +354,21 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                         switch (drag_type) {
                             case SP_DRAG_TRANSLATE:
                             {
-                                sp_guide_moveto(*guide, guide->point_on_line + event_dt - drag_origin, true);
+                                document->selected_guides_translate(event_dt - drag_origin, true);
                                 break;
                             }
+                            /**
                             case SP_DRAG_TRANSLATE_CONSTRAINED:
                             {
                                 Geom::Point pt_constr = Geom::constrain_angle(guide->point_on_line, event_dt);
                                 sp_guide_moveto(*guide, pt_constr, true);
                                 break;
                             }
+                            **/
                             case SP_DRAG_ROTATE:
                             {
                                 double angle = angle_between(drag_origin - guide->point_on_line, event_dt - guide->point_on_line);
-                                sp_guide_set_normal(*guide, guide->normal_to_line * Geom::Rotate(angle), true);
+                                document->selected_guides_rotate_around(guide->point_on_line, angle, true);
                                 break;
                             }
                             case SP_DRAG_MOVE_ORIGIN:
@@ -360,6 +395,14 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                     moved = false;
                     desktop->set_coordinate_status(from_2geom(event_dt));
                     desktop->setPosition (from_2geom(event_dt));
+                } else {
+                    g_print ("moved == false\n");
+                    if (!tmp_selected) {
+                        document->guide_toggle_selected(guide);
+                    }
+                    tmp_selected = false;
+                    g_print ("Guide was toggled (now %s)\n",
+                             document->guide_is_selected(guide) ? "selected" : "deselected");
                 }
                 drag_type = SP_DRAG_NONE;
                 sp_canvas_set_snap_delay_active(desktop->canvas, false);
@@ -368,7 +411,11 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
             }
     case GDK_ENTER_NOTIFY:
     {
-            sp_guideline_set_color(SP_GUIDELINE(item), guide->hicolor);
+            if (!sp_guide_is_selected(guide)) {
+                sp_guideline_set_color(SP_GUIDELINE(item), guide->hicolor);
+            } else {
+                g_print ("Guide is selected. Leaving along...\n");
+            }
 
             char *guide_description = sp_guide_description(guide);
             desktop->guidesMessageContext()->setF(Inkscape::NORMAL_MESSAGE, _("<b>Guideline</b>: %s"), guide_description);
@@ -376,9 +423,15 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
             break;
     }
     case GDK_LEAVE_NOTIFY:
-            sp_guideline_set_color(SP_GUIDELINE(item), guide->color);
+            if (!sp_guide_is_selected(guide)) {
+                sp_guideline_set_color(SP_GUIDELINE(item), guide->color);
+            } else {
+                g_print ("Guide is selected. Leaving along...\n");
+            }
             desktop->guidesMessageContext()->clear();
             break;
+        break;
+
     default:
             break;
     }
diff --git a/src/display/guideline.cpp b/src/display/guideline.cpp
index f1b85b5..8b7cd83 100644
--- a/src/display/guideline.cpp
+++ b/src/display/guideline.cpp
@@ -79,6 +79,7 @@ static void sp_guideline_init(SPGuideLine *gl)
     gl->angle = 3.14159265358979323846/2;
     gl->point_on_line = Geom::Point(0,0);
     gl->sensitive = 0;
+    gl->selected = false;
 
     gl->origin = NULL;
 }
@@ -229,6 +230,8 @@ SPCanvasItem *sp_guideline_new(SPCanvasGroup *parent, Geom::Point point_on_line,
 {
     SPCanvasItem *item = sp_canvas_item_new(parent, SP_TYPE_GUIDELINE, NULL);
     SPCanvasItem *origin = sp_canvas_item_new(parent, SP_TYPE_CTRLPOINT, NULL);
+    // initially we hide the origin; it is only displayed if the guide is selected
+    sp_canvas_item_hide(SP_CANVAS_ITEM(origin));
 
     SPGuideLine *gl = SP_GUIDELINE(item);
     SPCtrlPoint *cp = SP_CTRLPOINT(origin);
@@ -271,6 +274,16 @@ void sp_guideline_set_sensitive(SPGuideLine *gl, int sensitive)
     gl->sensitive = sensitive;
 }
 
+void sp_guideline_set_selected(SPGuideLine *gl, bool select)
+{
+    gl->selected = select;
+    if (select) {
+        sp_canvas_item_show(SP_CANVAS_ITEM(gl->origin));
+    } else {
+        sp_canvas_item_hide(SP_CANVAS_ITEM(gl->origin));
+    }
+}
+
 void sp_guideline_delete(SPGuideLine *gl)
 {
     //gtk_object_destroy(GTK_OBJECT(gl->origin));
diff --git a/src/display/guideline.h b/src/display/guideline.h
index a6ce571..65dd6d3 100644
--- a/src/display/guideline.h
+++ b/src/display/guideline.h
@@ -34,6 +34,7 @@ struct SPGuideLine {
     double angle;
 
     unsigned int sensitive : 1;
+    bool selected;
 
     inline bool is_horizontal() const { return (normal_to_line[Geom::X] == 0.); };
     inline bool is_vertical() const { return (normal_to_line[Geom::Y] == 0.); };
@@ -51,6 +52,7 @@ void sp_guideline_set_position(SPGuideLine *gl, Geom::Point point_on_line);
 void sp_guideline_set_normal(SPGuideLine *gl, Geom::Point normal_to_line);
 void sp_guideline_set_color(SPGuideLine *gl, unsigned int rgba);
 void sp_guideline_set_sensitive(SPGuideLine *gl, int sensitive);
+void sp_guideline_set_selected(SPGuideLine *gl, bool select);
 void sp_guideline_delete(SPGuideLine *gl);
 
 #endif
diff --git a/src/document.cpp b/src/document.cpp
index 4f54870..52e9653 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -57,6 +57,7 @@
 #include "sp-item-group.h"
 #include "profile-manager.h"
 #include "persp3d.h"
+#include "sp-guide.h"
 
 #include "display/nr-arena-item.h"
 
@@ -225,6 +226,97 @@ void SPDocument::remove_persp3d (Persp3D * const /*persp*/)
     g_print ("Please implement deletion of perspectives here.\n");
 }
 
+
+/**
+ * Mark guide as selected (e.g., when the user clicks on it).
+ */
+void
+SPDocument::select_guide(SPGuide *guide)
+{
+    sp_guide_set_selected(guide, true);
+    guides_selected.insert(guide);
+}
+
+/**
+ * Mark guide as deselected (e.g., when the user clicks on it a second time or when it is
+ * destroyed). We don't require that the guide is already selected.
+ */
+void
+SPDocument::deselect_guide(SPGuide *guide)
+{
+    if (guides_selected.find(guide) == guides_selected.end()) {
+        g_print ("Guide not selected. Deselecting anyway...\n");
+    }
+    sp_guide_set_selected(guide, false);
+    guides_selected.erase(guide);
+}
+
+/**
+ * Returns true if the guide is marked as selected.
+ */
+bool
+SPDocument::guide_is_selected(SPGuide *guide)
+{
+    return guides_selected.find(guide) != guides_selected.end();
+}
+
+/**
+ * Toggles the selection status of a guide.
+ */
+void
+SPDocument::guide_toggle_selected(SPGuide *guide)
+{
+    if (guide_is_selected(guide)) {
+        deselect_guide(guide);
+    } else {
+        select_guide(guide);
+    }
+}
+
+/**
+ * Marks all guides as deselected.
+ */
+void
+SPDocument::deselect_all_guides()
+{
+    std::set<SPGuide*>::iterator i;
+    for (i = guides_selected.begin(); i != guides_selected.end(); ++i) {
+        sp_guide_set_selected(*i, false);
+    }
+    guides_selected.clear();
+}
+
+/**
+ * Translates all selected guides by the specified vector.
+ * Only writes to SVG if commit is true.
+ */
+void
+SPDocument::selected_guides_translate(Geom::Point const &v, bool commit)
+{
+    std::set<SPGuide*>::iterator i;
+    SPGuide *guide;
+    for (i = guides_selected.begin(); i != guides_selected.end(); ++i) {
+        guide = *i;
+        sp_guide_moveto(*guide, guide->point_on_line + v, commit);
+    }
+}
+
+/**
+ * Rotates all selected guides by the specified angle (in radians).
+ * Only writes to svg if commit is true.
+ */
+void
+SPDocument::selected_guides_rotate_around(Geom::Point const &pt, double const angle, bool commit)
+{
+    std::set<SPGuide*>::iterator i;
+    SPGuide *guide;
+    for (i = guides_selected.begin(); i != guides_selected.end(); ++i) {
+        guide = *i;
+        //sp_guide_set_normal(*guide, guide->normal_to_line * Geom::Rotate(angle), commit);
+        sp_guide_rotate_around(guide, pt, angle, commit);
+    }
+}
+
 unsigned long SPDocument::serial() const {
     return priv->serial;
 }
diff --git a/src/document.h b/src/document.h
index 3ede5a3..4df9e67 100644
--- a/src/document.h
+++ b/src/document.h
@@ -108,6 +108,8 @@ struct SPDocument : public Inkscape::GC::Managed<>,
 
     Persp3D *current_persp3d; // "currently active" perspective (e.g., newly created boxes are attached to this one)
 
+    std::set<SPGuide*> guides_selected;
+
     GSList *_collection_queue;
 
     bool oldSignalsConnected;
@@ -115,6 +117,14 @@ struct SPDocument : public Inkscape::GC::Managed<>,
     void add_persp3d (Persp3D * const persp);
     void remove_persp3d (Persp3D * const persp);
 
+    void select_guide (SPGuide *guide);
+    void deselect_guide (SPGuide *guide);
+    void deselect_all_guides ();
+    bool guide_is_selected (SPGuide *guide);
+    void guide_toggle_selected (SPGuide *guide);
+    void selected_guides_translate(Geom::Point const &v, bool commit);
+    void selected_guides_rotate_around(Geom::Point const &pt, double const angle, bool commit);
+
     sigc::connection connectModified(ModifiedSignal::slot_type slot);
     sigc::connection connectURISet(URISetSignal::slot_type slot);
     sigc::connection connectResized(ResizedSignal::slot_type slot);
diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp
index 307402d..ea6a474 100644
--- a/src/sp-guide.cpp
+++ b/src/sp-guide.cpp
@@ -332,6 +332,15 @@ void sp_guide_sensitize(SPGuide *guide, SPCanvas *canvas, gboolean sensitive)
     g_assert_not_reached();
 }
 
+void sp_guide_set_selected(SPGuide *guide, bool select)
+{
+    guide->selected = select;
+    for (GSList *l = guide->views; l != NULL; l = l->next) {
+        sp_guideline_set_color(SP_GUIDELINE(l->data), select ? guide->hicolor : guide->color);
+        sp_guideline_set_selected(SP_GUIDELINE(l->data), select);
+    }
+}
+
 Geom::Point sp_guide_position_from_pt(SPGuide const *guide, Geom::Point const &pt)
 {
     return -(pt - guide->point_on_line);
@@ -403,6 +412,35 @@ void sp_guide_set_normal(SPGuide const &guide, Geom::Point const normal_to_line,
 }
 
 /**
+ * \arg commit False indicates temporary moveto in response to motion event while dragging,
+ *      true indicates a "committing" version: in response to button release event after
+ *      dragging a guideline, or clicking OK in guide editing dialog.
+ */
+void sp_guide_rotate_around(SPGuide const *guide, Geom::Point const &pt, double const angle, bool const commit)
+{
+    g_assert(SP_IS_GUIDE(guide));
+
+    Geom::Point dir(guide->point_on_line - pt);
+    Geom::Rotate rot(angle);
+
+    Geom::Point new_pos = pt + dir * rot;
+    Geom::Point new_normal = guide->normal_to_line * rot;
+    for (GSList *l = guide->views; l != NULL; l = l->next) {
+        sp_guideline_set_position(SP_GUIDELINE(l->data), new_pos);
+    }
+    for (GSList *l = guide->views; l != NULL; l = l->next) {
+        sp_guideline_set_normal(SP_GUIDELINE(l->data), new_normal);
+    }
+
+    /* Calling sp_repr_set_svg_point must precede calling sp_item_notify_moveto in the commit
+       case, so that the guide's new position is available for sp_item_rm_unsatisfied_cns. */
+    if (commit) {
+        sp_repr_set_point(SP_OBJECT(guide)->repr, "position", pt + dir * rot);
+        sp_repr_set_point(SP_OBJECT(guide)->repr, "orientation", guide->normal_to_line * rot);
+    }
+}
+
+/**
  * Returns a human-readable description of the guideline for use in dialog boxes and status bar.
  *
  * The caller is responsible for freeing the string.
diff --git a/src/sp-guide.h b/src/sp-guide.h
index 593e458..0754691 100644
--- a/src/sp-guide.h
+++ b/src/sp-guide.h
@@ -33,6 +33,7 @@ struct SPGuide : public SPObject {
     guint32 hicolor;
     GSList *views;
     std::vector<SPGuideAttachment> attached_items;
+    bool selected;
 
     inline bool is_horizontal() const { return (normal_to_line[Geom::X] == 0.); };
     inline bool is_vertical() const { return (normal_to_line[Geom::Y] == 0.); };
@@ -53,10 +54,14 @@ void sp_guide_show(SPGuide *guide, SPCanvasGroup *group, GCallback handler);
 void sp_guide_hide(SPGuide *guide, SPCanvas *canvas);
 void sp_guide_sensitize(SPGuide *guide, SPCanvas *canvas, gboolean sensitive);
 
+void sp_guide_set_selected(SPGuide *guide, bool select);
+inline bool sp_guide_is_selected(SPGuide *guide) { return guide->selected; }
+
 Geom::Point sp_guide_position_from_pt(SPGuide const *guide, Geom::Point const &pt);
 double sp_guide_distance_from_pt(SPGuide const *guide, Geom::Point const &pt);
 void sp_guide_moveto(SPGuide const &guide, Geom::Point const point_on_line, bool const commit);
 void sp_guide_set_normal(SPGuide const &guide, Geom::Point const normal_to_line, bool const commit);
+void sp_guide_rotate_around(SPGuide const *guide, Geom::Point const &pt, double const angle, bool const commit);
 void sp_guide_remove(SPGuide *guide);
 
 char *sp_guide_description(SPGuide const *guide);
