Browse Source

Port xed to dbus and GtkApplication

This further improves on the port to GtkSource API's and cleans up a ton of
legacy code in xed based on upstream changes in Gedit.
tags/1.4.0
JosephMcc 4 years ago
parent
commit
2aa009cb76
45 changed files with 1423 additions and 6547 deletions
  1. +8
    -20
      configure.ac
  2. +9
    -0
      data/Makefile.am
  3. +1
    -0
      debian/xed.install
  4. +0
    -2
      docs/reference/xed.types
  5. +1
    -3
      plugins/filebrowser/xed-file-browser-plugin.c
  6. +2
    -2
      plugins/sort/xed-sort-plugin.c
  7. +2
    -2
      plugins/spell/xed-spell-language-dialog.c
  8. +2
    -2
      plugins/time/xed-time-plugin.c
  9. +0
    -1
      po/POTFILES.in
  10. +2
    -16
      xed/Makefile.am
  11. +0
    -396
      xed/bacon-message-connection.c
  12. +0
    -43
      xed/bacon-message-connection.h
  13. +1
    -2
      xed/dialogs/xed-encodings-dialog.c
  14. +3
    -6
      xed/dialogs/xed-preferences-dialog.c
  15. +0
    -39
      xed/smclient/Makefile.am
  16. +0
    -1502
      xed/smclient/eggdesktopfile.c
  17. +0
    -160
      xed/smclient/eggdesktopfile.h
  18. +0
    -39
      xed/smclient/eggsmclient-private.h
  19. +0
    -1365
      xed/smclient/eggsmclient-xsmp.c
  20. +0
    -573
      xed/smclient/eggsmclient.c
  21. +0
    -117
      xed/smclient/eggsmclient.h
  22. +702
    -391
      xed/xed-app.c
  23. +29
    -18
      xed/xed-app.h
  24. +73
    -48
      xed/xed-commands-file.c
  25. +18
    -16
      xed/xed-commands-help.c
  26. +2
    -2
      xed/xed-commands-search.c
  27. +2
    -5
      xed/xed-commands.h
  28. +67
    -67
      xed/xed-dirs.c
  29. +15
    -10
      xed/xed-dirs.h
  30. +52
    -39
      xed/xed-document.c
  31. +0
    -99
      xed/xed-help.c
  32. +0
    -44
      xed/xed-help.h
  33. +45
    -48
      xed/xed-metadata-manager.c
  34. +7
    -6
      xed/xed-metadata-manager.h
  35. +8
    -8
      xed/xed-searchbar.c
  36. +4
    -4
      xed/xed-searchbar.h
  37. +0
    -618
      xed/xed-session.c
  38. +0
    -47
      xed/xed-session.h
  39. +13
    -14
      xed/xed-settings.c
  40. +240
    -111
      xed/xed-tab.c
  41. +35
    -9
      xed/xed-tab.h
  42. +1
    -1
      xed/xed-view.c
  43. +65
    -32
      xed/xed-window.c
  44. +5
    -5
      xed/xed-window.h
  45. +9
    -615
      xed/xed.c

+ 8
- 20
configure.ac View File

@@ -49,12 +49,6 @@ dnl toolbar style for GSettings schemas
TOOLBAR_STYLE="XED_TOOLBAR_SYSTEM"
AC_SUBST(TOOLBAR_STYLE)

# GLib min/max required versions
AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_36],
[Warn on use of APIs added after GLib 2.36])
AC_DEFINE([GLIB_VERSION_MIN_REQUIRED], [GLIB_VERSION_2_36],
[Warn on use of APIs deprecated before GLib 2.36])

dnl ===============================================================
dnl Expanded dirs
dnl ===============================================================
@@ -151,12 +145,12 @@ dnl ================================================================
PKG_CHECK_MODULES(GMODULE,gmodule-2.0,[GMODULE_ADD="gmodule-2.0"],[GMODULE_ADD=""])
PKG_CHECK_MODULES(XED, [
libxml-2.0 >= 2.5.0
glib-2.0 >= 2.36.0
glib-2.0 >= 2.40.0
$GMODULE_ADD
gthread-2.0 >= 2.13.0
gio-2.0 >= 2.26.0
gtk+-3.0 >= 3.10.0
gtksourceview-3.0 >= 2.9.7
gio-2.0 >= 2.40.0
gtk+-3.0 >= 3.14.0
gtksourceview-3.0 >= 3.14.3
libpeas-1.0 >= 1.12.0
libpeas-gtk-1.0 >= 1.12.0
])
@@ -169,19 +163,14 @@ XED_LIBS="$XED_LIBS $X11_LIBS"
AC_SUBST(XED_CFLAGS)
AC_SUBST(XED_LIBS)

PKG_CHECK_MODULES(EGG_SMCLIENT, [sm >= 1.0.0])

AC_SUBST(EGG_SMCLIENT_CFLAGS)
AC_SUBST(EGG_SMCLIENT_LIBS)

# Introspection
GOBJECT_INTROSPECTION_CHECK([0.9.3])

if test "$found_introspection" = "yes"; then
have_introspection=yes
AC_DEFINE([HAVE_INTROSPECTION], [1], [Define to enable GObject Introspection])
enable_introspection=yes
AC_DEFINE([ENABLE_INTROSPECTION], [1], [Define to enable GObject Introspection])
else
have_introspection=no
enable_introspection=no
fi

dnl ================================================================
@@ -235,7 +224,6 @@ data/Makefile
docs/Makefile
docs/reference/Makefile
xed/dialogs/Makefile
xed/smclient/Makefile
xed/Makefile
help/Makefile
pixmaps/Makefile
@@ -264,5 +252,5 @@ Configuration:
Compiler: ${CC}
Spell Plugin enabled: $enable_enchant
Gvfs metadata enabled: $enable_gvfs_metadata
GObject Introspection: ${have_introspection}
GObject Introspection: ${enable_introspection}
"

+ 9
- 0
data/Makefile.am View File

@@ -13,6 +13,13 @@ gsettings_SCHEMAS = org.x.editor.gschema.xml

@GSETTINGS_RULES@

servicedir = $(datadir)/dbus-1/services
service_in_files = org.x.editor.service.in
service_DATA = $(service_in_files:.service.in=.service)

$(service_DATA): $(service_in_files) Makefile
@sed -e "s|\@bindir\@|$(bindir)|" $<> $@

man_MANS = xed.1

pkgconfigdir = $(libdir)/pkgconfig
@@ -24,12 +31,14 @@ bugreport_SCRIPTS = xed-bugreport.sh
EXTRA_DIST = \
$(appdata_in_files) \
$(desktop_in_files) \
$(service_in_files) \
$(man_MANS) \
xed.pc.in \
xed-bugreport.sh.in

CLEANFILES = \
$(desktop_DATA) \
$(service_DATA) \
$(gsettings_SCHEMAS) \
$(pkgconfig_DATA) \
$(appdata_DATA)


+ 1
- 0
debian/xed.install View File

@@ -4,4 +4,5 @@ usr/lib/xed/xed-bugreport.sh
usr/lib/*/xed/plugins/*.plugin
usr/lib/*/xed/plugins/*.so
usr/share/applications/xed.desktop
usr/share/dbus-1/
usr/share/man/

+ 0
- 2
docs/reference/xed.types View File

@@ -1,5 +1,3 @@
egg_sm_client_get_type
egg_sm_client_xsmp_get_type
xed_app_activatable_get_type
xed_app_get_type
xed_close_button_get_type


+ 1
- 3
plugins/filebrowser/xed-file-browser-plugin.c View File

@@ -761,13 +761,11 @@ on_rename_cb (XedFileBrowserStore *store,
GFile *newfile,
XedWindow *window)
{
XedApp *app;
GList *documents;
GList *item;

/* Find all documents and set its uri to newuri where it matches olduri */
app = xed_app_get_default ();
documents = xed_app_get_documents (app);
documents = xed_app_get_documents (XED_APP (g_application_get_default ()));

