How to keep the cursor focus on the REPL?

I need help with Gtk.jl for the following basic problem.

I am trying to get input from the REPL in a closed loop program and update a Gtk window that keeps track of all items generated during program execution.

See the MWE example below. Each input string and integer items are added to a Gtk window list, which is redrawn each time to reflect the new data. The problem is that displaying the Gtk window steals the cursor focus from the REPL.

How can this be solved?
Thanks in advance.

Gtk.jl MWE code
using Gtk

@kwdef mutable struct Item
    name::String = ""
    size::Int = 0
end

function gtk_list(data::Vector{Item})
    global win
    visible(win, false)

    ts = GtkTreeStore(String, String, String)
    tv = GtkTreeView(GtkTreeModel(ts))
    sw = GtkScrolledWindow(tv)
    rTxt = GtkCellRendererText()

    c0 = GtkTreeViewColumn("#", rTxt, Dict([("text", 0)]))
    c1 = GtkTreeViewColumn("Name", rTxt, Dict([("text", 1)]))
    c2 = GtkTreeViewColumn("Size", rTxt, Dict([("text", 2)]))

    cols = [c0, c1, c2]
    push!(tv, cols...)

    iter1 = push!(ts, ("", "MY ITEMS", "",))
    for (n,d) in pairs(data)
        push!(ts, (string(n), d.name, string(d.size)), iter1)
    end

    win = GtkWindow(sw, "MyData")
    Gtk.showall(win)
    Gtk.G_.position(win, 200, 200)
    set_gtk_property!(win, :width_request, 700)
    visible(win, true)
    
    return nothing
end

function input_data!(data::Vector{Item})
    s = "n"
    while s āˆ‰ ("y", "Y")
        println("New item name:")
        name = readline()
        println("New item size (Int):")
        sz = tryparse(Int, readline())
        isnothing(sz) && (sz = -999)
        push!(data, Item(name, sz))
        gtk_list(data)
        println("[ENTER]:continue, (Y):stop")
        s = readline()
    end
    return nothing
end

function start_code()
    @eval win = GtkWindow("MyData", visible=false)
    data = Item[]
    input_data!(data)
    destroy(win)                    
    return nothing
end


# Copy and paste the above code into the Julia REPL (not the VSCode REPL)
# ... and then call the function:
start_code()

Here are some clues from the C Gtk3 documentation and source code. Maybe you can do something with ccall to set the flag on your window.

https://lazka.github.io/pgi-docs/Gtk-3.0/classes/Window.html#Gtk.Window.get_focus_on_map

Even better, call this: gtk/gtkwindow.c Ā· 3.24.39 Ā· GNOME / gtk Ā· GitLab

1 Like

Thanks Jeff.

I am afraid I am totally out of my depth with ccall().

I modified the MWE above with using GTK3_jll and adding the line:

ccall((:gtk_window_set_focus_on_map, libgtk3), Nothing, (Ptr{GObject}, Bool), win, false)

But still could not get the text input focus back to the REPL.

Gtk.jl MWE edited with ccall() before `visible`
using Gtk, GTK3_jll

@kwdef mutable struct Item
    name::String = ""
    size::Int = 0
end

function gtk_list(data::Vector{Item})
    global win
    visible(win, false)

    ts = GtkTreeStore(String, String, String)
    tv = GtkTreeView(GtkTreeModel(ts))
    sw = GtkScrolledWindow(tv)
    rTxt = GtkCellRendererText()

    c0 = GtkTreeViewColumn("#", rTxt, Dict([("text", 0)]))
    c1 = GtkTreeViewColumn("Name", rTxt, Dict([("text", 1)]))
    c2 = GtkTreeViewColumn("Size", rTxt, Dict([("text", 2)]))

    cols = [c0, c1, c2]
    push!(tv, cols...)

    iter1 = push!(ts, ("", "MY ITEMS", "",))
    for (n,d) in pairs(data)
        push!(ts, (string(n), d.name, string(d.size)), iter1)
    end

    win = GtkWindow(sw, "MyData")
    Gtk.showall(win)
    Gtk.G_.position(win, 200, 200)
    set_gtk_property!(win, :width_request, 700)
    ccall((:gtk_window_set_focus_on_map, libgtk3), Nothing, (Ptr{GObject}, Bool), win, false)
    visible(win, true)
    println("\nFocus on map: $(ccall((:gtk_window_get_focus_on_map, libgtk3), Bool, (Ptr{GObject},), win))) \n")

    return nothing
end

function input_data!(data::Vector{Item})
    s = "n"
    while s āˆ‰ ("y", "Y")
        println("New item name:")
        name = readline()
        println("New item size (Int):")
        sz = tryparse(Int, readline())
        isnothing(sz) && (sz = -999)
        push!(data, Item(name, sz))
        gtk_list(data)
        println("[ENTER]:continue, (Y):stop")
        s = readline()
    end
    return nothing
end

function start_code()
    @eval win = GtkWindow("MyData", visible=false)
    input_data!(Item[])
    destroy(win)                     
    return nothing
end


# Copy and paste the above code into the Julia REPL (not the VSCode REPL)
# ... and then call the function:
start_code()

You need to do gtk_window_set_focus_on_map before visible. Mapping in X Windows parlance is making the window visible, so you need to set the flag before the window is mapped. You can also try calling to gtk_window_get_focus_on_map to check whether you actually set the flag correctly.

1 Like

I have edited the code above according to your last recommendation. We can see that the focus on map was set to false. However, displaying the gtk window still steals the cursor focusā€¦

Could this be a Windows OS ā€œfeatureā€?

Probably. Is it possible in Windows 10 to prevent an opening application from stealing focus? - Super User

1 Like

OMG, Windows just keeps getting betterā€¦ Iā€™ve marked your post as the solution, until the Gates Corporation shows some charity to its users.