thunar-usagebars/thunar/thunar-ice.c

140 lines
3.8 KiB
C
Raw Permalink Normal View History

/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
* Copyright (c) 2006 Benedikt Meurer <benny@xfce.org>
*
* 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
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_LIBSM
#include <X11/ICE/ICElib.h>
#endif
#include "thunar/thunar-ice.h"
#ifdef HAVE_LIBSM
static void
thunar_ice_error_handler (IceConn connection)
{
/*
* The I/O error handler does whatever is necessary to respond
* to the I/O error and then returns, but it does not call
* IceCloseConnection. The ICE connection is given a "bad IO"
* status, and all future reads and writes to the connection
* are ignored. The next time IceProcessMessages is called it
* will return a status of IceProcessMessagesIOError. At that
* time, the application should call IceCloseConnection.
*/
}
static gboolean
thunar_ice_process_messages (GIOChannel *channel,
GIOCondition condition,
gpointer client_data)
{
IceProcessMessagesStatus status;
IceConn connection = client_data;
/* try to process pending messages */
status = IceProcessMessages (connection, NULL, NULL);
if (G_UNLIKELY (status == IceProcessMessagesIOError))
{
/* we were disconnected from the session manager */
IceSetShutdownNegotiation (connection, False);
IceCloseConnection (connection);
}
return TRUE;
}
static void
thunar_ice_connection_watch (IceConn connection,
IcePointer client_data,
Bool opening,
IcePointer *watch_data)
{
GIOChannel *channel;
guint watch_id;
gint fd;
if (G_LIKELY (opening))
{
/* determine the file descriptor */
fd = IceConnectionNumber (connection);
/* Make sure we don't pass on these file descriptors to an exec'd child process */
fcntl (fd, F_SETFD, fcntl (fd, F_GETFD, 0) | FD_CLOEXEC);
/* allocate an I/O channel to watch the connection */
channel = g_io_channel_unix_new (fd);
watch_id = g_io_add_watch (channel, G_IO_ERR | G_IO_HUP | G_IO_IN, thunar_ice_process_messages, connection);
g_io_channel_unref (channel);
/* remember the watch id */
*watch_data = GUINT_TO_POINTER (watch_id);
}
else
{
/* remove the watch */
watch_id = GPOINTER_TO_UINT (*watch_data);
g_source_remove (watch_id);
}
}
#endif /* !HAVE_LIBSM */
/**
* thunar_ice_init:
*
* This function should be called before you use any ICE functions.
* It will arrange for ICE connections to be read and dispatched via
* the Glib event loop mechanism. This function can be called any number
* of times without any harm.
**/
void
thunar_ice_init (void)
{
#ifdef HAVE_LIBSM
static gboolean initialized = FALSE;
if (G_LIKELY (!initialized))
{
/* setup our custom I/O error handler */
IceSetIOErrorHandler (thunar_ice_error_handler);
/* add the connection watch */
IceAddConnectionWatch (thunar_ice_connection_watch, NULL);
initialized = TRUE;
}
#endif /* !HAVE_LIBSM */
}