for (item = documents; item; item = item->next)
{


+ 2
- 2
plugins/sort/xed-sort-plugin.c View File

@@ -34,7 +34,7 @@
#include <xed/xed-window-activatable.h>
#include <xed/xed-debug.h>
#include <xed/xed-utils.h>
#include <xed/xed-help.h>
#include <xed/xed-app.h>

#define XED_SORT_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), XED_TYPE_SORT_PLUGIN, XedSortPluginPrivate))

@@ -110,7 +110,7 @@ sort_dialog_response_handler (GtkDialog *dlg,
break;

case GTK_RESPONSE_HELP:
xed_help_display (GTK_WINDOW (dlg), NULL, "xed-sort-plugin");
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dlg), NULL, "xed-sort-plugin");
break;

case GTK_RESPONSE_CANCEL:


+ 2
- 2
plugins/spell/xed-spell-language-dialog.c View File

@@ -34,7 +34,7 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <xed/xed-utils.h>
#include <xed/xed-help.h>
#include <xed/xed-app.h>
#include "xed-spell-language-dialog.h"
#include "xed-spell-checker-language.h"

@@ -70,7 +70,7 @@ dialog_response_handler (GtkDialog *dlg,
{
if (res_id == GTK_RESPONSE_HELP)
{
xed_help_display (GTK_WINDOW (dlg), NULL, "xed-spell-checker-plugin");
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dlg), NULL, "xed-spell-checker-plugin");

g_signal_stop_emission_by_name (dlg, "response");
}


+ 2
- 2
plugins/time/xed-time-plugin.c View File

@@ -32,7 +32,7 @@
#include <time.h>

#include "xed-time-plugin.h"
#include <xed/xed-help.h>
#include <xed/xed-app.h>

#include <glib/gi18n-lib.h>
#include <glib.h>
@@ -916,7 +916,7 @@ choose_format_dialog_response_cb (GtkWidget *widget,
case GTK_RESPONSE_HELP:
{
xed_debug_message (DEBUG_PLUGINS, "GTK_RESPONSE_HELP");
xed_help_display (GTK_WINDOW (widget), NULL, "xed-insert-date-time-plugin");
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (widget), NULL, "xed-insert-date-time-plugin");
break;
}
case GTK_RESPONSE_OK:


+ 0
- 1
po/POTFILES.in View File

@@ -17,7 +17,6 @@ xed/xed-commands-search.c
xed/xed-debug.c
xed/xed-document.c
xed/xed-documents-panel.c
xed/xed-encodings.c
xed/xed-encodings-combo-box.c
xed/xed-file-chooser-dialog.c
xed/xed-gio-document-loader.c


+ 2
- 16
xed/Makefile.am View File

@@ -1,5 +1,5 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = dialogs smclient
SUBDIRS = dialogs

bin_PROGRAMS = xed

@@ -8,7 +8,6 @@ noinst_LTLIBRARIES = libxed.la
AM_CPPFLAGS = \
-I$(top_srcdir) \
-I$(srcdir) \
-I$(srcdir)/smclient \
$(XED_CFLAGS) \
$(WARN_CFLAGS) \
$(INTROSPECTION_CFLAGS) \
@@ -22,7 +21,6 @@ xed_SOURCES = \
xed_LDADD = \
libxed.la \
$(XED_LIBS) \
$(EGG_SMCLIENT_LIBS) \
$(INTROSPECTION_LIBS)

xed_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"
@@ -30,8 +28,7 @@ xed_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"
libxed_la_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"

libxed_la_LIBADD = \
dialogs/libdialogs.la \
smclient/libeggsmclient.la
dialogs/libdialogs.la

# XED_LIBS must be the last to ensure correct order on some platforms
libxed_la_LIBADD += $(XED_LIBS) -lICE
@@ -52,7 +49,6 @@ NOINST_H_FILES = \
xed-plugins-engine.h \
xed-print-job.h \
xed-print-preview.h \
xed-session.h \
xed-settings.h \
xed-status-combo-box.h \
xed-tab-label.h \
@@ -69,7 +65,6 @@ INST_H_FILES = \
xed-document.h \
xed-encodings-combo-box.h \
xed-file-chooser-dialog.h \
xed-help.h \
xed-message-bus.h \
xed-message-type.h \
xed-message.h \
@@ -111,7 +106,6 @@ libxed_c_files = \
xed-documents-panel.c \
xed-encodings-combo-box.c \
xed-file-chooser-dialog.c \
xed-help.c \
xed-history-entry.c \
xed-io-error-message-area.c \
xed-message-bus.c \
@@ -123,7 +117,6 @@ libxed_c_files = \
xed-print-job.c \
xed-print-preview.c \
xed-progress-message-area.c \
xed-session.c \
xed-settings.c \
xed-searchbar.c \
xed-statusbar.c \
@@ -140,7 +133,6 @@ libxed_c_files = \
libxed_la_SOURCES = \
$(BUILT_SOURCES) \
$(libxed_c_files) \
$(BACON_FILES) \
$(POSIXIO_FILES) \
$(NOINST_H_FILES) \
$(INST_H_FILES)
@@ -205,10 +197,4 @@ endif
dist-hook:
cd $(distdir); rm -f $(BUILT_SOURCES)

BACON_DIR=$(srcdir)/../../libbacon/src/
BACON_FILES=bacon-message-connection.h bacon-message-connection.c

regenerate-built-sources:
BACONFILES="$(BACON_FILES)" BACONDIR="$(BACON_DIR)" $(top_srcdir)/xed/update-from-bacon.sh

-include $(top_srcdir)/git.mk

+ 0
- 396
xed/bacon-message-connection.c View File

@@ -1,396 +0,0 @@
/*
* Copyright (C) 2003 Bastien Nocera <hadess@hadess.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>

#include "bacon-message-connection.h"

#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 108
#endif

struct BaconMessageConnection {
/* A server accepts connections */
gboolean is_server;

/* The socket path itself */
char *path;

/* File descriptor of the socket */
int fd;
/* Channel to watch */
GIOChannel *chan;
/* Event id returned by g_io_add_watch() */
int conn_id;

/* Connections accepted by this connection */
GSList *accepted_connections;

/* callback */
void (*func) (const char *message, gpointer user_data);
gpointer data;
};

static gboolean
test_is_socket (const char *path)
{
struct stat s;

if (stat (path, &s) == -1)
return FALSE;

if (S_ISSOCK (s.st_mode))
return TRUE;

return FALSE;
}

static gboolean
is_owned_by_user_and_socket (const char *path)
{
struct stat s;

if (stat (path, &s) == -1)
return FALSE;

if (s.st_uid != geteuid ())
return FALSE;

if ((s.st_mode & S_IFSOCK) != S_IFSOCK)
return FALSE;
return TRUE;
}

static gboolean server_cb (GIOChannel *source,
GIOCondition condition, gpointer data);

static gboolean
setup_connection (BaconMessageConnection *conn)
{
g_return_val_if_fail (conn->chan == NULL, FALSE);

conn->chan = g_io_channel_unix_new (conn->fd);
if (!conn->chan) {
return FALSE;
}
g_io_channel_set_line_term (conn->chan, "\n", 1);
conn->conn_id = g_io_add_watch (conn->chan, G_IO_IN, server_cb, conn);

return TRUE;
}

