rename api functions...
[blender.git] / source / blender / editors / interface / interface_handlers.c
index fce7af795e1c1b7e8026bfed94cbaa448728d9c3..dc7ea930e4505688c41073f8595c0f620d35b8c5 100644 (file)
@@ -54,6 +54,7 @@
 
 #include "PIL_time.h"
 
+#include "BKE_blender.h"
 #include "BKE_colortools.h"
 #include "BKE_context.h"
 #include "BKE_idprop.h"
@@ -77,6 +78,9 @@
 #include "WM_api.h"
 #include "WM_types.h"
 
+/* place the mouse at the scaled down location when un-grabbing */
+#define USE_CONT_MOUSE_CORRECT
+
 /* proto */
 static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to);
 static void ui_add_link(bContext *C, uiBut *from, uiBut *to);
@@ -120,8 +124,10 @@ typedef struct uiHandleButtonData {
 
        /* overall state */
        uiHandleButtonState state;
-       int cancel, escapecancel, retval;
-       int applied, appliedinteractive;
+       int retval;
+       /* booleans (could be made into flags) */
+       char cancel, escapecancel;
+       char applied, appliedinteractive;
        wmTimer *flashtimer;
 
        /* edited value */
@@ -149,6 +155,12 @@ typedef struct uiHandleButtonData {
        float dragf, dragfstart;
        CBData *dragcbd;
 
+#ifdef USE_CONT_MOUSE_CORRECT
+       /* when ungrabbing buttons which are #ui_is_a_warp_but(), we may want to position them
+        * FLT_MAX signifies do-nothing, use #ui_block_to_window_fl() to get this into a usable space  */
+       float ungrab_mval[2];
+#endif
+
        /* menu open (watch uiFreeActiveButtons) */
        uiPopupBlockHandle *menu;
        int menuretval;
@@ -193,7 +205,7 @@ typedef struct uiAfterFunc {
 
        bContextStore *context;
 
-       char undostr[512];
+       char undostr[BKE_UNDO_STR_MAX];
 
        int autokey;
 } uiAfterFunc;
@@ -256,13 +268,42 @@ static uiBut *ui_but_last(uiBlock *block)
 
 static int ui_is_a_warp_but(uiBut *but)
 {
-       if (U.uiflag & USER_CONTINUOUS_MOUSE)
-               if (ELEM4(but->type, NUM, NUMABS, HSVCIRCLE, TRACKPREVIEW))
+       if (U.uiflag & USER_CONTINUOUS_MOUSE) {
+               if (ELEM6(but->type, NUM, NUMABS, HSVCIRCLE, TRACKPREVIEW, HSVCUBE, BUT_CURVE)) {
                        return TRUE;
+               }
+       }
 
        return FALSE;
 }
 
+static float ui_mouse_scale_warp_factor(const short shift)
+{
+       if (U.uiflag & USER_CONTINUOUS_MOUSE) {
+               return shift ? 0.05f : 1.0f;
+       }
+       else {
+               return 1.0f;
+       }
+}
+
+static void ui_mouse_scale_warp(uiHandleButtonData *data,
+                                const float mx, const float my,
+                                float *r_mx, float *r_my,
+                                const short shift)
+{
+       if (U.uiflag & USER_CONTINUOUS_MOUSE) {
+               const float fac = ui_mouse_scale_warp_factor(shift);
+               /* slow down the mouse, this is fairly picky */
+               *r_mx = (data->dragstartx * (1.0f - fac) + mx * fac);
+               *r_my = (data->dragstarty * (1.0f - fac) + my * fac);
+       }
+       else {
+               *r_mx = mx;
+               *r_my = my;
+       }
+}
+
 /* file selectors are exempt from utf-8 checks */
 int ui_is_but_utf8(uiBut *but)
 {
@@ -432,7 +473,7 @@ static void ui_apply_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data)
        ui_apply_but_func(C, but);
 
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_BUTM(bContext *C, uiBut *but, uiHandleButtonData *data)
@@ -441,7 +482,7 @@ static void ui_apply_but_BUTM(bContext *C, uiBut *but, uiHandleButtonData *data)
        ui_apply_but_func(C, but);
 
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data)
@@ -452,7 +493,7 @@ static void ui_apply_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data
        ui_check_but(but);
        ui_apply_but_func(C, but);
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data)
@@ -462,19 +503,21 @@ static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data)
        
        /* local hack... */
        if (but->type == BUT_TOGDUAL && data->togdual) {
-               if (but->pointype == SHO)
+               if (but->pointype == UI_BUT_POIN_SHORT) {
                        but->poin += 2;
-               else if (but->pointype == INT)
+               }
+               else if (but->pointype == UI_BUT_POIN_INT) {
                        but->poin += 4;
+               }
        }
        
        value = ui_get_but_val(but);
        lvalue = (int)value;
        
        if (but->bit) {
-               w = BTST(lvalue, but->bitnr);
-               if (w) lvalue = BCLR(lvalue, but->bitnr);
-               else lvalue = BSET(lvalue, but->bitnr);
+               w = UI_BITBUT_TEST(lvalue, but->bitnr);
+               if (w) lvalue = UI_BITBUT_CLR(lvalue, but->bitnr);
+               else   lvalue = UI_BITBUT_SET(lvalue, but->bitnr);
                
                if (but->type == TOGR) {
                        if (!data->togonly) {
@@ -502,16 +545,18 @@ static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data)
        
        /* end local hack... */
        if (but->type == BUT_TOGDUAL && data->togdual) {
-               if (but->pointype == SHO)
+               if (but->pointype == UI_BUT_POIN_SHORT) {
                        but->poin -= 2;
-               else if (but->pointype == INT)
+               }
+               else if (but->pointype == UI_BUT_POIN_INT) {
                        but->poin -= 4;
+               }
        }
        
        ui_apply_but_func(C, but);
 
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data)
@@ -528,7 +573,7 @@ static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
        ui_apply_but_func(C, but);
 
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
@@ -547,7 +592,7 @@ static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
        ui_apply_but_func(C, but);
 
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
@@ -557,7 +602,7 @@ static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
                        data->value = ui_get_but_val(but);
                }
                else {
-                       data->cancel = 1;
+                       data->cancel = TRUE;
                        return;
                }
        }
@@ -568,42 +613,42 @@ static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
        ui_apply_but_func(C, but);
 
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_TOG3(bContext *C, uiBut *but, uiHandleButtonData *data)
 { 
-       if (but->pointype == SHO) {
+       if (but->pointype == UI_BUT_POIN_SHORT) {
                short *sp = (short *)but->poin;
                
-               if (BTST(sp[1], but->bitnr)) {
-                       sp[1] = BCLR(sp[1], but->bitnr);
-                       sp[0] = BCLR(sp[0], but->bitnr);
+               if (UI_BITBUT_TEST(sp[1], but->bitnr)) {
+                       sp[1] = UI_BITBUT_CLR(sp[1], but->bitnr);
+                       sp[0] = UI_BITBUT_CLR(sp[0], but->bitnr);
                }
-               else if (BTST(sp[0], but->bitnr)) {
-                       sp[1] = BSET(sp[1], but->bitnr);
+               else if (UI_BITBUT_TEST(sp[0], but->bitnr)) {
+                       sp[1] = UI_BITBUT_SET(sp[1], but->bitnr);
                }
                else {
-                       sp[0] = BSET(sp[0], but->bitnr);
+                       sp[0] = UI_BITBUT_SET(sp[0], but->bitnr);
                }
        }
        else {
-               if (BTST(*(but->poin + 2), but->bitnr)) {
-                       *(but->poin + 2) = BCLR(*(but->poin + 2), but->bitnr);
-                       *(but->poin) = BCLR(*(but->poin), but->bitnr);
+               if (UI_BITBUT_TEST(*(but->poin + 2), but->bitnr)) {
+                       *(but->poin + 2) = UI_BITBUT_CLR(*(but->poin + 2), but->bitnr);
+                       *(but->poin)     = UI_BITBUT_CLR(*(but->poin),     but->bitnr);
                }
-               else if (BTST(*(but->poin), but->bitnr)) {
-                       *(but->poin + 2) = BSET(*(but->poin + 2), but->bitnr);
+               else if (UI_BITBUT_TEST(*(but->poin), but->bitnr)) {
+                       *(but->poin + 2) = UI_BITBUT_SET(*(but->poin + 2), but->bitnr);
                }
                else {
-                       *(but->poin) = BSET(*(but->poin), but->bitnr);
+                       *(but->poin) = UI_BITBUT_SET(*(but->poin), but->bitnr);
                }
        }
        
        ui_check_but(but);
        ui_apply_but_func(C, but);
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_VEC(bContext *C, uiBut *but, uiHandleButtonData *data)
@@ -613,21 +658,21 @@ static void ui_apply_but_VEC(bContext *C, uiBut *but, uiHandleButtonData *data)
        ui_apply_but_func(C, but);
 
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_COLORBAND(bContext *C, uiBut *but, uiHandleButtonData *data)
 {
        ui_apply_but_func(C, but);
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_CURVE(bContext *C, uiBut *but, uiHandleButtonData *data)
 {
        ui_apply_but_func(C, but);
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_IDPOIN(bContext *C, uiBut *but, uiHandleButtonData *data)
@@ -636,7 +681,7 @@ static void ui_apply_but_IDPOIN(bContext *C, uiBut *but, uiHandleButtonData *dat
        ui_check_but(but);
        ui_apply_but_func(C, but);
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 #ifdef WITH_INTERNATIONAL
@@ -644,7 +689,7 @@ static void ui_apply_but_CHARTAB(bContext *C, uiBut *but, uiHandleButtonData *da
 {
        ui_apply_but_func(C, but);
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 #endif
 
@@ -657,20 +702,21 @@ static int ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, wmEvent *event)
        
        ui_window_to_block(ar, but->block, &x, &y);
        
-       rect.xmin = but->x1; rect.xmax = but->x2;
-       rect.ymin = but->y1; rect.ymax = but->y2;
+       BLI_rcti_rctf_copy(&rect, &but->rect);
        
-       if (but->imb) ;  /* use button size itself */
+       if (but->imb) {
+               /* use button size itself */
+       }
        else if (but->flag & UI_ICON_LEFT) {
-               rect.xmax = rect.xmin + (rect.ymax - rect.ymin);
+               rect.xmax = rect.xmin + (BLI_rcti_size_y(&rect));
        }
        else {
-               int delta = (rect.xmax - rect.xmin) - (rect.ymax - rect.ymin);
+               int delta = BLI_rcti_size_x(&rect) - BLI_rcti_size_y(&rect);
                rect.xmin += delta / 2;
                rect.xmax -= delta / 2;
        }
        
-       return BLI_in_rcti(&rect, x, y);
+       return BLI_rcti_isect_pt(&rect, x, y);
 }
 
 static int ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
@@ -682,11 +728,11 @@ static int ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data,
                wmDrag *drag;
                
                button_activate_state(C, but, BUTTON_STATE_EXIT);
-               data->cancel = 1;
+               data->cancel = TRUE;
                
                drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but));
                if (but->imb)
-                       WM_event_drag_image(drag, but->imb, but->imb_scale, but->x2 - but->x1, but->y2 - but->y1);
+                       WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect));
                return 1;
        }
        
@@ -701,13 +747,10 @@ static void ui_delete_active_linkline(uiBlock *block)
        uiLink *link;
        uiLinkLine *line, *nline;
        int a, b;
-       
-       but = block->buttons.first;
-       while (but) {
+
+       for (but = block->buttons.first; but; but = but->next) {
                if (but->type == LINK && but->link) {
-                       line = but->link->lines.first;
-                       while (line) {
-                               
+                       for (line = but->link->lines.first; line; line = nline) {
                                nline = line->next;
                                
                                if (line->flag & UI_SELECT) {
@@ -727,11 +770,11 @@ static void ui_delete_active_linkline(uiBlock *block)
                                                        b = 0;
                                                        for (a = 0; a < (*(link->totlink)); a++) {
                                                                
-                                                               if ( (*(link->ppoin))[a] != line->to->poin) {
+                                                               if ((*(link->ppoin))[a] != line->to->poin) {
                                                                        (*(link->ppoin))[b] = (*(link->ppoin))[a];
                                                                        b++;
                                                                }
-                                                       }       
+                                                       }
                                                        (*(link->totlink))--;
                                                }
                                        }
@@ -741,10 +784,8 @@ static void ui_delete_active_linkline(uiBlock *block)
                                        
                                        MEM_freeN(line);
                                }
-                               line = nline;
                        }
                }
-               but = but->next;
        }
 }
 
@@ -756,10 +797,10 @@ static uiLinkLine *ui_is_a_link(uiBut *from, uiBut *to)
        
        link = from->link;
        if (link) {
-               line = link->lines.first;
-               while (line) {
-                       if (line->from == from && line->to == to) return line;
-                       line = line->next;
+               for (line = link->lines.first; line; line = line->next) {
+                       if (line->from == from && line->to == to) {
+                               return line;
+                       }
                }
        }
        return NULL;
@@ -778,6 +819,8 @@ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to)
 
        uiLink *link = from->link;
 
+       PointerRNA props_ptr, object_ptr;
+       
        if (link->ppoin)
                sens_from_links = (bController ***)(link->ppoin);
        else return;
@@ -804,12 +847,19 @@ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to)
                        break;
        }
 
-       // only works if the sensor and the actuator are from the same object
+       /* only works if the sensor and the actuator are from the same object */
        if (!act_iter) return;
+       
+       /* in case the linked controller is not the active one */
+       RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
+       
+       WM_operator_properties_create(&props_ptr, "LOGIC_OT_controller_add");
+       RNA_string_set(&props_ptr, "object", ob->id.name + 2);
 
        /* (3) add a new controller */
-       if (WM_operator_name_call(C, "LOGIC_OT_controller_add", WM_OP_EXEC_DEFAULT, NULL) & OPERATOR_FINISHED) {
+       if (WM_operator_name_call(C, "LOGIC_OT_controller_add", WM_OP_EXEC_DEFAULT, &props_ptr) & OPERATOR_FINISHED) {
                cont = (bController *)ob->controllers.last;
+               cont->type = CONT_LOGIC_AND; /* Quick fix to make sure we always have an AND controller. It might be nicer to make sure the operator gives us the right one though... */
 
                /* (4) link the sensor->controller->actuator */
                tmp_but = MEM_callocN(sizeof(uiBut), "uiBut");
@@ -827,6 +877,7 @@ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to)
                MEM_freeN(tmp_but->link);
                MEM_freeN(tmp_but);
        }
+       WM_operator_properties_free(&props_ptr);
 }
 
 static void ui_add_link(bContext *C, uiBut *from, uiBut *to)
