Bug 1875369 [Wayland] Create IMContextWrapper without GdkWindow and allow to update/delete GdkWindow r=emilio

nsWindow::mGdkWindow is set/reset when nsWindow becomes visible/invisible so we need to update GdkWindow in IMContextWrapper according to it.

Differential Revision: https://phabricator.services.mozilla.com/D200270
This commit is contained in:
stransky 2024-02-13 09:15:33 +00:00
Родитель c5eb881965
Коммит 3de34039e7
2 изменённых файлов: 22 добавлений и 20 удалений

Просмотреть файл

@ -232,18 +232,11 @@ class SelectionStyleProvider final {
sHasShutDown = true;
}
// aGDKWindow is a GTK window which will be associated with an IM context.
void AttachTo(GdkWindow* aGDKWindow) {
GtkWidget* widget = nullptr;
// gdk_window_get_user_data() typically returns pointer to widget that
// window belongs to. If it's widget, fcitx retrieves selection colors
// of them. So, we need to overwrite its style.
gdk_window_get_user_data(aGDKWindow, (gpointer*)&widget);
if (GTK_IS_WIDGET(widget)) {
gtk_style_context_add_provider(gtk_widget_get_style_context(widget),
GTK_STYLE_PROVIDER(mProvider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
// mContainer associated with an IM context.
void AttachTo(MozContainer* aContainer) {
gtk_style_context_add_provider(
gtk_widget_get_style_context(GTK_WIDGET(aContainer)),
GTK_STYLE_PROVIDER(mProvider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
void OnThemeChanged() {
@ -417,21 +410,17 @@ nsDependentCSubstring IMContextWrapper::GetIMName() const {
}
void IMContextWrapper::Init() {
MozContainer* container = mOwnerWindow->GetMozContainer();
MOZ_ASSERT(container, "container is null");
GdkWindow* gdkWindow = gtk_widget_get_window(GTK_WIDGET(container));
// Overwrite selection colors of the window before associating the window
// with IM context since IME may look up selection colors via IM context
// to support any colored widgets.
SelectionStyleProvider::GetInstance()->AttachTo(gdkWindow);
SelectionStyleProvider::GetInstance()->AttachTo(
mOwnerWindow->GetMozContainer());
// NOTE: gtk_im_*_new() abort (kill) the whole process when it fails.
// So, we don't need to check the result.
// Normal context.
mContext = gtk_im_multicontext_new();
gtk_im_context_set_client_window(mContext, gdkWindow);
g_signal_connect(mContext, "preedit_changed",
G_CALLBACK(IMContextWrapper::OnChangeCompositionCallback),
this);
@ -503,7 +492,6 @@ void IMContextWrapper::Init() {
// Simple context
if (sUseSimpleContext) {
mSimpleContext = gtk_im_context_simple_new();
gtk_im_context_set_client_window(mSimpleContext, gdkWindow);
g_signal_connect(mSimpleContext, "preedit_changed",
G_CALLBACK(&IMContextWrapper::OnChangeCompositionCallback),
this);
@ -526,7 +514,6 @@ void IMContextWrapper::Init() {
// Dummy context
mDummyContext = gtk_im_multicontext_new();
gtk_im_context_set_client_window(mDummyContext, gdkWindow);
MOZ_LOG(gIMELog, LogLevel::Info,
("0x%p Init(), mOwnerWindow=%p, mContext=%p (im=\"%s\"), "
@ -553,6 +540,17 @@ IMContextWrapper::~IMContextWrapper() {
MOZ_LOG(gIMELog, LogLevel::Info, ("0x%p ~IMContextWrapper()", this));
}
void IMContextWrapper::SetGdkWindow(GdkWindow* aGdkWindow) {
MOZ_LOG(gIMELog, LogLevel::Info,
("0x%p GdkWindowChanged(%p)", this, aGdkWindow));
MOZ_ASSERT(!aGdkWindow || mOwnerWindow->GetGdkWindow() == aGdkWindow);
gtk_im_context_set_client_window(mContext, aGdkWindow);
if (mSimpleContext) {
gtk_im_context_set_client_window(mSimpleContext, aGdkWindow);
}
gtk_im_context_set_client_window(mDummyContext, aGdkWindow);
}
NS_IMETHODIMP
IMContextWrapper::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
const IMENotification& aNotification) {

Просмотреть файл

@ -117,6 +117,10 @@ class IMContextWrapper final : public TextEventDispatcherListener {
void OnUpdateComposition();
void OnLayoutChange();
// Set GdkWindow associated with IM context.
// It can be null which disables context operations.
void SetGdkWindow(GdkWindow* aGdkWindow);
TextEventDispatcher* GetTextEventDispatcher();
// TODO: Typically, new IM comes every several years. And now, our code