Hi all.
The attached patches implement X session management protocol (XSMP) support via libSM library.
Why XSMP?
When a user logs out with some instances of Geany running, XSMP support will allow those instances to safely save their configuration and gracefully ask the user about unsaved documents. The logout process will halt until Geany instances report that they are ready for shutdown.
When the user logs in, all Geany instances will be restored, with the same documents open. XSMP allows us to set a restart command for each Geany instance, so I just remember open documents by passing their file paths via command-line arguments.
Why libSM?
This library is as lightweight as possible. AFAIK, it is written by the authors of Xorg. It is also very popular, used in claws-mail and required by GNOME.
Patches:
[1.autotools.patch]
Building with X session management support if libSM library is present. Is the library is not installed or ./configure was run with `--enable-libsm=no', XSMP support is disabled.
I tested three cases: * libSM installed; * libSM installed, --enable-libsm=no; * libSM is not installed.
[2.waf.patch]
The same thing, but using waf instead of autotools. It is possible to disable XSMP support by passing `--disable-libsm' to `./waf congigure'.
Again, I tested three cases: * libSM installed; * libSM installed, --disable-libsm supplied; * libSM is not installed.
[3.refactor.patch]
This is probably the most doubtful part. In order to support XSMP properly, I need:
1) a non-destructive function to completely save Geany's state;
2) a function to quit Geany without saving anything and interacting with user.
I found `main_quit' function to satisfy the (2) requirements. But there was no function to satisfy (1), so I created a new one called `main_save' from `quit_app' function located in [callbacks.c].
I also had to
* add `force' argument to `document_close_all' function to be used when you do not want the function to ask about unsaved documents;
* create a trivial `project_save' function; add `save_config' argument to `project_close' function so that I can set it to FALSE when I already called `project_save'.
I wanted to reuse existing static `check_no_unsaved' function located in [callbacks.c], so I created new `document_any_unsaved' function from it.
I renamed `main_quit' function to `main_finalize' in order to point out that it does not interact with user and does not save anything (yes, it's doubtful and I'll change it back if you wish).
As far as I understand, none of the changed functions are exported for plugins, so the changes do not break API or ABI compatibility.
[4.implementation.patch]
The implementation. I did not to extract it to separate source code files so far, but I'll definitely do it if you wish.
XSMP requires a Geany instance to have the same XSMP client-ID when it is restarted by the session manager. I created new `--libsm-client-id' command-line option in order to specify it in restart command.
Actually, I looked into claws-mail source code and did not find any code to maintain client-ID there. Maybe maintaining client-ID is not very important, so I can remove `--libsm-client-id' option if anyone votes against it.
Problems:
1. Geany session management
I have to use `--no-session' command-line option in restart command. Please see code comments inside [4.implementation.patch], the "FIXME" section. There I described, why I have to use the option and why it is bad.
There is an easy fix: Geany instance should not save Geany session if the instance is run with `--new-instance' option. I consider this behaviour acceptable.
If all geany-devel subscribers agree, we should ask geany-users. If they agree too, anyone can write the necessary code, and I will change the handling of `--no-session' in my [4.implementation.patch].
Untested functionality:
1. Building on Windows
I had no opportunity to test building on Windows. Autotools and waf should simply fail to find libsm, thus XSMP support should be disabled.
TODO:
1. Handle all command-line options
Most of command-line options, specified when running Geany, should go to restart command. Things get little complicated as some options need special handling (for example, I think that `--line' and `--column' options should not go to restart command).
There is a little problem with this task: if I write all command-line handling code in my `sm_set_command_props' function, there will be code duplication between `sm_set_command_props' implementation and the array of GOptionEntry. Every time when a new command-line option is added, `sm_set_command_props' will have to be changed, particularly:
* the name of the variable, where the option's value is stored, will have to be duplicated there;
* the handling of the option will depend on option's type (int, string, etc.), which is directly corresponds to the type specified in the `entries' array.
I think, the best solution of this code duplication problem is some kind of a "reverse" parser of GOptionEntry's. It does not make sense to write one when you have 10 options or so, most of which have string values. But if such a "reverse" parser existed, I would consider using it. Information about whether a particular option should/shouldn't go to restart command could be placed in a separate array near `entries'.
Maybe write a plugin?
Yes, it is possible to write a plugin instead of building XSMP support straight into Geany. The plugin would require:
* some data when initializing (argv[0] and the value of `--libsm-client-id' command-line option);
* access to `cl_options' struct to set restart command properly;
* access to `main_save' and `main_finalize' functions in order to control Geany.
A bad thing about this is that we'll still have to hardcode `--libsm-client-id' command-line option in Geany's source code, even with XSMP support residing in a plugin.
Summary of questions
* Are there anyone who thinks that `--new-instance's should save Geany session?
* Are there any "reverse" parser of GOptionEntries?
* Should I write a plugin? If not, should I extract the code into separate source code files?
Hope you find it useful. Any thoughts?
Best regards, Eugene.