Merging trunk up to r39145.
[blender.git] / source / blender / editors / space_action / action_select.c
index 1881cfbc99cf198a380f16184bb36253ccbd3e03..68dd0a8c2562587b6c0412132337a2d9af9757b9 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2008 Blender Foundation
  *
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/editors/space_action/action_select.c
+ *  \ingroup spaction
+ */
+
+
 #include <math.h>
 #include <stdlib.h>
 #include <string.h>
 #include <float.h>
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
 #include "BLI_dlrbTree.h"
+#include "BLI_utildefines.h"
 
 #include "DNA_anim_types.h"
-#include "DNA_action_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_curve_types.h"
+#include "DNA_gpencil_types.h"
 #include "DNA_object_types.h"
-#include "DNA_screen_types.h"
 #include "DNA_scene_types.h"
-#include "DNA_space_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_key_types.h"
-#include "DNA_lamp_types.h"
-#include "DNA_material_types.h"
-#include "DNA_userdef_types.h"
-#include "DNA_gpencil_types.h"
-#include "DNA_windowmanager_types.h"
-#include "DNA_world_types.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
 
-#include "BKE_action.h"
-#include "BKE_depsgraph.h"
 #include "BKE_fcurve.h"
-#include "BKE_key.h"
-#include "BKE_material.h"
 #include "BKE_nla.h"
-#include "BKE_object.h"
 #include "BKE_context.h"
-#include "BKE_utildefines.h"
 
 #include "UI_view2d.h"
 
 #include "ED_anim_api.h"
-#include "ED_keyframing.h"
+#include "ED_gpencil.h"
 #include "ED_keyframes_draw.h"
 #include "ED_keyframes_edit.h"
 #include "ED_markers.h"
 #include "ED_screen.h"
-#include "ED_space_api.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
 
 #include "action_intern.h"
 
+
 /* ************************************************************************** */
 /* KEYFRAMES STUFF */
 
  *     - This is called by the deselect all operator, as well as other ones!
  *
  *     - test: check if select or deselect all
- *     - sel: how to select keyframes 
- *             0 = deselect
- *             1 = select
- *             2 = invert
+ *     - sel: how to select keyframes (SELECT_*)
  */
 static void deselect_action_keys (bAnimContext *ac, short test, short sel)
 {
@@ -110,33 +90,32 @@ static void deselect_action_keys (bAnimContext *ac, short test, short sel)
        bAnimListElem *ale;
        int filter;
        
-       BeztEditData bed;
-       BeztEditFunc test_cb, sel_cb;
+       KeyframeEditData ked= {{NULL}};
+       KeyframeEditFunc test_cb, sel_cb;
        
        /* determine type-based settings */
        if (ac->datatype == ANIMCONT_GPENCIL)
-               filter= (ANIMFILTER_VISIBLE);
+               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
        else
-               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        
        /* filter data */
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* init BezTriple looping data */
-       memset(&bed, 0, sizeof(BeztEditData));
        test_cb= ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
        
        /* See if we should be selecting or deselecting */
        if (test) {
                for (ale= anim_data.first; ale; ale= ale->next) {
                        if (ale->type == ANIMTYPE_GPLAYER) {
-                               //if (is_gplayer_frame_selected(ale->data)) {
-                               //      sel= 0;
-                               //      break;
-                               //}
+                               if (is_gplayer_frame_selected(ale->data)) {
+                                       sel= SELECT_SUBTRACT;
+                                       break;
+                               }
                        }
                        else {
-                               if (ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, test_cb, NULL)) {
+                               if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
                                        sel= SELECT_SUBTRACT;
                                        break;
                                }
@@ -149,10 +128,10 @@ static void deselect_action_keys (bAnimContext *ac, short test, short sel)
        
        /* Now set the flags */
        for (ale= anim_data.first; ale; ale= ale->next) {
-               //if (ale->type == ACTTYPE_GPLAYER)
-               //      set_gplayer_frame_selection(ale->data, sel);
-               //else
-                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, sel_cb, NULL);
+               if (ale->type == ANIMTYPE_GPLAYER)
+                       set_gplayer_frame_selection(ale->data, sel);
+               else
+                       ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL); 
        }
        
        /* Cleanup */
@@ -176,7 +155,7 @@ static int actkeys_deselectall_exec(bContext *C, wmOperator *op)
                deselect_action_keys(&ac, 1, SELECT_ADD);
        
        /* set notifier that keyframe selection have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_SELECTED, NULL);
        
        return OPERATOR_FINISHED;
 }
@@ -186,7 +165,7 @@ void ACTION_OT_select_all_toggle (wmOperatorType *ot)
        /* identifiers */
        ot->name= "Select All";
        ot->idname= "ACTION_OT_select_all_toggle";
-       ot->description= "Toggle selection of all keyframes.";
+       ot->description= "Toggle selection of all keyframes";
        
        /* api callbacks */
        ot->exec= actkeys_deselectall_exec;
@@ -196,7 +175,7 @@ void ACTION_OT_select_all_toggle (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* props */
-       RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
+       ot->prop= RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
 }
 
 /* ******************** Border Select Operator **************************** */
@@ -212,17 +191,17 @@ enum {
        ACTKEYS_BORDERSEL_ALLKEYS       = 0,
        ACTKEYS_BORDERSEL_FRAMERANGE,
        ACTKEYS_BORDERSEL_CHANNELS,
-} eActKeys_BorderSelect_Mode;
+} /*eActKeys_BorderSelect_Mode*/;
 
 
 static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short selectmode)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