@@ -837,7 +888,7 @@ static void ui_add_link(bContext *C, uiBut *from, uiBut *to)
        void **oldppoin;
        int a;
        
-       if ( (line = ui_is_a_link(from, to)) ) {
+       if ((line = ui_is_a_link(from, to))) {
                line->flag |= UI_SELECT;
                ui_delete_active_linkline(from->block);
                return;
@@ -900,35 +951,35 @@ static void ui_apply_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data)
                ui_apply_but_func(C, but);
                data->retval = but->retval;
        }
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_IMAGE(bContext *C, uiBut *but, uiHandleButtonData *data)
 {
        ui_apply_but_func(C, but);
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_HISTOGRAM(bContext *C, uiBut *but, uiHandleButtonData *data)
 {
        ui_apply_but_func(C, but);
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_WAVEFORM(bContext *C, uiBut *but, uiHandleButtonData *data)
 {
        ui_apply_but_func(C, but);
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 static void ui_apply_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonData *data)
 {
        ui_apply_but_func(C, but);
        data->retval = but->retval;
-       data->applied = 1;
+       data->applied = TRUE;
 }
 
 
@@ -959,10 +1010,12 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
        else {
                /* we avoid applying interactive edits a second time
                 * at the end with the appliedinteractive flag */
-               if (interactive)
-                       data->appliedinteractive = 1;
-               else if (data->appliedinteractive)
+               if (interactive) {
+                       data->appliedinteractive = TRUE;
+               }
+               else if (data->appliedinteractive) {
                        return;
+               }
        }
 
        /* ensures we are writing actual values */
@@ -1010,7 +1063,7 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
                        break;
                case HSVSLI:
                        break;
-               case TOG3:      
+               case TOG3:
                        ui_apply_but_TOG3(C, but, data);
                        break;
                case MENU:
@@ -1020,7 +1073,7 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
                case PULLDOWN:
                        ui_apply_but_BLOCK(C, but, data);
                        break;
-               case COL:
+               case COLOR:
                        if (data->cancel)
                                ui_apply_but_VEC(C, but, data);
                        else
@@ -1056,10 +1109,10 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
                case INLINK:
                        ui_apply_but_LINK(C, but, data);
                        break;
-               case BUT_IMAGE: 
+               case BUT_IMAGE:
                        ui_apply_but_IMAGE(C, but, data);
                        break;
-               case HISTOGRAM: 
+               case HISTOGRAM:
                        ui_apply_but_HISTOGRAM(C, but, data);
                        break;
                case WAVEFORM:
@@ -1111,8 +1164,9 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
        static ColorBand but_copypaste_coba = {0};
        char buf[UI_MAX_DRAW_STR + 1] = {0};
 
-       if (mode == 'v' && but->lock)
+       if (mode == 'v' && but->lock  == TRUE) {
                return;
+       }
 
        if (mode == 'v') {
                /* extract first line from clipboard in case of multi-line copies */
@@ -1132,7 +1186,9 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
        /* numeric value */
        if (ELEM4(but->type, NUM, NUMABS, NUMSLI, HSVSLI)) {
                
-               if (but->poin == NULL && but->rnapoin.data == NULL) ;
+               if (but->poin == NULL && but->rnapoin.data == NULL) {
+                       /* pass */
+               }
                else if (mode == 'c') {
                        ui_get_but_string(but, buf, sizeof(buf));
                        WM_clipboard_text_set(buf, 0);
@@ -1150,19 +1206,29 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
        }
 
        /* RGB triple */
-       else if (but->type == COL) {
+       else if (but->type == COLOR) {
                float rgb[3];
                
-               if (but->poin == NULL && but->rnapoin.data == NULL) ;
+               if (but->poin == NULL && but->rnapoin.data == NULL) {
+                       /* pass */
+               }
                else if (mode == 'c') {
 
                        ui_get_but_vectorf(but, rgb);
+                       /* convert to linear color to do compatible copy between gamma and non-gamma */
+                       if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
+                               srgb_to_linearrgb_v3_v3(rgb, rgb);
+
                        BLI_snprintf(buf, sizeof(buf), "[%f, %f, %f]", rgb[0], rgb[1], rgb[2]);
                        WM_clipboard_text_set(buf, 0);
                        
                }
                else {
                        if (sscanf(buf, "[%f, %f, %f]", &rgb[0], &rgb[1], &rgb[2]) == 3) {
+                               /* assume linear colors in buffer */
+                               if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
+                                       linearrgb_to_srgb_v3_v3(rgb, rgb);
+
                                button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
                                ui_set_but_vectorf(but, rgb);
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -1174,12 +1240,14 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
        else if (ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) {
                uiHandleButtonData *active_data = but->active;
 
-               if (but->poin == NULL && but->rnapoin.data == NULL) ;
+               if (but->poin == NULL && but->rnapoin.data == NULL) {
+                       /* pass */
+               }
                else if (mode == 'c') {
                        button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
                        BLI_strncpy(buf, active_data->str, UI_MAX_DRAW_STR);
                        WM_clipboard_text_set(active_data->str, 0);
-                       active_data->cancel = 1;
+                       active_data->cancel = TRUE;
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                }
                else {
@@ -1253,7 +1321,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
 {
        uiStyle *style = UI_GetStyle();  // XXX pass on as arg
        uiFontStyle *fstyle = &style->widget;
-       int startx = but->x1;
+       int startx = but->rect.xmin;
        char *origstr;
 
        uiStyleFontSet(fstyle);
@@ -1267,7 +1335,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
        
        /* XXX solve generic */
        if (but->type == NUM || but->type == NUMSLI)
-               startx += (int)(0.5f * (but->y2 - but->y1));
+               startx += (int)(0.5f * (BLI_rctf_size_y(&but->rect)));
        else if (ELEM(but->type, TEX, SEARCH_MENU)) {
                startx += 5;
                if (but->flag & UI_HAS_ICON)
@@ -1275,14 +1343,17 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
        }
        
        /* mouse dragged outside the widget to the left */
-       if (x < startx && but->ofs > 0) {       
+       if (x < startx && but->ofs > 0) {
                int i = but->ofs;
 
                origstr[but->ofs] = 0;
                
                while (i > 0) {
                        if (BLI_str_cursor_step_prev_utf8(origstr, but->ofs, &i)) {
-                               if (BLF_width(fstyle->uifont_id, origstr + i) > (startx - x) * 0.25f) break;  // 0.25 == scale factor for less sensitivity
+                               /* 0.25 == scale factor for less sensitivity */
+                               if (BLF_width(fstyle->uifont_id, origstr + i) > (startx - x) * 0.25f) {
+                                       break;
+                               }
                        }
                        else {
                                break; /* unlikely but possible */
@@ -1305,7 +1376,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
 
                while (TRUE) {
                        /* XXX does not take zoom level into account */
-                       cdist = startx + aspect_sqrt *BLF_width(fstyle->uifont_id, origstr + but->ofs);
+                       cdist = startx + aspect_sqrt * BLF_width(fstyle->uifont_id, origstr + but->ofs);
 
                        /* check if position is found */
                        if (cdist < x) {
@@ -1341,13 +1412,13 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho
 
 static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, short x)
 {
-       if (x > data->selstartx) data->selextend = EXTEND_RIGHT;
+       if      (x > data->selstartx) data->selextend = EXTEND_RIGHT;
        else if (x < data->selstartx) data->selextend = EXTEND_LEFT;
 
        ui_textedit_set_cursor_pos(but, data, x);
-                                               
-       if (data->selextend == EXTEND_RIGHT) but->selend = but->pos;
-       if (data->selextend == EXTEND_LEFT) but->selsta = but->pos;
+
+       if      (data->selextend == EXTEND_RIGHT) but->selend = but->pos;
+       else if (data->selextend == EXTEND_LEFT)  but->selsta = but->pos;
 
        ui_check_but(but);
 }
@@ -1399,7 +1470,8 @@ static int ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char asc
        return ui_textedit_type_buf(but, data, buf, 1);
 }
 
-static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, strCursorJumpDirection direction, int select, strCursorJumpType jump)
+static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, strCursorJumpDirection direction,
+                             int select, strCursorJumpType jump)
 {
        const char *str = data->str;
        const int len = strlen(str);
@@ -1515,7 +1587,7 @@ static int ui_textedit_delete(uiBut *but, uiHandleButtonData *data, int directio
                                but->pos -= step;
                                changed = 1;
                        }
-               } 
+               }
        }
 
        return changed;
@@ -1550,6 +1622,7 @@ static int ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, int paste
        
        /* paste */
        if (paste) {
+               /* TODO, ensure UTF8 ui_is_but_utf8() - campbell */
                /* extract the first line from the clipboard */
                p = pbuf = WM_clipboard_text_get(0);
 
@@ -1603,7 +1676,7 @@ static int ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, int paste
                if (cut)
                        if ((but->selend - but->selsta) > 0)
                                changed = ui_textedit_delete_selection(but, data);
-       } 
+       }
 
        return changed;
 }
@@ -1748,13 +1821,13 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                        break;
                case RIGHTMOUSE:
                case ESCKEY:
-                       data->cancel = 1;
-                       data->escapecancel = 1;
+                       data->cancel = TRUE;
+                       data->escapecancel = TRUE;
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                        retval = WM_UI_HANDLER_BREAK;
                        break;
-               case LEFTMOUSE: {
-                       
+               case LEFTMOUSE:
+               {
                        /* exit on LMB only on RELEASE for searchbox, to mimic other popups, and allow multiple menu levels */
                        if (data->searchbox)
                                inbox = ui_searchbox_inside(data->searchbox, event->x, event->y);
@@ -1775,7 +1848,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                                else if (inbox == 0) {
                                        /* if searchbox, click outside will cancel */
                                        if (data->searchbox)
-                                               data->cancel = data->escapecancel = 1;
+                                               data->cancel = data->escapecancel = TRUE;
                                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                                        retval = WM_UI_HANDLER_BREAK;
                                }
@@ -1805,11 +1878,13 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                                }
                                break;
                        case RIGHTARROWKEY:
-                               ui_textedit_move(but, data, STRCUR_DIR_NEXT, event->shift, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
+                               ui_textedit_move(but, data, STRCUR_DIR_NEXT,
+                                                event->shift, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
                                retval = WM_UI_HANDLER_BREAK;
                                break;
                        case LEFTARROWKEY:
-                               ui_textedit_move(but, data, STRCUR_DIR_PREV, event->shift, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
+                               ui_textedit_move(but, data, STRCUR_DIR_PREV,
+                                                event->shift, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
                                retval = WM_UI_HANDLER_BREAK;
                                break;
                        case DOWNARROWKEY:
@@ -1819,7 +1894,8 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                                }
                        /* pass on purposedly */
                        case ENDKEY:
-                               ui_textedit_move(but, data, STRCUR_DIR_NEXT, event->shift, STRCUR_JUMP_ALL);
+                               ui_textedit_move(but, data, STRCUR_DIR_NEXT,
+                                                event->shift, STRCUR_JUMP_ALL);
                                retval = WM_UI_HANDLER_BREAK;
                                break;
                        case UPARROWKEY:
@@ -1829,7 +1905,8 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                                }
                        /* pass on purposedly */
                        case HOMEKEY:
-                               ui_textedit_move(but, data, STRCUR_DIR_PREV, event->shift, STRCUR_JUMP_ALL);
+                               ui_textedit_move(but, data, STRCUR_DIR_PREV,
+                                                event->shift, STRCUR_JUMP_ALL);
                                retval = WM_UI_HANDLER_BREAK;
                                break;
                        case PADENTER:
@@ -1838,12 +1915,14 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
                                retval = WM_UI_HANDLER_BREAK;
                                break;
                        case DELKEY:
-                               changed = ui_textedit_delete(but, data, 1, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
+                               changed = ui_textedit_delete(but, data, 1,
+                                                            event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE);
                                retval = WM_UI_HANDLER_BREAK;
                                break;
 
                        case BACKSPACEKEY:
-                               changed = ui_textedit_delete(but, data, 0, event->shift ? STRCUR_JUMP_ALL :  (event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE));
+                               changed = ui_textedit_delete(but, data, 0,
+                                                            event->shift ? STRCUR_JUMP_ALL : (event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE));
                                retval = WM_UI_HANDLER_BREAK;
                                break;
                                
@@ -1903,8 +1982,12 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
 
        if (changed) {
                /* only update when typing for TAB key */
-               if (update && data->interactive) ui_apply_button(C, block, but, data, 1);
-               else ui_check_but(but);
+               if (update && data->interactive) {
+                       ui_apply_button(C, block, but, data, 1);
+               }
+               else {
+                       ui_check_but(but);
+               }
                but->changed = TRUE;
                
                if (data->searchbox)
@@ -1920,7 +2003,8 @@ static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, u
        int mx, my, retval = WM_UI_HANDLER_CONTINUE;
 
        switch (event->type) {
-               case MOUSEMOVE: {
+               case MOUSEMOVE:
+               {
                        mx = event->x;
                        my = event->y;
                        ui_window_to_block(data->region, block, &mx, &my);
@@ -1994,8 +2078,12 @@ static void ui_numedit_end(uiBut *but, uiHandleButtonData *data)
 
 static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data)
 {
-       if (data->interactive) ui_apply_button(C, block, but, data, 1);
-       else ui_check_but(but);
+       if (data->interactive) {
+               ui_apply_button(C, block, but, data, 1);
+       }
+       else {
+               ui_check_but(but);
+       }
 
        ED_region_tag_redraw(data->region);
 }
@@ -2043,14 +2131,18 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data
                        menufunc = ui_block_func_ICONTEXTROW;
                        arg = but;
                        break;
-               case COL:
+               case COLOR:
                        ui_get_but_vectorf(but, data->origvec);
                        copy_v3_v3(data->vec, data->origvec);
                        but->editvec = data->vec;
 
-                       handlefunc = ui_block_func_COL;
+                       handlefunc = ui_block_func_COLOR;
                        arg = but;
                        break;
+
+                       /* quiet warnings for unhandled types */
+               default:
+                       break;
        }
 
        if (func || handlefunc) {
@@ -2065,7 +2157,7 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data
        }
 
        /* this makes adjacent blocks auto open from now on */
-       //if (but->block->auto_open==0) but->block->auto_open= 1;
+       //if (but->block->auto_open == 0) but->block->auto_open = 1;
 }
 
 static void ui_blockopen_end(bContext *C, uiBut *but, uiHandleButtonData *data)
@@ -2083,6 +2175,16 @@ static void ui_blockopen_end(bContext *C, uiBut *but, uiHandleButtonData *data)
        }
 }
 
+int ui_button_open_menu_direction(uiBut *but)
+{
+       uiHandleButtonData *data = but->active;
+
+       if (data && data->menu)
+               return data->menu->direction;
+       
+       return 0;
+}
+
 /* ***************** events for different button types *************** */
 
 static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event)
@@ -2104,7 +2206,7 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEv
        else if (data->state == BUTTON_STATE_WAIT_RELEASE) {
                if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
                        if (!(but->flag & UI_SELECT))
-                               data->cancel = 1;
+                               data->cancel = TRUE;
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                        return WM_UI_HANDLER_BREAK;
                }
@@ -2135,7 +2237,7 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
                                if (but->flag & UI_BUT_IMMEDIATE)
                                        ui_set_but_val(but, 0);
                                else
-                                       data->cancel = 1;
+                                       data->cancel = TRUE;
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                                return WM_UI_HANDLER_BREAK;
                        }
@@ -2152,19 +2254,19 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
                ED_region_tag_redraw(data->region);
                        
                if (event->val == KM_PRESS) {
-                       if (ISHOTKEY(event->type)) { 
+                       if (ISHOTKEY(event->type)) {
                                
                                if (WM_key_event_string(event->type)[0])
                                        ui_set_but_val(but, event->type);
                                else
-                                       data->cancel = 1;
+                                       data->cancel = TRUE;
                                
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                                return WM_UI_HANDLER_BREAK;
                        }
                        else if (event->type == ESCKEY) {
-                               data->cancel = 1;
-                               data->escapecancel = 1;
+                               data->cancel = TRUE;
+                               data->escapecancel = TRUE;
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                        }
                        
@@ -2190,7 +2292,7 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, w
                        if (WM_key_event_string(event->type)[0])
                                ui_set_but_val(but, event->type);
                        else
-                               data->cancel = 1;
+                               data->cancel = TRUE;
 
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                }
@@ -2203,7 +2305,9 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
 {
        if (data->state == BUTTON_STATE_HIGHLIGHT) {
                if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN) && event->val == KM_PRESS) {
-                       if (but->dt == UI_EMBOSSN && !event->ctrl) ;
+                       if (but->dt == UI_EMBOSSN && !event->ctrl) {
+                               /* pass */
+                       }
                        else {
                                button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
                                return WM_UI_HANDLER_BREAK;
@@ -2316,14 +2420,14 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa
                }
 
                if (snap == 1) {
-                       if (softrange < 2.10f) tempf = 0.1f * floorf(10.0f * tempf);
+                       if      (softrange < 2.10f) tempf = 0.1f  * floorf(10.0f * tempf);
                        else if (softrange < 21.0f) tempf = floorf(tempf);
-                       else tempf = 10.0f * floorf(tempf / 10.0f);
+                       else                        tempf = 10.0f * floorf(tempf / 10.0f);
                }
                else if (snap == 2) {
-                       if (softrange < 2.10f) tempf = 0.01f * floorf(100.0f * tempf);
-                       else if (softrange < 21.0f) tempf = 0.1f * floorf(10.0f * tempf);
-                       else tempf = floor(tempf);
+                       if      (softrange < 2.10f) tempf = 0.01f * floorf(100.0f * tempf);
+                       else if (softrange < 21.0f) tempf = 0.1f  * floorf(10.0f * tempf);
+                       else                        tempf = floor(tempf);
                }
                
                if (fac != 1.0f)
@@ -2402,9 +2506,9 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
                        }
                }
                else {
-                       if (softrange > 256) fac = 1.0;             /* 1px == 1 */
-                       else if (softrange > 32) fac = 1.0 / 2.0;   /* 2px == 1 */
-                       else fac = 1.0 / 16.0;                  /* 16px == 1? */
+                       if      (softrange > 256) fac = 1.0;        /* 1px == 1 */
+                       else if (softrange >  32) fac = 1.0 / 2.0;  /* 2px == 1 */
+                       else                      fac = 1.0 / 16.0; /* 16px == 1? */
 
                        temp = data->startvalue + (((double)mx - data->dragstartx) * (double)fac);
                        temp = ui_numedit_apply_snap(temp, softmin, softmax, snap);
@@ -2436,10 +2540,9 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
                deler = 500;
                if (!ui_is_but_float(but)) {
                        /* prevent large ranges from getting too out of control */
-                       if (softrange > 600) deler = powf(softrange, 0.75);
-                       
-                       if (softrange < 100) deler = 200.0;
-                       if (softrange < 25) deler = 50.0;
+                       if      (softrange > 600) deler = powf(softrange, 0.75);
+                       else if (softrange < 100) deler = 200.0;
+                       else if (softrange <  25) deler = 50.0;
                }
                deler /= fac;
 
@@ -2508,11 +2611,11 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
        if (data->state == BUTTON_STATE_HIGHLIGHT) {
                /* XXX hardcoded keymap check.... */
                if (event->type == WHEELDOWNMOUSE && event->alt) {
-                       mx = but->x1;
+                       mx = but->rect.xmin;
                        click = 1;
                }
                else if (event->type == WHEELUPMOUSE && event->alt) {
-                       mx = but->x2;
+                       mx = but->rect.xmax;
                        click = 1;
                }
                else if (event->val == KM_PRESS) {
@@ -2525,8 +2628,9 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
                                button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
                                retval = WM_UI_HANDLER_BREAK;
                        }
-                       else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS)
+                       else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) {
                                click = 1;
+                       }
                        else if (event->type == MINUSKEY && event->val == KM_PRESS) {
                                button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
                                data->value = -data->value;
@@ -2538,8 +2642,8 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
        }
        else if (data->state == BUTTON_STATE_NUM_EDITING) {
                if (event->type == ESCKEY) {
-                       data->cancel = 1;
-                       data->escapecancel = 1;
+                       data->cancel = TRUE;
+                       data->escapecancel = TRUE;
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                }
                else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
@@ -2554,7 +2658,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
 
                        fac = 1.0f;
                        if (event->shift) fac /= 10.0f;
-                       if (event->alt) fac /= 20.0f;
+                       if (event->alt)   fac /= 20.0f;
                        
                        snap = (event->ctrl) ? (event->shift) ? 2 : 1 : 0;
 
@@ -2582,33 +2686,34 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
                softmax = but->softmax;
 
                if (!ui_is_but_float(but)) {
-                       if (mx < (but->x1 + (but->x2 - but->x1) / 3 - 3)) {
+                       if (mx < (but->rect.xmin + BLI_rctf_size_x(&but->rect) / 3 - 3)) {
                                button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
 
                                temp = (int)data->value - 1;
                                if (temp >= softmin && temp <= softmax)
                                        data->value = (double)temp;
                                else
-                                       data->cancel = 1;
+                                       data->cancel = TRUE;
 
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                        }
-                       else if (mx > (but->x1 + (2 * (but->x2 - but->x1) / 3) + 3)) {
+                       else if (mx > (but->rect.xmin + (2 * BLI_rctf_size_x(&but->rect) / 3) + 3)) {
                                button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
 
                                temp = (int)data->value + 1;
                                if (temp >= softmin && temp <= softmax)
                                        data->value = (double)temp;
                                else
-                                       data->cancel = 1;
+                                       data->cancel = TRUE;
 
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                        }
-                       else
+                       else {
                                button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+                       }
                }
                else {
-                       if (mx < (but->x1 + (but->x2 - but->x1) / 3 - 3)) {
+                       if (mx < (but->rect.xmin + BLI_rctf_size_x(&but->rect) / 3 - 3)) {
                                button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
 
                                tempf = (float)data->value - 0.01f * but->a1;
@@ -2617,7 +2722,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
 
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                        }
-                       else if (mx > but->x1 + (2 * ((but->x2 - but->x1) / 3) + 3)) {
+                       else if (mx > but->rect.xmin + (2 * (BLI_rctf_size_x(&but->rect) / 3) + 3)) {
                                button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
 
                                tempf = (float)data->value + 0.01f * but->a1;
@@ -2626,8 +2731,9 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
 
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                        }
-                       else
+                       else {
                                button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+                       }
                }
 
                retval = WM_UI_HANDLER_BREAK;
@@ -2636,7 +2742,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
        return retval;
 }
 
-static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, int shift, int ctrl, int mx)
+static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, const short shift, const short ctrl, int mx)
 {
        float deler, f, tempf, softmin, softmax, softrange;
        int temp, lvalue, changed = 0;
@@ -2645,14 +2751,20 @@ static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, int shift, i
        softmax = but->softmax;
        softrange = softmax - softmin;
 
-       if (but->type == NUMSLI) deler = ((but->x2 - but->x1) - 5.0f * but->aspect);
-       else if (but->type == HSVSLI) deler = ((but->x2 - but->x1) / 2.0f - 5.0f * but->aspect);
+       if (but->type == NUMSLI) {
+               deler = (BLI_rctf_size_x(&but->rect) - 5.0f * but->aspect);
+       }
+       else if (but->type == HSVSLI) {
+               deler = (BLI_rctf_size_x(&but->rect) / 2.0f - 5.0f * but->aspect);
+       }
        else if (but->type == SCROLL) {
-               int horizontal = (but->x2 - but->x1 > but->y2 - but->y1);
-               float size = (horizontal) ? (but->x2 - but->x1) : -(but->y2 - but->y1);
+               int horizontal = (BLI_rctf_size_x(&but->rect) > BLI_rctf_size_y(&but->rect));
+               float size = (horizontal) ? BLI_rctf_size_x(&but->rect) : -BLI_rctf_size_y(&but->rect);
                deler = size * (but->softmax - but->softmin) / (but->softmax - but->softmin + but->a1);
        }
-       else deler = (but->x2 - but->x1 - 5.0f * but->aspect);
+       else {
+               deler = (BLI_rctf_size_x(&but->rect) - 5.0f * but->aspect);
+       }
 
        f = (float)(mx - data->dragstartx) / deler + data->dragfstart;
        
@@ -2664,19 +2776,21 @@ static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, int shift, i
        temp = floorf(tempf + 0.5f);
 
        if (ctrl) {
-               if (tempf == softmin || tempf == softmax) ;
+               if (tempf == softmin || tempf == softmax) {
+                       /* pass */
+               }
                else if (ui_is_but_float(but)) {
 
                        if (shift) {
-                               if (tempf == softmin || tempf == softmax) ;
+                               if      (tempf == softmin || tempf == softmax) {}
                                else if (softmax - softmin < 2.10f) tempf = 0.01f * floorf(100.0f * tempf);
-                               else if (softmax - softmin < 21.0f) tempf = 0.1f * floorf(10.0f * tempf);
-                               else tempf = floorf(tempf);
+                               else if (softmax - softmin < 21.0f) tempf = 0.1f  * floorf(10.0f * tempf);
+                               else                                tempf = floorf(tempf);
                        }
                        else {
-                               if (softmax - softmin < 2.10f) tempf = 0.1f * floorf(10.0f * tempf);
+                               if      (softmax - softmin < 2.10f) tempf = 0.1f * floorf(10.0f * tempf);
                                else if (softmax - softmin < 21.0f) tempf = floorf(tempf);
-                               else tempf = 10.0f * floorf(tempf / 10.0f);
+                               else                                tempf = 10.0f * floorf(tempf / 10.0f);
                        }
                }
                else {
@@ -2721,11 +2835,11 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
        if (data->state == BUTTON_STATE_HIGHLIGHT) {
                /* XXX hardcoded keymap check.... */
                if (event->type == WHEELDOWNMOUSE && event->alt) {
-                       mx = but->x1;
+                       mx = but->rect.xmin;
                        click = 2;
                }
                else if (event->type == WHEELUPMOUSE && event->alt) {
-                       mx = but->x2;
+                       mx = but->rect.xmax;
                        click = 2;
                }
                else if (event->val == KM_PRESS) {
@@ -2735,12 +2849,12 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
                        }
                        /* alt-click on sides to get "arrows" like in NUM buttons, and match wheel usage above */
                        else if (event->type == LEFTMOUSE && event->alt) {
-                               int halfpos = (but->x1 + but->x2) / 2;
+                               int halfpos = BLI_rctf_cent_x(&but->rect);
                                click = 2;
                                if (mx < halfpos)
-                                       mx = but->x1;
+                                       mx = but->rect.xmin;
                                else
-                                       mx = but->x2;
+                                       mx = but->rect.xmax;
                        }
                        else if (event->type == LEFTMOUSE) {
                                data->dragstartx = mx;
@@ -2748,8 +2862,9 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
                                button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
                                retval = WM_UI_HANDLER_BREAK;
                        }
-                       else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS)
+                       else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) {
                                click = 1;
+                       }
                        else if (event->type == MINUSKEY && event->val == KM_PRESS) {
                                button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
                                data->value = -data->value;
@@ -2760,8 +2875,8 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
        }
        else if (data->state == BUTTON_STATE_NUM_EDITING) {
                if (event->type == ESCKEY) {
-                       data->cancel = 1;
-                       data->escapecancel = 1;
+                       data->cancel = TRUE;
+                       data->escapecancel = TRUE;
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                }
                else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
@@ -2802,12 +2917,12 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
 
 #if 0
                        if (but->type == SLI) {
-                               f = (float)(mx - but->x1) / (but->x2 - but->x1); /* same as below */
+                               f = (float)(mx - but->rect.xmin) / (BLI_rctf_size_x(&but->rect)); /* same as below */
                        }
                        else
 #endif
                        {
-                               f = (float)(mx - but->x1) / (but->x2 - but->x1);
+                               f = (float)(mx - but->rect.xmin) / (BLI_rctf_size_x(&but->rect));
                        }
                        
                        f = softmin + f * softrange;
@@ -2819,8 +2934,8 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
                                if (temp >= softmin && temp <= softmax)
                                        data->value = temp;
                                else
-                                       data->cancel = 1;
-                       } 
+                                       data->cancel = TRUE;
+                       }
                        else {
                                if (f < tempf) tempf -= 0.01f;
                                else tempf += 0.01f;
@@ -2828,7 +2943,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
                                if (tempf >= softmin && tempf <= softmax)
                                        data->value = tempf;
                                else
-                                       data->cancel = 1;
+                                       data->cancel = TRUE;
                        }
                        
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -2846,9 +2961,9 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
 
 static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event)
 {
-       int mx, my /*, click= 0 */;
+       int mx, my /*, click = 0 */;
        int retval = WM_UI_HANDLER_CONTINUE;
-       int horizontal = (but->x2 - but->x1 > but->y2 - but->y1);
+       int horizontal = (BLI_rctf_size_x(&but->rect) > BLI_rctf_size_y(&but->rect));
        
        mx = event->x;
        my = event->y;
@@ -2877,8 +2992,8 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
        }
        else if (data->state == BUTTON_STATE_NUM_EDITING) {
                if (event->type == ESCKEY) {
-                       data->cancel = 1;
-                       data->escapecancel = 1;
+                       data->cancel = TRUE;
+                       data->escapecancel = TRUE;
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                }
                else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
@@ -2917,9 +3032,11 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm
                        return WM_UI_HANDLER_BREAK;
                }
                else if (ELEM3(but->type, MENU, ICONROW, ICONTEXTROW)) {
-                       
-                       if (event->type == WHEELDOWNMOUSE && event->alt) {
-                               data->value = ui_step_name_menu(but, -1);
+                       if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
+                               const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1;
+
+                               data->value = ui_step_name_menu(but, direction);
+
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                                ui_apply_button(C, but->block, but, data, 1);
 
@@ -2933,21 +3050,20 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm
                                data->postbut = but;
                                data->posttype = BUTTON_ACTIVATE_OVER;
 
-                               return WM_UI_HANDLER_BREAK;
-                       }
-                       else if (event->type == WHEELUPMOUSE && event->alt) {
-                               data->value = ui_step_name_menu(but, 1);
-                               button_activate_state(C, but, BUTTON_STATE_EXIT);
-                               ui_apply_button(C, but->block, but, data, 1);
-
-                               /* why this is needed described above */
-                               data->postbut = but;
-                               data->posttype = BUTTON_ACTIVATE_OVER;
+                               /* without this, a new interface that draws as result of the menu change
+                                * won't register that the mouse is over it, eg:
+                                * Alt+MouseWheel over the render slots, without this,
+                                * the slot menu fails to switch a second time.
+                                *
+                                * The active state of the button could be maintained some other way
+                                * and remove this mousemove event.
+                                */
+                               WM_event_add_mousemove(C);
 
                                return WM_UI_HANDLER_BREAK;
                        }
                }
-               else if (but->type == COL) {
+               else if (but->type == COLOR) {
                        if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) {
                                float *hsv = ui_block_hsv_get(but->block);
                                float col[3];
@@ -2979,7 +3095,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm
                /* outside icon quit, not needed if drag activated */
                if (0 == ui_but_mouse_inside_icon(but, data->region, event)) {
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
-                       data->cancel = 1;
+                       data->cancel = TRUE;
                        return WM_UI_HANDLER_BREAK;
                }
                
@@ -3005,7 +3121,7 @@ static int ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data, int mx, i
         * else we'll get a harmless but annoying jump when first clicking */
 
        fp = data->origvec;
-       rad = (but->x2 - but->x1);
+       rad = BLI_rctf_size_x(&but->rect);
        radsq = rad * rad;
        
        if (fp[2] > 0.0f) {
@@ -3018,7 +3134,9 @@ static int ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data, int mx, i
                mdx = 2.0f * mrad * fp[0] - (rad * fp[0]);
                mdy = 2.0f * mrad * fp[1] - (rad * fp[1]);
        }
-       else mdx = mdy = 0;
+       else {
+               mdx = mdy = 0;
+       }
        
        dx = (float)(mx + mdx - data->dragstartx);
        dy = (float)(my + mdy - data->dragstarty);
@@ -3082,8 +3200,9 @@ static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
                                        ui_numedit_apply(C, block, but, data);
                        }
                }
-               else if (event->type == LEFTMOUSE && event->val != KM_PRESS)
+               else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
+               }
 
                return WM_UI_HANDLER_BREAK;
        }
@@ -3091,26 +3210,41 @@ static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
        return WM_UI_HANDLER_CONTINUE;
 }
 
-static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, int my)
+static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, int my, const short shift)
 {
        float rgb[3];
        float *hsv = ui_block_hsv_get(but->block);
        float x, y;
+       float mx_fl, my_fl;
        int changed = 1;
        int color_profile = but->block->color_profile;
        
+       ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift);
+
+#ifdef USE_CONT_MOUSE_CORRECT
+       if (ui_is_a_warp_but(but)) {
+               /* OK but can go outside bounds */
+               data->ungrab_mval[0] = mx_fl;
+               data->ungrab_mval[1] = my_fl;
+               BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval);
+       }
+#endif
+
        if (but->rnaprop) {
                if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
-                       color_profile = BLI_PR_NONE;
+                       color_profile = FALSE;
        }
 
        ui_get_but_vectorf(but, rgb);
 
+       if (color_profile && (int)but->a1)
+               ui_block_to_display_space_v3(but->block, rgb);
+
        rgb_to_hsv_compat_v(rgb, hsv);
 
        /* relative position within box */
-       x = ((float)mx - but->x1) / (but->x2 - but->x1);
-       y = ((float)my - but->y1) / (but->y2 - but->y1);
+       x = ((float)mx_fl - but->rect.xmin) / BLI_rctf_size_x(&but->rect);
+       y = ((float)my_fl - but->rect.ymin) / BLI_rctf_size_y(&but->rect);
        CLAMP(x, 0.0f, 1.0f);
        CLAMP(y, 0.0f, 1.0f);
 
@@ -3142,17 +3276,16 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx,
                        /* exception only for value strip - use the range set in but->min/max */
                        hsv[2] = y * (but->softmax - but->softmin) + but->softmin;
 
-                       if (color_profile)
-                               hsv[2] = srgb_to_linearrgb(hsv[2]);
-
-                       if (hsv[2] > but->softmax)
-                               hsv[2] = but->softmax;
                        break;
                default:
                        assert(!"invalid hsv type");
        }
 
        hsv_to_rgb_v(hsv, rgb);
+
+       if (color_profile && (int)but->a1)
+               ui_block_to_scene_linear_v3(but->block, rgb);
+
        copy_v3_v3(data->vec, rgb);
 
        data->draglastx = mx;
@@ -3161,7 +3294,7 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx,
        return changed;
 }
 
-static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOFMotionData *ndof, int shift)
+static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOFMotionData *ndof, const short shift)
 {
        float *hsv = ui_block_hsv_get(but->block);
        float rgb[3];
@@ -3171,10 +3304,14 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF
        
        if (but->rnaprop) {
                if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
-                       color_profile = BLI_PR_NONE;
+                       color_profile = FALSE;
        }
 
        ui_get_but_vectorf(but, rgb);
+
+       if (color_profile && (int)but->a1)
+               ui_block_to_display_space_v3(but->block, rgb);
+
        rgb_to_hsv_compat_v(rgb, hsv);
        
        switch ((int)but->a1) {
@@ -3199,21 +3336,22 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF
                case UI_GRAD_V:
                        hsv[2] += ndof->ry * sensitivity;
                        break;
-               case UI_GRAD_V_ALT:     
+               case UI_GRAD_V_ALT:
                        /* vertical 'value' strip */
                        
                        /* exception only for value strip - use the range set in but->min/max */
                        hsv[2] += ndof->rx * sensitivity;
                        
-                       if (color_profile)
-                               hsv[2] = srgb_to_linearrgb(hsv[2]);
-                       
                        CLAMP(hsv[2], but->softmin, but->softmax);
                default:
                        assert(!"invalid hsv type");
        }
-       
+
        hsv_to_rgb_v(hsv, rgb);
+
+       if (color_profile && (int)but->a1)
+               ui_block_to_scene_linear_v3(but->block, rgb);
+
        copy_v3_v3(data->vec, rgb);
        ui_set_but_vectorf(but, data->vec);
 }
@@ -3235,7 +3373,7 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
                        button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
 
                        /* also do drag the first time */
-                       if (ui_numedit_but_HSVCUBE(but, data, mx, my))
+                       if (ui_numedit_but_HSVCUBE(but, data, mx, my, event->shift))
                                ui_numedit_apply(C, block, but, data);
                        
                        return WM_UI_HANDLER_BREAK;
@@ -3286,18 +3424,19 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
        }
        else if (data->state == BUTTON_STATE_NUM_EDITING) {
                if (event->type == ESCKEY) {
-                       data->cancel = 1;
-                       data->escapecancel = 1;
+                       data->cancel = TRUE;
+                       data->escapecancel = TRUE;
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                }
                else if (event->type == MOUSEMOVE) {
                        if (mx != data->draglastx || my != data->draglasty) {
-                               if (ui_numedit_but_HSVCUBE(but, data, mx, my))
+                               if (ui_numedit_but_HSVCUBE(but, data, mx, my, event->shift))
                                        ui_numedit_apply(C, block, but, data);
                        }
                }
-               else if (event->type == LEFTMOUSE && event->val != KM_PRESS)
+               else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
+               }
                
                return WM_UI_HANDLER_BREAK;
        }
