wmww / gtk4-layer-shell

A library to create panels and other desktop components for Wayland using the Layer Shell protocol and GTK4
MIT License
128 stars 4 forks source link

Problem with Keyboard Mode #19

Closed dhansmair closed 1 year ago

dhansmair commented 1 year ago

Hi! I've been playing with LayerShell in the past days and I have encountered a problem when setting the keyboard mode. First, this is a minimal code:

from ctypes import CDLL
CDLL('libgtk4-layer-shell.so')

import gi
gi.require_version("Gtk", "4.0")
gi.require_version('Gtk4LayerShell', '1.0')
from gi.repository import Gtk, Gtk4LayerShell as LayerShell

def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)

    LayerShell.init_for_window(win)
    LayerShell.set_layer(win, LayerShell.Layer.TOP)
    LayerShell.auto_exclusive_zone_enable(win)
    LayerShell.set_anchor(win, LayerShell.Edge.TOP, True)
    LayerShell.set_keyboard_mode(win, LayerShell.KeyboardMode.NONE)

    root = Gtk.Box()
    win.set_child(root)
    button = Gtk.Button(label="click me")
    root.append(button)
    def close(*args):
        app.quit()
    popover = Gtk.Popover()
    box = Gtk.Box()
    input = Gtk.Text(placeholder_text='placeholder text')
    button2 = Gtk.Button(label='close')
    button2.connect('clicked', close)
    box.append(input)
    box.append(button2)
    popover.set_child(box)
    popover.set_parent(button)

    def clicked(*args):
        popover.popup()
    button.connect('clicked', clicked)

    win.present()

app = Gtk.Application(application_id='org.gtk.Example')
app.connect('activate', on_activate)
app.run(None)

So my plan is to create a panel that contains a button. When the button gets clicked, a popover window with an input field should open (for an application menu with a search field).

The problem on hyprland is:

On the other hand, when running the same code on plasma wayland, setting the keyboard mode has no effect at all, meaning I can focus any window, as well as typing in the text field, regardless of the mode.

could you give me a hint on how to solve this problem?

wmww commented 1 year ago

Sounds like on-demand keyboard mode isn't supported by your compositor. you could try to set mode to exclusive when the input field is selected and set it back to none when it's deselected, or get your compositor to fully support layer shell v4. Not something I can fix in the library, or something I'm going to try to work around here.

dhansmair commented 1 year ago

Thank you for the suggestion, I was able to work around ON_DEMAND:

from ctypes import CDLL
CDLL('libgtk4-layer-shell.so')
import gi
gi.require_version("Gtk", "4.0")
gi.require_version('Gtk4LayerShell', '1.0')
from gi.repository import Gtk, GLib, Gtk4LayerShell as LayerShell

def on_activate(app):
    win = Gtk.ApplicationWindow(application=app)
    LayerShell.init_for_window(win)
    LayerShell.set_layer(win, LayerShell.Layer.TOP)
    LayerShell.auto_exclusive_zone_enable(win)
    LayerShell.set_anchor(win, LayerShell.Edge.TOP, True)
    LayerShell.set_anchor(win, LayerShell.Edge.LEFT, True)
    LayerShell.set_anchor(win, LayerShell.Edge.RIGHT, True)

    root = Gtk.Box()
    win.set_child(root)
    button = Gtk.Button(icon_name='system-search-symbolic')
    root.append(button)
    popover = Gtk.Popover(child=Gtk.Text())
    popover.set_parent(button)

    def clicked_cb(*args):
        print("setting mode to EXCLUSIVE")
        LayerShell.set_keyboard_mode(win, LayerShell.KeyboardMode.EXCLUSIVE)
        GLib.idle_add(popover.popup) # need to do this instead of popover.popup()

    def close_cb(*args):
        print("setting mode to NONE")
        LayerShell.set_keyboard_mode(win, LayerShell.KeyboardMode.NONE)

    button.connect('clicked', clicked_cb)
    popover.connect('closed', close_cb)
    win.present()

app = Gtk.Application(application_id='org.gtk.Example')
app.connect('activate', on_activate)
app.run(None)