-       int filter, filterflag;
+       int filter;
        
-       BeztEditData bed;
-       BeztEditFunc ok_cb, select_cb;
+       KeyframeEditData ked;
+       KeyframeEditFunc ok_cb, select_cb;
        View2D *v2d= &ac->ar->v2d;
        rctf rectf;
        float ymin=0, ymax=(float)(-ACHANNEL_HEIGHT_HALF);
@@ -232,17 +211,9 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short
        UI_view2d_region_to_view(v2d, rect.xmax, rect.ymax-2, &rectf.xmax, &rectf.ymax);
        
        /* filter data */
-       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
+       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
-       /* get filtering flag for dopesheet data (if applicable) */
-       if (ac->datatype == ANIMCONT_DOPESHEET) {
-               bDopeSheet *ads= (bDopeSheet *)ac->data;
-               filterflag= ads->filterflag;
-       }
-       else
-               filterflag= 0;
-       
        /* get beztriple editing/validation funcs  */
        select_cb= ANIM_editkeyframes_select(selectmode);
        
@@ -252,7 +223,7 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short
                ok_cb= NULL;
                
        /* init editing data */
-       memset(&bed, 0, sizeof(BeztEditData));
+       memset(&ked, 0, sizeof(KeyframeEditData));
        
        /* loop over data, doing border select */
        for (ale= anim_data.first; ale; ale= ale->next) {
@@ -265,12 +236,12 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short
                if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) {
                        /* if channel is mapped in NLA, apply correction */
                        if (adt) {
-                               bed.f1= BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
-                               bed.f2= BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
+                               ked.f1= BKE_nla_tweakedit_remap(adt, rectf.xmin, NLATIME_CONVERT_UNMAP);
+                               ked.f2= BKE_nla_tweakedit_remap(adt, rectf.xmax, NLATIME_CONVERT_UNMAP);
                        }
                        else {
-                               bed.f1= rectf.xmin;
-                               bed.f2= rectf.xmax;
+                               ked.f1= rectf.xmin;
+                               ked.f2= rectf.xmax;
                        }
                }
                
@@ -279,10 +250,10 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short
                        !((ymax < rectf.ymin) || (ymin > rectf.ymax)) )
                {
                        /* loop over data selecting */
-                       //if (ale->type == ANIMTYPE_GPLAYER)
-                       //      borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
-                       //else
-                               ANIM_animchannel_keys_bezier_loop(&bed, ale, ok_cb, select_cb, NULL, filterflag);
+                       if (ale->type == ANIMTYPE_GPLAYER)
+                               borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
+                       else
+                               ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
                }
                
                /* set minimum extent to be the maximum of the next channel */
@@ -337,7 +308,7 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op)
        borderselect_action(&ac, rect, mode, selectmode);
        
        /* set notifier that keyframe selection have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_SELECTED, NULL);
        
        return OPERATOR_FINISHED;
 } 
@@ -347,12 +318,13 @@ void ACTION_OT_select_border(wmOperatorType *ot)
        /* identifiers */
        ot->name= "Border Select";
        ot->idname= "ACTION_OT_select_border";
-       ot->description= "Select all keyframes within the specified region.";
+       ot->description= "Select all keyframes within the specified region";
        
        /* api callbacks */
        ot->invoke= WM_border_select_invoke;
        ot->exec= actkeys_borderselect_exec;
        ot->modal= WM_border_select_modal;
+       ot->cancel= WM_border_select_cancel;
        
        ot->poll= ED_operator_action_active;
        
@@ -362,7 +334,7 @@ void ACTION_OT_select_border(wmOperatorType *ot)
        /* rna */
        WM_operator_properties_gesture_border(ot, FALSE);
        
-       RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
+       ot->prop= RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
 }
 
 /* ******************** Column Select Operator **************************** */
@@ -391,8 +363,8 @@ static void markers_selectkeys_between (bAnimContext *ac)
        bAnimListElem *ale;
        int filter;
        
-       BeztEditFunc ok_cb, select_cb;
-       BeztEditData bed;
+       KeyframeEditFunc ok_cb, select_cb;
+       KeyframeEditData ked= {{NULL}};
        float min, max;
        
        /* get extreme markers */