@@ -3305,16 +3444,34 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu
        return WM_UI_HANDLER_CONTINUE;
 }
 
-static int ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, int mx, int my, int shift)
+static int ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, float mx, float my, int shift)
 {
        rcti rect;
        int changed = 1;
+       float mx_fl, my_fl;
        float rgb[3];
        float hsv[3];
        
-       rect.xmin = but->x1; rect.xmax = but->x2;
-       rect.ymin = but->y1; rect.ymax = but->y2;
-       
+       ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift);
+
+#ifdef USE_CONT_MOUSE_CORRECT
+       if (ui_is_a_warp_but(but)) {
+               /* OK but can go outside bounds */
+               data->ungrab_mval[0] = mx_fl;
+               data->ungrab_mval[1] = my_fl;
+               {       /* clamp */
+                       const float radius = min_ff(BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect)) / 2.0f;
+                       const float cent[2] = {BLI_rctf_cent_x(&but->rect), BLI_rctf_cent_y(&but->rect)};
+                       const float len = len_v2v2(cent, data->ungrab_mval);
+                       if (len > radius) {
+                               dist_ensure_v2_v2fl(data->ungrab_mval, cent, radius);
+                       }
+               }
+       }
+#endif
+
+       BLI_rcti_rctf_copy(&rect, &but->rect);
+
        ui_get_but_vectorf(but, rgb);
        copy_v3_v3(hsv, ui_block_hsv_get(but->block));
        rgb_to_hsv_compat_v(rgb, hsv);
