gaphor / gaphor

Gaphor is the simple modeling tool
https://gaphor.org
1.88k stars 199 forks source link

IME support in popup editor of any element in a diagram #2647

Open pinxue opened 1 year ago

pinxue commented 1 year ago

Describe the bug

So far generaleditors.py connects key-pressed event to popdown on enter key pressing, but give no chance for IME to do its work.

To Reproduce

Steps to reproduce the behavior:

  1. Double click any elment to get popup editor and try to input with OS input method activated, IME doesn't work.

Expected behavior

IME should get the key events and convert input keys.

Screenshots

OS

Just tested on macOS, should impacts all platforms.

Version

Version of Gaphor: latest.

Additional information

The problem has root cause in on_enter function at gaphor/diagram/general/generaleditors.py Line 38.

     text_view.im_context_filter_keypress(text_view.get_current_event()):

Maybe fix it. I cannot test it yet because LibAdwaita is missing from macports.

amolenaar commented 1 year ago

Hi @pinxue, thank you for creating this issue.

How would IME work? Are there apps om macOS I can see it work? (I suppose I have to change my locale settings).

Does it work with gtk4-demo? I'm not sure about the state of support in GTK4 on macOS.

pinxue commented 1 year ago

You may switch input method here:

image

If there is no IME installed, you may add input methods in Settings - Keyboard - Text Input - Input Source - Edit:

image

The point is generaleditors intercepts all key pressing, filter out enter key and pass all other keys into text buffer, which just bypassed IME framework, im_context_filter_keypress just pass the event to it, if the key is consumed by IME it will return true. The code snippet post previous is not so right, I removed wrong part. I will try to do some verification later.

danyeaw commented 1 year ago

Thanks @pinxue for the bug report, having IME support is really important.

I can reproduce this on Windows. Next I'll try to test it on Linux.

danyeaw commented 1 year ago

I was not able to reproduce it on Linux, it looks like GNOME always uses ibus to pull up the IME candidate window, no matter what the app is supporting.

danyeaw commented 1 year ago

The proposed changes text_view.im_context_filter_keypress(text_view.get_current_event()) don't seem to fix this for me. It isn't really clear to me how the filter_keypress is supposed to work with ControllerKey.

danyeaw commented 1 year ago

This minimum example does work with a Gtk.Entry fine with IME.

import gi

gi.require_version("Gtk", "4.0")
from gi.repository import Gtk, GLib

class EntryWindow(Gtk.ApplicationWindow):
    def __init__(self, **kargs):
        super().__init__(**kargs, title="Entry Demo")

        self.set_size_request(200, 100)

        header = Gtk.HeaderBar()
        self.set_titlebar(header)

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        vbox.props.margin_start = 24
        vbox.props.margin_end = 24
        vbox.props.margin_top = 24
        vbox.props.margin_bottom = 24
        self.set_child(vbox)

        self.entry = Gtk.Entry()
        self.entry.set_text("Hello World")
        vbox.append(self.entry)

def on_activate(app):
    win = EntryWindow(application=app)
    win.present()

app = Gtk.Application(application_id="com.example.App")
app.connect("activate", on_activate)

app.run(None)

I don't think it is related to our key press event controllers at all. If I turn them all off in the instanteditors module, the problem still exists. So why does this Gtk.Entry work but ours in a popup window doesn't update. Maybe the IME popup is stealing focus away from our popup?

danyeaw commented 1 year ago

Yup, I think this is an upstream bug. The popover is losing focus when the IME selection Window opens, here is a min reproducible example:

import gi

gi.require_version("Gtk", "4.0")
from gi.repository import Gtk, GLib

class EntryWindow(Gtk.ApplicationWindow):
    def __init__(self, **kargs):
        super().__init__(**kargs, title="Entry Demo")

        self.set_size_request(200, 100)

        header = Gtk.HeaderBar()
        self.set_titlebar(header)

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        vbox.props.margin_start = 24
        vbox.props.margin_end = 24
        vbox.props.margin_top = 24
        vbox.props.margin_bottom = 24
        self.set_child(vbox)

        button = Gtk.Button.new_with_label("Click Me")
        button.connect("clicked", self.on_click_me_clicked)
        vbox.append(button)

        self.entry = Gtk.Entry()
        self.entry.set_text("Hello World")
        self.popover = Gtk.Popover.new()
        self.popover.set_child(self.entry)
        vbox.append(self.popover)

    def on_click_me_clicked(self, button):
        self.popover.set_visible(True)

def on_activate(app):
    win = EntryWindow(application=app)
    win.present()

app = Gtk.Application(application_id="com.example.App")
app.connect("activate", on_activate)

app.run(None)
danyeaw commented 1 year ago

Upstream issue now at https://gitlab.gnome.org/GNOME/gtk/-/issues/6041

danyeaw commented 1 year ago

@all-contributors please add @pinxue for bug

allcontributors[bot] commented 1 year ago

@danyeaw

I've put up a pull request to add @pinxue! :tada:

pinxue commented 1 year ago

Glad to see you root-caused it so soon and thanks for adding me. Sorry for not verifying the theory, I got some nasty dependency issue to build on my M1 Mac even with homebrew.

So far pycairo v1.24.0 installed by poetry references symbol cairo_get_hairline which is introduced by cairo 1.8, brew only has 1.6 and has other trouble to build from HEAD source. Here is the lock file generated on my env poetry.lock.txt.

By forcing pycairo 1.22.0 in pyproject.toml, it will pass but run into :

Failed to load shared library 'libgtk-4.1.dylib' referenced by the typelib: dlopen(libgtk-4.1.dylib, 0x0009): Symbol not found: _cairo_ft_font_face_create_for_pattern
  Referenced from: <6DE01E30-C883-364F-A1C4-CAE5BEC1ADB1> /opt/homebrew/Cellar/pango/1.50.14/lib/libpangocairo-1.0.0.dylib
  Expected in:     <C1707E34-ED90-34F5-8B6E-05E90798E712> /opt/homebrew/Cellar/cairo/1.16.0_5/lib/libcairo.2.dylib

Now, I'm quite curious about how the release package for mac is constructed.

amolenaar commented 1 year ago

@pinxue for macOS we take whatever is current in Homebrew and bundle it.

macOS build: https://github.com/gaphor/gaphor/blob/main/.github/workflows/full-build.yml#L144 and associating package commands: https://github.com/gaphor/gaphor/blob/main/.github/actions/macos_dmg/action.yml.

I had no trouble installing Gaphor (poetry install) on my Mac, with updated homebrew.

amolenaar commented 1 year ago

On macOS I see the IME popup appear when you edit a text entry field in, say, the property editor. Nothing appears when you edit text in a popup window. It also doesn't work with drop-down widgets, like when selecting a metaclass.

danyeaw commented 1 year ago

So it sounds like the issues might be slightly different between macOS and Windows.

amolenaar commented 1 year ago

I think it is, since both use different backend code.

amolenaar commented 8 months ago

Fixed on macOS by https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/7041.

It does fix macOS keybindings in popups as well.

danyeaw commented 8 months ago

@amolenaar Nice one!