@@ -403,13 +375,12 @@ static void markers_selectkeys_between (bAnimContext *ac)
        /* get editing funcs + data */
        ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
        select_cb= ANIM_editkeyframes_select(SELECT_ADD);
-       
-       memset(&bed, 0, sizeof(BeztEditData));
-       bed.f1= min; 
-       bed.f2= max;
+
+       ked.f1= min; 
+       ked.f2= max;
        
        /* filter data */
-       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* select keys in-between */
@@ -418,11 +389,14 @@ static void markers_selectkeys_between (bAnimContext *ac)
                
                if (adt) {
                        ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
-                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+                       ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
                        ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
                }
+               else if (ale->type == ANIMTYPE_GPLAYER) {
+                       borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD);
+               }
                else {
-                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+                       ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
                }
        }
        
@@ -440,28 +414,27 @@ static void columnselect_action_keys (bAnimContext *ac, short mode)
        
        Scene *scene= ac->scene;
        CfraElem *ce;
-       BeztEditFunc select_cb, ok_cb;
-       BeztEditData bed;
+       KeyframeEditFunc select_cb, ok_cb;
+       KeyframeEditData ked= {{NULL}};
        
        /* initialise keyframe editing data */
-       memset(&bed, 0, sizeof(BeztEditData));
        
        /* build list of columns */
        switch (mode) {
                case ACTKEYS_COLUMNSEL_KEYS: /* list of selected keys */
                        if (ac->datatype == ANIMCONT_GPENCIL) {
-                               filter= (ANIMFILTER_VISIBLE);
+                               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
                                ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
                                
-                               //for (ale= anim_data.first; ale; ale= ale->next)
-                               //      gplayer_make_cfra_list(ale->data, &elems, 1);
+                               for (ale= anim_data.first; ale; ale= ale->next)
+                                       gplayer_make_cfra_list(ale->data, &ked.list, 1);
                        }
                        else {
-                               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+                               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
                                ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
                                
                                for (ale= anim_data.first; ale; ale= ale->next)
-                                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, NULL, bezt_to_cfraelem, NULL);
+                                       ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, bezt_to_cfraelem, NULL);
                        }
                        BLI_freelistN(&anim_data);
                        break;
@@ -469,13 +442,13 @@ static void columnselect_action_keys (bAnimContext *ac, short mode)
                case ACTKEYS_COLUMNSEL_CFRA: /* current frame */
                        /* make a single CfraElem for storing this */
                        ce= MEM_callocN(sizeof(CfraElem), "cfraElem");
-                       BLI_addtail(&bed.list, ce);
+                       BLI_addtail(&ked.list, ce);
                        
                        ce->cfra= (float)CFRA;
                        break;
                        
                case ACTKEYS_COLUMNSEL_MARKERS_COLUMN: /* list of selected markers */
-                       ED_markers_make_cfra_list(ac->markers, &bed.list, 1);
+                       ED_markers_make_cfra_list(ac->markers, &ked.list, SELECT);
                        break;
                        
                default: /* invalid option */
@@ -490,44 +463,34 @@ static void columnselect_action_keys (bAnimContext *ac, short mode)
         * based on the keys found to be selected above
         */
        if (ac->datatype == ANIMCONT_GPENCIL)
-               filter= (ANIMFILTER_VISIBLE);
+               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
        else
-               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        for (ale= anim_data.first; ale; ale= ale->next) {
                AnimData *adt= ANIM_nla_mapping_get(ac, ale);
                
-               /* loop over cfraelems (stored in the BeztEditData->list)
+               /* loop over cfraelems (stored in the KeyframeEditData->list)
                 *      - we need to do this here, as we can apply fewer NLA-mapping conversions
                 */
-               for (ce= bed.list.first; ce; ce= ce->next) {
+               for (ce= ked.list.first; ce; ce= ce->next) {
                        /* set frame for validation callback to refer to */
                        if (adt)
-                               bed.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
+                               ked.f1= BKE_nla_tweakedit_remap(adt, ce->cfra, NLATIME_CONVERT_UNMAP);
                        else
-                               bed.f1= ce->cfra;
+                               ked.f1= ce->cfra;
                        
                        /* select elements with frame number matching cfraelem */
-                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
-                       
-#if 0 // XXX reenable when Grease Pencil stuff is back
-                       if (ale->type == ANIMTYPE_GPLAYER) {
-                               bGPDlayer *gpl= (bGPDlayer *)ale->data;
-                               bGPDframe *gpf;
-                               
-                               for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
-                                       if (ecfra == gpf->framenum) 
-                                               gpf->flag |= GP_FRAME_SELECT;
-                               }
-                       }
-                       //else... 
-#endif // XXX reenable when Grease Pencil stuff is back
+                       if (ale->type == ANIMTYPE_GPLAYER)
+                               select_gpencil_frame(ale->data, ce->cfra, SELECT_ADD);
+                       else
+                               ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
                }
        }
        
        /* free elements */