@@ -3325,14 +3482,8 @@ static int ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, int mx
                if (hsv[2] == 0.f) hsv[2] = 0.0001f;
        }
 
-       if (U.uiflag & USER_CONTINUOUS_MOUSE) {
-               float fac = shift ? 0.05f : 1.0f;
-               /* slow down the mouse, this is fairly picky */
-               mx = (data->dragstartx * (1.0f - fac) + mx * fac);
-               my = (data->dragstarty * (1.0f - fac) + my * fac);
-       }
 
-       ui_hsvcircle_vals_from_pos(hsv, hsv + 1, &rect, (float)mx, (float)my);
+       ui_hsvcircle_vals_from_pos(hsv, hsv + 1, &rect, mx_fl, my_fl);
 
        if (but->flag & UI_BUT_COLOR_CUBIC)
                hsv[1] = 1.0f - sqrt3f(1.0f - hsv[1]);
@@ -3352,7 +3503,7 @@ static int ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, int mx
        return changed;
 }
 
-static void ui_ndofedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, wmNDOFMotionData *ndof, int shift)
+static void ui_ndofedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, wmNDOFMotionData *ndof, const short shift)
 {
        float *hsv = ui_block_hsv_get(but->block);
        float rgb[3];
@@ -3362,10 +3513,10 @@ static void ui_ndofedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, wmND
        ui_get_but_vectorf(but, rgb);
        rgb_to_hsv_compat_v(rgb, hsv);
        
-       /* Convert current colour on hue/sat disc to circular coordinates phi, r */
+       /* Convert current color on hue/sat disc to circular coordinates phi, r */
        phi = fmodf(hsv[0] + 0.25f, 1.0f) * -2.0f * (float)M_PI;
        r = hsv[1];
-       /* sqr= r>0.f?sqrtf(r):1; */ /* UNUSED */
+       /* sqr = r > 0.0f ? sqrtf(r) : 1; */ /* UNUSED */
        
        /* Convert to 2d vectors */
        v[0] = r * cosf(phi);
@@ -3470,21 +3621,21 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle
        }
        else if (data->state == BUTTON_STATE_NUM_EDITING) {
                if (event->type == ESCKEY) {
-                       data->cancel = 1;
-                       data->escapecancel = 1;
+                       data->cancel = TRUE;
+                       data->escapecancel = TRUE;
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                }
                /* XXX hardcoded keymap check.... */
                else if (event->type == WHEELDOWNMOUSE) {
                        float *hsv = ui_block_hsv_get(but->block);
                        hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f);
-                       ui_set_but_hsv(but);    // converts to rgb
+                       ui_set_but_hsv(but);    /* converts to rgb */
                        ui_numedit_apply(C, block, but, data);
                }
                else if (event->type == WHEELUPMOUSE) {
                        float *hsv = ui_block_hsv_get(but->block);
                        hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f);
-                       ui_set_but_hsv(but);    // converts to rgb
+                       ui_set_but_hsv(but);    /* converts to rgb */
                        ui_numedit_apply(C, block, but, data);
                }
                else if (event->type == MOUSEMOVE) {
@@ -3511,7 +3662,7 @@ static int ui_numedit_but_COLORBAND(uiBut *but, uiHandleButtonData *data, int mx
        if (data->draglastx == mx)
                return changed;
 
-       dx = ((float)(mx - data->draglastx)) / (but->x2 - but->x1);
+       dx = ((float)(mx - data->draglastx)) / BLI_rctf_size_x(&but->rect);
        data->dragcbd->pos += dx;
        CLAMP(data->dragcbd->pos, 0.0f, 1.0f);
        
@@ -3540,7 +3691,7 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle
 
                        if (event->ctrl) {
                                /* insert new key on mouse location */
-                               float pos = ((float)(mx - but->x1)) / (but->x2 - but->x1);
+                               float pos = ((float)(mx - but->rect.xmin)) / BLI_rctf_size_x(&but->rect);
                                colorband_element_add(coba, pos);
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                        }
@@ -3552,7 +3703,7 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle
 
                                /* activate new key when mouse is close */
                                for (a = 0, cbd = coba->data; a < coba->tot; a++, cbd++) {
-                                       xco = but->x1 + (cbd->pos * (but->x2 - but->x1));
+                                       xco = but->rect.xmin + (cbd->pos * BLI_rctf_size_x(&but->rect));
                                        xco = ABS(xco - mx);
                                        if (a == coba->cur) xco += 5;  // selected one disadvantage
                                        if (xco < mindist) {
@@ -3575,8 +3726,9 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle
                                        ui_numedit_apply(C, block, but, data);
                        }
                }
-               else if (event->type == LEFTMOUSE && event->val != KM_PRESS)
+               else if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
+               }
                
                return WM_UI_HANDLER_BREAK;
        }
