gotk3 / gotk3

Go bindings for GTK3
ISC License
2.11k stars 231 forks source link

[Project question] Grab Window focus #856

Open ark3us opened 2 years ago

ark3us commented 2 years ago

Hello and thank you for your work!

Given that I have nearly no experience with UI coding, I'm trying to make an application that opens a new Window when a certain hotkey is pressed and gives focus to the newly created window. This is an example of the code:

package main

import (
    "github.com/gotk3/gotk3/gtk"
    hook "github.com/robotn/gohook"
    "log"
)

func startHotkeyListener() {
    hook.Register(hook.KeyDown, []string{"z", "alt"}, func(event hook.Event) {
        createWin()
    })
    start := hook.Start()
    <-hook.Process(start)
}

func createWin() {
    win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
    if err != nil {
        log.Fatal("Unable to create window:", err)
    }
    win.SetTitle("Simple Example")

    b, err := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 10)
    if err != nil {
        log.Fatal("Unable to create label:", err)
    }

    l, err := gtk.LabelNew("Hello, gotk3 2!")
    if err != nil {
        log.Fatal("Unable to create label:", err)
    }

    b.Add(l)

    e, err := gtk.EntryNew()
    if err != nil {
        log.Fatal("Unable to create entry:", err)
    }

    b.Add(e)

    win.Add(b)

    win.SetDefaultSize(800, 600)
    win.SetKeepAbove(true)
    win.SetSkipTaskbarHint(true)

    win.ShowAll()
    win.Present()
    win.GrabFocus()
}

func main() {
    gtk.Init(nil)
    go startHotkeyListener()
    gtk.Main()
}

However, I'm experiencing the following problem:

  1. I press the hotkey (alt + z)
  2. The Window is shown and focused correctly
  3. If I DO NOT FOCUS OUT the window, even if i close it, the next window is created and focused correctly as well
  4. If I FOCUS OUT the window (i.e., focus some other window on my screen), the next window is created correctly BUT does not grab the focus

I have also tried to set different window type hints without success. The only way i can always grab the focus is creating the window as WINDOW_POPUP, but in that case i can't write into the Entry object.

Can anyone help with this please? Thanks!

OS: Ubuntu 21.10 GNOME version: 40.4.0 X.Org version: 1.20.13

hfmrow commented 2 years ago

hi, have you tryed (*gtk.Window).GrabFocus() method just after window creation ?

ark3us commented 2 years ago

Hi, do you mean moving win.GrabFocus() just after gtk.WindowNew(gtk.WINDOW_TOPLEVEL)? Just tried, same result :(

ark3us commented 2 years ago

I was finally able to accomplish what I was looking for. I took inspiration from some python from https://github.com/kupferlauncher/kupfer (i'm trying to implement something similar in golang):

ts = Gtk.get_current_event_time()
win.present_with_time(ts)
win.get_window().focus(timestamp=ts)
win.show_all()

For some reason the difference is made by that gdk.Window.focus() function, which i think is missing in gotk3? gtk.Window.PresentWithTime() is not enough. Calling it from C accomplishes what I need, the focus is always grabbed by the new window:

win.PresentWithTime(gdk.CURRENT_TIME)
w, _ := win.GetWindow()
p := unsafe.Pointer(w.GObject)
C.gdk_window_focus(C.toGdkWindow(p), gdk.CURRENT_TIME)
win.ShowAll()

Hope this can be useful!

hfmrow commented 2 years ago

good! The first time I tried to run your code, I could not get it to work, even when installing the required Ubuntu development libraries (given in robotgo doc)

sudo apt install gcc libc6-dev sudo apt install libx11-dev xorg-dev libxtst-dev libpng++-dev sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev libxkbcommon-dev sudo apt install xsel xclip

It seems that the robotgo key hooker is not working, nothing appears on 'alt+z'. I realized that I am actually using an azerty keyboard, and that 'z' is represented by 'w'.

So I tested correctly and your problem does not appear on my machine, when I exit/close the window and switch to another application, your window appears correctly focusing on the input control if I press the keyboard shortcut combination.

ark3us commented 2 years ago

Hi,

So I tested correctly and your problem does not appear on my machine, when I exit/close the window and switch to another application, your window appears correctly focusing on the input control if I press the keyboard shortcut combination.

It might depend from the desktop environment (which one do you have?), i think in my case the issue was caused by gnome-shell focus stealing prevention, as explained here: https://gitlab.gnome.org/GNOME/mutter/-/issues/673

hfmrow commented 2 years ago

Yes, after some search about prevent_focus_stealing, i found this thread that explain the case (i'm on xfce which does not natively use this prevention method). The given command clearly indicate this state:

yyy@xx:~$ xfconf-query -c xfwm4 -l -v | grep focus
/general/click_to_focus                  true
/general/focus_delay                     250
/general/focus_hint                      true
/general/focus_new                       true
/general/prevent_focus_stealing          *false*
/general/raise_on_focus                  false