-       BLI_freelistN(&bed.list);
+       BLI_freelistN(&ked.list);
        BLI_freelistN(&anim_data);
 }
 
@@ -551,7 +514,7 @@ static int actkeys_columnselect_exec(bContext *C, wmOperator *op)
                columnselect_action_keys(&ac, mode);
        
        /* set notifier that keyframe selection have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_SELECTED, NULL);
        
        return OPERATOR_FINISHED;
 }
@@ -561,7 +524,7 @@ void ACTION_OT_select_column (wmOperatorType *ot)
        /* identifiers */
        ot->name= "Select All";
        ot->idname= "ACTION_OT_select_column";
-       ot->description= "Select all keyframes on the specified frame(s).";
+       ot->description= "Select all keyframes on the specified frame(s)";
        
        /* api callbacks */
        ot->exec= actkeys_columnselect_exec;
@@ -571,61 +534,196 @@ void ACTION_OT_select_column (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* props */
-       RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
+       ot->prop= RNA_def_enum(ot->srna, "mode", prop_column_select_types, 0, "Mode", "");
 }
 
-/* ******************** Mouse-Click Select Operator *********************** */
-/* This operator works in one of three ways:
- *     - 1) keyframe under mouse - no special modifiers
- *     - 2) all keyframes on the same side of current frame indicator as mouse - ALT modifier
- *     - 3) column select all keyframes in frame under mouse - CTRL modifier
- *
- * In addition to these basic options, the SHIFT modifier can be used to toggle the 
- * selection mode between replacing the selection (without) and inverting the selection (with).
- */
+/* ******************** Select Linked Operator *********************** */
+
+static int actkeys_select_linked_exec (bContext *C, wmOperator *UNUSED(op))
+{
+       bAnimContext ac;
+       
+       ListBase anim_data= {NULL, NULL};
+       bAnimListElem *ale;
+       int filter;
+       
+       KeyframeEditFunc ok_cb = ANIM_editkeyframes_ok(BEZT_OK_SELECTED);
+       KeyframeEditFunc sel_cb = ANIM_editkeyframes_select(SELECT_ADD);
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+       
+       /* loop through all of the keys and select additional keyframes based on these */
+       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+       
+       for (ale= anim_data.first; ale; ale= ale->next) {
+               FCurve *fcu= (FCurve *)ale->key_data;
+               
+               /* check if anything selected? */
+               if (ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, ok_cb, NULL)) {
+                       /* select every keyframe in this curve then */
+                       ANIM_fcurve_keyframes_loop(NULL, fcu, NULL, sel_cb, NULL);
+               }
+       }
+       
+       /* Cleanup */
+       BLI_freelistN(&anim_data);
+       
+       /* set notifier that keyframe selection has changed */
+       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_SELECTED, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ACTION_OT_select_linked (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Select Linked";
+       ot->idname= "ACTION_OT_select_linked";
+       ot->description = "Select keyframes occurring the same F-Curves as selected ones";
+       
+       /* api callbacks */
+       ot->exec= actkeys_select_linked_exec;
+       ot->poll= ED_operator_action_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+}
+
+/* ******************** Select More/Less Operators *********************** */
+
+/* Common code to perform selection */
+static void select_moreless_action_keys (bAnimContext *ac, short mode)
+{
+       ListBase anim_data= {NULL, NULL};
+       bAnimListElem *ale;
+       int filter;
+       
+       KeyframeEditData ked= {{NULL}};
+       KeyframeEditFunc build_cb;
+       
+       
+       /* init selmap building data */
+       build_cb= ANIM_editkeyframes_buildselmap(mode);
+       
+       /* loop through all of the keys and select additional keyframes based on these */
+       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+       
+       for (ale= anim_data.first; ale; ale= ale->next) {
+               FCurve *fcu= (FCurve *)ale->key_data;
+               
+               /* only continue if F-Curve has keyframes */
+               if (fcu->bezt == NULL)
+                       continue;
+               
+               /* build up map of whether F-Curve's keyframes should be selected or not */
+               ked.data= MEM_callocN(fcu->totvert, "selmap actEdit more");
+               ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, build_cb, NULL);
+               
+               /* based on this map, adjust the selection status of the keyframes */
+               ANIM_fcurve_keyframes_loop(&ked, fcu, NULL, bezt_selmap_flush, NULL);
+               
+               /* free the selmap used here */
+               MEM_freeN(ked.data);
+               ked.data= NULL;
+       }
+       
+       /* Cleanup */
+       BLI_freelistN(&anim_data);
+}
+
+/* ----------------- */
+
+static int actkeys_select_more_exec (bContext *C, wmOperator *UNUSED(op))
+{
+       bAnimContext ac;
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+       
+       /* perform select changes */
+       select_moreless_action_keys(&ac, SELMAP_MORE);
+       
+       /* set notifier that keyframe selection has changed */
+       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_SELECTED, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ACTION_OT_select_more (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Select More";
+       ot->idname= "ACTION_OT_select_more";
+       ot->description = "Select keyframes beside already selected ones";
+       
+       /* api callbacks */
+       ot->exec= actkeys_select_more_exec;
+       ot->poll= ED_operator_action_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+}
+
+/* ----------------- */
+
+static int actkeys_select_less_exec (bContext *C, wmOperator *UNUSED(op))
+{
+       bAnimContext ac;
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+       
+       /* perform select changes */
+       select_moreless_action_keys(&ac, SELMAP_LESS);
+       
+       /* set notifier that keyframe selection has changed */
+       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_SELECTED, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ACTION_OT_select_less (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Select Less";
+       ot->idname= "ACTION_OT_select_less";
+       ot->description = "Deselect keyframes on ends of selection islands";
+       
+       /* api callbacks */
+       ot->exec= actkeys_select_less_exec;
+       ot->poll= ED_operator_action_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/;
+}
+
+/* ******************** Select Left/Right Operator ************************* */
+/* Select keyframes left/right of the current frame indicator */
 
 /* defines for left-right select tool */
 static EnumPropertyItem prop_actkeys_leftright_select_types[] = {
        {ACTKEYS_LRSEL_TEST, "CHECK", 0, "Check if Select Left or Right", ""},
-       {ACTKEYS_LRSEL_NONE, "OFF", 0, "Don't select", ""},
        {ACTKEYS_LRSEL_LEFT, "LEFT", 0, "Before current frame", ""},
        {ACTKEYS_LRSEL_RIGHT, "RIGHT", 0, "After current frame", ""},
        {0, NULL, 0, NULL, NULL}
 };
 
-/* sensitivity factor for frame-selections */
-#define FRAME_CLICK_THRESH             0.1f
+/* --------------------------------- */
 
-/* ------------------- */
-/* option 1) select keyframe directly under mouse */
-static void actkeys_mselect_single (bAnimContext *ac, bAnimListElem *ale, short select_mode, float selx)
-{
-       bDopeSheet *ads= (ac->datatype == ANIMCONT_DOPESHEET) ? ac->data : NULL;
-       int ds_filter = ((ads) ? (ads->filterflag) : (0));
-       
-       BeztEditData bed;
-       BeztEditFunc select_cb, ok_cb;
-       
-       /* get functions for selecting keyframes */
-       select_cb= ANIM_editkeyframes_select(select_mode);
-       ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
-       memset(&bed, 0, sizeof(BeztEditData)); 
-       bed.f1= selx;
-       
-       /* select the nominated keyframe on the given frame */
-       ANIM_animchannel_keys_bezier_loop(&bed, ale, ok_cb, select_cb, NULL, ds_filter);
-}
-
-/* Option 2) Selects all the keyframes on either side of the current frame (depends on which side the mouse is on) */
-static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short select_mode)
+static void actkeys_select_leftright (bAnimContext *ac, short leftright, short select_mode)
 {
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
        
-       BeztEditFunc ok_cb, select_cb;
-       BeztEditData bed;
+       KeyframeEditFunc ok_cb, select_cb;
+       KeyframeEditData ked= {{NULL}};
        Scene *scene= ac->scene;
        
        /* if select mode is replace, deselect all keyframes (and channels) first */
@@ -633,7 +731,7 @@ static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short
                select_mode= SELECT_ADD;
                
                /* deselect all other channels and keyframes */
-               ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+               ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
                deselect_action_keys(ac, 0, SELECT_SUBTRACT);
        }
        
@@ -641,42 +739,177 @@ static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short
        ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE);
        select_cb= ANIM_editkeyframes_select(select_mode);
        