@@ -3584,7 +3736,8 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle
        return WM_UI_HANDLER_CONTINUE;
 }
 
-static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap, int mx, int my)
+static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
+                                float mx, float my, const short shift)
 {
        CurveMapping *cumap = (CurveMapping *)but->poin;
        CurveMap *cuma = cumap->cm + cumap->cur;
@@ -3592,10 +3745,10 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
        float fx, fy, zoomx, zoomy /*, offsx, offsy */ /* UNUSED */;
        int a, changed = 0;
 
-       zoomx = (but->x2 - but->x1) / (cumap->curr.xmax - cumap->curr.xmin);
-       zoomy = (but->y2 - but->y1) / (cumap->curr.ymax - cumap->curr.ymin);
-       /* offsx= cumap->curr.xmin; */
-       /* offsy= cumap->curr.ymin; */
+       zoomx = BLI_rctf_size_x(&but->rect) / BLI_rctf_size_x(&cumap->curr);
+       zoomy = BLI_rctf_size_y(&but->rect) / BLI_rctf_size_y(&cumap->curr);
+       /* offsx = cumap->curr.xmin; */
+       /* offsy = cumap->curr.ymin; */
 
        if (snap) {
                float d[2];
@@ -3608,12 +3761,18 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
        }
 
        if (data->dragsel != -1) {
+               CurveMapPoint *cmp_last = NULL;
+               const float mval_factor = ui_mouse_scale_warp_factor(shift);
                int moved_point = 0;     /* for ctrl grid, can't use orig coords because of sorting */
-               
+
                fx = (mx - data->draglastx) / zoomx;
                fy = (my - data->draglasty) / zoomy;
+
+               fx *= mval_factor;
+               fy *= mval_factor;
+
                for (a = 0; a < cuma->totpoint; a++) {
-                       if (cmp[a].flag & SELECT) {
+                       if (cmp[a].flag & CUMA_SELECT) {
                                float origx = cmp[a].x, origy = cmp[a].y;
                                cmp[a].x += fx;
                                cmp[a].y += fy;
@@ -3623,15 +3782,29 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap,
                                }
                                if (cmp[a].x != origx || cmp[a].y != origy)
                                        moved_point = 1;
+
+                               cmp_last = &cmp[a];
                        }
                }
 
-               curvemapping_changed(cumap, 0); /* no remove doubles */
+               curvemapping_changed(cumap, FALSE);
                
                if (moved_point) {
                        data->draglastx = mx;
                        data->draglasty = my;
                        changed = 1;
+
+#ifdef USE_CONT_MOUSE_CORRECT
+                       /* note: using 'cmp_last' is weak since there may be multiple points selected,
+                        * but in practice this isnt really an issue */
+                       if (ui_is_a_warp_but(but)) {
+                               /* OK but can go outside bounds */
+                               data->ungrab_mval[0] = but->rect.xmin + ((cmp_last->x - cumap->curr.xmin) * zoomx);
+                               data->ungrab_mval[1] = but->rect.ymin + ((cmp_last->y - cumap->curr.ymin) * zoomy);
+                               BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval);
+                       }
+#endif
+
                }
 
                data->dragchange = 1; /* mark for selection */
@@ -3683,25 +3856,25 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
                        float dist, mindist = 200.0f; // 14 pixels radius
                        int sel = -1;
 
-                       zoomx = (but->x2 - but->x1) / (cumap->curr.xmax - cumap->curr.xmin);
-                       zoomy = (but->y2 - but->y1) / (cumap->curr.ymax - cumap->curr.ymin);
+                       zoomx = BLI_rctf_size_x(&but->rect) / BLI_rctf_size_x(&cumap->curr);
+                       zoomy = BLI_rctf_size_y(&but->rect) / BLI_rctf_size_y(&cumap->curr);
                        offsx = cumap->curr.xmin;
                        offsy = cumap->curr.ymin;
 
                        if (event->ctrl) {
-                               fx = ((float)my - but->x1) / zoomx + offsx;
-                               fy = ((float)my - but->y1) / zoomy + offsy;
+                               fx = ((float)mx - but->rect.xmin) / zoomx + offsx;
+                               fy = ((float)my - but->rect.ymin) / zoomy + offsy;
                                
                                curvemap_insert(cuma, fx, fy);
-                               curvemapping_changed(cumap, 0);
+                               curvemapping_changed(cumap, FALSE);
                                changed = 1;
                        }
 
                        /* check for selecting of a point */
                        cmp = cuma->curve;   /* ctrl adds point, new malloc */
                        for (a = 0; a < cuma->totpoint; a++) {
-                               fx = but->x1 + zoomx * (cmp[a].x - offsx);
-                               fy = but->y1 + zoomy * (cmp[a].y - offsy);
+                               fx = but->rect.xmin + zoomx * (cmp[a].x - offsx);
+                               fy = but->rect.ymin + zoomy * (cmp[a].y - offsy);
                                dist = (fx - mx) * (fx - mx) + (fy - my) * (fy - my);
                                if (dist < mindist) {
                                        sel = a;
@@ -3714,24 +3887,24 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
 
                                /* if the click didn't select anything, check if it's clicked on the 
                                 * curve itself, and if so, add a point */
-                               fx = ((float)mx - but->x1) / zoomx + offsx;
-                               fy = ((float)my - but->y1) / zoomy + offsy;
+                               fx = ((float)mx - but->rect.xmin) / zoomx + offsx;
+                               fy = ((float)my - but->rect.ymin) / zoomy + offsy;
                                
                                cmp = cuma->table;
 
                                /* loop through the curve segment table and find what's near the mouse.
                                 * 0.05 is kinda arbitrary, but seems to be what works nicely. */
                                for (i = 0; i <= CM_TABLE; i++) {
-                                       if ( (fabsf(fx - cmp[i].x) < 0.05f) &&
-                                            (fabsf(fy - cmp[i].y) < 0.05f))
+                                       if ((fabsf(fx - cmp[i].x) < 0.05f) &&
+                                           (fabsf(fy - cmp[i].y) < 0.05f))
                                        {
                                        
                                                curvemap_insert(cuma, fx, fy);
-                                               curvemapping_changed(cumap, 0);
+                                               curvemapping_changed(cumap, FALSE);
 
                                                changed = 1;
                                                
-                                               /* reset cmp back to the curve points again, rather than drawing segments */            
+                                               /* reset cmp back to the curve points again, rather than drawing segments */
                                                cmp = cuma->curve;
                                                
                                                /* find newly added point and make it 'sel' */
@@ -3748,16 +3921,18 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
                                /* ok, we move a point */
                                /* deselect all if this one is deselect. except if we hold shift */
                                if (event->shift == FALSE) {
-                                       for (a = 0; a < cuma->totpoint; a++)
-                                               cmp[a].flag &= ~SELECT;
-                                       cmp[sel].flag |= SELECT;
+                                       for (a = 0; a < cuma->totpoint; a++) {
+                                               cmp[a].flag &= ~CUMA_SELECT;
+                                       }
+                                       cmp[sel].flag |= CUMA_SELECT;
+                               }
+                               else {
+                                       cmp[sel].flag ^= CUMA_SELECT;
                                }
-                               else
-                                       cmp[sel].flag ^= SELECT;
                        }
                        else {
                                /* move the view */
-                               data->cancel = 1;
+                               data->cancel = TRUE;
                        }
 
                        data->dragsel = sel;
@@ -3774,7 +3949,7 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
        else if (data->state == BUTTON_STATE_NUM_EDITING) {
                if (event->type == MOUSEMOVE) {
                        if (mx != data->draglastx || my != data->draglasty) {
-                               if (ui_numedit_but_CURVE(but, data, event->ctrl, mx, my))
+                               if (ui_numedit_but_CURVE(but, data, event->ctrl, mx, my, event->shift))
                                        ui_numedit_apply(C, block, but, data);
                        }
                }
@@ -3788,12 +3963,13 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
                                        /* deselect all, select one */
                                        if (event->shift == FALSE) {
                                                for (a = 0; a < cuma->totpoint; a++)
-                                                       cmp[a].flag &= ~SELECT;
-                                               cmp[data->dragsel].flag |= SELECT;
+                                                       cmp[a].flag &= ~CUMA_SELECT;
+                                               cmp[data->dragsel].flag |= CUMA_SELECT;
                                        }
                                }
-                               else
-                                       curvemapping_changed(cumap, 1);  /* remove doubles */
+                               else {
+                                       curvemapping_changed(cumap, TRUE);  /* remove doubles */
+                               }
                        }
 
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
@@ -3810,8 +3986,8 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt
 
 static int in_scope_resize_zone(uiBut *but, int UNUSED(x), int y)
 {
-       // bottom corner return (x > but->x2 - SCOPE_RESIZE_PAD) && (y < but->y1 + SCOPE_RESIZE_PAD);
-       return (y < but->y1 + SCOPE_RESIZE_PAD);
+       /* bottom corner return (x > but->rect.xmax - SCOPE_RESIZE_PAD) && (y < but->rect.ymin + SCOPE_RESIZE_PAD); */
+       return (y < but->rect.ymin + SCOPE_RESIZE_PAD);
 }
 
 static int ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int mx, int my)
@@ -3819,25 +3995,24 @@ static int ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int mx
        Histogram *hist = (Histogram *)but->poin;
        /* rcti rect; */
        int changed = 1;
-       float /* dx, */ dy, yfac = 1.f; /* UNUSED */
+       float /* dx, */ dy; /* UNUSED */
        
-       /* rect.xmin = but->x1; rect.xmax = but->x2; */
-       /* rect.ymin = but->y1; rect.ymax = but->y2; */
+       /* BLI_rcti_rctf_copy(&rect, &but->rect); */
        
        /* dx = mx - data->draglastx; */ /* UNUSED */
        dy = my - data->draglasty;
-       
-       
+
        if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
                /* resize histogram widget itself */
-               hist->height = (but->y2 - but->y1) + (data->dragstarty - my);
+               hist->height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my);
        }
        else {
-               /* scale histogram values */
-               yfac = MIN2(powf(hist->ymax, 2.f), 1.f) * 0.5f;
-               hist->ymax += dy * yfac;
+               /* scale histogram values (dy / 10 for better control) */
+               const float yfac = min_ff(powf(hist->ymax, 2.0f), 1.0f) * 0.5f;
+               hist->ymax += (dy * 0.1f) * yfac;
        
-               CLAMP(hist->ymax, 1.f, 100.f);
+               /* 0.1 allows us to see HDR colors up to 10 */
+               CLAMP(hist->ymax, 0.1f, 100.f);
        }
        
        data->draglastx = mx;