static void
accept_new_connection (BaconMessageConnection *server_conn)
{
BaconMessageConnection *conn;
int alen;

g_return_if_fail (server_conn->is_server);

conn = g_new0 (BaconMessageConnection, 1);
conn->is_server = FALSE;
conn->func = server_conn->func;
conn->data = server_conn->data;

conn->fd = accept (server_conn->fd, NULL, (guint *)&alen);

server_conn->accepted_connections =
g_slist_prepend (server_conn->accepted_connections, conn);

setup_connection (conn);
}

static gboolean
server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
{
BaconMessageConnection *conn = (BaconMessageConnection *)data;
char *message, *subs, buf;
int cd, rc, offset;
gboolean finished;

offset = 0;
if (conn->is_server && conn->fd == g_io_channel_unix_get_fd (source)) {
accept_new_connection (conn);
return TRUE;
}
message = g_malloc (1);
cd = conn->fd;
rc = read (cd, &buf, 1);
while (rc > 0 && buf != '\n')
{
message = g_realloc (message, rc + offset + 1);
message[offset] = buf;
offset = offset + rc;
rc = read (cd, &buf, 1);
}
if (rc <= 0) {
g_io_channel_shutdown (conn->chan, FALSE, NULL);
g_io_channel_unref (conn->chan);
conn->chan = NULL;
close (conn->fd);
conn->fd = -1;
g_free (message);
conn->conn_id = 0;

return FALSE;
}
message[offset] = '\0';

subs = message;
finished = FALSE;

while (finished == FALSE && *subs != '\0')
{
if (conn->func != NULL)
(*conn->func) (subs, conn->data);

subs += strlen (subs) + 1;
if (subs - message >= offset)
finished = TRUE;
}

g_free (message);

return TRUE;
}

static char *
find_file_with_pattern (const char *dir, const char *pattern)
{
GDir *filedir;
char *found_filename;
const char *filename;
GPatternSpec *pat;

filedir = g_dir_open (dir, 0, NULL);
if (filedir == NULL)
return NULL;

pat = g_pattern_spec_new (pattern);
if (pat == NULL)
{
g_dir_close (filedir);
return NULL;
}

found_filename = NULL;

while ((filename = g_dir_read_name (filedir)))
{
if (g_pattern_match_string (pat, filename))
{
char *tmp = g_build_filename (dir, filename, NULL);
if (is_owned_by_user_and_socket (tmp))
found_filename = g_strdup (filename);
g_free (tmp);
}

if (found_filename != NULL)
break;
}

g_pattern_spec_free (pat);
g_dir_close (filedir);

return found_filename;
}

static char *
socket_filename (const char *prefix)
{
char *pattern, *newfile, *path, *filename;
const char *tmpdir;

pattern = g_strdup_printf ("%s.%s.*", prefix, g_get_user_name ());
tmpdir = g_get_tmp_dir ();
filename = find_file_with_pattern (tmpdir, pattern);
if (filename == NULL)
{
newfile = g_strdup_printf ("%s.%s.%u", prefix,
g_get_user_name (), g_random_int ());
path = g_build_filename (tmpdir, newfile, NULL);
g_free (newfile);
} else {
path = g_build_filename (tmpdir, filename, NULL);
g_free (filename);
}

g_free (pattern);
return path;
}

static gboolean
try_server (BaconMessageConnection *conn)
{
struct sockaddr_un uaddr;

uaddr.sun_family = AF_UNIX;
strncpy (uaddr.sun_path, conn->path,
MIN (strlen(conn->path)+1, UNIX_PATH_MAX));
conn->fd = socket (PF_UNIX, SOCK_STREAM, 0);
if (bind (conn->fd, (struct sockaddr *) &uaddr, sizeof (uaddr)) == -1)
{
conn->fd = -1;
return FALSE;
}
listen (conn->fd, 5);

if (!setup_connection (conn))
return FALSE;
return TRUE;
}

static gboolean
try_client (BaconMessageConnection *conn)
{
struct sockaddr_un uaddr;

uaddr.sun_family = AF_UNIX;
strncpy (uaddr.sun_path, conn->path,
MIN(strlen(conn->path)+1, UNIX_PATH_MAX));
conn->fd = socket (PF_UNIX, SOCK_STREAM, 0);
if (connect (conn->fd, (struct sockaddr *) &uaddr,
sizeof (uaddr)) == -1)
{
conn->fd = -1;
return FALSE;
}

return setup_connection (conn);
}

BaconMessageConnection *
bacon_message_connection_new (const char *prefix)
{
BaconMessageConnection *conn;

g_return_val_if_fail (prefix != NULL, NULL);

conn = g_new0 (BaconMessageConnection, 1);
conn->path = socket_filename (prefix);

if (test_is_socket (conn->path) == FALSE)
{
if (!try_server (conn))
{
bacon_message_connection_free (conn);
return NULL;
}

conn->is_server = TRUE;
return conn;
}

if (try_client (conn) == FALSE)
{
unlink (conn->path);
try_server (conn);
if (conn->fd == -1)
{
bacon_message_connection_free (conn);
return NULL;
}

conn->is_server = TRUE;
return conn;
}

conn->is_server = FALSE;
return conn;
}

void
bacon_message_connection_free (BaconMessageConnection *conn)
{
GSList *child_conn;

g_return_if_fail (conn != NULL);
/* Only servers can accept other connections */
g_return_if_fail (conn->is_server != FALSE ||
conn->accepted_connections == NULL);

child_conn = conn->accepted_connections;
while (child_conn != NULL) {
bacon_message_connection_free (child_conn->data);
child_conn = g_slist_next (child_conn);
}
g_slist_free (conn->accepted_connections);

if (conn->conn_id) {
g_source_remove (conn->conn_id);
conn->conn_id = 0;
}
if (conn->chan) {
g_io_channel_shutdown (conn->chan, FALSE, NULL);
g_io_channel_unref (conn->chan);
}

if (conn->is_server != FALSE) {
unlink (conn->path);
}
if (conn->fd != -1) {
close (conn->fd);
}

g_free (conn->path);
g_free (conn);
}

void
bacon_message_connection_set_callback (BaconMessageConnection *conn,
BaconMessageReceivedFunc func,
gpointer user_data)
{
g_return_if_fail (conn != NULL);

conn->func = func;
conn->data = user_data;
}

void
bacon_message_connection_send (BaconMessageConnection *conn,
const char *message)
{
g_return_if_fail (conn != NULL);
g_return_if_fail (message != NULL);

g_io_channel_write_chars (conn->chan, message, strlen (message),
NULL, NULL);
g_io_channel_write_chars (conn->chan, "\n", 1, NULL, NULL);
g_io_channel_flush (conn->chan, NULL);
}

gboolean
bacon_message_connection_get_is_server (BaconMessageConnection *conn)
{
g_return_val_if_fail (conn != NULL, FALSE);

return conn->is_server;
}


+ 0
- 43
xed/bacon-message-connection.h View File

@@ -1,43 +0,0 @@
/*
* Copyright (C) 2003 Bastien Nocera <hadess@hadess.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/

#ifndef BACON_MESSAGE_CONNECTION_H
#define BACON_MESSAGE_CONNECTION_H

#include <glib.h>

G_BEGIN_DECLS

typedef void (*BaconMessageReceivedFunc) (const char *message,
gpointer user_data);

typedef struct BaconMessageConnection BaconMessageConnection;

BaconMessageConnection *bacon_message_connection_new (const char *prefix);
void bacon_message_connection_free (BaconMessageConnection *conn);
void bacon_message_connection_set_callback (BaconMessageConnection *conn,
BaconMessageReceivedFunc func,
gpointer user_data);
void bacon_message_connection_send (BaconMessageConnection *conn,
const char *message);
gboolean bacon_message_connection_get_is_server (BaconMessageConnection *conn);

G_END_DECLS

#endif /* BACON_MESSAGE_CONNECTION_H */

