diff --git a/VersionASM b/VersionASM
index b6adce6c88d6932b21c824a251c0727cb173751f..ad52466fcd687cf991e4ecbb287d1744e6ae59c6 100644
--- a/VersionASM
+++ b/VersionASM
@@ -9,12 +9,12 @@
                         GBLS    Module_ApplicationDate
                         GBLS    Module_HelpVersion
                         GBLS    Module_ComponentName
-Module_MajorVersion     SETS    "6.36"
-Module_Version          SETA    636
+Module_MajorVersion     SETS    "6.37"
+Module_Version          SETA    637
 Module_MinorVersion     SETS    ""
-Module_Date             SETS    "18 Mar 2020"
-Module_ApplicationDate  SETS    "18-Mar-20"
+Module_Date             SETS    "21 Mar 2020"
+Module_ApplicationDate  SETS    "21-Mar-20"
 Module_ComponentName    SETS    "Kernel"
-Module_FullVersion      SETS    "6.36"
-Module_HelpVersion      SETS    "6.36 (18 Mar 2020)"
+Module_FullVersion      SETS    "6.37"
+Module_HelpVersion      SETS    "6.37 (21 Mar 2020)"
                         END
diff --git a/VersionNum b/VersionNum
index abcbea70270fb05ff0848563490eac55b24bf4cb..e875e4e3b018189e514aa6472ee5e9db5b7341ca 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,21 +1,21 @@
-/* (6.36)
+/* (6.37)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
  *
  */
-#define Module_MajorVersion_CMHG        6.36
+#define Module_MajorVersion_CMHG        6.37
 #define Module_MinorVersion_CMHG        
-#define Module_Date_CMHG                18 Mar 2020
+#define Module_Date_CMHG                21 Mar 2020
 
-#define Module_MajorVersion             "6.36"
-#define Module_Version                  636
+#define Module_MajorVersion             "6.37"
+#define Module_Version                  637
 #define Module_MinorVersion             ""
-#define Module_Date                     "18 Mar 2020"
+#define Module_Date                     "21 Mar 2020"
 
-#define Module_ApplicationDate          "18-Mar-20"
+#define Module_ApplicationDate          "21-Mar-20"
 
 #define Module_ComponentName            "Kernel"
 
-#define Module_FullVersion              "6.36"
-#define Module_HelpVersion              "6.36 (18 Mar 2020)"
-#define Module_LibraryVersionInfo       "6:36"
+#define Module_FullVersion              "6.37"
+#define Module_HelpVersion              "6.37 (21 Mar 2020)"
+#define Module_LibraryVersionInfo       "6:37"
diff --git a/hdr/KeyWS b/hdr/KeyWS
index 4a4cf3de78ac58a92e08090e532068c334710432..d31d7ddddf077ea12d214e8d79a663fc2d76ee44 100644
--- a/hdr/KeyWS
+++ b/hdr/KeyWS
@@ -55,6 +55,8 @@ SoftKeyPtr      #       4
 MouseXMult      #       4
 MouseYMult      #       4
 KeyVec          #       4
+MouseAltX       #       4
+MouseAltY       #       4
 
 
 MouseBounds     #       16
@@ -73,6 +75,10 @@ SoftKeyExpand   #       255             ; current key expansion
 UserKeyWorkSpaceSize *  KeyWorkSpaceSize-(:INDEX: @)
 UserKeyWorkSpace #      UserKeyWorkSpaceSize
 
+ [ :DEF: ShowWS
+      ! 0, "UserKeyWorkSpaceSize  is ":CC::STR:(UserKeyWorkSpaceSize)
+ ]
+        ASSERT  UserKeyWorkSpaceSize >= 64 ; "About 170 bytes" according to IntKey.Doc.HandlerAPI, but we've been smaller than that for a long time
 
 ; PMF -> VDU communication stuff put in here because both VDU and PMF
 ; 'GET' this file
diff --git a/hdr/RISCOS b/hdr/RISCOS
index bee6155de99a80043281a03af3d8e3b84f55c39c..5b57b5b45b6d598a08214471e4a861dfada2691a 100644
--- a/hdr/RISCOS
+++ b/hdr/RISCOS
@@ -340,6 +340,8 @@ Event_PRISM             * 32    ; State change events from the PRISM subsystem
 Event_Expansion_SmartCard       # 0          ; ANC Rich Buckley
 Event_Expansion_SCInterface     # 1          ; 0 more useful alias for above
 Event_Expansion_SCTransport     # 1          ; 1
+                                # 2
+Event_Expansion_PointerScroll   # 1          ; 4
 
 ; Subreason codes for Event_Internet - to be passed in R1 on the event call
                                 ^ 1
diff --git a/s/NewIRQs b/s/NewIRQs
index fd18ee5d1706a2ae4079af1623da765888f44369..be83d011805d72c58f9d1dc285a1178fe6c132a8 100644
--- a/s/NewIRQs
+++ b/s/NewIRQs
@@ -530,6 +530,13 @@ OSEVEN ROUT
 
 DefEvent ROUT
 
+        ; Scrollwheel handling - (vector-based) event watchers are allowed to
+        ; suppress scroll updates by claiming the vector. If we made it all the
+        ; way to this default handler, then the scroll update should be applied.
+        TEQ     r0, #Event_Expansion
+        TEQEQ   r1, #Event_Expansion_PointerScroll
+        BLEQ    PointerScrollApply
+
         MOV     lr, pc                  ; link with all the bits
         LDMIA   r12, {r12, pc}          ; call EventHandler, returns to ...
 