-       memset(&bed, 0, sizeof(BeztEditFunc));
        if (leftright == ACTKEYS_LRSEL_LEFT) {
-               bed.f1 = MINAFRAMEF;
-               bed.f2 = (float)(CFRA + FRAME_CLICK_THRESH);
+               ked.f1 = MINAFRAMEF;
+               ked.f2 = (float)(CFRA + 0.1f);
        } 
        else {
-               bed.f1 = (float)(CFRA - FRAME_CLICK_THRESH);
-               bed.f2 = MAXFRAMEF;
+               ked.f1 = (float)(CFRA - 0.1f);
+               ked.f2 = MAXFRAMEF;
        }
        
        /* filter data */
        if (ac->datatype == ANIMCONT_GPENCIL)
-               filter= (ANIMFILTER_VISIBLE);
+               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
        else
-               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
                
-       /* select keys on the side where most data occurs */
+       /* select keys */
        for (ale= anim_data.first; ale; ale= ale->next) {
                AnimData *adt= ANIM_nla_mapping_get(ac, ale);
                
                if (adt) {
                        ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1);
-                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+                       ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
                        ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
                }
-               //else if (ale->type == ANIMTYPE_GPLAYER)
-               //      borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD);
+               else if (ale->type == ANIMTYPE_GPLAYER) 
+                       borderselect_gplayer_frames(ale->data, ked.f1, ked.f2, select_mode);
                else