+ 1
- 2
xed/dialogs/xed-encodings-dialog.c View File

@@ -40,7 +40,6 @@
#include "xed-encodings-dialog.h"
#include "xed-utils.h"
#include "xed-debug.h"
#include "xed-help.h"
#include "xed-dirs.h"
#include "xed-settings.h"

@@ -271,7 +270,7 @@ response_handler (GtkDialog *dialog,
{
if (response_id == GTK_RESPONSE_HELP)
{
xed_help_display (GTK_WINDOW (dialog), "xed", NULL);
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dialog), "xed", NULL);
g_signal_stop_emission_by_name (dialog, "response");
return;
}


+ 3
- 6
xed/dialogs/xed-preferences-dialog.c View File

@@ -47,7 +47,6 @@
#include "xed-utils.h"
#include "xed-debug.h"
#include "xed-document.h"
#include "xed-help.h"
#include "xed-dirs.h"
#include "xed-settings.h"
#include "xed-utils.h"
@@ -172,11 +171,11 @@ dialog_response_handler (GtkDialog *dlg,
switch (res_id)
{
case GTK_RESPONSE_HELP:
xed_help_display (GTK_WINDOW (dlg), NULL, "xed-prefs");
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dlg), NULL, "xed-prefs");
g_signal_stop_emission_by_name (dlg, "response");
break;
default:
gtk_widget_destroy (GTK_WIDGET(dlg));
gtk_widget_destroy (GTK_WIDGET (dlg));
}
}

@@ -308,13 +307,11 @@ setup_view_page (XedPreferencesDialog *dlg)
{
GtkWrapMode wrap_mode;
gboolean display_right_margin;
guint right_margin_position;

xed_debug (DEBUG_PREFS);

/* Get values */
display_right_margin = g_settings_get_boolean (dlg->priv->editor, XED_SETTINGS_DISPLAY_RIGHT_MARGIN);
right_margin_position = g_settings_get_uint (dlg->priv->editor, XED_SETTINGS_RIGHT_MARGIN_POSITION);

/* Set initial state */
wrap_mode = g_settings_get_enum (dlg->priv->editor, XED_SETTINGS_WRAP_MODE);
@@ -400,7 +397,7 @@ setup_font_colors_page_font_section (XedPreferencesDialog *dlg)
ATK_RELATION_CONTROLLER_FOR);

/* Get values */
settings = _xed_app_get_settings (xed_app_get_default ());
settings = _xed_app_get_settings (XED_APP (g_application_get_default ()));
system_font = xed_settings_get_system_font (XED_SETTINGS (settings));
use_default_font = g_settings_get_boolean (dlg->priv->editor, XED_SETTINGS_USE_DEFAULT_FONT);



+ 0
- 39
xed/smclient/Makefile.am View File

@@ -1,39 +0,0 @@
platform_defines = -DEGG_SM_CLIENT_BACKEND_XSMP
platform_libs = libeggdesktopfile.la
platform_ltlibraries = libeggdesktopfile.la
platform_sources = eggsmclient-xsmp.c

AM_CPPFLAGS = \
-DG_LOG_DOMAIN=\""EggSMClient"\" \
$(XED_CFLAGS) \
$(platform_defines) \
$(EGG_SMCLIENT_CFLAGS)

noinst_LTLIBRARIES = \
libeggsmclient.la \
$(platform_ltlibraries)

libeggsmclient_la_LIBADD = \
$(EGG_SMCLIENT_LIBS) \
$(platform_libs)

libeggsmclient_la_LDFLAGS = \
$(platform_ldflags)

libeggsmclient_la_SOURCES = \
eggsmclient.c \
eggsmclient.h \
eggsmclient-private.h \
$(platform_sources)

libeggdesktopfile_la_LIBADD = \
$(EGG_LIBS)

libeggdesktopfile_la_SOURCES = \
eggdesktopfile.c \
eggdesktopfile.h

EXTRA_DIST = \
eggsmclient-xsmp.c

-include $(top_srcdir)/git.mk

+ 0
- 1502
xed/smclient/eggdesktopfile.c
File diff suppressed because it is too large
View File


+ 0
- 160
xed/smclient/eggdesktopfile.h View File

@@ -1,160 +0,0 @@
/* eggdesktopfile.h - Freedesktop.Org Desktop Files
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING.LIB. If not,
* write to the Free Software Foundation, Inc., 151 Franklin Street,
* Fifth Floor, Boston, MA 02110-1301, USA.
*/

#ifndef __EGG_DESKTOP_FILE_H__
#define __EGG_DESKTOP_FILE_H__

#include <glib.h>

G_BEGIN_DECLS

typedef struct EggDesktopFile EggDesktopFile;

typedef enum {
EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED,

EGG_DESKTOP_FILE_TYPE_APPLICATION,
EGG_DESKTOP_FILE_TYPE_LINK,
EGG_DESKTOP_FILE_TYPE_DIRECTORY
} EggDesktopFileType;

EggDesktopFile *egg_desktop_file_new (const char *desktop_file_path,
GError **error);

EggDesktopFile *egg_desktop_file_new_from_data_dirs (const char *desktop_file_path,
GError **error);
EggDesktopFile *egg_desktop_file_new_from_dirs (const char *desktop_file_path,
const char **search_dirs,
GError **error);
EggDesktopFile *egg_desktop_file_new_from_key_file (GKeyFile *key_file,
const char *source,
GError **error);

void egg_desktop_file_free (EggDesktopFile *desktop_file);

const char *egg_desktop_file_get_source (EggDesktopFile *desktop_file);

EggDesktopFileType egg_desktop_file_get_desktop_file_type (EggDesktopFile *desktop_file);

const char *egg_desktop_file_get_name (EggDesktopFile *desktop_file);
const char *egg_desktop_file_get_icon (EggDesktopFile *desktop_file);

gboolean egg_desktop_file_can_launch (EggDesktopFile *desktop_file,
const char *desktop_environment);

gboolean egg_desktop_file_accepts_documents (EggDesktopFile *desktop_file);
gboolean egg_desktop_file_accepts_multiple (EggDesktopFile *desktop_file);
gboolean egg_desktop_file_accepts_uris (EggDesktopFile *desktop_file);

char *egg_desktop_file_parse_exec (EggDesktopFile *desktop_file,
GSList *documents,
GError **error);

gboolean egg_desktop_file_launch (EggDesktopFile *desktop_file,
GSList *documents,
GError **error,
...) G_GNUC_NULL_TERMINATED;

typedef enum {
EGG_DESKTOP_FILE_LAUNCH_CLEARENV = 1,
EGG_DESKTOP_FILE_LAUNCH_PUTENV,
EGG_DESKTOP_FILE_LAUNCH_SCREEN,
EGG_DESKTOP_FILE_LAUNCH_WORKSPACE,
EGG_DESKTOP_FILE_LAUNCH_DIRECTORY,
EGG_DESKTOP_FILE_LAUNCH_TIME,
EGG_DESKTOP_FILE_LAUNCH_FLAGS,
EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC,
EGG_DESKTOP_FILE_LAUNCH_RETURN_PID,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID
} EggDesktopFileLaunchOption;

/* Standard Keys */
#define EGG_DESKTOP_FILE_GROUP "Desktop Entry"

