2010-11-12 12:18:58 +00:00
|
|
|
/* GDK - The GIMP Drawing Kit
|
2010-11-16 11:33:02 +00:00
|
|
|
* gdkdisplay-broadway.c
|
2010-11-12 12:18:58 +00:00
|
|
|
*
|
|
|
|
* Copyright 2001 Sun Microsystems Inc.
|
|
|
|
* Copyright (C) 2004 Nokia Corporation
|
|
|
|
*
|
|
|
|
* Erwann Chenede <erwann.chenede@sun.com>
|
|
|
|
*
|
|
|
|
* 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
|
2012-02-27 13:01:10 +00:00
|
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
2010-11-12 12:18:58 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "gdkdisplay-broadway.h"
|
|
|
|
|
|
|
|
#include "gdkdisplay.h"
|
|
|
|
#include "gdkeventsource.h"
|
2016-04-03 03:42:40 +00:00
|
|
|
#include "gdkmonitor-broadway.h"
|
2010-11-12 12:18:58 +00:00
|
|
|
#include "gdkinternals.h"
|
|
|
|
#include "gdkdeviceprivate.h"
|
2011-01-06 22:36:44 +00:00
|
|
|
#include "gdkdevicemanager-broadway.h"
|
2010-11-12 12:18:58 +00:00
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
#include <glib/gprintf.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
2013-07-01 12:51:03 +00:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2010-11-12 12:18:58 +00:00
|
|
|
#include <unistd.h>
|
2013-07-01 12:51:03 +00:00
|
|
|
#endif
|
2011-04-18 17:52:05 +00:00
|
|
|
#include <sys/types.h>
|
2010-11-12 12:18:58 +00:00
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static void gdk_broadway_display_dispose (GObject *object);
|
|
|
|
static void gdk_broadway_display_finalize (GObject *object);
|
2010-11-12 12:18:58 +00:00
|
|
|
|
2011-11-10 09:12:28 +00:00
|
|
|
#if 0
|
|
|
|
#define DEBUG_WEBSOCKETS 1
|
|
|
|
#endif
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
G_DEFINE_TYPE (GdkBroadwayDisplay, gdk_broadway_display, GDK_TYPE_DISPLAY)
|
2010-11-12 12:18:58 +00:00
|
|
|
|
|
|
|
static void
|
2011-01-06 22:36:44 +00:00
|
|
|
gdk_broadway_display_init (GdkBroadwayDisplay *display)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2010-11-20 21:38:34 +00:00
|
|
|
display->id_ht = g_hash_table_new (NULL, NULL);
|
2016-04-03 03:42:40 +00:00
|
|
|
|
|
|
|
display->monitor = g_object_new (GDK_TYPE_BROADWAY_MONITOR,
|
|
|
|
"display", display,
|
|
|
|
NULL);
|
|
|
|
gdk_monitor_set_manufacturer (display->monitor, "browser");
|
|
|
|
gdk_monitor_set_model (display->monitor, "0");
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-01-06 22:36:44 +00:00
|
|
|
gdk_event_init (GdkDisplay *display)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2011-01-06 22:36:44 +00:00
|
|
|
GdkBroadwayDisplay *broadway_display;
|
2010-11-12 12:18:58 +00:00
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
broadway_display = GDK_BROADWAY_DISPLAY (display);
|
|
|
|
broadway_display->event_source = _gdk_broadway_event_source_new (display);
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
2017-11-01 18:46:26 +00:00
|
|
|
void
|
|
|
|
_gdk_broadway_display_size_changed (GdkDisplay *display,
|
|
|
|
BroadwayInputScreenResizeNotify *msg)
|
|
|
|
{
|
|
|
|
GdkBroadwayDisplay *broadway_display = GDK_BROADWAY_DISPLAY (display);
|
|
|
|
GdkMonitor *monitor;
|
|
|
|
GdkRectangle size;
|
|
|
|
GList *toplevels, *l;
|
|
|
|
|
|
|
|
monitor = broadway_display->monitor;
|
|
|
|
gdk_monitor_get_geometry (monitor, &size);
|
|
|
|
|
|
|
|
if (msg->width == size.width && msg->height == size.height)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gdk_monitor_set_size (monitor, msg->width, msg->height);
|
|
|
|
gdk_monitor_set_physical_size (monitor, msg->width * 25.4 / 96, msg->height * 25.4 / 96);
|
|
|
|
|
2017-11-05 23:19:04 +00:00
|
|
|
toplevels = broadway_display->toplevels;
|
2017-11-01 18:46:26 +00:00
|
|
|
for (l = toplevels; l != NULL; l = l->next)
|
|
|
|
{
|
|
|
|
GdkWindow *toplevel = l->data;
|
|
|
|
GdkWindowImplBroadway *toplevel_impl = GDK_WINDOW_IMPL_BROADWAY (toplevel->impl);
|
|
|
|
|
|
|
|
if (toplevel_impl->maximized)
|
|
|
|
gdk_window_move_resize (toplevel, 0, 0, msg->width, msg->height);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_list_free (toplevels);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-12 12:18:58 +00:00
|
|
|
GdkDisplay *
|
2011-01-06 22:36:44 +00:00
|
|
|
_gdk_broadway_display_open (const gchar *display_name)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
|
|
|
GdkDisplay *display;
|
2011-01-06 22:36:44 +00:00
|
|
|
GdkBroadwayDisplay *broadway_display;
|
2014-03-02 16:59:34 +00:00
|
|
|
GError *error = NULL;
|
2010-11-16 21:11:53 +00:00
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
display = g_object_new (GDK_TYPE_BROADWAY_DISPLAY, NULL);
|
|
|
|
broadway_display = GDK_BROADWAY_DISPLAY (display);
|
2010-11-12 12:18:58 +00:00
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
display->device_manager = _gdk_broadway_device_manager_new (display);
|
2010-11-12 12:18:58 +00:00
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
gdk_event_init (display);
|
2010-11-12 12:18:58 +00:00
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
_gdk_broadway_display_init_dnd (display);
|
2010-11-12 12:18:58 +00:00
|
|
|
|
2011-03-14 14:58:55 +00:00
|
|
|
if (display_name == NULL)
|
|
|
|
display_name = g_getenv ("BROADWAY_DISPLAY");
|
|
|
|
|
2014-03-02 16:59:34 +00:00
|
|
|
broadway_display->server = _gdk_broadway_server_new (display_name, &error);
|
2012-12-19 11:37:02 +00:00
|
|
|
if (broadway_display->server == NULL)
|
2010-11-18 12:17:23 +00:00
|
|
|
{
|
2014-03-02 16:59:34 +00:00
|
|
|
g_printerr ("Unable to init server: %s\n", error->message);
|
|
|
|
g_error_free (error);
|
2010-11-18 12:17:23 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-11-12 12:18:58 +00:00
|
|
|
g_signal_emit_by_name (display, "opened");
|
|
|
|
|
|
|
|
return display;
|
|
|
|
}
|
|
|
|
|
2011-06-06 18:05:18 +00:00
|
|
|
static const gchar *
|
2011-01-06 22:36:44 +00:00
|
|
|
gdk_broadway_display_get_name (GdkDisplay *display)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
|
|
|
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
|
2010-11-15 19:08:18 +00:00
|
|
|
|
|
|
|
return (gchar *) "Broadway";
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static void
|
|
|
|
gdk_broadway_display_beep (GdkDisplay *display)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2011-01-06 22:36:44 +00:00
|
|
|
g_return_if_fail (GDK_IS_DISPLAY (display));
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static void
|
|
|
|
gdk_broadway_display_sync (GdkDisplay *display)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2012-12-19 11:37:02 +00:00
|
|
|
GdkBroadwayDisplay *broadway_display = GDK_BROADWAY_DISPLAY (display);
|
2011-01-06 22:36:44 +00:00
|
|
|
|
2012-12-19 11:37:02 +00:00
|
|
|
g_return_if_fail (GDK_IS_BROADWAY_DISPLAY (display));
|
|
|
|
|
|
|
|
_gdk_broadway_server_sync (broadway_display->server);
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static void
|
|
|
|
gdk_broadway_display_flush (GdkDisplay *display)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2011-03-11 13:37:39 +00:00
|
|
|
GdkBroadwayDisplay *broadway_display = GDK_BROADWAY_DISPLAY (display);
|
|
|
|
|
2012-12-19 11:37:02 +00:00
|
|
|
g_return_if_fail (GDK_IS_BROADWAY_DISPLAY (display));
|
2010-11-15 19:08:18 +00:00
|
|
|
|
2012-12-19 11:37:02 +00:00
|
|
|
_gdk_broadway_server_flush (broadway_display->server);
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static gboolean
|
|
|
|
gdk_broadway_display_has_pending (GdkDisplay *display)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2011-01-06 22:36:44 +00:00
|
|
|
return FALSE;
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static GdkWindow *
|
|
|
|
gdk_broadway_display_get_default_group (GdkDisplay *display)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
|
|
|
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
|
|
|
|
|
2010-11-15 19:08:18 +00:00
|
|
|
return NULL;
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-01-06 22:36:44 +00:00
|
|
|
gdk_broadway_display_dispose (GObject *object)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2011-01-06 22:36:44 +00:00
|
|
|
GdkBroadwayDisplay *broadway_display = GDK_BROADWAY_DISPLAY (object);
|
2010-11-12 12:18:58 +00:00
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
if (broadway_display->event_source)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2011-01-06 22:36:44 +00:00
|
|
|
g_source_destroy (broadway_display->event_source);
|
|
|
|
g_source_unref (broadway_display->event_source);
|
|
|
|
broadway_display->event_source = NULL;
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
G_OBJECT_CLASS (gdk_broadway_display_parent_class)->dispose (object);
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-01-06 22:36:44 +00:00
|
|
|
gdk_broadway_display_finalize (GObject *object)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2011-01-06 22:36:44 +00:00
|
|
|
GdkBroadwayDisplay *broadway_display = GDK_BROADWAY_DISPLAY (object);
|
2010-11-12 12:18:58 +00:00
|
|
|
|
|
|
|
/* Keymap */
|
2011-01-06 22:36:44 +00:00
|
|
|
if (broadway_display->keymap)
|
|
|
|
g_object_unref (broadway_display->keymap);
|
2010-11-12 12:18:58 +00:00
|
|
|
|
2016-10-25 20:01:50 +00:00
|
|
|
_gdk_broadway_cursor_display_finalize (GDK_DISPLAY(broadway_display));
|
2010-11-12 12:18:58 +00:00
|
|
|
|
2016-04-03 03:42:40 +00:00
|
|
|
g_object_unref (broadway_display->monitor);
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
G_OBJECT_CLASS (gdk_broadway_display_parent_class)->finalize (object);
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static void
|
|
|
|
gdk_broadway_display_notify_startup_complete (GdkDisplay *display,
|
|
|
|
const gchar *startup_id)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static gboolean
|
|
|
|
gdk_broadway_display_supports_selection_notification (GdkDisplay *display)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2010-11-15 19:08:18 +00:00
|
|
|
return FALSE;
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static gboolean
|
|
|
|
gdk_broadway_display_request_selection_notification (GdkDisplay *display,
|
|
|
|
GdkAtom selection)
|
2010-11-12 12:18:58 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static gboolean
|
|
|
|
gdk_broadway_display_supports_clipboard_persistence (GdkDisplay *display)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2010-11-15 19:08:18 +00:00
|
|
|
return FALSE;
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static void
|
|
|
|
gdk_broadway_display_store_clipboard (GdkDisplay *display,
|
|
|
|
GdkWindow *clipboard_window,
|
|
|
|
guint32 time_,
|
|
|
|
const GdkAtom *targets,
|
|
|
|
gint n_targets)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static gboolean
|
|
|
|
gdk_broadway_display_supports_shapes (GdkDisplay *display)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2010-11-15 19:08:18 +00:00
|
|
|
return FALSE;
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static gboolean
|
|
|
|
gdk_broadway_display_supports_input_shapes (GdkDisplay *display)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2010-11-15 19:08:18 +00:00
|
|
|
return FALSE;
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static gulong
|
|
|
|
gdk_broadway_display_get_next_serial (GdkDisplay *display)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2011-03-10 13:58:47 +00:00
|
|
|
GdkBroadwayDisplay *broadway_display;
|
|
|
|
broadway_display = GDK_BROADWAY_DISPLAY (display);
|
2010-11-12 12:18:58 +00:00
|
|
|
|
2012-12-19 11:37:02 +00:00
|
|
|
return _gdk_broadway_server_get_next_serial (broadway_display->server);
|
|
|
|
}
|
2011-01-06 22:36:44 +00:00
|
|
|
|
2013-11-13 11:20:07 +00:00
|
|
|
void
|
|
|
|
gdk_broadway_display_show_keyboard (GdkBroadwayDisplay *display)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GDK_IS_BROADWAY_DISPLAY (display));
|
|
|
|
|
|
|
|
_gdk_broadway_server_set_show_keyboard (display->server, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gdk_broadway_display_hide_keyboard (GdkBroadwayDisplay *display)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GDK_IS_BROADWAY_DISPLAY (display));
|
|
|
|
|
|
|
|
_gdk_broadway_server_set_show_keyboard (display->server, FALSE);
|
|
|
|
}
|
|
|
|
|
2016-04-03 03:42:40 +00:00
|
|
|
static int
|
|
|
|
gdk_broadway_display_get_n_monitors (GdkDisplay *display)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GdkMonitor *
|
|
|
|
gdk_broadway_display_get_monitor (GdkDisplay *display,
|
|
|
|
int monitor_num)
|
|
|
|
{
|
|
|
|
GdkBroadwayDisplay *broadway_display = GDK_BROADWAY_DISPLAY (display);
|
|
|
|
|
|
|
|
if (monitor_num == 0)
|
|
|
|
return broadway_display->monitor;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GdkMonitor *
|
|
|
|
gdk_broadway_display_get_primary_monitor (GdkDisplay *display)
|
|
|
|
{
|
|
|
|
GdkBroadwayDisplay *broadway_display = GDK_BROADWAY_DISPLAY (display);
|
|
|
|
|
|
|
|
return broadway_display->monitor;
|
|
|
|
}
|
|
|
|
|
2017-10-30 20:43:13 +00:00
|
|
|
static gboolean
|
|
|
|
gdk_broadway_display_get_setting (GdkDisplay *display,
|
|
|
|
const char *name,
|
|
|
|
GValue *value)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2011-01-06 22:36:44 +00:00
|
|
|
static void
|
|
|
|
gdk_broadway_display_class_init (GdkBroadwayDisplayClass * class)
|
2010-11-12 12:18:58 +00:00
|
|
|
{
|
2011-01-06 22:36:44 +00:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
|
|
GdkDisplayClass *display_class = GDK_DISPLAY_CLASS (class);
|
|
|
|
|
|
|
|
object_class->dispose = gdk_broadway_display_dispose;
|
|
|
|
object_class->finalize = gdk_broadway_display_finalize;
|
|
|
|
|
|
|
|
display_class->window_type = GDK_TYPE_BROADWAY_WINDOW;
|
|
|
|
|
|
|
|
display_class->get_name = gdk_broadway_display_get_name;
|
|
|
|
display_class->beep = gdk_broadway_display_beep;
|
|
|
|
display_class->sync = gdk_broadway_display_sync;
|
|
|
|
display_class->flush = gdk_broadway_display_flush;
|
|
|
|
display_class->has_pending = gdk_broadway_display_has_pending;
|
|
|
|
display_class->queue_events = _gdk_broadway_display_queue_events;
|
|
|
|
display_class->get_default_group = gdk_broadway_display_get_default_group;
|
|
|
|
display_class->supports_selection_notification = gdk_broadway_display_supports_selection_notification;
|
|
|
|
display_class->request_selection_notification = gdk_broadway_display_request_selection_notification;
|
|
|
|
display_class->supports_clipboard_persistence = gdk_broadway_display_supports_clipboard_persistence;
|
|
|
|
display_class->store_clipboard = gdk_broadway_display_store_clipboard;
|
|
|
|
display_class->supports_shapes = gdk_broadway_display_supports_shapes;
|
|
|
|
display_class->supports_input_shapes = gdk_broadway_display_supports_input_shapes;
|
|
|
|
display_class->get_default_cursor_size = _gdk_broadway_display_get_default_cursor_size;
|
|
|
|
display_class->get_maximal_cursor_size = _gdk_broadway_display_get_maximal_cursor_size;
|
|
|
|
display_class->supports_cursor_alpha = _gdk_broadway_display_supports_cursor_alpha;
|
|
|
|
display_class->supports_cursor_color = _gdk_broadway_display_supports_cursor_color;
|
|
|
|
|
|
|
|
display_class->get_next_serial = gdk_broadway_display_get_next_serial;
|
|
|
|
display_class->notify_startup_complete = gdk_broadway_display_notify_startup_complete;
|
|
|
|
display_class->create_window_impl = _gdk_broadway_display_create_window_impl;
|
|
|
|
display_class->get_keymap = _gdk_broadway_display_get_keymap;
|
|
|
|
display_class->get_selection_owner = _gdk_broadway_display_get_selection_owner;
|
|
|
|
display_class->set_selection_owner = _gdk_broadway_display_set_selection_owner;
|
|
|
|
display_class->send_selection_notify = _gdk_broadway_display_send_selection_notify;
|
|
|
|
display_class->get_selection_property = _gdk_broadway_display_get_selection_property;
|
|
|
|
display_class->convert_selection = _gdk_broadway_display_convert_selection;
|
|
|
|
display_class->text_property_to_utf8_list = _gdk_broadway_display_text_property_to_utf8_list;
|
|
|
|
display_class->utf8_to_string_target = _gdk_broadway_display_utf8_to_string_target;
|
2016-04-03 03:42:40 +00:00
|
|
|
|
|
|
|
display_class->get_n_monitors = gdk_broadway_display_get_n_monitors;
|
|
|
|
display_class->get_monitor = gdk_broadway_display_get_monitor;
|
|
|
|
display_class->get_primary_monitor = gdk_broadway_display_get_primary_monitor;
|
2017-10-30 20:43:13 +00:00
|
|
|
display_class->get_setting = gdk_broadway_display_get_setting;
|
2010-11-12 12:18:58 +00:00
|
|
|
}
|