After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 502446 - Add XSETTINGS support for immodule
Add XSETTINGS support for immodule
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: .General
unspecified
Other Linux
: Normal enhancement
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2007-12-08 06:28 UTC by Akira TAGOH
Modified: 2009-01-12 18:14 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
proposed patch (7.57 KB, patch)
2007-12-08 06:30 UTC, Akira TAGOH
needs-work Details | Review
proposed patch: take 2 (13.56 KB, patch)
2007-12-10 15:13 UTC, Akira TAGOH
needs-work Details | Review
proposed patch: take 3 (14.75 KB, patch)
2007-12-11 09:19 UTC, Akira TAGOH
none Details | Review
proposed patch: take 4 (15.59 KB, patch)
2007-12-11 12:00 UTC, Akira TAGOH
needs-work Details | Review
my own patch (8.45 KB, patch)
2007-12-16 07:39 UTC, Matthias Clasen
none Details | Review
new patch (11.05 KB, patch)
2007-12-17 15:25 UTC, Matthias Clasen
committed Details | Review

Description Akira TAGOH 2007-12-08 06:28:00 UTC
Currently all the applications have to be restarted to apply the changes of immodule and need to specify GTK_IM_MODULE environment variable. this issue can be improved with XSETTINGS support.

This proposal is a first step to get rid of the sort of restarting to do something with the input method.
Comment 1 Akira TAGOH 2007-12-08 06:30:28 UTC
Created attachment 100573 [details] [review]
proposed patch
Comment 2 Matthias Clasen 2007-12-09 06:52:19 UTC
The parts for adding the x setting and gtk setting are looking fine.

Some comments on the immodule part:

_gtk_im_module_get_default_context_id() is called exactly once, and you are replacing that call. Therefore there is no need to add a new
_gtk_im_module_get_default_context_id_from_settings() function, simply
add the client_window argument to the existing function and add the
settings-handling code there.

(Not your fault, but) the return type of both get_default_context_id 
variants should be gchar *, not const gchar *, since they return 
allocated memory.

+  if (client_window == NULL)
+    g_warning("No client window is set.");
+  if (client_window == NULL ||
+      !GDK_IS_DRAWABLE (client_window))
+    return _gtk_im_module_get_default_context_id (locale);

I'd get rid of the warning, and simply do this as

  if (client_window != NULL) 
    {
      ... settings-handling code ...

      return context_id;
    }

  ... old code from get_default_context_id ...


If you want to keep a check for client_window, do a 

  g_return_val_if_fail (client_window == NULL || GDK_IS_DRAWABLE (client_window), NULL);

But I don't think that is necessary.


One thing I'd reconsider when combining the two get_default_context_id
functions into a single one is whether you really want the setting to
override the envvar. In any case, the priorities need to be documented,
perhaps in the paragraph on the GTK_IM_MODULE envvar in 
docs/reference/gtk/running.sgml and in the docs for the gtk-im-module
setting.


+      /* destroy the slave and the global_context_id because it might
+       * be set the different thing from XSETTINGS
+       */

Setting the global_context_id to a value that depends on the screen on which 
an im context happens to lie does not really work. Also, randomly freeing
global_context_id is problematic, considering the following:

     multicontext->context_id = global_context_id;
  
You probably need to switch to giving each multicontext its own allocated
context_id. Don't forget to free it in finalize.






