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.