#define EGG_DESKTOP_FILE_KEY_TYPE "Type"
#define EGG_DESKTOP_FILE_KEY_VERSION "Version"
#define EGG_DESKTOP_FILE_KEY_NAME "Name"
#define EGG_DESKTOP_FILE_KEY_GENERIC_NAME "GenericName"
#define EGG_DESKTOP_FILE_KEY_NO_DISPLAY "NoDisplay"
#define EGG_DESKTOP_FILE_KEY_COMMENT "Comment"
#define EGG_DESKTOP_FILE_KEY_ICON "Icon"
#define EGG_DESKTOP_FILE_KEY_HIDDEN "Hidden"
#define EGG_DESKTOP_FILE_KEY_ONLY_SHOW_IN "OnlyShowIn"
#define EGG_DESKTOP_FILE_KEY_NOT_SHOW_IN "NotShowIn"
#define EGG_DESKTOP_FILE_KEY_TRY_EXEC "TryExec"
#define EGG_DESKTOP_FILE_KEY_EXEC "Exec"
#define EGG_DESKTOP_FILE_KEY_PATH "Path"
#define EGG_DESKTOP_FILE_KEY_TERMINAL "Terminal"
#define EGG_DESKTOP_FILE_KEY_MIME_TYPE "MimeType"
#define EGG_DESKTOP_FILE_KEY_CATEGORIES "Categories"
#define EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY "StartupNotify"
#define EGG_DESKTOP_FILE_KEY_STARTUP_WM_CLASS "StartupWMClass"
#define EGG_DESKTOP_FILE_KEY_URL "URL"

/* Accessors */
gboolean egg_desktop_file_has_key (EggDesktopFile *desktop_file,
const char *key,
GError **error);
char *egg_desktop_file_get_string (EggDesktopFile *desktop_file,
const char *key,
GError **error) G_GNUC_MALLOC;
char *egg_desktop_file_get_locale_string (EggDesktopFile *desktop_file,
const char *key,
const char *locale,
GError **error) G_GNUC_MALLOC;
gboolean egg_desktop_file_get_boolean (EggDesktopFile *desktop_file,
const char *key,
GError **error);
double egg_desktop_file_get_numeric (EggDesktopFile *desktop_file,
const char *key,
GError **error);
char **egg_desktop_file_get_string_list (EggDesktopFile *desktop_file,
const char *key,
gsize *length,
GError **error) G_GNUC_MALLOC;
char **egg_desktop_file_get_locale_string_list (EggDesktopFile *desktop_file,
const char *key,
const char *locale,
gsize *length,
GError **error) G_GNUC_MALLOC;


/* Errors */
#define EGG_DESKTOP_FILE_ERROR egg_desktop_file_error_quark()

GQuark egg_desktop_file_error_quark (void);

typedef enum {
EGG_DESKTOP_FILE_ERROR_INVALID,
EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION
} EggDesktopFileError;

/* Global application desktop file */
void egg_set_desktop_file (const char *desktop_file_path);
void egg_set_desktop_file_without_defaults (const char *desktop_file_path);
EggDesktopFile *egg_get_desktop_file (void);


G_END_DECLS

#endif /* __EGG_DESKTOP_FILE_H__ */

+ 0
- 39
xed/smclient/eggsmclient-private.h View File

@@ -1,39 +0,0 @@
/* eggsmclient-private.h
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/

#ifndef __EGG_SM_CLIENT_PRIVATE_H__
#define __EGG_SM_CLIENT_PRIVATE_H__

#include <gtk/gtk.h>
#include "eggsmclient.h"

G_BEGIN_DECLS

GKeyFile *egg_sm_client_save_state (EggSMClient *client);
void egg_sm_client_quit_requested (EggSMClient *client);
void egg_sm_client_quit_cancelled (EggSMClient *client);
void egg_sm_client_quit (EggSMClient *client);

GType egg_sm_client_xsmp_get_type (void);
EggSMClient *egg_sm_client_xsmp_new (void);

G_END_DECLS


#endif /* __EGG_SM_CLIENT_PRIVATE_H__ */

+ 0
- 1365
xed/smclient/eggsmclient-xsmp.c
File diff suppressed because it is too large
View File


+ 0
- 573
xed/smclient/eggsmclient.c View File

@@ -1,573 +0,0 @@
/*
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/

#include "config.h"

#include <string.h>
#include <glib/gi18n.h>

#include "eggsmclient.h"
#include "eggsmclient-private.h"

static void egg_sm_client_debug_handler (const char *log_domain,
GLogLevelFlags log_level,
const char *message,
gpointer user_data);

enum {
SAVE_STATE,
QUIT_REQUESTED,
QUIT_CANCELLED,
QUIT,
LAST_SIGNAL
};

static guint signals[LAST_SIGNAL] = { 0 };

struct _EggSMClientPrivate {
GKeyFile *state_file;
};

#define EGG_SM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_SM_CLIENT, EggSMClientPrivate))

G_DEFINE_TYPE (EggSMClient, egg_sm_client, G_TYPE_OBJECT)

static EggSMClient *global_client;
static EggSMClientMode global_client_mode = EGG_SM_CLIENT_MODE_NORMAL;

static void
egg_sm_client_init (EggSMClient *client)
{
;
}

static void
egg_sm_client_class_init (EggSMClientClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);

g_type_class_add_private (klass, sizeof (EggSMClientPrivate));

/**
* EggSMClient::save_state:
* @client: the client
* @state_file: a #GKeyFile to save state information into
*
* Emitted when the session manager has requested that the
* application save information about its current state. The
* application should save its state into @state_file, and then the
* session manager may then restart the application in a future
* session and tell it to initialize itself from that state.
*
* You should not save any data into @state_file's "start group"
* (ie, the %NULL group). Instead, applications should save their
* data into groups with names that start with the application name,
* and libraries that connect to this signal should save their data
* into groups with names that start with the library name.
*
* Alternatively, rather than (or in addition to) using @state_file,
* the application can save its state by calling
* egg_sm_client_set_restart_command() during the processing of this
* signal (eg, to include a list of files to open).
**/
signals[SAVE_STATE] =
g_signal_new ("save_state",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, save_state),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE,
1, G_TYPE_POINTER);

/**
* EggSMClient::quit_requested:
* @client: the client
*
* Emitted when the session manager requests that the application
* exit (generally because the user is logging out). The application
* should decide whether or not it is willing to quit (perhaps after
* asking the user what to do with documents that have unsaved
* changes) and then call egg_sm_client_will_quit(), passing %TRUE
* or %FALSE to give its answer to the session manager. (It does not
* need to give an answer before returning from the signal handler;
* it can interact with the user asynchronously and then give its
* answer later on.) If the application does not connect to this
* signal, then #EggSMClient will automatically return %TRUE on its
* behalf.
*
* The application should not save its session state as part of
* handling this signal; if the user has requested that the session
* be saved when logging out, then ::save_state will be emitted
* separately.
*
* If the application agrees to quit, it should then wait for either
* the ::quit_cancelled or ::quit signals to be emitted.
**/
signals[QUIT_REQUESTED] =
g_signal_new ("quit_requested",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, quit_requested),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);

/**
* EggSMClient::quit_cancelled:
* @client: the client
*
* Emitted when the session manager decides to cancel a logout after
* the application has already agreed to quit. After receiving this
* signal, the application can go back to what it was doing before
* receiving the ::quit_requested signal.
**/
signals[QUIT_CANCELLED] =
g_signal_new ("quit_cancelled",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, quit_cancelled),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);