Comment 3 Akira TAGOH 2007-12-10 00:47:12 UTC
(In reply to comment #2)
> _gtk_im_module_get_default_context_id() is called exactly once, and you are
> replacing that call. Therefore there is no need to add a new
> _gtk_im_module_get_default_context_id_from_settings() function, simply
> add the client_window argument to the existing function and add the
> settings-handling code there.

I have been worrying about the ABI breakage since it was declared as public API. even though the function name has a prefix '_'. if that change is acceptable, I'll go that way.

> (Not your fault, but) the return type of both get_default_context_id 
> variants should be gchar *, not const gchar *, since they return 
> allocated memory.

You're right.

> I'd get rid of the warning, and simply do this as

No problem. I should do that, it was just to check if there are any cases that applications goes through there without client_window.

> If you want to keep a check for client_window, do a 
> 
>   g_return_val_if_fail (client_window == NULL || GDK_IS_DRAWABLE
> (client_window), NULL);
> 
> But I don't think that is necessary.

I agree.

> One thing I'd reconsider when combining the two get_default_context_id
> functions into a single one is whether you really want the setting to
> override the envvar. In any case, the priorities need to be documented,
> perhaps in the paragraph on the GTK_IM_MODULE envvar in 
> docs/reference/gtk/running.sgml and in the docs for the gtk-im-module
> setting.

Hmm, ok. well, I was thinking of overriding GTK_IM_MODULE with XSETTINGS because  in most distributions, they set GTK_IM_MODULE to ensure bringing up IM they want.  but indeed this entirely makes GTK_IM_MODULE unusable. so it may be good to be changed outside gtk+. I mean it follows to XSETTINGS if GTK_IM_MODULE isn't set.

> Setting the global_context_id to a value that depends on the screen on which 
> an im context happens to lie does not really work. Also, randomly freeing
> global_context_id is problematic, considering the following:
> 
>      multicontext->context_id = global_context_id;
> 
> You probably need to switch to giving each multicontext its own allocated
> context_id. Don't forget to free it in finalize.
> 

Ok, thanks for your comment.
Comment 4 Akira TAGOH 2007-12-10 15:13:36 UTC
Created attachment 100693 [details] [review]
proposed patch: take 2

attached the re-worked patch, including a fix of crash issue and use GtkSettings to deliver the changes from IM menu instead of global_context_id.
Comment 5 Matthias Clasen 2007-12-10 16:26:29 UTC
> I have been worrying about the ABI breakage since it was declared as public
> API. even though the function name has a prefix '_'. if that change is
> acceptable, I'll go that way.

_-prefixed functions are not exported from the .so, so there is no danger of anybody outside gtk using it.


/**
  * _gtk_im_module_get_default_context_id:
+ * @widget: a #GtkWidget
  * @locale: a locale id in the form 'en_US'

That should be 

@client_window: the client window 

instead.


  gtk_im_multicontext_set_slave (multicontext, NULL, TRUE);
+  if (multicontext->priv->settings)
+    {
+      g_signal_handlers_disconnect_by_func (multicontext->priv->settings,
+					    G_CALLBACK (gtk_im_multicontext_changes_im_module),
+					    multicontext);
+    }


GTK+ coding style omits the {} if the body is a single statement.


 if (GDK_IS_DRAWABLE (window) &&
+      multicontext->priv->client_window != window)
+    {
+      GdkScreen *screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
+
+      if (multicontext->priv->settings)
+        {
+          g_signal_handlers_disconnect_by_func (multicontext->priv->settings,
+						G_CALLBACK (gtk_im_multicontext_changes_im_module),
+						multicontext);
+	}
+      if (screen)
+        multicontext->priv->settings = gtk_settings_get_for_screen (screen);
+      else
+	multicontext->priv->settings = gtk_settings_get_default ();
 

It would perhaps be nicer to only do the full re-get-settings-and-reconstruct-slave thing if the settings actually changed ?
many different windows can give you the same settings, thus the same slave...


Looks good in general, otherwise. Have you tested it a bit ?

One thing that is still needed is some documentation about the priorities of
GTK_IM_MODULE envvar vs gtk-im-module setting
Comment 6 Akira TAGOH 2007-12-11 09:19:25 UTC
Created attachment 100749 [details] [review]
proposed patch: take 3
Comment 7 Akira TAGOH 2007-12-11 10:35:13 UTC
(In reply to comment #5)
> _-prefixed functions are not exported from the .so, so there is no danger of
> anybody outside gtk using it.

Ok, I see.

> /**
>   * _gtk_im_module_get_default_context_id:
> + * @widget: a #GtkWidget
>   * @locale: a locale id in the form 'en_US'
> 
> That should be 
> 
> @client_window: the client window 
> 
> instead.

Fixed.

> GTK+ coding style omits the {} if the body is a single statement.

I have looked through the whole code in the patch and corrected them.

> It would perhaps be nicer to only do the full
> re-get-settings-and-reconstruct-slave thing if the settings actually changed ?
> many different windows can give you the same settings, thus the same slave...

Sure. fixed.

> Looks good in general, otherwise. Have you tested it a bit ?

Yes, I have tested with some applications and among some widgets, and looks good so far.

> One thing that is still needed is some documentation about the priorities of
> GTK_IM_MODULE envvar vs gtk-im-module setting

I have added some in the latest patch though, is it close to what you expect?
Comment 8 Akira TAGOH 2007-12-11 12:00:09 UTC
Created attachment 100758 [details] [review]
proposed patch: take 4

Sorry, found a bug that doesn't apply the change from the input method menu.
Comment 9 Matthias Clasen 2007-12-11 14:57:13 UTC
Hmm, that looks wrong to me.

You are right, that calling gtk_settings_set_string_property
in activate_cb will not work as intended, since the setting is global for the application (or at least shared by all windows on a screen) whereas the input method menu is supposed to only change a specific im context.

You probably need to add something like gtk_im_multicontext_set_context_id()
and call that from the activate_cb. That function would then have to remember that the context was explicitly set, so that it knows to ignore changes of the setting.

We probably also need to change the meaning of the "Default" menutitem to not mean
"imcontextsimple" but rather "use the setting".
Comment 10 Matthias Clasen 2007-12-11 15:01:36 UTC
That being said, I am not sure why you thought you needed the changed_from_menu
boolean. The (wrong, as explained above) call to gtk_settings_set_string_property
should set the setting with application priority, which is higher than xsettings priority, so a change from the menu should have an effect, even without the 
changed_from_menu boolean.
Comment 11 Akira TAGOH 2007-12-12 00:23:32 UTC
(In reply to comment #9)
> Hmm, that looks wrong to me.
> 
> You are right, that calling gtk_settings_set_string_property
> in activate_cb will not work as intended, since the setting is global for the
> application (or at least shared by all windows on a screen) whereas the input
> method menu is supposed to only change a specific im context.

No, actually the change from the IM menu effects to all the IM contexts on the application, and global_context_id was needed to do that. what I made mistake in the previous patch was actually the change is just ignored when GTK_IM_MODULE is set, because now GTK_IM_MODULE takes a priority.

> You probably need to add something like gtk_im_multicontext_set_context_id()
> and call that from the activate_cb. That function would then have to remember
> that the context was explicitly set, so that it knows to ignore changes of the
> setting.

changed_from_menu boolean was supposed to do it.

> We probably also need to change the meaning of the "Default" menutitem to not
> mean
> "imcontextsimple" but rather "use the setting".

Indeed, current behavior may causes misleading if one changes the IM context from the menu and changes the IM context through XSETTINGS after that. in this case, it doesn't effect to such application. I don't know if this is correct behavior. but actually it didn't.  However it's still useful that I can see from the menu which IM is currently selected. so I'll miss that "feature" if we change "Default" to "use the setting" in the label or the behavior.

(In reply to comment #10)
> That being said, I am not sure why you thought you needed the changed_from_menu
> boolean. The (wrong, as explained above) call to
> gtk_settings_set_string_property
> should set the setting with application priority, which is higher than
> xsettings priority, so a change from the menu should have an effect, even
> without the 
> changed_from_menu boolean.

Right but as I mentioned above, I needed to ignore GTK_IM_MODULE envvar explicitly for the change from the menu.
Comment 12 Matthias Clasen 2007-12-13 04:03:57 UTC
I don't like the changed_from_menu thing. I'd much rather have a very simple behaviour a la:

if GTK_IM_MODULE is set and yields a im context, use that

otherwise, if the gtk-im-module setting yields a im context, use that

else determine the im context from the locale

And then just make the menu set the setting; we'll have to add a menu item for 
"System" (and probably have to rename the "Default" to be "None" instead). 
The "System" menuitem must unset the setting. (Unfortunately, there is no way to "unset" an application-set setting currently, but that is fixable)


Doing things this way has 2 consequences which you may not find ideal:

1) The envvar wins, period. Don't like it ? Don't set it...

2) If != System has been selected in the menus, the app does not react to global settings changes until the menu is set back to System.

But it has the advantage of giving an easily understandable algorithm.


Comment 13 Murray Cumming 2007-12-14 07:39:06 UTC
By the way, where is the GTK_IM_MODULE environment variable documented? I've seen it mentioned, but I never got it to work.
Comment 15 Matthias Clasen 2007-12-16 07:39:12 UTC
Created attachment 101042 [details] [review]
my own patch

Ok, unsetting a setting turned out to be harder than I thought, so here is a patch that does things a bit differently. Notable differences to your patch:

- uses only a single signal handler for the setting, not one per context
- both setting and menu set global_context_id and the last one to set it wins
- I've made _gtk_im_module_get_default_context_id actually return const again,
  to simplify memory management

I haven't tested changes of the setting, but changing from the menu works fine.
If it is necessary to reset all contexts when the setting changes (instead of 
waiting for the next focus-in), then we must keep all contexts in a list and iterate over them in im_context_setting_changed().
Comment 16 Akira TAGOH 2007-12-17 07:10:28 UTC
(In reply to comment #15)
> I haven't tested changes of the setting, but changing from the menu works fine.
> If it is necessary to reset all contexts when the setting changes (instead of 
> waiting for the next focus-in), then we must keep all contexts in a list and
> iterate over them in im_context_setting_changed().
> 

I have tried your patch, but unfortunately gtk+ applications got a crash after sending the change through XSETTINGS. I'll look into it.
Comment 17 Akira TAGOH 2007-12-17 08:13:31 UTC
There is three or four problems in your patch:

1. as I described in the previous comment, the following code has to check if global_context_id is NULL:

  /* If the globalcontext type is different from the context we were
   * using before, get rid of the old slave and create a new one
   * for the new global context type
   */
  if (!multicontext->context_id ||
      strcmp (global_context_id, multicontext->context_id) != 0)
    gtk_im_multicontext_set_slave (multicontext, NULL, FALSE);

2. when the applications is closing, the warnings happens like:

Gdk-CRITICAL **: gdk_drawable_get_screen: assertion `GDK_IS_DRAWABLE (drawable)' failed.

3. gtk-im-module isn't applied at startup time if it has the different settings to the default thing came from current locale. this issue happens global_context_id already has something when the client window is set.

4. I'm not sure what the behavior is useful and people are expecting, but if people explicitly changes the IM settings from the menu say, XSETTINGS stuff shouldn't affects to such applications IMHO. someone may want to keep current settings for some reason, otherwise they could just change it through XSETTINGS.
Comment 18 Matthias Clasen 2007-12-17 14:21:35 UTC
Ok, thanks for testing.

For 2.,
'lll
+  screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
+  if (screen)
+    settings = gtk_settings_get_for_screen (screen);
+  else
+    settings = gtk_settings_get_default ();

This part of the set_client_window() function needs to be wrapped in
if (window) 
  {
   }


For 3., you probably need to reset global_context_id in the 

  if (!connected) 
    {
    }

block in the same function.


For 4., I don't really care at all, since as far as I am concerned, the menu will never be visible. Anyway, to implement the behaviour you propose, I'll introduce another static variable, user_context_id, and have the menus set that,
and take it into account when calculating the new id.


Let me produce a new patch with those fixes.
Comment 19 Matthias Clasen 2007-12-17 15:25:45 UTC
Created attachment 101127 [details] [review]
new patch
Comment 20 Akira TAGOH 2007-12-18 02:25:59 UTC
Thank you for updates. it works fine as expected.
Comment 21 Matthias Clasen 2007-12-18 03:27:35 UTC
2007-12-17  Matthias Clasen  <mclasen@redhat.com>

        * gtk/gtksettings.c: Add a gtk-im-module GTK setting
        * gdk/win32/gdkproperty-win32.c:
        * gdk/x11/gdksettings.c: ...and back it by a Gtk/IMModule X setting.

        * gtk/gtkimmodule.[hc]:
        * gtk/gtkimmulticontext.[hc]: When determining the default context,
        look at the gtk-im-module setting, and listen for changes to the
        setting.  (#502446, Akira Tagoh)
Comment 22 Peng Huang 2008-03-12 03:39:50 UTC
Hi Matthias Clasen,  Akira TAGOH,

I tested it. I found gtk does not destroy im context immediately, when the im module is changed by xsettings. So some IMs will not exit immediately for those alive clients. And I must click every input widgets on the screen, and then the IM will exit. It is very weird. (especially there are many input widgets on the screen.) Could you fix this problem? 
Comment 23 Murray Cumming 2008-04-16 21:50:14 UTC
Haung, could you file a bug or reopen this bug? Maybe you could attach a test case.
Comment 24 Peng Huang 2008-04-17 01:43:05 UTC
Filed bug 528502.
Comment 25 Murray Cumming 2009-01-12 11:08:28 UTC
I don't quite understand what this does. It's documented as 
"Which IM module should be used by default."
http://library.gnome.org/devel/gtk/unstable/GtkSettings.html#GtkSettings--gtk-im-module

Does that mean I can change the IM at runtime, if the user has never chosen an IM  from the context menu? Can I change it again afterwards?
Comment 26 Matthias Clasen 2009-01-12 18:14:11 UTC
Yes to both questions.

If you go to the context menu you'll see that the first entry is "System (...)", which will bring you back to the im selected by the setting.