-                       ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
+                       ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
        }
        
+       /* Sync marker support */
+       if (select_mode==SELECT_ADD) {
+               SpaceAction *saction= (SpaceAction *)ac->sl;
+               
+               if ((saction) && (saction->flag & SACTION_MARKERS_MOVE)) {
+                       ListBase *markers = ED_animcontext_get_markers(ac);
+                       TimeMarker *marker;
+                       
+                       for (marker= markers->first; marker; marker= marker->next) {
+                               if(     ((leftright == ACTKEYS_LRSEL_LEFT) && (marker->frame < CFRA)) ||
+                                       ((leftright == ACTKEYS_LRSEL_RIGHT) && (marker->frame >= CFRA)) ) 
+                               {
+                                       marker->flag |= SELECT;
+                               }
+                               else {
+                                       marker->flag &= ~SELECT;
+                               }
+                       }
+               }
+       }
+
        /* Cleanup */
        BLI_freelistN(&anim_data);
 }
 
+/* ----------------- */
+
+static int actkeys_select_leftright_exec (bContext *C, wmOperator *op)
+{
+       bAnimContext ac;
+       short leftright = RNA_enum_get(op->ptr, "mode");
+       short selectmode;
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+       
+       /* select mode is either replace (deselect all, then add) or add/extend */
+       if (RNA_boolean_get(op->ptr, "extend"))
+               selectmode= SELECT_INVERT;
+       else
+               selectmode= SELECT_REPLACE;
+               
+       /* if "test" mode is set, we don't have any info to set this with */
+       if (leftright == ACTKEYS_LRSEL_TEST)
+               return OPERATOR_CANCELLED;
+       
+       /* do the selecting now */
+       actkeys_select_leftright(&ac, leftright, selectmode);
+       
+       /* set notifier that keyframe selection (and channels too) have changed */
+       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|ND_ANIMCHAN|NA_SELECTED, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+static int actkeys_select_leftright_invoke (bContext *C, wmOperator *op, wmEvent *event)
+{
+       bAnimContext ac;
+       short leftright = RNA_enum_get(op->ptr, "mode");
+       
+       /* get editor data */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return OPERATOR_CANCELLED;
+               
+       /* handle mode-based testing */
+       if (leftright == ACTKEYS_LRSEL_TEST) {
+               Scene *scene= ac.scene;
+               ARegion *ar= ac.ar;
+               View2D *v2d= &ar->v2d;
+               float x;
+
+               /* determine which side of the current frame mouse is on */
+               UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, NULL);
+               if (x < CFRA)
+                       RNA_enum_set(op->ptr, "mode", ACTKEYS_LRSEL_LEFT);
+               else    
+                       RNA_enum_set(op->ptr, "mode", ACTKEYS_LRSEL_RIGHT);
+       }
+       
+       /* perform selection */
+       return actkeys_select_leftright_exec(C, op);
+}
+
+void ACTION_OT_select_leftright (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Select Left/Right";
+       ot->idname= "ACTION_OT_select_leftright";
+       ot->description= "Select keyframes to the left or the right of the current frame";
+       
+       /* api callbacks  */
+       ot->invoke= actkeys_select_leftright_invoke;
+       ot->exec= actkeys_select_leftright_exec;
+       ot->poll= ED_operator_action_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+       
+       /* id-props */
+       ot->prop= RNA_def_enum(ot->srna, "mode", prop_actkeys_leftright_select_types, ACTKEYS_LRSEL_TEST, "Mode", "");
+       RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "");
+}
+
+/* ******************** Mouse-Click Select Operator *********************** */
+/* This operator works in one of three ways:
+ *     - 1) keyframe under mouse - no special modifiers
+ *     - 2) all keyframes on the same side of current frame indicator as mouse - ALT modifier
+ *     - 3) column select all keyframes in frame under mouse - CTRL modifier
+ *
+ * In addition to these basic options, the SHIFT modifier can be used to toggle the 
+ * selection mode between replacing the selection (without) and inverting the selection (with).
+ */
+
+/* sensitivity factor for frame-selections */
+#define FRAME_CLICK_THRESH             0.1f
+
+/* ------------------- */
+/* option 1) select keyframe directly under mouse */
+static void actkeys_mselect_single (bAnimContext *ac, bAnimListElem *ale, short select_mode, float selx)
+{
+       KeyframeEditData ked= {{NULL}};
+       KeyframeEditFunc select_cb, ok_cb;
+       
+       /* get functions for selecting keyframes */
+       select_cb= ANIM_editkeyframes_select(select_mode);
+       ok_cb= ANIM_editkeyframes_ok(BEZT_OK_FRAME);
+       ked.f1= selx;
+       
+       /* select the nominated keyframe on the given frame */
+       if (ale->type == ANIMTYPE_GPLAYER)
+               select_gpencil_frame(ale->data, selx, select_mode);
+       else
+               ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
+}
+
+/* Option 2) Selects all the keyframes on either side of the current frame (depends on which side the mouse is on) */
+/* (see actkeys_select_leftright) */
+
 /* Option 3) Selects all visible keyframes in the same frame as the mouse click */
 static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float selx)
 {
@@ -684,11 +917,10 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
        bAnimListElem *ale;
        int filter;
        
-       BeztEditFunc select_cb, ok_cb;
-       BeztEditData bed;
+       KeyframeEditFunc select_cb, ok_cb;
+       KeyframeEditData ked= {{NULL}};
        
        /* initialise keyframe editing data */
-       memset(&bed, 0, sizeof(BeztEditData));
        
        /* set up BezTriple edit callbacks */
        select_cb= ANIM_editkeyframes_select(select_mode);
@@ -698,9 +930,9 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
         * based on the keys found to be selected above
         */
        if (ac->datatype == ANIMCONT_GPENCIL)
-               filter= (ANIMFILTER_VISIBLE);
+               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
        else
-               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+               filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        for (ale= anim_data.first; ale; ale= ale->next) {
@@ -708,35 +940,25 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
                
                /* set frame for validation callback to refer to */
                if (adt)
-                       bed.f1= BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
+                       ked.f1= BKE_nla_tweakedit_remap(adt, selx, NLATIME_CONVERT_UNMAP);
                else
-                       bed.f1= selx;
+                       ked.f1= selx;
                
                /* select elements with frame number matching cfra */
-               ANIM_fcurve_keys_bezier_loop(&bed, ale->key_data, ok_cb, select_cb, NULL);
-                       
-#if 0 // XXX reenable when Grease Pencil stuff is back
-                       if (ale->type == ANIMTYPE_GPLAYER) {
-                               bGPDlayer *gpl= (bGPDlayer *)ale->data;
-                               bGPDframe *gpf;
-                               
-                               for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
-                                       if (ecfra == gpf->framenum) 
-                                               gpf->flag |= GP_FRAME_SELECT;
-                               }
-                       }
-                       //else... 
-#endif // XXX reenable when Grease Pencil stuff is back
+               if (ale->type == ANIMTYPE_GPLAYER)
+                       select_gpencil_frame(ale->key_data, selx, select_mode);
+               else 
+                       ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
        }
        
        /* free elements */
