Stanzilla / WoWUIBugs

World of Warcraft UI Bug Tracker
153 stars 7 forks source link

EditBox cursor invisible while typing or moving the cursor #484

Open weltensturm opened 9 months ago

weltensturm commented 9 months ago

When starting to type or moving the cursor while the cursor is hidden during its blinking animation, the cursor will stay hidden. The cursor should be set to visible/its blinking animation reset when starting to type or move the cursor.

arcadepro commented 9 months ago

If anyone has a quick hack to alleviate this issue somehow I'd be very grateful. It's been driving me insane.

Duugu commented 9 months ago

This issue was introduced to Wrath and Era too. Please add them. :) Thanks!

Winsane commented 9 months ago

If anyone has a quick hack to alleviate this issue somehow I'd be very grateful. It's been driving me insane.

UIParent:HookScript("OnUpdate",function()
      local editbox = GetCurrentKeyBoardFocus()
      if editbox then
         editbox:SetBlinkSpeed(0.01)
      end
end)

I couldn't think of a neat way of applying it to all edit boxes without iterating through frames or constantly calling GetCurrentKeyBoardFocus(). Maybe there is some global thing for keyboard focus changes we can hook.

weltensturm commented 8 months ago

This completely replaces the default cursor:

local BLINK_SPEED = 0.6

local function FixEditBox(editbox)
    editbox:SetBlinkSpeed(0)

    local customCursor = editbox:CreateTexture()
    customCursor:SetColorTexture(1, 1, 1, 1)
    customCursor:Hide()
    customCursor:SetDrawLayer 'OVERLAY'
    function customCursor:Reset()
        if self.ticker then
            self.ticker:Cancel()
        end
        self.ticker = C_Timer.NewTicker(
            BLINK_SPEED,
            function()
                self:SetShown(not self:IsShown())
            end
        )
        self:Show()
    end
    local hideOrig = customCursor.Hide
    function customCursor:Hide()
        hideOrig(self)
        if self.ticker then
            self.ticker:Cancel()
        end
    end

    local left, _, top, _ = editbox:GetTextInsets()
    local isMultiline = editbox:IsMultiLine()
    editbox:HookScript(
        'OnCursorChanged',
        function(self, x, y, w, h)
            customCursor:SetSize(w, h)
            customCursor:SetPoint(
                isMultiline and 'TOPLEFT' or 'LEFT',
                self,
                isMultiline and 'TOPLEFT' or 'LEFT',
                left+x,
                top+y
            )
            customCursor:Reset()
        end
    )
    editbox:HookScript('OnEditFocusLost', function() customCursor:Hide() end)
end

local Fixed = {} 

UIParent:HookScript("OnUpdate", function()
    local editbox = GetCurrentKeyBoardFocus()
    if editbox and not Fixed[editbox] then
        FixEditBox(editbox)
        Fixed[editbox] = true
    end
end)

Notes:

Meorawr commented 6 months ago

Re-test this on the 10.2.6 PTR when that comes up.

Winsane commented 3 months ago

@weltensturm Thank you! I got around the GetTextInsets loop by hooking SetTextInsets. And I had an issue with vertical position in some cases, which I fixed by changing top+y to y-top.

local BLINK_SPEED = 0.6

local function FixEditBox(editbox)
    editbox:SetBlinkSpeed(0)

    local customCursor = editbox:CreateTexture()
    customCursor:SetColorTexture(1, 1, 1, 1)
    customCursor:Hide()
    customCursor:SetDrawLayer 'OVERLAY'
    function customCursor:Reset()
        if self.ticker then
            self.ticker:Cancel()
        end
        self.ticker = C_Timer.NewTicker(
            BLINK_SPEED,
            function()
                self:SetShown(not self:IsShown())
            end
        )
        self:Show()
    end
    local hideOrig = customCursor.Hide
    function customCursor:Hide()
        hideOrig(self)
        if self.ticker then
            self.ticker:Cancel()
        end
    end

    local left, _, top, _ = editbox:GetTextInsets()
    local isMultiline = editbox:IsMultiLine()
    editbox:HookScript(
        'OnCursorChanged',
        function(self, x, y, w, h)
            customCursor:SetSize(w, h)
            customCursor:SetPoint(
                isMultiline and 'TOPLEFT' or 'LEFT',
                self,
                isMultiline and 'TOPLEFT' or 'LEFT',
                x+left,
                y-top
            )
            customCursor:Reset()
        end
    )
    editbox:HookScript('OnEditFocusLost', function() customCursor:Hide() end)

    hooksecurefunc(editbox,"SetTextInsets",function(_,newleft,_,newtop)
            left, top = newleft, newtop
    end)
end

local Fixed = {} 

UIParent:HookScript("OnUpdate", function()
        local editbox = GetCurrentKeyBoardFocus()
        if editbox and not Fixed[editbox] then
            FixEditBox(editbox)
            Fixed[editbox] = true
        end
end)
Ketho commented 3 months ago

On 10.2.6 the cursor seems to be always visible again while moving the cursor.

(while typing it depends whether the cursor was visible or not, but I have no opinion on that and don't remember the original functionality)