Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/ChangeLog,v
retrieving revision 1.1999
diff -u -p -r1.1999 ChangeLog
--- ChangeLog	21 Jan 2003 20:40:31 -0000	1.1999
+++ ChangeLog	30 Jan 2003 00:24:57 -0000
@@ -0,0 +1,44 @@
+2003-01-30  Mark McLoughlin  <mark@skynet.ie>
+
+	* Makefile.am: add panel-ctrl-alt-delete.[ch] to the
+	build.
+
+	* global-keys.c:
+	(panel_global_keys_filter): invoke panel_ctrl_alt_delete()
+	in <Ctrl><Alt>Delete rather than panel_kill_application().
+
+	* main.c: (main): add $(prefix)/share/icons/gnome-app-manager
+	to the icon path for the moment.
+
+	* panel-ctrl-alt-delete.[ch]: implenet a popup which gives
+	a choice between Lock/Logout/Start App Manager and Kill Application.
+
+	* panel-stock-icons.[ch]: (panel_init_stock_icons_and_items):
+	Register various stock icons and items for use with the dialog.
+
+2003-01-24  Mark McLoughlin  <mark@skynet.ie>
+
+	* Makefile.am: add panel-kill-application.[ch] to
+	the build.
+
+	* panel-application-kill.[ch]: impl a safer more GNOMEish
+	version of xkill.
+
+	* global-keys.c: (panel_global_keys_setup),
+	(panel_global_keys_filter): impl monitoring for
+	the kill application binding.
+
+	* menu.c: (create_button_menu): add the kill application
+	button.
+
+	* panel-action-button.[ch]: (panel_action_kill): ditto.
+
+	* panel-config-global.[ch]: (panel_global_config_set_entry):
+	handle the kill_application_key global setting.
+
+	* panel-global-config.schemas.in: add the kill_application_key
+	gconf key. Default to <Ctrl><Atl>Delete.
+
+	* panel-stock-icons.[ch]: (panel_init_stock_icons_and_items):
+	add the panel-kill stock icon.
+
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/Makefile.am,v
retrieving revision 1.307
diff -u -p -r1.307 Makefile.am
--- Makefile.am	12 Jan 2003 04:08:46 -0000	1.307
+++ Makefile.am	30 Jan 2003 00:24:58 -0000
@@ -139,6 +139,8 @@ panel_sources =			\
 	panel-menu-bar.c        \
 	panel-recent.c		\
 	panel-gdk-pixbuf-extensions.c \
+	panel-kill-application.c \
+	panel-ctrl-alt-delete.c \
 	$(EGG_RECENT_FILES_C)	\
 	$(NULL)
 
@@ -184,6 +186,8 @@ panel_headers =			\
 	panel-menu-bar.h        \
 	panel-recent.h		\
 	panel-gdk-pixbuf-extensions.h \
+	panel-kill-application.h \
+	panel-ctrl-alt-delete.h \
 	$(EGG_RECENT_FILES_H)	\
 	$(NULL)
 
Index: global-keys.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/global-keys.c,v
retrieving revision 1.38
diff -u -p -r1.38 global-keys.c
--- global-keys.c	21 Jan 2003 08:45:37 -0000	1.38
+++ global-keys.c	30 Jan 2003 00:25:00 -0000
@@ -16,6 +16,7 @@
 #include "egg-screen-exec.h"
 #include "eggaccelerators.h"
 #include "xstuff.h"
+#include "panel-ctrl-alt-delete.h"
 
 extern GlobalConfig global_config;
 extern GSList *panels;
@@ -131,6 +132,8 @@ panel_global_keys_setup (void)
 	static guint laststate_screenshot = 0;
 	static guint lastkey_window_screenshot = 0;
 	static guint laststate_window_screenshot = 0;
+	static guint lastkey_kill_application = 0;
+	static guint laststate_kill_application = 0;
 
 	/* FIXME: the if trees are horrible, this shoul dbe cleaned up with
 	 * lists or something */
@@ -144,14 +147,14 @@ panel_global_keys_setup (void)
 	     laststate_menu != laststate_run)) {
 		ungrab_key (laststate_run, lastkey_run);
 	}