@@ -3879,8 +4054,8 @@ static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandle
        }
        else if (data->state == BUTTON_STATE_NUM_EDITING) {
                if (event->type == ESCKEY) {
-                       data->cancel = 1;
-                       data->escapecancel = 1;
+                       data->cancel = TRUE;
+                       data->escapecancel = TRUE;
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                }
                else if (event->type == MOUSEMOVE) {
@@ -3903,10 +4078,9 @@ static int ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx,
        Scopes *scopes = (Scopes *)but->poin;
        /* rcti rect; */
        int changed = 1;
-       float /* dx, */ dy /* , yfac=1.f */; /* UNUSED */
+       float /* dx, */ dy /* , yfac =1.0f */; /* UNUSED */
 
-       /* rect.xmin = but->x1; rect.xmax = but->x2; */
-       /* rect.ymin = but->y1; rect.ymax = but->y2; */
+       /* BLI_rcti_rctf_copy(&rect, &but->rect); */
 
        /* dx = mx - data->draglastx; */ /* UNUSED */
        dy = my - data->draglasty;
@@ -3914,7 +4088,7 @@ static int ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx,
 
        if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
                /* resize waveform widget itself */
-               scopes->wavefrm_height = (but->y2 - but->y1) + (data->dragstarty - my);
+               scopes->wavefrm_height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my);
        }
        else {
                /* scale waveform values */
@@ -3963,8 +4137,8 @@ static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleB
        }
        else if (data->state == BUTTON_STATE_NUM_EDITING) {
                if (event->type == ESCKEY) {
-                       data->cancel = 1;
-                       data->escapecancel = 1;
+                       data->cancel = TRUE;
+                       data->escapecancel = TRUE;
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                }
                else if (event->type == MOUSEMOVE) {
@@ -3989,15 +4163,14 @@ static int ui_numedit_but_VECTORSCOPE(uiBut *but, uiHandleButtonData *data, int
        int changed = 1;
        /* float dx, dy; */
 
-       /* rect.xmin = but->x1; rect.xmax = but->x2; */
-       /* rect.ymin = but->y1; rect.ymax = but->y2; */
+       /* BLI_rcti_rctf_copy(&rect, &but->rect); */
 
        /* dx = mx - data->draglastx; */
        /* dy = my - data->draglasty; */
 
        if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
                /* resize vectorscope widget itself */
-               scopes->vecscope_height = (but->y2 - but->y1) + (data->dragstarty - my);
+               scopes->vecscope_height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my);
        }
 
        data->draglastx = mx;
@@ -4031,8 +4204,8 @@ static int ui_do_but_VECTORSCOPE(bContext *C, uiBlock *block, uiBut *but, uiHand
        }
        else if (data->state == BUTTON_STATE_NUM_EDITING) {
                if (event->type == ESCKEY) {
-                       data->cancel = 1;
-                       data->escapecancel = 1;
+                       data->cancel = TRUE;
+                       data->escapecancel = TRUE;
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                }
                else if (event->type == MOUSEMOVE) {
@@ -4067,17 +4240,17 @@ static int ui_do_but_CHARTAB(bContext *UNUSED(C), uiBlock *UNUSED(block), uiBut
        if (data->state == BUTTON_STATE_HIGHLIGHT) {
                if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
                        /* Calculate the size of the button */
-                       width = abs(but->x2 - but->x1);
-                       height = abs(but->y2 - but->y1);
+                       width  = abs(BLI_rctf_size_x(&but->rect));
+                       height = abs(BLI_rctf_size_y(&but->rect));
 
                        butw = floor(width / 12);
                        buth = floor(height / 6);
 
                        /* Initialize variables */
-                       sx = but->x1;
-                       ex = but->x1 + butw;
-                       sy = but->y1 + height - buth;
-                       ey = but->y1 + height;
+                       sx = but->rect.xmin;
+                       ex = but->rect.xmin + butw;
+                       sy = but->rect.ymin + height - buth;
+                       ey = but->rect.ymin + height;
 
                        cs = G.charstart;
 
@@ -4174,7 +4347,7 @@ static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, wmE
                
                if (event->type == LEFTMOUSE && event->val != KM_PRESS) {
                        if (!(but->flag & UI_SELECT))
-                               data->cancel = 1;
+                               data->cancel = TRUE;
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                        return WM_UI_HANDLER_BREAK;
                }
@@ -4183,7 +4356,8 @@ static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, wmE
        return WM_UI_HANDLER_CONTINUE;
 }
 
-static int ui_numedit_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonData *data, int mx, int my, int shift)
+static int ui_numedit_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonData *data,
+                                       int mx, int my, const short shift)
 {
        MovieClipScopes *scopes = (MovieClipScopes *)but->poin;
        int changed = 1;
@@ -4199,16 +4373,16 @@ static int ui_numedit_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonDa
 
        if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) {
                /* resize preview widget itself */
-               scopes->track_preview_height = (but->y2 - but->y1) + (data->dragstarty - my);
+               scopes->track_preview_height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my);
        }
        else {
-               if (scopes->marker) {
+               if (!scopes->track_locked) {
                        if (scopes->marker->framenr != scopes->framenr)
-                               scopes->marker = BKE_tracking_ensure_marker(scopes->track, scopes->framenr);
+                               scopes->marker = BKE_tracking_marker_ensure(scopes->track, scopes->framenr);
 
                        scopes->marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED);
-                       scopes->marker->pos[0] += -dx * scopes->slide_scale[0] / (but->block->maxx - but->block->minx);
-                       scopes->marker->pos[1] += -dy * scopes->slide_scale[1] / (but->block->maxy - but->block->miny);
+                       scopes->marker->pos[0] += -dx * scopes->slide_scale[0] / BLI_rctf_size_x(&but->block->rect);
+                       scopes->marker->pos[1] += -dy * scopes->slide_scale[1] / BLI_rctf_size_y(&but->block->rect);
 
                        WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
                }
@@ -4247,8 +4421,8 @@ static int ui_do_but_TRACKPREVIEW(bContext *C, uiBlock *block, uiBut *but, uiHan
        }
        else if (data->state == BUTTON_STATE_NUM_EDITING) {
                if (event->type == ESCKEY) {
-                       data->cancel = 1;
-                       data->escapecancel = 1;
+                       data->cancel = TRUE;
+                       data->escapecancel = TRUE;
                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                }
                else if (event->type == MOUSEMOVE) {
@@ -4334,11 +4508,11 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
        int kmi_id;
        
        /* XXX this guess_opname can potentially return a different keymap than being found on adding later... */
-       km = WM_keymap_guess_opname(C, but->optype->idname);            
+       km = WM_keymap_guess_opname(C, but->optype->idname);
        kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0);
        kmi_id = kmi->id;
 
-       /* copy properties, prop can be NULL for reset */       
+       /* copy properties, prop can be NULL for reset */
        if (prop)
                prop = IDP_CopyProperty(prop);
        WM_keymap_properties_reset(kmi, prop);
@@ -4346,7 +4520,7 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
        /* update and get pointers again */
        WM_keyconfig_update(wm);
 
-       km = WM_keymap_guess_opname(C, but->optype->idname);            
+       km = WM_keymap_guess_opname(C, but->optype->idname);
        kmi = WM_keymap_item_find_id(km, kmi_id);
 
        RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
@@ -4397,26 +4571,27 @@ static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
 
 static int ui_but_menu(bContext *C, uiBut *but)
 {
+       ARegion *ar = CTX_wm_region(C);
        uiPopupMenu *pup;
        uiLayout *layout;
        int length;
-       const char *name;
+       char *name;
+       uiStringInfo label = {BUT_GET_LABEL, NULL};
 
-       if ((but->rnapoin.data && but->rnaprop) == 0 && but->optype == NULL)
-               return 0;
+/*     if ((but->rnapoin.data && but->rnaprop) == 0 && but->optype == NULL)*/
+/*             return 0;*/
        
        button_timers_tooltip_remove(C, but);
 
-       if (but->rnaprop)
-               name = RNA_property_ui_name(but->rnaprop);
-       else if (but->optype && but->optype->srna)
-               name = RNA_struct_ui_name(but->optype->srna);
-       else
-               name = IFACE_("<needs_name>");  // XXX - should never happen.
+       uiButGetStrInfo(C, but, 1, &label);
+       name = label.strinfo;
 
        pup = uiPupMenuBegin(C, name, ICON_NONE);
        layout = uiPupMenuLayout(pup);
-       
+
+       if (label.strinfo)
+               MEM_freeN(label.strinfo);
+
        uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
 
        if (but->rnapoin.data && but->rnaprop) {
@@ -4453,7 +4628,9 @@ static int ui_but_menu(bContext *C, uiBut *but)
                        
                        
                }
-               else if (but->flag & UI_BUT_DRIVEN) ;
+               else if (but->flag & UI_BUT_DRIVEN) {
+                       /* pass */
+               }
                else if (is_anim) {
                        if (length) {
                                uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframes"),
@@ -4461,11 +4638,25 @@ static int ui_but_menu(bContext *C, uiBut *but)
                                uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Single Keyframe"),
                                               ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
                        }
-                       else
+                       else {
                                uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"),
                                               ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0);
+                       }
                }
                
+               if (but->flag & UI_BUT_ANIMATED) {
+                       if (length) {
+                               uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
+                                              ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 1);
+                               uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Single Keyframes"),
+                                              ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0);
+                       }
+                       else {
+                               uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"),
+                                              ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0);
+                       }
+               }
+
                /* Drivers */
                if (but->flag & UI_BUT_DRIVEN) {
                        uiItemS(layout);
@@ -4476,17 +4667,21 @@ static int ui_but_menu(bContext *C, uiBut *but)
                                uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Driver"),
                                               ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0);
                        }
-                       else
+                       else {
                                uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Driver"),
                                               ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0);
+                       }
 
                        uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Driver"),
                                ICON_NONE, "ANIM_OT_copy_driver_button");
-                       if (ANIM_driver_can_paste())
+                       if (ANIM_driver_can_paste()) {
                                uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
                                        ICON_NONE, "ANIM_OT_paste_driver_button");
+                       }
+               }
+               else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) {
+                       /* pass */
                }
-               else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) ;
                else if (is_anim) {
                        uiItemS(layout);
 
@@ -4496,17 +4691,19 @@ static int ui_but_menu(bContext *C, uiBut *but)
                                uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single Driver"),
                                               ICON_NONE, "ANIM_OT_driver_button_add", "all", 0);
                        }
-                       else
+                       else {
                                uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"),
                                               ICON_NONE, "ANIM_OT_driver_button_add", "all", 0);
+                       }
 
-                       if (ANIM_driver_can_paste())
+                       if (ANIM_driver_can_paste()) {
                                uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"),
                                        ICON_NONE, "ANIM_OT_paste_driver_button");
+                       }
                }
                
                /* Keying Sets */
-               // TODO: check on modifyability of Keying Set when doing this
+               /* TODO: check on modifyability of Keying Set when doing this */
                if (is_anim) {
                        uiItemS(layout);
 
@@ -4530,8 +4727,8 @@ static int ui_but_menu(bContext *C, uiBut *but)
                
                /* Property Operators */
                
-               //Copy Property Value
-               //Paste Property Value
+               /Copy Property Value
+                * Paste Property Value */
                
                if (length) {
                        uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset All to Default Values"),
@@ -4539,9 +4736,10 @@ static int ui_but_menu(bContext *C, uiBut *but)
                        uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Single to Default Value"),
                                       ICON_NONE, "UI_OT_reset_default_button", "all", 0);
                }
-               else
+               else {
                        uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"),
                                ICON_NONE, "UI_OT_reset_default_button");
+               }
                
                uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"),
                        ICON_NONE, "UI_OT_copy_data_path_button");
@@ -4567,7 +4765,7 @@ static int ui_but_menu(bContext *C, uiBut *but)
                /* keyboard shortcuts */
                if ((kmi) && ISKEYBOARD(kmi->type)) {
 
-                       // would rather use a block but, but gets weirdly positioned...
+                       /* would rather use a block but, but gets weirdly positioned... */
                        //uiDefBlockBut(block, menu_change_shortcut, but, "Change Shortcut", 0, 0, uiLayoutGetWidth(layout), UI_UNIT_Y, "");
                        
                        but2 = uiDefIconTextBut(block, BUT, 0, 0, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"),
@@ -4588,7 +4786,12 @@ static int ui_but_menu(bContext *C, uiBut *but)
                uiItemS(layout);
        }
 
-       
+       /* Show header tools for header buttons. */
+       if (ar->regiontype == RGN_TYPE_HEADER) {
+               uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL);
+               uiItemS(layout);
+       }
+
        {   /* Docs */
                char buf[512];
                PointerRNA ptr_props;
@@ -4604,7 +4807,7 @@ static int ui_but_menu(bContext *C, uiBut *but)
 
                        WM_operator_properties_create(&ptr_props, "WM_OT_doc_view");
                        RNA_string_set(&ptr_props, "doc_id", buf);
-                       uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Python Documentation"),
+                       uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
                                    ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
 
                        /* XXX inactive option, not for public! */
@@ -4627,7 +4830,7 @@ static int ui_but_menu(bContext *C, uiBut *but)
 
                        WM_operator_properties_create(&ptr_props, "WM_OT_doc_view");
                        RNA_string_set(&ptr_props, "doc_id", buf);
-                       uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Python Documentation"),
+                       uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
                                    ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
 
                        /* XXX inactive option, not for public! */
@@ -4643,8 +4846,8 @@ static int ui_but_menu(bContext *C, uiBut *but)
        }
 
        /* perhaps we should move this into (G.debug & G_DEBUG) - campbell */
-       uiItemFullO(layout, "UI_OT_editsource", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Edit Source"),
-                   ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0);
+       uiItemFullO(layout, "UI_OT_editsource", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0);
+       uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0);
 
        uiPupMenuEnd(C, pup);
 
@@ -4653,7 +4856,6 @@ static int ui_but_menu(bContext *C, uiBut *but)
 
 static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
 {
-//     Scene *scene= CTX_data_scene(C);
        uiHandleButtonData *data;
        int retval;
 
@@ -4679,18 +4881,31 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
                        ui_but_drop(C, event, but, data);
                }
                /* handle keyframing */
-               else if (event->type == IKEY && !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
-                       if (event->alt)
-                               ui_but_anim_delete_keyframe(C);
-                       else
+               else if ((event->type == IKEY) &&
+                        !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey) &&
+                        (event->val == KM_PRESS))
+               {
+                       if (event->alt) {
+                               if (event->shift) {
+                                       ui_but_anim_clear_keyframe(C);
+                               }
+                               else {
+                                       ui_but_anim_delete_keyframe(C);
+                               }
+                       }
+                       else {
                                ui_but_anim_insert_keyframe(C);
+                       }
                        
                        ED_region_tag_redraw(CTX_wm_region(C));
                        
                        return WM_UI_HANDLER_BREAK;
                }
                /* handle drivers */