/**
* EggSMClient::quit:
* @client: the client
*
* Emitted when the session manager wants the application to quit
* (generally because the user is logging out). The application
* should exit as soon as possible after receiving this signal; if
* it does not, the session manager may choose to forcibly kill it.
*
* Normally a GUI application would only be sent a ::quit if it
* agreed to quit in response to a ::quit_requested signal. However,
* this is not guaranteed; in some situations the session manager
* may decide to end the session without giving applications a
* chance to object.
**/
signals[QUIT] =
g_signal_new ("quit",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, quit),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
}

static gboolean sm_client_disable = FALSE;
static char *sm_client_state_file = NULL;
static char *sm_client_id = NULL;
static char *sm_config_prefix = NULL;

static gboolean
sm_client_post_parse_func (GOptionContext *context,
GOptionGroup *group,
gpointer data,
GError **error)
{
EggSMClient *client = egg_sm_client_get ();

if (sm_client_id == NULL)
{
const gchar *desktop_autostart_id;

desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");

if (desktop_autostart_id != NULL)
sm_client_id = g_strdup (desktop_autostart_id);
}

/* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
* use the same client id. */
g_unsetenv ("DESKTOP_AUTOSTART_ID");

if (EGG_SM_CLIENT_GET_CLASS (client)->startup)
EGG_SM_CLIENT_GET_CLASS (client)->startup (client, sm_client_id);
return TRUE;
}

/**
* egg_sm_client_get_option_group:
*
* Creates a %GOptionGroup containing the session-management-related
* options. You should add this group to the application's
* %GOptionContext if you want to use #EggSMClient.
*
* Return value: the %GOptionGroup
**/
GOptionGroup *
egg_sm_client_get_option_group (void)
{
const GOptionEntry entries[] = {
{ "sm-client-disable", 0, 0,
G_OPTION_ARG_NONE, &sm_client_disable,
N_("Disable connection to session manager"), NULL },
{ "sm-client-state-file", 0, 0,
G_OPTION_ARG_FILENAME, &sm_client_state_file,
N_("Specify file containing saved configuration"), N_("FILE") },
{ "sm-client-id", 0, 0,
G_OPTION_ARG_STRING, &sm_client_id,
N_("Specify session management ID"), N_("ID") },
/* MateClient compatibility option */
{ "sm-disable", 0, G_OPTION_FLAG_HIDDEN,
G_OPTION_ARG_NONE, &sm_client_disable,
NULL, NULL },
/* MateClient compatibility option. This is a dummy option that only
* exists so that sessions saved by apps with MateClient can be restored
* later when they've switched to EggSMClient. See bug #575308.
*/
{ "sm-config-prefix", 0, G_OPTION_FLAG_HIDDEN,
G_OPTION_ARG_STRING, &sm_config_prefix,
NULL, NULL },
{ NULL }
};
GOptionGroup *group;

/* Use our own debug handler for the "EggSMClient" domain. */
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
egg_sm_client_debug_handler, NULL);

group = g_option_group_new ("sm-client",
_("Session management options:"),
_("Show session management options"),
NULL, NULL);
g_option_group_add_entries (group, entries);
g_option_group_set_parse_hooks (group, NULL, sm_client_post_parse_func);

return group;
}

/**
* egg_sm_client_set_mode:
* @mode: an #EggSMClient mode
*
* Sets the "mode" of #EggSMClient as follows:
*
* %EGG_SM_CLIENT_MODE_DISABLED: Session management is completely
* disabled. The application will not even connect to the session
* manager. (egg_sm_client_get() will still return an #EggSMClient,
* but it will just be a dummy object.)
*
* %EGG_SM_CLIENT_MODE_NO_RESTART: The application will connect to
* the session manager (and thus will receive notification when the
* user is logging out, etc), but will request to not be
* automatically restarted with saved state in future sessions.
*
* %EGG_SM_CLIENT_MODE_NORMAL: The default. #EggSMCLient will
* function normally.
*
* This must be called before the application's main loop begins.
**/
void
egg_sm_client_set_mode (EggSMClientMode mode)
{
global_client_mode = mode;
}

/**
* egg_sm_client_get_mode:
*
* Gets the global #EggSMClientMode. See egg_sm_client_set_mode()
* for details.
*
* Return value: the global #EggSMClientMode
**/
EggSMClientMode
egg_sm_client_get_mode (void)
{
return global_client_mode;
}

/**
* egg_sm_client_get:
*
* Returns the master #EggSMClient for the application.
*
* On platforms that support saved sessions (ie, POSIX/X11), the
* application will only request to be restarted by the session
* manager if you call egg_set_desktop_file() to set an application
* desktop file. In particular, if the desktop file contains the key
* "X
*
* Return value: the master #EggSMClient.
**/
EggSMClient *
egg_sm_client_get (void)
{
if (!global_client)
{
if (global_client_mode != EGG_SM_CLIENT_MODE_DISABLED &&
!sm_client_disable)
{
global_client = egg_sm_client_xsmp_new ();
}

/* Fallback: create a dummy client, so that callers don't have
* to worry about a %NULL return value.
*/
if (!global_client)
global_client = g_object_new (EGG_TYPE_SM_CLIENT, NULL);
}

return global_client;
}

/**
* egg_sm_client_is_resumed:
* @client: the client
*
* Checks whether or not the current session has been resumed from
* a previous saved session. If so, the application should call
* egg_sm_client_get_state_file() and restore its state from the
* returned #GKeyFile.
*
* Return value: %TRUE if the session has been resumed
**/
gboolean
egg_sm_client_is_resumed (EggSMClient *client)
{
g_return_val_if_fail (client == global_client, FALSE);

return sm_client_state_file != NULL;
}

/**
* egg_sm_client_get_state_file:
* @client: the client
*
* If the application was resumed by the session manager, this will
* return the #GKeyFile containing its state from the previous
* session.
*
* Note that other libraries and #EggSMClient itself may also store
* state in the key file, so if you call egg_sm_client_get_groups(),
* on it, the return value will likely include groups that you did not
* put there yourself. (It is also not guaranteed that the first
* group created by the application will still be the "start group"
* when it is resumed.)
*
* Return value: the #GKeyFile containing the application's earlier
* state, or %NULL on error. You should not free this key file; it
* is owned by @client.
**/
GKeyFile *
egg_sm_client_get_state_file (EggSMClient *client)
{
EggSMClientPrivate *priv = EGG_SM_CLIENT_GET_PRIVATE (client);
char *state_file_path;
GError *err = NULL;

g_return_val_if_fail (client == global_client, NULL);

if (!sm_client_state_file)
return NULL;
if (priv->state_file)
return priv->state_file;

if (!strncmp (sm_client_state_file, "file://", 7))
state_file_path = g_filename_from_uri (sm_client_state_file, NULL, NULL);
else
state_file_path = g_strdup (sm_client_state_file);

priv->state_file = g_key_file_new ();
if (!g_key_file_load_from_file (priv->state_file, state_file_path, 0, &err))
{
g_warning ("Could not load SM state file '%s': %s",
sm_client_state_file, err->message);
g_clear_error (&err);
g_key_file_free (priv->state_file);
priv->state_file = NULL;
}

g_free (state_file_path);
return priv->state_file;
}

/**
* egg_sm_client_set_restart_command:
* @client: the client
* @argc: the length of @argv
* @argv: argument vector
*
* Sets the command used to restart @client if it does not have a
* .desktop file that can be used to find its restart command.
*
* This can also be used when handling the ::save_state signal, to
* save the current state via an updated command line. (Eg, providing
* a list of filenames to open when the application is resumed.)
**/
void
egg_sm_client_set_restart_command (EggSMClient *client,
int argc,
const char **argv)
{
g_return_if_fail (EGG_IS_SM_CLIENT (client));

if (EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command)
EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command (client, argc, argv);
}

