B4J Question KeyBoard Overlay with WebSocket and NativeHook [Solved]

tkstarir

Member
Hi B4X Community

i have a question about 2 Libraries: Server Websocket and NativeHook

i wanna write an overlay keyboard screen with this 2 library and everything is ok except one thing

when NH_NativeKeyPressed Call and i Got hotkey text, i dont know how can i send it to my browser in overlay.html

this is my codes:

Main.b4j:
#Region Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
    Dim MyServer As Server
    Dim MyWebSocket As Overlay_WebSocket
End Sub

Sub AppStart (Args() As String)
    MyServer.Initialize("MyServer")
    MyServer.Port = 1111
    MyServer.AddHandler("/asd", "Overlay_Handler", False)
    MyServer.AddWebSocket("/asd2", "Overlay_WebSocket")
    MyServer.Start
    StartMessageLoop
End Sub

Sub NH_NativeKeyPressed(Hotkey As NativeKeyEvent)
    MyWebSocket.Initialize
    MyWebSocket.SendMessage(Hotkey.KeyText)
End Sub

Sub NH_Unregistered
End Sub

Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub


WebSocket Server:
Public Sub Class_Globals
    Dim ws As WebSocket
End Sub

Public Sub Initialize
End Sub

Public Sub WebSocket_Connected (WebSocket As WebSocket)
    ws = WebSocket
    Dim NH As NativeHook
    NH.Initialize("NH", Main)
    NH.startNativeKeyListener
    NH.enableKillCode
    NH.EnableEventConsumption
    Log("Connected !")
End Sub

Public Sub SendMessage(message As String)
    Log(message)
    If message <> "" Then
        ws.Alert(message)
        ws.Flush
    End If
End Sub

Public Sub WebSocket_Disconnected
End Sub

overlay.html:
<script type="text/javascript">
    window.onload = function(){
        var socket = new WebSocket('ws://127.0.0.1:1111/asd2');
        socket.onopen = function(){
            socket.onmessage = function(message){
                try {
                    var json = JSON.parse(message.data);
                    if(json.etype == 'alert'){
                        document.getElementById('show_hotkey').innerHTML = json.prop;
                        return true;
                    }else{
                        return false;
                    }
                } catch(error) {
                    return false;
                }
            };
        };
    };
</script>
<style type="text/css">
    #show_hotkey {
        color: red;
        font-size: 50px;
        font-weight: bold;
        margin: 50px;
    }
</style>
<span id="show_hotkey">HotKey</span>


the problem is that it when i call SendMessage method in WebSocket Server Nothing happens. mean both Log and Alert functions not call
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. Not sure what you did with the code snippet but it broke the syntax highlighting.
2. This cannot work:
B4X:
 Dim MyWebSocket As Overlay_WebSocket
MyWebSocket.Initialize
 MyWebSocket.SendMessage(Hotkey.KeyText)
A new class instance is created on each connection.
Never call Initialize on a server handler.

See the online chat example. The way to deal with such cases is to put the instance in a thread safe map:
B4X:
Public Sub WebSocket_Connected (WebSocket As WebSocket)
  Main.Connections.Put(SomeId, Me) 'if there is no id then use a random number that is stored as a global field in the class.
'Later in Disconnected event:
Main.Connections.Remove(SomeId) 'same id
This will allow you to get all connections:
B4X:
For Each my As Overlay_WebSocket In Connections.Values
 ...
Next
 
Upvote 0

tkstarir

Member
1. Not sure what you did with the code snippet but it broke the syntax highlighting.

sry i changed the snippet language. it's ok now

For Each my As Overlay_WebSocket In Connections.Values
...
Next

i do that what you said

B4X:
' In Globals:
Dim Connection As Map

' In AppStart
Connection.Initialize

' In WebSocket WebSocket_Connected
Main.Connection.Put("Overlay", Me)

' In NH_NativeKeyPressed
    For Each my As Overlay_WebSocket In Connection.Values
        Log(my)
        my.MyWebSocket.Alert(Hotkey.KeyText)
    Next

but this still dont work and alert dont send to overlay.html

while in overlay.html, connection is open and waiting for onmessage event

when in WebSocket_Connected i use Alert Method it works fine ! but when i use it in NH_NativeKeyPressed dont work !
 
Upvote 0

tkstarir

Member
i change your code to that i think is true:

B4X:
' In WebSocket WebSocket_Connect
Main.Connection.Put("Overlay", WebSocket)


' In NH_NativeKeyPressed
Dim MyWebSocket As WebSocket = Connection.Get("Overlay")
MyWebSocket.Alert(Hotkey.KeyText)

but this also dont work and don't send anything to web browser client
 
Last edited:
Upvote 0

tkstarir

Member
i fixed this problem

tnx erel for your help and your kindnesses

i must use Flush after call Alert Method

Solved Code:

B4X:
' In Main Process_Globals Sub:
Dim Connection As Map


' In Main AppStart Sub:
Connection.Initialize


' In Main NH_NativeKeyPressed Sub:
Dim MyWebSocket As WebSocket = Connection.Get("Overlay_Client")
MyWebSocket.Alert(Hotkey.KeyText)
MyWebSocket.Flush


' In WebSocket Server WebSocket_Connected:
Main.Connection.Put("Overlay_Client", WebSocket)




My Problem Has been Solve
 
Upvote 0
Top