Skip to content
Snippets Groups Projects
Commit c4d7ec99 authored by dkirov's avatar dkirov
Browse files

added eggtrayicon from mail-notification.

This should make tray icon transparent for non-
gnome desktops.
parent 956ae9c3
No related branches found
No related tags found
No related merge requests found
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* eggtrayicon.c /* eggtrayicon.c
* Copyright (C) 2002 Anders Carlsson <andersca@gnu.org> * Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
* *
...@@ -18,25 +17,30 @@ ...@@ -18,25 +17,30 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
//#include <config.h>
#include <string.h> #include <string.h>
#include <glib/gi18n.h>
#include <libintl.h> #include <libintl.h>
#include "eggtrayicon.h" #include "eggtrayicon.h"
#include <gdkconfig.h>
#if defined (GDK_WINDOWING_X11)
#include <gdk/gdkx.h> #include <gdk/gdkx.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#elif defined (GDK_WINDOWING_WIN32)
#include <gdk/gdkwin32.h>
#endif
/*#ifndef EGG_COMPILATION #ifndef EGG_COMPILATION
#ifndef _ #ifndef _
#define _(x) dgettext ('gajim', x) #define _(x) dgettext (GETTEXT_PACKAGE, x)
#define N_(x) x #define N_(x) x
#endif #endif
#else #else
#define _(x) x #define _(x) x
#define N_(x) x #define N_(x) x
#endif #endif
*/
#define SYSTEM_TRAY_REQUEST_DOCK 0 #define SYSTEM_TRAY_REQUEST_DOCK 0
#define SYSTEM_TRAY_BEGIN_MESSAGE 1 #define SYSTEM_TRAY_BEGIN_MESSAGE 1
#define SYSTEM_TRAY_CANCEL_MESSAGE 2 #define SYSTEM_TRAY_CANCEL_MESSAGE 2
...@@ -48,7 +52,7 @@ enum { ...@@ -48,7 +52,7 @@ enum {
PROP_0, PROP_0,
PROP_ORIENTATION PROP_ORIENTATION
}; };
static GtkPlugClass *parent_class = NULL; static GtkPlugClass *parent_class = NULL;
static void egg_tray_icon_init (EggTrayIcon *icon); static void egg_tray_icon_init (EggTrayIcon *icon);
...@@ -59,10 +63,16 @@ static void egg_tray_icon_get_property (GObject *object, ...@@ -59,10 +63,16 @@ static void egg_tray_icon_get_property (GObject *object,
GValue *value, GValue *value,
GParamSpec *pspec); GParamSpec *pspec);
static void egg_tray_icon_add (GtkContainer *container, GtkWidget *widget);
static void egg_tray_icon_realize (GtkWidget *widget); static void egg_tray_icon_realize (GtkWidget *widget);
static void egg_tray_icon_unrealize (GtkWidget *widget); static void egg_tray_icon_unrealize (GtkWidget *widget);
static void egg_tray_icon_update_manager_window (EggTrayIcon *icon); #ifdef GDK_WINDOWING_X11
static void egg_tray_icon_update_manager_window (EggTrayIcon *icon,
gboolean dock_if_realized);
static void egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon);
#endif
GType GType
egg_tray_icon_get_type (void) egg_tray_icon_get_type (void)
...@@ -95,7 +105,7 @@ egg_tray_icon_init (EggTrayIcon *icon) ...@@ -95,7 +105,7 @@ egg_tray_icon_init (EggTrayIcon *icon)
{ {
icon->stamp = 1; icon->stamp = 1;
icon->orientation = GTK_ORIENTATION_HORIZONTAL; icon->orientation = GTK_ORIENTATION_HORIZONTAL;
gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK); gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK);
} }
...@@ -104,6 +114,7 @@ egg_tray_icon_class_init (EggTrayIconClass *klass) ...@@ -104,6 +114,7 @@ egg_tray_icon_class_init (EggTrayIconClass *klass)
{ {
GObjectClass *gobject_class = (GObjectClass *)klass; GObjectClass *gobject_class = (GObjectClass *)klass;
GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
GtkContainerClass *container_class = (GtkContainerClass *)klass;
parent_class = g_type_class_peek_parent (klass); parent_class = g_type_class_peek_parent (klass);
...@@ -112,16 +123,24 @@ egg_tray_icon_class_init (EggTrayIconClass *klass) ...@@ -112,16 +123,24 @@ egg_tray_icon_class_init (EggTrayIconClass *klass)
widget_class->realize = egg_tray_icon_realize; widget_class->realize = egg_tray_icon_realize;
widget_class->unrealize = egg_tray_icon_unrealize; widget_class->unrealize = egg_tray_icon_unrealize;
container_class->add = egg_tray_icon_add;
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_ORIENTATION, PROP_ORIENTATION,
g_param_spec_enum ("orientation", g_param_spec_enum ("orientation",
"Orientation", _("Orientation"),
"The orientation of the tray.", _("The orientation of the tray."),
// _("Orientation"),
// _("The orientation of the tray."),
GTK_TYPE_ORIENTATION, GTK_TYPE_ORIENTATION,
GTK_ORIENTATION_HORIZONTAL, GTK_ORIENTATION_HORIZONTAL,
G_PARAM_READABLE)); G_PARAM_READABLE));
#if defined (GDK_WINDOWING_X11)
/* Nothing */
#elif defined (GDK_WINDOWING_WIN32)
g_warning ("Port eggtrayicon to Win32");
#else
g_warning ("Port eggtrayicon to this GTK+ backend");
#endif
} }
static void static void
...@@ -143,6 +162,8 @@ egg_tray_icon_get_property (GObject *object, ...@@ -143,6 +162,8 @@ egg_tray_icon_get_property (GObject *object,
} }
} }
#ifdef GDK_WINDOWING_X11
static void static void
egg_tray_icon_get_orientation_property (EggTrayIcon *icon) egg_tray_icon_get_orientation_property (EggTrayIcon *icon)
{ {
...@@ -158,7 +179,7 @@ egg_tray_icon_get_orientation_property (EggTrayIcon *icon) ...@@ -158,7 +179,7 @@ egg_tray_icon_get_orientation_property (EggTrayIcon *icon)
int error, result; int error, result;
g_assert (icon->manager_window != None); g_assert (icon->manager_window != None);
xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
gdk_error_trap_push (); gdk_error_trap_push ();
...@@ -205,7 +226,7 @@ egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_ ...@@ -205,7 +226,7 @@ egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_
xev->xclient.message_type == icon->manager_atom && xev->xclient.message_type == icon->manager_atom &&
xev->xclient.data.l[1] == icon->selection_atom) xev->xclient.data.l[1] == icon->selection_atom)
{ {
egg_tray_icon_update_manager_window (icon); egg_tray_icon_update_manager_window (icon, TRUE);
} }
else if (xev->xany.window == icon->manager_window) else if (xev->xany.window == icon->manager_window)
{ {
...@@ -216,16 +237,18 @@ egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_ ...@@ -216,16 +237,18 @@ egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_
} }
if (xev->xany.type == DestroyNotify) if (xev->xany.type == DestroyNotify)
{ {
egg_tray_icon_update_manager_window (icon); egg_tray_icon_manager_window_destroyed (icon);
} }
} }
return GDK_FILTER_CONTINUE; return GDK_FILTER_CONTINUE;
} }
#endif
static void static void
egg_tray_icon_unrealize (GtkWidget *widget) egg_tray_icon_unrealize (GtkWidget *widget)
{ {
#ifdef GDK_WINDOWING_X11
EggTrayIcon *icon = EGG_TRAY_ICON (widget); EggTrayIcon *icon = EGG_TRAY_ICON (widget);
GdkWindow *root_window; GdkWindow *root_window;
...@@ -245,8 +268,11 @@ egg_tray_icon_unrealize (GtkWidget *widget) ...@@ -245,8 +268,11 @@ egg_tray_icon_unrealize (GtkWidget *widget)
if (GTK_WIDGET_CLASS (parent_class)->unrealize) if (GTK_WIDGET_CLASS (parent_class)->unrealize)
(* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
#endif
} }
#ifdef GDK_WINDOWING_X11
static void static void
egg_tray_icon_send_manager_message (EggTrayIcon *icon, egg_tray_icon_send_manager_message (EggTrayIcon *icon,
long message, long message,
...@@ -257,7 +283,7 @@ egg_tray_icon_send_manager_message (EggTrayIcon *icon, ...@@ -257,7 +283,7 @@ egg_tray_icon_send_manager_message (EggTrayIcon *icon,
{ {
XClientMessageEvent ev; XClientMessageEvent ev;
Display *display; Display *display;
ev.type = ClientMessage; ev.type = ClientMessage;
ev.window = window; ev.window = window;
ev.message_type = icon->system_tray_opcode_atom; ev.message_type = icon->system_tray_opcode_atom;
...@@ -269,7 +295,7 @@ egg_tray_icon_send_manager_message (EggTrayIcon *icon, ...@@ -269,7 +295,7 @@ egg_tray_icon_send_manager_message (EggTrayIcon *icon,
ev.data.l[4] = data3; ev.data.l[4] = data3;
display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
gdk_error_trap_push (); gdk_error_trap_push ();
XSendEvent (display, XSendEvent (display,
icon->manager_window, False, NoEventMask, (XEvent *)&ev); icon->manager_window, False, NoEventMask, (XEvent *)&ev);
...@@ -288,24 +314,18 @@ egg_tray_icon_send_dock_request (EggTrayIcon *icon) ...@@ -288,24 +314,18 @@ egg_tray_icon_send_dock_request (EggTrayIcon *icon)
} }
static void static void
egg_tray_icon_update_manager_window (EggTrayIcon *icon) egg_tray_icon_update_manager_window (EggTrayIcon *icon,
gboolean dock_if_realized)
{ {
Display *xdisplay; Display *xdisplay;
xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
if (icon->manager_window != None) if (icon->manager_window != None)
{ return;
GdkWindow *gdkwin;
xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
icon->manager_window);
gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
}
XGrabServer (xdisplay); XGrabServer (xdisplay);
icon->manager_window = XGetSelectionOwner (xdisplay, icon->manager_window = XGetSelectionOwner (xdisplay,
icon->selection_atom); icon->selection_atom);
...@@ -315,26 +335,76 @@ egg_tray_icon_update_manager_window (EggTrayIcon *icon) ...@@ -315,26 +335,76 @@ egg_tray_icon_update_manager_window (EggTrayIcon *icon)
XUngrabServer (xdisplay); XUngrabServer (xdisplay);
XFlush (xdisplay); XFlush (xdisplay);
if (icon->manager_window != None) if (icon->manager_window != None)
{ {
GdkWindow *gdkwin; GdkWindow *gdkwin;
gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
icon->manager_window); icon->manager_window);
gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon); gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon);
/* Send a request that we'd like to dock */ if (dock_if_realized && GTK_WIDGET_REALIZED (icon))
egg_tray_icon_send_dock_request (icon); egg_tray_icon_send_dock_request (icon);
egg_tray_icon_get_orientation_property (icon); egg_tray_icon_get_orientation_property (icon);
} }
} }
static gboolean
transparent_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
{
gdk_window_clear_area (widget->window, event->area.x, event->area.y,
event->area.width, event->area.height);
return FALSE;
}
static void
make_transparent_again (GtkWidget *widget, GtkStyle *previous_style,
gpointer user_data)
{
gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
}
static void
make_transparent (GtkWidget *widget, gpointer user_data)
{
if (GTK_WIDGET_NO_WINDOW (widget) || GTK_WIDGET_APP_PAINTABLE (widget))
return;
gtk_widget_set_app_paintable (widget, TRUE);
gtk_widget_set_double_buffered (widget, FALSE);
gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
g_signal_connect (widget, "expose_event",
G_CALLBACK (transparent_expose_event), NULL);
g_signal_connect_after (widget, "style_set",
G_CALLBACK (make_transparent_again), NULL);
}
static void
egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon)
{
GdkWindow *gdkwin;
g_return_if_fail (icon->manager_window != None);
gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
icon->manager_window);
gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
icon->manager_window = None;
egg_tray_icon_update_manager_window (icon, TRUE);
}
#endif
static void static void
egg_tray_icon_realize (GtkWidget *widget) egg_tray_icon_realize (GtkWidget *widget)
{ {
#ifdef GDK_WINDOWING_X11
EggTrayIcon *icon = EGG_TRAY_ICON (widget); EggTrayIcon *icon = EGG_TRAY_ICON (widget);
GdkScreen *screen; GdkScreen *screen;
GdkDisplay *display; GdkDisplay *display;
...@@ -345,6 +415,8 @@ egg_tray_icon_realize (GtkWidget *widget) ...@@ -345,6 +415,8 @@ egg_tray_icon_realize (GtkWidget *widget)
if (GTK_WIDGET_CLASS (parent_class)->realize) if (GTK_WIDGET_CLASS (parent_class)->realize)
GTK_WIDGET_CLASS (parent_class)->realize (widget); GTK_WIDGET_CLASS (parent_class)->realize (widget);
make_transparent (widget, NULL);
screen = gtk_widget_get_screen (widget); screen = gtk_widget_get_screen (widget);
display = gdk_screen_get_display (screen); display = gdk_screen_get_display (screen);
xdisplay = gdk_x11_display_get_xdisplay (display); xdisplay = gdk_x11_display_get_xdisplay (display);
...@@ -355,9 +427,9 @@ egg_tray_icon_realize (GtkWidget *widget) ...@@ -355,9 +427,9 @@ egg_tray_icon_realize (GtkWidget *widget)
gdk_screen_get_number (screen)); gdk_screen_get_number (screen));
icon->selection_atom = XInternAtom (xdisplay, buffer, False); icon->selection_atom = XInternAtom (xdisplay, buffer, False);
icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False); icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False);
icon->system_tray_opcode_atom = XInternAtom (xdisplay, icon->system_tray_opcode_atom = XInternAtom (xdisplay,
"_NET_SYSTEM_TRAY_OPCODE", "_NET_SYSTEM_TRAY_OPCODE",
False); False);
...@@ -366,13 +438,23 @@ egg_tray_icon_realize (GtkWidget *widget) ...@@ -366,13 +438,23 @@ egg_tray_icon_realize (GtkWidget *widget)
"_NET_SYSTEM_TRAY_ORIENTATION", "_NET_SYSTEM_TRAY_ORIENTATION",
False); False);
egg_tray_icon_update_manager_window (icon); egg_tray_icon_update_manager_window (icon, FALSE);
egg_tray_icon_send_dock_request (icon);
root_window = gdk_screen_get_root_window (screen); root_window = gdk_screen_get_root_window (screen);
/* Add a root window filter so that we get changes on MANAGER */ /* Add a root window filter so that we get changes on MANAGER */
gdk_window_add_filter (root_window, gdk_window_add_filter (root_window,
egg_tray_icon_manager_filter, icon); egg_tray_icon_manager_filter, icon);
#endif
}
static void
egg_tray_icon_add (GtkContainer *container, GtkWidget *widget)
{
g_signal_connect (widget, "realize",
G_CALLBACK (make_transparent), NULL);
GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
} }
EggTrayIcon * EggTrayIcon *
...@@ -396,19 +478,22 @@ egg_tray_icon_send_message (EggTrayIcon *icon, ...@@ -396,19 +478,22 @@ egg_tray_icon_send_message (EggTrayIcon *icon,
gint len) gint len)
{ {
guint stamp; guint stamp;
g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0); g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0);
g_return_val_if_fail (timeout >= 0, 0); g_return_val_if_fail (timeout >= 0, 0);
g_return_val_if_fail (message != NULL, 0); g_return_val_if_fail (message != NULL, 0);
#ifdef GDK_WINDOWING_X11
if (icon->manager_window == None) if (icon->manager_window == None)
return 0; return 0;
#endif
if (len < 0) if (len < 0)
len = strlen (message); len = strlen (message);
stamp = icon->stamp++; stamp = icon->stamp++;
#ifdef GDK_WINDOWING_X11
/* Get ready to send the message */ /* Get ready to send the message */
egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE, egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE,
(Window)gtk_plug_get_id (GTK_PLUG (icon)), (Window)gtk_plug_get_id (GTK_PLUG (icon)),
...@@ -422,7 +507,7 @@ egg_tray_icon_send_message (EggTrayIcon *icon, ...@@ -422,7 +507,7 @@ egg_tray_icon_send_message (EggTrayIcon *icon,
Display *xdisplay; Display *xdisplay;
xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
ev.type = ClientMessage; ev.type = ClientMessage;
ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon)); ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon));
ev.format = 8; ev.format = 8;
...@@ -445,6 +530,7 @@ egg_tray_icon_send_message (EggTrayIcon *icon, ...@@ -445,6 +530,7 @@ egg_tray_icon_send_message (EggTrayIcon *icon,
XSync (xdisplay, False); XSync (xdisplay, False);
} }
gdk_error_trap_pop (); gdk_error_trap_pop ();
#endif
return stamp; return stamp;
} }
...@@ -455,10 +541,11 @@ egg_tray_icon_cancel_message (EggTrayIcon *icon, ...@@ -455,10 +541,11 @@ egg_tray_icon_cancel_message (EggTrayIcon *icon,
{ {
g_return_if_fail (EGG_IS_TRAY_ICON (icon)); g_return_if_fail (EGG_IS_TRAY_ICON (icon));
g_return_if_fail (id > 0); g_return_if_fail (id > 0);
#ifdef GDK_WINDOWING_X11
egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE, egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE,
(Window)gtk_plug_get_id (GTK_PLUG (icon)), (Window)gtk_plug_get_id (GTK_PLUG (icon)),
id, 0, 0); id, 0, 0);
#endif
} }
GtkOrientation GtkOrientation
......
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
#define __EGG_TRAY_ICON_H__ #define __EGG_TRAY_ICON_H__
#include <gtk/gtkplug.h> #include <gtk/gtkplug.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h> #include <gdk/gdkx.h>
#endif
G_BEGIN_DECLS G_BEGIN_DECLS
...@@ -32,7 +34,7 @@ G_BEGIN_DECLS ...@@ -32,7 +34,7 @@ G_BEGIN_DECLS
#define EGG_IS_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TRAY_ICON)) #define EGG_IS_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TRAY_ICON))
#define EGG_IS_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_TRAY_ICON)) #define EGG_IS_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_TRAY_ICON))
#define EGG_TRAY_ICON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_TRAY_ICON, EggTrayIconClass)) #define EGG_TRAY_ICON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_TRAY_ICON, EggTrayIconClass))
typedef struct _EggTrayIcon EggTrayIcon; typedef struct _EggTrayIcon EggTrayIcon;
typedef struct _EggTrayIconClass EggTrayIconClass; typedef struct _EggTrayIconClass EggTrayIconClass;
...@@ -41,13 +43,14 @@ struct _EggTrayIcon ...@@ -41,13 +43,14 @@ struct _EggTrayIcon
GtkPlug parent_instance; GtkPlug parent_instance;
guint stamp; guint stamp;
#ifdef GDK_WINDOWING_X11
Atom selection_atom; Atom selection_atom;
Atom manager_atom; Atom manager_atom;
Atom system_tray_opcode_atom; Atom system_tray_opcode_atom;
Atom orientation_atom; Atom orientation_atom;
Window manager_window; Window manager_window;
#endif
GtkOrientation orientation; GtkOrientation orientation;
}; };
...@@ -71,7 +74,7 @@ void egg_tray_icon_cancel_message (EggTrayIcon *icon, ...@@ -71,7 +74,7 @@ void egg_tray_icon_cancel_message (EggTrayIcon *icon,
guint id); guint id);
GtkOrientation egg_tray_icon_get_orientation (EggTrayIcon *icon); GtkOrientation egg_tray_icon_get_orientation (EggTrayIcon *icon);
G_END_DECLS G_END_DECLS
#endif /* __EGG_TRAY_ICON_H__ */ #endif /* __EGG_TRAY_ICON_H__ */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment