bin_PROGRAMS = \
openbox/openbox \
+ tools/gdm-control/gdm-control \
tools/gnome-panel-control/gnome-panel-control
dist_secretbin_SCRIPTS = \
openbox/actions/if.c \
openbox/actions/kill.c \
openbox/actions/layer.c \
+ openbox/actions/session.c \
openbox/actions/lower.c \
openbox/actions/maximize.c \
openbox/actions/move.c \
tools_gnome_panel_control_gnome_panel_control_SOURCES = \
tools/gnome-panel-control/gnome-panel-control.c
+## gdm-control ##
+
+tools_gdm_control_gdm_control_CPPFLAGS = \
+ $(X_CFLAGS) \
+ $(GLIB_CFLAGS)
+tools_gdm_control_gdm_control_LDADD = \
+ $(X_LIBS) \
+ $(GLIB_LIBS)
+tools_gdm_control_gdm_control_SOURCES = \
+ tools/gdm-control/gdm-control.c
+
## default button masks ##
dist_docxbm_DATA = \
</item>
</menu>
+<menu id="system-menu" label="System">
+ <item label="Openbox Configuration Manager">
+ <action name="Execute">
+ <command>obconf</command>
+ <startupnotify><enabled>yes</enabled></startupnotify>
+ </action>
+ </item>
+ <item label="Gnome Control Center">
+ <action name="Execute">
+ <command>gnome-control-center</command>
+ <startupnotify><enabled>yes</enabled></startupnotify>
+ </action>
+ </item>
+ <item label="KDE Control Center">
+ <action name="Execute">
+ <command>kcontrol</command>
+ <startupnotify><enabled>yes</enabled></startupnotify>
+ </action>
+ </item>
+ <item label="Manage Cups Printers">
+ <action name="Execute">
+ <command>xdg-open http://localhost:631/</command>
+ <startupnotify>
+ <enabled>no</enabled>
+ <icon>cups</icon>
+ </startupnotify>
+ </action>
+ </item>
+ <separator />
+ <item label="Reconfigure Openbox">
+ <action name="Reconfigure" />
+ </item>
+ <item label="Exit Openbox">
+ <action name="Exit">
+ <prompt>yes</prompt>
+ </action>
+ </item>
+</menu>
+
<menu id="root-menu" label="Openbox 3">
<separator label="Applications" />
<menu id="apps-accessories-menu"/>
<menu id="apps-term-menu"/>
<menu id="apps-fileman-menu"/>
<separator label="System" />
- <item label="ObConf">
- <action name="Execute">
- <command>obconf</command>
- <startupnotify><enabled>yes</enabled></startupnotify>
- </action>
- </item>
- <item label="Reconfigure">
- <action name="Reconfigure" />
- </item>
+ <menu id="system-menu"/>
<separator />
- <item label="Exit">
- <action name="Exit">
+ <item label="Logout">
+ <action name="SessionLogout">
<prompt>yes</prompt>
</action>
</item>
action_reconfigure_startup();
action_exit_startup();
action_restart_startup();
+ action_session_startup();
action_cyclewindows_startup();
action_breakchroot_startup();
action_close_startup();
void action_reconfigure_startup(void);
void action_exit_startup(void);
void action_restart_startup(void);
+void action_session_startup(void);
void action_cyclewindows_startup(void);
void action_breakchroot_startup(void);
void action_close_startup(void);
Options *o;
o = g_new0(Options, 1);
+ o->prompt = TRUE;
if ((n = obt_parse_find_node(node, "prompt")))
o->prompt = obt_parse_node_bool(n);
--- /dev/null
+#include "openbox/actions.h"
+#include "openbox/prompt.h"
+#include "openbox/session.h"
+#include "gettext.h"
+
+#ifndef USE_SM
+void action_logout_startup(void) {}
+#else
+
+typedef struct {
+ gboolean prompt;
+ gboolean silent;
+} Options;
+
+static gpointer setup_func(xmlNodePtr node);
+static gboolean logout_func(ObActionsData *data, gpointer options);
+
+void action_session_startup(void)
+{
+ actions_register("SessionLogout", setup_func, NULL, logout_func,
+ NULL, NULL);
+}
+
+static gpointer setup_func(xmlNodePtr node)
+{
+ xmlNodePtr n;
+ Options *o;
+
+ o = g_new0(Options, 1);
+ o->prompt = TRUE;
+
+ if ((n = obt_parse_find_node(node, "prompt")))
+ o->prompt = obt_parse_node_bool(n);
+
+ return o;
+}
+
+static void prompt_cb(ObPrompt *p, gint result, gpointer data)
+{
+ Options *o = data;
+ if (result)
+ session_request_logout(o->silent);
+ g_free(o);
+ prompt_unref(p);
+}
+
+/* Always return FALSE because its not interactive */
+static gboolean logout_func(ObActionsData *data, gpointer options)
+{
+ Options *o = options;
+
+ if (o->prompt) {
+ Options *o2;
+ ObPrompt *p;
+ ObPromptAnswer answers[] = {
+ { _("Cancel"), 0 },
+ { _("Log out"), 1 }
+ };
+
+ o2 = g_memdup(o, sizeof(Options));
+ p = prompt_new(_("Are you sure you want to log out?"),
+ answers, 2, 0, 0, prompt_cb, o2);
+ prompt_show(p, NULL, FALSE);
+ }
+ else
+ prompt_cb(NULL, 1, NULL);
+
+ return FALSE;
+}
+
+#endif
else if (keycode == ob_keycode(OB_KEY_LEFT)) {
/* Left goes to the parent menu */
- menu_frame_select(frame, NULL, TRUE);
+ if (frame->parent)
+ menu_frame_select(frame, NULL, TRUE);
ret = TRUE;
}
self->button[i].width = bw;
self->button[i].height = bh;
RrMinSize(prompt_a_focus, &bw, &bh);
- g_print("button w %d h %d\n", bw, bh);
self->button[i].width = MAX(self->button[i].width, bw);
self->button[i].height = MAX(self->button[i].height, bh);
RrMinSize(prompt_a_press, &bw, &bh);
a->texture[4].data.lineart.x2 = e->width - r - 1;
a->texture[4].data.lineart.y1 = t;
a->texture[4].data.lineart.y2 = e->height - b - 1;
-
- g_print("setting x2 %d\n", e->width - r - 1);
}
static void render_button(ObPrompt *self, ObPromptElement *e)
void session_startup(gint argc, gchar **argv) {}
void session_shutdown(gboolean permanent) {}
GList* session_state_find(struct _ObClient *c) { return NULL; }
+void session_request_logout(gboolean silent) {}
#else
#include "debug.h"
obt_parse_instance_unref(i);
}
+void session_request_logout(gboolean silent)
+{
+ if (sm_conn) {
+ SmcRequestSaveYourself(sm_conn,
+ SmSaveBoth,
+ TRUE, /* logout */
+ (silent ?
+ SmInteractStyleNone : SmInteractStyleAny),
+ TRUE, /* if false, with GSM, it shows the old
+ logout prompt */
+ TRUE); /* global */
+ }
+ else
+ g_message(_("Not connected to a session manager"));
+}
+
#endif
GList* session_state_find(struct _ObClient *c);
+void session_request_logout(gboolean silent);
+
#endif
--- /dev/null
+all clean install:
+ $(MAKE) -C ../.. -$(MAKEFLAGS) $@
+
+.PHONY: all clean install
--- /dev/null
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xauth.h>
+
+#include <glib.h>
+
+typedef enum
+{
+ INVALID,
+ NONE,
+ SHUTDOWN,
+ REBOOT,
+ SUSPEND,
+ SWITCHUSER
+} Action;
+
+#define GDM_PROTOCOL_SOCKET_PATH1 "/var/run/gdm_socket"
+#define GDM_PROTOCOL_SOCKET_PATH2 "/tmp/.gdm_socket"
+
+#define GDM_PROTOCOL_MSG_CLOSE "CLOSE"
+#define GDM_PROTOCOL_MSG_VERSION "VERSION"
+#define GDM_PROTOCOL_MSG_AUTHENTICATE "AUTH_LOCAL"
+#define GDM_PROTOCOL_MSG_QUERY_ACTION "QUERY_LOGOUT_ACTION"
+#define GDM_PROTOCOL_MSG_SET_ACTION "SET_SAFE_LOGOUT_ACTION"
+#define GDM_PROTOCOL_MSG_FLEXI_XSERVER "FLEXI_XSERVER"
+
+#define GDM_ACTION_STR_NONE GDM_PROTOCOL_MSG_SET_ACTION" NONE"
+#define GDM_ACTION_STR_SHUTDOWN GDM_PROTOCOL_MSG_SET_ACTION" HALT"
+#define GDM_ACTION_STR_REBOOT GDM_PROTOCOL_MSG_SET_ACTION" REBOOT"
+#define GDM_ACTION_STR_SUSPEND GDM_PROTOCOL_MSG_SET_ACTION" SUSPEND"
+
+#define GDM_MIT_MAGIC_COOKIE_LEN 16
+
+static int fd = 0;
+
+static void gdm_disconnect()
+{
+ if (fd > 0)
+ close(fd);
+ fd = 0;
+}
+
+static char* get_display_number(void)
+{
+ char *display_name;
+ char *retval;
+ char *p;
+
+ display_name = XDisplayName(NULL);
+
+ p = strchr(display_name, ':');
+ if (!p)
+ return g_strdup ("0");
+
+ while (*p == ':') p++;
+
+ retval = g_strdup (p);
+
+ p = strchr (retval, '.');
+ if (p != NULL)
+ *p = '\0';
+
+ return retval;
+}
+
+static char* gdm_send_protocol_msg (const char *msg)
+{
+ GString *retval;
+ char buf[256];
+ char *p;
+ int len;
+
+ p = g_strconcat(msg, "\n", NULL);
+ if (write (fd, p, strlen(p)) < 0) {
+ g_free (p);
+
+ g_warning ("Failed to send message to GDM: %s",
+ g_strerror (errno));
+ return NULL;
+ }
+ g_free (p);
+
+ p = NULL;
+ retval = NULL;
+ while ((len = read(fd, buf, sizeof(buf) - 1)) > 0) {
+ buf[len] = '\0';
+
+ if (!retval)
+ retval = g_string_new(buf);
+ else
+ retval = g_string_append(retval, buf);
+
+ if ((p = strchr(retval->str, '\n')))
+ break;
+ }
+
+ if (p) *p = '\0';
+
+ return retval ? g_string_free(retval, FALSE) : NULL;
+}
+
+static gboolean gdm_authenticate()
+{
+ FILE *f;
+ Xauth *xau;
+ const char *xau_path;
+ char *display_number;
+ gboolean retval;
+
+ if (!(xau_path = XauFileName()))
+ return FALSE;
+
+ if (!(f = fopen(xau_path, "r")))
+ return FALSE;
+
+ retval = FALSE;
+ display_number = get_display_number();
+
+ while ((xau = XauReadAuth(f))) {
+ char buffer[40]; /* 2*16 == 32, so 40 is enough */
+ char *msg;
+ char *response;
+ int i;
+
+ if (xau->family != FamilyLocal ||
+ strncmp (xau->number, display_number, xau->number_length) ||
+ strncmp (xau->name, "MIT-MAGIC-COOKIE-1", xau->name_length) ||
+ xau->data_length != GDM_MIT_MAGIC_COOKIE_LEN)
+ {
+ XauDisposeAuth(xau);
+ continue;
+ }
+
+ for (i = 0; i < GDM_MIT_MAGIC_COOKIE_LEN; i++)
+ g_snprintf(buffer + 2*i, 3, "%02x", (guint)(guchar)xau->data[i]);
+
+ XauDisposeAuth(xau);
+
+ msg = g_strdup_printf(GDM_PROTOCOL_MSG_AUTHENTICATE " %s", buffer);
+ response = gdm_send_protocol_msg(msg);
+ g_free (msg);
+
+ if (response && !strcmp(response, "OK")) {
+ /*auth_cookie = g_strdup(buffer);*/
+ g_free(response);
+ retval = TRUE;
+ break;
+ }
+
+ g_free (response);
+ }
+
+ fclose(f);
+ return retval;
+}
+
+static gboolean gdm_connect()
+{
+ struct sockaddr_un addr;
+ char *response;
+
+ assert(fd <= 0);
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ g_warning("Failed to create GDM socket: %s", g_strerror (errno));
+ gdm_disconnect();
+ return FALSE;
+ }
+
+ if (g_file_test(GDM_PROTOCOL_SOCKET_PATH1, G_FILE_TEST_EXISTS))
+ strcpy(addr.sun_path, GDM_PROTOCOL_SOCKET_PATH1);
+ else
+ strcpy(addr.sun_path, GDM_PROTOCOL_SOCKET_PATH2);
+
+ addr.sun_family = AF_UNIX;
+
+ if (connect(fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) {
+ g_warning("Failed to establish a connection with GDM: %s",
+ g_strerror(errno));
+ gdm_disconnect();
+ return FALSE;
+ }
+
+ response = gdm_send_protocol_msg(GDM_PROTOCOL_MSG_VERSION);
+ if (!response || strncmp(response, "GDM ", strlen("GDM ") != 0)) {
+ g_free(response);
+
+ g_warning("Failed to get protocol version from GDM");
+ gdm_disconnect();
+ return FALSE;
+ }
+ g_free(response);
+
+ if (!gdm_authenticate()) {
+ g_warning("Failed to authenticate with GDM");
+ gdm_disconnect();
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+ Action a = INVALID;
+
+ for (i = 1; i < argc; ++i) {
+ if (!strcmp(argv[i], "--help")) {
+ a = INVALID;
+ break;
+ }
+ if (!strcmp(argv[i], "--none")) {
+ a = NONE;
+ break;
+ }
+ if (!strcmp(argv[i], "--shutdown")) {
+ a = SHUTDOWN;
+ break;
+ }
+ if (!strcmp(argv[i], "--reboot")) {
+ a = REBOOT;
+ break;
+ }
+ if (!strcmp(argv[i], "--suspend")) {
+ a = SUSPEND;
+ break;
+ }
+ if (!strcmp(argv[i], "--switch-user")) {
+ a = SWITCHUSER;
+ break;
+ }
+ }
+
+ if (!a) {
+ printf("Usage: gdm-control ACTION\n\n");
+ printf("Actions:\n");
+ printf(" --help Display this help and exit\n");
+ printf(" --none Do nothing special when the current session ends\n");
+ printf(" --shutdown Shutdown the computer when the current session ends\n");
+ printf(" --reboot Reboot the computer when the current session ends\n");
+ printf(" --suspend Suspend the computer when the current session ends\n");
+ printf(" --switch-user Log in as a new user (this works immediately)\n\n");
+ return 0;
+ }
+
+ {
+ char *d, *response;
+ const char *action_string;
+
+ d = XDisplayName(NULL);
+ if (!d) {
+ fprintf(stderr,
+ "Unable to fina an X display specified by the DISPLAY "
+ "environment variable. Ensure that it is set correctly.");
+ return 1;
+ }
+
+ switch (a) {
+ case NONE:
+ action_string = GDM_ACTION_STR_NONE;
+ break;
+ case SHUTDOWN:
+ action_string = GDM_ACTION_STR_SHUTDOWN;
+ break;
+ case REBOOT:
+ action_string = GDM_ACTION_STR_REBOOT;
+ break;
+ case SUSPEND:
+ action_string = GDM_ACTION_STR_SUSPEND;
+ break;
+ case SWITCHUSER:
+ action_string = GDM_PROTOCOL_MSG_FLEXI_XSERVER;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (gdm_connect()) {
+ response = gdm_send_protocol_msg(action_string);
+ g_free(response);
+ gdm_disconnect();
+ }
+ }
+
+ return 0;
+}