-	if (lastkey_run != 0 &&
+	if (lastkey_screenshot != 0 &&
 	    (lastkey_menu != lastkey_screenshot ||
 	     laststate_menu != laststate_screenshot) &&
 	    (lastkey_run != lastkey_screenshot ||
 	     laststate_run != laststate_screenshot)) {
 		ungrab_key (laststate_screenshot, lastkey_screenshot);
 	}
-	if (lastkey_run != 0 &&
+	if (lastkey_window_screenshot != 0 &&
 	    (lastkey_menu != lastkey_window_screenshot ||
 	     laststate_menu != laststate_window_screenshot) &&
 	    (lastkey_run != lastkey_window_screenshot ||
@@ -161,6 +164,18 @@ panel_global_keys_setup (void)
 		ungrab_key (laststate_window_screenshot,
 			    lastkey_window_screenshot);
 	}
+	if (lastkey_kill_application != 0 &&
+	    (lastkey_menu != lastkey_kill_application ||
+	     laststate_menu != laststate_kill_application) &&
+	    (lastkey_run != lastkey_kill_application ||
+	     laststate_run != laststate_kill_application) &&
+	    (lastkey_screenshot != lastkey_kill_application ||
+	     laststate_screenshot != laststate_kill_application) &&
+	    (lastkey_window_screenshot != lastkey_kill_application ||
+	     laststate_window_screenshot != laststate_kill_application)) {
+		ungrab_key (laststate_kill_application,
+			    lastkey_kill_application);
+	}
 	
 	if (global_config.keys_enabled && 
 	    global_config.menu_key.keysym) {
@@ -219,6 +234,26 @@ panel_global_keys_setup (void)
 		lastkey_window_screenshot = 0;
 	}
 
+	if (global_config.keys_enabled && 
+	    global_config.kill_application_key.keysym) {
+		lastkey_kill_application = XKeysymToKeycode
+			(GDK_DISPLAY (), global_config.kill_application_key.keysym);
+		laststate_kill_application = global_config.kill_application_key.state;
+		if (lastkey_kill_application != 0 &&
+		    (lastkey_menu != lastkey_kill_application ||
+		     laststate_menu != laststate_kill_application) &&
+		    (lastkey_run != lastkey_kill_application ||
+		     laststate_run != laststate_kill_application) &&
+		    (lastkey_screenshot != lastkey_kill_application ||
+		     laststate_screenshot != laststate_kill_application) &&
+		    (lastkey_window_screenshot != lastkey_kill_application ||
+		     laststate_window_screenshot != laststate_kill_application))
+			grab_key (laststate_kill_application,
+				  lastkey_kill_application);
+	} else {
+		lastkey_kill_application = 0;
+	}
+
 	gdk_flush ();
 	gdk_error_trap_pop();
 }
@@ -247,6 +282,7 @@ panel_global_keys_filter (GdkXEvent *gdk
 	guint run_keycode, run_state;
 	guint screenshot_keycode, screenshot_state;
 	guint window_screenshot_keycode, window_screenshot_state;
+	guint kill_application_keycode, kill_application_state;
         guint ignored_mods;
 
 	g_return_val_if_fail (GDK_IS_SCREEN (screen), GDK_FILTER_CONTINUE);
@@ -276,6 +312,12 @@ panel_global_keys_filter (GdkXEvent *gdk
 				  global_config.window_screenshot_key.keysym);
 	window_screenshot_state = global_config.window_screenshot_key.state;
 
+	kill_application_keycode =
+		XKeysymToKeycode (GDK_DISPLAY (),
+				  global_config.kill_application_key.keysym);
+	kill_application_state = global_config.kill_application_key.state;
+
+
 	if (keycode == menu_keycode &&
 	    (state & (~ignored_mods)) == menu_state) {
 		PanelWidget *panel_widget;
@@ -365,7 +407,9 @@ panel_global_keys_filter (GdkXEvent *gdk
 		g_free (proggie);
 
 		return GDK_FILTER_REMOVE;
-	}
+	} else if (keycode == kill_application_keycode &&
+		   (state & (~ignored_mods)) == kill_application_state)
+		panel_ctrl_alt_delete (screen);
 
 	return GDK_FILTER_CONTINUE;
 }
Index: main.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/main.c,v
retrieving revision 1.330
diff -u -p -r1.330 main.c
--- main.c	10 Jan 2003 01:19:51 -0000	1.330
+++ main.c	30 Jan 2003 00:25:00 -0000
@@ -175,6 +175,10 @@ main(int argc, char **argv)
 		return -1;
 
 	panel_icon_theme = gnome_icon_theme_new ();
+
+	/* FIXME: temporary hack for the gnome-kill-application1.png */
+	gnome_icon_theme_append_search_path (
+		panel_icon_theme, DATADIR "/icons/gnome-app-manager");
 	
 	find_kde_directory();
 
Index: menu.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/menu.c,v
retrieving revision 1.648
diff -u -p -r1.648 menu.c
--- menu.c	20 Jan 2003 06:36:32 -0000	1.648
+++ menu.c	30 Jan 2003 00:25:10 -0000
@@ -3135,6 +3135,15 @@ create_button_menu (void)
 
 	menuitem = gtk_image_menu_item_new ();
 	setup_stock_menu_item (
+		menuitem, GTK_ICON_SIZE_MENU, PANEL_STOCK_KILL, _("Kill Application"));
+	gtk_menu_shell_append (GTK_MENU_SHELL (retval), menuitem);
+	g_signal_connect (menuitem, "activate",
+			  G_CALLBACK (add_action_button_to_panel),
+			  GINT_TO_POINTER (PANEL_ACTION_KILL));
+	setup_internal_applet_drag (menuitem, "ACTION:kill:NEW");
+
+	menuitem = gtk_image_menu_item_new ();
+	setup_stock_menu_item (
 		menuitem, GTK_ICON_SIZE_MENU, PANEL_STOCK_LOGOUT, _("Log Out"));
 	gtk_menu_shell_append (GTK_MENU_SHELL (retval), menuitem);
 	g_signal_connect (menuitem, "activate",
Index: panel-action-button.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-action-button.c,v
retrieving revision 1.4
diff -u -p -r1.4 panel-action-button.c
--- panel-action-button.c	20 Jan 2003 06:36:32 -0000	1.4
+++ panel-action-button.c	30 Jan 2003 00:25:12 -0000
@@ -39,6 +39,7 @@
 #include "panel-gconf.h"
 #include "panel-stock-icons.h"
 #include "panel-typebuiltins.h"
+#include "panel-kill-application.h"
 #include "panel-util.h"
 #include "session.h"
 
@@ -67,6 +68,7 @@ static GConfEnumStringPair panel_action_
 	{ PANEL_ACTION_RUN,          "run"          },
 	{ PANEL_ACTION_SEARCH,       "search"       },
 	{ PANEL_ACTION_SCREENSHOT,   "screenshot"   },
+	{ PANEL_ACTION_KILL,         "kill"   },
 };
 
 /* Lock Screen
@@ -171,6 +173,18 @@ panel_action_screenshot (GtkWidget *widg
 				    _("Cannot execute gnome-panel-screenshot"));
 }
 
+/* Kill application
+ */
+static void
+panel_action_kill (GtkWidget *widget)
+{
+	GdkScreen *screen;
+
+	screen = gtk_widget_get_screen (widget);
+
+	panel_kill_application (screen);
+}
+
 typedef struct {
 	PanelActionButtonType   type;
 	char                   *stock_icon;
@@ -212,6 +226,11 @@ static PanelAction actions [] = {
 		PANEL_ACTION_SCREENSHOT, PANEL_STOCK_SCREENSHOT,
 		N_("Screenshot"), NULL,
 		panel_action_screenshot, NULL, NULL
+	},
+	{
+		PANEL_ACTION_KILL, PANEL_STOCK_KILL,
+		N_("Kill Application"), NULL,
+		panel_action_kill, NULL, NULL
 	}
 };
 
Index: panel-action-button.h
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-action-button.h,v
retrieving revision 1.2
diff -u -p -r1.2 panel-action-button.h
--- panel-action-button.h	20 Jan 2003 06:36:32 -0000	1.2
+++ panel-action-button.h	30 Jan 2003 00:25:12 -0000
@@ -49,7 +49,7 @@ typedef enum {
 	PANEL_ACTION_RUN,
 	PANEL_ACTION_SEARCH,
 	PANEL_ACTION_SCREENSHOT,
-	PANEL_ACTION_SHOW_DESKTOP,
+	PANEL_ACTION_KILL,
 	PANEL_ACTION_LAST
 } PanelActionButtonType;
 
Index: panel-config-global.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-config-global.c,v
retrieving revision 1.17
diff -u -p -r1.17 panel-config-global.c
--- panel-config-global.c	7 Dec 2002 21:18:46 -0000	1.17
+++ panel-config-global.c	30 Jan 2003 00:25:12 -0000
@@ -111,6 +111,15 @@ panel_global_config_set_entry (GConfEntr
 
 		panel_parse_accelerator (&global_config.window_screenshot_key);
 
+	} else if (strcmp (key, "kill_application_key") == 0) {
+		if (global_config.kill_application_key.str)
+			g_free (global_config.kill_application_key.str);
+
+		global_config.kill_application_key.str =
+			 g_strdup (gconf_value_get_string (value));
+
+		panel_parse_accelerator (&global_config.kill_application_key);
+
 	} else if (strcmp (key, "drawer_autoclose") == 0)
 		global_config.drawer_auto_close =
 			gconf_value_get_bool (value);
Index: panel-config-global.h
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-config-global.h,v
retrieving revision 1.62
diff -u -p -r1.62 panel-config-global.h
--- panel-config-global.h	7 Dec 2002 21:18:46 -0000	1.62
+++ panel-config-global.h	30 Jan 2003 00:25:12 -0000
@@ -31,6 +31,7 @@ typedef struct {
  * menu_key
  * run_key
  * window_screenshot_key
+ * kill_application_key
  *
  * drawer_autoclose (+)
  * confirm_panel_remove
@@ -53,6 +54,7 @@ struct _GlobalConfig {
 	GlobalConfigKey    run_key;
 	GlobalConfigKey    screenshot_key;
 	GlobalConfigKey    window_screenshot_key;
+	GlobalConfigKey    kill_application_key;
 
 	gboolean           drawer_auto_close;
 	gboolean           confirm_panel_remove;
Index: panel-ctrl-alt-delete.c
===================================================================
RCS file: panel-ctrl-alt-delete.c
diff -N panel-ctrl-alt-delete.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ panel-ctrl-alt-delete.c	30 Jan 2003 00:25:12 -0000
@@ -0,0 +1,249 @@
+/*
+ * panel-kill-application.c:
+ *
+ * Copyright (C) 2002 Sun Microsystems, 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *	Mark McLoughlin <mark@skynet.ie>
+ */
+
+#include <config.h>
+
+#include "panel-ctrl-alt-delete.h"
+
+#include <string.h>
+#include <libgnome/gnome-i18n.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+
+#include "panel-stock-icons.h"
+#include "panel-kill-application.h"
+#include "panel-util.h"
+#include "session.h"
+#include "egg-screen-exec.h"
+
+static GdkFilterReturn popup_filter (GdkXEvent *gdk_xevent,
+				     GdkEvent  *event,
+				     GtkWidget *popup);
+
+static void
+close_popup (GtkWidget *dialog)
+{
+	GdkWindow *root;
+
+	root = gdk_screen_get_root_window (
+			gtk_window_get_screen (GTK_WINDOW (dialog)));
+	gdk_window_remove_filter (root, (GdkFilterFunc) popup_filter, dialog);
+
+	gtk_widget_destroy (dialog);
+	gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+}
+
+static void
+handle_lock_screen (GtkWidget *dialog)
+{
+	GdkScreen *screen;
+
+	screen = gtk_window_get_screen (GTK_WINDOW (dialog));
+
+	close_popup (dialog);
+
+	panel_lock_screen (screen);
+}
+
+static void
+handle_logout (GtkWidget *dialog)
+{
+	close_popup (dialog);
+
+	panel_quit ();
+}
+
+static void
+handle_app_manager (GtkWidget *dialog)
+{
+	GdkScreen *screen;
+	GError    *error = NULL;
+	char      *program;
+
+	screen = gtk_window_get_screen (GTK_WINDOW (dialog));
+
+	close_popup (dialog);
+
+	if (!(program = g_find_program_in_path ("gnome-app-manager")))
+		return;
+
+	egg_screen_execute_command_line_async (screen, program, &error);
+	if (error) {
+		/* FIXME:
+		 *   should have an error dialog here.
+		 */
+		g_warning ("Could not launch %s: %s\n", program, error->message);
+		g_error_free (error);
+	}
+
+	g_free (program);
+}
+
+static void
+handle_kill_application (GtkWidget *dialog)
+{
+	GdkScreen *screen;
+
+	screen = gtk_window_get_screen (GTK_WINDOW (dialog));
+
+	close_popup (dialog);
+
+	panel_kill_application (screen);
+}
+
+static void
+append_large_button (GtkWidget  *box,
+		     const char *stockid,
+		     GCallback   callback,
+		     gpointer    user_data)
+{
+	GtkWidget    *button;
+	GtkWidget    *alignment;
+	GtkWidget    *vbox;
+	GtkWidget    *image;
+	GtkStockItem  stock_item;
+
+	button = gtk_button_new ();
+
+	alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
+	gtk_container_add (GTK_CONTAINER (button), alignment);
+
+	vbox = gtk_vbox_new (FALSE, 4);
+	gtk_container_add (GTK_CONTAINER (alignment), vbox);
+
+	image = gtk_image_new_from_stock (stockid, GTK_ICON_SIZE_DIALOG);
+	gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0);
+
+	if (gtk_stock_lookup (stockid, &stock_item)) {
+		GtkWidget *label;
+
+		label = gtk_label_new_with_mnemonic (stock_item.label);
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (button));
+
+		gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+	}
+
+	gtk_box_pack_start (GTK_BOX (box), button, TRUE, TRUE, 0);
+	gtk_widget_show_all (button);
+
+	g_signal_connect_swapped (button, "clicked", callback, user_data);
+}
+
+static GtkWidget *
+display_popup_window (GdkScreen *screen)
+{
+	GtkWidget *retval;
+	GtkWidget *hbox;
+	GtkWidget *frame;
+	int        screen_width, screen_height;
+	char      *tmp;
+
+	retval = gtk_window_new (GTK_WINDOW_POPUP);
+	gtk_window_set_screen (GTK_WINDOW (retval), screen);
+	gtk_window_stick (GTK_WINDOW (retval));
+	gtk_widget_add_events (retval, GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK);
+
+	frame = gtk_frame_new (NULL);
+	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
+	gtk_container_add (GTK_CONTAINER (retval), frame);
+	gtk_widget_show (frame);
+
+	hbox = gtk_hbox_new (TRUE, 8);
+	gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
+	gtk_container_add (GTK_CONTAINER (frame), hbox);
+	gtk_widget_show (hbox);
+
+	append_large_button (
+		hbox, PANEL_STOCK_LOCKSCREEN, G_CALLBACK (handle_lock_screen), retval);
+	append_large_button (
+		hbox, PANEL_STOCK_LOGOUT, G_CALLBACK (handle_logout), retval);
+
+	if ((tmp = g_find_program_in_path ("gnome-app-manager"))) {
+		append_large_button (
+			hbox, PANEL_STOCK_APP_MANAGER,
+			G_CALLBACK (handle_app_manager), retval);
+		g_free (tmp);
+	}
+	
+	append_large_button (
+		hbox, PANEL_STOCK_KILL, G_CALLBACK (handle_kill_application), retval);
+	append_large_button (
+		hbox, PANEL_STOCK_CANCEL, G_CALLBACK (close_popup), retval);
+
+	gtk_widget_realize (retval);
+
+	screen_width  = gdk_screen_get_width  (screen);
+	screen_height = gdk_screen_get_height (screen);
+
+	gtk_window_move (GTK_WINDOW (retval),
+			 (screen_width  - retval->allocation.width) / 2,
+			 (screen_height - retval->allocation.height) / 2);
+
+	gtk_window_present (GTK_WINDOW (retval));
+
+	return retval;
+}
+
+static GdkFilterReturn
+popup_filter (GdkXEvent *gdk_xevent,
+	      GdkEvent  *event,
+	      GtkWidget *popup)
+{
+        XEvent *xevent = (XEvent *) gdk_xevent;
+
+	if (xevent->type != KeyPress)
+		return GDK_FILTER_CONTINUE;
+
+	if (xevent->xkey.keycode != XKeysymToKeycode (gdk_display, XK_Escape))
+		return GDK_FILTER_CONTINUE;
+
+	close_popup (popup);
+
+	return GDK_FILTER_REMOVE;
+}
+
+void
+panel_ctrl_alt_delete (GdkScreen *screen)
+{
+	GdkGrabStatus  status;
+        GtkWidget     *popup;
+        GdkWindow     *root;
+
+	popup = display_popup_window (screen);
+
+	root = gdk_screen_get_root_window (screen);
+
+	gdk_window_add_filter (root, (GdkFilterFunc) popup_filter, popup);
+
+	status = gdk_keyboard_grab (root, FALSE, GDK_CURRENT_TIME);
+	if (status != GDK_GRAB_SUCCESS) {
+		g_warning ("Keyboard grab failed\n");
+		close_popup (popup);
+		return;
+	}
+
+        gdk_flush ();
+}
Index: panel-ctrl-alt-delete.h
===================================================================
RCS file: panel-ctrl-alt-delete.h
diff -N panel-ctrl-alt-delete.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ panel-ctrl-alt-delete.h	30 Jan 2003 00:25:13 -0000
@@ -0,0 +1,36 @@
+/*
+ * panel-ctrl-alt-delete.h:
+ *
+ * Copyright (C) 2002 Sun Microsystems, 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *	Mark McLoughlin <mark@skynet.ie>
+ */
+
+#ifndef __PANEL_CTRL_ALT_DELETE_H__
+#define __PANEL_CTRL_ALT_DELETE_H__
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+void panel_ctrl_alt_delete (GdkScreen *screen);
+
+G_END_DECLS
+
+#endif /* __PANEL_CTRL_ALT_DELETE_H__ */
Index: panel-global-config.schemas.in
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-global-config.schemas.in,v
retrieving revision 1.20
diff -u -p -r1.20 panel-global-config.schemas.in
--- panel-global-config.schemas.in	7 Dec 2002 21:18:46 -0000	1.20
+++ panel-global-config.schemas.in	30 Jan 2003 00:25:13 -0000
@@ -152,6 +152,18 @@ Panel Global Config Schema File -  work 
       </schema>
 
       <schema>
+        <key>/schemas/apps/panel/global/kill_application_key</key>
+        <applyto>/apps/panel/global/kill_application_key</applyto>
+        <owner>panel</owner>
+        <type>string</type>
+        <default>&lt;Ctrl&gt;&lt;Alt&gt;Delete</default>
+        <locale name="C">
+          <short>Kill an application</short>
+          <long></long>
+        </locale>
+      </schema>
+
+      <schema>
         <key>/schemas/apps/panel/global/drawer_autoclose</key>
         <applyto>/apps/panel/global/drawer_autoclose</applyto>
         <owner>panel</owner>
Index: panel-kill-application.c
===================================================================
RCS file: panel-kill-application.c
diff -N panel-kill-application.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ panel-kill-application.c	30 Jan 2003 00:25:13 -0000
@@ -0,0 +1,281 @@
+/*
+ * panel-kill-application.c:
+ *
+ * Copyright (C) 2002 Sun Microsystems, 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *	Mark McLoughlin <mark@skynet.ie>
+ */
+
+#include <config.h>
+
+#include "panel-kill-application.h"
+
+#include <libgnome/gnome-i18n.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+
+#include "panel-stock-icons.h"
+
+static GdkFilterReturn popup_filter (GdkXEvent *gdk_xevent,
+				     GdkEvent  *event,
+				     GtkWidget *popup);
+
+static Atom wm_state_atom = None;
+
+static GtkWidget *
+display_popup_window (GdkScreen *screen)
+{
+	GtkWidget *retval;
+	GtkWidget *vbox;
+	GtkWidget *image;
+	GtkWidget *frame;
+	GtkWidget *label;
+	int        screen_width, screen_height;
+
+	retval = gtk_window_new (GTK_WINDOW_POPUP);
+	gtk_window_set_screen (GTK_WINDOW (retval), screen);
+	gtk_window_stick (GTK_WINDOW (retval));
+	gtk_widget_add_events (retval, GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK);
+
+	frame = gtk_frame_new (NULL);
+	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
+	gtk_container_add (GTK_CONTAINER (retval), frame);
+	gtk_widget_show (frame);
+
+	vbox = gtk_vbox_new (FALSE, 0);
+	gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
+	gtk_container_add (GTK_CONTAINER (frame), vbox);
+	gtk_widget_show (vbox);
+
+	image = gtk_image_new_from_stock (PANEL_STOCK_KILL, GTK_ICON_SIZE_DIALOG);
+	gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.5);
+	gtk_box_pack_start (GTK_BOX (vbox), image, TRUE, TRUE, 4);
+	gtk_widget_show (image);
+
+	label = gtk_label_new (_("Click on a window to kill the application. "
+				 "To cancel press <ESC>."));
+	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+	gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
+	gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4);
+	gtk_widget_show (label);
+
+	gtk_widget_realize (retval);
+
+	screen_width  = gdk_screen_get_width  (screen);
+	screen_height = gdk_screen_get_height (screen);
+
+	gtk_window_move (GTK_WINDOW (retval),
+			 (screen_width  - retval->allocation.width) / 2,
+			 (screen_height - retval->allocation.height) / 2);
+
+	gtk_widget_show (GTK_WIDGET (retval));
+
+	return retval;
+}
+
+static void
+remove_popup (GtkWidget *popup)
+{
+	GdkWindow *root;
+
+	root = gdk_screen_get_root_window (
+			gtk_window_get_screen (GTK_WINDOW (popup)));
+	gdk_window_remove_filter (root, (GdkFilterFunc) popup_filter, popup);
+
+	gtk_widget_destroy (popup);
+	gdk_pointer_ungrab (GDK_CURRENT_TIME);
+	gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+}
+
+static gboolean
+wm_state_set (Window window)
+{
+	gulong  nitems;
+	gulong  bytes_after;
+	gulong *prop;
+	Atom    ret_type = None;
+	int     ret_format;
+	int     result;
+
+	gdk_error_trap_push ();
+	result = XGetWindowProperty (gdk_display, window, wm_state_atom,
+				     0, G_MAXLONG, False, wm_state_atom,
+				     &ret_type, &ret_format, &nitems,
+				     &bytes_after, (guchar **) &prop);
+
+	if (gdk_error_trap_pop ())
+		return FALSE;
+
+	if (result != Success)
+		return FALSE;
+
+	XFree (prop);
+
+	if (ret_type != wm_state_atom)
+		return FALSE;
+
+	return TRUE;
+}
+
+static Window 
+find_managed_window (Window window)
+{
+	Window  root;
+	Window  parent;
+	Window *kids = NULL;
+	Window  retval;
+	int     nkids, i;
+	int     result;
+
+	if (wm_state_set (window))
+		return window;
+
+	gdk_error_trap_push ();
+	result = XQueryTree (gdk_display, window, &root, &parent, &kids, &nkids);
+	if (gdk_error_trap_pop () || !result)
+		return None;
+
+	retval = None;
+
+	for (i = 0; i < nkids; i++) {
+		if (wm_state_set (kids [i])) {
+			retval = kids [i];
+			break;
+		}
+
+		retval = find_managed_window (kids [i]);
+		if (retval != None)
+			break;
+	}
+
+	if (kids)
+		XFree (kids);
+
+	return retval;
+}
+
+/* From metacity */
+static gboolean
+kill_window_question (void)
+{
+	GtkWidget *dialog;
+	gboolean   retval;
+ 
+	dialog = gtk_message_dialog_new (NULL, 0,
+					 GTK_MESSAGE_QUESTION,
+					 GTK_BUTTONS_NONE,
+					 _("Force this application to exit?\n"
+					   "(Any open documents will be lost.)"));
+ 
+	gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+				GTK_STOCK_CANCEL,
+				GTK_RESPONSE_REJECT,
+				PANEL_STOCK_KILL,
+				GTK_RESPONSE_ACCEPT,
+				NULL);
+ 
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT);
+
+	retval = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT;
+
+	gtk_widget_destroy (dialog);
+
+	return retval;
+}
+
+static void 
+handle_button_press_event (GtkWidget *popup,
+			   XKeyEvent *event)
+{
+	Window window;
+
+	remove_popup (popup);
+
+	if (event->subwindow == None)
+		return;
+
+	if (wm_state_atom == None)
+		wm_state_atom = XInternAtom (gdk_display, "WM_STATE", FALSE);
+
+	window = find_managed_window (event->subwindow);
+
+	if (window != None && kill_window_question ())
+		XKillClient (gdk_display, window);
+}
+
+static GdkFilterReturn
+popup_filter (GdkXEvent *gdk_xevent,
+	      GdkEvent  *event,
+	      GtkWidget *popup)
+{
+	XEvent *xevent = (XEvent *) gdk_xevent;
+
+	switch (xevent->type) {
+	case ButtonPress:
+		handle_button_press_event (popup, &xevent->xkey);
+		return GDK_FILTER_REMOVE;
+	case KeyPress:
+		if (xevent->xkey.keycode == XKeysymToKeycode (gdk_display, XK_Escape)) {
+			remove_popup (popup);
+			return GDK_FILTER_REMOVE;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return GDK_FILTER_CONTINUE;
+}
+
+
+void
+panel_kill_application (GdkScreen *screen)
+{
+	GdkGrabStatus  status;
+	GdkCursor     *cross;
+	GtkWidget     *popup;
+	GdkWindow     *root;
+
+	popup = display_popup_window (screen);
+
+	root = gdk_screen_get_root_window (screen);
+
+	gdk_window_add_filter (root, (GdkFilterFunc) popup_filter, popup);
+
+	cross = gdk_cursor_new (GDK_CROSS);
+	status = gdk_pointer_grab (root, FALSE, GDK_BUTTON_PRESS_MASK,
+				   NULL, cross, GDK_CURRENT_TIME);
+	gdk_cursor_unref (cross);
+	if (status != GDK_GRAB_SUCCESS) {
+		g_warning ("Pointer grab failed\n");
+		remove_popup (popup);
+		return;
+	}
+
+	status = gdk_keyboard_grab (root, FALSE, GDK_CURRENT_TIME);
+	if (status != GDK_GRAB_SUCCESS) {
+		g_warning ("Keyboard grab failed\n");
+		remove_popup (popup);
+		return;
+	}
+
+	gdk_flush ();
+}
Index: panel-kill-application.h
===================================================================
RCS file: panel-kill-application.h
diff -N panel-kill-application.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ panel-kill-application.h	30 Jan 2003 00:25:13 -0000
@@ -0,0 +1,36 @@
+/*
+ * panel-kill-application.h:
+ *
+ * Copyright (C) 2002 Sun Microsystems, 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *	Mark McLoughlin <mark@skynet.ie>
+ */
+
+#ifndef __PANEL_KILL_APPLICATION_H__
+#define __PANEL_KILL_APPLICATION_H__
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+void panel_kill_application (GdkScreen *screen);
+
+G_END_DECLS
+
+#endif /* __PANEL_KILL_APPLICATION_H__ */
Index: panel-stock-icons.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-stock-icons.c,v
retrieving revision 1.6
diff -u -p -r1.6 panel-stock-icons.c
--- panel-stock-icons.c	12 Jan 2003 04:08:47 -0000	1.6
+++ panel-stock-icons.c	30 Jan 2003 00:25:15 -0000
@@ -66,6 +66,8 @@ static PanelStockIcon stock_icons [] = {
 	{ PANEL_STOCK_SCREENSHOT,          "gnome-screenshot" },
 	{ PANEL_STOCK_LOCKSCREEN,          "gnome-lockscreen" },
 	{ PANEL_STOCK_LOGOUT,              "gnome-term-night" },
+	{ PANEL_STOCK_KILL,                "gnome-kill-application1" },
+	{ PANEL_STOCK_APP_MANAGER,         "gnome-app-manager" },
 	{ PANEL_STOCK_GNOME_LOGO,          "gnome-logo-icon-transparent"},
 	{ PANEL_STOCK_DEBIAN,              "gnome-debian"},
 	{ PANEL_STOCK_SUSE,                "gnome-suse"},
@@ -139,7 +141,12 @@ typedef struct {
 } PanelStockItem;
 
 static PanelStockItem stock_items [] = {
-	{ PANEL_STOCK_EXECUTE, GTK_STOCK_EXECUTE, N_("_Run") },
+	{ PANEL_STOCK_EXECUTE,     GTK_STOCK_EXECUTE,        N_("_Run") },
+	{ PANEL_STOCK_KILL,        PANEL_STOCK_KILL,         N_("_Kill application") },
+	{ PANEL_STOCK_LOGOUT,      PANEL_STOCK_LOGOUT,       N_("Log _out") },
+	{ PANEL_STOCK_LOCKSCREEN,  PANEL_STOCK_LOCKSCREEN,   N_("_Lock screen") },
+	{ PANEL_STOCK_APP_MANAGER, PANEL_STOCK_APP_MANAGER,  N_("_Start Application Manager") },
+	{ PANEL_STOCK_CANCEL,      GTK_STOCK_DIALOG_WARNING, N_("_Cancel") },
 };
 
 static void
@@ -185,8 +192,8 @@ panel_init_stock_icons_and_items (void)
 	factory = gtk_icon_factory_new ();
 	gtk_icon_factory_add_default (factory);
 
-	panel_init_stock_items (factory);
 	panel_init_stock_icons (factory);
+	panel_init_stock_items (factory);
 
 	g_object_unref (factory);
 }
Index: panel-stock-icons.h
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-stock-icons.h,v
retrieving revision 1.6
diff -u -p -r1.6 panel-stock-icons.h
--- panel-stock-icons.h	12 Jan 2003 04:08:47 -0000	1.6
+++ panel-stock-icons.h	30 Jan 2003 00:25:15 -0000
@@ -40,6 +40,9 @@ G_BEGIN_DECLS
 #define PANEL_STOCK_SCREENSHOT          "panel-screenshot"
 #define PANEL_STOCK_LOCKSCREEN          "panel-lockscreen"
 #define PANEL_STOCK_LOGOUT              "panel-logout"
+#define PANEL_STOCK_KILL                "panel-kill"
+#define PANEL_STOCK_APP_MANAGER         "panel-app-manager"
+#define PANEL_STOCK_CANCEL              "panel-cancel"
 #define PANEL_STOCK_GNOME_LOGO          "panel-gnome-logo"
 #define PANEL_STOCK_DEBIAN              "panel-debian"
 #define PANEL_STOCK_SUSE                "panel-suse"
