mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 01:20:42 -05:00
remove msm from here, now in its own module
This commit is contained in:
parent
52dc32031d
commit
b09a781a80
@ -1,23 +0,0 @@
|
||||
|
||||
INCLUDES=@MSM_CFLAGS@ -DMSM_PKGDATADIR=\"$(datadir)/msm\"
|
||||
|
||||
msm_SOURCES= \
|
||||
client.c \
|
||||
client.h \
|
||||
gui.c \
|
||||
gui.h \
|
||||
main.c \
|
||||
main.h \
|
||||
props.c \
|
||||
props.h \
|
||||
server.c \
|
||||
server.h \
|
||||
session.c \
|
||||
session.h \
|
||||
util.c \
|
||||
util.h
|
||||
|
||||
noinst_PROGRAMS=msm
|
||||
|
||||
msm_LDADD= @MSM_LIBS@
|
||||
|
343
src/msm/client.c
343
src/msm/client.c
@ -1,343 +0,0 @@
|
||||
/* msm client object */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "props.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct _MsmClient
|
||||
{
|
||||
MsmServer *server;
|
||||
SmsConn cnxn;
|
||||
MsmClientState state;
|
||||
char *id;
|
||||
char *hostname;
|
||||
char *desc;
|
||||
int restart_style;
|
||||
GList *properties;
|
||||
};
|
||||
|
||||
#define DEFAULT_RESTART_STYLE SmRestartIfRunning
|
||||
|
||||
MsmClient*
|
||||
msm_client_new (MsmServer *server,
|
||||
SmsConn cnxn)
|
||||
{
|
||||
MsmClient *client;
|
||||
|
||||
client = g_new (MsmClient, 1);
|
||||
|
||||
client->server = server;
|
||||
client->cnxn = cnxn;
|
||||
client->state = MSM_CLIENT_STATE_NEW;
|
||||
client->id = NULL;
|
||||
client->hostname = NULL;
|
||||
client->desc = g_strdup ("unknown");
|
||||
client->restart_style = DEFAULT_RESTART_STYLE;
|
||||
client->properties = NULL;
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_free (MsmClient *client)
|
||||
{
|
||||
IceConn ice_cnxn;
|
||||
GList *tmp;
|
||||
|
||||
ice_cnxn = SmsGetIceConnection (client->cnxn);
|
||||
SmsCleanUp (client->cnxn);
|
||||
IceSetShutdownNegotiation (ice_cnxn, False);
|
||||
IceCloseConnection (ice_cnxn);
|
||||
|
||||
tmp = client->properties;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
SmProp *prop = tmp->data;
|
||||
|
||||
SmFreeProperty (prop);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
g_list_free (client->properties);
|
||||
|
||||
g_free (client->id);
|
||||
g_free (client->hostname);
|
||||
g_free (client->desc);
|
||||
|
||||
g_free (client);
|
||||
}
|
||||
|
||||
SmsConn
|
||||
msm_client_get_connection (MsmClient *client)
|
||||
{
|
||||
return client->cnxn;
|
||||
}
|
||||
|
||||
const char*
|
||||
msm_client_get_description (MsmClient *client)
|
||||
{
|
||||
return client->desc;
|
||||
}
|
||||
|
||||
MsmClientState
|
||||
msm_client_get_state (MsmClient *client)
|
||||
{
|
||||
return client->state;
|
||||
}
|
||||
|
||||
MsmServer*
|
||||
msm_client_get_server (MsmClient *client)
|
||||
{
|
||||
return client->server;
|
||||
}
|
||||
|
||||
const char*
|
||||
msm_client_get_id (MsmClient *client)
|
||||
{
|
||||
return client->id;
|
||||
}
|
||||
|
||||
int
|
||||
msm_client_get_restart_style (MsmClient *client)
|
||||
{
|
||||
return client->restart_style;
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_register (MsmClient *client,
|
||||
const char *id)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (client->state != MSM_CLIENT_STATE_NEW)
|
||||
{
|
||||
msm_warning (_("Client '%s' attempted to register when it was already registered\n"), client->desc);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
client->state = MSM_CLIENT_STATE_IDLE;
|
||||
client->id = g_strdup (id);
|
||||
|
||||
SmsRegisterClientReply (client->cnxn, client->id);
|
||||
|
||||
p = SmsClientHostName (client->cnxn);
|
||||
client->hostname = g_strdup (p);
|
||||
free (p);
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_interact_request (MsmClient *client)
|
||||
{
|
||||
if (client->state != MSM_CLIENT_STATE_SAVING &&
|
||||
client->state != MSM_CLIENT_STATE_SAVING_PHASE2)
|
||||
{
|
||||
msm_warning (_("Client '%s' requested interaction when it was not being saved\n"),
|
||||
client->desc);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
msm_server_queue_interaction (client->server, client);
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_begin_interact (MsmClient *client)
|
||||
{
|
||||
SmsInteract (client->cnxn);
|
||||
}
|
||||
|
||||
static void
|
||||
internal_save (MsmClient *client,
|
||||
int save_style,
|
||||
gboolean allow_interaction,
|
||||
gboolean shut_down)
|
||||
{
|
||||
if (client->state != MSM_CLIENT_STATE_IDLE)
|
||||
{
|
||||
msm_warning (_("Tried to save client '%s' but it was not in the idle state\n"),
|
||||
client->desc);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
client->state = MSM_CLIENT_STATE_SAVING;
|
||||
|
||||
SmsSaveYourself (client->cnxn,
|
||||
save_style,
|
||||
shut_down,
|
||||
allow_interaction ? SmInteractStyleAny : SmInteractStyleNone,
|
||||
FALSE /* not "fast" */);
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_save (MsmClient *client,
|
||||
gboolean allow_interaction,
|
||||
gboolean shut_down)
|
||||
{
|
||||
internal_save (client, SmSaveBoth, /* ? don't know what to do here */
|
||||
allow_interaction, shut_down);
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_initial_save (MsmClient *client)
|
||||
{
|
||||
/* This is the save on client registration in the spec under
|
||||
* RegisterClientReply
|
||||
*/
|
||||
internal_save (client, SmSaveLocal, FALSE, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_shutdown_cancelled (MsmClient *client)
|
||||
{
|
||||
if (client->state != MSM_CLIENT_STATE_SAVING &&
|
||||
client->state != MSM_CLIENT_STATE_SAVING_PHASE2)
|
||||
{
|
||||
msm_warning (_("Tried to send cancel shutdown to client '%s' which was not saving\n"),
|
||||
client->desc);
|
||||
return;
|
||||
}
|
||||
|
||||
client->state = MSM_CLIENT_STATE_IDLE;
|
||||
SmsShutdownCancelled (client->cnxn);
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_phase2_request (MsmClient *client)
|
||||
{
|
||||
if (client->state != MSM_CLIENT_STATE_SAVING)
|
||||
{
|
||||
msm_warning (_("Client '%s' requested phase 2 save but was not in a phase 1 save\n"),
|
||||
client->desc);
|
||||
return;
|
||||
}
|
||||
|
||||
client->state = MSM_CLIENT_STATE_PHASE2_REQUESTED;
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_save_phase2 (MsmClient *client)
|
||||
{
|
||||
if (client->state != MSM_CLIENT_STATE_PHASE2_REQUESTED)
|
||||
{
|
||||
msm_warning (_("We tried to save client '%s' in phase 2, but it hadn't requested it.\n"), client->desc);
|
||||
return;
|
||||
}
|
||||
|
||||
SmsSaveYourselfPhase2 (client->cnxn);
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_die (MsmClient *client)
|
||||
{
|
||||
client->state = MSM_CLIENT_STATE_DEAD;
|
||||
SmsDie (client->cnxn);
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_save_complete (MsmClient *client)
|
||||
{
|
||||
client->state = MSM_CLIENT_STATE_IDLE;
|
||||
SmsSaveComplete (client->cnxn);
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_save_confirmed (MsmClient *client,
|
||||
gboolean successful)
|
||||
{
|
||||
if (client->state != MSM_CLIENT_STATE_SAVING &&
|
||||
client->state != MSM_CLIENT_STATE_SAVING_PHASE2)
|
||||
{
|
||||
msm_warning (_("Client '%s' said it was done saving, but it hadn't been told to save\n"),
|
||||
client->desc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (successful)
|
||||
client->state = MSM_CLIENT_STATE_SAVE_DONE;
|
||||
else
|
||||
client->state = MSM_CLIENT_STATE_SAVE_FAILED;
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_set_property_taking_ownership (MsmClient *client,
|
||||
SmProp *prop)
|
||||
{
|
||||
/* we own prop which should be freed with SmFreeProperty() */
|
||||
|
||||
/* pass our ownership into the proplist */
|
||||
client->properties = proplist_replace (client->properties, prop);
|
||||
|
||||
/* update pieces of the client struct */
|
||||
if (strcmp (prop->name, "SmRestartStyleHint") == 0)
|
||||
{
|
||||
int hint;
|
||||
if (smprop_get_card8 (prop, &hint))
|
||||
client->restart_style = hint;
|
||||
else
|
||||
client->restart_style = DEFAULT_RESTART_STYLE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_unset_property (MsmClient *client,
|
||||
const char *name)
|
||||
{
|
||||
client->properties = proplist_delete (client->properties, name);
|
||||
|
||||
/* Return to default values */
|
||||
if (strcmp (name, "SmRestartStyleHint") == 0)
|
||||
{
|
||||
client->restart_style = DEFAULT_RESTART_STYLE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
msm_client_send_properties (MsmClient *client)
|
||||
{
|
||||
int n_props;
|
||||
SmProp **props;
|
||||
GList *tmp;
|
||||
int i;
|
||||
|
||||
n_props = g_list_length (client->properties);
|
||||
props = g_new (SmProp*, n_props);
|
||||
|
||||
i = 0;
|
||||
tmp = client->properties;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
props[i] = tmp->data;
|
||||
|
||||
tmp = tmp->next;
|
||||
++i;
|
||||
}
|
||||
|
||||
SmsReturnProperties (client->cnxn, n_props, props);
|
||||
|
||||
g_free (props);
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
/* msm client object */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MSM_CLIENT_H
|
||||
#define MSM_CLIENT_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "server.h"
|
||||
|
||||
/* See xsmp docs for a state description. This enum doesn't
|
||||
* correspond exactly, but close enough.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/* Client has just newly connected, not yet registered */
|
||||
MSM_CLIENT_STATE_NEW,
|
||||
/* Client has registered with us successfully, isn't doing
|
||||
* anything special
|
||||
*/
|
||||
MSM_CLIENT_STATE_IDLE,
|
||||
/* Client is saving self in phase 1 */
|
||||
MSM_CLIENT_STATE_SAVING,
|
||||
/* Client has requested phase 2 save, but we aren't in phase 2 yet */
|
||||
MSM_CLIENT_STATE_PHASE2_REQUESTED,
|
||||
/* Client is in phase 2 save; all the same things are
|
||||
* allowed as with STATE_SAVING, except you can't request
|
||||
* a phase 2 save
|
||||
*/
|
||||
MSM_CLIENT_STATE_SAVING_PHASE2,
|
||||
|
||||
/* Client sent SaveYourselfDone with success = TRUE */
|
||||
MSM_CLIENT_STATE_SAVE_DONE,
|
||||
|
||||
/* Client sent SaveYourselfDone with success = FALSE */
|
||||
MSM_CLIENT_STATE_SAVE_FAILED,
|
||||
|
||||
/* Client was asked to die */
|
||||
MSM_CLIENT_STATE_DEAD
|
||||
|
||||
} MsmClientState;
|
||||
|
||||
MsmClient* msm_client_new (MsmServer *server,
|
||||
SmsConn cnxn);
|
||||
void msm_client_free (MsmClient *client);
|
||||
|
||||
SmsConn msm_client_get_connection (MsmClient *client);
|
||||
const char* msm_client_get_description (MsmClient *client);
|
||||
MsmClientState msm_client_get_state (MsmClient *client);
|
||||
MsmServer* msm_client_get_server (MsmClient *client);
|
||||
/* can return NULL */
|
||||
const char* msm_client_get_id (MsmClient *client);
|
||||
int msm_client_get_restart_style (MsmClient *client);
|
||||
|
||||
void msm_client_set_property_taking_ownership (MsmClient *client,
|
||||
SmProp *prop);
|
||||
void msm_client_unset_property (MsmClient *client,
|
||||
const char *name);
|
||||
void msm_client_send_properties (MsmClient *client);
|
||||
|
||||
void msm_client_register (MsmClient *client,
|
||||
const char *id);
|
||||
void msm_client_interact_request (MsmClient *client);
|
||||
void msm_client_begin_interact (MsmClient *client);
|
||||
void msm_client_save (MsmClient *client,
|
||||
gboolean allow_interaction,
|
||||
gboolean shut_down);
|
||||
void msm_client_initial_save (MsmClient *client);
|
||||
void msm_client_shutdown_cancelled (MsmClient *client);
|
||||
void msm_client_phase2_request (MsmClient *client);
|
||||
void msm_client_save_phase2 (MsmClient *client);
|
||||
void msm_client_save_confirmed (MsmClient *client,
|
||||
gboolean successful);
|
||||
|
||||
void msm_client_die (MsmClient *client);
|
||||
void msm_client_save_complete (MsmClient *client);
|
||||
|
||||
#endif
|
||||
|
@ -1,359 +0,0 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
* this file Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* FIXME implementation contains a bunch of cut-and-paste from GtkFrame
|
||||
* that would be easy to avoid by adding an "int space_before_label_widget"
|
||||
* in GtkFrame that was overridden by subclasses.
|
||||
*/
|
||||
|
||||
/* FIXME the whole GtkFrame derivation idea is fucked since we can't get
|
||||
* the click event on the arrow.
|
||||
*/
|
||||
|
||||
|
||||
#define ARROW_SIZE 12
|
||||
#define ARROW_PAD 2
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_DISCLOSED,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static void gtk_disclosure_box_class_init (GtkDisclosureBoxClass *klass);
|
||||
static void gtk_disclosure_box_init (GtkDisclosureBox *box);
|
||||
static void gtk_disclosure_box_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void gtk_disclosure_box_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void gtk_disclosure_box_paint (GtkWidget *widget,
|
||||
GdkRectangle *area);
|
||||
static gint gtk_disclosure_box_expose (GtkWidget *widget,
|
||||
GdkEventExpose *event);
|
||||
static void gtk_disclosure_box_size_request (GtkWidget *widget,
|
||||
GtkRequisition *requisition);
|
||||
static void gtk_disclosure_box_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation);
|
||||
|
||||
static void gtk_frame_compute_child_allocation (GtkFrame *frame,
|
||||
GtkAllocation *child_allocation);
|
||||
|
||||
GType
|
||||
gtk_disclosure_box_get_type (void)
|
||||
{
|
||||
static GType disclosure_box_type = 0;
|
||||
|
||||
if (!disclosure_box_type)
|
||||
{
|
||||
static const GtkTypeInfo disclosure_box_info =
|
||||
{
|
||||
"GtkDisclosureBox",
|
||||
sizeof (GtkDisclosureBox),
|
||||
sizeof (GtkDisclosureBoxClass),
|
||||
(GtkClassInitFunc) gtk_disclosure_box_class_init,
|
||||
(GtkObjectInitFunc) gtk_disclosure_box_init,
|
||||
/* reserved_1 */ NULL,
|
||||
/* reserved_2 */ NULL,
|
||||
(GtkClassInitFunc) NULL,
|
||||
};
|
||||
|
||||
disclosure_box_type = gtk_type_unique (gtk_box_get_type (), &disclosure_box_info);
|
||||
}
|
||||
|
||||
return disclosure_box_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_disclosure_box_class_init (GtkDisclosureBoxClass *class)
|
||||
{
|
||||
GtkWidgetClass *widget_class;
|
||||
GObjectClass *gobject_class;
|
||||
GtkContainerClass *container_class;
|
||||
GtkFrameClass *frame_class;
|
||||
|
||||
gobject_class = G_OBJECT_CLASS (class);
|
||||
widget_class = GTK_WIDGET_CLASS (class);
|
||||
container_class = GTK_CONTAINER_CLASS (class);
|
||||
frame_class = GTK_FRAME_CLASS (class);
|
||||
|
||||
gobject_class->set_property = gtk_disclosure_box_set_property;
|
||||
gobject_class->get_property = gtk_disclosure_box_get_property;
|
||||
|
||||
widget_class->size_request = gtk_disclosure_box_size_request;
|
||||
widget_class->size_allocate = gtk_disclosure_box_size_allocate;
|
||||
widget_class->expose_event = gtk_disclosure_box_expose;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_disclosure_box_init (GtkDisclosureBox *disclosure_box)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
gtk_disclosure_box_new (const char *label)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_DISCLOSURE_BOX, "label", label, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_disclosure_box_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkDisclosureBox *box;
|
||||
|
||||
box = GTK_DISCLOSURE_BOX (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DISCLOSED:
|
||||
gtk_disclosure_box_set_disclosed (box,
|
||||
g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_disclosure_box_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkDisclosureBox *box;
|
||||
|
||||
box = GTK_DISCLOSURE_BOX (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DISCLOSED:
|
||||
g_value_set_boolean (value, box->disclosed);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gtk_disclosure_box_set_disclosed (GtkDisclosureBox *box,
|
||||
gboolean disclosed)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_DISCLOSURE_BOX (box));
|
||||
|
||||
disclosed = disclosed != FALSE;
|
||||
|
||||
if (disclosed != box->disclosed)
|
||||
{
|
||||
box->disclosed = disclosed;
|
||||
gtk_widget_queue_resize (GTK_WIDGET (box));
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_disclosure_box_get_disclosed (GtkDisclosureBox *box)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_DISCLOSURE_BOX (box), FALSE);
|
||||
|
||||
return box->disclosed;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gtk_disclosure_box_paint (GtkWidget *widget,
|
||||
GdkRectangle *area)
|
||||
{
|
||||
GtkFrame *frame;
|
||||
gint x, y, width, height;
|
||||
|
||||
if (GTK_WIDGET_DRAWABLE (widget))
|
||||
{
|
||||
frame = GTK_FRAME (widget);
|
||||
|
||||
x = frame->child_allocation.x - widget->style->xthickness;
|
||||
y = frame->child_allocation.y - widget->style->ythickness;
|
||||
width = frame->child_allocation.width + 2 * widget->style->xthickness;
|
||||
height = frame->child_allocation.height + 2 * widget->style->ythickness;
|
||||
|
||||
if (frame->label_widget)
|
||||
{
|
||||
GtkRequisition child_requisition;
|
||||
gfloat xalign;
|
||||
gint height_extra;
|
||||
gint x2;
|
||||
|
||||
gtk_widget_get_child_requisition (frame->label_widget, &child_requisition);
|
||||
|
||||
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
|
||||
xalign = frame->label_xalign;
|
||||
else
|
||||
xalign = 1 - frame->label_xalign;
|
||||
|
||||
height_extra = MAX (0, child_requisition.height - widget->style->xthickness);
|
||||
y -= height_extra * (1 - frame->label_yalign);
|
||||
height += height_extra * (1 - frame->label_yalign);
|
||||
|
||||
x2 = widget->style->xthickness + (frame->child_allocation.width - child_requisition.width - 2 * LABEL_PAD - 2 * LABEL_SIDE_PAD) * xalign + LABEL_SIDE_PAD;
|
||||
|
||||
|
||||
gtk_paint_shadow_gap (widget->style, widget->window,
|
||||
GTK_STATE_NORMAL, frame->shadow_type,
|
||||
area, widget, "frame",
|
||||
x, y, width, height,
|
||||
GTK_POS_TOP,
|
||||
x2 + ARROW_SIZE + ARROW_PAD * 2, child_requisition.width + 2 * LABEL_PAD);
|
||||
|
||||
gtk_paint_arrow (widget->style, widget->window,
|
||||
widget->state, GTK_SHADOW_OUT,
|
||||
area, widget, "arrow",
|
||||
GTK_DISCLOSURE_BOX (widget)->disclosed ?
|
||||
GTK_ARROW_RIGHT : GTK_ARROW_DOWN,
|
||||
TRUE,
|
||||
x2 + ARROW_PAD, y, ARROW_SIZE, ARROW_SIZE);
|
||||
}
|
||||
else
|
||||
gtk_paint_shadow (widget->style, widget->window,
|
||||
GTK_STATE_NORMAL, frame->shadow_type,
|
||||
area, widget, "frame",
|
||||
x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_disclosure_box_expose (GtkWidget *widget,
|
||||
GdkEventExpose *event)
|
||||
{
|
||||
if (GTK_WIDGET_DRAWABLE (widget))
|
||||
{
|
||||
gtk_disclosure_box_paint (widget, &event->area);
|
||||
|
||||
(* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_disclosure_box_size_request (GtkWidget *widget,
|
||||
GtkRequisition *requisition)
|
||||
{
|
||||
GtkFrame *frame = GTK_FRAME (widget);
|
||||
GtkBin *bin = GTK_BIN (widget);
|
||||
GtkRequisition child_requisition;
|
||||
|
||||
if (frame->label_widget && GTK_WIDGET_VISIBLE (frame->label_widget))
|
||||
{
|
||||
gtk_widget_size_request (frame->label_widget, &child_requisition);
|
||||
|
||||
requisition->width = child_requisition.width + 2 * LABEL_PAD + 2 * LABEL_SIDE_PAD + ARROW_SIZE + ARROW_PAD * 2;
|
||||
requisition->height =
|
||||
MAX (0, child_requisition.height - GTK_WIDGET (widget)->style->xthickness);
|
||||
}
|
||||
else
|
||||
{
|
||||
requisition->width = 0;
|
||||
requisition->height = 0;
|
||||
}
|
||||
|
||||
if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
|
||||
{
|
||||
gtk_widget_size_request (bin->child, &child_requisition);
|
||||
|
||||
requisition->width = MAX (requisition->width, child_requisition.width);
|
||||
requisition->height += child_requisition.height;
|
||||
}
|
||||
|
||||
requisition->width += (GTK_CONTAINER (widget)->border_width +
|
||||
GTK_WIDGET (widget)->style->xthickness) * 2;
|
||||
requisition->height += (GTK_CONTAINER (widget)->border_width +
|
||||
GTK_WIDGET (widget)->style->ythickness) * 2;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_disclosure_box_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
GtkFrame *frame = GTK_FRAME (widget);
|
||||
GtkBin *bin = GTK_BIN (widget);
|
||||
GtkAllocation new_allocation;
|
||||
|
||||
widget->allocation = *allocation;
|
||||
|
||||
gtk_frame_compute_child_allocation (frame, &new_allocation);
|
||||
|
||||
/* If the child allocation changed, that means that the frame is drawn
|
||||
* in a new place, so we must redraw the entire widget.
|
||||
*/
|
||||
if (GTK_WIDGET_MAPPED (widget) &&
|
||||
(new_allocation.x != frame->child_allocation.x ||
|
||||
new_allocation.y != frame->child_allocation.y ||
|
||||
new_allocation.width != frame->child_allocation.width ||
|
||||
new_allocation.height != frame->child_allocation.height))
|
||||
gtk_widget_queue_clear (widget);
|
||||
|
||||
if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
|
||||
gtk_widget_size_allocate (bin->child, &new_allocation);
|
||||
|
||||
frame->child_allocation = new_allocation;
|
||||
|
||||
if (frame->label_widget && GTK_WIDGET_VISIBLE (frame->label_widget))
|
||||
{
|
||||
GtkRequisition child_requisition;
|
||||
GtkAllocation child_allocation;
|
||||
gfloat xalign;
|
||||
|
||||
gtk_widget_get_child_requisition (frame->label_widget, &child_requisition);
|
||||
|
||||
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
|
||||
xalign = frame->label_xalign;
|
||||
else
|
||||
xalign = 1 - frame->label_xalign;
|
||||
|
||||
child_allocation.x = frame->child_allocation.x + LABEL_SIDE_PAD +
|
||||
(frame->child_allocation.width - child_requisition.width - 2 * LABEL_PAD - 2 * LABEL_SIDE_PAD) * xalign + LABEL_PAD + ARROW_SIZE + ARROW_PAD * 2;
|
||||
child_allocation.width = child_requisition.width;
|
||||
|
||||
child_allocation.y = frame->child_allocation.y - child_requisition.height;
|
||||
child_allocation.height = child_requisition.height;
|
||||
|
||||
gtk_widget_size_allocate (frame->label_widget, &child_allocation);
|
||||
}
|
||||
}
|
||||
|
@ -1,76 +0,0 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
* this file Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_DISCLOSURE_BOX_H__
|
||||
#define __GTK_DISCLOSURE_BOX_H__
|
||||
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gtk/gtkframe.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#define GTK_TYPE_DISCLOSURE_BOX (gtk_disclosure_box_get_type ())
|
||||
#define GTK_DISCLOSURE_BOX(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_DISCLOSURE_BOX, GtkDisclosureBox))
|
||||
#define GTK_DISCLOSURE_BOX_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_DISCLOSURE_BOX, GtkDisclosureBoxClass))
|
||||
#define GTK_IS_DISCLOSURE_BOX(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_DISCLOSURE_BOX))
|
||||
#define GTK_IS_DISCLOSURE_BOX_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_DISCLOSURE_BOX))
|
||||
#define GTK_DISCLOSURE_BOX_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_DISCLOSURE_BOX, GtkDisclosureBoxClass))
|
||||
|
||||
typedef struct _GtkDisclosureBox GtkDisclosureBox;
|
||||
typedef struct _GtkDisclosureBoxClass GtkDisclosureBoxClass;
|
||||
|
||||
struct _GtkDisclosureBox
|
||||
{
|
||||
GtkFrame parent_instance;
|
||||
|
||||
guint disclosed : 1;
|
||||
};
|
||||
|
||||
struct _GtkDisclosureBoxClass
|
||||
{
|
||||
GtkFrameClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_disclosure_box_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget* gtk_disclosure_box_new (const char *label);
|
||||
|
||||
void gtk_disclosure_box_set_disclosed (GtkDisclosureBox *box,
|
||||
gboolean disclosed);
|
||||
gboolean gtk_disclosure_box_get_disclosed (GtkDisclosureBox *box);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __GTK_FRAME_H__ */
|
@ -1,22 +0,0 @@
|
||||
/* msm GUI stuff */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "gui.h"
|
@ -1,27 +0,0 @@
|
||||
/* msm GUI stuff */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MSM_GUI_H
|
||||
#define MSM_GUI_H
|
||||
|
||||
|
||||
|
||||
#endif
|
136
src/msm/main.c
136
src/msm/main.c
@ -1,136 +0,0 @@
|
||||
/* msm main() */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "server.h"
|
||||
#include "util.h"
|
||||
|
||||
static GMainLoop *main_loop = NULL;
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
g_print ("msm [--choose-session=NAME] [--failsafe]\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
static void
|
||||
shutdown_cleanly_on_signal (int signo)
|
||||
{
|
||||
if (main_loop && g_main_is_running (main_loop))
|
||||
g_main_quit (main_loop);
|
||||
}
|
||||
|
||||
void
|
||||
msm_quit (void)
|
||||
{
|
||||
if (main_loop && g_main_is_running (main_loop))
|
||||
g_main_quit (main_loop);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
const char *prev_arg;
|
||||
char *session_name;
|
||||
gboolean failsafe;
|
||||
struct sigaction act;
|
||||
sigset_t empty_mask;
|
||||
MsmServer *server;
|
||||
|
||||
sigemptyset (&empty_mask);
|
||||
act.sa_handler = SIG_IGN;
|
||||
act.sa_mask = empty_mask;
|
||||
act.sa_flags = 0;
|
||||
sigaction (SIGPIPE, &act, 0);
|
||||
|
||||
act.sa_handler = shutdown_cleanly_on_signal;
|
||||
sigaction (SIGHUP, &act, 0);
|
||||
sigaction (SIGINT, &act, 0);
|
||||
|
||||
/* connect to display */
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
/* Parse options lamely */
|
||||
session_name = NULL;
|
||||
failsafe = FALSE;
|
||||
prev_arg = NULL;
|
||||
i = 1;
|
||||
while (i < argc)
|
||||
{
|
||||
const char *arg = argv[i];
|
||||
|
||||
if (strcmp (arg, "--help") == 0 ||
|
||||
strcmp (arg, "-h") == 0 ||
|
||||
strcmp (arg, "-?") == 0)
|
||||
usage ();
|
||||
else if (strcmp (arg, "--failsafe") == 0)
|
||||
failsafe = TRUE;
|
||||
else if (strstr (arg, "--choose-session=") == arg)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
if (session_name != NULL)
|
||||
msm_fatal ("Can't specify session name twice\n");
|
||||
|
||||
name = strchr (arg, '=');
|
||||
++name;
|
||||
|
||||
session_name = g_strdup (name);
|
||||
}
|
||||
else if (prev_arg &&
|
||||
strcmp (prev_arg, "--choose-session") == 0)
|
||||
{
|
||||
if (session_name != NULL)
|
||||
msm_fatal ("Can't specify session name twice\n");
|
||||
|
||||
session_name = g_strdup (arg);
|
||||
}
|
||||
else if (strcmp (arg, "--choose-session") == 0)
|
||||
; /* wait for next arg */
|
||||
else
|
||||
usage ();
|
||||
|
||||
prev_arg = arg;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
if (failsafe)
|
||||
server = msm_server_new_failsafe ();
|
||||
else
|
||||
server = msm_server_new (session_name);
|
||||
|
||||
msm_server_launch_session (server);
|
||||
|
||||
main_loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
g_main_run (main_loop);
|
||||
|
||||
return 0;
|
||||
}
|
351
src/msm/props.c
351
src/msm/props.c
@ -1,351 +0,0 @@
|
||||
/* msm SmProp utils */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "props.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Property functions stolen from gnome-session */
|
||||
|
||||
GList*
|
||||
proplist_find_link_by_name (GList *list,
|
||||
const char *name)
|
||||
{
|
||||
for (; list; list = list->next)
|
||||
{
|
||||
SmProp *prop = (SmProp *) list->data;
|
||||
if (strcmp (prop->name, name) == 0)
|
||||
return list;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
SmProp*
|
||||
proplist_find_by_name (GList *list, const char *name)
|
||||
{
|
||||
GList *ret;
|
||||
|
||||
ret = proplist_find_link_by_name (list, name);
|
||||
|
||||
return ret ? ret->data : NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
proplist_find_card8 (GList *list, const char *name,
|
||||
int *result)
|
||||
{
|
||||
SmProp *prop;
|
||||
|
||||
g_return_val_if_fail (result != NULL, FALSE);
|
||||
|
||||
prop = proplist_find_by_name (list, name);
|
||||
if (prop == NULL)
|
||||
return FALSE;
|
||||
else
|
||||
return smprop_get_card8 (prop, result);
|
||||
}
|
||||
|
||||
gboolean
|
||||
proplist_find_string (GList *list, const char *name,
|
||||
char **result)
|
||||
{
|
||||
SmProp *prop;
|
||||
|
||||
g_return_val_if_fail (result != NULL, FALSE);
|
||||
|
||||
prop = proplist_find_by_name (list, name);
|
||||
if (prop == NULL)
|
||||
return FALSE;
|
||||
else
|
||||
return smprop_get_string (prop, result);
|
||||
}
|
||||
|
||||
GList*
|
||||
proplist_replace (GList *list,
|
||||
SmProp *new_prop)
|
||||
{
|
||||
GList *link;
|
||||
|
||||
link = proplist_find_link_by_name (list, new_prop->name);
|
||||
if (link)
|
||||
{
|
||||
SmFreeProperty (link->data);
|
||||
link->data = new_prop;
|
||||
}
|
||||
else
|
||||
{
|
||||
list = g_list_prepend (list, new_prop);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
GList*
|
||||
proplist_delete (GList *list,
|
||||
const char *name)
|
||||
{
|
||||
GList *link;
|
||||
|
||||
link = proplist_find_link_by_name (list, name);
|
||||
if (link)
|
||||
{
|
||||
SmFreeProperty (link->data);
|
||||
list = g_list_delete_link (list, link);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
GList*
|
||||
proplist_replace_card8 (GList *list,
|
||||
const char *name,
|
||||
int value)
|
||||
{
|
||||
SmProp *prop;
|
||||
|
||||
prop = smprop_new_card8 (name, value);
|
||||
|
||||
return proplist_replace (list, prop);
|
||||
}
|
||||
|
||||
GList*
|
||||
proplist_replace_string (GList *list,
|
||||
const char *name,
|
||||
const char *str,
|
||||
int len)
|
||||
{
|
||||
SmProp *prop;
|
||||
|
||||
prop = smprop_new_string (name, str, len);
|
||||
|
||||
return proplist_replace (list, prop);
|
||||
}
|
||||
|
||||
GList*
|
||||
proplist_replace_vector (GList *list,
|
||||
const char *name,
|
||||
int argc,
|
||||
char **argv)
|
||||
{
|
||||
SmProp *prop;
|
||||
|
||||
prop = smprop_new_vector (name, argc, argv);
|
||||
|
||||
return proplist_replace (list, prop);
|
||||
}
|
||||
|
||||
gboolean
|
||||
proplist_find_vector (GList *list, const char *name,
|
||||
int *argcp, char ***argvp)
|
||||
{
|
||||
SmProp *prop;
|
||||
|
||||
g_return_val_if_fail (argcp != NULL, FALSE);
|
||||
g_return_val_if_fail (argvp != NULL, FALSE);
|
||||
|
||||
prop = proplist_find_by_name (list, name);
|
||||
if (prop == NULL)
|
||||
return FALSE;
|
||||
else
|
||||
return smprop_get_vector (prop, argcp, argvp);
|
||||
}
|
||||
|
||||
gboolean
|
||||
smprop_get_card8 (SmProp *prop,
|
||||
int *result)
|
||||
{
|
||||
g_return_val_if_fail (result != NULL, FALSE);
|
||||
|
||||
if (strcmp (prop->type, SmCARD8) == 0)
|
||||
{
|
||||
char *p;
|
||||
p = prop->vals[0].value;
|
||||
*result = *p;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
smprop_get_string (SmProp *prop,
|
||||
char **result)
|
||||
{
|
||||
g_return_val_if_fail (result != NULL, FALSE);
|
||||
|
||||
if (strcmp (prop->type, SmARRAY8) == 0)
|
||||
{
|
||||
*result = g_malloc (prop->vals[0].length + 1);
|
||||
memcpy (*result, prop->vals[0].value, prop->vals[0].length);
|
||||
(*result)[prop->vals[0].length] = '\0';
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
smprop_get_vector (SmProp *prop,
|
||||
int *argcp,
|
||||
char ***argvp)
|
||||
{
|
||||
g_return_val_if_fail (argcp != NULL, FALSE);
|
||||
g_return_val_if_fail (argvp != NULL, FALSE);
|
||||
|
||||
if (strcmp (prop->type, SmLISTofARRAY8) == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
*argcp = prop->num_vals;
|
||||
*argvp = g_new0 (char *, *argcp + 1);
|
||||
for (i = 0; i < *argcp; ++i)
|
||||
{
|
||||
(*argvp)[i] = g_malloc (prop->vals[i].length + 1);
|
||||
memcpy ((*argvp)[i], prop->vals[i].value, prop->vals[i].length);
|
||||
(*argvp)[i][prop->vals[i].length] = '\0';
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SmProp*
|
||||
smprop_copy (SmProp *prop)
|
||||
{
|
||||
int i;
|
||||
SmProp *copy;
|
||||
|
||||
/* This all uses malloc so we can use SmFreeProperty() */
|
||||
|
||||
copy = msm_non_glib_malloc (sizeof (SmProp));
|
||||
|
||||
if (prop->name)
|
||||
copy->name = msm_non_glib_strdup (prop->name);
|
||||
else
|
||||
copy->name = NULL;
|
||||
|
||||
if (prop->type)
|
||||
copy->type = msm_non_glib_strdup (prop->type);
|
||||
else
|
||||
copy->type = NULL;
|
||||
|
||||
copy->num_vals = prop->num_vals;
|
||||
copy->vals = NULL;
|
||||
|
||||
if (copy->num_vals > 0 && prop->vals)
|
||||
{
|
||||
copy->vals = msm_non_glib_malloc (sizeof (SmPropValue) * copy->num_vals);
|
||||
|
||||
for (i = 0; i < copy->num_vals; i++)
|
||||
{
|
||||
if (prop->vals[i].value)
|
||||
{
|
||||
copy->vals[i].length = prop->vals[i].length;
|
||||
copy->vals[i].value = msm_non_glib_malloc (copy->vals[i].length);
|
||||
memcpy (copy->vals[i].value, prop->vals[i].value,
|
||||
copy->vals[i].length);
|
||||
}
|
||||
else
|
||||
{
|
||||
copy->vals[i].length = 0;
|
||||
copy->vals[i].value = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
SmProp*
|
||||
smprop_new_vector (const char *name,
|
||||
int argc,
|
||||
char **argv)
|
||||
{
|
||||
SmProp *prop;
|
||||
int i;
|
||||
|
||||
prop = msm_non_glib_malloc (sizeof (SmProp));
|
||||
prop->name = msm_non_glib_strdup (name);
|
||||
prop->type = msm_non_glib_strdup (SmLISTofARRAY8);
|
||||
|
||||
prop->num_vals = argc;
|
||||
prop->vals = msm_non_glib_malloc (sizeof (SmPropValue) * prop->num_vals);
|
||||
i = 0;
|
||||
while (i < argc)
|
||||
{
|
||||
prop->vals[i].length = strlen (argv[i]);
|
||||
prop->vals[i].value = msm_non_glib_strdup (argv[i]);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
SmProp*
|
||||
smprop_new_string (const char *name,
|
||||
const char *str,
|
||||
int len)
|
||||
{
|
||||
SmProp *prop;
|
||||
|
||||
if (len < 0)
|
||||
len = strlen (str);
|
||||
|
||||
prop = msm_non_glib_malloc (sizeof (SmProp));
|
||||
prop->name = msm_non_glib_strdup (name);
|
||||
prop->type = msm_non_glib_strdup (SmARRAY8);
|
||||
|
||||
prop->num_vals = 1;
|
||||
prop->vals = msm_non_glib_malloc (sizeof (SmPropValue) * prop->num_vals);
|
||||
|
||||
prop->vals[0].length = len;
|
||||
prop->vals[0].value = msm_non_glib_malloc (len);
|
||||
memcpy (prop->vals[0].value, str, len);
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
SmProp*
|
||||
smprop_new_card8 (const char *name,
|
||||
int value)
|
||||
{
|
||||
SmProp *prop;
|
||||
|
||||
prop = msm_non_glib_malloc (sizeof (SmProp));
|
||||
prop->name = msm_non_glib_strdup (name);
|
||||
prop->type = msm_non_glib_strdup (SmARRAY8);
|
||||
|
||||
prop->num_vals = 1;
|
||||
prop->vals = msm_non_glib_malloc (sizeof (SmPropValue) * prop->num_vals);
|
||||
|
||||
prop->vals[0].length = 1;
|
||||
prop->vals[0].value = msm_non_glib_malloc (1);
|
||||
(* (char*) prop->vals[0].value) = (char) value;
|
||||
|
||||
return prop;
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/* msm SmProp utils */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MSM_PROPS_H
|
||||
#define MSM_PROPS_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <X11/ICE/ICElib.h>
|
||||
#include <X11/SM/SMlib.h>
|
||||
|
||||
GList* proplist_find_link_by_name (GList *list,
|
||||
const char *name);
|
||||
SmProp* proplist_find_by_name (GList *list,
|
||||
const char *name);
|
||||
gboolean proplist_find_card8 (GList *list,
|
||||
const char *name,
|
||||
int *result);
|
||||
gboolean proplist_find_string (GList *list,
|
||||
const char *name,
|
||||
char **result);
|
||||
gboolean proplist_find_vector (GList *list,
|
||||
const char *name,
|
||||
int *argcp,
|
||||
char ***argvp);
|
||||
|
||||
GList* proplist_replace (GList *list,
|
||||
SmProp *new_prop);
|
||||
|
||||
GList* proplist_delete (GList *list,
|
||||
const char *name);
|
||||
|
||||
GList* proplist_replace_card8 (GList *list,
|
||||
const char *name,
|
||||
int value);
|
||||
GList* proplist_replace_string (GList *list,
|
||||
const char *name,
|
||||
const char *str,
|
||||
int len);
|
||||
GList* proplist_replace_vector (GList *list,
|
||||
const char *name,
|
||||
int argc,
|
||||
char **argv);
|
||||
|
||||
gboolean smprop_get_card8 (SmProp *prop,
|
||||
int *result);
|
||||
gboolean smprop_get_string (SmProp *prop,
|
||||
char **result);
|
||||
gboolean smprop_get_vector (SmProp *prop,
|
||||
int *argcp,
|
||||
char ***argvp);
|
||||
|
||||
SmProp* smprop_new_card8 (const char *name,
|
||||
int value);
|
||||
SmProp* smprop_new_string (const char *name,
|
||||
const char *str,
|
||||
int len);
|
||||
SmProp* smprop_new_vector (const char *name,
|
||||
int argc,
|
||||
char **argv);
|
||||
|
||||
|
||||
SmProp* smprop_copy (SmProp *prop);
|
||||
|
||||
#endif
|
||||
|
1330
src/msm/server.c
1330
src/msm/server.c
File diff suppressed because it is too large
Load Diff
@ -1,63 +0,0 @@
|
||||
/* msm server object */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MSM_SERVER_H
|
||||
#define MSM_SERVER_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <X11/ICE/ICElib.h>
|
||||
#include <X11/SM/SMlib.h>
|
||||
|
||||
typedef struct _MsmClient MsmClient;
|
||||
typedef struct _MsmServer MsmServer;
|
||||
|
||||
typedef void (* MsmClientFunc) (MsmClient* client);
|
||||
|
||||
MsmServer* msm_server_new (const char *session_name);
|
||||
MsmServer* msm_server_new_failsafe (void);
|
||||
void msm_server_free (MsmServer *server);
|
||||
|
||||
void msm_server_queue_interaction (MsmServer *server,
|
||||
MsmClient *client);
|
||||
|
||||
void msm_server_save_all (MsmServer *server,
|
||||
gboolean allow_interaction,
|
||||
gboolean shut_down);
|
||||
void msm_server_cancel_shutdown (MsmServer *server);
|
||||
|
||||
void msm_server_consider_phase_change (MsmServer *server);
|
||||
|
||||
void msm_server_foreach_client (MsmServer *server,
|
||||
MsmClientFunc func);
|
||||
|
||||
void msm_server_drop_client (MsmServer *server,
|
||||
MsmClient *client);
|
||||
|
||||
void msm_server_next_pending_interaction (MsmServer *server);
|
||||
|
||||
gboolean msm_server_client_id_in_use (MsmServer *server,
|
||||
const char *id);
|
||||
|
||||
void msm_server_launch_session (MsmServer *server);
|
||||
|
||||
gboolean msm_server_in_shutdown (MsmServer *server);
|
||||
|
||||
#endif
|
@ -1,759 +0,0 @@
|
||||
/* msm session */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "session.h"
|
||||
#include "util.h"
|
||||
#include "props.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
typedef struct _MsmSavedClient MsmSavedClient;
|
||||
|
||||
struct _MsmSavedClient
|
||||
{
|
||||
char *id;
|
||||
GList *properties;
|
||||
};
|
||||
|
||||
struct _MsmSession
|
||||
{
|
||||
char *name;
|
||||
GList *clients;
|
||||
char *filename;
|
||||
char *full_filename;
|
||||
int lock_fd;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MSM_SESSION_FAILURE_OPENING_FILE,
|
||||
MSM_SESSION_FAILURE_LOCKING,
|
||||
MSM_SESSION_FAILURE_BAD_FILE,
|
||||
MSM_SESSION_FAILURE_EMPTY
|
||||
} MsmSessionFailureReason;
|
||||
|
||||
static GHashTable *sessions = NULL;
|
||||
|
||||
MsmSavedClient *saved_new (void);
|
||||
void saved_free (MsmSavedClient *saved);
|
||||
|
||||
|
||||
static MsmSession* recover_failed_session (MsmSession *session,
|
||||
MsmSessionFailureReason reason,
|
||||
const char *details);
|
||||
|
||||
static gboolean parse_session_file (MsmSession *session,
|
||||
GError **error);
|
||||
|
||||
static char* decode_text_from_utf8 (const char *text);
|
||||
static char* encode_text_as_utf8 (const char *text);
|
||||
|
||||
void
|
||||
msm_session_clear (MsmSession *session)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
msm_session_update_client (MsmSession *session,
|
||||
MsmClient *client)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
msm_session_remove_client (MsmSession *session,
|
||||
MsmClient *client)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
gboolean
|
||||
msm_session_client_id_known (MsmSession *session,
|
||||
const char *previous_id)
|
||||
{
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
msm_session_launch (MsmSession *session)
|
||||
{
|
||||
system ("xclock &");
|
||||
}
|
||||
|
||||
MsmSavedClient*
|
||||
saved_new (void)
|
||||
{
|
||||
MsmSavedClient *saved;
|
||||
|
||||
saved = g_new (MsmSavedClient, 1);
|
||||
|
||||
saved->id = NULL;
|
||||
saved->properties = NULL;
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
void
|
||||
saved_free (MsmSavedClient *saved)
|
||||
{
|
||||
g_free (saved->id);
|
||||
|
||||
g_free (saved);
|
||||
}
|
||||
|
||||
static const char*
|
||||
session_dir (void)
|
||||
{
|
||||
static char *dir;
|
||||
|
||||
if (dir == NULL)
|
||||
{
|
||||
dir = g_strconcat (msm_get_work_directory (),
|
||||
"/sessions",
|
||||
NULL);
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
static void
|
||||
set_close_on_exec (int fd)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = fcntl (fd, F_GETFD, 0);
|
||||
if (val < 0)
|
||||
{
|
||||
msm_warning ("couldn't F_GETFD: %s\n", g_strerror (errno));
|
||||
return;
|
||||
}
|
||||
|
||||
val |= FD_CLOEXEC;
|
||||
|
||||
if (fcntl (fd, F_SETFD, val) < 0)
|
||||
msm_warning ("couldn't F_SETFD: %s\n", g_strerror (errno));
|
||||
}
|
||||
|
||||
/* Your basic Stevens cut-and-paste */
|
||||
static int
|
||||
lock_reg (int fd, int cmd, int type, off_t offset, int whence, off_t len)
|
||||
{
|
||||
struct flock lock;
|
||||
|
||||
lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */
|
||||
lock.l_start = offset; /* byte offset relative to whence */
|
||||
lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
|
||||
lock.l_len = len; /* #bytes, 0 for eof */
|
||||
|
||||
return fcntl (fd, cmd, &lock);
|
||||
}
|
||||
|
||||
#define lock_entire_file(fd) \
|
||||
lock_reg ((fd), F_SETLK, F_WRLCK, 0, SEEK_SET, 0)
|
||||
#define unlock_entire_file(fd) \
|
||||
lock_reg ((fd), F_SETLK, F_UNLCK, 0, SEEK_SET, 0)
|
||||
|
||||
static MsmSession*
|
||||
msm_session_get_for_filename (const char *name,
|
||||
const char *filename)
|
||||
{
|
||||
MsmSession *session;
|
||||
int fd = -1;
|
||||
GError *dir_error = NULL;
|
||||
GError *err;
|
||||
|
||||
if (sessions)
|
||||
{
|
||||
session = g_hash_table_lookup (sessions, filename);
|
||||
if (session)
|
||||
return session;
|
||||
}
|
||||
|
||||
session = g_new0 (MsmSession, 1);
|
||||
session->name = g_strdup (name);
|
||||
session->clients = NULL;
|
||||
session->filename = g_strdup (filename);
|
||||
session->full_filename = g_strconcat (session_dir (), "/", filename, NULL);
|
||||
session->lock_fd = -1;
|
||||
|
||||
dir_error = NULL;
|
||||
msm_create_dir_and_parents (session_dir (), 0700, &dir_error);
|
||||
/* We save dir_error for later; if creating the file fails,
|
||||
* we give dir_error in the reason.
|
||||
*/
|
||||
|
||||
/* To use a session, we need to lock the file in the user's
|
||||
* save dir (by default in .msm/sessions/).
|
||||
*
|
||||
* If the file didn't previously exist, then we
|
||||
* init the session from the global session of the same name,
|
||||
* if any.
|
||||
*
|
||||
* This locking stuff has several races in it, and probably doesn't
|
||||
* work over NFS, and all that jazz, but avoiding the races
|
||||
* introduces stale lock issues, which are in practice more serious
|
||||
* for users than the usual issues one worries about when locking.
|
||||
*/
|
||||
|
||||
fd = open (session->full_filename, O_RDWR | O_CREAT, 0700);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
char *message;
|
||||
|
||||
message = g_strdup_printf (_("Failed to open the session file '%s': %s (%s)"),
|
||||
session->full_filename,
|
||||
g_strerror (errno),
|
||||
dir_error ?
|
||||
dir_error->message :
|
||||
_("file's parent directory created successfully"));
|
||||
|
||||
if (dir_error)
|
||||
g_error_free (dir_error);
|
||||
|
||||
session = recover_failed_session (session,
|
||||
MSM_SESSION_FAILURE_OPENING_FILE,
|
||||
message);
|
||||
|
||||
g_free (message);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
if (dir_error)
|
||||
{
|
||||
g_error_free (dir_error);
|
||||
dir_error = NULL;
|
||||
}
|
||||
|
||||
if (lock_entire_file (fd) < 0)
|
||||
{
|
||||
char *message;
|
||||
|
||||
close (fd);
|
||||
|
||||
message = g_strdup_printf (_("Failed to lock the session file '%s': %s"),
|
||||
session->full_filename,
|
||||
g_strerror (errno));
|
||||
|
||||
session = recover_failed_session (session,
|
||||
MSM_SESSION_FAILURE_LOCKING,
|
||||
message);
|
||||
|
||||
g_free (message);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
session->lock_fd = fd;
|
||||
set_close_on_exec (fd);
|
||||
|
||||
err = NULL;
|
||||
if (!parse_session_file (session, &err))
|
||||
{
|
||||
char *message;
|
||||
|
||||
message = g_strdup_printf (_("Failed to parse the session file '%s': %s\n"),
|
||||
session->full_filename,
|
||||
err->message);
|
||||
|
||||
g_error_free (err);
|
||||
|
||||
session = recover_failed_session (session,
|
||||
MSM_SESSION_FAILURE_BAD_FILE,
|
||||
message);
|
||||
|
||||
g_free (message);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/* FIXME FALSE */
|
||||
if (FALSE && session->clients == NULL)
|
||||
{
|
||||
session = recover_failed_session (session,
|
||||
MSM_SESSION_FAILURE_EMPTY,
|
||||
NULL);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
MsmSession*
|
||||
msm_session_get (const char *name)
|
||||
{
|
||||
if (name == NULL)
|
||||
{
|
||||
return msm_session_get_for_filename (_("Default"), "Default.session");
|
||||
}
|
||||
else
|
||||
{
|
||||
char *filename;
|
||||
char *p;
|
||||
MsmSession *session;
|
||||
|
||||
filename = g_strconcat (name, ".session", NULL);
|
||||
|
||||
/* Remove path separators from the filename */
|
||||
p = filename;
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '/')
|
||||
*p = '_';
|
||||
++p;
|
||||
}
|
||||
|
||||
session = msm_session_get_for_filename (name, filename);
|
||||
|
||||
g_free (filename);
|
||||
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
MsmSession*
|
||||
msm_session_get_failsafe (void)
|
||||
{
|
||||
return msm_session_get_for_filename (_("Failsafe"), "Failsafe.session");
|
||||
}
|
||||
|
||||
static void
|
||||
write_proplist (FILE *fp,
|
||||
GList *properties)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
tmp = properties;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
SmProp *prop = tmp->data;
|
||||
char *name_encoded;
|
||||
char *type_encoded;
|
||||
|
||||
name_encoded = encode_text_as_utf8 (prop->name);
|
||||
type_encoded = encode_text_as_utf8 (prop->type);
|
||||
|
||||
fprintf (fp, " <prop name=\"%s\" type=\"%s\">\n",
|
||||
name_encoded, type_encoded);
|
||||
|
||||
g_free (name_encoded);
|
||||
g_free (type_encoded);
|
||||
|
||||
if (strcmp (prop->type, SmCARD8) == 0)
|
||||
{
|
||||
int val = 0;
|
||||
smprop_get_card8 (prop, &val);
|
||||
fprintf (fp, " <value>%d</value>\n", val);
|
||||
}
|
||||
else if (strcmp (prop->type, SmARRAY8) == 0)
|
||||
{
|
||||
char *str = NULL;
|
||||
char *encoded = NULL;
|
||||
smprop_get_string (prop, &str);
|
||||
if (str)
|
||||
encoded = encode_text_as_utf8 (str);
|
||||
if (encoded)
|
||||
fprintf (fp, " <value>%s</value>\n", encoded);
|
||||
|
||||
g_free (encoded);
|
||||
g_free (str);
|
||||
}
|
||||
else if (strcmp (prop->type, SmLISTofARRAY8) == 0)
|
||||
{
|
||||
char **vec;
|
||||
int vec_len;
|
||||
int i;
|
||||
|
||||
vec = NULL;
|
||||
vec_len = 0;
|
||||
|
||||
smprop_get_vector (prop, &vec_len, &vec);
|
||||
|
||||
i = 0;
|
||||
while (i < vec_len)
|
||||
{
|
||||
char *encoded;
|
||||
|
||||
encoded = encode_text_as_utf8 (vec[i]);
|
||||
|
||||
fprintf (fp, " <value>%s</value>\n", encoded);
|
||||
|
||||
g_free (encoded);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
g_strfreev (vec);
|
||||
}
|
||||
else
|
||||
{
|
||||
msm_warning (_("Not saving unknown property type '%s'\n"),
|
||||
prop->type);
|
||||
}
|
||||
|
||||
fputs (" </prop>\n", fp);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
msm_session_save (MsmSession *session,
|
||||
MsmServer *server)
|
||||
{
|
||||
/* We save to a secondary file then copy over, to handle
|
||||
* out-of-disk-space robustly
|
||||
*/
|
||||
int new_fd;
|
||||
char *new_filename;
|
||||
char *error;
|
||||
FILE *fp;
|
||||
|
||||
error = NULL;
|
||||
new_fd = -1;
|
||||
|
||||
new_filename = g_strconcat (session->full_filename, ".new", NULL);
|
||||
new_fd = open (session->full_filename, O_RDWR | O_CREAT | O_EXCL, 0700);
|
||||
if (new_fd < 0)
|
||||
{
|
||||
error = g_strdup_printf (_("Failed to open '%s': %s\n"),
|
||||
new_filename, g_strerror (errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lock_entire_file (new_fd) < 0)
|
||||
{
|
||||
error = g_strdup_printf (_("Failed to lock file '%s': %s"),
|
||||
new_filename,
|
||||
g_strerror (errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
fp = fdopen (new_fd, "w");
|
||||
if (fp == NULL)
|
||||
{
|
||||
error = g_strdup_printf (_("Failed to write to new session file '%s': %s"),
|
||||
new_filename, g_strerror (errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
fputs ("<msm_session>\n", fp);
|
||||
|
||||
{
|
||||
GList *tmp;
|
||||
tmp = session->clients;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MsmSavedClient *saved = tmp->data;
|
||||
char *encoded;
|
||||
|
||||
encoded = encode_text_as_utf8 (saved->id);
|
||||
|
||||
fprintf (fp, " <client id=\"%s\">\n",
|
||||
encoded);
|
||||
|
||||
g_free (encoded);
|
||||
|
||||
write_proplist (fp, saved->properties);
|
||||
|
||||
fputs (" </client>\n", fp);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
fputs ("</msm_session>\n", fp);
|
||||
|
||||
if (ferror (fp))
|
||||
{
|
||||
error = g_strdup_printf (_("Error writing new session file '%s': %s"),
|
||||
new_filename, g_strerror (errno));
|
||||
fclose (fp);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fclose (fp) < 0)
|
||||
{
|
||||
error = g_strdup_printf (_("Failed to close to new session file '%s': %s"),
|
||||
new_filename, g_strerror (errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rename (new_filename, session->full_filename) < 0)
|
||||
{
|
||||
error = g_strdup_printf (_("Failed to replace the old session file '%s' with the new session contents in the temporary file '%s': %s"),
|
||||
session->full_filename,
|
||||
new_filename, g_strerror (errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
out:
|
||||
g_free (new_filename);
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (new_fd >= 0)
|
||||
close (new_fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (session->lock_fd >= 0)
|
||||
close (session->lock_fd);
|
||||
session->lock_fd = new_fd;
|
||||
set_close_on_exec (new_fd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_details_to_dialog (GtkDialog *dialog,
|
||||
const char *details)
|
||||
{
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *button;
|
||||
GtkWidget *label;
|
||||
GtkRequisition req;
|
||||
|
||||
hbox = gtk_hbox_new (FALSE, 0);
|
||||
|
||||
gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (dialog->vbox),
|
||||
hbox,
|
||||
FALSE, FALSE, 0);
|
||||
|
||||
button = gtk_button_new_with_mnemonic (_("_Details"));
|
||||
|
||||
gtk_box_pack_end (GTK_BOX (hbox), button,
|
||||
FALSE, FALSE, 0);
|
||||
|
||||
label = gtk_label_new (details);
|
||||
|
||||
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (hbox), label,
|
||||
TRUE, TRUE, 0);
|
||||
|
||||
/* show the label on click */
|
||||
g_signal_connect_swapped (G_OBJECT (button),
|
||||
"clicked",
|
||||
G_CALLBACK (gtk_widget_show),
|
||||
label);
|
||||
|
||||
/* second callback destroys the button (note disconnects first callback) */
|
||||
g_signal_connect (G_OBJECT (button), "clicked",
|
||||
G_CALLBACK (gtk_widget_destroy),
|
||||
NULL);
|
||||
|
||||
/* Set default dialog size to size with the label,
|
||||
* and without the button, but then rehide the label
|
||||
*/
|
||||
gtk_widget_show_all (hbox);
|
||||
|
||||
gtk_widget_size_request (GTK_WIDGET (dialog), &req);
|
||||
#if 0
|
||||
/* Omitted for now because it triggers a GTK 1.3.7 bug */
|
||||
gtk_window_set_default_size (GTK_WINDOW (dialog), req.width, req.height);
|
||||
#endif
|
||||
|
||||
gtk_widget_hide (label);
|
||||
}
|
||||
|
||||
static MsmSession*
|
||||
recover_failed_session (MsmSession *session,
|
||||
MsmSessionFailureReason reason,
|
||||
const char *details)
|
||||
{
|
||||
/* FIXME, actually give option to recover, don't just complain */
|
||||
GtkWidget *dialog;
|
||||
char *message;
|
||||
|
||||
message = NULL;
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
case MSM_SESSION_FAILURE_OPENING_FILE:
|
||||
message = g_strdup_printf (_("Could not open the session \"%s.\""),
|
||||
session->name);
|
||||
/* FIXME recovery options:
|
||||
* - give up and exit; something pathological is going on
|
||||
* - choose another session?
|
||||
* - use default session in read-only mode?
|
||||
* - open xterm to repair the problem, then try again (experts only)
|
||||
*/
|
||||
break;
|
||||
|
||||
case MSM_SESSION_FAILURE_LOCKING:
|
||||
message = g_strdup_printf (_("You are already logged in elsewhere, using the session \"%s.\" You can only use a session from one location at a time."),
|
||||
session->name);
|
||||
/* FIXME recovery options:
|
||||
* - log in anyhow, with possible weirdness
|
||||
* - try again (after logging out the other session)
|
||||
* - choose another session
|
||||
* - open xterm to repair the problem, then try again (experts only)
|
||||
*/
|
||||
break;
|
||||
|
||||
case MSM_SESSION_FAILURE_BAD_FILE:
|
||||
message = g_strdup_printf (_("The session file for session \"%s\" appears to be invalid or corrupted."),
|
||||
session->name);
|
||||
/* FIXME recovery options:
|
||||
* - revert session to defaults
|
||||
* - choose another session
|
||||
* - open xterm to repair the problem, then try again (experts only)
|
||||
*/
|
||||
break;
|
||||
|
||||
case MSM_SESSION_FAILURE_EMPTY:
|
||||
message = g_strdup_printf (_("The session \"%s\" contains no applications."),
|
||||
session->name);
|
||||
/* FIXME recovery options:
|
||||
* - put default applications in the session
|
||||
* - choose another session
|
||||
* - open xterm to repair the problem, then try again (experts only)
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
dialog = gtk_message_dialog_new (NULL,
|
||||
GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
message);
|
||||
|
||||
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
|
||||
if (details)
|
||||
add_details_to_dialog (GTK_DIALOG (dialog), details);
|
||||
|
||||
g_free (message);
|
||||
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
|
||||
gtk_widget_destroy (dialog);
|
||||
|
||||
exit (1);
|
||||
|
||||
/* FIXME instead of exiting, always recover by coming up with some sort
|
||||
* of session. Also, offer nice recovery options specific to each of the above
|
||||
* failure modes.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_session_file (MsmSession *session,
|
||||
GError **error)
|
||||
{
|
||||
char *parse_file;
|
||||
struct stat sb;
|
||||
gboolean file_empty;
|
||||
|
||||
parse_file = NULL;
|
||||
file_empty = FALSE;
|
||||
|
||||
/* If the file is empty, probably because we just created it or have
|
||||
* never saved our session, then parse the global session file
|
||||
* instead of the user session file for our initial state.
|
||||
*/
|
||||
if (fstat (session->lock_fd, &sb) < 0)
|
||||
{
|
||||
/* Can't imagine this actually happening */
|
||||
msm_warning (_("Failed to stat new session file descriptor (%s)\n"),
|
||||
g_strerror (errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sb.st_size == 0)
|
||||
file_empty = TRUE;
|
||||
}
|
||||
|
||||
if (file_empty)
|
||||
parse_file = g_strconcat (MSM_PKGDATADIR, "/", session->filename, NULL);
|
||||
else
|
||||
parse_file = g_strdup (session->full_filename);
|
||||
|
||||
/* FIXME do the parsing */
|
||||
|
||||
g_free (parse_file);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static char*
|
||||
encode_text_as_utf8 (const char *text)
|
||||
{
|
||||
/* text can be any encoding, and is nul-terminated.
|
||||
* we pretend it's Latin-1 and encode as UTF-8
|
||||
*/
|
||||
GString *str;
|
||||
const char *p;
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
p = text;
|
||||
while (*p)
|
||||
{
|
||||
g_string_append_unichar (str, *p);
|
||||
++p;
|
||||
}
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
static char*
|
||||
decode_text_from_utf8 (const char *text)
|
||||
{
|
||||
/* Convert back from the encoded UTF-8 */
|
||||
GString *str;
|
||||
const char *p;
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
p = text;
|
||||
while (*p)
|
||||
{
|
||||
/* obviously this barfs if the UTF-8 contains chars > 255 */
|
||||
g_string_append_c (str, g_utf8_get_char (p));
|
||||
|
||||
p = g_utf8_next_char (p);
|
||||
}
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/* msm session */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MSM_SESSION_H
|
||||
#define MSM_SESSION_H
|
||||
|
||||
#include "client.h"
|
||||
|
||||
typedef struct _MsmSession MsmSession;
|
||||
|
||||
MsmSession* msm_session_get (const char *name);
|
||||
MsmSession* msm_session_get_failsafe (void);
|
||||
void msm_session_save (MsmSession *session,
|
||||
MsmServer *server);
|
||||
void msm_session_clear (MsmSession *session);
|
||||
void msm_session_update_client (MsmSession *session,
|
||||
MsmClient *client);
|
||||
void msm_session_remove_client (MsmSession *session,
|
||||
MsmClient *client);
|
||||
void msm_session_launch (MsmSession *session);
|
||||
gboolean msm_session_client_id_known (MsmSession *session,
|
||||
const char *previous_id);
|
||||
|
||||
|
||||
#endif
|
||||
|
181
src/msm/util.c
181
src/msm/util.c
@ -1,181 +0,0 @@
|
||||
/* msm utils */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "util.h"
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
void
|
||||
msm_fatal (const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
gchar *str;
|
||||
|
||||
g_return_if_fail (format != NULL);
|
||||
|
||||
va_start (args, format);
|
||||
str = g_strdup_vprintf (format, args);
|
||||
va_end (args);
|
||||
|
||||
fputs ("Session manager: ", stderr);
|
||||
fputs (str, stderr);
|
||||
|
||||
fflush (stderr);
|
||||
|
||||
g_free (str);
|
||||
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
msm_warning (const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
gchar *str;
|
||||
|
||||
g_return_if_fail (format != NULL);
|
||||
|
||||
va_start (args, format);
|
||||
str = g_strdup_vprintf (format, args);
|
||||
va_end (args);
|
||||
|
||||
fputs ("Session manager: ", stderr);
|
||||
fputs (str, stderr);
|
||||
|
||||
fflush (stderr);
|
||||
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
gboolean
|
||||
msm_create_dir_and_parents (const char *dir,
|
||||
int mode,
|
||||
GError **error)
|
||||
{
|
||||
char *parent;
|
||||
GSList *parents;
|
||||
GSList *tmp;
|
||||
|
||||
/* This function is crap; GNU fileutils has some really
|
||||
* robust code that does this.
|
||||
*/
|
||||
|
||||
parents = NULL;
|
||||
parent = g_path_get_dirname (dir);
|
||||
while (parent && parent[0] &&
|
||||
strcmp (parent, ".") != 0 &&
|
||||
strcmp (parent, "..") != 0 &&
|
||||
strcmp (parent, "/") != 0 &&
|
||||
/* an optimization since we will normally be using a homedir */
|
||||
strcmp (parent, g_get_home_dir ()) != 0)
|
||||
{
|
||||
parents = g_slist_prepend (parents, parent);
|
||||
parent = g_path_get_dirname (parent);
|
||||
}
|
||||
|
||||
/* Errors are a bit tricky; if we can't create /foo because
|
||||
* we lack write perms, and can't create /foo/bar because it exists,
|
||||
* but can create /foo/bar/baz, then it's not really an error.
|
||||
*
|
||||
* We more or less punt, and just display an error for the last mkdir.
|
||||
*/
|
||||
tmp = parents;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
mkdir (tmp->data, mode);
|
||||
|
||||
g_free (tmp->data);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
g_slist_free (parents);
|
||||
|
||||
if (mkdir (dir, mode) < 0)
|
||||
{
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_FILE_ERROR,
|
||||
g_file_error_from_errno (errno),
|
||||
_("Failed to create directory '%s': %s\n"),
|
||||
dir, g_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const char*
|
||||
msm_get_work_directory (void)
|
||||
{
|
||||
static const char *dir = NULL;
|
||||
|
||||
if (dir == NULL)
|
||||
{
|
||||
dir = g_getenv ("SM_SAVE_DIR");
|
||||
if (dir == NULL)
|
||||
dir = g_strconcat (g_get_home_dir (), "/.msm", NULL);
|
||||
}
|
||||
|
||||
/* ignore errors here, we'll catch them later when we
|
||||
* try to use the dir
|
||||
*/
|
||||
msm_create_dir_and_parents (dir, 0700, NULL);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
char*
|
||||
msm_non_glib_strdup (const char *str)
|
||||
{
|
||||
char *new_str;
|
||||
|
||||
if (str)
|
||||
{
|
||||
new_str = msm_non_glib_malloc (strlen (str) + 1);
|
||||
strcpy (new_str, str);
|
||||
}
|
||||
else
|
||||
new_str = NULL;
|
||||
|
||||
return new_str;
|
||||
}
|
||||
|
||||
void*
|
||||
msm_non_glib_malloc (int bytes)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
ptr = malloc (bytes);
|
||||
if (ptr == NULL)
|
||||
g_error ("Failed to allocate %d bytes\n", bytes);
|
||||
|
||||
return ptr;
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/* msm utils */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MSM_UTIL_H
|
||||
#define MSM_UTIL_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/* FIXME */
|
||||
#include <config.h>
|
||||
#define _(x) x
|
||||
#define N_(x) x
|
||||
|
||||
void msm_warning (const char *format,
|
||||
...) G_GNUC_PRINTF (1, 2);
|
||||
void msm_fatal (const char *format,
|
||||
...) G_GNUC_PRINTF (1, 2);
|
||||
|
||||
void msm_quit (void);
|
||||
|
||||
const char* msm_get_work_directory (void);
|
||||
|
||||
char* msm_non_glib_strdup (const char *src);
|
||||
void* msm_non_glib_malloc (int bytes);
|
||||
|
||||
gboolean msm_create_dir_and_parents (const char *dir,
|
||||
int mode,
|
||||
GError **error);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user