/**
* egg_sm_client_will_quit:
* @client: the client
* @will_quit: whether or not the application is willing to quit
*
* This MUST be called in response to the ::quit_requested signal, to
* indicate whether or not the application is willing to quit. The
* application may call it either directly from the signal handler, or
* at some later point (eg, after asynchronously interacting with the
* user).
*
* If the application does not connect to ::quit_requested,
* #EggSMClient will call this method on its behalf (passing %TRUE
* for @will_quit).
*
* After calling this method, the application should wait to receive
* either ::quit_cancelled or ::quit.
**/
void
egg_sm_client_will_quit (EggSMClient *client,
gboolean will_quit)
{
g_return_if_fail (EGG_IS_SM_CLIENT (client));

if (EGG_SM_CLIENT_GET_CLASS (client)->will_quit)
EGG_SM_CLIENT_GET_CLASS (client)->will_quit (client, will_quit);
}

/**
* egg_sm_client_end_session:
* @style: a hint at how to end the session
* @request_confirmation: whether or not the user should get a chance
* to confirm the action
*
* Requests that the session manager end the current session. @style
* indicates how the session should be ended, and
* @request_confirmation indicates whether or not the user should be
* given a chance to confirm the logout/reboot/shutdown. Both of these
* flags are merely hints though; the session manager may choose to
* ignore them.
*
* Return value: %TRUE if the request was sent; %FALSE if it could not
* be (eg, because it could not connect to the session manager).
**/
gboolean
egg_sm_client_end_session (EggSMClientEndStyle style,
gboolean request_confirmation)
{
EggSMClient *client = egg_sm_client_get ();

g_return_val_if_fail (EGG_IS_SM_CLIENT (client), FALSE);

if (EGG_SM_CLIENT_GET_CLASS (client)->end_session)
{
return EGG_SM_CLIENT_GET_CLASS (client)->end_session (client, style,
request_confirmation);
}
else
return FALSE;
}

/* Signal-emitting callbacks from platform-specific code */

GKeyFile *
egg_sm_client_save_state (EggSMClient *client)
{
GKeyFile *state_file;
char *group;

g_return_val_if_fail (client == global_client, NULL);

state_file = g_key_file_new ();

g_debug ("Emitting save_state");
g_signal_emit (client, signals[SAVE_STATE], 0, state_file);
g_debug ("Done emitting save_state");

group = g_key_file_get_start_group (state_file);
if (group)
{
g_free (group);
return state_file;
}
else
{
g_key_file_free (state_file);
return NULL;
}
}

void
egg_sm_client_quit_requested (EggSMClient *client)
{
g_return_if_fail (client == global_client);

if (!g_signal_has_handler_pending (client, signals[QUIT_REQUESTED], 0, FALSE))
{
g_debug ("Not emitting quit_requested because no one is listening");
egg_sm_client_will_quit (client, TRUE);
return;
}

g_debug ("Emitting quit_requested");
g_signal_emit (client, signals[QUIT_REQUESTED], 0);
g_debug ("Done emitting quit_requested");
}

void
egg_sm_client_quit_cancelled (EggSMClient *client)
{
g_return_if_fail (client == global_client);

g_debug ("Emitting quit_cancelled");
g_signal_emit (client, signals[QUIT_CANCELLED], 0);
g_debug ("Done emitting quit_cancelled");
}

void
egg_sm_client_quit (EggSMClient *client)
{
g_return_if_fail (client == global_client);

g_debug ("Emitting quit");
g_signal_emit (client, signals[QUIT], 0);
g_debug ("Done emitting quit");

/* FIXME: should we just call gtk_main_quit() here? */
}

static void
egg_sm_client_debug_handler (const char *log_domain,
GLogLevelFlags log_level,
const char *message,
gpointer user_data)
{
static int debug = -1;

if (debug < 0)
debug = (g_getenv ("EGG_SM_CLIENT_DEBUG") != NULL);

if (debug)
g_log_default_handler (log_domain, log_level, message, NULL);
}

+ 0
- 117
xed/smclient/eggsmclient.h View File

@@ -1,117 +0,0 @@
/* eggsmclient.h
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/

#ifndef __EGG_SM_CLIENT_H__
#define __EGG_SM_CLIENT_H__

#include <glib-object.h>

G_BEGIN_DECLS

#define EGG_TYPE_SM_CLIENT (egg_sm_client_get_type ())
#define EGG_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT, EggSMClient))
#define EGG_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT, EggSMClientClass))
#define EGG_IS_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT))
#define EGG_IS_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT))
#define EGG_SM_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT, EggSMClientClass))

typedef struct _EggSMClient EggSMClient;
typedef struct _EggSMClientClass EggSMClientClass;
typedef struct _EggSMClientPrivate EggSMClientPrivate;

typedef enum {
EGG_SM_CLIENT_END_SESSION_DEFAULT,
EGG_SM_CLIENT_LOGOUT,
EGG_SM_CLIENT_REBOOT,
EGG_SM_CLIENT_SHUTDOWN
} EggSMClientEndStyle;

typedef enum {
EGG_SM_CLIENT_MODE_DISABLED,
EGG_SM_CLIENT_MODE_NO_RESTART,
EGG_SM_CLIENT_MODE_NORMAL
} EggSMClientMode;

struct _EggSMClient
{
GObject parent;

};

struct _EggSMClientClass
{
GObjectClass parent_class;

/* signals */
void (*save_state) (EggSMClient *client,
GKeyFile *state_file);

void (*quit_requested) (EggSMClient *client);
void (*quit_cancelled) (EggSMClient *client);
void (*quit) (EggSMClient *client);

/* virtual methods */
void (*startup) (EggSMClient *client,
const char *client_id);
void (*set_restart_command) (EggSMClient *client,
int argc,
const char **argv);
void (*will_quit) (EggSMClient *client,
gboolean will_quit);
gboolean (*end_session) (EggSMClient *client,
EggSMClientEndStyle style,
gboolean request_confirmation);

/* Padding for future expansion */
void (*_egg_reserved1) (void);
void (*_egg_reserved2) (void);
void (*_egg_reserved3) (void);
void (*_egg_reserved4) (void);
};

GType egg_sm_client_get_type (void) G_GNUC_CONST;

GOptionGroup *egg_sm_client_get_option_group (void);

/* Initialization */
void egg_sm_client_set_mode (EggSMClientMode mode);
EggSMClientMode egg_sm_client_get_mode (void);
EggSMClient *egg_sm_client_get (void);

/* Resuming a saved session */
gboolean egg_sm_client_is_resumed (EggSMClient *client);
GKeyFile *egg_sm_client_get_state_file (EggSMClient *client);

/* Alternate means of saving state */
void egg_sm_client_set_restart_command (EggSMClient *client,
int argc,
const char **argv);

/* Handling "quit_requested" signal */
void egg_sm_client_will_quit (EggSMClient *client,
gboolean will_quit);

/* Initiate a logout/reboot/shutdown */
gboolean egg_sm_client_end_session (EggSMClientEndStyle style,
gboolean request_confirmation);

G_END_DECLS


#endif /* __EGG_SM_CLIENT_H__ */

+ 702
- 391
xed/xed-app.c
File diff suppressed because it is too large
View File


+ 29
- 18
xed/xed-app.h View File

@@ -50,7 +50,7 @@ typedef struct _XedAppClass XedAppClass;

