Can't terminate panel focus without removing it.

I have tried making a chatbox using vgui elements only.
I created a panel and added a DTextEntry to it (coffee_textArea), but appearently I can’t disable the cursor and start walking again without removing the whole chatbox…
the cursor just stays there and I cant make it go away even if I click ESC thousand times or try to pop up some other menus - it stays there until I execute self:Remove() on the chatbox.

Here is my code:


local PANEL = {}
function PANEL:Init()
    self:SetSize( 300, 150 )
    self:SetPos( -300, ScrH() - self:GetTall() - 5 )
    self:setTitle( "Chat" )
    self.input = vgui.Create( "coffee_textArea", self )
    self.input:SetPos( 2, self:GetTall() - 22 )
    self.input:SetSize( self:GetWide() - 4, 20 )
    self.input:SetText( "" )
    self.input.OnEnter = function()
        RunConsoleCommand( "say", self.input:GetText() )
        self:Remove()
    end
end


function PANEL:startInput()
    self:MakePopup()
    self.input:RequestFocus()
end


function PANEL:show()
    self:MoveTo( 5, ScrH() - self:GetTall() - 5, 0.25, 0, 0.5, function() end )
end


function PANEL:hide()
    self:MoveTo( -300, ScrH() - self:GetTall() - 5, 0.25, 0, 0.5, function() end )
end


function PANEL:Paint( w, h )
    surface.SetDrawColor( Color( 28, 32, 36 ) )
    surface.DrawRect( 0, 0, w, h )
    surface.SetDrawColor( Color( 58, 69 ,79 ) )
    surface.DrawOutlinedRect( 0, 0, w, h )
    surface.SetDrawColor( Color( 78,205,196 ) )
    surface.DrawRect( 0, 0, w, 20 )
    surface.SetDrawColor( Color( 38, 165, 156 ) )
    surface.DrawRect( 0, 20, w, 5 )


    surface.SetTextColor( Color( 84, 36, 55 ) )
    surface.SetFont( "CoffeeFont16Bold" )
    local tw, th = surface.GetTextSize( self.title )
    surface.SetTextPos( ( w / 2 ) - ( tw / 2 ), 4 )
    surface.DrawText( self.title )
end


function PANEL:Think()
    print( vgui.GetKeyboardFocus() )
end
vgui.Register( "coffee_chat", PANEL, "coffee_frame" )

coffee_frame is using DFrame as a base.
That think hook is there only for debugging.

I’m assuming you’ve already tried this?

Indeed, all it did was disallow me from using developer console and I had to ALT+F4 my game.

The only way I’ve worked around this is to call DFRAME:SetDeleteOnClose(false) and then call DFRAME:Close() [optionally overriding Close to do some extra stuff before calling the original function]

Except that I don’t want to close it, nor remove it and not delete it either.

[editline]26th June 2014[/editline]

Not to mention that :KillFocus() should work, if it doesn’t then it’s a bug and it needs to be reported.

I was thinking something like this:
[lua]dframe.OldClose = dframe.Close
dframe.Close = function(self)
self:OldClose() --call the base function that takes care of the cursor hiding
self:SetVisible(true) --make it instantly visible again
end[/lua] Then you could just call :Close() to make it unfocus, although you’d need another function for really closing it.

Agreed.

This is what I am currently using to make the minimise button of the dframe return mouse and keyboard control to the game while still staying visible.
[lua]
–Minimise button restores game focus
MyMenu.btnMinim:SetDisabled(false)
MyMenu.btnMinim.DoClick = function(btn)
MyMenu:SetKeyboardInputEnabled(false)
MyMenu:SetMouseInputEnabled(false)
gui.EnableScreenClicker(false)
end[/lua]

I’m a little unclear on your exact requirements though. The window should still be visible I understand, but are you trying to restore mouse and keyboard focus to the game, or just the keyboard / just the mouse?

Both, keyboard and the mouse, but keyboard won’t work because mouse is enabled (like with context emnu).

And I don’t like using tricky ways to doing stuff, so I’d rather look/wait for a fix that doesn’t require that.

Fair enough, although I don’t consider it ‘tricky’; the whole point of vgui/lua is extensibility, there is no rule that says you have to use the built in elements with their built in functions. But if you decide to not wait then this is exactly what I’m using for a window that stays on screen and is focussed via concommand/bind.
[lua]local MyMenu --This will hold the reference to the panel

local function MakeMenu()
–Make the menu
MyMenu = vgui.Create(“DFrame”)
MyMenu:SetSize(700,400)
MyMenu:SetPos(20,20)
MyMenu:SetSizable(true)
MyMenu:SetTitle(“Test menu”)
MyMenu:SetDeleteOnClose(false) --Keep this frame even when it gets ‘closed’
MyMenu:MakePopup()

MyMenu.Showing = true --We track whether it is visible or not

MyMenu.OnClose = function(self)
	self.Showing = false
	print("Menu hidden")
end

local OldPopup = MyMenu.MakePopup --Overriding MakePopup to enforce SetVisible and Set*InputEnabled
MyMenu.MakePopup = function(self,...)
	self.Showing = true
	self:SetVisible(true)
	self:SetKeyboardInputEnabled(true)
	self:SetMouseInputEnabled(true)
	OldPopup(self,unpack({...}))
end

--Minimise button restores game focus
MyMenu.btnMinim:SetDisabled(false)
MyMenu.btnMinim.DoClick = function(btn)
	MyMenu:SetKeyboardInputEnabled(false)
	MyMenu:SetMouseInputEnabled(false)
	gui.EnableScreenClicker(false)
end

end

concommand.Add(“mymenu”, function()
if not IsValid(MyMenu) then
print(“Make new menu”)
MakeMenu()
else
if MyMenu.Showing then
print(“Menu is showing, focus it”)
–Toggle focus
MyMenu:MakePopup()
else
–Show the menu and focus it
print(“Menu is hidden, show it”)
MyMenu:MakePopup()
end
end
end)[/lua]
(The close button of the frame actually closes it, but the minimise button just unfocuses it)

If only you gave enough cares to look into the source code…

FocusNext() doesn’t work…
I browsed the source code deeply.

… . . . . . … . .

If it didn’t work, it wouldn’t work in spawnmenu either. Yet it does.

[editline]27th June 2014[/editline]

Test in on vanilla DTextEntry, not on your custom controls.

Will do.
Also, lol… just noticed my razer keyboard had macro enabled and it spammed with dots… nevermind haha.

Okay, this worked fine:


	self.input.OnEnter = function()
		RunConsoleCommand( "say", self.input:GetText() )
		self:SetKeyboardInputEnabled( false )
		self:SetMouseInputEnabled( false )
	end

Thanks!