-       BLI_freelistN(&bed.list);
+       BLI_freelistN(&ked.list);
        BLI_freelistN(&anim_data);
 }
  
 /* ------------------- */
 
-static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, short column)
+static void mouse_action_keys (bAnimContext *ac, const int mval[2], short select_mode, short column)
 {
        ListBase anim_data = {NULL, NULL};
        DLRBT_Tree anim_keys;
@@ -764,7 +986,7 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
        UI_view2d_region_to_view(v2d, mval[0]+7, mval[1], &rectf.xmax, &rectf.ymax);
        
        /* filter data */
-       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
+       filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
        ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
        /* try to get channel */
@@ -781,7 +1003,6 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
                ActKeyColumn *ak, *akn=NULL;
                
                /* make list of keyframes */
-               // TODO: it would be great if we didn't have to apply this to all the keyframes to do this...
                BLI_dlrbTree_init(&anim_keys);
                
                if (ale->key_data) {
@@ -816,29 +1037,22 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
                        /* dopesheet summary covers everything */
                        summary_to_keylist(ac, &anim_keys, NULL);
                }
-               else if (ale->type == ANIMTYPE_GROUP) {
+               else if (ale->type == ANIMTYPE_GROUP) { 
+                       // TODO: why don't we just give groups key_data too?
                        bActionGroup *agrp= (bActionGroup *)ale->data;
                        agroup_to_keylist(adt, agrp, &anim_keys, NULL);
                }
-               else if (ale->type == ANIMTYPE_GPDATABLOCK) {
-                       /* cleanup */
-                       // FIXME:...
-                       BLI_freelistN(&anim_data);
-                       return;
-               }
                else if (ale->type == ANIMTYPE_GPLAYER) {
-                       bGPDlayer *gpl= (bGPDlayer *)ale->data;
-                       gpl_to_keylist(ads, gpl, &anim_keys, NULL);
+                       // TODO: why don't we just give gplayers key_data too?
+                       bGPDlayer *gpl = (bGPDlayer *)ale->data;
+                       gpl_to_keylist(ads, gpl, &anim_keys);
                }
                
-               // the call below is not strictly necessary, since we have adjacency info anyway
-               //BLI_dlrbTree_linkedlist_sync(&anim_keys);
-               
-               /* loop through keyframes, finding one that was within the range clicked on */
+               /* start from keyframe at root of BST, traversing until we find one within the range that was clicked on */
                for (ak= anim_keys.root; ak; ak= akn) {
                        if (IN_RANGE(ak->cfra, rectf.xmin, rectf.xmax)) {
                                /* set the frame to use, and apply inverse-correction for NLA-mapping 
-                                * so that the frame will get selected by the selection functiosn without
+                                * so that the frame will get selected by the selection functions without
                                 * requiring to map each frame once again...
                                 */
                                selx= BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP);
@@ -872,7 +1086,7 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
                /* highlight channel clicked on */
                if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
                        /* deselect all other channels first */
-                       ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                       ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
                        
                        /* Highlight Action-Group or F-Curve? */
                        if (ale && ale->data) {
@@ -891,11 +1105,16 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
                        }
                }
                else if (ac->datatype == ANIMCONT_GPENCIL) {
-                       ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                       /* deselect all other channels first */
+                       ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
                        
-                       /* Highlight gpencil layer */
-                       //gpl->flag |= GP_LAYER_SELECT;
-                       //gpencil_layer_setactive(gpd, gpl);
+                       /* Highlight GPencil Layer */
+                       if ((ale && ale->data) && (ale->type == ANIMTYPE_GPLAYER)) {
+                               bGPDlayer *gpl = ale->data;
+                               
+                               gpl->flag |= GP_LAYER_SELECT;
+                               //gpencil_layer_setactive(gpd, gpl);
+                       }
                }
        }
        
@@ -903,11 +1122,7 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
        if (ale) {
                if (found) {
                        /* apply selection to keyframes */
-                       if (/*gpl*/0) {
-                               /* grease pencil */
-                               //select_gpencil_frame(gpl, (int)selx, selectmode);
-                       }
-                       else if (column) {
+                       if (column) {
                                /* select all keyframes in the same frame as the one we hit on the active channel */
                                actkeys_mselect_column(ac, select_mode, selx);
                        }
@@ -926,25 +1141,16 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode,
 static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        bAnimContext ac;
-       Scene *scene;
        ARegion *ar;
-       View2D *v2d;
        short selectmode, column;
-       int mval[2];
        
        /* get editor data */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return OPERATOR_CANCELLED;
                
        /* get useful pointers from animation context data */
-       scene= ac.scene;
        ar= ac.ar;
-       v2d= &ar->v2d;
-       
-       /* get mouse coordinates (in region coordinates) */
-       mval[0]= (event->x - ar->winrct.xmin);
-       mval[1]= (event->y - ar->winrct.ymin);
-       
+
        /* select mode is either replace (deselect all, then add) or add/extend */
        if (RNA_boolean_get(op->ptr, "extend"))
                selectmode= SELECT_INVERT;
@@ -954,26 +1160,11 @@ static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *even
        /* column selection */
        column= RNA_boolean_get(op->ptr, "column");
        
-       /* figure out action to take */
-       if (RNA_enum_get(op->ptr, "left_right")) {
-               /* select all keys on same side of current frame as mouse */
-               float x;
-               
-               UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, NULL);
-               if (x < CFRA)
-                       RNA_int_set(op->ptr, "left_right", ACTKEYS_LRSEL_LEFT);
-               else    
-                       RNA_int_set(op->ptr, "left_right", ACTKEYS_LRSEL_RIGHT);
-               
-               actkeys_mselect_leftright(&ac, RNA_enum_get(op->ptr, "left_right"), selectmode);
-       }
-       else {
-               /* select keyframe(s) based upon mouse position*/
-               mouse_action_keys(&ac, mval, selectmode, column);
-       }
+       /* select keyframe(s) based upon mouse position*/
+       mouse_action_keys(&ac, event->mval, selectmode, column);
        
        /* set notifier that keyframe selection (and channels too) have changed */
-       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_SELECT|ND_ANIMCHAN_SELECT, NULL);
+       WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|ND_ANIMCHAN|NA_SELECTED, NULL);
        
        /* for tweak grab to work */
        return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
@@ -984,7 +1175,7 @@ void ACTION_OT_clickselect (wmOperatorType *ot)
        /* identifiers */
        ot->name= "Mouse Select Keys";
        ot->idname= "ACTION_OT_clickselect";
-       ot->description= "Select keyframes by clicking on them.";
+       ot->description= "Select keyframes by clicking on them";
        
        /* api callbacks - absolutely no exec() this yet... */
        ot->invoke= actkeys_clickselect_invoke;
@@ -994,8 +1185,6 @@ void ACTION_OT_clickselect (wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
        /* id-props */
-       // XXX should we make this into separate operators?
-       RNA_def_enum(ot->srna, "left_right", prop_actkeys_leftright_select_types, 0, "Left Right", ""); // CTRLKEY
        RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY
        RNA_def_boolean(ot->srna, "column", 0, "Column Select", ""); // ALTKEY
 }