struct _XedApp
{
GObject object;
GtkApplication parent;

/*< private > */
XedAppPrivate *priv;
@@ -58,38 +58,49 @@ struct _XedApp

struct _XedAppClass
{
GObjectClass parent_class;
GtkApplicationClass parent_class;

// gboolean (*last_window_destroyed) (XedApp *app);

gboolean (*show_help) (XedApp *app,
GtkWindow *parent,
const gchar *name,
const gchar *link_id);

gchar *(*help_link_id) (XedApp *app,
const gchar *name,
const gchar *link_id);

void (*set_window_title) (XedApp *app,
XedWindow *window,
const gchar *title);
};

/*
* Public methods
*/
/* Public methods */
GType xed_app_get_type (void) G_GNUC_CONST;

XedApp *xed_app_get_default (void);

XedWindow *xed_app_create_window (XedApp *app,
GdkScreen *screen);

const GList *xed_app_get_windows (XedApp *app);
XedWindow *xed_app_get_active_window (XedApp *app);
GList *xed_app_get_main_windows (XedApp *app);

/* Returns a newly allocated list with all the documents */
GList *xed_app_get_documents (XedApp *app);

/* Returns a newly allocated list with all the views */
GList *xed_app_get_views (XedApp *app);

/*
* Non exported functions
*/
gboolean xed_app_show_help (XedApp *app,
GtkWindow *parent,
const gchar *name,
const gchar *link_id);

void xed_app_set_window_title (XedApp *app,
XedWindow *window,
const gchar *title);

/* Non exported functions */
XedWindow *_xed_app_restore_window (XedApp *app,
const gchar *role);
XedWindow *_xed_app_get_window_in_viewport (XedApp *app,
GdkScreen *screen,
gint workspace,
gint viewport_x,
gint viewport_y);

/* global print config */
GtkPageSetup *_xed_app_get_default_page_setup (XedApp *app);


+ 73
- 48
xed/xed-commands-file.c View File

@@ -61,6 +61,9 @@ static void tab_state_changed_while_saving (XedTab *tab,
GParamSpec *pspec,
XedWindow *window);

static void save_as_tab (XedTab *tab,
XedWindow *window);

void
_xed_cmd_file_new (GtkAction *action,
XedWindow *window)
@@ -116,7 +119,7 @@ is_duplicated_file (GSList *files,
}

/* File loading */
static gint
static GSList *
load_file_list (XedWindow *window,
const GSList *files,
const GtkSourceEncoding *encoding,
@@ -124,11 +127,12 @@ load_file_list (XedWindow *window,
gboolean create)
{
XedTab *tab;
gint loaded_files = 0; /* Number of files to load */
GSList *loaded_files = NULL; /* Number of files to load */
gboolean jump_to = TRUE; /* Whether to jump to the new tab */
GList *win_docs;
GSList *files_to_load = NULL;
const GSList *l;
gint num_loaded_files = 0;

xed_debug (DEBUG_COMMANDS);

@@ -145,29 +149,25 @@ load_file_list (XedWindow *window,
{
if (l == files)
{
XedDocument *doc;

xed_window_set_active_tab (window, tab);
jump_to = FALSE;
doc = xed_tab_get_document (tab);

if (line_pos > 0)
{
XedDocument *doc;
XedView *view;

doc = xed_tab_get_document (tab);
view = xed_tab_get_view (tab);

/* document counts lines starting from 0 */
xed_document_goto_line (doc, line_pos - 1);
xed_view_scroll_to_cursor (view);
xed_view_scroll_to_cursor (xed_tab_get_view (tab));
}
}

++loaded_files;
++num_loaded_files;
loaded_files = g_slist_prepend (loaded_files, xed_tab_get_document (tab));
}
else
{
files_to_load = g_slist_prepend (files_to_load,
l->data);
files_to_load = g_slist_prepend (files_to_load, l->data);
}
}
}
@@ -176,7 +176,7 @@ load_file_list (XedWindow *window,

if (files_to_load == NULL)
{
return loaded_files;
return g_slist_reverse (loaded_files);
}

files_to_load = g_slist_reverse (files_to_load);
@@ -196,7 +196,8 @@ load_file_list (XedWindow *window,
l = g_slist_next (l);
jump_to = FALSE;

++loaded_files;
++num_loaded_files;
loaded_files = g_slist_prepend (loaded_files, xed_tab_get_document (tab));
}
}

@@ -209,13 +210,16 @@ load_file_list (XedWindow *window,
if (tab != NULL)
{
jump_to = FALSE;
++loaded_files;
++num_loaded_files;
loaded_files = g_slist_prepend (loaded_files, xed_tab_get_document (tab));
}

l = g_slist_next (l);
}

if (loaded_files == 1)
loaded_files = g_slist_reverse (loaded_files);

if (num_loaded_files == 1)
{
XedDocument *doc;
gchar *uri_for_display;
@@ -238,8 +242,8 @@ load_file_list (XedWindow *window,
window->priv->generic_message_cid,
ngettext("Loading %d file\342\200\246",
"Loading %d files\342\200\246",
loaded_files),
loaded_files);
num_loaded_files),
num_loaded_files);
}

/* Free uris_to_load. Note that l points to the first element of uris_to_load */
@@ -265,6 +269,7 @@ xed_commands_load_location (XedWindow *window,
{
GSList *locations = NULL;
gchar *uri;
GSList *ret;

g_return_if_fail (XED_IS_WINDOW (window));
g_return_if_fail (G_IS_FILE (location));
@@ -276,7 +281,8 @@ xed_commands_load_location (XedWindow *window,

locations = g_slist_prepend (locations, location);

load_file_list (window, locations, encoding, line_pos, FALSE);
ret = load_file_list (window, locations, encoding, line_pos, FALSE);
g_slist_free (ret);

g_slist_free (locations);
}
@@ -292,7 +298,7 @@ xed_commands_load_location (XedWindow *window,
*
* Returns:
*/
gint
GSList *
xed_commands_load_locations (XedWindow *window,
const GSList *locations,
const GtkSourceEncoding *encoding,
@@ -311,7 +317,7 @@ xed_commands_load_locations (XedWindow *window,
* first doc. Beside specifying a not existing uri creates a
* titled document.
*/
gint
GSList *
_xed_cmd_load_files_from_prompt (XedWindow *window,
GSList *files,
const GtkSourceEncoding *encoding,
@@ -338,6 +344,7 @@ open_dialog_response_cb (XedFileChooserDialog *dialog,
{
GSList *files;
const GtkSourceEncoding *encoding;
GSList *loaded;

xed_debug (DEBUG_COMMANDS);

@@ -358,7 +365,9 @@ open_dialog_response_cb (XedFileChooserDialog *dialog,
/* Remember the folder we navigated to */
_xed_window_set_default_location (window, files->data);

xed_commands_load_locations (window, files, encoding, 0);
loaded = xed_commands_load_locations (window, files, encoding, 0);

g_slist_free (loaded);

g_slist_foreach (files, (GFunc) g_object_unref, NULL);
g_slist_free (files);
@@ -433,9 +442,6 @@ _xed_cmd_file_open (GtkAction *action,
gtk_widget_show (open_dialog);
}

/* File saving */
static void file_save_as (XedTab *tab, XedWindow *window);

static gboolean
is_read_only (GFile *location)
{
@@ -511,6 +517,14 @@ replace_read_only_file (GtkWindow *parent,
return (ret == GTK_RESPONSE_YES);
}

static void
save_finish_cb (XedTab *tab,
GAsyncResult *result,
gpointer user_data)
{
_xed_tab_save_finish (tab, result);
}

static void
save_dialog_response_cb (XedFileChooserDialog *dialog,