-               else if (event->type == DKEY && !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
+               else if ((event->type == DKEY) &&
+                        !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
+                        (event->val == KM_PRESS))
+               {
                        if (event->alt)
                                ui_but_anim_remove_driver(C);
                        else
@@ -4701,7 +4916,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
                        return WM_UI_HANDLER_BREAK;
                }
                /* handle keyingsets */
-               else if (event->type == KKEY && !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) {
+               else if ((event->type == KKEY) &&
+                        !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) &&
+                        (event->val == KM_PRESS))
+               {
                        if (event->alt)
                                ui_but_anim_remove_keyingset(C);
                        else
@@ -4730,13 +4948,13 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
        /* verify if we can edit this button */
        if (ELEM(event->type, LEFTMOUSE, RETKEY)) {
                /* this should become disabled button .. */
-               if (but->lock) {
+               if (but->lock == TRUE) {
                        if (but->lockstr) {
                                BKE_report(NULL, RPT_WARNING, but->lockstr);
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                                return WM_UI_HANDLER_BREAK;
                        }
-               } 
+               }
                else if (but->pointype && but->poin == NULL) {
                        /* there's a pointer needed */
                        BKE_reportf(NULL, RPT_WARNING, "DoButton pointer error: %s", but->str);
@@ -4812,8 +5030,8 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
                case BUTM:
                        retval = ui_do_but_BUT(C, but, data, event);
                        break;
-               case COL:
-                       if (but->a1 == UI_GRAD_V_ALT) // signal to prevent calling up color picker
+               case COLOR:
+                       if (but->a1 == UI_GRAD_V_ALT)  /* signal to prevent calling up color picker */
                                retval = ui_do_but_EXIT(C, but, data, event);
                        else
                                retval = ui_do_but_BLOCK(C, but, data, event);
@@ -4837,6 +5055,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
                case CHARTAB:
                        retval = ui_do_but_CHARTAB(C, block, but, data, event);
                        break;
+#else
+                       /* do nothing */
+               case CHARTAB:
+                       break;
 #endif
 
                case LINK:
@@ -4846,6 +5068,11 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
                case TRACKPREVIEW:
                        retval = ui_do_but_TRACKPREVIEW(C, block, but, data, event);
                        break;
+
+                       /* quiet warnings for unhandled types */
+               case SEPR:
+               case BUT_EXTRA:
+                       break;
        }
        
        return retval;
@@ -4855,7 +5082,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
 
 static int ui_but_contains_pt(uiBut *but, int mx, int my)
 {
-       return ((but->x1 < mx && but->x2 >= mx) && (but->y1 < my && but->y2 >= my));
+       return BLI_rctf_isect_pt(&but->rect, mx, my);
 }
 
 static uiBut *ui_but_find_activated(ARegion *ar)
@@ -4931,7 +5158,7 @@ static int ui_mouse_inside_region(ARegion *ar, int x, int y)
        uiBlock *block;
        
        /* check if the mouse is in the region */
-       if (!BLI_in_rcti(&ar->winrct, x, y)) {
+       if (!BLI_rcti_isect_pt(&ar->winrct, x, y)) {
                for (block = ar->uiblocks.first; block; block = block->next)
                        block->auto_open = FALSE;
                
@@ -4954,10 +5181,7 @@ static int ui_mouse_inside_region(ARegion *ar, int x, int y)
                ui_window_to_region(ar, &mx, &my);
                
                /* make a copy of the mask rect, and tweak accordingly for hidden scrollbars */
-               mask_rct.xmin = v2d->mask.xmin;
-               mask_rct.xmax = v2d->mask.xmax;
-               mask_rct.ymin = v2d->mask.ymin;
-               mask_rct.ymax = v2d->mask.ymax;
+               mask_rct = v2d->mask;
                
                if (v2d->scroll & (V2D_SCROLL_VERTICAL_HIDE | V2D_SCROLL_VERTICAL_FULLR)) {
                        if (v2d->scroll & V2D_SCROLL_LEFT)
@@ -4973,7 +5197,7 @@ static int ui_mouse_inside_region(ARegion *ar, int x, int y)
                }
                
                /* check if in the rect */
-               if (!BLI_in_rcti(&mask_rct, mx, my)) 
+               if (!BLI_rcti_isect_pt(&mask_rct, mx, my)) 
                        return 0;
        }
        
@@ -5010,7 +5234,7 @@ static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
                ui_window_to_block(ar, block, &mx, &my);
 
                for (but = block->buttons.first; but; but = but->next) {
-                       /* note, LABEL is included for hilights, this allows drags */
+                       /* note, LABEL is included for highlights, this allows drags */
                        if (but->type == LABEL && but->dragpoin == NULL)
                                continue;
                        if (ELEM3(but->type, ROUNDBOX, SEPR, LISTBOX))
@@ -5026,9 +5250,7 @@ static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
                /* CLIP_EVENTS prevents the event from reaching other blocks */
                if (block->flag & UI_BLOCK_CLIP_EVENTS) {
                        /* check if mouse is inside block */
-                       if (block->minx <= mx && block->maxx >= mx &&
-                           block->miny <= my && block->maxy >= my)
-                       {
+                       if (BLI_rctf_isect_pt(&block->rect, mx, my)) {
                                break;
                        }
                }
@@ -5130,13 +5352,22 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
                        if (data->used_mouse && !data->autoopentimer) {
                                int time;
 
-                               if (but->block->auto_open == TRUE) time = 1;  // test for toolbox
-                               else if ((but->block->flag & UI_BLOCK_LOOP && but->type != BLOCK) || but->block->auto_open == TRUE) time = 5 * U.menuthreshold2;
-                               else if (U.uiflag & USER_MENUOPENAUTO) time = 5 * U.menuthreshold1;
-                               else time = -1;
+                               if (but->block->auto_open == TRUE) {  /* test for toolbox */
+                                       time = 1;
+                               }
+                               else if ((but->block->flag & UI_BLOCK_LOOP && but->type != BLOCK) || but->block->auto_open == TRUE) {
+                                       time = 5 * U.menuthreshold2;
+                               }
+                               else if (U.uiflag & USER_MENUOPENAUTO) {
+                                       time = 5 * U.menuthreshold1;
+                               }
+                               else {
+                                       time = -1;  /* do nothing */
+                               }
 
-                               if (time >= 0)
+                               if (time >= 0) {
                                        data->autoopentimer = WM_event_add_timer(data->wm, data->window, TIMER, 0.02 * (double)time);
+                               }
                        }
                }
        }
@@ -5156,13 +5387,29 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
        /* number editing */
        if (state == BUTTON_STATE_NUM_EDITING) {
                if (ui_is_a_warp_but(but))
-                       WM_cursor_grab(CTX_wm_window(C), TRUE, TRUE, NULL);
+                       WM_cursor_grab_enable(CTX_wm_window(C), TRUE, TRUE, NULL);
                ui_numedit_begin(but, data);
        }
        else if (data->state == BUTTON_STATE_NUM_EDITING) {
                ui_numedit_end(but, data);
-               if (ui_is_a_warp_but(but))
-                       WM_cursor_ungrab(CTX_wm_window(C));
+               if (ui_is_a_warp_but(but)) {
+
+#ifdef USE_CONT_MOUSE_CORRECT
+                       if (data->ungrab_mval[0] != FLT_MAX) {
+                               int mouse_ungrab_xy[2];
+                               ui_block_to_window_fl(data->region, but->block, &data->ungrab_mval[0], &data->ungrab_mval[1]);
+                               mouse_ungrab_xy[0] = data->ungrab_mval[0];
+                               mouse_ungrab_xy[1] = data->ungrab_mval[1];
+
+                               WM_cursor_grab_disable(data->window, mouse_ungrab_xy);
+                       }
+                       else {
+                               WM_cursor_grab_disable(data->window, NULL);
+                       }
+#else
+                       WM_cursor_grab_disable(data->window, );
+#endif
+               }
        }
        /* menu open */
        if (state == BUTTON_STATE_MENU_OPEN)
@@ -5224,8 +5471,17 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA
        data->wm = CTX_wm_manager(C);
        data->window = CTX_wm_window(C);
        data->region = ar;
-       if (ELEM(but->type, BUT_CURVE, SEARCH_MENU) ) ;  // XXX curve is temp
-       else data->interactive = 1;
+
+#ifdef USE_CONT_MOUSE_CORRECT
+       copy_v2_fl(data->ungrab_mval, FLT_MAX);
+#endif
+
+       if (ELEM(but->type, BUT_CURVE, SEARCH_MENU)) {
+               /* XXX curve is temp */
+       }
+       else {
+               data->interactive = TRUE;
+       }
        
        data->state = BUTTON_STATE_INIT;
 
@@ -5353,7 +5609,7 @@ void ui_button_active_free(const bContext *C, uiBut *but)
         * case cleanly anyway in case it happens */
        if (but->active) {
                data = but->active;
-               data->cancel = 1;
+               data->cancel = TRUE;
                button_activate_exit((bContext *)C, data, but, 0, 1);
        }
 }
@@ -5501,20 +5757,24 @@ void uiContextAnimUpdate(const bContext *C)
                                ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f);
                                ED_region_tag_redraw(ar);
                                
-                               if (but->active)
+                               if (but->active) {
                                        activebut = but;
-                               else if (!activebut && (but->flag & UI_BUT_LAST_ACTIVE))
+                               }
+                               else if (!activebut && (but->flag & UI_BUT_LAST_ACTIVE)) {
                                        activebut = but;
+                               }
                        }
                }
 
                if (activebut) {
                        /* always recurse into opened menu, so all buttons update (like colorpicker) */
                        uiHandleButtonData *data = activebut->active;
-                       if (data && data->menu)
+                       if (data && data->menu) {
                                ar = data->menu->region;
-                       else
+                       }
+                       else {
                                return;
+                       }
                }
                else {
                        /* no active button */
@@ -5544,8 +5804,9 @@ static int ui_handle_button_over(bContext *C, wmEvent *event, ARegion *ar)
 
        if (event->type == MOUSEMOVE) {
                but = ui_but_find_mouse_over(ar, event->x, event->y);
-               if (but)
+               if (but) {
                        button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER);
+               }
        }
        else if (event->type == EVT_BUT_OPEN) {
                but = uit_but_find_open_event(ar, event);
@@ -5583,7 +5844,7 @@ static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiBu
        oldbut = ui_but_find_activated(ar);
        if (oldbut) {
                data = oldbut->active;
-               data->cancel = 1;
+               data->cancel = TRUE;
                button_activate_exit(C, data, oldbut, 0, 0);
        }
 
@@ -5611,18 +5872,18 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
                switch (event->type) {
                        case WINDEACTIVATE:
                        case EVT_BUT_CANCEL:
-                               data->cancel = 1;
+                               data->cancel = TRUE;
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                                retval = WM_UI_HANDLER_CONTINUE;
                                break;
                        case MOUSEMOVE:
                                /* verify if we are still over the button, if not exit */
                                if (!ui_mouse_inside_button(ar, but, event->x, event->y)) {
-                                       data->cancel = 1;
+                                       data->cancel = TRUE;
                                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                                }
                                else if (ui_but_find_mouse_over(ar, event->x, event->y) != but) {
-                                       data->cancel = 1;
+                                       data->cancel = TRUE;
                                        button_activate_state(C, but, BUTTON_STATE_EXIT);
                                }
                                else if (event->x != event->prevx || event->y != event->prevy) {
@@ -5632,7 +5893,8 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
                                }
 
                                break;
-                       case TIMER: {
+                       case TIMER:
+                       {
                                /* handle tooltip timer */
                                if (event->customdata == data->tooltiptimer) {
                                        WM_event_remove_timer(data->wm, data->window, data->tooltiptimer);
@@ -5670,7 +5932,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
        else if (data->state == BUTTON_STATE_WAIT_RELEASE) {
                switch (event->type) {
                        case WINDEACTIVATE:
-                               data->cancel = 1;
+                               data->cancel = TRUE;
                                button_activate_state(C, but, BUTTON_STATE_EXIT);
                                break;
 
@@ -5686,18 +5948,18 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
                                        if (ui_mouse_inside_button(ar, but, event->x, event->y)) {
                                                if (!(but->flag & UI_SELECT)) {
                                                        but->flag |= (UI_SELECT | UI_ACTIVE);
-                                                       data->cancel = 0;
+                                                       data->cancel = FALSE;
                                                        ED_region_tag_redraw(data->region);
                                                }
                                        }
                                        else {
                                                if (but->flag & UI_SELECT) {
                                                        but->flag &= ~(UI_SELECT | UI_ACTIVE);
-                                                       data->cancel = 1;
+                                                       data->cancel = TRUE;
                                                        ED_region_tag_redraw(data->region);
                                                }
                                        }
-                               }                               
+                               }
                                break;
                        default:
                                /* otherwise catch mouse release event */
@@ -5709,9 +5971,11 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
        }
        else if (data->state == BUTTON_STATE_WAIT_FLASH) {
                switch (event->type) {
-                       case TIMER: {
-                               if (event->customdata == data->flashtimer)
+                       case TIMER:
+                       {
+                               if (event->customdata == data->flashtimer) {
                                        button_activate_state(C, but, BUTTON_STATE_EXIT);
+                               }
                        }
                }
 
@@ -5721,21 +5985,41 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
                /* check for exit because of mouse-over another button */
                switch (event->type) {
                        case MOUSEMOVE:
-                               
-                               if (data->menu && data->menu->region)
-                                       if (ui_mouse_inside_region(data->menu->region, event->x, event->y))
+                       {
+                               /* if the mouse is over the button, do nothing */
+                               if (ui_mouse_inside_button(data->region, but, event->x, event->y)) {
+                                       break;
+                               }
+
+                               /* if the mouse is over the menu, also do nothing */
+                               if (data->menu && data->menu->region) {
+                                       if (ui_mouse_inside_region(data->menu->region, event->x, event->y)) {
                                                break;
-                       
-                               {
-                                       uiBut *bt = ui_but_find_mouse_over(ar, event->x, event->y);
+                                       }
+                                       else {
+                                               /* make a rectangle between the menu and the button that opened it,
+                                                * this avoids any space between them exiting the popup. see [#29072] - campbell */
+                                               rctf rct_all = but->rect;
+                                               rctf rct_win;
+
+                                               ui_block_to_window_fl(ar, block, &rct_all.xmin, &rct_all.ymin);
+                                               ui_block_to_window_fl(ar, block, &rct_all.xmax, &rct_all.ymax);
+
+                                               BLI_rctf_rcti_copy(&rct_win, &data->menu->region->winrct);
+                                               BLI_rctf_union(&rct_all, &rct_win);
 
-                                       if (bt && bt->active != data) {
-                                               if (but->type != COL) /* exception */
-                                                       data->cancel = 1;
-                                               button_activate_state(C, but, BUTTON_STATE_EXIT);
+                                               if (BLI_rctf_isect_pt(&rct_all, event->x, event->y)) {
+                                                       break;
+                                               }
                                        }
-                                       break;
                                }
+
+                               if (but->type != COLOR) {  /* exception */
+                                       data->cancel = TRUE;
+                               }
+                               button_activate_state(C, but, BUTTON_STATE_EXIT);
+                               break;
+                       }
                }
 
                ui_do_button(C, block, but, event);
@@ -5743,7 +6027,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but)
        }
        else {
                retval = ui_do_button(C, block, but, event);
-               // retval= WM_UI_HANDLER_BREAK; XXX why ? 
+               // retval = WM_UI_HANDLER_BREAK; XXX why ?
        }
 
        if (data->state == BUTTON_STATE_EXIT) {
@@ -5780,6 +6064,8 @@ static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
                        else
                                value++;
 
+                       CLAMP(value, 0, pa->list_last_len - 1);
+
                        if (value < pa->list_scroll)
                                pa->list_scroll = value;
                        else if (value >= pa->list_scroll + pa->list_size)
@@ -5838,15 +6124,19 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut *
 
        /* copy over return values from the closing menu */
        if ((menu->menuretval & UI_RETURN_OK) || (menu->menuretval & UI_RETURN_UPDATE)) {
-               if (but->type == COL)
+               if (but->type == COLOR)
                        copy_v3_v3(data->vec, menu->retvec);
                else if (ELEM3(but->type, MENU, ICONROW, ICONTEXTROW))
                        data->value = menu->retvalue;
        }
 
        if (menu->menuretval & UI_RETURN_UPDATE) {
-               if (data->interactive) ui_apply_button(C, but->block, but, data, 1);
-               else ui_check_but(but);
+               if (data->interactive) {
+                       ui_apply_button(C, but->block, but, data, TRUE);
+               }
+               else {
+                       ui_check_but(but);
+               }
 
                menu->menuretval = 0;
        }
@@ -5854,7 +6144,7 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut *
        /* now change button state or exit, which will close the submenu */
        if ((menu->menuretval & UI_RETURN_OK) || (menu->menuretval & UI_RETURN_CANCEL)) {
                if (menu->menuretval != UI_RETURN_OK)
-                       data->cancel = 1;
+                       data->cancel = TRUE;
 
                button_activate_exit(C, data, but, 1, 0);
        }
@@ -5869,7 +6159,7 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut *
                                button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT);
                        }
                        else {
-                               data->cancel = 1;
+                               data->cancel = TRUE;
                                button_activate_exit(C, data, but, 1, 0);
                        }
                }
@@ -5890,7 +6180,7 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut *
 static void ui_mouse_motion_towards_init(uiPopupBlockHandle *menu, int mx, int my, int force)
 {
        if (!menu->dotowards || force) {
-               menu->dotowards = 1;
+               menu->dotowards = TRUE;
                menu->towardsx = mx;
                menu->towardsy = my;
 
@@ -5906,22 +6196,24 @@ static int ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *men
        float p1[2], p2[2], p3[2], p4[2], oldp[2], newp[2];
        int closer;
 
-       if (!menu->dotowards) return 0;
+       if (!menu->dotowards) {
+               return 0;
+       }
 
        /* verify that we are moving towards one of the edges of the
         * menu block, in other words, in the triangle formed by the
         * initial mouse location and two edge points. */
-       p1[0] = block->minx - 20;
-       p1[1] = block->miny - 20;
+       p1[0] = block->rect.xmin - 20;
+       p1[1] = block->rect.ymin - 20;
 
-       p2[0] = block->maxx + 20;
-       p2[1] = block->miny - 20;
+       p2[0] = block->rect.xmax + 20;
+       p2[1] = block->rect.ymin - 20;
        
-       p3[0] = block->maxx + 20;
-       p3[1] = block->maxy + 20;
+       p3[0] = block->rect.xmax + 20;
+       p3[1] = block->rect.ymax + 20;
 
-       p4[0] = block->minx - 20;
-       p4[1] = block->maxy + 20;
+       p4[0] = block->rect.xmin - 20;
+       p4[1] = block->rect.ymax + 20;
 
        oldp[0] = menu->towardsx;
        oldp[1] = menu->towardsy;
@@ -5929,21 +6221,20 @@ static int ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *men
        newp[0] = mx;
        newp[1] = my;
 
-       if (len_v2v2(oldp, newp) < 4.0f)
+       if (len_squared_v2v2(oldp, newp) < (4.0f * 4.0f))
                return menu->dotowards;
 
-       closer = 0;
-       closer |= isect_point_tri_v2(newp, oldp, p1, p2);
-       closer |= isect_point_tri_v2(newp, oldp, p2, p3);
-       closer |= isect_point_tri_v2(newp, oldp, p3, p4);
-       closer |= isect_point_tri_v2(newp, oldp, p4, p1);
+       closer = (isect_point_tri_v2(newp, oldp, p1, p2) ||
+                 isect_point_tri_v2(newp, oldp, p2, p3) ||
+                 isect_point_tri_v2(newp, oldp, p3, p4) ||
+                 isect_point_tri_v2(newp, oldp, p4, p1));
 
        if (!closer)
-               menu->dotowards = 0;
+               menu->dotowards = FALSE;
 
        /* 1 second timer */
        if (PIL_check_seconds_timer() - menu->towardstime > BUTTON_MOUSE_TOWARDS_THRESH)
-               menu->dotowards = 0;
+               menu->dotowards = FALSE;
 
        return menu->dotowards;
 }
@@ -5952,10 +6243,10 @@ static char ui_menu_scroll_test(uiBlock *block, int my)
 {
        if (block->flag & (UI_BLOCK_CLIPTOP | UI_BLOCK_CLIPBOTTOM)) {
                if (block->flag & UI_BLOCK_CLIPTOP) 
-                       if (my > block->maxy - 14)
+                       if (my > block->rect.ymax - 14)
                                return 't';
                if (block->flag & UI_BLOCK_CLIPBOTTOM)
-                       if (my < block->miny + 14)
+                       if (my < block->rect.ymin + 14)
                                return 'b';
        }
        return 0;
@@ -5986,25 +6277,25 @@ static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my)
                
                if (test == 't') {
                        /* bottom button is first button */
-                       if (b1->y1 < b2->y1)
-                               dy = bnext->y1 - b1->y1;
+                       if (b1->rect.ymin < b2->rect.ymin)
+                               dy = bnext->rect.ymin - b1->rect.ymin;
                        /* bottom button is last button */
                        else 
-                               dy = bprev->y1 - b2->y1;
+                               dy = bprev->rect.ymin - b2->rect.ymin;
                }
                else if (test == 'b') {
                        /* bottom button is first button */
-                       if (b1->y1 < b2->y1)
-                               dy = b1->y1 - bnext->y1;
+                       if (b1->rect.ymin < b2->rect.ymin)
+                               dy = b1->rect.ymin - bnext->rect.ymin;
                        /* bottom button is last button */
                        else 
-                               dy = b2->y1 - bprev->y1;
+                               dy = b2->rect.ymin - bprev->rect.ymin;
                }
                if (dy) {
                        
                        for (b1 = block->buttons.first; b1; b1 = b1->next) {
-                               b1->y1 -= dy;
-                               b1->y2 -= dy;
+                               b1->rect.ymin -= dy;
+                               b1->rect.ymax -= dy;
                        }
                        /* set flags again */
                        ui_popup_block_scrolltest(block);
@@ -6018,7 +6309,7 @@ static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my)
        return 0;
 }
 
-static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int UNUSED(topmenu))
+static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int level)
 {
        ARegion *ar;
        uiBlock *block;
@@ -6036,10 +6327,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
        ui_window_to_block(ar, block, &mx, &my);
 
        /* check if mouse is inside block */
-       inside = 0;
-       if (block->minx <= mx && block->maxx >= mx)
-               if (block->miny <= my && block->maxy >= my)
-                       inside = 1;
+       inside = BLI_rctf_isect_pt(&block->rect, mx, my);
 
        /* if there's an active modal button, don't check events or outside, except for search menu */
        but = ui_but_find_activated(ar);
@@ -6066,10 +6354,22 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
                }
                
                /* first block own event func */
-               if (block->block_event_func && block->block_event_func(C, block, event)) ;
-               /* events not for active search menu button */
+               if (block->block_event_func && block->block_event_func(C, block, event)) {
+                       /* pass */
+               }   /* events not for active search menu button */
                else if (but == NULL || but->type != SEARCH_MENU) {
                        switch (event->type) {
+
+
+                       /* let the parent menu get the event */
+#define     PASS_EVENT_TO_PARENT_IF_NONACTIVE                                 \
+                               if ((level != 0) && (but == NULL)) {                          \
+                                       menu->menuretval = UI_RETURN_OUT | UI_RETURN_OUT_PARENT;  \
+                                       BLI_assert(retval == WM_UI_HANDLER_CONTINUE);             \
+                                       break;                                                    \
+                               } (void)0
+
+
                                /* closing sublevels of pulldowns */
                                case LEFTARROWKEY:
                                        if (event->val == KM_PRESS && (block->flag & UI_BLOCK_LOOP))
@@ -6080,8 +6380,11 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
                                        break;
 
                                /* opening sublevels of pulldowns */
-                               case RIGHTARROWKEY:     
+                               case RIGHTARROWKEY:
                                        if (event->val == KM_PRESS && (block->flag & UI_BLOCK_LOOP)) {
+
+                                               PASS_EVENT_TO_PARENT_IF_NONACTIVE;
+
                                                but = ui_but_find_activated(ar);
 
                                                if (!but) {
@@ -6102,9 +6405,14 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
                                case WHEELUPMOUSE:
                                case WHEELDOWNMOUSE:
                                        /* arrowkeys: only handle for block_loop blocks */
-                                       if (event->alt || event->shift || event->ctrl || event->oskey) ;
+                                       if (event->alt || event->shift || event->ctrl || event->oskey) {
+                                               /* pass */
+                                       }
                                        else if (inside || (block->flag & UI_BLOCK_LOOP)) {
                                                if (event->val == KM_PRESS) {
+
+                                                       PASS_EVENT_TO_PARENT_IF_NONACTIVE;
+
                                                        but = ui_but_find_activated(ar);
                                                        if (but) {
                                                                /* is there a situation where UI_LEFT or UI_RIGHT would also change navigation direction? */
@@ -6151,8 +6459,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
                                                                        }
                                                                }
 
-                                                               if (bt)
+                                                               if (bt) {
                                                                        ui_handle_button_activate(C, ar, bt, BUTTON_ACTIVATE);
+                                                               }
                                                        }
                                                }
 
@@ -6183,11 +6492,14 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
                                        if (act == 0) act = 10;
 
                                        if ((block->flag & UI_BLOCK_NUMSELECT) && event->val == KM_PRESS) {
+
+                                               PASS_EVENT_TO_PARENT_IF_NONACTIVE;
+
                                                if (event->alt) act += 10;
 
                                                count = 0;
                                                for (but = block->buttons.first; but; but = but->next) {
-                                                       int doit = 0;
+                                                       int doit = FALSE;
                                                        
                                                        if (but->type != LABEL && but->type != SEPR)
                                                                count++;
@@ -6196,19 +6508,29 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
                                                        if (but->rnapoin.data && but->rnaprop) {
                                                                if (ELEM(RNA_property_subtype(but->rnaprop), PROP_LAYER, PROP_LAYER_MEMBER)) {
                                                                        if (but->rnaindex == act - 1)
-                                                                               doit = 1;
+                                                                               doit = TRUE;
                                                                }
                                                        }
                                                        /* exception for menus like layer buts, with button aligning they're not drawn in order */
                                                        else if (but->type == TOGR) {
                                                                if (but->bitnr == act - 1)
-                                                                       doit = 1;
+                                                                       doit = TRUE;
+                                                       }
+                                                       else if (count == act) {
+                                                               doit = TRUE;
                                                        }
-                                                       else if (count == act)
-                                                               doit = 1;
                                                        
                                                        if (doit) {
-                                                               ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_APPLY);
+                                                               /* activate buttons but open menu's */
+                                                               uiButtonActivateType activate;
+                                                               if (but->type == PULLDOWN) {
+                                                                       activate = BUTTON_ACTIVATE_OPEN;
+                                                               }
+                                                               else {
+                                                                       activate = BUTTON_ACTIVATE_APPLY;
+                                                               }
+
+                                                               ui_handle_button_activate(C, ar, but, activate);
                                                                break;
                                                        }
                                                }
@@ -6245,15 +6567,17 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
                                case YKEY:
                                case ZKEY:
                                {
-                                       if ((event->val == KM_PRESS) &&
+                                       if ((event->val   == KM_PRESS) &&
                                            (event->shift == FALSE) &&
-                                           (event->ctrl ==  FALSE) &&
+                                           (event->ctrl  == FALSE) &&
                                            (event->oskey == FALSE))
                                        {
+                                               PASS_EVENT_TO_PARENT_IF_NONACTIVE;
+
                                                for (but = block->buttons.first; but; but = but->next) {
 
                                                        if (but->menu_key == event->type) {
-                                                               if (but->type == BUT) {
+                                                               if (ELEM(but->type, BUT, BUTM)) {
                                                                        /* mainly for operator buttons */
                                                                        ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_APPLY);
                                                                }
@@ -6288,7 +6612,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
                                uiSafetyRct *saferct = block->saferct.first;
 
                                if (ELEM3(event->type, LEFTMOUSE, MIDDLEMOUSE, RIGHTMOUSE) && event->val == KM_PRESS) {
-                                       if (saferct && !BLI_in_rctf(&saferct->parent, event->x, event->y)) {
+                                       if (saferct && !BLI_rctf_isect_pt(&saferct->parent, event->x, event->y)) {
                                                if (block->flag & (UI_BLOCK_OUT_1))
                                                        menu->menuretval = UI_RETURN_OK;
                                                else
@@ -6297,7 +6621,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
                                }
                        }
 
-                       if (menu->menuretval) ;
+                       if (menu->menuretval) {
+                               /* pass */
+                       }
                        else if (event->type == ESCKEY && event->val == KM_PRESS) {
                                /* esc cancels this and all preceding menus */
                                menu->menuretval = UI_RETURN_CANCEL;
@@ -6321,9 +6647,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
                                                 * events we check all preceding block rects too to make
                                                 * arrow keys navigation work */
                                                if (event->type != MOUSEMOVE || saferct == block->saferct.first) {
-                                                       if (BLI_in_rctf(&saferct->parent, (float)event->x, (float)event->y))
+                                                       if (BLI_rctf_isect_pt(&saferct->parent, (float)event->x, (float)event->y))
                                                                break;
-                                                       if (BLI_in_rctf(&saferct->safety, (float)event->x, (float)event->y))
+                                                       if (BLI_rctf_isect_pt(&saferct->safety, (float)event->x, (float)event->y))
                                                                break;
                                                }
                                        }
@@ -6339,6 +6665,10 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
                                                retval = WM_UI_HANDLER_BREAK;
                                }
                        }
+
+                       /* end switch */
+#undef PASS_EVENT_TO_PARENT_IF_NONACTIVE
+
                }
        }
 
@@ -6346,7 +6676,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle
         * buttons inside this region. disabled inside check .. not sure
         * anymore why it was there? but it meant enter didn't work
         * for example when mouse was not over submenu */
-       if ((/*inside &&*/ (!menu->menuretval || (menu->menuretval & UI_RETURN_UPDATE)) && retval == WM_UI_HANDLER_CONTINUE) || event->type == TIMER) {
+       if ((event->type == TIMER) ||
+           (/*inside &&*/ (!menu->menuretval || (menu->menuretval & UI_RETURN_UPDATE)) && retval == WM_UI_HANDLER_CONTINUE))
+       {
                but = ui_but_find_activated(ar);
 
                if (but) {
@@ -6425,7 +6757,7 @@ static int ui_handle_menu_return_submenu(bContext *C, wmEvent *event, uiPopupBlo
                return WM_UI_HANDLER_BREAK;
 }
 
-static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHandle *menu)
+static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int level)
 {
        uiBut *but;
        uiHandleButtonData *data;
@@ -6438,14 +6770,24 @@ static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHa
        submenu = (data) ? data->menu : NULL;
 
        if (submenu)
-               retval = ui_handle_menus_recursive(C, event, submenu);
+               retval = ui_handle_menus_recursive(C, event, submenu, level + 1);
 
        /* now handle events for our own menu */
        if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) {
-               if (submenu && submenu->menuretval)
+               if (submenu && submenu->menuretval) {
+                       int do_ret_out_parent = (submenu->menuretval & UI_RETURN_OUT_PARENT);
                        retval = ui_handle_menu_return_submenu(C, event, menu);
-               else
-                       retval = ui_handle_menu_event(C, event, menu, (submenu == NULL));
+                       submenu = NULL;  /* hint not to use this, it may be freed by call above */
+                       (void)submenu;
+                       /* we may wan't to quit the submenu and handle the even in this menu,
+                        * if its important to use it, check 'data->menu' first */
+                       if ((retval == WM_UI_HANDLER_BREAK) && do_ret_out_parent) {
+                               retval = ui_handle_menu_event(C, event, menu, level);
+                       }
+               }
+               else {
+                       retval = ui_handle_menu_event(C, event, menu, level);  /* same as above */
+               }
        }
 
        return retval;
@@ -6533,7 +6875,7 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *UNUSED(user
                if (data->state == BUTTON_STATE_MENU_OPEN) {
                        /* handle events for menus and their buttons recursively,
                         * this will handle events from the top to the bottom menu */
-                       retval = ui_handle_menus_recursive(C, event, data->menu);
+                       retval = ui_handle_menus_recursive(C, event, data->menu, 0);
 
                        /* handle events for the activated button */
                        if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) {
@@ -6577,7 +6919,7 @@ static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata)
                retval = WM_UI_HANDLER_CONTINUE;
        }
 
-       ui_handle_menus_recursive(C, event, menu);
+       ui_handle_menus_recursive(C, event, menu, 0);
 
        /* free if done, does not free handle itself */
        if (menu->menuretval) {