diff --git a/s/PMF/mouse b/s/PMF/mouse
index 0cc74b5bde036aa91d52b0b9707bae37f118e132..d4b9cac5ff0d26fc6a87cc5271a20b41f669402d 100644
--- a/s/PMF/mouse
+++ b/s/PMF/mouse
@@ -54,13 +54,18 @@ MouseInit
 ;
 ;       MouseButtonChange - Called by keyboard handler when mouse button change
 ;
-; in:   R0 = state of buttons (bit0=R, bit1=C, bit2=L)
+; in:   R0 = state of three primary buttons (bit0=R, bit1=C, bit2=L)
 ;       R11 -> KeyWorkSpace
 ;
 
 MouseButtonChange ROUT
-        Push    "R0-R5, R12, R14"
+        Entry   "R0-R5, R12"
 
+        LDRB    R1, MouseButtons        ; Preserve the extra buttons (they
+        AND     R0, R0, #7              ; aren't part of the keyboard handler)
+        BIC     R1, R1, #7
+        ORR     R0, R0, R1
+10
         VDWS    WsPtr
         STRB    R0, MouseButtons        ; save it for ReadMouse calls
         MOV     R3, R0
@@ -101,7 +106,18 @@ MouseButtonChange ROUT
         BL      GoVec2                  ; Call the vector in R10
         Pull    "R10,R12"
         ADD     SP, SP, #3*4            ; Destroy mouse data buffer
-        Pull    "R0-R5, R12, PC"
+        EXIT
+
+
+; *****************************************************************************
+;
+;       MouseButtonChange2 - Called when mouse buttons change
+;
+; in:   R0 = state of all buttons
+;       R11 -> KeyWorkSpace
+;
+MouseButtonChange2 ALTENTRY
+        B       %BT10
 
 ; *****************************************************************************
 ;
@@ -272,7 +288,7 @@ PollPointer
         TEQ     r0, #0
         Pull    "r4,r12,pc",NE
 
-        MOV     r0, #0                  ; Request pointer state.
+        MOV     r0, #PointerReason_Request
         LDRB    r1, MouseType
         MOV     r2, #0                  ; Default to no movement.
         MOV     r3, #0
@@ -292,9 +308,9 @@ PollPointer
 ;
 ;       PointerVector - the default PointerV claimant
 ;
-PointerVector
+PointerVector   ROUT
         CMP     r0, #PointerReason_Report
-        Pull    pc, NE
+        BNE     %FT50
         Push    "r2,r3,r11"
         LDR     r11, =ZeroPage+KeyWorkSpace
         LDRB    lr, MouseType
@@ -304,6 +320,61 @@ PointerVector
         BL      ProcessMouseXY
         Pull    "r2,r3,r11,pc"
 
+50
+        CMP     r0, #PointerReason_WheelChange
+        Pull    pc, NE
+
+        ; R1 = Y scroll, negative = up/away
+        ; R2 = extra buttons
+        ; R3 = X scroll
+        PHPSEI
+        Push    "r0-r3,r11,lr"
+        LDR     r11, =ZeroPage+KeyWorkSpace
+        ; Update extra buttons
+        AND     r2, r2, #&1F
+        LDRB    r0, MouseButtons
+        EORS    lr, r2, r0, LSR #3      ; Any change?
+        EORNE   r0, r0, lr, LSL #3
+        BLNE    MouseButtonChange2
+        ; Update scroll wheels
+        EORS    lr, r1, r3
+        BEQ     %FT90
+        MOV     r2, r3                  ; X delta
+        RSB     r3, r1, #0              ; Y delta, positive = up/away
+        MOV     r0, #Event_Expansion
+        MOV     r1, #Event_Expansion_PointerScroll
+        BL      OSEVEN                  ; May call PointerScrollApply via OS's default handler (to allow event claimints to suppress scroll updates)
+        BLCS    PointerScrollApply      ; Unless the event is disabled, in which case we must call direct
+90
+        Pull    "r0-r3,r11,lr"
+        PLP
+        Pull    "pc"
+
+
+; *****************************************************************************
+;
+;       PointerScrollApply - Update our scroll wheel data
+;
+;       in:     r2 = X delta
+;               r3 = Y delta
+;               Interrupts disabled
+;
+PointerScrollApply ROUT
+        Entry   "r0-r1,r11"
+        LDR     r11, =ZeroPage+KeyWorkSpace
+        ; Mimic RISCOS Ltd's funky wrap-to-zero logic
+        MOV     lr, #&80000000
+        LDR     r0, MouseAltX
+        ADDS    r1, r0, r2
+        EORVS   r0, lr, r0, ASR #31 ; &80000000 if originally positive, &7FFFFFFF if negative
+        SUBVS   r1, r1, r0          ; positive -> negative wrapping loses &80000000, negative -> positive loses &7FFFFFFF
+        STR     r1, MouseAltX
+        LDR     r0, MouseAltY
+        ADDS    r1, r0, r3
+        EORVS   r0, lr, r0, ASR #31
+        SUBVS   r1, r1, r0
+        STR     r1, MouseAltY
+        EXIT
 
 
 ; *****************************************************************************
@@ -312,11 +383,16 @@ PointerVector
 ;
 PointerSWI
         LDR     r11, =ZeroPage+KeyWorkSpace
-        TEQ     r0, #0
+        TEQ     r0, #OSPointer_GetPointerType
         LDREQB  r0, MouseType
         BEQ     SLVK
 
-        TEQ     r0, #1
+        TEQ     r0, #OSPointer_ReadAltPosition
+        LDREQ   r0, MouseAltX
+        LDREQ   r1, MouseAltY
+        BEQ     SLVK
+
+        TEQ     r0, #OSPointer_SetPointerType
         BNE     %FT10
 
         Push    "r0,r10,r12,lr"