system-controller: added weston/wayland window management (no resource).
authorJanos Kovacs <jankovac503@gmail.com>
Mon, 18 Nov 2013 11:24:53 +0000 (13:24 +0200)
committerKrisztian Litkey <krisztian.litkey@intel.com>
Thu, 8 Jan 2015 16:37:11 +0000 (18:37 +0200)
Change-Id: Ic2590b502b316595da67262c6545cdff7bd18f79

39 files changed:
configure.ac
src/Makefile.am
src/plugins/system-controller/application/application.c [new file with mode: 0644]
src/plugins/system-controller/application/application.h [new file with mode: 0644]
src/plugins/system-controller/application/scripting-application.c [new file with mode: 0644]
src/plugins/system-controller/application/scripting-application.h [new file with mode: 0644]
src/plugins/system-controller/data-types.h [new file with mode: 0644]
src/plugins/system-controller/plugin-system-controller.c
src/plugins/system-controller/resource-manager/resource-manager.c [new file with mode: 0644]
src/plugins/system-controller/resource-manager/resource-manager.h [new file with mode: 0644]
src/plugins/system-controller/resource-manager/scripting-resource-manager.c [new file with mode: 0644]
src/plugins/system-controller/resource-manager/scripting-resource-manager.h [new file with mode: 0644]
src/plugins/system-controller/wayland/animation.c [new file with mode: 0644]
src/plugins/system-controller/wayland/animation.h [new file with mode: 0644]
src/plugins/system-controller/wayland/area.c [new file with mode: 0644]
src/plugins/system-controller/wayland/area.h [new file with mode: 0644]
src/plugins/system-controller/wayland/ico-input-manager.c [new file with mode: 0644]
src/plugins/system-controller/wayland/ico-input-manager.h [new file with mode: 0644]
src/plugins/system-controller/wayland/ico-window-manager.c [new file with mode: 0644]
src/plugins/system-controller/wayland/ico-window-manager.h [new file with mode: 0644]
src/plugins/system-controller/wayland/input-manager.h [new file with mode: 0644]
src/plugins/system-controller/wayland/layer.c [new file with mode: 0644]
src/plugins/system-controller/wayland/layer.h [new file with mode: 0644]
src/plugins/system-controller/wayland/output.c [new file with mode: 0644]
src/plugins/system-controller/wayland/output.h [new file with mode: 0644]
src/plugins/system-controller/wayland/scripting-animation.c [new file with mode: 0644]
src/plugins/system-controller/wayland/scripting-area.c [new file with mode: 0644]
src/plugins/system-controller/wayland/scripting-layer.c [new file with mode: 0644]
src/plugins/system-controller/wayland/scripting-output.c [new file with mode: 0644]
src/plugins/system-controller/wayland/scripting-wayland.c [new file with mode: 0644]
src/plugins/system-controller/wayland/scripting-wayland.h [new file with mode: 0644]
src/plugins/system-controller/wayland/scripting-window-manager.c [new file with mode: 0644]
src/plugins/system-controller/wayland/scripting-window.c [new file with mode: 0644]
src/plugins/system-controller/wayland/wayland.c [new file with mode: 0644]
src/plugins/system-controller/wayland/wayland.h [new file with mode: 0644]
src/plugins/system-controller/wayland/window-manager.h [new file with mode: 0644]
src/plugins/system-controller/wayland/window.c [new file with mode: 0644]
src/plugins/system-controller/wayland/window.h [new file with mode: 0644]
src/resource/data-types.h

index cadb449..dc87ba4 100644 (file)
@@ -486,6 +486,36 @@ AC_SUBST(TELEPHONY_ENABLED)
 AC_SUBST(TELEPHONY_CFLAGS)
 AC_SUBST(TELEPHONY_LIBS)
 
+# Check if system-controller (plugin) support should be enabled.
+AC_ARG_ENABLE(system-controller,
+              [  --enable-system-controller enable system-controller support],
+             [enable_systemctl=$enableval], [enable_systemctl=auto])
+
+if test "$enable_systemctl" != "no"; then
+    if test "$enable_systemctl" = "auto"; then
+        enable_systemctl="$enable_websockets"
+    else
+        if test "$enable_websockets" != "yes"; then
+            AC_MSG_ERROR([System controller requires websocket support.])
+        fi
+    fi
+else
+    AC_MSG_NOTICE([System controller support is disabled.])
+fi
+
+if test "$enable_systemctl" = "yes"; then
+    AC_MSG_NOTICE([System-controller support is enabled.])
+    AC_DEFINE([SYSTEMCTL_ENABLED], 1, [Enable system-controller support ?])
+    PKG_CHECK_MODULES(WAYLAND_CLIENT, wayland-client)
+else
+    AC_MSG_NOTICE([System-controller support is disabled.])
+fi
+
+AM_CONDITIONAL(SYSTEMCTL_ENABLED, [test "$enable_systemctl" = "yes"])
+AC_SUBST(SYSTEMCTL_ENABLED)
+AC_SUBST(WAYLAND_CLIENT_CFLAGS)
+AC_SUBST(WAYLAND_CLIENT_LIBS)
+
 # Check if dlog support was enabled.
 AC_ARG_ENABLE(dlog,
               [  --enable-dlog           enable dlog support],
@@ -543,6 +573,16 @@ fi
 AM_CONDITIONAL(RESOURCE_ASM_ENABLED, [test "$enable_resource_asm" = "yes"])
 AC_SUBST(RESOURCE_ASM_ENABLED)
 
+PKG_CHECK_MODULES(AIL, ail, [have_ail=yes], [have_ail=no])
+if test "$have_ail" = "no" ; then
+    AC_MSG_ERROR([AIL development headers not found.])
+fi
+AC_SUBST(AIL_CFLAGS)
+AC_SUBST(AIL_LIBS)
+
+enable_ail="$have_ail"
+
+
 # Set up murphy CFLAGS and LIBS.
 MURPHY_CFLAGS=""
 MURPHY_LIBS=""
@@ -818,6 +858,8 @@ echo "Resource management support: $with_resources"
 echo "Websockets support: $enable_websockets"
 echo "systemd support: $enable_systemd"
 echo "Telephony support: $enable_telephony"
+echo "System controller support: $enable_systemctl"
+echo "AIL support: $enable_ail"
 echo "Plugins:"
 echo "  - linked-in:"
 for plugin in ${INTERNAL_PLUGINS:-none}; do
index 91d17f0..15d4ed7 100644 (file)
@@ -1519,9 +1519,36 @@ endif
 
 # system-controller
 if SYSTEMCTL_ENABLED
-SYSTEMCTL_PLUGIN_SOURCES = plugins/system-controller/plugin-system-controller.c
-SYSTEMCTL_PLUGIN_CFLAGS  = $(WEBSOCKETS_CFLAGS)
-SYSTEMCTL_PLUGIN_LIBS    =
+SYSTEMCTL_DIR = plugins/system-controller
+SYSTEMCTL_PLUGIN_SOURCES =                                             \
+       $(SYSTEMCTL_DIR)/plugin-system-controller.c                    \
+       $(SYSTEMCTL_DIR)/resource-manager/resource-manager.c           \
+       $(SYSTEMCTL_DIR)/resource-manager/scripting-resource-manager.c \
+       $(SYSTEMCTL_DIR)/application/application.c                     \
+       $(SYSTEMCTL_DIR)/application/scripting-application.c           \
+       $(SYSTEMCTL_DIR)/wayland/wayland.c                             \
+       $(SYSTEMCTL_DIR)/wayland/output.c                              \
+       $(SYSTEMCTL_DIR)/wayland/layer.c                               \
+       $(SYSTEMCTL_DIR)/wayland/area.c                                \
+       $(SYSTEMCTL_DIR)/wayland/window.c                              \
+       $(SYSTEMCTL_DIR)/wayland/animation.c                           \
+       $(SYSTEMCTL_DIR)/wayland/ico-window-manager.c                  \
+       $(SYSTEMCTL_DIR)/wayland/ico-input-manager.c                   \
+       $(SYSTEMCTL_DIR)/wayland/scripting-wayland.c                   \
+       $(SYSTEMCTL_DIR)/wayland/scripting-window-manager.c            \
+       $(SYSTEMCTL_DIR)/wayland/scripting-animation.c                 \
+       $(SYSTEMCTL_DIR)/wayland/scripting-window.c                    \
+       $(SYSTEMCTL_DIR)/wayland/scripting-output.c                    \
+       $(SYSTEMCTL_DIR)/wayland/scripting-area.c                      \
+       $(SYSTEMCTL_DIR)/wayland/scripting-layer.c
+
+SYSTEMCTL_PLUGIN_CFLAGS  = \
+                       $(WEBSOCKETS_CFLAGS) $(WAYLAND_CLIENT_CFLAGS) \
+                       -Iico-uxf-weston-plugin \
+                        -I$(top_builddir)/src/$(SYSTEMCTL_DIR)
+SYSTEMCTL_PLUGIN_LIBS    = \
+                       $(WEBSOCKET_LIBS) $(WAYLAND_CLIENT_LIBS) \
+                       -lico-uxf-weston-plugin
 
 if !DISABLED_PLUGIN_SYSTEMCTL
 if BUILTIN_PLUGIN_SYSTEMCTL
diff --git a/src/plugins/system-controller/application/application.c b/src/plugins/system-controller/application/application.c
new file mode 100644 (file)
index 0000000..22ec565
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+                                     /* this includes application.h */
+#include "scripting-application.h"
+#include "wayland/area.h"
+
+static void init_applications(void);
+static mrp_wayland_area_t *area_find(const char *);
+
+mrp_htbl_t *applications;
+
+mrp_application_t *mrp_application_create(mrp_application_update_t *u,
+                                          void *scripting_data)
+{
+#define IF_PRESENT(u,n) (u->mask & MRP_WAYLAND_APP_ ## n ## _MASK)
+
+    mrp_application_update_mask_t mask;
+    mrp_application_t *app;
+    mrp_wayland_area_t *area;
+    mrp_wayland_t *wl;
+    char buf[4096];
+    void *it;
+
+    MRP_ASSERT(u && (u->mask & MRP_APPLICATION_APPID_MASK) && u->appid &&
+               (u->mask & MRP_APPLICATION_AREA_NAME_MASK) && u->area_name,
+               "invalid argument");
+
+    mask = u->mask;
+
+    if (!(app = mrp_allocz(sizeof(mrp_application_t)))) {
+        mrp_log_error("failed to create application '%s': out of memory",
+                      u->appid);
+        return NULL;
+    }
+
+    app->appid = mrp_strdup(u->appid);
+
+    if (!applications) {
+        init_applications();
+        MRP_ASSERT(applications, "failed to initialize "
+                   "hash table for applications");
+    }
+
+    if (!mrp_htbl_insert(applications, app->appid, app)) {
+        mrp_log_error("failed to create application '%s': "
+                      "already exists", app->appid);
+        mrp_free(app);
+        return NULL;
+    }
+
+    app->area_name = mrp_strdup(u->area_name);
+
+    if ((area = area_find(app->area_name))) {
+        mask |= MRP_APPLICATION_AREA_MASK;
+        app->area = area;
+    }
+
+    if ((mask & MRP_APPLICATION_SCREEN_PRIVILEGE_MASK))
+        app->privileges.screen = u->privileges.screen;
+    if ((mask & MRP_APPLICATION_AUDIO_PRIVILEGE_MASK))
+        app->privileges.audio = u->privileges.audio;
+
+    if (!scripting_data)
+        scripting_data = mrp_application_scripting_app_create_from_c(app);
+
+    app->scripting_data = scripting_data;
+
+    mrp_application_print(app, mask, buf,sizeof(buf));
+    mrp_debug("application '%s' created%s", app->appid, buf);
+
+    if (app->scripting_data) {
+        mrp_wayland_foreach(wl, it) {
+            if (wl->application_update_callback) {
+                wl->application_update_callback(wl, MRP_APPLICATION_CREATE,
+                                                mask, app);
+            }
+        }
+    }
+
+    return app;
+
+#undef IF_PRESENT
+}
+
+void mrp_application_destroy(mrp_application_t *app)
+{
+    mrp_wayland_t *wl;
+    void *it;
+
+    if (app && app->appid) {
+        mrp_debug("destroying application '%s'", app->appid);
+
+        mrp_wayland_foreach(wl, it) {
+            if (wl->application_update_callback) {
+                wl->application_update_callback(wl, MRP_APPLICATION_DESTROY,
+                                                0, app);
+            }
+        }
+
+        mrp_application_scripting_app_destroy_from_c(app);
+
+        if ((void *)app != mrp_htbl_remove(applications, app->appid, false)) {
+            mrp_log_error("failed to destroy application '%s': confused with "
+                          "data structures", app->appid);
+            return;
+        }
+
+        mrp_free(app->appid);
+
+        free(app);
+    }
+}
+
+
+mrp_application_t *mrp_application_find(const char *appid)
+{
+    if (!appid)
+        return NULL;
+
+    return (mrp_application_t *)mrp_htbl_lookup(applications, (void *)appid);
+}
+
+
+size_t mrp_application_print(mrp_application_t *app,
+                             mrp_application_update_mask_t mask,
+                             char *buf, size_t len)
+{
+#define PRINT(fmt, args...) \
+    do{ if (p < e) { p += snprintf(p,e-p, "\n      " fmt, ## args); } }while(0)
+
+    mrp_wayland_area_t *area;
+    char *p, *e;
+
+    e = (p = buf) + len;
+
+    *p = 0;
+
+    if ((mask & MRP_APPLICATION_AREA_NAME_MASK))
+        PRINT("area_name: '%s'", app->area_name);
+    if ((mask & MRP_APPLICATION_AREA_MASK)) {
+        if (!(area = app->area))
+            PRINT("area: -1 - <unknown>");
+        else
+            PRINT("area: %d - '%s'", area->areaid, area->name);
+    }
+    if ((mask & MRP_APPLICATION_PRIVILEGES_MASK)) {
+        PRINT("privileges: screen=%s audio=%s",
+              mrp_application_privilege_str(app->privileges.screen),
+              mrp_application_privilege_str(app->privileges.audio));
+    }
+
+    return p - buf;
+
+#undef PRINT
+}
+
+
+void mrp_application_set_scripting_data(mrp_application_t *app, void *data)
+{
+    MRP_ASSERT(app, "Invalid Argument");
+
+    mrp_debug("%sset scripting data", data ? "" : "re");
+
+    app->scripting_data = data;
+}
+
+int mrp_application_foreach(mrp_htbl_iter_cb_t cb, void *user_data)
+{
+    return mrp_htbl_foreach(applications, cb, user_data);
+}
+
+
+
+const char *mrp_application_privilege_str(mrp_application_privilege_t priv)
+{
+    switch (priv) {
+    case MRP_APPLICATION_PRIVILEGE_NONE:           return "none";
+    case MRP_APPLICATION_PRIVILEGE_CERTIFIED:      return "certified";
+    case MRP_APPLICATION_PRIVILEGE_MANUFACTURER:   return "manufacturer";
+    case MRP_APPLICATION_PRIVILEGE_SYSTEM:         return "system";
+    case MRP_APPLICATION_PRIVILEGE_UNLIMITED:      return "unlimited";
+    default:                                       return "<unknown>";
+    }
+}
+
+
+static void init_applications(void)
+{
+    mrp_htbl_config_t cfg;
+
+    memset(&cfg, 0, sizeof(cfg));
+    cfg.nentry = MRP_APPLICATION_MAX;
+    cfg.comp = mrp_string_comp;
+    cfg.hash = mrp_string_hash;
+    cfg.nbucket = MRP_APPLICATION_BUCKETS;
+
+    applications = mrp_htbl_create(&cfg);
+}
+
+static mrp_wayland_area_t *area_find(const char *fullname)
+{
+    mrp_wayland_t *wl;
+    mrp_wayland_area_t *area;
+    void *it;
+
+    mrp_wayland_foreach(wl, it) {
+        if ((area = mrp_wayland_area_find(wl, fullname)))
+            return area;
+    }
+
+    return NULL;
+}
diff --git a/src/plugins/system-controller/application/application.h b/src/plugins/system-controller/application/application.h
new file mode 100644 (file)
index 0000000..0c73ce6
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_APPLICATION_H__
+#define __MURPHY_APPLICATION_H__
+
+#include <sys/types.h>
+
+#include "data-types.h"
+
+#ifndef __MURPHY_WAYLAND_H__
+#error "do not include directly application.h; include wayland/wayland.h"
+#endif
+
+#define MRP_APPLICATION_MAX 500
+#define MRP_APPLICATION_BUCKETS (MRP_APPLICATION_MAX / 10)
+
+typedef enum mrp_application_operation_e      mrp_application_operation_t;
+typedef enum mrp_application_privilege_e      mrp_application_privilege_t;
+typedef enum mrp_application_update_mask_e    mrp_application_update_mask_t;
+
+typedef struct mrp_application_s              mrp_application_t;
+typedef struct mrp_application_update_s       mrp_application_update_t;
+typedef struct mrp_application_privileges_s   mrp_application_privileges_t;
+
+enum mrp_application_operation_e {
+    MRP_APPLICATION_OPERATION_NONE = 0,
+    MRP_APPLICATION_CREATE,
+    MRP_APPLICATION_DESTROY,
+};
+
+enum mrp_application_privilege_e {
+    MRP_APPLICATION_PRIVILEGE_NONE =           0,
+    MRP_APPLICATION_PRIVILEGE_CERTIFIED,    /* 1 */
+    MRP_APPLICATION_PRIVILEGE_MANUFACTURER, /* 2 */
+    MRP_APPLICATION_PRIVILEGE_SYSTEM,       /* 3 */
+    MRP_APPLICATION_PRIVILEGE_UNLIMITED,    /* 4 */
+
+    MRP_APPLICATION_PRIVILEGE_MAX           /* 5 */
+};
+
+struct mrp_application_privileges_s {
+    mrp_application_privilege_t screen;
+    mrp_application_privilege_t audio;
+};
+
+struct mrp_application_s {
+    char *appid;
+    char *area_name;
+
+    mrp_wayland_area_t *area;
+    mrp_application_privileges_t privileges;
+
+    void *scripting_data;
+};
+
+enum mrp_application_update_mask_e {
+    MRP_APPLICATION_APPID_MASK      = 0x01,
+    MRP_APPLICATION_AREA_NAME_MASK  = 0x02,
+    MRP_APPLICATION_AREA_MASK       = 0x04,
+    MRP_APPLICATION_SCREEN_PRIVILEGE_MASK = 0x08,
+    MRP_APPLICATION_AUDIO_PRIVILEGE_MASK  = 0x10,
+    MRP_APPLICATION_PRIVILEGES_MASK = 0x18,
+
+    MRP_APPLICATION_END_MASK        = 0x20
+};
+
+struct mrp_application_update_s {
+    mrp_application_update_mask_t mask;    
+    const char *appid;
+    const char *area_name;
+    mrp_application_privileges_t privileges;
+};
+
+mrp_application_t *mrp_application_create(mrp_application_update_t *u,
+                                          void *scripting_data);
+void mrp_application_destroy(mrp_application_t *app);
+
+mrp_application_t *mrp_application_find(const char *appid);
+
+size_t mrp_application_print(mrp_application_t *app,
+                             mrp_application_update_mask_t mask,
+                             char *buf, size_t len);
+
+void mrp_application_set_scripting_data(mrp_application_t *app, void *data);
+
+int mrp_application_foreach(mrp_htbl_iter_cb_t cb, void *user_data);
+
+const char *mrp_application_privilege_str(mrp_application_privilege_t priv);
+
+#endif /* __MURPHY_APPLICATION_H__ */
diff --git a/src/plugins/system-controller/application/scripting-application.c b/src/plugins/system-controller/application/scripting-application.c
new file mode 100644 (file)
index 0000000..a06386c
--- /dev/null
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+#include <murphy/core/lua-bindings/murphy.h>
+#include <murphy/core/lua-utils/error.h>
+#include <murphy/core/lua-utils/object.h>
+#include <murphy/core/lua-utils/funcbridge.h>
+
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include "wayland/wayland.h"
+#include "wayland/area.h"
+
+/* TODO: this shoud actually go to some common scripting */
+char *mrp_wayland_scripting_canonical_name(const char *, char *, size_t);
+
+
+#define APPLICATION_CLASS      MRP_LUA_CLASS_SIMPLE(application)
+
+typedef enum mrp_sysctl_scripting_field_e  field_t;
+typedef struct scripting_app_s  scripting_app_t;
+
+
+struct scripting_app_s {
+    mrp_application_t *app;
+    char *id;
+};
+
+
+
+static int  app_create_from_lua(lua_State *);
+static int  app_getfield(lua_State *);
+static int  app_setfield(lua_State *);
+static int  app_stringify(lua_State *);
+static void app_destroy_from_lua(void *);
+
+static scripting_app_t *app_check(lua_State *, int);
+
+static mrp_application_privileges_t *priv_check(lua_State *, int);
+static void priv_free(mrp_application_privileges_t *);
+static int  priv_push(lua_State *L, mrp_application_privileges_t *);
+
+static field_t field_check(lua_State *, int, const char **);
+static field_t field_name_to_type(const char *, ssize_t);
+
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    application,                  /* class name */
+    scripting_app_t,              /* userdata type */
+    app_destroy_from_lua,         /* userdata destructor */
+    MRP_LUA_METHOD_LIST (         /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR   (app_create_from_lua)
+    ),
+    MRP_LUA_METHOD_LIST (         /* overrides */
+       MRP_LUA_OVERRIDE_CALL        (app_create_from_lua)
+       MRP_LUA_OVERRIDE_GETFIELD    (app_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD    (app_setfield)
+       MRP_LUA_OVERRIDE_STRINGIFY   (app_stringify)
+    )
+);
+
+
+void mrp_application_scripting_init(lua_State *L)
+{
+    mrp_lua_create_object_class(L, APPLICATION_CLASS);
+}
+
+mrp_application_t *mrp_application_scripting_app_check(lua_State *L, int idx)
+{
+    scripting_app_t *a;
+    mrp_application_t *app;
+
+    if ((a = app_check(L, idx)) && (app = a->app)) {
+        MRP_ASSERT(app->scripting_data == (void *)a,
+                   "confused with data structures");
+        return app;
+    }
+
+    return NULL;
+}
+
+mrp_application_t *mrp_application_scripting_app_unwrap(void *void_a)
+{
+    scripting_app_t *a = (scripting_app_t *)void_a;
+
+    if (a && mrp_lua_get_object_classdef(a) == APPLICATION_CLASS)
+        return a->app;
+
+    return NULL;
+}
+
+
+void *mrp_application_scripting_app_create_from_c(mrp_application_t *app)
+{
+    lua_State *L;
+    scripting_app_t *a;
+
+    MRP_ASSERT(app, "invald argument");
+    
+    if (app->scripting_data)
+        a = app->scripting_data;
+    else {
+        if (!(L = mrp_lua_get_lua_state())) {
+            mrp_log_error("can't create scripting application '%s': LUA is "
+                          "not initialized", app->appid);
+            return NULL;
+        }
+
+        a = (scripting_app_t *)mrp_lua_create_object(L, APPLICATION_CLASS,
+                                                     app->appid, 0);
+        if (!a) {
+            mrp_log_error("can't create scripting application '%s': "
+                          "LUA object creation failed", app->appid);
+        }
+        else {
+            a->app = app;
+            mrp_application_set_scripting_data(app, a);
+            lua_pop(L, 1);
+        }
+    }
+
+    return a;
+}
+
+
+void mrp_application_scripting_app_destroy_from_c(mrp_application_t *app)
+{
+    lua_State *L;
+    scripting_app_t *a;
+
+    MRP_ASSERT(app, "invalid argument");
+
+    if (!(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("can't destroy scripting application '%s': "
+                      "LUA is not initialized", app->appid);
+        return;
+    }
+
+    if ((a = app->scripting_data)) {
+        mrp_debug("destroy scripting application '%s'", app->appid);
+
+        a->app = NULL;
+        mrp_application_set_scripting_data(app, NULL);
+
+        mrp_lua_destroy_object(L, a->id,0, a);
+    }
+}
+
+
+static int app_create_from_lua(lua_State *L)
+{
+    mrp_application_update_t u;
+    mrp_application_t *app;
+    scripting_app_t *a;
+    size_t fldnamlen;
+    const char *fldnam;
+    const char *appid = NULL;
+    const char *arnam = "default";
+    mrp_application_privileges_t *privs = NULL;
+    char *id;
+    char buf[4096];
+
+
+    MRP_LUA_ENTER;
+
+    luaL_checktype(L, 2, LUA_TTABLE);
+
+    MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
+        switch (field_name_to_type(fldnam, fldnamlen)) {
+
+        case APPID:       appid = luaL_checkstring(L, -1);           break;
+        case AREA:        arnam = luaL_checkstring(L, -1);           break;
+        case PRIVILEGES:  privs = priv_check(L, -1);                 break;
+        default:          luaL_error(L, "bad field '%s'", fldnam);   break;
+        }
+    }
+
+    if (!appid)
+        luaL_error(L, "'appid' field is missing"); 
+
+
+    id = mrp_wayland_scripting_canonical_name(appid, buf, sizeof(buf));
+    a = (scripting_app_t*)mrp_lua_create_object(L, APPLICATION_CLASS, id, 0);
+
+    if (!(a))
+        luaL_error(L, "can't create scripting application '%s'", appid);
+
+    u.mask = MRP_APPLICATION_APPID_MASK | MRP_APPLICATION_AREA_NAME_MASK ;
+    u.appid = appid;
+    u.area_name = arnam;
+
+    if (privs) {
+        u.mask |= MRP_APPLICATION_PRIVILEGES_MASK;
+        u.privileges.screen = privs->screen;
+        u.privileges.audio = privs->audio;
+        priv_free(privs);
+    }
+
+    if ((app = mrp_application_create(&u, a))) {
+        a->app = app;
+        a->id = mrp_strdup(id);
+    }
+    else {
+        lua_pop(L, 1);
+        mrp_lua_destroy_object(L, id,0, a);
+        lua_pushnil(L);
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int app_getfield(lua_State *L)
+{
+    scripting_app_t *a;
+    mrp_application_t *app;
+    mrp_wayland_area_t *area;
+    const char *fldnam;
+    field_t fld;
+
+    MRP_LUA_ENTER;
+
+    a = app_check(L, 1);
+    fld = field_check(L, 2, &fldnam);
+    lua_pop(L, 1);
+
+    if (!a || !(app = a->app))
+        lua_pushnil(L);
+    else {
+        area = app->area;
+
+        switch (fld) {
+        case APPID:      lua_pushstring(L, app->appid ? app->appid:"");  break;
+        case AREA:       lua_pushstring(L, area ? area->fullname:"");    break;
+        case PRIVILEGES: priv_push(L, &app->privileges);                 break;
+        default:         lua_pushnil(L);                                 break;
+        }
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int  app_setfield(lua_State *L)
+{
+    MRP_LUA_ENTER;
+
+    app_check(L, 1);
+    luaL_error(L, "application objects are read-only");
+
+    lua_pop(L, 2);
+
+    MRP_LUA_LEAVE(0);
+}
+
+static int  app_stringify(lua_State *L)
+{
+#define ALL_FIELDS (MRP_APPLICATION_END_MASK - 1)
+
+    scripting_app_t *a;
+    mrp_application_t *app;
+    char *p, *e;
+    char buf[4096];
+
+    MRP_LUA_ENTER;
+
+    a = app_check(L, 1);
+
+    if (!(app = a->app))
+        lua_pushnil(L);
+    else {
+        e = (p = buf) + sizeof(buf);
+        p += snprintf(p, e-p, "application '%s'", app->appid);
+        p += mrp_application_print(app, ALL_FIELDS, p, e-p);
+
+        lua_pushlstring(L, buf, p-buf);
+    }
+
+    MRP_LUA_LEAVE(1);
+
+#undef ALL_FIELDS
+}
+
+static void app_destroy_from_lua(void *data)
+{
+    scripting_app_t *a = (scripting_app_t *)data;
+    mrp_application_t *app;
+
+    MRP_LUA_ENTER;
+
+    if (a && (app = a->app)) {
+        a->app = NULL;
+        mrp_application_set_scripting_data(app, NULL);
+        mrp_free(a->id);
+    }
+
+    MRP_LUA_LEAVE_NOARG;
+}
+
+
+static scripting_app_t *app_check(lua_State *L, int idx)
+{
+    return (scripting_app_t *)mrp_lua_check_object(L, APPLICATION_CLASS, idx);
+}
+
+
+static mrp_application_privileges_t *priv_check(lua_State *L, int idx)
+{
+    mrp_application_privileges_t *priv;
+    int *p, v;
+    int screen = -1;
+    int audio = -1;
+    int n;
+    size_t fldnamlen, privnamlen;
+    const char *fldnam, *privnam;
+
+    idx = mrp_lua_absidx(L, idx);
+
+    luaL_checktype(L, idx, LUA_TTABLE);
+
+    MRP_LUA_FOREACH_FIELD(L, idx, fldnam, fldnamlen) {
+        switch (field_name_to_type(fldnam, fldnamlen)) {
+
+        case SCREEN:
+            p = &screen;
+            goto get_privilege;
+
+        case AUDIO:
+            p = &audio;
+            goto get_privilege;
+
+        default:
+            luaL_error(L, "bad field '%s'", fldnam);
+            break;
+
+        get_privilege:
+            v = -1;
+            if (lua_isnumber(L, -1)) {
+                n = lua_tointeger(L, -1);
+                if (n >= 0 && n < MRP_APPLICATION_PRIVILEGE_MAX)
+                    v = n;
+            }
+            else if ((privnam = lua_tolstring(L, -1, &privnamlen))) {
+                switch (privnamlen) {
+                case 4:
+                    if (!strcmp(privnam, "none"))
+                        v = MRP_APPLICATION_PRIVILEGE_NONE;
+                    break;
+                case 6:
+                    if (!strcmp(privnam, "system"))
+                        v = MRP_APPLICATION_PRIVILEGE_SYSTEM;
+                    break;
+                case 9:
+                    if (!strcmp(privnam, "unlimited"))
+                        v = MRP_APPLICATION_PRIVILEGE_UNLIMITED;
+                    else if (!strcmp(privnam, "certified"))
+                        v = MRP_APPLICATION_PRIVILEGE_CERTIFIED;
+                    break;
+                case 12:
+                    if (!strcmp(privnam, "manufacturer"))
+                        v = MRP_APPLICATION_PRIVILEGE_MANUFACTURER;
+                    break;
+                default:
+                    break;
+                } /* switch privnamlen */
+            }
+            *p = v;
+            break;
+        } /* switch fldnam */
+    } /* FOREACH_FIELD */
+
+    if (screen < 0)
+        luaL_error(L, "missing or invalid 'screen' field");
+    if (audio < 0)
+        luaL_error(L, "missing or invalid 'audio' field");
+
+    if ((priv = mrp_allocz(sizeof(*priv)))) {
+        priv->screen = screen;
+        priv->audio = audio;
+    }
+
+    return priv;
+}
+
+static void priv_free(mrp_application_privileges_t *priv)
+{
+    mrp_free(priv);
+}
+
+static int priv_push(lua_State *L, mrp_application_privileges_t *privs)
+{
+    if (!privs)
+        lua_pushnil(L);
+    else {
+        lua_createtable(L, 0, 2);
+
+        lua_pushstring(L, "screen");
+        lua_pushstring(L, mrp_application_privilege_str(privs->screen));
+        lua_settable(L, -3);
+
+        lua_pushstring(L, "audio");
+        lua_pushstring(L, mrp_application_privilege_str(privs->audio));
+        lua_settable(L, -3);
+    }
+
+    return 1;
+}
+
+static field_t field_check(lua_State *L, int idx, const char **ret_fldnam)
+{
+    const char *fldnam;
+    size_t fldnamlen;
+    field_t fldtyp;
+
+    if (!(fldnam = lua_tolstring(L, idx, &fldnamlen)))
+        fldtyp = 0;
+    else
+        fldtyp = field_name_to_type(fldnam, fldnamlen);
+
+    if (ret_fldnam)
+        *ret_fldnam = fldnam;
+
+    return fldtyp;
+}
+
+static field_t field_name_to_type(const char *name, ssize_t len)
+{
+    if (len < 0)
+        len = strlen(name);
+
+    switch (len) {
+
+    case 4:
+        if (!strcmp(name, "area"))
+            return AREA;
+        break;
+
+    case 5:
+        if (!strcmp(name, "appid"))
+            return APPID;
+        if (!strcmp(name, "audio"))
+            return AUDIO;
+        break;
+
+    case 6:
+        if (!strcmp(name, "screen"))
+            return SCREEN;
+        break;
+
+    case 10:
+        if (!strcmp(name, "privileges"))
+            return PRIVILEGES;
+        break;
+
+    default:
+        break;
+    }
+
+    return 0;
+}
+
diff --git a/src/plugins/system-controller/application/scripting-application.h b/src/plugins/system-controller/application/scripting-application.h
new file mode 100644 (file)
index 0000000..fbf9ebb
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_APPLICATION_SCRIPTING_H__
+#define __MURPHY_APPLICATION_SCRIPTING_H__
+
+#include <lua.h>
+
+#include <murphy/core/lua-bindings/lua-json.h>
+
+#include "wayland/wayland.h"
+
+void mrp_application_scripting_init(lua_State *L);
+
+
+mrp_application_t *mrp_application_scripting_app_check(lua_State *L, int idx);
+mrp_application_t *mrp_application_scripting_app_unwrap(void *void_a);
+void *mrp_application_scripting_app_create_from_c(mrp_application_t *app);
+void mrp_application_scripting_app_destroy_from_c(mrp_application_t *app);
+
+
+
+#endif /* __MURPHY_APPLICTION_SCRIPTING_H__ */
diff --git a/src/plugins/system-controller/data-types.h b/src/plugins/system-controller/data-types.h
new file mode 100644 (file)
index 0000000..e9734ec
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_SYSTEM_CONTROLLER_DATA_TYPES_H__
+#define __MURPHY_SYSTEM_CONTROLLER_DATA_TYPES_H__
+
+typedef enum mrp_sysctl_scripting_field_e  mrp_sysctl_scripting_field_t;
+
+enum mrp_sysctl_scripting_field_e {
+    /*  2 */ ID = 1,
+    /*  3 */ PID, TOP,
+    /*  4 */ AREA, FLIP, HIDE, LEFT, MAKE, MASK, MOVE, NAME, NODE, SIZE, SHOW,
+    /*  5 */ ALIGN, APPID, AUDIO, INDEX, INPUT, LAYER, MODEL, POS_X, POS_Y,
+             RAISE, RIGHT, WIDTH,
+    /*  6 */ ACTIVE, BOTTOM, HEIGHT, LAYERS, MAPPED, MIDDLE, OUTPUT, RESIZE,
+             ROTATE, SCREEN,
+    /*  7 */ CLASSES, DISPLAY, PIXEL_X, PIXEL_Y, SURFACE, VISIBLE,
+    /*  8 */ POSITION, SUBPIXEL, VERTICAL,
+    /*  9 */ LAYERTYPE, SHAREABLE,
+    /* 10 */ ATTRIBUTES, HORIZONTAL, KEEPRATIO, PRIVILEGES,
+    /* 11 */ AREA_CREATE, PIXEL_WIDTH,
+    /* 12 */ PIXEL_HEIGHT, LAYER_UPDATE,
+    /* 13 */ LAYER_REQUEST, OUTPUT_UPDATE, WINDOW_UPDATE,
+    /* 14 */ OUTPUT_REQUEST, WINDOW_MANAGER, WINDOW_REQUEST,
+};
+
+#endif /* __MURPHY_SYSTEM_CONTROLLER_DATA_TYPES_H__ */
index ccdd69e..856966d 100644 (file)
 
 #include "system-controller.h"
 
+#include "resource-manager/scripting-resource-manager.h"
+#include "application/scripting-application.h"
+#include "wayland/scripting-wayland.h"
+
+
 
 #define DEFAULT_ADDRESS "wsck:127.0.0.1:18081/ico_syc_protocol"
 
@@ -656,6 +661,10 @@ static int register_lua_bindings(sysctl_t *sc)
     if ((sc->L = mrp_lua_get_lua_state()) == NULL)
         return FALSE;
 
+    mrp_resmgr_scripting_init(sc->L);
+    mrp_application_scripting_init(sc->L);
+    mrp_wayland_scripting_init(sc->L);
+
     mrp_lua_create_object_class(sc->L, SYSCTL_LUA_CLASS);
 
     return mrp_lua_register_murphy_bindings(&bindings);
@@ -673,9 +682,9 @@ static int plugin_init(mrp_plugin_t *plugin)
     if (sc != NULL) {
         mrp_list_init(&sc->clients);
 
-        sc->id   = 1;
-        sc->ctx  = plugin->ctx;
-        sc->addr = plugin->args[ARG_ADDRESS].str;
+        sc->id      = 1;
+        sc->ctx     = plugin->ctx;
+        sc->addr    = plugin->args[ARG_ADDRESS].str;
 
         if (!transport_create(sc))
             goto fail;
@@ -719,7 +728,7 @@ static void plugin_exit(mrp_plugin_t *plugin)
 #define PLUGIN_VERSION     MRP_VERSION_INT(0, 0, 1)
 
 static mrp_plugin_arg_t plugin_args[] = {
-    MRP_PLUGIN_ARGIDX(ARG_ADDRESS, STRING, "address", DEFAULT_ADDRESS)
+    MRP_PLUGIN_ARGIDX(ARG_ADDRESS, STRING, "address", DEFAULT_ADDRESS),
 };
 
 MURPHY_REGISTER_PLUGIN("system-controller",
diff --git a/src/plugins/system-controller/resource-manager/resource-manager.c b/src/plugins/system-controller/resource-manager/resource-manager.c
new file mode 100644 (file)
index 0000000..155dc35
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2012, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+#include <murphy/common/debug.h>
+#include <murphy/core/plugin.h>
+#include <murphy/core/console.h>
+#include <murphy/core/event.h>
+#include <murphy/core/context.h>
+
+
+#include <murphy/resource/config-api.h>
+#include <murphy/resource/manager-api.h>
+#include <murphy/resource/client-api.h>
+#include <murphy/resource/protocol.h>
+
+#include "resource-manager.h"
+
+static int hash_compare(const void *, const void *);
+static uint32_t hash_function(const void *);
+
+mrp_resmgr_t *mrp_resmgr_create(void)
+{
+    mrp_resmgr_t *resmgr;
+    mrp_htbl_config_t cfg;
+
+    if (!(resmgr = mrp_allocz(sizeof(mrp_resmgr_t)))) {
+        mrp_log_error("system-controller: failed to allocate private data "
+                      "resource manager");
+        return NULL;
+    }
+
+    cfg.nentry = MRP_RESMGR_RESOURCE_MAX;
+    cfg.comp = hash_compare;
+    cfg.hash = hash_function;
+    cfg.free = NULL;
+    cfg.nbucket = MRP_RESMGR_RESOURCE_BUCKETS;
+
+    resmgr->resources = mrp_htbl_create(&cfg);
+
+    return resmgr;
+}
+
+void mrp_resmgr_insert_resource(mrp_resmgr_t *resmgr,
+                                mrp_zone_t *zone,
+                                mrp_resource_t *key,
+                                void *resource)
+{
+    uint32_t zoneid;
+
+    MRP_ASSERT(resmgr && zone && key && resource, "invalid argument");
+    MRP_ASSERT(resmgr->resources, "uninitialised data structure");
+
+    zoneid = mrp_zone_get_id(zone);
+
+    resmgr->zones |= ((mrp_zone_mask_t)1 << zoneid);
+
+    mrp_htbl_insert(resmgr->resources, key, resource);
+}
+
+void *mrp_resmgr_remove_resource(mrp_resmgr_t *resmgr,
+                                 mrp_zone_t *zone,
+                                 mrp_resource_t *key)
+{
+    MRP_ASSERT(resmgr && zone && key, "invalid argument");
+    MRP_ASSERT(resmgr->resources, "uninitialised data structure");
+
+    return mrp_htbl_remove(resmgr->resources, key, FALSE);
+}
+
+void *mrp_resmgr_lookup_resource(mrp_resmgr_t *resmgr, mrp_resource_t *key)
+{
+    MRP_ASSERT(resmgr && key, "invalid argument");
+    MRP_ASSERT(resmgr->resources, "uninitialised data structure");
+
+    return mrp_htbl_lookup(resmgr->resources, key);
+}
+
+static int hash_compare(const void *key1, const void *key2)
+{
+    if (key1 < key2)
+        return -1;
+    if (key1 > key2)
+        return 1;
+    return 0;
+}
+
+static uint32_t hash_function(const void *key)
+{
+    return (uint32_t)(((ptrdiff_t)key >> 4) & (ptrdiff_t)0xffffffff);
+}
diff --git a/src/plugins/system-controller/resource-manager/resource-manager.h b/src/plugins/system-controller/resource-manager/resource-manager.h
new file mode 100644 (file)
index 0000000..2fb1fbe
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_SYSTEM_CONTROLLER_RESOURCE_MANAGER_H__
+#define __MURPHY_SYSTEM_CONTROLLER_RESOURCE_MANAGER_H__
+
+#include <sys/types.h>
+
+#include <murphy/common/hashtbl.h>
+
+#include <murphy/resource/data-types.h>
+
+#include "data-types.h"
+
+typedef enum mrp_sysctl_scripting_field_e  mrp_resmgr_scripting_field_t;
+
+typedef struct mrp_resmgr_s                mrp_resmgr_t;
+typedef struct mrp_resmgr_screen_s         mrp_resmgr_screen_t;
+typedef struct mrp_resmgr_audio_s          mrp_resmgr_audio_t;
+typedef struct mrp_resmgr_input_s          mrp_resmgr_input_t;
+
+#define MRP_RESMGR_RESOURCE_MAX            256
+#define MRP_RESMGR_RESOURCE_BUCKETS        (MRP_RESMGR_RESOURCE_MAX / 4)
+
+struct mrp_resmgr_s {
+    mrp_htbl_t *resources;
+    mrp_zone_mask_t zones;
+
+    mrp_resmgr_screen_t *screen;
+    mrp_resmgr_audio_t *audio;
+    mrp_resmgr_input_t *input;
+
+    void *scripting_data;
+};
+
+
+mrp_resmgr_t *mrp_resmgr_create(void);
+void mrp_resmgr_destroy(mrp_resmgr_t *resmgr);
+
+void  mrp_resmgr_insert_resource(mrp_resmgr_t *resmgr, mrp_zone_t *zone,
+                                 mrp_resource_t *key, void *resource);
+void *mrp_resmgr_remove_resource(mrp_resmgr_t *resmgr, mrp_zone_t *zone,
+                                 mrp_resource_t *key);
+void *mrp_resmgr_lookup_resource(mrp_resmgr_t *resmgr, mrp_resource_t *key);
+
+
+#endif /* __MURPHY_SYSTEM_CONTROLLER_RESOURCE_MANAGER_H__ */
diff --git a/src/plugins/system-controller/resource-manager/scripting-resource-manager.c b/src/plugins/system-controller/resource-manager/scripting-resource-manager.c
new file mode 100644 (file)
index 0000000..e809c80
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+#include <murphy/core/lua-bindings/murphy.h>
+#include <murphy/core/lua-utils/error.h>
+#include <murphy/core/lua-utils/object.h>
+#include <murphy/core/lua-utils/funcbridge.h>
+
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include "scripting-resource-manager.h"
+#include "wayland/scripting-wayland.h"
+
+#define RESOURCE_MANAGER_CLASS   MRP_LUA_CLASS_SIMPLE(resource_manager)
+
+typedef struct scripting_resmgr_s  scripting_resmgr_t;
+typedef struct funcbridge_def_s    funcbridge_def_t;
+
+struct scripting_resmgr_s {
+    mrp_resmgr_t *resmgr;
+};
+
+struct funcbridge_def_s {
+    const char *name;
+    const char *sign;
+    mrp_funcbridge_cfunc_t func;
+    void *data;
+    mrp_funcbridge_t **ptr;
+};
+
+static int  resmgr_create(lua_State *);
+static int  resmgr_canonical_name(lua_State *);
+static int  resmgr_getfield(lua_State *);
+static int  resmgr_setfield(lua_State *);
+static void resmgr_destroy(void *);
+
+static scripting_resmgr_t *resmgr_check(lua_State *, int);
+
+static bool register_methods(lua_State *);
+
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    resource_manager,              /* class name */
+    scripting_resmgr_t,            /* userdata type */
+    resmgr_destroy,                /* userdata destructor */
+    MRP_LUA_METHOD_LIST (          /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR    (resmgr_create)
+    ),
+    MRP_LUA_METHOD_LIST (          /* overrides */
+       MRP_LUA_OVERRIDE_CALL         (resmgr_create)
+       MRP_LUA_OVERRIDE_GETFIELD     (resmgr_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD     (resmgr_setfield)
+    )
+);
+
+
+static mrp_funcbridge_t *area_create;
+
+
+void mrp_resmgr_scripting_init(lua_State *L)
+{
+    MRP_ASSERT(L, "invalid argument");
+
+    mrp_lua_create_object_class(L, RESOURCE_MANAGER_CLASS);
+    register_methods(L);
+}
+
+
+mrp_resmgr_t *mrp_resmgr_scripting_check(lua_State *L, int idx)
+{
+    scripting_resmgr_t *rm;
+    mrp_resmgr_t *resmgr;
+
+    if ((rm = resmgr_check(L, idx)) && (resmgr = rm->resmgr)) {
+        MRP_ASSERT(resmgr->scripting_data == (void *)rm,
+                   "confused with data structures");
+        return resmgr;
+    }
+
+    return NULL;
+}
+
+mrp_resmgr_t *mrp_resmgr_scripting_unwrap(void *void_rm)
+{
+    scripting_resmgr_t *rm = (scripting_resmgr_t *)void_rm;
+
+    if (rm && mrp_lua_get_object_classdef(rm) == RESOURCE_MANAGER_CLASS)
+        return rm->resmgr;
+
+    return NULL;
+}
+
+static int resmgr_create(lua_State *L)
+{
+    mrp_resmgr_t *resmgr;
+    size_t fldnamlen;
+    const char *fldnam;
+    scripting_resmgr_t *rm;
+    int table;
+
+    MRP_LUA_ENTER;
+
+    luaL_checktype(L, 2, LUA_TTABLE);
+
+    rm = (scripting_resmgr_t *)mrp_lua_create_object(L, RESOURCE_MANAGER_CLASS,
+                                                     NULL, 1);
+
+    if (!rm)
+        luaL_error(L, "failed to create resource manager");
+
+    table = lua_gettop(L);
+
+    MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
+        switch (mrp_resmgr_scripting_field_name_to_type(fldnam, fldnamlen)) {
+
+        default:
+            lua_pushvalue(L, -2);
+            lua_pushvalue(L, -2);
+            lua_rawset(L, table);
+            break;
+        }
+    }
+
+    if (!(resmgr = mrp_resmgr_create()))
+        luaL_error(L, "can't create resmgr object");
+
+    rm->resmgr = resmgr;
+
+    lua_settop(L, table);
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int resmgr_getfield(lua_State *L)
+{
+    scripting_resmgr_t *rm;
+    const char *fldnam;
+    mrp_resmgr_scripting_field_t fld;
+
+    MRP_LUA_ENTER;
+
+    fld = mrp_resmgr_scripting_field_check(L, 2, &fldnam);
+    lua_pop(L, 1);
+
+    rm = resmgr_check(L, 1);
+
+    if (!rm)
+        lua_pushnil(L);
+    else {
+        switch (fld) {
+
+        case AREA_CREATE:
+            mrp_funcbridge_push(L, area_create);
+            break;
+
+        default:
+            lua_pushstring(L, fldnam);
+            lua_rawget(L, 1);
+            break;
+        }
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int  resmgr_setfield(lua_State *L)
+{
+    MRP_LUA_ENTER;
+
+    resmgr_check(L, 1);
+    luaL_error(L, "resource manager is read-only");
+
+    MRP_LUA_LEAVE(0);
+}
+
+static void resmgr_destroy(void *data)
+{
+    scripting_resmgr_t *rm = (scripting_resmgr_t *)data;
+
+    MRP_UNUSED(data);
+    MRP_UNUSED(rm);
+
+    MRP_LUA_ENTER;
+
+    MRP_LUA_LEAVE_NOARG;
+}
+
+static scripting_resmgr_t *resmgr_check(lua_State *L, int idx)
+{
+
+    return (scripting_resmgr_t*)mrp_lua_check_object(L, RESOURCE_MANAGER_CLASS,
+                                                     idx);
+}
+
+
+static bool area_create_bridge(lua_State *L,
+                               void *data,
+                               const char *signature,
+                               mrp_funcbridge_value_t *args,
+                               char *ret_type,
+                               mrp_funcbridge_value_t *ret_val)
+{
+    mrp_wayland_area_t *area;
+    mrp_resmgr_t *resmgr;
+
+    MRP_UNUSED(L);
+    MRP_UNUSED(data);
+    MRP_UNUSED(ret_val);
+    MRP_ASSERT(signature && args && ret_type, "invalid argument");
+
+    *ret_type = MRP_FUNCBRIDGE_NO_DATA;
+
+    if (strcmp(signature, "oo")) {
+        mrp_log_error("bad signature: expected 'oo' got '%s'",signature);
+        return false;
+    }
+
+    if (!(resmgr = mrp_resmgr_scripting_unwrap(args[0].pointer))) {
+        mrp_log_error("argument 1 is not a 'resource_manager' class object");
+        return false;
+    }
+
+    if (!(area = mrp_wayland_scripting_area_unwrap(args[1].pointer))) {
+        mrp_log_error("argument 2 is not 'area' class object");
+        return false;
+    }
+
+
+    return true;
+}
+
+
+
+mrp_resmgr_scripting_field_t
+mrp_resmgr_scripting_field_check(lua_State *L,int idx,const char **ret_fldnam)
+{
+    const char *fldnam;
+    size_t fldnamlen;
+    mrp_resmgr_scripting_field_t fldtyp;
+
+    if (!(fldnam = lua_tolstring(L, idx, &fldnamlen)))
+        fldtyp = 0;
+    else
+        fldtyp = mrp_resmgr_scripting_field_name_to_type(fldnam, fldnamlen);
+
+    if (ret_fldnam)
+        *ret_fldnam = fldnam;
+
+    return fldtyp;
+}
+
+mrp_resmgr_scripting_field_t
+mrp_resmgr_scripting_field_name_to_type(const char *name, ssize_t len)
+{
+    if (len < 0)
+        len = strlen(name);
+
+    switch (len) {
+
+    case 4:
+        if (!strcmp(name, "name"))
+            return NAME;
+        break;
+
+    case 5:
+        switch (name[0]) {
+        case 'a':
+            if (!strcmp(name, "AUDIO"))
+                return AUDIO;
+            break;
+        case 'i':
+            if (!strcmp(name, "input"))
+                return INPUT;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case 6:
+        if (!strcmp(name, "screen"))
+            return SCREEN;
+        break;
+
+    case 7:
+        if (!strcmp(name, "classes"))
+            return CLASSES;
+        break;
+
+    case 9:
+        if (!strcmp(name, "SHAREABLE"))
+            return SHAREABLE;
+        break;
+
+    case 10:
+        if (!strcmp(name, "attributes"))
+            return ATTRIBUTES;
+        break;
+
+    case 11:
+        if (!strcmp(name, "area_create"))
+            return AREA_CREATE;
+        break;
+
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+static bool register_methods(lua_State *L)
+{
+#define FUNCBRIDGE(n,s,d) { #n, s, n##_bridge, d, &n }
+#define FUNCBRIDGE_END    { NULL, NULL, NULL, NULL, NULL }
+
+    static funcbridge_def_t funcbridge_defs[] = {
+        FUNCBRIDGE(area_create   , "oo"  , NULL),
+        FUNCBRIDGE_END
+    };
+
+    mrp_funcbridge_t *f;
+    funcbridge_def_t *d;
+    bool success = true;
+
+    for (d = funcbridge_defs;   d->name;    d++) {
+        *(d->ptr) = f = mrp_funcbridge_create_cfunc(L, d->name, d->sign,
+                                                    d->func, d->data);
+        if (!f) {
+            mrp_log_error("failed to register builtin function '%s'", d->name);
+            success = false;
+        }
+    }
+
+    return success;
+
+#undef FUNCBRIDGE_END
+#undef FUNCBRIDGE
+}
diff --git a/src/plugins/system-controller/resource-manager/scripting-resource-manager.h b/src/plugins/system-controller/resource-manager/scripting-resource-manager.h
new file mode 100644 (file)
index 0000000..da4a4d2
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_SYSTEM_CONTROLLER_RESOURCE_MANAGER_SCRIPTING_H__
+#define __MURPHY_SYSTEM_CONTROLLER_RESOURCE_MANAGER_SCRIPTING_H__
+
+#include <lua.h>
+
+#include "resource-manager/resource-manager.h"
+
+void mrp_resmgr_scripting_init(lua_State *L);
+
+mrp_resmgr_t *mrp_resmgr_scripting_check(lua_State *L, int idx);
+mrp_resmgr_t *mrp_resmgr_scripting_unwrap(void *void_rm);
+
+
+mrp_resmgr_scripting_field_t
+mrp_resmgr_scripting_field_check(lua_State *, int, const char **);
+
+mrp_resmgr_scripting_field_t
+mrp_resmgr_scripting_field_name_to_type(const char *, ssize_t);
+
+
+#endif /* __MURPHY_SYSTEM_CONTROLLER_RESOURCE_MANAGER_SCRIPTING_H__ */
diff --git a/src/plugins/system-controller/wayland/animation.c b/src/plugins/system-controller/wayland/animation.c
new file mode 100644 (file)
index 0000000..1b27e23
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+
+#include "animation.h"
+
+static const char *type_str(mrp_wayland_animation_type_t type);
+
+mrp_wayland_animation_t *mrp_wayland_animation_create(void)
+{
+    size_t size;
+    mrp_wayland_animation_t *anims;
+
+    size = sizeof(mrp_wayland_animation_t) * MRP_WAYLAND_ANIMATION_MAX;
+
+    if (!(anims = mrp_allocz(size)))
+        mrp_log_error("can't get memory for animation");
+
+    return anims;
+}
+
+void mrp_wayland_animation_destroy(mrp_wayland_animation_t *anims)
+{
+    int i;
+
+    if (anims) {
+        for (i = 0;  i < MRP_WAYLAND_ANIMATION_MAX;  i++)
+            mrp_free((void *)anims[i].name);
+        mrp_free(anims);
+    }
+}
+
+bool mrp_wayland_animation_set(mrp_wayland_animation_t *anims,
+                               mrp_wayland_animation_type_t type,
+                               const char *name,
+                               int32_t time)
+{
+    mrp_wayland_animation_t *anim;
+
+    MRP_ASSERT(anims, "invalid argument");
+
+    if (type < 0 || type > MRP_WAYLAND_ANIMATION_MAX)
+        return false;
+
+    anim = anims + type;
+
+    mrp_free((void *)anim->name);
+
+    if (!name || !name[0] || time <= 0)
+        memset(anim, 0, sizeof(mrp_wayland_animation_t));
+    else {
+        anim->type = type;
+        anim->name = mrp_strdup(name);
+        anim->time = time;
+    }
+
+    return true;
+}
+
+size_t mrp_wayland_animation_print(mrp_wayland_animation_t *anims,
+                                   char *buf, size_t len)
+{
+#define PRINT(fmt, args...) \
+    if (p < e) { p += snprintf(p, e-p, "\n      " fmt , ## args); }
+
+    mrp_wayland_animation_t *anim;
+    char *p, *e;
+    size_t i;
+    bool empty;
+
+    MRP_ASSERT(buf && len > 0, "invalid argument");
+
+    e = (p = buf) + len;
+    empty = true;
+
+    if (anims) {
+        for (i = 0;   i < MRP_WAYLAND_ANIMATION_MAX;   i++) {
+            anim = anims + i;
+
+            if (anim->name && anim->name[0]) {
+                PRINT("%s: '%s' %d", type_str(i), anim->name, anim->time);
+                empty = false;
+            }
+        }
+    }
+
+    if (empty)
+        PRINT("<none>");
+
+    return p - buf;
+
+#undef PRINT
+}
+
+static const char *type_str(mrp_wayland_animation_type_t type)
+{
+    const char *str;
+
+    switch (type) {
+    case MRP_WAYLAND_ANIMATION_HIDE:     str = "hide";              break;
+    case MRP_WAYLAND_ANIMATION_SHOW:     str = "show";              break;
+    case MRP_WAYLAND_ANIMATION_MOVE:     str = "move";              break;
+    case MRP_WAYLAND_ANIMATION_RESIZE:   str = "resize";            break;
+    default:                             str = "<not-supported>";   break;
+    }
+
+    return str;
+}
diff --git a/src/plugins/system-controller/wayland/animation.h b/src/plugins/system-controller/wayland/animation.h
new file mode 100644 (file)
index 0000000..f1fbe32
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_WAYLAND_ANIMATION_H__
+#define __MURPHY_WAYLAND_ANIMATION_H__
+
+#include <sys/types.h>
+
+#include "wayland/wayland.h"
+
+
+enum mrp_wayland_animation_type_e {
+    MRP_WAYLAND_ANIMATION_HIDE = 0,
+    MRP_WAYLAND_ANIMATION_SHOW,
+    MRP_WAYLAND_ANIMATION_MOVE,
+    MRP_WAYLAND_ANIMATION_RESIZE,
+
+    MRP_WAYLAND_ANIMATION_MAX
+};
+
+struct mrp_wayland_animation_s {
+    mrp_wayland_animation_type_t type;
+    const char *name;
+    int32_t time;
+};
+
+mrp_wayland_animation_t *mrp_wayland_animation_create(void);
+void mrp_wayland_animation_destroy(mrp_wayland_animation_t *);
+
+bool mrp_wayland_animation_set(mrp_wayland_animation_t *anims,
+                               mrp_wayland_animation_type_t type,
+                               const char *name,
+                               int32_t time);
+
+size_t mrp_wayland_animation_print(mrp_wayland_animation_t *anims,
+                                   char *buf, size_t len);
+
+
+#endif /* __MURPHY_WAYLAND_ANIMATION_H__ */
diff --git a/src/plugins/system-controller/wayland/area.c b/src/plugins/system-controller/wayland/area.c
new file mode 100644 (file)
index 0000000..3517058
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+
+#include "area.h"
+#include "window-manager.h"
+#include "output.h"
+#include "scripting-wayland.h"
+
+
+static char *align_str(mrp_wayland_area_align_t, char *, size_t);
+
+static int set_area_for_applications(void *, void *, void *);
+
+
+
+mrp_wayland_area_t *mrp_wayland_area_create(mrp_wayland_t *wl,
+                                            mrp_wayland_area_update_t *u)
+{
+#define IF_PRESENT(u,n) (u->mask & MRP_WAYLAND_AREA_ ## n ## _MASK)
+
+    static mrp_wayland_area_align_t left_and_right =
+        MRP_WAYLAND_AREA_ALIGN_LEFT  |
+        MRP_WAYLAND_AREA_ALIGN_RIGHT ;
+    static mrp_wayland_area_align_t top_and_bottom =
+        MRP_WAYLAND_AREA_ALIGN_LEFT  |
+        MRP_WAYLAND_AREA_ALIGN_RIGHT ;
+
+
+    mrp_wayland_area_update_mask_t mask;
+    mrp_wayland_area_t *area;
+    char fullname[2048];
+    char buf[2048];
+
+    MRP_ASSERT(wl && u &&
+               (u->mask & MRP_WAYLAND_AREA_NAME_MASK) && u->name &&
+               (u->mask & MRP_WAYLAND_AREA_OUTPUT_MASK) &&
+               (u->mask & MRP_WAYLAND_AREA_WIDTH_MASK) &&
+               (u->mask & MRP_WAYLAND_AREA_HEIGHT_MASK),
+               "invalid argument");
+
+    if (!(area = mrp_allocz(sizeof(mrp_wayland_area_t)))) {
+        mrp_log_error("failed to create area %d: out of memory",
+                      u->areaid);
+        return NULL;
+    }
+
+    snprintf(fullname, sizeof(fullname), "%s.%s",
+             u->output->outputname, u->name);
+
+    area->wl = wl;
+    area->wm = wl->wm;
+    area->name = mrp_strdup(u->name);
+    area->fullname = mrp_strdup(fullname);
+    area->output = u->output;
+    area->width = u->width;
+    area->height = u->height;
+
+    mask = u->mask | MRP_WAYLAND_AREA_FULLNAME_MASK;
+
+    area->areaid    = IF_PRESENT(u, AREAID   ) ? u->areaid : -1;
+    area->x         = IF_PRESENT(u, X        ) ? u->x : 0;
+    area->y         = IF_PRESENT(u, Y        ) ? u->y : 0;
+    area->keepratio = IF_PRESENT(u, KEEPRATIO) ? u->keepratio : false;
+    area->align     = IF_PRESENT(u, ALIGN    ) ? u->align : 0;
+
+    if ((area->align & MRP_WAYLAND_AREA_ALIGN_HMASK) == left_and_right)
+        area->align &= ~MRP_WAYLAND_AREA_ALIGN_HMASK; /* align middle */
+
+    if ((area->align & MRP_WAYLAND_AREA_ALIGN_VMASK) == top_and_bottom)
+        area->align &= ~MRP_WAYLAND_AREA_ALIGN_VMASK; /* align middle */
+
+    if (!mrp_htbl_insert(wl->areas, area->fullname, area)) {
+        mrp_log_error("failed to create area: already exists");
+        mrp_free(area->name);
+        mrp_free(area->fullname);
+        mrp_free(area);
+        return NULL;
+    }
+
+    if (wl->create_scripting_areas) {
+        area->scripting_data = mrp_wayland_scripting_area_create_from_c(NULL,
+                                                                        area);
+    }
+
+    mrp_wayland_area_print(area, mask, buf,sizeof(buf));
+    mrp_debug("area '%s' created%s", area->name, buf);
+
+    if (wl->area_update_callback)
+        wl->area_update_callback(wl, MRP_WAYLAND_AREA_CREATE, mask, area);
+
+    mrp_application_foreach(set_area_for_applications, area);
+
+    return area;
+
+#undef IF_PRESENT
+}
+
+void mrp_wayland_area_destroy(mrp_wayland_area_t *area)
+{
+    mrp_wayland_t *wl;
+    char buf[1024];
+
+    MRP_ASSERT(area && area->wl, "invalid argument");
+
+    wl = area->wl;
+
+    mrp_wayland_area_print(area, MRP_WAYLAND_AREA_AREAID_MASK,
+                           buf, sizeof(buf));
+    mrp_debug("destroying area '%s'%s", area->name, buf);
+
+    if (wl->area_update_callback)
+        wl->area_update_callback(wl, MRP_WAYLAND_AREA_DESTROY, 0, area);
+
+    if ((void *)area != mrp_htbl_remove(wl->areas, area->name, false)) {
+        mrp_log_error("failed to destroy area '%s': confused with "
+                      "data structures", area->name);
+        return;
+    }
+
+    mrp_free(area->name);
+
+    free(area);
+}
+
+
+mrp_wayland_area_t *mrp_wayland_area_find(mrp_wayland_t *wl,
+                                          const char *fullname)
+{
+    MRP_ASSERT(wl, "invalid argument");
+
+    return (mrp_wayland_area_t*)mrp_htbl_lookup(wl->areas, (void *)fullname);
+}
+
+
+size_t mrp_wayland_area_print(mrp_wayland_area_t *area,
+                               mrp_wayland_area_update_mask_t mask,
+                               char *buf, size_t len)
+{
+#define PRINT(fmt, args...) \
+    if (p < e) { p += snprintf(p, e-p, "\n      " fmt , ## args); }
+
+    mrp_wayland_output_t *out;
+    char *p, *e;
+    char as[256];
+
+    out = area->output;
+    e = (p = buf) + len;
+
+    *p = 0;
+
+    if ((mask & MRP_WAYLAND_AREA_AREAID_MASK))
+        PRINT("areaid: %d", area->areaid);
+    if ((mask & MRP_WAYLAND_AREA_NAME_MASK))
+        PRINT("name: '%s'", area->name);
+    if ((mask & MRP_WAYLAND_AREA_FULLNAME_MASK))
+        PRINT("fullname: '%s'", area->fullname);
+    if ((mask & MRP_WAYLAND_AREA_OUTPUT_MASK))
+        PRINT("output: '%s'", out ? out->outputname : "<not set>");
+    if ((mask & MRP_WAYLAND_AREA_POSITION_MASK))
+        PRINT("position: %d,%d", area->x, area->y);
+    if ((mask & MRP_WAYLAND_AREA_SIZE_MASK))
+        PRINT("size: %dx%d", area->width, area->height);
+    if ((mask & MRP_WAYLAND_AREA_KEEPRATIO_MASK))
+        PRINT("keepratio: %s", area->keepratio ? "yes" : "no");
+    if ((mask & MRP_WAYLAND_AREA_ALIGN_MASK))
+        PRINT("align: 0x%x =%s", area->align, align_str(area->align,
+                                                        as, sizeof(as)));
+    return p - buf;
+
+#undef PRINT
+}
+
+const char *mrp_wayland_area_align_str(mrp_wayland_area_align_t align)
+{
+    switch (align) {
+    case MRP_WAYLAND_AREA_ALIGN_LEFT:    return "left";
+    case MRP_WAYLAND_AREA_ALIGN_RIGHT:   return "right";
+    case MRP_WAYLAND_AREA_ALIGN_TOP:     return "top";
+    case MRP_WAYLAND_AREA_ALIGN_BOTTOM:  return "bottom";
+    default:                             return "middle";
+    }
+}
+
+void mrp_wayland_area_set_scripting_data(mrp_wayland_area_t *area, void *data)
+{
+    MRP_ASSERT(area, "Invalid Argument");
+
+    mrp_debug("%sset scripting data", data ? "" : "re");
+
+    area->scripting_data = data;
+}
+
+
+static char *align_str(mrp_wayland_area_align_t align, char *buf, size_t len)
+{
+#define PRINT(fmt, args... ) \
+    if (p < e) { p += snprintf(p, e-p, " " fmt , ## args); }
+
+    typedef struct {
+        mrp_wayland_area_align_t mask;
+        const char *name;
+    } map_t;
+
+    static map_t hmap[] = {
+        { MRP_WAYLAND_AREA_ALIGN_LEFT   ,  "left"    },
+        { MRP_WAYLAND_AREA_ALIGN_MIDDLE ,  "hmiddle" },
+        { MRP_WAYLAND_AREA_ALIGN_RIGHT  ,  "right"   },
+        {                 0,                NULL     }
+    };
+    static map_t vmap[] = {
+        { MRP_WAYLAND_AREA_ALIGN_TOP    ,  "top"     },
+        { MRP_WAYLAND_AREA_ALIGN_MIDDLE ,  "vmiddle" },
+        { MRP_WAYLAND_AREA_ALIGN_BOTTOM ,  "bottom"  },
+        {                 0,                NULL     }
+    };
+
+    mrp_wayland_area_align_t halign, valign;
+    map_t *m;
+    char *p, *e;
+
+    halign = align & MRP_WAYLAND_AREA_ALIGN_HMASK;
+    valign = align & MRP_WAYLAND_AREA_ALIGN_VMASK;
+
+    e = (p = buf) + len;
+
+    *p = 0;
+
+    for (m = hmap;   m->name;   m++) {
+        if ((halign == m->mask)) {
+                PRINT("%s", m->name);
+                align &= ~m->mask;
+                break;
+        }
+    }
+
+    for (m = vmap;   m->name;   m++) {
+        if ((valign == m->mask)) {
+                PRINT("%s", m->name);
+                align &= ~m->mask;
+                break;
+        }
+    }
+
+    if (align)
+        PRINT("<unknown 0x%x>", align);
+
+    return buf;
+
+#undef PRINT
+}
+
+
+static int set_area_for_applications(void *key, void *object, void *ud)
+{
+    mrp_application_t *app = (mrp_application_t *)object;
+    mrp_wayland_area_t *area = (mrp_wayland_area_t *)ud;
+
+    MRP_UNUSED(key);
+
+    if (!strcmp(app->area_name, area->fullname)) {
+        mrp_debug("set area '%s' for app '%s'", area->name, app->appid);
+        app->area = area;
+    }
+
+    return MRP_HTBL_ITER_MORE;
+}
diff --git a/src/plugins/system-controller/wayland/area.h b/src/plugins/system-controller/wayland/area.h
new file mode 100644 (file)
index 0000000..db1c318
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_WAYLAND_AREA_H__
+#define __MURPHY_WAYLAND_AREA_H__
+
+#include <sys/types.h>
+
+#include "wayland/wayland.h"
+
+enum mrp_wayland_area_operation_e {
+    MRP_WAYLAND_AREA_OPERATION_NONE = 0,
+    MRP_WAYLAND_AREA_CREATE,
+    MRP_WAYLAND_AREA_DESTROY,
+};
+
+enum mrp_wayland_area_align_e {
+    MRP_WAYLAND_AREA_ALIGN_MIDDLE   = 0x00,
+
+    MRP_WAYLAND_AREA_ALIGN_HMASK    = 0x03,
+    MRP_WAYLAND_AREA_ALIGN_LEFT     = 0x01,
+    MRP_WAYLAND_AREA_ALIGN_RIGHT    = 0x02,
+
+    MRP_WAYLAND_AREA_ALIGN_VMASK    = 0x0C,
+    MRP_WAYLAND_AREA_ALIGN_TOP      = 0x04,
+    MRP_WAYLAND_AREA_ALIGN_BOTTOM   = 0x08,
+
+    MRP_WAYLAND_AREA_ALIGN_END_MASK = 0x10
+};
+
+struct mrp_wayland_area_s {
+    mrp_wayland_t *wl;
+    mrp_wayland_window_manager_t *wm;
+
+    int32_t areaid;
+    char *name;
+    char *fullname;
+    mrp_wayland_output_t *output;
+    int32_t x, y;
+    int32_t width, height;
+    bool keepratio;
+    mrp_wayland_area_align_t align;
+
+    void *scripting_data;
+};
+
+
+enum mrp_wayland_area_update_mask_e {
+    MRP_WAYLAND_AREA_AREAID_MASK    = 0x0001,
+    MRP_WAYLAND_AREA_NAME_MASK      = 0x0002,
+    MRP_WAYLAND_AREA_FULLNAME_MASK  = 0x0004,
+    MRP_WAYLAND_AREA_OUTPUT_MASK    = 0x0008,
+    MRP_WAYLAND_AREA_X_MASK         = 0x0010,
+    MRP_WAYLAND_AREA_Y_MASK         = 0x0020,
+    MRP_WAYLAND_AREA_POSITION_MASK  = 0x0030,
+    MRP_WAYLAND_AREA_WIDTH_MASK     = 0x0040,
+    MRP_WAYLAND_AREA_HEIGHT_MASK    = 0x0080,
+    MRP_WAYLAND_AREA_SIZE_MASK      = 0x00C0,
+    MRP_WAYLAND_AREA_KEEPRATIO_MASK = 0x0100,
+    MRP_WAYLAND_AREA_ALIGN_MASK     = 0x0200,
+
+    MRP_WAYLAND_AREA_END_MASK       = 0x0400
+};
+
+
+struct mrp_wayland_area_update_s {
+    mrp_wayland_area_update_mask_t mask;
+    int32_t areaid;
+    const char *name;
+    mrp_wayland_output_t *output;
+    int32_t x, y;
+    int32_t width, height;
+    bool keepratio;
+    mrp_wayland_area_align_t align;
+};
+
+mrp_wayland_area_t *mrp_wayland_area_create(mrp_wayland_t *wl,
+                                            mrp_wayland_area_update_t *u);
+void mrp_wayland_area_destroy(mrp_wayland_area_t *area);
+
+mrp_wayland_area_t *mrp_wayland_area_find(mrp_wayland_t *wl,
+                                          const char *fullname);
+
+size_t mrp_wayland_area_print(mrp_wayland_area_t *area,
+                              mrp_wayland_area_update_mask_t mask,
+                              char *buf, size_t len);
+
+const char *mrp_wayland_area_align_str(mrp_wayland_area_align_t align);
+
+void mrp_wayland_area_set_scripting_data(mrp_wayland_area_t *area, void *data);
+
+
+#endif /* __MURPHY_WAYLAND_AREA_H__ */
diff --git a/src/plugins/system-controller/wayland/ico-input-manager.c b/src/plugins/system-controller/wayland/ico-input-manager.c
new file mode 100644 (file)
index 0000000..c084d22
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+
+#include <wayland-util.h>
+#include <ico-uxf-weston-plugin/ico_input_mgr-client-protocol.h>
+
+#include "ico-input-manager.h"
+#include "input-manager.h"
+
+typedef struct exinput_s  exinput_t;
+typedef struct device_s   device_t;
+
+struct mrp_ico_input_manager_s {
+    MRP_WAYLAND_INPUT_MANAGER_COMMON;
+};
+
+struct exinput_s {
+    MRP_WAYLAND_OBJECT_COMMON;
+};
+
+struct device_s {
+    MRP_WAYLAND_OBJECT_COMMON;
+};
+
+
+static bool input_manager_constructor(mrp_wayland_t *, mrp_wayland_object_t *);
+static bool exinput_constructor(mrp_wayland_t *, mrp_wayland_object_t *);
+static void exinput_destructor(mrp_wayland_object_t *);
+static bool device_constructor(mrp_wayland_t *, mrp_wayland_object_t *);
+static void device_destructor(mrp_wayland_object_t *);
+
+
+static bool input_manager_constructor(mrp_wayland_t *,mrp_wayland_object_t *);
+
+static void exinput_capabilities_callback(void *, struct ico_exinput *,
+                                          const char *, int32_t,
+                                          const char *, int32_t,
+                                          const char *, int32_t);
+static void exinput_code_callback(void *, struct ico_exinput *, const char *,
+                                  int32_t, const char *, int32_t);
+static void exinput_input_callback(void *, struct ico_exinput *, uint32_t,
+                                   const char *, int32_t, int32_t, int32_t);
+static void device_input_regions_callback(void *,
+                                          struct ico_input_mgr_device *,
+                                          struct wl_array *);
+
+
+bool mrp_ico_input_manager_register(mrp_wayland_t *wl)
+{
+    mrp_wayland_factory_t factory;
+
+    factory.size = sizeof(mrp_ico_input_manager_t);
+    factory.interface = &ico_input_mgr_control_interface;
+    factory.constructor = input_manager_constructor;
+    factory.destructor = NULL;
+    mrp_wayland_register_interface(wl, &factory);
+
+    factory.size = sizeof(exinput_t);
+    factory.interface = &ico_exinput_interface;
+    factory.constructor = exinput_constructor;
+    factory.destructor = exinput_destructor;
+    mrp_wayland_register_interface(wl, &factory);
+
+    factory.size = sizeof(device_t);
+    factory.interface = &ico_input_mgr_device_interface;
+    factory.constructor = device_constructor;
+    factory.destructor = device_destructor;
+    mrp_wayland_register_interface(wl, &factory);
+
+    return true;
+}
+
+static bool input_manager_constructor(mrp_wayland_t *wl,
+                                      mrp_wayland_object_t *obj)
+{
+    mrp_ico_input_manager_t *im = (mrp_ico_input_manager_t *)obj;
+
+    MRP_ASSERT(im, "invalid argument");
+
+    wl->im = (mrp_wayland_input_manager_t *)im;
+
+    return true;
+}
+
+static bool exinput_constructor(mrp_wayland_t *wl, mrp_wayland_object_t *obj)
+{
+    static struct ico_exinput_listener listener = {
+        .capabilities = exinput_capabilities_callback,
+        .code         = exinput_code_callback,
+        .input        = exinput_input_callback
+    };
+
+    exinput_t *xinp = (exinput_t *)obj;
+    int sts;
+
+    MRP_UNUSED(wl);
+
+    sts = ico_exinput_add_listener((struct ico_exinput *)xinp->proxy,
+                                   &listener, xinp);
+    if (sts < 0)
+        return false;
+
+    return true;
+}
+
+static void exinput_destructor(mrp_wayland_object_t *obj)
+{
+    exinput_t *xinp = (exinput_t *)obj;
+
+    MRP_UNUSED(xinp);
+}
+
+static bool device_constructor(mrp_wayland_t *wl, mrp_wayland_object_t *obj)
+{
+    static struct ico_input_mgr_device_listener listener = {
+        .input_regions = NULL
+    };
+
+    device_t *dev = (device_t *)obj;
+    int sts;
+
+    MRP_UNUSED(wl);
+    MRP_UNUSED(device_input_regions_callback);
+
+    sts = ico_input_mgr_device_add_listener((struct ico_input_mgr_device *)dev,
+                                            &listener, dev);
+    if (sts < 0)
+        return false;
+
+    return true;
+}
+
+static void device_destructor(mrp_wayland_object_t *obj)
+{
+    device_t *dev = (device_t *)obj;
+
+    MRP_UNUSED(dev);
+}
+
+
+
+static void exinput_capabilities_callback(void *data,
+                                          struct ico_exinput *ico_exinput,
+                                          const char *device,
+                                          int32_t type,
+                                          const char *swname,
+                                          int32_t input,
+                                          const char *codename,
+                                          int32_t code)
+{
+    exinput_t *xinp = (exinput_t *)data;
+
+    MRP_ASSERT(xinp && xinp->interface && xinp->interface->wl,
+               "invalid argument");
+    MRP_ASSERT(ico_exinput == (struct ico_exinput *)xinp->proxy,
+               "confused with data structures");
+
+    mrp_debug("exinput_capabilities_callback(device='%s', type=%d,"
+              "swname='%s', input=%d, codename='%s', code=%d)",
+              device, type, swname, input, codename, code);
+
+}
+
+
+static void exinput_code_callback(void *data,
+                                  struct ico_exinput *ico_exinput,
+                                  const char *device,
+                                  int32_t input,
+                                  const char *codename,
+                                  int32_t code)
+{
+    exinput_t *xinp = (exinput_t *)data;
+
+    MRP_ASSERT(xinp && xinp->interface && xinp->interface->wl,
+               "invalid argument");
+    MRP_ASSERT(ico_exinput == (struct ico_exinput *)xinp->proxy,
+               "confused with data structures");
+
+    mrp_debug("exinput_code_callback(device='%s', input=%d, "
+              "codename='%s', code=%d)",
+              device, input, codename, code);
+}
+
+
+static void exinput_input_callback(void *data,
+                                   struct ico_exinput *ico_exinput,
+                                   uint32_t time,
+                                   const char *device,
+                                   int32_t input,
+                                   int32_t code,
+                                   int32_t state)
+{
+    exinput_t *xinp = (exinput_t *)data;
+
+    MRP_ASSERT(xinp && xinp->interface && xinp->interface->wl,
+               "invalid argument");
+    MRP_ASSERT(ico_exinput == (struct ico_exinput *)xinp->proxy,
+               "confused with data structures");
+
+    mrp_debug("exinput_input_callback(time=%u, device='%s', "
+              "input=%d, code=%d, state=%d)",
+              time, device, input, code, state);
+}
+
+
+static void device_input_regions_callback(void *data,
+                                          struct ico_input_mgr_device *
+                                                              ico_input_device,
+                                          struct wl_array *regions)
+{
+    device_t *dev = (device_t *)data;
+
+    MRP_UNUSED(regions);
+
+    MRP_ASSERT(dev && dev->interface && dev->interface->wl,
+               "invalid argument");
+    MRP_ASSERT(ico_input_device == (struct ico_input_mgr_device *)dev->proxy,
+               "confused with data structures");
+
+    mrp_debug("device_input_regions_callback()");
+}
diff --git a/src/plugins/system-controller/wayland/ico-input-manager.h b/src/plugins/system-controller/wayland/ico-input-manager.h
new file mode 100644 (file)
index 0000000..1e9cf70
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_ICO_INPUT_MANAGER_H__
+#define __MURPHY_ICO_INPUT_MANAGER_H__
+
+#include "wayland/wayland.h"
+
+typedef struct mrp_ico_input_manager_s  mrp_ico_input_manager_t;
+
+bool mrp_ico_input_manager_register(mrp_wayland_t *wl);
+
+#endif /* __MURPHY_ICO_INPUT_MANAGER_H__ */
diff --git a/src/plugins/system-controller/wayland/ico-window-manager.c b/src/plugins/system-controller/wayland/ico-window-manager.c
new file mode 100644 (file)
index 0000000..d221b90
--- /dev/null
@@ -0,0 +1,1020 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+
+#include <ico-uxf-weston-plugin/ico_window_mgr-client-protocol.h>
+
+#include "ico-window-manager.h"
+#include "layer.h"
+#include "output.h"
+#include "animation.h"
+#include "window.h"
+#include "window-manager.h"
+#include "area.h"
+
+#define MAX_COORDINATE       16383
+
+#define SURFACE_TO_NODE(s)   (((s) >> 16) & 0xFF)
+#define SURFACE_TO_HOST(s)   (((s) >> 24) & 0xFF)
+
+struct mrp_ico_window_manager_s {
+    MRP_WAYLAND_WINDOW_MANAGER_COMMON;
+};
+
+
+static bool window_manager_constructor(mrp_wayland_t *,mrp_wayland_object_t *);
+
+static void window_created_callback(void *, struct ico_window_mgr *, uint32_t,
+                                    const char *,int32_t,const char *,int32_t);
+static void window_name_callback(void *, struct ico_window_mgr *,
+                                 uint32_t, const char *);
+static void window_destroyed_callback(void *,struct ico_window_mgr *,uint32_t);
+static void window_visible_callback(void *, struct ico_window_mgr *, uint32_t,
+                                    int32_t, int32_t, int32_t);
+static void window_configure_callback(void *, struct ico_window_mgr *,uint32_t,
+                                      uint32_t, int32_t, uint32_t, int32_t,
+                                      int32_t, int32_t,int32_t, int32_t);
+static void window_active_callback(void *, struct ico_window_mgr *, uint32_t,
+                                   int32_t);
+static void layer_visible_callback(void *, struct ico_window_mgr *,
+                                   uint32_t, int32_t);
+static void app_surfaces_callback(void *, struct ico_window_mgr *,
+                                  const char *, int32_t, struct wl_array *);
+static void map_surface_callback(void *, struct ico_window_mgr *, int32_t,
+                                 uint32_t, uint32_t, uint32_t,
+                                 int32_t,int32_t, int32_t, uint32_t);
+
+
+static void layer_request(mrp_wayland_layer_t *,
+                          mrp_wayland_layer_update_t *);
+
+static mrp_wayland_window_t *find_window(mrp_ico_window_manager_t *, int32_t,
+                                         const char *);
+static int32_t set_window_animation(mrp_wayland_window_t *,
+                                    mrp_wayland_animation_type_t,
+                                    mrp_wayland_animation_t *);
+static void set_window_area(mrp_wayland_window_t *,
+                            mrp_wayland_window_update_t *,
+                            mrp_wayland_animation_t *);
+static void set_window_geometry(mrp_wayland_window_t *,
+                                mrp_wayland_window_update_t *,
+                                mrp_wayland_animation_t *);
+static void set_window_alignment(mrp_wayland_window_t *,
+                                 mrp_wayland_window_update_t *);
+static void set_window_visible(mrp_wayland_window_t *,
+                               mrp_wayland_window_update_t *,
+                               mrp_wayland_animation_t *);
+static void set_window_active(mrp_wayland_window_t *,
+                              mrp_wayland_window_update_t *);
+static void set_window_mapped(mrp_wayland_window_t *,
+                              mrp_wayland_window_update_t *,
+                              uint32_t);
+static void set_window_layer(mrp_wayland_window_t *,
+                             mrp_wayland_window_update_t *);
+static void window_request(mrp_wayland_window_t *,
+                           mrp_wayland_window_update_t *,
+                           mrp_wayland_animation_t *, uint32_t);
+
+static mrp_wayland_layer_type_t get_layer_type(uint32_t);
+
+
+bool mrp_ico_window_manager_register(mrp_wayland_t *wl)
+{
+    mrp_wayland_factory_t factory;
+
+    factory.size = sizeof(mrp_ico_window_manager_t);
+    factory.interface = &ico_window_mgr_interface;
+    factory.constructor = window_manager_constructor;
+    factory.destructor = NULL;
+
+    mrp_wayland_register_interface(wl, &factory);
+
+    return true;
+}
+
+static bool window_manager_constructor(mrp_wayland_t *wl,
+                                       mrp_wayland_object_t *obj)
+{
+    static struct ico_window_mgr_listener listener =  {
+        .window_created   = window_created_callback,
+        .window_name      = window_name_callback,
+        .window_destroyed = window_destroyed_callback,
+        .window_visible   = window_visible_callback,
+        .window_configure = window_configure_callback,
+        .window_active    = window_active_callback,
+        .layer_visible    = layer_visible_callback,
+        .app_surfaces     = app_surfaces_callback,
+        .map_surface      = map_surface_callback
+    };
+
+    mrp_ico_window_manager_t *wm = (mrp_ico_window_manager_t *)obj;
+    int sts;
+
+    MRP_ASSERT(wm, "invalid argument");
+
+    wm->layer_request = layer_request;
+    wm->window_request = window_request;
+
+    sts = ico_window_mgr_add_listener((struct ico_window_mgr *)wm->proxy,
+                                      &listener, wm);
+
+    if (sts < 0)
+        return false;
+
+    ico_window_mgr_declare_manager((struct ico_window_mgr *)wm->proxy,
+                                   ICO_WINDOW_MGR_DECLARE_MANAGER_MANAGER);
+
+    mrp_wayland_register_window_manager(wl, (mrp_wayland_window_manager_t*)wm);
+
+    return true;
+}
+
+
+static void window_created_callback(void *data,
+                                    struct ico_window_mgr *ico_window_mgr,
+                                    uint32_t surfaceid,
+                                    const char *winname,
+                                    int32_t pid,
+                                    const char *appid,
+                                    int32_t layertype)
+{
+    mrp_ico_window_manager_t *wm = (mrp_ico_window_manager_t *)data;
+    mrp_wayland_t *wl;
+    mrp_wayland_window_update_t u;
+
+    MRP_ASSERT(wm && wm->interface && wm->interface->wl, "invalid argument");
+    MRP_ASSERT(ico_window_mgr == (struct ico_window_mgr *)wm->proxy,
+               "confused with data structures");
+
+    wl = wm->interface->wl;
+
+    memset(&u, 0, sizeof(u));
+    u.mask = MRP_WAYLAND_WINDOW_SURFACEID_MASK |
+             MRP_WAYLAND_WINDOW_NAME_MASK      |
+             MRP_WAYLAND_WINDOW_APPID_MASK     |
+             MRP_WAYLAND_WINDOW_PID_MASK       |
+             MRP_WAYLAND_WINDOW_LAYERTYPE_MASK ;
+
+    u.surfaceid = surfaceid;
+    u.name = winname ? winname : "";
+    u.appid = appid ? appid : "";
+    u.pid = pid;
+    u.layertype = get_layer_type(layertype);
+
+    mrp_debug("surfaceid=%d, winname='%s' pid=%d appid='%s' layertype='%d'",
+              u.surfaceid, u.name, u.pid, u.appid, u.layertype);
+
+    mrp_wayland_window_create(wl, &u);
+}
+
+static void window_name_callback(void *data,
+                                 struct ico_window_mgr *ico_window_mgr,
+                                 uint32_t surfaceid,
+                                 const char *winname)
+{
+    mrp_ico_window_manager_t *wm = (mrp_ico_window_manager_t *)data;
+    mrp_wayland_window_t *win;
+    mrp_wayland_window_update_t u;
+
+    MRP_ASSERT(wm && wm->interface, "invalid argument");
+    MRP_ASSERT(ico_window_mgr == (struct ico_window_mgr *)wm->proxy,
+               "confused with data structures");
+
+    if (!winname) {
+        mrp_log_error("Missing window name in %s()", __FUNCTION__);
+        return;
+    }
+
+    mrp_debug("surfaceid=%d, winname='%s'", surfaceid, winname);
+
+    if (!(win = find_window(wm, surfaceid, "update")))
+        return;
+
+    memset(&u, 0, sizeof(u));
+    u.mask = MRP_WAYLAND_WINDOW_NAME_MASK;
+    u.name = winname;
+
+    mrp_wayland_window_update(win, MRP_WAYLAND_WINDOW_NAMECHANGE, &u);
+}
+
+static void window_destroyed_callback(void *data,
+                                      struct ico_window_mgr *ico_window_mgr,
+                                      uint32_t surfaceid)
+{
+    mrp_ico_window_manager_t *wm = (mrp_ico_window_manager_t *)data;
+    mrp_wayland_window_t *win;
+
+    MRP_ASSERT(wm && wm->interface, "invalid argument");
+    MRP_ASSERT(ico_window_mgr == (struct ico_window_mgr *)wm->proxy,
+               "confused with data structures");
+
+    mrp_debug("surfaceid=%d", surfaceid);
+
+    if (!(win = find_window(wm, surfaceid, "destruction")))
+        return;
+
+    mrp_wayland_window_destroy(win);
+}
+
+static void window_visible_callback(void *data,
+                                    struct ico_window_mgr *ico_window_mgr,
+                                    uint32_t surfaceid,
+                                    int32_t visible,
+                                    int32_t raise,
+                                    int32_t hint)
+{
+    mrp_ico_window_manager_t *wm = (mrp_ico_window_manager_t *)data;
+    mrp_wayland_window_t *win;
+    mrp_wayland_window_update_t u;
+
+    MRP_UNUSED(hint);
+
+    MRP_ASSERT(wm && wm->interface, "invalid argument");
+    MRP_ASSERT(ico_window_mgr == (struct ico_window_mgr *)wm->proxy,
+               "confused with data structures");
+
+    mrp_debug("surfaceid=%d visible=%d raise=%d hint=%d",
+              surfaceid, visible, raise, hint);
+
+    if (!(win = find_window(wm, surfaceid, "visibility update")))
+        return;
+
+    memset(&u, 0, sizeof(u));
+    if (visible != ICO_WINDOW_MGR_V_NOCHANGE) {
+        u.mask |= MRP_WAYLAND_WINDOW_VISIBLE_MASK;
+        u.visible = visible ? true : false;
+    }
+    if (raise != ICO_WINDOW_MGR_V_NOCHANGE) {
+        u.mask |= MRP_WAYLAND_WINDOW_RAISE_MASK;
+        u.raise = raise ? true : false;
+    }
+
+    if (u.mask)
+        mrp_wayland_window_update(win, MRP_WAYLAND_WINDOW_VISIBLE, &u);
+    else
+        mrp_debug("nothing to do");
+}
+
+static void window_configure_callback(void *data,
+                                      struct ico_window_mgr *ico_window_mgr,
+                                      uint32_t surfaceid,
+                                      uint32_t node,
+                                      int32_t layertype,
+                                      uint32_t layer,
+                                      int32_t x,
+                                      int32_t y,
+                                      int32_t width,
+                                      int32_t height,
+                                      int32_t hint)
+{
+    mrp_ico_window_manager_t *wm = (mrp_ico_window_manager_t *)data;
+    mrp_wayland_window_t *win;
+    mrp_wayland_t *wl;
+    mrp_wayland_window_update_t u;
+
+    MRP_UNUSED(layertype);
+    MRP_UNUSED(hint);
+
+    MRP_ASSERT(wm && wm->interface && wm->interface->wl, "invalid argument");
+    MRP_ASSERT(ico_window_mgr == (struct ico_window_mgr *)wm->proxy,
+               "confused with data structures");
+
+    wl = wm->interface->wl;
+
+    mrp_debug("surfaceid=%d node=%u layertype=%d layer=%u position=%d,%d "
+              "size=%dx%d hint=%d", surfaceid, node, layertype, layer,
+              x,y, width,height, hint);
+
+    if (!(win = find_window(wm, surfaceid, "configuration update")))
+        return;
+
+    memset(&u, 0, sizeof(u));
+    u.mask = MRP_WAYLAND_WINDOW_NODEID_MASK    |
+             MRP_WAYLAND_WINDOW_LAYERTYPE_MASK ;
+    u.nodeid = node;
+    u.layertype = layertype;
+
+    if (hint == ICO_WINDOW_MGR_HINT_CHANGE) {
+        if (x <= MAX_COORDINATE) {
+            u.mask |= MRP_WAYLAND_WINDOW_X_MASK;
+            u.x = x;
+        }
+        if (y <= MAX_COORDINATE) {
+            u.mask |= MRP_WAYLAND_WINDOW_Y_MASK;
+            u.y = y;
+        }
+        if (width <= MAX_COORDINATE) {
+            u.mask |= MRP_WAYLAND_WINDOW_WIDTH_MASK;
+            u.width = width;
+        }
+        if (height <= MAX_COORDINATE) {
+            u.mask |= MRP_WAYLAND_WINDOW_HEIGHT_MASK;
+            u.height = height;
+        }
+    }
+
+    if (!(u.layer = mrp_wayland_layer_find(wl, layer)))
+        mrp_log_error("can't find layer %u", layer);
+    else
+        u.mask |= MRP_WAYLAND_WINDOW_LAYER_MASK;
+
+    mrp_wayland_window_update(win, MRP_WAYLAND_WINDOW_CONFIGURE, &u);
+}
+
+static void window_active_callback(void *data,
+                                   struct ico_window_mgr *ico_window_mgr,
+                                   uint32_t surfaceid,
+                                   int32_t active)
+{
+    mrp_ico_window_manager_t *wm = (mrp_ico_window_manager_t *)data;
+    mrp_wayland_window_t *win;
+    mrp_wayland_window_update_t u;
+
+    MRP_ASSERT(wm && wm->interface, "invalid argument");
+    MRP_ASSERT(ico_window_mgr == (struct ico_window_mgr *)wm->proxy,
+               "confused with data structures");
+
+    mrp_debug("surfaceid=%u active=%d", surfaceid, active);
+
+    if (!(win = find_window(wm, surfaceid, "state update")))
+        return;
+
+    memset(&u, 0, sizeof(u));
+    u.mask = MRP_WAYLAND_WINDOW_ACTIVE_MASK;
+    u.active = 0;
+
+    if ((active & MRP_WAYLAND_WINDOW_ACTIVE_POINTER))
+        u.active |= ICO_WINDOW_MGR_ACTIVE_POINTER;
+    if ((active & MRP_WAYLAND_WINDOW_ACTIVE_KEYBOARD))
+        u.active |= ICO_WINDOW_MGR_ACTIVE_KEYBOARD;
+    if ((active & MRP_WAYLAND_WINDOW_ACTIVE_SELECTED))
+        u.active |= ICO_WINDOW_MGR_ACTIVE_SELECTED;
+
+    mrp_wayland_window_update(win, MRP_WAYLAND_WINDOW_ACTIVE, &u);
+}
+
+static void layer_visible_callback(void *data,
+                                   struct ico_window_mgr *ico_window_mgr,
+                                   uint32_t layerid,
+                                   int32_t visible)
+{
+    mrp_ico_window_manager_t *wm = (mrp_ico_window_manager_t *)data;
+    mrp_wayland_t *wl;
+    mrp_wayland_layer_t *layer;
+    mrp_wayland_layer_update_t u;
+
+    MRP_ASSERT(wm && wm->interface && wm->interface->wl, "invalid argument");
+    MRP_ASSERT(ico_window_mgr == (struct ico_window_mgr *)wm->proxy,
+               "confused with data structures");
+
+    wl = wm->interface->wl;
+
+    mrp_debug("layerid=%u visible=%d", layerid, visible);
+
+    memset(&u, 0, sizeof(u));
+    u.mask = MRP_WAYLAND_WINDOW_VISIBLE_MASK;
+    u.visible = visible;
+
+    if (!(layer = mrp_wayland_layer_find(wl, layerid))) {
+        mrp_log_error("can't find layer %u", layerid);
+        return;
+    }
+
+    mrp_wayland_layer_update(layer, MRP_WAYLAND_LAYER_VISIBLE, &u);
+}
+
+static void app_surfaces_callback(void *data,
+                                  struct ico_window_mgr *ico_window_mgr,
+                                  const char *appid,
+                                  int32_t pid,
+                                  struct wl_array *surfaces)
+{
+    mrp_ico_window_manager_t *wm = (mrp_ico_window_manager_t *)data;
+
+    MRP_UNUSED(pid);
+    MRP_UNUSED(surfaces);
+
+    MRP_ASSERT(wm, "invalid argument");
+    MRP_ASSERT(ico_window_mgr == (struct ico_window_mgr *)wm->proxy,
+               "confused with data structures");
+
+    mrp_debug("app '%s' surfaces:",
+              appid);
+}
+
+static void map_surface_callback(void *data,
+                                 struct ico_window_mgr *ico_window_mgr,
+                                 int32_t event,
+                                 uint32_t surfaceid,
+                                 uint32_t type,
+                                 uint32_t target,
+                                 int32_t width,
+                                 int32_t height,
+                                 int32_t stride,
+                                 uint32_t format)
+{
+    mrp_ico_window_manager_t *wm = (mrp_ico_window_manager_t *)data;
+
+    MRP_UNUSED(event);
+    MRP_UNUSED(type);
+    MRP_UNUSED(target);
+    MRP_UNUSED(width);
+    MRP_UNUSED(height);
+    MRP_UNUSED(stride);
+    MRP_UNUSED(format);
+
+    MRP_ASSERT(wm, "invalid argument");
+    MRP_ASSERT(ico_window_mgr == (struct ico_window_mgr *)wm->proxy,
+               "confused with data structures");
+
+    mrp_debug("event=%d surfaceid=%u type=%d target=%d size=%dx%d stride=%d "
+              "format=%u", event, surfaceid, type, target, width,height,
+              stride, format);
+}
+
+static void set_layer_visible(mrp_wayland_layer_t *layer,
+                              mrp_wayland_layer_update_t *u)
+{
+    struct ico_window_mgr *ico_window_mgr;
+    mrp_wayland_layer_update_mask_t mask;
+    int32_t visible;
+    bool need_visibility_change;
+
+    ico_window_mgr = (struct ico_window_mgr *)layer->wm->proxy;
+    mask = u->mask;
+
+    need_visibility_change = false;
+    if (!(mask & MRP_WAYLAND_LAYER_VISIBLE_MASK) ||
+        (u->visible && layer->visible) || (!u->visible && !layer->visible))
+    {
+        visible = ICO_WINDOW_MGR_V_NOCHANGE;
+    }
+    else {
+        visible = u->visible ? ICO_WINDOW_MGR_VISIBLE_SHOW :
+                               ICO_WINDOW_MGR_VISIBLE_HIDE;
+        need_visibility_change = true;
+    }
+
+    if (!need_visibility_change) {
+        mrp_debug("nothing to do");
+        return;
+    }
+
+    mrp_debug("calling ico_window_mgr_set_layer_visible(layer=%d, visible=%d)",
+              layer->layerid, visible);
+
+    ico_window_mgr_set_layer_visible(ico_window_mgr, layer->layerid, visible);
+}
+
+static void layer_request(mrp_wayland_layer_t *layer,
+                          mrp_wayland_layer_update_t *u)
+{
+    mrp_wayland_t *wl;
+    mrp_wayland_layer_update_mask_t mask;
+    char buf[2048];
+
+    MRP_ASSERT(layer && layer->wm && layer->wm->proxy &&
+               layer->wm->interface && layer->wm->interface->wl,
+               "invalid argument");
+
+    wl = layer->wm->interface->wl;
+    mask = u->mask;
+
+    mrp_wayland_layer_request_print(u, buf, sizeof(buf));
+    mrp_debug("request for layer %d update:%s", layer->layerid, buf);
+
+    while (mask) {
+        if ((mask & MRP_WAYLAND_LAYER_VISIBLE_MASK)) {
+            set_layer_visible(layer, u);
+            mask &= ~MRP_WAYLAND_LAYER_VISIBLE_MASK;
+        }
+        else {
+            mask = 0;
+        }
+    }
+
+    mrp_wayland_flush(wl);
+}
+
+
+static mrp_wayland_window_t *find_window(mrp_ico_window_manager_t *wm,
+                                         int32_t surfaceid,
+                                         const char *operation)
+{
+    mrp_wayland_t *wl;
+    mrp_wayland_window_t *win = NULL;
+
+    if (!(wm->interface) || !(wl = wm->interface->wl) ||
+        !(win = mrp_wayland_window_find(wl, surfaceid)))
+    {
+        mrp_log_error("window %d not found. No %s", surfaceid, operation);
+    }
+
+    return win;
+}
+
+static int32_t set_window_animation(mrp_wayland_window_t *win,
+                                    mrp_wayland_animation_type_t type,
+                                    mrp_wayland_animation_t *anims)
+{
+    static int32_t ico_types[MRP_WAYLAND_ANIMATION_MAX] = {
+        [MRP_WAYLAND_ANIMATION_HIDE]   = ICO_WINDOW_MGR_ANIMATION_TYPE_HIDE,
+        [MRP_WAYLAND_ANIMATION_SHOW]   = ICO_WINDOW_MGR_ANIMATION_TYPE_SHOW,
+        [MRP_WAYLAND_ANIMATION_MOVE]   = ICO_WINDOW_MGR_ANIMATION_TYPE_MOVE,
+        [MRP_WAYLAND_ANIMATION_RESIZE] = ICO_WINDOW_MGR_ANIMATION_TYPE_RESIZE
+    };
+
+    struct ico_window_mgr *ico_window_mgr;
+    mrp_wayland_animation_t *a;
+    int32_t flags;
+
+    ico_window_mgr = (struct ico_window_mgr *)win->wm->proxy;
+    flags = ICO_WINDOW_MGR_FLAGS_NO_CONFIGURE;
+
+    if (anims && type >= 0 && type < MRP_WAYLAND_ANIMATION_MAX) {
+        a = anims + type;
+
+        if (a->name && a->name[0] && a->time > 0) {
+            mrp_debug("calling ico_window_mgr_set_animation"
+                      "(surfaceid=%d type=%d, animation='%s' time=%d)",
+                      win->surfaceid, ico_types[type], a->name, a->time);
+
+            ico_window_mgr_set_animation(ico_window_mgr, win->surfaceid,
+                                         ico_types[type], a->name, a->time);
+            flags = ICO_WINDOW_MGR_FLAGS_ANIMATION;
+        }
+    }
+
+    return flags;
+}
+
+static void set_window_area(mrp_wayland_window_t *win,
+                            mrp_wayland_window_update_t *u,
+                            mrp_wayland_animation_t *anims)
+{
+    mrp_wayland_area_t *area;
+    mrp_wayland_output_t *output;
+
+    if (!(area = u->area)) {
+        mrp_log_error("system-controller: request for area change but "
+                      "no area defined");
+        return;
+    }
+
+    output = area->output;
+
+    MRP_ASSERT(output, "confused withdata structures");
+
+    if (win->nodeid != output->outputid) {
+        u->mask |= MRP_WAYLAND_WINDOW_NODEID_MASK;
+        u->nodeid = output->outputid;
+    }
+
+    u->mask |= MRP_WAYLAND_WINDOW_POSITION_MASK | MRP_WAYLAND_WINDOW_SIZE_MASK;
+
+    u->x = area->x;
+    u->y = area->y;
+
+    u->width  = area->width;
+    u->height = area->height;
+
+    set_window_geometry(win, u, anims);
+}
+
+
+static void set_window_geometry(mrp_wayland_window_t *win,
+                                mrp_wayland_window_update_t *u,
+                                mrp_wayland_animation_t *anims)
+{
+    struct ico_window_mgr *ico_window_mgr;
+    mrp_wayland_window_update_mask_t mask;
+    int32_t node;
+    int32_t x, y;
+    int32_t width, height;
+    int32_t flags;
+    bool first_time;
+    bool need_nodechanging;
+    bool need_positioning;
+    bool need_resizing;
+
+    ico_window_mgr = (struct ico_window_mgr *)win->wm->proxy;
+    mask = u->mask;
+    flags = ICO_WINDOW_MGR_FLAGS_NO_CONFIGURE;
+    first_time = win->nodeid < 0;
+
+    node = (mask & MRP_WAYLAND_WINDOW_NODEID_MASK) ? u->nodeid : win->nodeid;
+    if (node < 0)
+        node = SURFACE_TO_NODE(win->surfaceid);
+    need_nodechanging = (mask & MRP_WAYLAND_WINDOW_NODEID_MASK) ||
+                        node != win->nodeid;
+
+    need_positioning = false;
+    if (!(mask & MRP_WAYLAND_WINDOW_X_MASK) || (u->x == win->x)) {
+        if (!first_time)
+            x = ICO_WINDOW_MGR_V_NOCHANGE;
+        else {
+            x = win->x;
+            need_positioning = true;
+        }
+    }
+    else {
+        x = u->x;
+        need_positioning = true;
+    }
+    if (!(mask & MRP_WAYLAND_WINDOW_Y_MASK) || (u->y == win->y)) {
+        if (!first_time)
+            y = ICO_WINDOW_MGR_V_NOCHANGE;
+        else {
+            y = win->y;
+            need_positioning = true;
+        }
+    }
+    else {
+        y = u->y;
+        need_positioning = true;
+    }
+
+    need_resizing = false;
+    if (!(mask & MRP_WAYLAND_WINDOW_WIDTH_MASK) || (u->width == win->width)) {
+        if (!first_time)
+            width = ICO_WINDOW_MGR_V_NOCHANGE;
+        else {
+            width = win->width;
+            need_positioning = true;
+        }
+    }
+    else {
+        width = u->width;
+        need_resizing = true;
+    }
+    if (!(mask&MRP_WAYLAND_WINDOW_HEIGHT_MASK) || (u->height == win->height)) {
+        if (!first_time)
+            height = ICO_WINDOW_MGR_V_NOCHANGE;
+        else {
+            height = win->height;
+            need_positioning = true;
+        }
+    }
+    else {
+        height = u->height;
+        need_resizing = true;
+    }
+
+    if (!need_nodechanging && !need_positioning && !need_resizing) {
+        mrp_debug("nothing to do");
+        return;
+    }
+
+    flags = ICO_WINDOW_MGR_FLAGS_NO_CONFIGURE;
+    if (need_positioning)
+        flags |= set_window_animation(win, MRP_WAYLAND_ANIMATION_MOVE, anims);
+    if (need_resizing)
+        flags |= set_window_animation(win, MRP_WAYLAND_ANIMATION_RESIZE,anims);
+    if ((flags & ~ICO_WINDOW_MGR_FLAGS_NO_CONFIGURE))
+        flags &= ~ICO_WINDOW_MGR_FLAGS_NO_CONFIGURE;
+
+    mrp_debug("calling ico_window_mgr_set_positionsize"
+              "(surfaceid=%d, node=%u position=%d,%d size=%dx%d flags=%d)",
+              win->surfaceid, node, x,y, width,height, flags);
+
+    ico_window_mgr_set_positionsize(ico_window_mgr, win->surfaceid, node,
+                                    x,y, width,height, flags);
+}
+
+static void set_window_alignment(mrp_wayland_window_t *win,
+                                 mrp_wayland_window_update_t *u)
+{
+    struct ico_window_mgr *ico_window_mgr;
+    mrp_wayland_area_t *area;
+    uint32_t attrs;
+
+    ico_window_mgr = (struct ico_window_mgr *)win->wm->proxy;
+
+    if (!(area = u->area)) {
+        mrp_log_error("attempt to set NULL area");
+        return;
+    }
+
+    if (win->area) {
+        if (win->area->keepratio == area->keepratio &&
+            win->area->align == area->align)
+        {
+            mrp_debug("nothing to do");
+            return;
+        }
+    }
+
+    win->area = area;
+
+    if (!area->keepratio)
+        attrs = 0;
+    else {
+        attrs = ICO_WINDOW_MGR_ATTR_FIXED_ASPECT;
+
+        switch ((area->align & MRP_WAYLAND_AREA_ALIGN_HMASK)) {
+        case MRP_WAYLAND_AREA_ALIGN_LEFT:
+            attrs |= ICO_WINDOW_MGR_ATTR_ALIGN_LEFT;
+            break;
+        case MRP_WAYLAND_AREA_ALIGN_RIGHT:
+            attrs |= ICO_WINDOW_MGR_ATTR_ALIGN_RIGHT;
+            break;
+        default:
+            break;
+        }
+
+        switch ((area->align & MRP_WAYLAND_AREA_ALIGN_VMASK)) {
+        case MRP_WAYLAND_AREA_ALIGN_TOP:
+            attrs |= ICO_WINDOW_MGR_ATTR_ALIGN_TOP;
+            break;
+        case MRP_WAYLAND_AREA_ALIGN_BOTTOM:
+            attrs |= ICO_WINDOW_MGR_ATTR_ALIGN_BOTTOM;
+            break;
+        default:
+            break;
+        }
+    }
+
+    mrp_debug("calling ico_window_mgr_set_attributes(surfaceid=%d attrs=0x%x)",
+              win->surfaceid, attrs);
+
+    ico_window_mgr_set_attributes(ico_window_mgr, win->surfaceid, attrs);
+
+    return;
+}
+
+static void set_window_visible(mrp_wayland_window_t *win,
+                               mrp_wayland_window_update_t *u,
+                               mrp_wayland_animation_t *anims)
+{
+    struct ico_window_mgr *ico_window_mgr;
+    mrp_wayland_window_update_mask_t mask;
+    mrp_wayland_animation_type_t anim_type;
+    int32_t visible;
+    int32_t raise;
+    int32_t flags;
+    bool need_visibility_change;
+    bool need_raising;
+
+    ico_window_mgr = (struct ico_window_mgr *)win->wm->proxy;
+    mask = u->mask;
+
+    need_visibility_change = false;
+    if (!(mask & MRP_WAYLAND_WINDOW_VISIBLE_MASK) ||
+        (u->visible && win->visible) || (!u->visible && !win->visible))
+    {
+        visible = ICO_WINDOW_MGR_V_NOCHANGE;
+        anim_type = 0;
+    }
+    else {
+        visible = u->visible ? ICO_WINDOW_MGR_VISIBLE_SHOW :
+                               ICO_WINDOW_MGR_VISIBLE_HIDE;
+        anim_type = visible ? MRP_WAYLAND_ANIMATION_SHOW :
+                              MRP_WAYLAND_ANIMATION_HIDE;
+        win->visible = u->visible;
+        need_visibility_change = true;
+    }
+
+    need_raising = false;
+    if (!(mask & MRP_WAYLAND_WINDOW_RAISE_MASK) ||
+        (u->raise && win->raise) || (!u->raise && !win->raise))
+    {
+        raise = ICO_WINDOW_MGR_V_NOCHANGE;
+    }
+    else {
+        raise = u->raise ? ICO_WINDOW_MGR_RAISE_RAISE :
+                           ICO_WINDOW_MGR_RAISE_LOWER;
+        win->raise = u->raise;
+        need_raising = true;
+    }
+
+    if (!need_visibility_change && !need_raising) {
+        mrp_debug("nothing to do");
+        return;
+    }
+
+    if (need_visibility_change)
+        flags = set_window_animation(win, anim_type, anims);
+    else
+        flags = ICO_WINDOW_MGR_FLAGS_NO_CONFIGURE;
+
+    mrp_debug("calling ico_window_mgr_set_visible"
+              "(surfaceid=%d, visible=%d, raise=%d, flags=%d)",
+              win->surfaceid, visible, raise, flags);
+
+    ico_window_mgr_set_visible(ico_window_mgr, win->surfaceid,
+                               visible, raise, flags);
+}
+
+static void set_window_active(mrp_wayland_window_t *win,
+                              mrp_wayland_window_update_t *u)
+{
+    struct ico_window_mgr *ico_window_mgr;
+    int32_t active;
+
+    ico_window_mgr = (struct ico_window_mgr *)win->wm->proxy;
+    active = 0;
+
+    if (u->active == win->active)
+        mrp_debug("nothing to do");
+    else {
+        if ((u->active & MRP_WAYLAND_WINDOW_ACTIVE_POINTER))
+            active |= ICO_WINDOW_MGR_ACTIVE_POINTER;
+        if ((u->active & MRP_WAYLAND_WINDOW_ACTIVE_KEYBOARD))
+            active |= ICO_WINDOW_MGR_ACTIVE_KEYBOARD;
+        if ((u->active & MRP_WAYLAND_WINDOW_ACTIVE_SELECTED))
+            active |= ICO_WINDOW_MGR_ACTIVE_SELECTED;
+
+        mrp_debug("calling ico_window_mgr_set_active"
+                  "(surfaceid=%d, active=0x%x)",
+                  win->surfaceid, active);
+
+        ico_window_mgr_set_active(ico_window_mgr, win->surfaceid, active);
+    }
+}
+
+static void set_window_mapped(mrp_wayland_window_t *win,
+                              mrp_wayland_window_update_t *u,
+                              uint32_t framerate)
+{
+    struct ico_window_mgr *ico_window_mgr;
+
+    ico_window_mgr = (struct ico_window_mgr *)win->wm->proxy;
+
+    if ((u->mapped && win->mapped) || (!u->mapped && !win->mapped))
+        mrp_debug("nothing to do");
+    else {
+        if (u->mapped) {
+            mrp_debug("calling ico_window_mgr_map_surface"
+                      "(surfaceid=%d, framerate=%u)",
+                      win->surfaceid, framerate);
+
+            ico_window_mgr_map_surface(ico_window_mgr, win->surfaceid,
+                                       framerate);
+        }
+        else {
+            mrp_debug("calling ico_window_mgr_unmap_surface(surfaceid=%d)",
+                      win->surfaceid);
+
+            ico_window_mgr_unmap_surface(ico_window_mgr, win->surfaceid);
+        }
+    }
+}
+
+static void set_window_layer(mrp_wayland_window_t *win,
+                             mrp_wayland_window_update_t *u)
+{
+    struct ico_window_mgr *ico_window_mgr;
+    uint32_t layer;
+
+    ico_window_mgr = (struct ico_window_mgr *)win->wm->proxy;
+
+    if (win->layer && (u->layer == win->layer)) {
+        mrp_debug("nothing to do");
+    }
+    else {
+        layer = u->layer->layerid;
+
+        mrp_debug("calling ico_window_mgr_set_window_layer"
+                  "(surfaceid=%d, layer=%u)", win->surfaceid, layer);
+
+        ico_window_mgr_set_window_layer(ico_window_mgr, win->surfaceid, layer);
+    }
+}
+
+static void window_request(mrp_wayland_window_t *win,
+                           mrp_wayland_window_update_t *u,
+                           mrp_wayland_animation_t *anims,
+                           uint32_t framerate)
+{
+    static mrp_wayland_window_update_mask_t visible_mask =
+        MRP_WAYLAND_WINDOW_VISIBLE_MASK |
+        MRP_WAYLAND_WINDOW_RAISE_MASK   ;
+    static mrp_wayland_window_update_mask_t active_mask =
+        MRP_WAYLAND_WINDOW_ACTIVE_MASK;
+    static mrp_wayland_window_update_mask_t mapped_mask =
+        MRP_WAYLAND_WINDOW_MAPPED_MASK;
+    static mrp_wayland_window_update_mask_t area_mask =
+        MRP_WAYLAND_WINDOW_AREA_MASK;
+    static mrp_wayland_window_update_mask_t geometry_mask =
+        MRP_WAYLAND_WINDOW_NODEID_MASK   |
+        MRP_WAYLAND_WINDOW_POSITION_MASK |
+        MRP_WAYLAND_WINDOW_SIZE_MASK     ;
+    static mrp_wayland_window_update_mask_t layer_mask =
+        MRP_WAYLAND_WINDOW_LAYER_MASK;
+    static mrp_wayland_window_update_mask_t align_mask =
+        MRP_WAYLAND_WINDOW_AREA_MASK;
+
+    mrp_wayland_t *wl;
+    mrp_wayland_window_update_mask_t mask;
+    char wbuf[2048];
+    char abuf[1024];
+
+    MRP_ASSERT(win && win->wm && win->wm->proxy && win->wm->interface &&
+               win->wm->interface->wl, "invalid argument");
+
+    wl = win->wm->interface->wl;
+    mask = u->mask;
+
+    mrp_wayland_window_request_print(u, wbuf, sizeof(wbuf));
+    mrp_wayland_animation_print(anims, abuf, sizeof(abuf));
+    mrp_debug("request for window %d update:%s\n   animations:%s",
+              win->surfaceid, wbuf, abuf);
+
+    while (mask) {
+        if ((mask & layer_mask)) {
+            set_window_layer(win, u);
+            mask &= ~layer_mask;
+        }
+        else if ((mask & mapped_mask)) {
+            set_window_mapped(win, u, framerate);
+            mask &= ~mapped_mask;
+        }
+        else if ((mask & area_mask))  {
+            set_window_area(win, u, anims);
+            mask &= ~(area_mask | geometry_mask);
+        }
+        else if ((mask & geometry_mask)) {
+            set_window_geometry(win, u, anims);
+            mask &= ~geometry_mask;
+        }
+        else if ((mask & align_mask)) {
+            set_window_alignment(win, u);
+            mask &= ~align_mask;
+        }
+        else if ((mask & visible_mask)) {
+            set_window_visible(win, u, anims);
+            mask &= ~visible_mask;
+        }
+        else if ((mask & active_mask)) {
+            set_window_active(win, u);
+            mask &= ~active_mask;
+        }
+        else {
+            mask = 0;
+        }
+    }
+
+    mrp_wayland_flush(wl);
+}
+
+static mrp_wayland_layer_type_t get_layer_type(uint32_t layertype)
+{
+    switch (layertype) {
+
+    case ICO_WINDOW_MGR_LAYERTYPE_BACKGROUND:
+        return MRP_WAYLAND_LAYER_BACKGROUND;
+
+    case ICO_WINDOW_MGR_LAYERTYPE_NORMAL:
+        return MRP_WAYLAND_LAYER_APPLICATION;
+
+    case ICO_WINDOW_MGR_LAYERTYPE_FULLSCREEN:
+    case ICO_WINDOW_MGR_LAYERTYPE_INPUTPANEL:
+        return MRP_WAYLAND_LAYER_INPUT;
+
+    case ICO_WINDOW_MGR_LAYERTYPE_TOUCH:
+        return MRP_WAYLAND_LAYER_TOUCH;
+
+    case ICO_WINDOW_MGR_LAYERTYPE_CURSOR:
+        return MRP_WAYLAND_LAYER_CURSOR;
+
+    case ICO_WINDOW_MGR_LAYERTYPE_STARTUP:
+        return MRP_WAYLAND_LAYER_STARTUP;
+
+    default:
+        return MRP_WAYLAND_LAYER_TYPE_UNKNOWN;
+    }
+}
diff --git a/src/plugins/system-controller/wayland/ico-window-manager.h b/src/plugins/system-controller/wayland/ico-window-manager.h
new file mode 100644 (file)
index 0000000..f918413
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_ICO_WINDOW_MANAGER_H__
+#define __MURPHY_ICO_WINDOW_MANAGER_H__
+
+#include "wayland/wayland.h"
+
+typedef struct mrp_ico_window_manager_s  mrp_ico_window_manager_t;
+
+bool mrp_ico_window_manager_register(mrp_wayland_t *wl);
+
+#endif /* __MURPHY_ICO_WINDOW_MANAGER_H__ */
diff --git a/src/plugins/system-controller/wayland/input-manager.h b/src/plugins/system-controller/wayland/input-manager.h
new file mode 100644 (file)
index 0000000..89703d0
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_WAYLAND_INPUT_MANAGER_H__
+#define __MURPHY_WAYLAND_INPUT_MANAGER_H__
+
+#include <sys/types.h>
+
+#include "wayland/wayland.h"
+
+#define MRP_WAYLAND_INPUT_MANAGER_COMMON                                \
+    MRP_WAYLAND_OBJECT_COMMON
+
+struct mrp_wayland_input_manager_s {
+    MRP_WAYLAND_INPUT_MANAGER_COMMON;
+};
+
+#endif /* __MURPHY_WAYLAND_INPUT_MANAGER_H__ */
diff --git a/src/plugins/system-controller/wayland/layer.c b/src/plugins/system-controller/wayland/layer.c
new file mode 100644 (file)
index 0000000..a5a4fef
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+
+#include "layer.h"
+#include "window-manager.h"
+#include "scripting-wayland.h"
+
+static mrp_wayland_layer_update_mask_t update(mrp_wayland_layer_t *,
+                                              mrp_wayland_layer_update_t *);
+
+
+mrp_wayland_layer_t *mrp_wayland_layer_create(mrp_wayland_t *wl,
+                                              mrp_wayland_layer_update_t *u)
+{
+    mrp_wayland_layer_t *layer;
+    mrp_wayland_layer_update_mask_t mask;
+    char buf[2048];
+
+    MRP_ASSERT(wl && u && (u->mask & MRP_WAYLAND_LAYER_LAYERID_MASK),
+               "invalid argument");
+
+    if (!(layer = mrp_allocz(sizeof(mrp_wayland_layer_t)))) {
+        mrp_log_error("failed to create layer %d: out of memory",
+                      u->layerid);
+        return NULL;
+    }
+
+    layer->wl = wl;
+    layer->wm = wl->wm;
+    layer->layerid =  u->layerid;
+
+    if (!mrp_htbl_insert(wl->layers, &layer->layerid, layer)) {
+        mrp_log_error("failed to create layer: already exists");
+        mrp_free(layer);
+        return NULL;
+    }
+
+    if (!(u->mask & MRP_WAYLAND_LAYER_NAME_MASK)) {
+        snprintf(buf, sizeof(buf), "layer-%d", layer->layerid);
+
+        u->mask |= MRP_WAYLAND_LAYER_NAME_MASK;
+        u->name = buf;
+    }
+
+    mask = update(layer, u);
+
+    if (wl->create_scripting_layers)
+        layer->scripting_data = mrp_wayland_scripting_layer_create_from_c(NULL,
+                                                                        layer);
+    mrp_wayland_layer_print(layer, mask, buf,sizeof(buf));
+    mrp_debug("layer %d created%s", layer->layerid, buf);
+
+    if (wl->layer_update_callback)
+        wl->layer_update_callback(wl, MRP_WAYLAND_LAYER_CREATE, mask, layer);
+
+    return layer;
+}
+
+void mrp_wayland_layer_destroy(mrp_wayland_layer_t *layer)
+{
+    mrp_wayland_t *wl;
+    char buf[1024];
+
+    MRP_ASSERT(layer && layer->wl, "invalid argument");
+
+    wl = layer->wl;
+
+    mrp_wayland_layer_print(layer, MRP_WAYLAND_LAYER_NAME_MASK,
+                            buf, sizeof(buf));
+    mrp_debug("destroying layer %d%s", layer->layerid, buf);
+
+    if (wl->layer_update_callback)
+        wl->layer_update_callback(wl, MRP_WAYLAND_LAYER_DESTROY, 0, layer);
+
+    mrp_free(layer->name);
+
+    if ((void *)layer != mrp_htbl_remove(wl->layers, &layer->layerid, false)) {
+        mrp_log_error("failed to destroy layer %d: confused with "
+                      "data structures", layer->layerid);
+        return;
+    }
+
+    free(layer);
+}
+
+mrp_wayland_layer_t *mrp_wayland_layer_find(mrp_wayland_t *wl, int32_t layerid)
+{
+    MRP_ASSERT(wl, "invalid argument");
+
+    return (mrp_wayland_layer_t*)mrp_htbl_lookup(wl->layers,&layerid);
+}
+
+void mrp_wayland_layer_visibility_request(mrp_wayland_layer_t *layer,
+                                          int32_t visible)
+{
+    mrp_wayland_window_manager_t *wm;
+    mrp_wayland_layer_update_t u;
+
+    MRP_ASSERT(layer && layer->wl, "invalid arguent");
+
+    if (!(wm = layer->wm))
+        mrp_debug("ignoring layer visibility request: no window-manager");
+    else {
+        memset(&u, 0, sizeof(u));
+
+        if (visible >= 0) {
+            u.mask |= MRP_WAYLAND_LAYER_VISIBLE_MASK;
+            u.visible = visible ? true : false;
+        }
+        
+        wm->layer_request(layer, &u);
+    }
+}
+
+void mrp_wayland_layer_request(mrp_wayland_t *wl,mrp_wayland_layer_update_t *u)
+{
+    mrp_wayland_layer_t *layer;
+    mrp_wayland_window_manager_t *wm;
+
+    MRP_ASSERT(wl && u, "invalid arguments");
+
+    if (!(u->mask & MRP_WAYLAND_LAYER_LAYERID_MASK) ||
+        !(layer = mrp_wayland_layer_find(wl, u->layerid)))
+    {
+        mrp_debug("can't find layer %u: request rejected", u->layerid);
+        return;
+    }
+
+    MRP_ASSERT(wl == layer->wl, "confused with data structures");
+
+    if ((wm = layer->wm))
+        wm->layer_request(layer, u);
+}
+
+void mrp_wayland_layer_update(mrp_wayland_layer_t *layer,
+                              mrp_wayland_layer_operation_t oper,
+                              mrp_wayland_layer_update_t *u)
+{
+    mrp_wayland_t *wl;
+    int32_t layerid;
+    mrp_wayland_layer_update_mask_t mask;
+    char buf[2048];
+
+    MRP_ASSERT(layer && layer->wl && u, "invalid argument");
+
+    wl = layer->wl;
+
+    layerid = layer->layerid;
+
+    if ((u->mask & MRP_WAYLAND_LAYER_LAYERID_MASK)) {
+        if (u->layerid != layerid) {
+            mrp_log_error("attempt to change layerid to %d of "
+                          "existing layer %d", u->layerid, layerid);
+            return;
+        }
+    }
+
+    mask = update(layer, u);
+
+    if (!mask)
+        mrp_debug("layer %d update requested but nothing changed", layerid);
+    else {
+        mrp_wayland_layer_print(layer, mask, buf,sizeof(buf));
+        mrp_debug("layer %d updated%s", layerid, buf);
+
+        if (wl->layer_update_callback)
+            wl->layer_update_callback(wl, oper, mask, layer);
+    }
+}
+
+size_t mrp_wayland_layer_print(mrp_wayland_layer_t *layer,
+                               mrp_wayland_layer_update_mask_t mask,
+                               char *buf,
+                               size_t len)
+{
+#define PRINT(fmt, args...) \
+    if (p < e) { p += snprintf(p, e-p, "\n      " fmt , ## args); }
+
+    char *p, *e;
+
+    e = (p = buf) + len;
+
+    *p = 0;
+
+    if ((mask & MRP_WAYLAND_LAYER_NAME_MASK))
+        PRINT("name: '%s'", layer->name);
+    if ((mask & MRP_WAYLAND_LAYER_TYPE_MASK))
+        PRINT("type: %s", mrp_wayland_layer_type_str(layer->type));
+    if ((mask & MRP_WAYLAND_LAYER_VISIBLE_MASK))
+        PRINT("visible: %s", layer->visible ? "yes" : "no");
+
+    return p - buf;
+
+#undef PRINT
+}
+
+size_t mrp_wayland_layer_request_print(mrp_wayland_layer_update_t *u,
+                                       char *buf, size_t len)
+{
+#define PRINT(fmt, args...) \
+    if (p < e) { p += snprintf(p, e-p, "\n      " fmt , ## args); }
+
+    mrp_wayland_layer_update_mask_t mask;
+    char *p, *e;
+
+    mask = u->mask;
+    e = (p = buf) + len;
+
+    *p = 0;
+
+    if ((mask & MRP_WAYLAND_LAYER_NAME_MASK))
+        PRINT("name: '%s'", u->name);
+    if ((mask & MRP_WAYLAND_LAYER_TYPE_MASK))
+        PRINT("type: %s", mrp_wayland_layer_type_str(u->type));
+    if ((mask & MRP_WAYLAND_LAYER_VISIBLE_MASK))
+        PRINT("visible: %s", u->visible ? "yes" : "no");
+
+    return p - buf;
+
+#undef PRINT
+}
+
+const char *
+mrp_wayland_layer_update_mask_str(mrp_wayland_layer_update_mask_t mask)
+{
+    switch (mask) {
+    case MRP_WAYLAND_LAYER_LAYERID_MASK:   return "layerid";
+    case MRP_WAYLAND_LAYER_NAME_MASK:      return "name";
+    case MRP_WAYLAND_LAYER_TYPE_MASK:      return "type";
+    case MRP_WAYLAND_LAYER_VISIBLE_MASK:   return "visible";
+    default:                               return "<unknown>";
+    }
+}
+
+const char *mrp_wayland_layer_type_str(mrp_wayland_layer_type_t type)
+{
+    switch (type) {
+    case MRP_WAYLAND_LAYER_BACKGROUND:   return "background";
+    case MRP_WAYLAND_LAYER_APPLICATION:  return "application";
+    case MRP_WAYLAND_LAYER_INPUT:        return "input";
+    case MRP_WAYLAND_LAYER_TOUCH:        return "touch";
+    case MRP_WAYLAND_LAYER_CURSOR:       return "cursor";
+    case MRP_WAYLAND_LAYER_STARTUP:      return "startup";
+    default:                             return "<unknown>";
+    }
+}
+
+void mrp_wayland_layer_set_scripting_data(mrp_wayland_layer_t *layer,
+                                          void *data)
+{
+    MRP_ASSERT(layer, "Invalid Argument");
+
+    mrp_debug("%sset scripting data", data ? "" : "re");
+
+    layer->scripting_data = data;
+}
+
+
+static mrp_wayland_layer_update_mask_t update(mrp_wayland_layer_t *layer,
+                                              mrp_wayland_layer_update_t *u)
+{
+    mrp_wayland_layer_update_mask_t mask = 0;
+
+    if ((u->mask & MRP_WAYLAND_LAYER_NAME_MASK)) {
+        if (!layer->name || strcmp(u->name, layer->name)) {
+            mask |= MRP_WAYLAND_LAYER_NAME_MASK;
+            mrp_free(layer->name);
+            layer->name = mrp_strdup(u->name);
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_LAYER_TYPE_MASK)) {
+        if (u->type != layer->type) {
+            mask |= MRP_WAYLAND_LAYER_TYPE_MASK;
+            layer->type = u->type;
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_LAYER_VISIBLE_MASK)) {
+        if ((u->visible && !layer->visible)||(!u->visible && layer->visible)) {
+            mask |= MRP_WAYLAND_LAYER_VISIBLE_MASK;
+            layer->visible = u->visible;
+        }
+    }
+
+    return mask;
+}
diff --git a/src/plugins/system-controller/wayland/layer.h b/src/plugins/system-controller/wayland/layer.h
new file mode 100644 (file)
index 0000000..7e6e658
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_WAYLAND_LAYER_H__
+#define __MURPHY_WAYLAND_LAYER_H__
+
+#include <sys/types.h>
+
+#include "wayland/wayland.h"
+
+enum mrp_wayland_layer_type_e {
+    MRP_WAYLAND_LAYER_TYPE_UNKNOWN  = 0,
+    MRP_WAYLAND_LAYER_BACKGROUND,  /* 1 */
+    MRP_WAYLAND_LAYER_APPLICATION, /* 2 */
+    MRP_WAYLAND_LAYER_INPUT,       /* 3 */
+    MRP_WAYLAND_LAYER_TOUCH,       /* 4 */
+    MRP_WAYLAND_LAYER_CURSOR,      /* 5 */
+    MRP_WAYLAND_LAYER_STARTUP,     /* 6 */
+
+    MRP_WAYLAND_LAYER_TYPE_MAX
+};
+
+enum mrp_wayland_layer_operation_e {
+    MRP_WAYLAND_LAYER_OPERATION_NONE = 0,
+    MRP_WAYLAND_LAYER_CREATE,
+    MRP_WAYLAND_LAYER_DESTROY,
+    MRP_WAYLAND_LAYER_VISIBLE
+};
+
+struct mrp_wayland_layer_s {
+    mrp_wayland_t *wl;
+    mrp_wayland_window_manager_t *wm;
+
+    int32_t layerid;
+    char *name;
+    mrp_wayland_layer_type_t type;
+    bool visible;
+
+    void *scripting_data;
+};
+
+
+enum mrp_wayland_layer_update_mask_e {
+    MRP_WAYLAND_LAYER_LAYERID_MASK   = 0x0001,
+    MRP_WAYLAND_LAYER_NAME_MASK      = 0x0002,
+    MRP_WAYLAND_LAYER_TYPE_MASK      = 0x0004,
+    MRP_WAYLAND_LAYER_VISIBLE_MASK   = 0x0008,
+
+    MRP_WAYLAND_LAYER_END_MASK       = 0x0010
+};
+
+
+struct mrp_wayland_layer_update_s {
+    mrp_wayland_layer_update_mask_t mask;
+    int32_t layerid;
+    const char *name;
+    mrp_wayland_layer_type_t type;
+    bool visible;
+};
+
+mrp_wayland_layer_t *mrp_wayland_layer_create(mrp_wayland_t *wl,
+                                              mrp_wayland_layer_update_t *u);
+void mrp_wayland_layer_destroy(mrp_wayland_layer_t *layer);
+
+mrp_wayland_layer_t *mrp_wayland_layer_find(mrp_wayland_t *wl,
+                                            int32_t layerid);
+
+void mrp_wayland_layer_visibility_request(mrp_wayland_layer_t *layer,
+                                          int32_t visible);
+
+void mrp_wayland_layer_request(mrp_wayland_t *wl,
+                               mrp_wayland_layer_update_t *u);
+void mrp_wayland_layer_update(mrp_wayland_layer_t *layer,
+                              mrp_wayland_layer_operation_t oper,
+                              mrp_wayland_layer_update_t *u);
+
+size_t mrp_wayland_layer_print(mrp_wayland_layer_t *layer,
+                               mrp_wayland_layer_update_mask_t mask,
+                               char *buf,
+                               size_t len);
+size_t mrp_wayland_layer_request_print(mrp_wayland_layer_update_t *u,
+                                       char *buf, size_t len);
+
+const char *mrp_wayland_layer_update_mask_str(mrp_wayland_layer_update_mask_t
+                                                                         mask);
+const char *mrp_wayland_layer_type_str(mrp_wayland_layer_type_t type);
+
+void mrp_wayland_layer_set_scripting_data(mrp_wayland_layer_t *layer,
+                                          void *data);
+
+
+#endif /* __MURPHY_WAYLAND_LAYER_H__ */
diff --git a/src/plugins/system-controller/wayland/output.c b/src/plugins/system-controller/wayland/output.c
new file mode 100644 (file)
index 0000000..c77557c
--- /dev/null
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+
+#include "output.h"
+#include "area.h"
+#include "scripting-wayland.h"
+
+typedef struct {
+    mrp_wayland_output_t *output;
+    int count;
+} output_iterator_helper_t;
+
+static bool output_constructor(mrp_wayland_t *, mrp_wayland_object_t *);
+
+static void geometry_callback(void *, struct wl_output *,
+                              int32_t,int32_t, int32_t,int32_t, int32_t,
+                              const char *, const char *, int32_t);
+static void mode_callback(void *, struct wl_output *, uint32_t,
+                          int32_t,int32_t, int32_t);
+static void done_callback(void *, struct wl_output *);
+static void scale_callback(void *, struct wl_output *, int32_t);
+
+static void check_if_ready(mrp_wayland_t *, mrp_wayland_output_t *);
+static int print_area(void *, void *, void *);
+
+
+bool mrp_wayland_output_register(mrp_wayland_t *wl)
+{
+    mrp_wayland_factory_t factory;
+
+    factory.size = sizeof(mrp_wayland_output_t);
+    factory.interface = &wl_output_interface;
+    factory.constructor = output_constructor;
+    factory.destructor = NULL;
+
+    mrp_wayland_register_interface(wl, &factory);
+
+    return true;
+}
+
+mrp_wayland_output_t *mrp_wayland_output_find(mrp_wayland_t *wl,uint32_t index)
+{    
+    MRP_ASSERT(wl, "invalid argument");
+
+    return (mrp_wayland_output_t *)mrp_htbl_lookup(wl->outputs, &index);
+}
+
+void mrp_wayland_output_request(mrp_wayland_t *wl,
+                                mrp_wayland_output_update_t *u)
+{
+    mrp_wayland_output_t *out;
+    mrp_wayland_output_update_mask_t mask;
+    char buf[4096];
+
+    MRP_ASSERT(wl && u, "invalid arguments");
+
+    if (!(u->mask & MRP_WAYLAND_OUTPUT_INDEX_MASK) ||
+        !(out = mrp_wayland_output_find(wl, u->index)))
+    {
+        mrp_debug("can't find output %u: request rejected", u->index);
+        return;
+    }
+
+    mrp_wayland_output_request_print(u, buf, sizeof(buf));
+    mrp_debug("request for output %u update:%s", out->index, buf);
+
+    mask = 0;
+
+    if ((u->mask & MRP_WAYLAND_OUTPUT_OUTPUTID_MASK)) {
+        if (u->outputid < 0) {
+            mrp_log_error("system-controller: refuse to set output ID %d",
+                          u->outputid);
+        }
+        else {
+            if (u->outputid != out->outputid) {
+                mask |= MRP_WAYLAND_OUTPUT_OUTPUTID_MASK;
+                out->outputid = u->outputid;
+            }
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_OUTPUT_NAME_MASK)) {
+        if (u->outputname && strcmp(u->outputname, out->outputname)) {
+            mask |= MRP_WAYLAND_OUTPUT_NAME_MASK;
+            mrp_free(out->outputname);
+            out->outputname = mrp_strdup(u->outputname);
+        }
+    }
+
+    if (wl->output_update_callback) {
+        wl->output_update_callback(wl, MRP_WAYLAND_OUTPUT_USER_REQUEST,
+                                   mask, out);
+    }
+}
+
+static bool output_constructor(mrp_wayland_t *wl, mrp_wayland_object_t *obj)
+{
+    static uint32_t index;
+    static struct wl_output_listener listener =  {
+        .geometry = geometry_callback,
+        .mode     = mode_callback,
+        .done     = done_callback,
+        .scale    = scale_callback
+    };
+
+    char name[256];
+    char buf[4096];
+
+    mrp_wayland_output_t *out = (mrp_wayland_output_t *)obj;
+    int sts;
+
+    MRP_ASSERT(out, "invalid argument");
+
+    snprintf(name, sizeof(name), "%s:%u", wl->display_name, index);
+
+    out->index = index++;
+    out->outputid = -1;
+    out->outputname = mrp_strdup(name);
+
+    if (!mrp_htbl_insert(wl->outputs, &out->index, out)) {
+        mrp_log_error("failed to create output: already exists");
+        mrp_free(out);
+        return NULL;
+    }
+
+    sts = wl_output_add_listener((struct wl_output *)out->proxy,&listener,out);
+
+    if (sts < 0)
+        mrp_log_error("failed to add listener to output %d", out->index);
+    else {
+        if (wl->create_scripting_outputs) {
+            out->scripting_data =
+                mrp_wayland_scripting_output_create_from_c(NULL, out);
+        }
+
+        mrp_wayland_output_print(out, MRP_WAYLAND_OUTPUT_NAME_MASK,
+                                 buf, sizeof(buf));
+        mrp_debug("output %u created%s", out->index, buf);
+
+        if (wl->output_update_callback) {
+            wl->output_update_callback(wl, MRP_WAYLAND_OUTPUT_CREATE,
+                                       MRP_WAYLAND_OUTPUT_NAME_MASK, out);
+        }
+    }
+
+    return (sts < 0) ? false : true;
+}
+
+static void geometry_callback(void *data,
+                              struct wl_output *wl_output,
+                              int32_t pixel_x,
+                              int32_t pixel_y,
+                              int32_t physical_width,
+                              int32_t physical_height,
+                              int32_t subpixel,
+                              const char *make,
+                              const char *model,
+                              int32_t transform)
+{
+#define UPDATE_INTEGER_FIELD(_f,_m)                       \
+    if (out->_f != _f) {                                  \
+        mask |= MRP_WAYLAND_OUTPUT_ ## _m ## _MASK;       \
+        out->_f = _f;                                     \
+    }
+#define UPDATE_STRING_FIELD(_f,_m)                        \
+    if (!out->_f || strcmp(out->_f, _f)) {                \
+        mrp_free((void *)out->_f);                        \
+        mask |= MRP_WAYLAND_OUTPUT_ ## _m ## _MASK;       \
+            out->_f = mrp_strdup(_f ? _f : "<unknown>");  \
+    }
+
+    mrp_wayland_output_t *out = (mrp_wayland_output_t *)data;
+    mrp_wayland_output_update_mask_t mask = 0;
+    mrp_wayland_t *wl;
+    uint32_t rotate;
+    bool flip;
+    int32_t width, height;
+    char buf[4096];
+
+    MRP_UNUSED(transform);
+
+    MRP_ASSERT(out && out->interface && out->interface->wl,"invalid argument");
+    MRP_ASSERT(wl_output == (struct wl_output *)out->proxy,
+               "confused with data structures");
+
+    wl = out->interface->wl;
+
+    mrp_debug("x=%d y=%d width=%d height=%d subpixel=%d make='%s' model='%s' "
+              "transorm=%d", pixel_x,pixel_y, physical_width,physical_height,
+              subpixel, make ? make : "", model ? model : "");
+
+    switch (transform) {
+    default:
+    case WL_OUTPUT_TRANSFORM_NORMAL:       rotate = 0;    flip = false;  break;
+    case WL_OUTPUT_TRANSFORM_90:           rotate = 90;   flip = false;  break;
+    case WL_OUTPUT_TRANSFORM_180:          rotate = 180;  flip = false;  break;
+    case WL_OUTPUT_TRANSFORM_270:          rotate = 270;  flip = false;  break;
+    case WL_OUTPUT_TRANSFORM_FLIPPED:      rotate = 0;    flip = true;   break;
+    case WL_OUTPUT_TRANSFORM_FLIPPED_90:   rotate = 90;   flip = true;   break;
+    case WL_OUTPUT_TRANSFORM_FLIPPED_180:  rotate = 180;  flip = true;   break;
+    case WL_OUTPUT_TRANSFORM_FLIPPED_270:  rotate = 270;  flip = true;   break;
+    };
+
+    UPDATE_INTEGER_FIELD (pixel_x, PIXEL_X);
+    UPDATE_INTEGER_FIELD (pixel_y, PIXEL_Y);
+    UPDATE_INTEGER_FIELD (physical_width, PHYSICAL_WIDTH);
+    UPDATE_INTEGER_FIELD (physical_height, PHYSICAL_HEIGHT);
+    UPDATE_INTEGER_FIELD (subpixel, SUBPIXEL);
+    UPDATE_STRING_FIELD  (make, MAKE);
+    UPDATE_STRING_FIELD  (model, MODEL);
+    UPDATE_INTEGER_FIELD (rotate, ROTATE);
+    UPDATE_INTEGER_FIELD (flip, FLIP);
+
+    if (rotate == 90 || rotate == 270) {
+        if (out->pixel_width > 0 && out->pixel_height > 0) {
+            width = out->pixel_height;
+            height = out->pixel_width;
+
+            UPDATE_INTEGER_FIELD (width, WIDTH);
+            UPDATE_INTEGER_FIELD (height, HEIGHT);
+        }
+    }
+
+    mrp_wayland_output_print(out, mask, buf,sizeof(buf));
+    mrp_debug("output %u configure%s", out->index, buf);
+
+    if (wl->output_update_callback)
+        wl->output_update_callback(wl, MRP_WAYLAND_OUTPUT_CONFIGURE, mask,out);
+
+    check_if_ready(wl, out);
+
+#undef UPDATE_STRING_FIELD
+#undef UPDATE_INTEGER_FIELD
+}
+
+static void mode_callback(void *data,
+                          struct wl_output *wl_output,
+                          uint32_t flags,
+                          int32_t pixel_width,
+                          int32_t pixel_height,
+                          int32_t refresh)
+{
+#define UPDATE_INTEGER_FIELD(_f,_m)                       \
+    if (out->_f != _f) {                                  \
+        mask |= MRP_WAYLAND_OUTPUT_ ## _m ## _MASK;       \
+        out->_f = _f;                                     \
+    }
+#define UPDATE_STRING_FIELD(_f,_m)                        \
+    if (!out->_f || strcmp(out->_f, _f)) {                \
+        mrp_free((void *)out->_f);                        \
+        mask |= MRP_WAYLAND_OUTPUT_ ## _m ## _MASK;       \
+            out->_f = mrp_strdup(_f ? _f : "<unknown>");  \
+    }
+
+    mrp_wayland_output_t *out = (mrp_wayland_output_t *)data;
+    mrp_wayland_output_update_mask_t mask = 0;
+    int32_t width;
+    int32_t height;
+    mrp_wayland_t *wl;
+
+    MRP_ASSERT(out && out->interface && out->interface->wl,"invalid argument");
+    MRP_ASSERT(wl_output == (struct wl_output *)out->proxy,
+               "confused with data structures");
+
+    wl = out->interface->wl;
+
+    mrp_debug("flags=0x%x width=%d height=%d refresh=%d",
+              flags, pixel_width,pixel_height, refresh);
+
+    if (out->rotate == 90 || out->rotate == 270) {
+        width = pixel_height;
+        height = pixel_width;
+    }
+    else {
+        width = pixel_width;
+        height = pixel_height;
+    }
+
+    if (!(flags & WL_OUTPUT_MODE_CURRENT)) {
+        mrp_debug("ignoring mode %dx%d@%d on output %u",
+                 width,height, refresh/1000, out->index);
+        return;
+    }
+
+    UPDATE_INTEGER_FIELD (pixel_width, PIXEL_WIDTH);
+    UPDATE_INTEGER_FIELD (pixel_height, PIXEL_HEIGHT);
+    UPDATE_INTEGER_FIELD (width, WIDTH);
+    UPDATE_INTEGER_FIELD (height, HEIGHT);
+    UPDATE_INTEGER_FIELD (refresh, REFRESH);
+
+    if (wl->output_update_callback)
+        wl->output_update_callback(wl, MRP_WAYLAND_OUTPUT_CONFIGURE, mask,out);
+
+    check_if_ready(wl, out);
+
+#undef UPDATE_STRING_FIELD
+#undef UPDATE_INTEGER_FIELD
+}
+
+static void done_callback(void *data, struct wl_output *wl_output)
+{
+    mrp_wayland_output_t *out = (mrp_wayland_output_t *)data;
+    mrp_wayland_t *wl;
+
+    MRP_ASSERT(out && out->interface && out->interface->wl,
+               "invalid argument");
+    MRP_ASSERT(wl_output == (struct wl_output *)out->proxy,
+               "confused with data structures");
+
+    wl = out->interface->wl;
+
+    mrp_debug("output %u update is done", out->index);
+
+    if (wl->output_update_callback)
+        wl->output_update_callback(wl, MRP_WAYLAND_OUTPUT_DONE, -1, out);
+}
+
+static void scale_callback(void *data,
+                           struct wl_output *wl_output,
+                           int32_t factor)
+{
+    mrp_wayland_output_t *out = (mrp_wayland_output_t *)data;
+
+    MRP_UNUSED(factor);
+
+    MRP_ASSERT(out, "invalid argument");
+    MRP_ASSERT(wl_output == (struct wl_output *)out->proxy,
+               "confused with data structures");
+
+    mrp_debug("output %u scale:",
+              out->index);
+}
+
+static void check_if_ready(mrp_wayland_t *wl, mrp_wayland_output_t *out)
+{
+    output_iterator_helper_t helper;
+    char buf[4096];
+
+    MRP_ASSERT(wl && out, "invalid argument");
+
+    if (!out->initialized && out->width > 0 && out->height > 0 &&
+        out->physical_width > 0 && out->physical_height > 0)
+    {
+        out->initialized = true;
+
+        mrp_wayland_output_print(out, -1, buf,sizeof(buf));
+        mrp_log_info("system-controller: found output %u%s", out->index, buf);
+
+        if (wl->output_update_callback)
+            wl->output_update_callback(wl, MRP_WAYLAND_OUTPUT_DONE, -1, out);
+
+        /* list the areas that belong to this output */
+        memset(&helper, 0, sizeof(helper));
+        helper.output = out;
+
+        mrp_htbl_foreach(wl->areas, print_area, &helper);
+
+        if (helper.count == 0) {
+            mrp_log_info("system-controller: output '%s' has no areas",
+                         out->outputname);
+        }
+    }
+}
+
+static int print_area(void *key, void *object, void *ud)
+{
+    output_iterator_helper_t *helper = (output_iterator_helper_t *)ud;
+    mrp_wayland_area_t *area = (mrp_wayland_area_t *)object;
+    char buf[4096];
+
+    MRP_UNUSED(key);
+
+    MRP_ASSERT(helper && helper->output && area,
+               "confused with data structures");
+
+    if (helper->output == area->output) {
+        helper->count++;
+
+        mrp_wayland_area_print(area, -1, buf, sizeof(buf));
+        mrp_log_info("system-controller: area for output '%s'%s",
+                     helper->output->outputname, buf);
+    }
+
+    return MRP_HTBL_ITER_MORE;
+}
+
+size_t mrp_wayland_output_print(mrp_wayland_output_t *out,
+                                mrp_wayland_output_update_mask_t mask,
+                                char *buf,
+                                size_t len)
+{
+#define PRINT(fmt, args...) \
+    if (p < e) { p += snprintf(p, e-p, "\n      " fmt , ## args); }
+
+    char *p, *e;
+
+    e = (p = buf) + len;
+
+    *p = 0;
+
+    if ((mask & MRP_WAYLAND_OUTPUT_OUTPUTID_MASK))
+        PRINT("id: %d", out->outputid);
+    if ((mask & MRP_WAYLAND_OUTPUT_NAME_MASK))
+        PRINT("outputname: '%s'", out->outputname ? out->outputname : "");
+    if ((mask & MRP_WAYLAND_OUTPUT_PIXEL_POSITION_MASK))
+        PRINT("pixel_position: %d,%d", out->pixel_x, out->pixel_y);
+    if ((mask & MRP_WAYLAND_OUTPUT_PHYSICAL_SIZE_MASK))
+        PRINT("physical_size: %dx%d mm", out->physical_width,
+                                         out->physical_height);
+    if ((mask & MRP_WAYLAND_OUTPUT_PIXEL_SIZE_MASK))
+        PRINT("pixel_size: %dx%d pixel", out->pixel_width, out->pixel_height);
+    if ((mask & MRP_WAYLAND_OUTPUT_SIZE_MASK))
+        PRINT("size: %dx%d pixel", out->width, out->height);
+    if ((mask & MRP_WAYLAND_OUTPUT_SUBPIXEL_MASK))
+        PRINT("subpixel: %d", out->subpixel);
+    if ((mask & MRP_WAYLAND_OUTPUT_ROTATE_MASK))
+        PRINT("rotate: %u degrees", out->rotate);
+    if ((mask & MRP_WAYLAND_OUTPUT_FLIP_MASK))
+        PRINT("flip: %s", out->flip ? "yes" : "no");
+    if ((mask & MRP_WAYLAND_OUTPUT_MONITOR_MASK)) {
+        PRINT("monitor: %s manufactured by %s",
+              out->model ? out->model: "<unknown>",
+              out->make  ? out->make  : "<unknown>");
+    }
+    if ((mask & MRP_WAYLAND_OUTPUT_REFRESH_MASK))
+        PRINT("refresh: %d Hz", out->refresh / 1000);
+
+    return p - buf;
+
+#undef PRINT
+}
+
+
+size_t mrp_wayland_output_request_print(mrp_wayland_output_update_t *u,
+                                        char *buf, size_t len)
+{
+#define PRINT(fmt, args...) \
+    if (p < e) { p += snprintf(p, e-p, "\n      " fmt , ## args); }
+
+    mrp_wayland_output_update_mask_t mask;
+    char *p, *e;
+
+    mask = u->mask;
+    e = (p = buf) + len;
+
+    *p = 0;
+
+    if ((mask & MRP_WAYLAND_OUTPUT_NAME_MASK))
+        PRINT("outputname: '%s'", u->outputname);
+
+    return p - buf;
+
+#undef PRINT
+}
+
+
+const char *
+mrp_wayland_output_update_mask_str(mrp_wayland_output_update_mask_t mask)
+{
+    switch (mask) {
+    case MRP_WAYLAND_OUTPUT_INDEX_MASK:           return "index";
+    case MRP_WAYLAND_OUTPUT_OUTPUTID_MASK:        return "id";
+    case MRP_WAYLAND_OUTPUT_NAME_MASK:            return "name";
+    case MRP_WAYLAND_OUTPUT_PIXEL_X_MASK:         return "pixel_x";
+    case MRP_WAYLAND_OUTPUT_PIXEL_Y_MASK:         return "pixel_y";
+    case MRP_WAYLAND_OUTPUT_PIXEL_POSITION_MASK:  return "pixel_position";
+    case MRP_WAYLAND_OUTPUT_PHYSICAL_WIDTH_MASK:  return "physical_width";
+    case MRP_WAYLAND_OUTPUT_PHYSICAL_HEIGHT_MASK: return "physical_height";
+    case MRP_WAYLAND_OUTPUT_PHYSICAL_SIZE_MASK:   return "physical_size";
+    case MRP_WAYLAND_OUTPUT_PIXEL_WIDTH_MASK:     return "pixel_width";
+    case MRP_WAYLAND_OUTPUT_PIXEL_HEIGHT_MASK:    return "pixel_height";
+    case MRP_WAYLAND_OUTPUT_PIXEL_SIZE_MASK:      return "pixel_size";
+    case MRP_WAYLAND_OUTPUT_WIDTH_MASK:           return "width";
+    case MRP_WAYLAND_OUTPUT_HEIGHT_MASK:          return "height";
+    case MRP_WAYLAND_OUTPUT_SIZE_MASK:            return "size";
+    case MRP_WAYLAND_OUTPUT_SUBPIXEL_MASK:        return "subpixel";
+    case MRP_WAYLAND_OUTPUT_MAKE_MASK:            return "make";
+    case MRP_WAYLAND_OUTPUT_MODEL_MASK:           return "model";
+    case MRP_WAYLAND_OUTPUT_ROTATE_MASK:          return "rotate";
+    case MRP_WAYLAND_OUTPUT_FLIP_MASK:            return "flip";
+    case MRP_WAYLAND_OUTPUT_REFRESH_MASK:         return "refresh";
+    default:                                      return "<unknown>";
+    }
+}
+
+void mrp_wayland_output_set_scripting_data(mrp_wayland_output_t *out,
+                                           void *data)
+{
+    MRP_ASSERT(out, "Invalid Argument");
+
+    mrp_debug("%sset scripting data", data ? "" : "re");
+
+    out->scripting_data = data;
+}
+
diff --git a/src/plugins/system-controller/wayland/output.h b/src/plugins/system-controller/wayland/output.h
new file mode 100644 (file)
index 0000000..7afd6c4
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_WAYLAND_OUTPUT_H__
+#define __MURPHY_WAYLAND_OUTPUT_H__
+
+#include "wayland/wayland.h"
+
+enum mrp_wayland_output_operation_e {
+    MRP_WAYLAND_OUTPUT_OPERATION_NONE = 0,
+    MRP_WAYLAND_OUTPUT_CREATE,       /* 1 */
+    MRP_WAYLAND_OUTPUT_DESTROY,      /* 2 */
+    MRP_WAYLAND_OUTPUT_CONFIGURE,    /* 3 */
+    MRP_WAYLAND_OUTPUT_MODE,         /* 4 */
+    MRP_WAYLAND_OUTPUT_DONE,         /* 5 */
+    MRP_WAYLAND_OUTPUT_USER_REQUEST, /* 6 */
+};
+
+
+struct mrp_wayland_output_s {
+    MRP_WAYLAND_OBJECT_COMMON;
+
+    uint32_t index;
+    int32_t outputid;
+    char *outputname;
+
+    int32_t pixel_x, pixel_y;
+    int32_t physical_width, physical_height;
+    int32_t pixel_width, pixel_height;
+    int32_t width, height;      /* pixel measures after rotation & flip */
+    int32_t subpixel;
+    char *make;
+    char *model;
+    uint32_t rotate;
+    bool flip;
+    int32_t refresh;
+
+    bool initialized;
+
+    void *scripting_data;
+};
+
+enum mrp_wayland_output_update_mask_e {
+    MRP_WAYLAND_OUTPUT_INDEX_MASK      = 0x00001,
+    MRP_WAYLAND_OUTPUT_OUTPUTID_MASK   = 0x00002,
+    MRP_WAYLAND_OUTPUT_NAME_MASK       = 0x00004,
+    MRP_WAYLAND_OUTPUT_PIXEL_X_MASK = 0x00008,
+    MRP_WAYLAND_OUTPUT_PIXEL_Y_MASK = 0x00010,
+    MRP_WAYLAND_OUTPUT_PIXEL_POSITION_MASK  = 0x00018,
+    MRP_WAYLAND_OUTPUT_PHYSICAL_WIDTH_MASK  = 0x00020,
+    MRP_WAYLAND_OUTPUT_PHYSICAL_HEIGHT_MASK = 0x00040,
+    MRP_WAYLAND_OUTPUT_PHYSICAL_SIZE_MASK   = 0x00060,
+    MRP_WAYLAND_OUTPUT_PIXEL_WIDTH_MASK     = 0x00080,
+    MRP_WAYLAND_OUTPUT_PIXEL_HEIGHT_MASK    = 0x00100,
+    MRP_WAYLAND_OUTPUT_PIXEL_SIZE_MASK      = 0x00180,
+    MRP_WAYLAND_OUTPUT_WIDTH_MASK       = 0x00200,
+    MRP_WAYLAND_OUTPUT_HEIGHT_MASK      = 0x00400,
+    MRP_WAYLAND_OUTPUT_SIZE_MASK        = 0x00600,
+    MRP_WAYLAND_OUTPUT_SUBPIXEL_MASK    = 0x00800,
+    MRP_WAYLAND_OUTPUT_MAKE_MASK        = 0x01000,
+    MRP_WAYLAND_OUTPUT_MODEL_MASK       = 0x02000,
+    MRP_WAYLAND_OUTPUT_MONITOR_MASK     = 0x03000,
+    MRP_WAYLAND_OUTPUT_ROTATE_MASK      = 0x04000,
+    MRP_WAYLAND_OUTPUT_FLIP_MASK        = 0x08000,
+    MRP_WAYLAND_OUTPUT_REFRESH_MASK     = 0x10000,
+
+    MRP_WAYLAND_OUTPUT_END_MASK         = 0x20000
+};
+
+struct mrp_wayland_output_update_s {
+    mrp_wayland_output_update_mask_t mask; 
+    uint32_t index;
+    int32_t outputid;
+    const char *outputname;
+};
+
+bool mrp_wayland_output_register(mrp_wayland_t *wl);
+
+mrp_wayland_output_t *mrp_wayland_output_find(mrp_wayland_t *wl,
+                                              uint32_t index);
+
+void mrp_wayland_output_request(mrp_wayland_t *wl,
+                                mrp_wayland_output_update_t *u);
+
+size_t mrp_wayland_output_print(mrp_wayland_output_t *out,
+                                mrp_wayland_output_update_mask_t mask,
+                                char *buf, size_t len);
+
+size_t mrp_wayland_output_request_print(mrp_wayland_output_update_t *u,
+                                        char *buf, size_t len);
+
+const char *mrp_wayland_output_update_mask_str(
+                                        mrp_wayland_output_update_mask_t mask);
+
+void mrp_wayland_output_set_scripting_data(mrp_wayland_output_t *out,
+                                           void *data);
+
+#endif /* __MURPHY_WAYLAND_OUTPUT_H__ */
diff --git a/src/plugins/system-controller/wayland/scripting-animation.c b/src/plugins/system-controller/wayland/scripting-animation.c
new file mode 100644 (file)
index 0000000..83ce688
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+#include <murphy/core/lua-bindings/murphy.h>
+#include <murphy/core/lua-utils/error.h>
+#include <murphy/core/lua-utils/object.h>
+#include <murphy/core/lua-utils/funcbridge.h>
+
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include "scripting-wayland.h"
+#include "animation.h"
+
+#define ANIMATION_CLASS  MRP_LUA_CLASS_SIMPLE(animation)
+
+typedef struct scripting_animation_s  scripting_animation_t;
+typedef struct animation_def_s  animation_def_t;
+
+struct scripting_animation_s {
+    mrp_wayland_animation_t *anims;
+};
+
+
+struct animation_def_s {
+    const char *name;
+    int32_t time;
+};
+
+
+static int  animation_create(lua_State *);
+static int  animation_getfield(lua_State *);
+static int  animation_setfield(lua_State *);
+static void animation_destroy(void *);
+
+static scripting_animation_t *animation_check(lua_State *, int);
+static int animation_push_type(lua_State *L, mrp_wayland_animation_t *,
+                               mrp_wayland_animation_type_t);
+
+static animation_def_t *animation_def_check(lua_State *, int);
+static void animation_def_free(animation_def_t *);
+
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    animation,                  /* class name */
+    scripting_animation_t,      /* userdata type */
+    animation_destroy,          /* userdata destructor */
+    MRP_LUA_METHOD_LIST (       /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR (animation_create)
+    ),
+    MRP_LUA_METHOD_LIST (       /* overrides */
+       MRP_LUA_OVERRIDE_CALL      (animation_create)
+       MRP_LUA_OVERRIDE_GETFIELD  (animation_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD  (animation_setfield)
+    )
+);
+
+
+void mrp_wayland_scripting_animation_init(lua_State *L)
+{
+    MRP_ASSERT(L, "invalid argument");
+
+    mrp_lua_create_object_class(L, ANIMATION_CLASS);
+}
+
+mrp_wayland_animation_t *mrp_wayland_scripting_animation_check(lua_State *L,
+                                                               int idx)
+{
+    scripting_animation_t *an;
+
+    MRP_ASSERT(L, "invalid argument");
+
+    if ((an = animation_check(L, idx)))
+        return an->anims;
+
+    return NULL;
+}                                        
+
+
+mrp_wayland_animation_t *mrp_wayland_scripting_animation_unwrap(void *void_an)
+{
+    scripting_animation_t *an = (scripting_animation_t *)void_an;
+
+    if (an && mrp_lua_get_object_classdef(an) == ANIMATION_CLASS)
+        return an->anims;
+
+    return NULL;
+}
+
+
+static int animation_create(lua_State *L)
+{
+    size_t fldnamlen;
+    const char *fldnam;
+    scripting_animation_t *an;
+    mrp_wayland_animation_t *anims;
+    animation_def_t *hide = NULL;
+    animation_def_t *show = NULL;
+    animation_def_t *move = NULL;
+    animation_def_t *resize = NULL;
+
+    MRP_LUA_ENTER;
+
+
+    luaL_checktype(L, 2, LUA_TTABLE);
+
+    MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
+        switch (mrp_wayland_scripting_field_name_to_type(fldnam, fldnamlen)) {
+        case HIDE:    hide   = animation_def_check(L, -1);     break;
+        case SHOW:    show   = animation_def_check(L, -1);     break;
+        case MOVE:    move   = animation_def_check(L, -1);     break;
+        case RESIZE:  resize = animation_def_check(L, -1);     break;
+        default:      luaL_error(L, "bad field '%s'", fldnam); break;
+        }
+    }
+
+    anims = mrp_wayland_animation_create();
+
+    if (hide) {
+        mrp_wayland_animation_set(anims, MRP_WAYLAND_ANIMATION_HIDE,
+                                  hide->name, hide->time);
+        mrp_free(hide);
+    }
+    if (show) {
+        mrp_wayland_animation_set(anims, MRP_WAYLAND_ANIMATION_SHOW,
+                                  show->name, show->time);
+        animation_def_free(show);
+    }
+    if (move) {
+        mrp_wayland_animation_set(anims, MRP_WAYLAND_ANIMATION_MOVE,
+                                  move->name, move->time);
+        animation_def_free(move);
+    }
+    if (resize) {
+        mrp_wayland_animation_set(anims, MRP_WAYLAND_ANIMATION_RESIZE,
+                                  resize->name, resize->time);
+        animation_def_free(resize);
+    }
+
+    an = (scripting_animation_t *)mrp_lua_create_object(L, ANIMATION_CLASS,
+                                                        NULL, 0);
+    if (!an)
+        luaL_error(L, "can't create animation");
+
+    an->anims = anims;
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int  animation_getfield(lua_State *L)
+{
+    scripting_animation_t *an;
+    mrp_wayland_animation_t *anims;
+    mrp_wayland_animation_type_t type;
+    mrp_wayland_scripting_field_t fld;
+
+    MRP_LUA_ENTER;
+
+    an = animation_check(L, 1);
+    fld = mrp_wayland_scripting_field_check(L, 2, NULL);
+
+    lua_pop(L, 1);
+
+    if (!an || !(anims = an->anims))
+        lua_pushnil(L);
+    else {
+        switch (fld) {
+        case HIDE:    type = MRP_WAYLAND_ANIMATION_HIDE;     goto push;
+        case SHOW:    type = MRP_WAYLAND_ANIMATION_SHOW;     goto push;
+        case MOVE:    type = MRP_WAYLAND_ANIMATION_MOVE;     goto push;
+        case RESIZE:  type = MRP_WAYLAND_ANIMATION_RESIZE;   goto push;
+        push:         animation_push_type(L, anims, type);   break;
+        default:      lua_pushnil(L);                        break;
+        }
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int  animation_setfield(lua_State *L)
+{
+    scripting_animation_t *an;
+    mrp_wayland_animation_t *anims;
+    mrp_wayland_scripting_field_t fld;
+    animation_def_t *def;
+    mrp_wayland_animation_type_t type;
+
+    MRP_LUA_ENTER;
+
+    an = animation_check(L, 1);
+    fld = mrp_wayland_scripting_field_check(L, 2, NULL);
+    def = animation_def_check(L, 3);
+
+    lua_pop(L, 2);
+
+    if (an && (anims = an->anims) && def) {
+        switch (fld) {
+        case HIDE:    type = MRP_WAYLAND_ANIMATION_HIDE;    goto setfield;
+        case SHOW:    type = MRP_WAYLAND_ANIMATION_SHOW;    goto setfield;
+        case MOVE:    type = MRP_WAYLAND_ANIMATION_MOVE;    goto setfield;
+        case RESIZE:  type = MRP_WAYLAND_ANIMATION_RESIZE;  goto setfield;
+        default:                                            break;
+        setfield:
+            mrp_wayland_animation_set(anims, type, def->name, def->time);
+            break;
+        }
+        mrp_free(def);
+    }
+    
+    MRP_LUA_LEAVE(0);
+}
+static void animation_destroy(void *data)
+{
+    scripting_animation_t *an = (scripting_animation_t *)data;
+
+    if (an) {
+        mrp_wayland_animation_destroy(an->anims);
+    }
+}
+
+
+static scripting_animation_t *animation_check(lua_State *L, int idx)
+{
+    return (scripting_animation_t*)mrp_lua_check_object(L,ANIMATION_CLASS,idx);
+}
+
+static int animation_push_type(lua_State *L, mrp_wayland_animation_t *anims,
+                               mrp_wayland_animation_type_t type)
+{
+    mrp_wayland_animation_t *a;
+
+    MRP_LUA_ENTER;
+
+    if (!anims || type < 0 || type >= MRP_WAYLAND_ANIMATION_MAX)
+        lua_pushnil(L);
+    else {
+        a = anims + type;
+
+        if (type != a->type || !a->name  || a->time < 1)
+            lua_pushnil(L);
+        else {
+            lua_createtable(L, 2, 0);
+
+            lua_pushinteger(L, 1);
+            lua_pushstring(L, a->name);
+            lua_settable(L, -3);
+
+            lua_pushinteger(L, 2);
+            lua_pushinteger(L, a->time);
+            lua_settable(L, -3);
+        }
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static animation_def_t *animation_def_check(lua_State *L, int t)
+{
+    animation_def_t *def;
+    size_t i, tlen;
+    const char *name = NULL;
+    int16_t time = -1;
+
+    t = (t < 0) ? lua_gettop(L) + t + 1 : t;
+
+    luaL_checktype(L, t, LUA_TTABLE);
+
+    if ((tlen = lua_objlen(L, t)) != 2) {
+        luaL_error(L,"invalid animation definition: "
+                   "expected 2 fields, got %u", tlen);
+    }
+
+    for (i = 0;  i < tlen;  i++) {
+        lua_pushinteger(L, (int)(i+1));
+        lua_gettable(L, t);
+
+        if (i == 0)
+            name = lua_isstring(L,-1) ?  mrp_strdup(lua_tostring(L,-1)) : NULL;
+        else
+            time = lua_tointeger(L,-1);
+
+        lua_pop(L, 1);
+    }
+
+    if (!name || time < 1)
+        return NULL;
+
+    if (!(def = mrp_allocz(sizeof(animation_def_t))))
+        mrp_free((void *)name);
+    else {
+        def->name = name;
+        def->time = time;
+    }
+
+    return def;
+}
+
+
+static void animation_def_free(animation_def_t *def)
+{
+    if (def) {
+        mrp_free((void *)def->name);
+        mrp_free(def);
+    }
+}
diff --git a/src/plugins/system-controller/wayland/scripting-area.c b/src/plugins/system-controller/wayland/scripting-area.c
new file mode 100644 (file)
index 0000000..72a4b2c
--- /dev/null
@@ -0,0 +1,593 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+#include <murphy/core/lua-bindings/murphy.h>
+#include <murphy/core/lua-utils/error.h>
+#include <murphy/core/lua-utils/object.h>
+#include <murphy/core/lua-utils/funcbridge.h>
+
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include "scripting-wayland.h"
+#include "area.h"
+#include "output.h"
+
+#define AREA_CLASS          MRP_LUA_CLASS_SIMPLE(area)
+#define ALIGN_MASK_CLASS    MRP_LUA_CLASS_SIMPLE(align_mask)
+
+#define ALIGN_MASK_INVALID  (~(uint32_t)0)
+
+
+typedef struct scripting_area_s  scripting_area_t;
+typedef struct scripting_align_mask_s  scripting_align_mask_t;
+
+
+struct scripting_area_s {
+    mrp_wayland_area_t *area;
+    const char *id;
+};
+
+struct scripting_align_mask_s {
+    uint32_t mask;
+};
+
+static int  area_create_from_lua(lua_State *);
+static int  area_getfield(lua_State *);
+static int  area_setfield(lua_State *);
+static int  area_stringify(lua_State *);
+static void area_destroy_from_lua(void *);
+
+static scripting_area_t *area_check(lua_State *, int);
+
+static int  align_mask_create_from_lua(lua_State *);
+static int  align_mask_getfield(lua_State *);
+static int  align_mask_setfield(lua_State *);
+static int  align_mask_stringify(lua_State *);
+static void align_mask_destroy(void *);
+
+static scripting_align_mask_t *align_mask_check(lua_State *, int);
+
+static uint32_t get_align_mask(mrp_wayland_scripting_field_t);
+
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    area,                       /* class name */
+    scripting_area_t,           /* userdata type */
+    area_destroy_from_lua,      /* userdata destructor */
+    MRP_LUA_METHOD_LIST (       /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR (area_create_from_lua)
+    ),
+    MRP_LUA_METHOD_LIST (       /* overrides */
+       MRP_LUA_OVERRIDE_CALL      (area_create_from_lua)
+       MRP_LUA_OVERRIDE_GETFIELD  (area_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD  (area_setfield)
+       MRP_LUA_OVERRIDE_STRINGIFY (area_stringify)
+    )
+);
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    align_mask,                 /* class name */
+    scripting_align_mask_t ,    /* userdata type */
+    align_mask_destroy,         /* userdata destructor */
+    MRP_LUA_METHOD_LIST (       /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR (align_mask_create_from_lua)
+    ),
+    MRP_LUA_METHOD_LIST (       /* overrides */
+       MRP_LUA_OVERRIDE_CALL      (align_mask_create_from_lua)
+       MRP_LUA_OVERRIDE_GETFIELD  (align_mask_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD  (align_mask_setfield)
+       MRP_LUA_OVERRIDE_STRINGIFY (align_mask_stringify)
+    )
+);
+
+void mrp_wayland_scripting_area_init(lua_State *L)
+{
+    mrp_lua_create_object_class(L, AREA_CLASS);
+    mrp_lua_create_object_class(L, ALIGN_MASK_CLASS);
+}
+
+
+mrp_wayland_area_t *mrp_wayland_scripting_area_check(lua_State *L, int idx)
+{
+    scripting_area_t *a;
+    mrp_wayland_area_t *area;
+
+    if ((a = area_check(L, idx)) && (area = a->area)) {
+        MRP_ASSERT(area->scripting_data == (void *)a,
+                   "confused with data structures");
+        return area;
+    }
+
+    return NULL;
+}
+
+mrp_wayland_area_t *mrp_wayland_scripting_area_unwrap(void *void_a)
+{
+    scripting_area_t *a = (scripting_area_t *)void_a;
+
+    if (a && mrp_lua_get_object_classdef(a) == AREA_CLASS)
+        return a->area;
+
+    return NULL;
+}
+
+int mrp_wayland_scripting_area_push(lua_State *L, mrp_wayland_area_t *area)
+{
+    MRP_LUA_ENTER;
+
+    if (!area || !area->scripting_data)
+        lua_pushnil(L);
+    else
+        mrp_lua_push_object(L, area->scripting_data);
+
+    MRP_LUA_LEAVE(1);
+}
+
+void *mrp_wayland_scripting_area_create_from_c(lua_State *L,
+                                               mrp_wayland_area_t *area)
+{
+    scripting_area_t *a;
+    char *id;
+    char buf[2048];
+
+    MRP_ASSERT(area && area->fullname, "invald argument");
+    
+    if (!L && !(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("can't create scripting area %d: LUA is "
+                      "not initialized", area->areaid);
+        return NULL;
+    }
+
+    id = mrp_wayland_scripting_canonical_name(area->fullname, buf,sizeof(buf));
+    a = (scripting_area_t*)mrp_lua_create_object(L, AREA_CLASS, id, 0);
+    if (!a) {
+        mrp_log_error("can't create scripting area %d: LUA object "
+                      "creation failed", area->areaid);
+        return NULL;
+    }
+
+    a->area = area;
+    a->id = mrp_strdup(id);
+
+    return a;
+}
+
+void mrp_wayland_scripting_area_destroy_from_c(lua_State *L,
+                                               mrp_wayland_area_t *area)
+{
+    scripting_area_t *a;
+
+    MRP_ASSERT(area, "invalid argument");
+
+    if (!L && !(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("can't destroy scripting area %d: LUA is "
+                      "not initialized", area->areaid);
+        area->scripting_data = NULL;
+        return;
+    }
+
+    if ((a = area->scripting_data)) {
+        mrp_debug("destroy scripting area %d", area->areaid);
+
+         a->area = NULL;
+
+         mrp_lua_destroy_object(L, a->id,0, area->scripting_data);
+
+         area->scripting_data = NULL;
+    }
+}
+
+
+static int area_create_from_lua(lua_State *L)
+{
+    MRP_LUA_ENTER;
+
+    luaL_error(L, "area from lua can only be created via the 'areas' field "
+               "of 'outputs' window_manager property");
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int area_getfield(lua_State *L)
+{
+    scripting_area_t *a;
+    mrp_wayland_area_t *area;
+    const char *fldnam;
+    mrp_wayland_scripting_field_t fld;
+    char buf[32];
+
+    MRP_LUA_ENTER;
+
+    fld = mrp_wayland_scripting_field_check(L, 2, &fldnam);
+    lua_pop(L, 1);
+
+    a = area_check(L, 1);
+
+    if (!a || !(area = a->area))
+        lua_pushnil(L);
+    else {
+        switch (fld) {
+        case ID:
+            lua_pushinteger(L, area->areaid);
+            break;
+
+        case OUTPUT:
+            if (!area->output)
+                lua_pushnil(L);
+            else if (area->output->outputname)
+                lua_pushstring(L, area->output->outputname);
+            else {
+                snprintf(buf, sizeof(buf), "%d", area->output->outputid);
+                lua_pushstring(L, buf);
+            }
+            break;
+
+        case POS_X:
+            lua_pushinteger(L, area->x);
+            break;
+        case POS_Y:
+            lua_pushinteger(L, area->y);
+            break;
+                                                           
+        case WIDTH:
+            lua_pushinteger(L, area->width);
+            break;
+        case HEIGHT:
+            lua_pushinteger(L, area->height);
+            break;
+
+        case KEEPRATIO:
+            lua_pushboolean(L, area->keepratio);
+            break;
+
+        case ALIGN:
+            mrp_wayland_scripting_align_mask_create_from_c(L, area->align);
+            break;
+
+        default:
+            lua_pushnil(L);
+            break;
+        }
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int  area_setfield(lua_State *L)
+{
+    MRP_LUA_ENTER;
+
+    area_check(L, 1);
+    luaL_error(L, "area objects are read-only");
+
+    MRP_LUA_LEAVE(0);
+}
+
+static int  area_stringify(lua_State *L)
+{
+#define ALL_FIELDS (MRP_WAYLAND_AREA_END_MASK - 1)
+
+    scripting_area_t *a;
+    mrp_wayland_area_t *area;
+    char *p, *e;
+    char buf[4096];
+
+    MRP_LUA_ENTER;
+
+    a = area_check(L, 1);
+
+    if (!a || !(area = a->area))
+        lua_pushnil(L);
+    else {
+        e = (p = buf) + sizeof(buf);
+        p += snprintf(p, e-p, "area %d", area->areaid);
+        p += mrp_wayland_area_print(area, ALL_FIELDS, p, e-p);
+
+        lua_pushlstring(L, buf, p-buf);
+    }
+
+    MRP_LUA_LEAVE(1);
+
+#undef ALL_FIELDS
+}
+
+static void area_destroy_from_lua(void *data)
+{
+    scripting_area_t *a = (scripting_area_t *)data;
+
+    MRP_LUA_ENTER;
+
+    if (a && a->area) {
+        mrp_wayland_area_set_scripting_data(a->area, NULL);
+        mrp_free((void *)a->id);
+    }
+
+    MRP_LUA_LEAVE_NOARG;
+}
+
+
+static scripting_area_t *area_check(lua_State *L, int idx)
+{
+    return (scripting_area_t *)mrp_lua_check_object(L, AREA_CLASS, idx);
+}
+
+
+void *mrp_wayland_scripting_align_mask_create_from_c(lua_State *L,
+                                                     uint32_t mask)
+{
+    scripting_align_mask_t *um;
+
+    if (!L && !(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("can't create scripting window mask: "
+                      "LUA is not initialized");
+        return NULL;
+    }
+
+    um = (scripting_align_mask_t *)mrp_lua_create_object(L, ALIGN_MASK_CLASS,
+                                                         NULL, 0);
+    if (!um)
+        mrp_log_error("can't create align_mask");
+    else
+        um->mask = mask;
+
+    return um;
+}
+
+
+static int align_mask_create_from_lua(lua_State *L)
+{
+    size_t fldnamlen;
+    const char *fldnam, *valstr;
+    scripting_align_mask_t *um;
+    mrp_wayland_scripting_field_t fld, val;
+    uint32_t m;
+    uint32_t mask = 0;
+
+    MRP_LUA_ENTER;
+
+    luaL_checktype(L, 2, LUA_TTABLE);
+
+    MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
+        fld = mrp_wayland_scripting_field_name_to_type(fldnam, fldnamlen);
+        
+        switch (fld) {
+
+        case MASK:
+            mask = lua_tointeger(L, -1);
+            break;
+
+        case HORIZONTAL:
+            val = mrp_wayland_scripting_field_check(L, -1, &valstr);
+            if ((m = get_align_mask(val)) == ALIGN_MASK_INVALID ||
+                (m & ~MRP_WAYLAND_AREA_ALIGN_HMASK))
+                luaL_error(L, "invalid horizontal alingment '%s'", valstr);
+            else {
+                mask &= ~MRP_WAYLAND_AREA_ALIGN_HMASK; 
+                mask |= m;
+            }
+            break;
+
+        case VERTICAL:
+            val = mrp_wayland_scripting_field_check(L, -1, &valstr);
+            if ((m = get_align_mask(val)) == ALIGN_MASK_INVALID ||
+                (m & ~MRP_WAYLAND_AREA_ALIGN_VMASK))
+                luaL_error(L, "invalid vertical alingment '%s'", valstr);
+            else {
+                mask &= ~MRP_WAYLAND_AREA_ALIGN_VMASK; 
+                mask |= m;
+            }
+            break;
+
+        default:
+            if ((m = get_align_mask(fld)) == ALIGN_MASK_INVALID)
+                luaL_error(L, "bad field '%s'", fldnam);
+            else {
+                mask &= ~((m & MRP_WAYLAND_AREA_ALIGN_HMASK) ?
+                          MRP_WAYLAND_AREA_ALIGN_HMASK :
+                          MRP_WAYLAND_AREA_ALIGN_VMASK);
+                if (lua_toboolean(L, -1))
+                    mask |= m;
+            }
+            break;
+        }
+    }
+
+    um = (scripting_align_mask_t *)mrp_lua_create_object(L, ALIGN_MASK_CLASS,
+                                                         NULL, 0);
+    if (!um)
+        luaL_error(L, "can't create window_mask");
+
+    um->mask = mask;
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int align_mask_getfield(lua_State *L)
+{
+    scripting_align_mask_t *um;
+    mrp_wayland_scripting_field_t fld;
+    uint32_t m;
+
+    MRP_LUA_ENTER;
+
+    um = align_mask_check(L, 1);
+    fld = mrp_wayland_scripting_field_check(L, 2, NULL);
+
+    lua_pop(L, 1);
+
+    if (!um)
+        lua_pushnil(L);
+    else {
+        switch (fld) {
+        case MASK:
+            lua_pushinteger(L, um->mask);
+            break;
+        case HORIZONTAL:
+            m = um->mask & MRP_WAYLAND_AREA_ALIGN_HMASK;
+            lua_pushstring(L, mrp_wayland_area_align_str(m));
+            break;
+        case VERTICAL:
+            m = um->mask & MRP_WAYLAND_AREA_ALIGN_VMASK;
+            lua_pushstring(L, mrp_wayland_area_align_str(m));
+            break;
+        default:
+            if ((m = get_align_mask(fld)) != ALIGN_MASK_INVALID)
+                lua_pushboolean(L, (um->mask & m) ? 1 : 0);
+            else
+                lua_pushnil(L);
+            break;
+        }
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int align_mask_setfield(lua_State *L)
+{
+    scripting_align_mask_t *um;
+    const char *fldstr, *valstr;
+    uint32_t m;
+    mrp_wayland_scripting_field_t fld, val;
+
+    MRP_LUA_ENTER;
+
+    um = align_mask_check(L, 1);
+    fld = mrp_wayland_scripting_field_check(L, 2, &fldstr);
+
+    lua_pop(L, 2);
+
+    if (um) {
+        switch (fld) {
+        case MASK:
+            um->mask = lua_tointeger(L, 3);
+            break;
+        case HORIZONTAL:
+            val = mrp_wayland_scripting_field_check(L, 3, &valstr);
+            if ((m = get_align_mask(val)) == ALIGN_MASK_INVALID ||
+                (m & ~MRP_WAYLAND_AREA_ALIGN_HMASK))
+                luaL_error(L, "invalid horizontal alingment '%s'", valstr);
+            else {
+                um->mask &= ~MRP_WAYLAND_AREA_ALIGN_HMASK;
+                um->mask |= m;
+            }
+            break;
+        case VERTICAL:
+            val = mrp_wayland_scripting_field_check(L, 3, &valstr);
+            if ((m = get_align_mask(val)) == ALIGN_MASK_INVALID ||
+                (m & ~MRP_WAYLAND_AREA_ALIGN_VMASK))
+                luaL_error(L, "invalid vertical alingment '%s'", valstr);
+            else {
+                um->mask &= ~MRP_WAYLAND_AREA_ALIGN_VMASK;
+                um->mask |= m;
+            }
+            break;
+        default:
+            if ((m = get_align_mask(fld)) == ALIGN_MASK_INVALID)
+                luaL_error(L, "invalid alignement field '%s'", fldstr);
+            else {
+                um->mask &= ~((m & MRP_WAYLAND_AREA_ALIGN_HMASK) ?
+                               MRP_WAYLAND_AREA_ALIGN_HMASK :
+                               MRP_WAYLAND_AREA_ALIGN_VMASK);
+                if (lua_toboolean(L, 3))
+                    um->mask |= m;
+            }            
+        }
+    }
+
+    MRP_LUA_LEAVE(0);
+}
+
+static int align_mask_stringify(lua_State *L)
+{
+    scripting_align_mask_t *um;
+    uint32_t m, mask;
+    char buf[4096];
+    char *p, *e;
+    const char *name;
+
+
+    MRP_LUA_ENTER;
+
+    um = align_mask_check(L, 1);
+
+    e = (p = buf) + sizeof(buf);
+    *p = 0;
+
+    mask = um->mask;
+
+    for (m=1; mask && m < MRP_WAYLAND_AREA_ALIGN_END_MASK && p < e;  m <<= 1) {
+        if ((mask & m)) {
+            mask &= ~m;
+
+            if ((name = mrp_wayland_area_align_str(m)))
+                p += snprintf(p, e-p, "%s%s", p > buf ? " | " : "", name);
+        }
+    }
+
+    lua_pushstring(L, (p > buf) ? buf : "<empty>");
+
+    MRP_LUA_LEAVE(1);
+}
+
+static void align_mask_destroy(void *data)
+{
+    scripting_align_mask_t *um = (scripting_align_mask_t *)data;
+
+    MRP_UNUSED(um);
+}
+
+static scripting_align_mask_t *align_mask_check(lua_State *L, int idx)
+{
+    return (scripting_align_mask_t *)mrp_lua_check_object(L, ALIGN_MASK_CLASS,
+                                                          idx);
+}
+
+
+static uint32_t get_align_mask(mrp_wayland_scripting_field_t fld)
+{
+    switch (fld) {
+    case MIDDLE:    return MRP_WAYLAND_AREA_ALIGN_MIDDLE;
+    case LEFT:      return MRP_WAYLAND_AREA_ALIGN_LEFT;
+    case RIGHT:     return MRP_WAYLAND_AREA_ALIGN_RIGHT;
+    case TOP:       return MRP_WAYLAND_AREA_ALIGN_TOP;
+    case BOTTOM:    return MRP_WAYLAND_AREA_ALIGN_BOTTOM;
+    default:        return ALIGN_MASK_INVALID;
+    }
+}
diff --git a/src/plugins/system-controller/wayland/scripting-layer.c b/src/plugins/system-controller/wayland/scripting-layer.c
new file mode 100644 (file)
index 0000000..b3a3b39
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+#include <murphy/core/lua-bindings/murphy.h>
+#include <murphy/core/lua-utils/error.h>
+#include <murphy/core/lua-utils/object.h>
+#include <murphy/core/lua-utils/funcbridge.h>
+
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include "scripting-wayland.h"
+#include "layer.h"
+
+#define LAYER_CLASS       MRP_LUA_CLASS_SIMPLE(layer)
+#define LAYER_MASK_CLASS  MRP_LUA_CLASS_SIMPLE(layer_mask)
+
+typedef struct scripting_layer_s  scripting_layer_t;
+typedef struct scripting_layer_mask_s  scripting_layer_mask_t;
+
+
+struct scripting_layer_s {
+    mrp_wayland_layer_t *layer;
+};
+
+struct scripting_layer_mask_s {
+    uint32_t mask;
+};
+
+
+static int  layer_create_from_lua(lua_State *);
+static int  layer_getfield(lua_State *);
+static int  layer_setfield(lua_State *);
+static int  layer_stringify(lua_State *);
+static void layer_destroy_from_lua(void *);
+
+static scripting_layer_t *layer_check(lua_State *, int);
+
+static int  layer_mask_create_from_lua(lua_State *);
+static int  layer_mask_getfield(lua_State *);
+static int  layer_mask_setfield(lua_State *);
+static int  layer_mask_stringify(lua_State *);
+static void layer_mask_destroy(void *);
+
+static scripting_layer_mask_t *layer_mask_check(lua_State *, int);
+
+static uint32_t get_layer_mask(mrp_wayland_scripting_field_t);
+
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    layer,                      /* class name */
+    scripting_layer_t,          /* userdata type */
+    layer_destroy_from_lua,     /* userdata destructor */
+    MRP_LUA_METHOD_LIST (       /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR (layer_create_from_lua)
+    ),
+    MRP_LUA_METHOD_LIST (       /* overrides */
+       MRP_LUA_OVERRIDE_CALL      (layer_create_from_lua)
+       MRP_LUA_OVERRIDE_GETFIELD  (layer_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD  (layer_setfield)
+       MRP_LUA_OVERRIDE_STRINGIFY (layer_stringify)
+    )
+);
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    layer_mask,                 /* class name */
+    scripting_layer_mask_t,     /* userdata type */
+    layer_mask_destroy,         /* userdata destructor */
+    MRP_LUA_METHOD_LIST (       /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR (layer_mask_create_from_lua)
+    ),
+    MRP_LUA_METHOD_LIST (       /* overrides */
+       MRP_LUA_OVERRIDE_CALL      (layer_mask_create_from_lua)
+       MRP_LUA_OVERRIDE_GETFIELD  (layer_mask_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD  (layer_mask_setfield)
+       MRP_LUA_OVERRIDE_STRINGIFY (layer_mask_stringify)
+    )
+);
+
+
+
+void mrp_wayland_scripting_layer_init(lua_State *L)
+{
+    MRP_ASSERT(L, "invalid argument");
+
+    mrp_lua_create_object_class(L, LAYER_CLASS);
+    mrp_lua_create_object_class(L, LAYER_MASK_CLASS);
+}
+
+
+mrp_wayland_layer_t *mrp_wayland_scripting_layer_check(lua_State *L, int idx)
+{
+    scripting_layer_t *l;
+    mrp_wayland_layer_t *layer;
+
+    if ((l = layer_check(L, idx)) && (layer = l->layer)) {
+        MRP_ASSERT(layer->scripting_data == (void *)l,
+                   "confused with data structures");
+        return layer;
+    }
+
+    return NULL;
+}
+
+mrp_wayland_layer_t *mrp_wayland_scripting_layer_unwrap(void *void_l)
+{
+    scripting_layer_t *l = (scripting_layer_t *)void_l;
+
+    if (l && mrp_lua_get_object_classdef(l) == LAYER_CLASS)
+        return l->layer;
+
+    return NULL;
+}
+
+void *mrp_wayland_scripting_layer_create_from_c(lua_State *L,
+                                                mrp_wayland_layer_t *layer)
+{
+    scripting_layer_t *l;
+    mrp_wayland_t *wl;
+
+    MRP_ASSERT(layer && layer->wl, "invald argument");
+
+    wl = layer->wl;
+
+    if (!wl->create_scripting_layers)
+        l = NULL;
+    else if (layer->scripting_data)
+        l = layer->scripting_data;
+    else {
+        if (!L && !(L = mrp_lua_get_lua_state())) {
+            mrp_log_error("can't create scripting layer %d: LUA is "
+                          "not initialized", layer->layerid);
+            return NULL;
+        }
+
+        l = (scripting_layer_t *)mrp_lua_create_object(L, LAYER_CLASS, NULL,
+                                                       layer->layerid + 1);
+        if (!l) {
+            mrp_log_error("can't create scripting layer %d: LUA object "
+                          "creation failed", layer->layerid);
+        }
+        else {
+            l->layer = layer;
+            mrp_wayland_layer_set_scripting_data(layer, l);
+            lua_pop(L, 1);
+        }
+    }
+
+    return l;
+}
+
+void mrp_wayland_scripting_layer_destroy_from_c(lua_State *L,
+                                                 mrp_wayland_layer_t *layer)
+{
+    scripting_layer_t *l;
+
+    MRP_ASSERT(layer, "invalid argument");
+
+    if (!L && !(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("can't destroy scripting layer %d: LUA is "
+                      "not initialized", layer->layerid);
+        layer->scripting_data = NULL;
+        return;
+    }
+
+    if ((l = layer->scripting_data)) {
+        mrp_debug("destroy scripting layer %d", layer->layerid);
+
+         l->layer = NULL;
+
+         mrp_lua_destroy_object(L,NULL,layer->layerid+1,layer->scripting_data);
+
+         layer->scripting_data = NULL;
+    }
+}
+
+
+static int layer_create_from_lua(lua_State *L)
+{
+    MRP_LUA_ENTER;
+
+    luaL_error(L, "layer from lua can only be created via the 'layers' "
+               "window_manager property");
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int layer_getfield(lua_State *L)
+{
+    scripting_layer_t *l;
+    mrp_wayland_layer_t *layer;
+    const char *fldnam;
+    mrp_wayland_scripting_field_t fld;
+
+    MRP_LUA_ENTER;
+
+    fld = mrp_wayland_scripting_field_check(L, 2, &fldnam);
+    lua_pop(L, 1);
+
+    l = layer_check(L, 1);
+
+    if (!l || !(layer = l->layer))
+        lua_pushnil(L);
+    else {
+        switch (fld) {
+        case ID:
+            lua_pushinteger(L, layer->layerid);
+            break;
+
+        case NAME:
+            lua_pushstring(L, layer->name ? layer->name : "");
+            break;
+
+        case LAYERTYPE:
+            lua_pushstring(L, mrp_wayland_layer_type_str(layer->type));
+            break;
+                                                           
+        case VISIBLE:
+            lua_pushboolean(L, layer->visible);
+            break;
+
+        default:
+            lua_pushnil(L);
+            break;
+        }
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int  layer_setfield(lua_State *L)
+{
+    MRP_LUA_ENTER;
+
+    layer_check(L, 1);
+    luaL_error(L, "layer objects are read-only");
+
+    MRP_LUA_LEAVE(0);
+}
+
+static int  layer_stringify(lua_State *L)
+{
+#define ALL_FIELDS (MRP_WAYLAND_LAYER_END_MASK - 1)
+
+    scripting_layer_t *l;
+    mrp_wayland_layer_t *layer;
+    char *p, *e;
+    char buf[4096];
+
+    MRP_LUA_ENTER;
+
+    l = layer_check(L, 1);
+
+    if (!l || !(layer = l->layer))
+        lua_pushnil(L);
+    else {
+        e = (p = buf) + sizeof(buf);
+        p += snprintf(p, e-p, "layer %d", layer->layerid);
+        p += mrp_wayland_layer_print(layer, ALL_FIELDS, p, e-p);
+
+        lua_pushlstring(L, buf, p-buf);
+    }
+
+    MRP_LUA_LEAVE(1);
+
+#undef ALL_FIELDS
+}
+
+static void layer_destroy_from_lua(void *data)
+{
+    scripting_layer_t *l = (scripting_layer_t *)data;
+
+    MRP_LUA_ENTER;
+
+    if (l && l->layer) {
+        mrp_wayland_layer_set_scripting_data(l->layer, NULL);
+    }
+
+    MRP_LUA_LEAVE_NOARG;
+}
+
+
+static scripting_layer_t *layer_check(lua_State *L, int idx)
+{
+    return (scripting_layer_t *)mrp_lua_check_object(L, LAYER_CLASS, idx);
+}
+
+void *mrp_wayland_scripting_layer_mask_create_from_c(lua_State *L,
+                                                     uint32_t mask)
+{
+    scripting_layer_mask_t *um;
+
+    um = (scripting_layer_mask_t *)mrp_lua_create_object(L, LAYER_MASK_CLASS,
+                                                         NULL, 0);
+    if (!um)
+        mrp_log_error("can't create layer_mask");
+    else
+        um->mask = mask;
+
+    return (void *)um;
+}
+
+static int layer_mask_create_from_lua(lua_State *L)
+{
+    size_t fldnamlen;
+    const char *fldnam;
+    scripting_layer_mask_t *um;
+    mrp_wayland_scripting_field_t fld;
+    uint32_t m;
+    uint32_t mask = 0;
+
+    MRP_LUA_ENTER;
+
+    luaL_checktype(L, 2, LUA_TTABLE);
+
+    MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
+        fld = mrp_wayland_scripting_field_name_to_type(fldnam, fldnamlen);
+
+        if (fld == MASK)
+            mask = lua_tointeger(L, -1);
+        else if ((m = get_layer_mask(fld)))
+            mask |= m;
+        else
+            luaL_error(L, "bad field '%s'", fldnam);
+    }
+
+    um = (scripting_layer_mask_t *)mrp_lua_create_object(L, LAYER_MASK_CLASS,
+                                                         NULL, 0);
+    if (!um)
+        luaL_error(L, "can't create layer_mask");
+
+    um->mask = mask;
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int layer_mask_getfield(lua_State *L)
+{
+    scripting_layer_mask_t *um;
+    mrp_wayland_scripting_field_t fld;
+    uint32_t m;
+
+    MRP_LUA_ENTER;
+
+    um = layer_mask_check(L, 1);
+    fld = mrp_wayland_scripting_field_check(L, 2, NULL);
+
+    lua_pop(L, 1);
+
+    if (!um)
+        lua_pushnil(L);
+    else {
+        if (fld == MASK)
+            lua_pushinteger(L, um->mask);
+        else if ((m = get_layer_mask(fld)))
+            lua_pushboolean(L, (um->mask & m) ? 1 : 0);
+        else
+            lua_pushnil(L);
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int layer_mask_setfield(lua_State *L)
+{
+    scripting_layer_mask_t *um;
+    uint32_t m;
+    mrp_wayland_scripting_field_t fld;
+
+    MRP_LUA_ENTER;
+
+    um = layer_mask_check(L, 1);
+    fld = mrp_wayland_scripting_field_check(L, 2, NULL);
+
+    lua_pop(L, 2);
+
+    if (um) {
+        if (fld == MASK)
+            um->mask = lua_tointeger(L, 3);
+        else if ((m = get_layer_mask(fld))) {
+            um->mask &= ~m;
+
+            if (lua_toboolean(L, 3))
+                um->mask |= m;
+        }
+    }
+
+    MRP_LUA_LEAVE(0);
+}
+
+static int layer_mask_stringify(lua_State *L)
+{
+    scripting_layer_mask_t *um;
+    uint32_t m, mask;
+    char buf[4096];
+    char *p, *e;
+    const char *name;
+
+
+    MRP_LUA_ENTER;
+
+    um = layer_mask_check(L, 1);
+    e = (p = buf) + sizeof(buf);
+    *p = 0;
+
+    mask = um->mask;
+
+    for (m = 1;  mask && m < MRP_WAYLAND_LAYER_END_MASK && p < e;   m <<= 1) {
+        if ((mask & m)) {
+            mask &= ~m;
+
+            if ((name = mrp_wayland_layer_update_mask_str(m)))
+                p += snprintf(p, e-p, "%s%s", p > buf ? " | " : "", name);
+        }
+    }
+
+    lua_pushstring(L, (p > buf) ? buf : "<empty>");
+
+    MRP_LUA_LEAVE(1);
+}
+
+static void layer_mask_destroy(void *data)
+{
+    scripting_layer_mask_t *um = (scripting_layer_mask_t *)data;
+
+    MRP_UNUSED(um);
+}
+
+
+static scripting_layer_mask_t *layer_mask_check(lua_State *L, int idx)
+{
+    return (scripting_layer_mask_t *)mrp_lua_check_object(L, LAYER_MASK_CLASS,
+                                                          idx);
+}
+
+static uint32_t get_layer_mask(mrp_wayland_scripting_field_t fld)
+{
+    switch (fld) {
+    case LAYER:     return MRP_WAYLAND_LAYER_LAYERID_MASK;
+    case VISIBLE:   return MRP_WAYLAND_LAYER_VISIBLE_MASK;
+    default:        return 0;
+    }
+}
diff --git a/src/plugins/system-controller/wayland/scripting-output.c b/src/plugins/system-controller/wayland/scripting-output.c
new file mode 100644 (file)
index 0000000..744c380
--- /dev/null
@@ -0,0 +1,488 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+#include <murphy/core/lua-bindings/murphy.h>
+#include <murphy/core/lua-utils/error.h>
+#include <murphy/core/lua-utils/object.h>
+#include <murphy/core/lua-utils/funcbridge.h>
+
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include "scripting-wayland.h"
+#include "output.h"
+
+#define OUTPUT_CLASS           MRP_LUA_CLASS_SIMPLE(output)
+#define OUTPUT_MASK_CLASS      MRP_LUA_CLASS_SIMPLE(output_mask)
+
+
+typedef struct scripting_output_s  scripting_output_t;
+typedef struct scripting_output_mask_s  scripting_output_mask_t;
+
+
+
+struct scripting_output_s {
+    mrp_wayland_output_t *out;
+};
+
+struct scripting_output_mask_s {
+    uint32_t mask;
+};
+
+
+
+static int  output_create_from_lua(lua_State *);
+static int  output_getfield(lua_State *);
+static int  output_setfield(lua_State *);
+static int  output_stringify(lua_State *);
+static void output_destroy_from_lua(void *);
+
+static scripting_output_t *output_check(lua_State *L, int idx);
+
+static int  output_mask_create_from_lua(lua_State *);
+static int  output_mask_getfield(lua_State *);
+static int  output_mask_setfield(lua_State *);
+static int  output_mask_stringify(lua_State *);
+static void output_mask_destroy(void *);
+
+static scripting_output_mask_t *output_mask_check(lua_State *, int);
+
+static uint32_t get_output_mask(mrp_wayland_scripting_field_t);
+
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    output,                     /* class name */
+    scripting_output_t,         /* userdata type */
+    output_destroy_from_lua,    /* userdata destructor */
+    MRP_LUA_METHOD_LIST (       /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR (output_create_from_lua)
+    ),
+    MRP_LUA_METHOD_LIST (       /* overrides */
+       MRP_LUA_OVERRIDE_CALL      (output_create_from_lua)
+       MRP_LUA_OVERRIDE_GETFIELD  (output_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD  (output_setfield)
+       MRP_LUA_OVERRIDE_STRINGIFY (output_stringify)
+    )
+);
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    output_mask,                /* class name */
+    scripting_output_mask_t,    /* userdata type */
+    output_mask_destroy,        /* userdata destructor */
+    MRP_LUA_METHOD_LIST (       /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR (output_mask_create_from_lua)
+    ),
+    MRP_LUA_METHOD_LIST (       /* overrides */
+       MRP_LUA_OVERRIDE_CALL      (output_mask_create_from_lua)
+       MRP_LUA_OVERRIDE_GETFIELD  (output_mask_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD  (output_mask_setfield)
+       MRP_LUA_OVERRIDE_STRINGIFY (output_mask_stringify)
+    )
+);
+
+
+
+
+void mrp_wayland_scripting_output_init(lua_State *L)
+{
+    MRP_ASSERT(L, "invalid argument");
+
+    mrp_lua_create_object_class(L, OUTPUT_CLASS);
+    mrp_lua_create_object_class(L, OUTPUT_MASK_CLASS);
+}
+
+
+mrp_wayland_output_t *mrp_wayland_scripting_output_check(lua_State *L, int idx)
+{
+    scripting_output_t *o;
+    mrp_wayland_output_t *out;
+
+    if ((o = output_check(L, idx)) && (out = o->out)) {
+        MRP_ASSERT(out->scripting_data == (void *)o,
+                   "confused with data structures");
+        return out;
+    }
+
+    return NULL;
+}
+
+mrp_wayland_output_t *mrp_wayland_scripting_output_unwrap(void *void_o)
+{
+    scripting_output_t *o = (scripting_output_t *)void_o;
+
+    if (o && mrp_lua_get_object_classdef(o) == OUTPUT_CLASS)
+        return o->out;
+
+    return NULL;
+}
+
+void *mrp_wayland_scripting_output_create_from_c(lua_State *L,
+                                                 mrp_wayland_output_t *out)
+{
+    scripting_output_t *o;
+    mrp_wayland_t *wl;
+
+    MRP_ASSERT(out && out->interface && out->interface->wl, "invald argument");
+    
+    wl = out->interface->wl;
+    
+    if (!wl->create_scripting_outputs)
+        o = NULL;
+    else if (out->scripting_data)
+        o = out->scripting_data;
+    else {
+        if (!L && !(L = mrp_lua_get_lua_state())) {
+            mrp_log_error("can't create scripting output %d: LUA is "
+                          "not initialized", out->outputid);
+            return NULL;
+        }
+
+        o = (scripting_output_t *)mrp_lua_create_object(L, OUTPUT_CLASS, NULL,
+                                                        out->outputid + 1);
+        if (!o) {
+            mrp_log_error("can't create scripting output %d: LUA object "
+                          "creation failed", out->outputid);
+        }
+        else {
+            o->out = out;
+            mrp_wayland_output_set_scripting_data(out, o);
+            lua_pop(L, 1);
+        }
+    }
+
+    return o;
+}
+
+void mrp_wayland_scripting_output_destroy_from_c(lua_State *L,
+                                                 mrp_wayland_output_t *out)
+{
+    scripting_output_t *o;
+
+    MRP_ASSERT(out, "invalid argument");
+
+    if (!L && !(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("can't destroy scripting output %d: LUA is "
+                      "not initialized", out->outputid);
+        out->scripting_data = NULL;
+        return;
+    }
+
+    if ((o = out->scripting_data)) {
+        mrp_debug("destroy scripting output %d", out->outputid);
+
+         o->out = NULL;
+
+         mrp_lua_destroy_object(L, NULL,out->outputid+1, out->scripting_data);
+
+         out->scripting_data = NULL;
+    }
+}
+
+
+static int output_create_from_lua(lua_State *L)
+{
+    MRP_LUA_ENTER;
+
+    luaL_error(L, "can't create output from lua");
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int output_getfield(lua_State *L)
+{
+    scripting_output_t *o;
+    mrp_wayland_output_t *out;
+    const char *fldnam;
+    mrp_wayland_scripting_field_t fld;
+
+    MRP_LUA_ENTER;
+
+    fld = mrp_wayland_scripting_field_check(L, 2, &fldnam);
+    lua_pop(L, 1);
+
+    o = output_check(L, 1);
+
+    if (!o || !(out = o->out))
+        lua_pushnil(L);
+    else {
+        switch (fld) {
+        case INDEX:        lua_pushinteger(L, out->index);               break;
+        case ID:           lua_pushinteger(L, out->outputid);            break;
+        case NAME:         lua_pushstring(L, out->outputname ?
+                                          out->outputname : "");         break;
+        case PIXEL_X:      lua_pushinteger(L, out->pixel_x);             break;
+        case PIXEL_Y:      lua_pushinteger(L, out->pixel_y);             break;
+        case PIXEL_WIDTH:  lua_pushinteger(L, out->pixel_width);         break;
+        case PIXEL_HEIGHT: lua_pushinteger(L, out->pixel_height);        break;
+        case WIDTH:        lua_pushinteger(L, out->width);               break;
+        case HEIGHT:       lua_pushinteger(L, out->height);              break;
+        case MAKE:         lua_pushstring(L, out->make ? out->make:"");  break;
+        case MODEL:        lua_pushstring(L, out->model?out->model:"");  break;
+        case ROTATE:       lua_pushinteger(L, out->rotate);              break;
+        case FLIP:         lua_pushboolean(L, out->flip);                break;
+        default:           lua_pushnil(L);                               break;
+        }
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int  output_setfield(lua_State *L)
+{
+    MRP_LUA_ENTER;
+
+    output_check(L, 1);
+    luaL_error(L, "output objects are read-only");
+
+    MRP_LUA_LEAVE(0);
+}
+
+static int  output_stringify(lua_State *L)
+{
+#define ALL_FIELDS (MRP_WAYLAND_OUTPUT_END_MASK - 1)
+
+    scripting_output_t *o;
+    mrp_wayland_output_t *out;
+    char *p, *e;
+    char buf[4096];
+
+    MRP_LUA_ENTER;
+
+    o = output_check(L, 1);
+
+    if (!o || !(out = o->out))
+        lua_pushnil(L);
+    else {
+        e = (p = buf) + sizeof(buf);
+        p += snprintf(p, e-p, "output %d", out->index);
+        p += mrp_wayland_output_print(out, ALL_FIELDS, p, e-p);
+
+        lua_pushlstring(L, buf, p-buf);
+    }
+
+    MRP_LUA_LEAVE(1);
+
+#undef ALL_FIELDS
+}
+
+static void output_destroy_from_lua(void *data)
+{
+    scripting_output_t *o = (scripting_output_t *)data;
+
+    MRP_LUA_ENTER;
+
+    if (o && o->out) {
+        mrp_wayland_output_set_scripting_data(o->out, NULL);
+    }
+
+    MRP_LUA_LEAVE_NOARG;
+}
+
+
+static scripting_output_t *output_check(lua_State *L, int idx)
+{
+    return (scripting_output_t *)mrp_lua_check_object(L, OUTPUT_CLASS, idx);
+}
+
+
+
+void *mrp_wayland_scripting_output_mask_create_from_c(lua_State *L,
+                                                      uint32_t mask)
+{
+    scripting_output_mask_t *um;
+
+    um = (scripting_output_mask_t *)mrp_lua_create_object(L, OUTPUT_MASK_CLASS,
+                                                          NULL, 0);
+    if (!um)
+        mrp_log_error("can't create output_mask");
+    else
+        um->mask = mask;
+
+    return um;
+}
+
+static int output_mask_create_from_lua(lua_State *L)
+{
+    size_t fldnamlen;
+    const char *fldnam;
+    scripting_output_mask_t *um;
+    mrp_wayland_scripting_field_t fld;
+    uint32_t m;
+    uint32_t mask = 0;
+
+    MRP_LUA_ENTER;
+
+    luaL_checktype(L, 2, LUA_TTABLE);
+
+    MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
+        fld = mrp_wayland_scripting_field_name_to_type(fldnam, fldnamlen);
+
+        if (fld == MASK)
+            mask = lua_tointeger(L, -1);
+        else if ((m = get_output_mask(fld)))
+            mask |= m;
+        else
+            luaL_error(L, "bad field '%s'", fldnam);
+    }
+
+    um = (scripting_output_mask_t *)mrp_lua_create_object(L, OUTPUT_MASK_CLASS,
+                                                          NULL, 0);
+    if (!um)
+        luaL_error(L, "can't create output_mask");
+
+    um->mask = mask;
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int output_mask_getfield(lua_State *L)
+{
+    scripting_output_mask_t *um;
+    mrp_wayland_scripting_field_t fld;
+    uint32_t m;
+
+    MRP_LUA_ENTER;
+
+    um = output_mask_check(L, 1);
+    fld = mrp_wayland_scripting_field_check(L, 2, NULL);
+
+    lua_pop(L, 1);
+
+    if (!um)
+        lua_pushnil(L);
+    else {
+        if (fld == MASK)
+            lua_pushinteger(L, um->mask);
+        else if ((m = get_output_mask(fld)))
+            lua_pushboolean(L, (um->mask & m) ? 1 : 0);
+        else
+            lua_pushnil(L);
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int output_mask_setfield(lua_State *L)
+{
+    scripting_output_mask_t *um;
+    uint32_t m;
+    mrp_wayland_scripting_field_t fld;
+
+    MRP_LUA_ENTER;
+
+    um = output_mask_check(L, 1);
+    fld = mrp_wayland_scripting_field_check(L, 2, NULL);
+
+    lua_pop(L, 2);
+
+    if (um) {
+        if (fld == MASK)
+            um->mask = lua_tointeger(L, 3);
+        else if ((m = get_output_mask(fld))) {
+            um->mask &= ~m;
+
+            if (lua_toboolean(L, 3))
+                um->mask |= m;
+        }
+    }
+
+    MRP_LUA_LEAVE(0);
+}
+
+static int output_mask_stringify(lua_State *L)
+{
+    scripting_output_mask_t *um;
+    uint32_t m, mask;
+    char buf[4096];
+    char *p, *e;
+    const char *name;
+
+
+    MRP_LUA_ENTER;
+
+    um = output_mask_check(L, 1);
+    e = (p = buf) + sizeof(buf);
+    *p = 0;
+
+    mask = um->mask;
+
+    for (m = 1;  mask && m < MRP_WAYLAND_OUTPUT_END_MASK && p < e;   m <<= 1) {
+        if ((mask & m)) {
+            mask &= ~m;
+
+            if ((name = mrp_wayland_output_update_mask_str(m)))
+                p += snprintf(p, e-p, "%s%s", p > buf ? " | " : "", name);
+        }
+    }
+
+    lua_pushstring(L, (p > buf) ? buf : "<empty>");
+
+    MRP_LUA_LEAVE(1);
+}
+
+static void output_mask_destroy(void *data)
+{
+    scripting_output_mask_t *um = (scripting_output_mask_t *)data;
+
+    MRP_UNUSED(um);
+}
+
+static scripting_output_mask_t *output_mask_check(lua_State *L, int idx)
+{
+    return (scripting_output_mask_t *)mrp_lua_check_object(L,OUTPUT_MASK_CLASS,
+                                                           idx);
+}
+
+static uint32_t get_output_mask(mrp_wayland_scripting_field_t fld)
+{
+    switch (fld) {
+    case ID:           return MRP_WAYLAND_OUTPUT_OUTPUTID_MASK;
+    case PIXEL_X:      return MRP_WAYLAND_OUTPUT_PIXEL_X_MASK;
+    case PIXEL_Y:      return MRP_WAYLAND_OUTPUT_PIXEL_Y_MASK;
+    case PIXEL_WIDTH:  return MRP_WAYLAND_OUTPUT_PIXEL_WIDTH_MASK;
+    case PIXEL_HEIGHT: return MRP_WAYLAND_OUTPUT_PIXEL_HEIGHT_MASK;
+    case WIDTH:        return MRP_WAYLAND_OUTPUT_WIDTH_MASK;
+    case HEIGHT:       return MRP_WAYLAND_OUTPUT_HEIGHT_MASK;
+    case SUBPIXEL:     return MRP_WAYLAND_OUTPUT_SUBPIXEL_MASK;
+    case MAKE:         return MRP_WAYLAND_OUTPUT_MAKE_MASK;
+    case MODEL:        return MRP_WAYLAND_OUTPUT_MODEL_MASK;
+    case ROTATE:       return MRP_WAYLAND_OUTPUT_ROTATE_MASK;
+    case FLIP:         return MRP_WAYLAND_OUTPUT_FLIP_MASK;
+    default:           return 0;
+    }
+}
diff --git a/src/plugins/system-controller/wayland/scripting-wayland.c b/src/plugins/system-controller/wayland/scripting-wayland.c
new file mode 100644 (file)
index 0000000..bac8e7a
--- /dev/null
@@ -0,0 +1,584 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+#include <murphy/core/lua-bindings/murphy.h>
+#include <murphy/core/lua-utils/error.h>
+#include <murphy/core/lua-utils/object.h>
+#include <murphy/core/lua-utils/funcbridge.h>
+
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include "scripting-wayland.h"
+#include "output.h"
+#include "area.h"
+#include "window.h"
+#include "layer.h"
+#include "animation.h"
+
+
+
+void mrp_wayland_scripting_init(lua_State *L)
+{
+    mrp_wayland_scripting_window_manager_init(L);
+    mrp_wayland_scripting_animation_init(L);
+    mrp_wayland_scripting_window_init(L);
+    mrp_wayland_scripting_output_init(L);
+    mrp_wayland_scripting_area_init(L);
+    mrp_wayland_scripting_layer_init(L);
+}
+
+
+char *mrp_wayland_scripting_canonical_name(const char *name,
+                                           char *buf,
+                                           size_t len)
+{
+    const char *q;
+    char *p, *e, c;
+
+    if (len < 2)
+        return "";
+
+    e = (p = buf) + (len - 1);
+    q = name;
+
+    if (isdigit(*q))
+        *p++ = '_';
+
+    while ((c = *q++) && p < e)
+        *p++ = isalnum(c) ? c : '_';
+
+    *p = 0;
+
+    return buf;
+}
+
+
+int mrp_wayland_json_integer_copy(mrp_wayland_t *wl, void *uval,
+                                  mrp_json_t *jval, int mask)
+{
+    const char *str;
+    int32_t val;
+    char *e;
+
+    MRP_UNUSED(wl);
+
+    if (mrp_json_is_type(jval, MRP_JSON_INTEGER)) {
+        *(int32_t *)uval = mrp_json_integer_value(jval);
+        return mask;
+    }
+
+    if (mrp_json_is_type(jval, MRP_JSON_STRING)) {
+        str = mrp_json_string_value(jval);
+        val = strtol(str, &e, 10);
+
+        if (e > str && !*e) {
+            *(int32_t *)uval = val;
+            return mask;
+        }
+    }
+
+    return 0;
+}
+
+int mrp_wayland_json_string_copy(mrp_wayland_t *wl, void *uval,
+                                 mrp_json_t *jval, int mask)
+{
+    MRP_UNUSED(wl);
+
+    if (mrp_json_is_type(jval, MRP_JSON_STRING)) {
+        *(const char **)uval = mrp_json_string_value(jval);
+        return mask;
+    }
+
+    return 0;
+}
+
+int mrp_wayland_json_boolean_copy(mrp_wayland_t *wl, void *uval,
+                                  mrp_json_t *jval, int mask)
+{
+    const char *str;
+
+    MRP_UNUSED(wl);
+
+    if (mrp_json_is_type(jval, MRP_JSON_BOOLEAN)) {
+        *(bool *)uval = mrp_json_boolean_value(jval) ? true : false;
+        return mask;
+    }
+
+    if (mrp_json_is_type(jval, MRP_JSON_INTEGER)) {
+        *(bool *)uval = mrp_json_integer_value(jval) ? true : false;
+        return mask;
+    }
+
+    if (mrp_json_is_type(jval, MRP_JSON_STRING)) {
+        str = mrp_json_string_value(jval);
+        
+        if (!strcmp(str,"yes") || !strcmp(str,"on") || !strcmp(str,"true")) {
+            *(bool *)uval = true;
+            return mask;
+        }
+
+        if (!strcmp(str,"no") || !strcmp(str,"off") || !strcmp(str,"false")) {
+            *(bool *)uval = false;
+            return mask;
+        }
+    }
+
+    return 0;
+}
+
+int mrp_wayland_json_layer_copy(mrp_wayland_t *wl, void *uval,
+                                mrp_json_t *jval, int mask)
+{
+    int32_t layerid;
+    mrp_wayland_layer_t *layer;
+
+    if (!mrp_json_is_type(jval, MRP_JSON_INTEGER))
+        return 0;
+
+    layerid = mrp_json_integer_value(jval);
+
+    if (!(layer = mrp_wayland_layer_find(wl, layerid)))
+        return 0;
+
+    *(mrp_wayland_layer_t **)uval = layer;
+
+    return mask;
+}
+
+int mrp_wayland_json_output_copy(mrp_wayland_t *wl, void *uval,
+                                 mrp_json_t *jval, int mask)
+{
+    uint32_t index;
+    mrp_wayland_output_t *out;
+
+    if (!mrp_json_is_type(jval, MRP_JSON_INTEGER))
+        return 0;
+
+    index = mrp_json_integer_value(jval);
+
+    if (!(out = mrp_wayland_output_find(wl, index)))
+        return 0;
+
+    *(mrp_wayland_output_t **)uval = out;
+
+    return mask;
+}
+
+int mrp_wayland_json_area_copy(mrp_wayland_t *wl, void *uval,
+                               mrp_json_t *jval, int mask)
+{
+    const char *fullname;
+    mrp_wayland_area_t *area;
+
+    if (!mrp_json_is_type(jval, MRP_JSON_STRING))
+        return 0;
+
+    fullname = mrp_json_string_value(jval);
+
+    if (!(area = mrp_wayland_area_find(wl, fullname)))
+        return 0;
+
+    *(mrp_wayland_area_t **)uval = area;
+
+    return mask;
+}
+
+int mrp_wayland_json_align_copy(mrp_wayland_t *wl, void *uval,
+                                mrp_json_t *jval, int mask)
+{
+    const char *key;
+    mrp_json_t *val;
+    mrp_json_iter_t it;
+    mrp_wayland_scripting_field_t fldid, valid;
+    const char *valstr;
+    mrp_wayland_area_align_t align;
+
+    MRP_UNUSED(wl);
+
+    if (!mrp_json_is_type(jval, MRP_JSON_ARRAY) &&
+        !mrp_json_is_type(jval, MRP_JSON_INTEGER))
+        return 0;
+
+    if (mrp_json_is_type(jval, MRP_JSON_INTEGER))
+        align = mrp_json_integer_value(jval);
+    else {
+        align = 0;
+        mrp_json_foreach_member(jval, key,val, it) {
+            if (!mrp_json_is_type(val, MRP_JSON_STRING))
+                return 0;
+            valstr = mrp_json_string_value(val);
+            fldid = mrp_wayland_scripting_field_name_to_type(key, -1);
+            valid = mrp_wayland_scripting_field_name_to_type(valstr, -1);
+            switch (fldid) {
+            case HORIZONTAL:
+                switch (valid) {
+                case LEFT:    align |= MRP_WAYLAND_AREA_ALIGN_LEFT;   break;
+                case RIGHT:   align |= MRP_WAYLAND_AREA_ALIGN_RIGHT;  break;
+                case MIDDLE:  align |= MRP_WAYLAND_AREA_ALIGN_MIDDLE; break;
+                default:      /* invalid alignement */                return 0;
+                }
+                break;
+            case VERTICAL:
+                switch (valid) {
+                case TOP:     align |= MRP_WAYLAND_AREA_ALIGN_TOP;    break;
+                case BOTTOM:  align |= MRP_WAYLAND_AREA_ALIGN_BOTTOM; break;
+                case MIDDLE:  align |= MRP_WAYLAND_AREA_ALIGN_MIDDLE; break;
+                default:      /* invalid alignement */                return 0;
+                }
+                break;
+            default:
+                return 0;
+            }
+        }
+    }
+
+    *(mrp_wayland_area_align_t *)uval = align;
+
+    return mask;
+}
+
+
+
+mrp_wayland_scripting_field_t
+mrp_wayland_scripting_field_check(lua_State *L,int idx,const char **ret_fldnam)
+{
+    const char *fldnam;
+    size_t fldnamlen;
+    mrp_wayland_scripting_field_t fldtyp;
+
+    if (!(fldnam = lua_tolstring(L, idx, &fldnamlen)))
+        fldtyp = 0;
+    else
+        fldtyp = mrp_wayland_scripting_field_name_to_type(fldnam, fldnamlen);
+
+    if (ret_fldnam)
+        *ret_fldnam = fldnam;
+
+    return fldtyp;
+}
+
+mrp_wayland_scripting_field_t
+mrp_wayland_scripting_field_name_to_type(const char *name, ssize_t len)
+{
+    if (len < 0)
+        len = strlen(name);
+
+    switch (len) {
+
+    case 2:
+        if (!strcmp(name, "id"))
+            return ID;
+        break;
+
+    case 3:
+        switch (name[0]) {
+        case 'p':
+            if (!strcmp(name, "pid"))
+                return PID;
+            break;
+        case 't':
+            if (!strcmp(name, "top"))
+                return TOP;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case 4:
+        switch (name[0]) {
+        case 'a':
+            if (!strcmp(name, "area"))
+                return AREA;
+            break;
+        case 'f':
+            if (!strcmp(name, "flip"))
+                return FLIP;
+            break;
+        case 'h':
+            if (!strcmp(name, "hide"))
+                return HIDE;
+            break;
+        case 'l':
+            if (!strcmp(name, "left"))
+                return LEFT;
+            break;
+        case 'm':
+            if (!strcmp(name, "make"))
+                return MAKE;
+            if (!strcmp(name, "mask"))
+                return MASK;
+            if (!strcmp(name, "move"))
+                return MOVE;
+            break;
+        case 'n':
+            if (!strcmp(name, "name"))
+                return NAME;
+            if (!strcmp(name, "node"))
+                return NODE;
+            break;
+        case 's':
+            if (!strcmp(name, "show"))
+                return SHOW;
+            if (!strcmp(name, "size"))
+                return SIZE;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case 5:
+        switch(name[0]) {
+        case 'a':
+            if (!strcmp(name, "align"))
+                return ALIGN;
+            if (!strcmp(name, "appid"))
+                return APPID;
+            break;
+        case 'i':
+            if (!strcmp(name, "index"))
+                return INDEX;
+            break;
+        case 'l':
+            if (!strcmp(name, "layer"))
+                return LAYER;
+            break;
+        case 'm':
+            if (!strcmp(name, "model"))
+                return MODEL;
+            break;
+        case 'p':
+            if (!strcmp(name, "pos_x"))
+                return POS_X;
+            if (!strcmp(name, "pos_y"))
+                return POS_Y;
+            break;
+        case 'r':
+            if (!strcmp(name, "raise"))
+                return RAISE;
+            if (!strcmp(name, "right"))
+                return RIGHT;
+            break;
+        case 'w':
+            if (!strcmp(name, "width"))
+                return WIDTH;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case 6:
+        switch (name[0]) {
+        case 'a':
+            if (!strcmp(name, "active"))
+                return ACTIVE;
+            break;
+        case 'b':
+            if (!strcmp(name, "bottom"))
+                return BOTTOM;
+            break;
+        case 'h':
+            if (!strcmp(name, "height"))
+                return HEIGHT;
+            break;
+        case 'l':
+            if (!strcmp(name, "layers"))
+                return LAYERS;
+            break;
+        case 'm':
+            if (!strcmp(name, "mapped"))
+                return MAPPED;
+            if (!strcmp(name, "middle"))
+                return MIDDLE;
+            break;
+        case 'o':
+            if (!strcmp(name, "output"))
+                return OUTPUT;
+            break;
+        case 'r':
+            if (!strcmp(name, "resize"))
+                return RESIZE;
+            if (!strcmp(name, "rotate"))
+                return ROTATE;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case 7:
+        switch (name[0]) {
+        case 'd':
+            if (!strcmp(name, "display"))
+                return DISPLAY;
+            break;
+        case 'p':
+            if (!strcmp(name, "pixel_x"))
+                return PIXEL_X;
+            if (!strcmp(name, "pixel_y"))
+                return PIXEL_Y;
+            break;
+        case 's':
+            if (!strcmp(name, "surface"))
+                return SURFACE;
+            break;
+        case 'v':
+            if (!strcmp(name, "visible"))
+                return VISIBLE;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case 8:
+        switch (name[0]) {
+        case 'p':
+            if (!strcmp(name, "position"))
+                return POSITION;
+            break;
+        case 's':
+            if (!strcmp(name, "subpixel"))
+                return SUBPIXEL;
+            break;
+        case 'v':
+            if (!strcmp(name, "vertical"))
+                return VERTICAL;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case 9:
+        if (!strcmp(name, "layertype"))
+            return LAYERTYPE;
+        break;
+
+    case 10:
+        switch (name[0]) {
+        case 'h':
+            if (!strcmp(name, "horizontal"))
+                return HORIZONTAL;
+            break;
+        case 'k':
+            if (!strcmp(name, "keep_ratio"))
+                return KEEPRATIO;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case 11:
+        switch (name[0]) {
+        case 'a':
+            if (!strcmp(name, "area_create"))
+                return AREA_CREATE;
+            break;
+        case 'p':
+            if (!strcmp(name, "pixel_width"))
+                return PIXEL_WIDTH;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case 12:
+        switch (name[0]) {
+        case 'l':
+            if (!strcmp(name, "layer_update"))
+                return LAYER_UPDATE;
+            break;
+        case 'p':
+            if (!strcmp(name, "pixel_height"))
+                return PIXEL_HEIGHT;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case 13:
+        switch (name[0]) {
+        case 'l':
+            if (!strcmp(name, "layer_request"))
+                return LAYER_REQUEST;
+            break;
+        case 'o':
+            if (!strcmp(name, "output_update"))
+                return OUTPUT_UPDATE;
+            break;
+        case 'w':
+            if (!strcmp(name, "window_update"))
+                return WINDOW_UPDATE;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    case 14:
+        switch (name[0]) {
+        case 'o':
+            if (!strcmp(name, "output_request"))
+                return OUTPUT_REQUEST;
+            break;
+        case 'w':
+            if (!strcmp(name, "window_manager"))
+                return WINDOW_MANAGER;
+            if (!strcmp(name, "window_request"))
+                return WINDOW_REQUEST;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    default:
+        break;
+    }
+
+    return 0;
+}
+
diff --git a/src/plugins/system-controller/wayland/scripting-wayland.h b/src/plugins/system-controller/wayland/scripting-wayland.h
new file mode 100644 (file)
index 0000000..4c5b903
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_WAYLAND_SCRIPTING_H__
+#define __MURPHY_WAYLAND_SCRIPTING_H__
+
+#include <lua.h>
+
+#include <murphy/core/lua-bindings/lua-json.h>
+
+#include "wayland/wayland.h"
+
+typedef int (*mrp_wayland_json_copy_func_t)(mrp_wayland_t *, void *,
+                                            mrp_json_t *, int);
+
+void mrp_wayland_scripting_init(lua_State *L);
+char *mrp_wayland_scripting_canonical_name(const char *name, char *buf,
+                                                size_t len);
+
+/* scripting-window-manager.c */
+void mrp_wayland_scripting_window_manager_init(lua_State *L);
+
+mrp_wayland_t *mrp_wayland_scripting_window_manager_check(lua_State *L,
+                                                          int idx);
+mrp_wayland_t *mrp_wayland_scripting_window_manager_unwrap(void *wmgr);
+
+/* scripting-animation.c */
+void mrp_wayland_scripting_animation_init(lua_State *L);
+mrp_wayland_animation_t *mrp_wayland_scripting_animation_check(lua_State *L,
+                                                               int idx);
+mrp_wayland_animation_t *mrp_wayland_scripting_animation_unwrap(void *void_an);
+
+/* scripting-window.c */
+void mrp_wayland_scripting_window_init(lua_State *);
+
+mrp_wayland_window_t *mrp_wayland_scripting_window_check(lua_State *L,int idx);
+mrp_wayland_window_t *mrp_wayland_scripting_window_unwrap(void *void_w);
+void *mrp_wayland_scripting_window_create_from_c(lua_State *L,
+                                                 mrp_wayland_window_t *win);
+void mrp_wayland_scripting_window_destroy_from_c(lua_State *L,
+                                                 mrp_wayland_window_t *win);
+
+uint32_t mrp_wayland_scripting_window_mask_check(lua_State *L, int idx);
+uint32_t mrp_wayland_scripting_window_mask_unwrap(void *void_um);
+void *mrp_wayland_scripting_window_mask_create_from_c(lua_State *L,
+                                                      uint32_t mask);
+
+/* scripting-output.c */
+void mrp_wayland_scripting_output_init(lua_State *L);
+
+mrp_wayland_output_t *mrp_wayland_scripting_output_check(lua_State *L,int idx);
+mrp_wayland_output_t *mrp_wayland_scripting_output_unwrap(void *void_o);
+void *mrp_wayland_scripting_output_create_from_c(lua_State *L,
+                                                 mrp_wayland_output_t *out);
+void mrp_wayland_scripting_output_destroy_from_c(lua_State *L,
+                                                 mrp_wayland_output_t *out);
+
+void *mrp_wayland_scripting_output_mask_create_from_c(lua_State *L,
+                                                      uint32_t mask);
+
+/* scripting-area.c */
+void mrp_wayland_scripting_area_init(lua_State *L);
+
+mrp_wayland_area_t *mrp_wayland_scripting_area_check(lua_State *L, int idx);
+mrp_wayland_area_t *mrp_wayland_scripting_area_unwrap(void *void_a);
+int mrp_wayland_scripting_area_push(lua_State *L, mrp_wayland_area_t *area);
+void *mrp_wayland_scripting_area_create_from_c(lua_State *L,
+                                               mrp_wayland_area_t *area);
+void mrp_wayland_scripting_area_destroy_from_c(lua_State *L,
+                                               mrp_wayland_area_t *area);
+
+void *mrp_wayland_scripting_align_mask_create_from_c(lua_State *L,
+                                                     uint32_t mask);
+
+
+/* scripting-layer.c */
+void mrp_wayland_scripting_layer_init(lua_State *L);
+
+mrp_wayland_layer_t *mrp_wayland_scripting_layer_check(lua_State *L, int idx);
+mrp_wayland_layer_t *mrp_wayland_scripting_layer_unwrap(void *void_l);
+void *mrp_wayland_scripting_layer_create_from_c(lua_State *L,
+                                                mrp_wayland_layer_t *layer);
+void mrp_wayland_scripting_layer_destroy_from_c(lua_State *L,
+                                                mrp_wayland_layer_t *layer);
+
+void *mrp_wayland_scripting_layer_mask_create_from_c(lua_State *L,
+                                                     uint32_t mask);
+
+/* internal for scripting-window-manager.c files  */
+int mrp_wayland_json_integer_copy(mrp_wayland_t *wl, void *uval,
+                                  mrp_json_t *jval, int mask);
+int mrp_wayland_json_string_copy(mrp_wayland_t *wl, void *uval,
+                                 mrp_json_t *jval, int mask);
+int mrp_wayland_json_boolean_copy(mrp_wayland_t *wl, void *uval,
+                                  mrp_json_t *jval, int mask);
+int mrp_wayland_json_layer_copy(mrp_wayland_t *wl, void *uval,
+                                mrp_json_t *jval, int mask);
+int mrp_wayland_json_output_copy(mrp_wayland_t *wl, void *uval,
+                                 mrp_json_t *jval, int mask);
+int mrp_wayland_json_area_copy(mrp_wayland_t *wl, void *uval,
+                               mrp_json_t *jval, int mask);
+int mrp_wayland_json_align_copy(mrp_wayland_t *wl, void *uval,
+                                mrp_json_t *jval, int mask);
+
+mrp_wayland_scripting_field_t
+mrp_wayland_scripting_field_check(lua_State *, int, const char **);
+
+mrp_wayland_scripting_field_t
+mrp_wayland_scripting_field_name_to_type(const char *, ssize_t);
+
+
+#endif /* __MURPHY_WAYLAND_SCRIPTING_H__ */
diff --git a/src/plugins/system-controller/wayland/scripting-window-manager.c b/src/plugins/system-controller/wayland/scripting-window-manager.c
new file mode 100644 (file)
index 0000000..5443eae
--- /dev/null
@@ -0,0 +1,964 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+#include <murphy/core/lua-bindings/murphy.h>
+#include <murphy/core/lua-utils/error.h>
+#include <murphy/core/lua-utils/object.h>
+#include <murphy/core/lua-utils/funcbridge.h>
+
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include "scripting-wayland.h"
+#include "animation.h"
+#include "window.h"
+#include "layer.h"
+#include "output.h"
+#include "area.h"
+#include "ico-window-manager.h"
+
+#define WINDOW_MANAGER_CLASS   MRP_LUA_CLASS_SIMPLE(window_manager)
+
+typedef struct scripting_winmgr_s  scripting_winmgr_t;
+typedef struct funcbridge_def_s    funcbridge_def_t;
+typedef struct layer_def_s         layer_def_t;
+typedef struct request_def_s       request_def_t;
+
+struct scripting_winmgr_s {
+    mrp_wayland_t *wl;
+    const char *name;
+    const char *display;
+    mrp_funcbridge_t *output_update;
+    mrp_funcbridge_t *layer_update;
+    mrp_funcbridge_t *window_update;
+};
+
+struct funcbridge_def_s {
+    const char *name;
+    const char *sign;
+    mrp_funcbridge_cfunc_t func;
+    void *data;
+    mrp_funcbridge_t **ptr;
+};
+
+
+struct layer_def_s {
+    int32_t id;
+    const char *name;
+    int32_t type;
+};
+
+struct request_def_s {
+    const char *name;
+    int offset;
+    int mask;
+    mrp_wayland_json_copy_func_t copy;
+};
+
+
+static int  window_manager_create(lua_State *);
+static int  window_manager_connect(lua_State *);
+static int  window_manager_canonical_name(lua_State *);
+static int  window_manager_getfield(lua_State *);
+static int  window_manager_setfield(lua_State *);
+static void window_manager_destroy(void *);
+
+static scripting_winmgr_t *window_manager_check(lua_State *, int);
+
+static layer_def_t *layer_def_check(lua_State *, int);
+static void layer_def_free(layer_def_t *);
+
+
+static bool window_request_bridge(lua_State *, void *,
+                                  const char *, mrp_funcbridge_value_t *,
+                                  char *, mrp_funcbridge_value_t *);
+static void window_update_callback(mrp_wayland_t *,
+                                   mrp_wayland_window_operation_t,
+                                   mrp_wayland_window_update_mask_t,
+                                   mrp_wayland_window_t *);
+
+static bool output_request_bridge(lua_State *, void *,
+                                  const char *, mrp_funcbridge_value_t *,
+                                  char *, mrp_funcbridge_value_t *);
+static void output_update_callback(mrp_wayland_t *,
+                                   mrp_wayland_output_operation_t,
+                                   mrp_wayland_output_update_mask_t,
+                                   mrp_wayland_output_t *);
+
+static bool area_create_bridge(lua_State *, void *,
+                               const char *, mrp_funcbridge_value_t *,
+                               char *, mrp_funcbridge_value_t *);
+
+static bool layer_request_bridge(lua_State *, void *,
+                                 const char *, mrp_funcbridge_value_t *,
+                                 char *, mrp_funcbridge_value_t *);
+static void layer_update_callback(mrp_wayland_t *,
+                                  mrp_wayland_layer_operation_t,
+                                  mrp_wayland_layer_update_mask_t,
+                                  mrp_wayland_layer_t *);
+
+static uint32_t copy_json_fields(mrp_wayland_t *, mrp_json_t *,
+                                 request_def_t *, void *);
+static bool register_methods(lua_State *);
+
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    window_manager,                /* class name */
+    scripting_winmgr_t,            /* userdata type */
+    window_manager_destroy,        /* userdata destructor */
+    MRP_LUA_METHOD_LIST (          /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR    (window_manager_create)
+       MRP_LUA_METHOD(connect,        window_manager_connect)
+       MRP_LUA_METHOD(canonical_name, window_manager_canonical_name)
+    ),
+    MRP_LUA_METHOD_LIST (          /* overrides */
+       MRP_LUA_OVERRIDE_CALL         (window_manager_create)
+       MRP_LUA_OVERRIDE_GETFIELD     (window_manager_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD     (window_manager_setfield)
+    )
+);
+
+static mrp_funcbridge_t *output_request;
+static mrp_funcbridge_t *area_create;
+static mrp_funcbridge_t *layer_request;
+static mrp_funcbridge_t *window_request;
+
+
+void mrp_wayland_scripting_window_manager_init(lua_State *L)
+{
+    MRP_ASSERT(L, "invalid argument");
+
+    mrp_lua_create_object_class(L, WINDOW_MANAGER_CLASS);
+    register_methods(L);
+}
+
+mrp_wayland_t *mrp_wayland_scripting_window_manager_check(lua_State *L,int idx)
+{
+    scripting_winmgr_t *wmgr;
+    mrp_wayland_t *wl;
+
+    if ((wmgr = window_manager_check(L, idx)) && (wl = wmgr->wl)) {
+        MRP_ASSERT(wl->scripting_data == (void *)wmgr,
+                   "confused with data structures");
+        return wl;
+    }
+
+    return NULL;
+}
+
+mrp_wayland_t *mrp_wayland_scripting_window_manager_unwrap(void *void_wmgr)
+{
+    scripting_winmgr_t *wmgr = (scripting_winmgr_t *)void_wmgr;
+
+    if (wmgr && mrp_lua_get_object_classdef(wmgr) == WINDOW_MANAGER_CLASS)
+        return wmgr->wl;
+
+    return NULL;
+}
+
+static int window_manager_create(lua_State *L)
+{
+    mrp_context_t *ctx;
+    mrp_wayland_t *wl;
+    size_t fldnamlen;
+    const char *fldnam;
+    scripting_winmgr_t *winmgr;
+    mrp_wayland_layer_update_t lu;
+    char *name;
+    const char *display = NULL;
+    layer_def_t *layers = NULL;
+    mrp_funcbridge_t *output_update = NULL;
+    mrp_funcbridge_t *layer_update = NULL;
+    mrp_funcbridge_t *window_update = NULL;
+    char buf[256];
+    layer_def_t *l;
+    int table;
+
+    MRP_LUA_ENTER;
+
+    ctx = mrp_lua_get_murphy_context();
+
+    MRP_ASSERT(ctx && ctx->ml, "invalid app.context or missing mainloop");
+
+    luaL_checktype(L, 2, LUA_TTABLE);
+
+    winmgr = (scripting_winmgr_t*)mrp_lua_create_object(L,WINDOW_MANAGER_CLASS,
+                                                        NULL, 0);
+    if (!winmgr)
+        luaL_error(L, "can't create window manager on display '%s'", display);
+
+    table = lua_gettop(L);
+
+    MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
+        switch (mrp_wayland_scripting_field_name_to_type(fldnam, fldnamlen)) {
+
+        case DISPLAY:
+            display = luaL_checkstring(L, -1);
+            break;
+
+        case LAYERS:
+            layers = layer_def_check(L, -1);
+            break;
+
+        case OUTPUT_UPDATE:
+            output_update = mrp_funcbridge_create_luafunc(L, -1);
+            break;
+
+        case LAYER_UPDATE:
+            layer_update = mrp_funcbridge_create_luafunc(L, -1);
+            break;
+
+        case WINDOW_UPDATE:
+            window_update = mrp_funcbridge_create_luafunc(L, -1);
+            break;            
+
+        default:
+            lua_pushvalue(L, -2);
+            lua_pushvalue(L, -2);
+            lua_rawset(L, table);
+            break;
+        }
+    }
+
+    if (!display)
+        display = getenv("WAYLAND_DISPLAY");
+
+    if (!display)
+        display = "wayland-0";
+
+    name = mrp_wayland_scripting_canonical_name(display, buf, sizeof(buf));
+
+    if (!(wl = mrp_wayland_create(display, ctx->ml)))
+        luaL_error(L, "can't create wayland object");
+
+    mrp_lua_set_object_name(L, WINDOW_MANAGER_CLASS, name);
+
+    winmgr->wl = wl;
+    winmgr->name = mrp_strdup(name);
+    winmgr->display = mrp_strdup(display);
+    winmgr->output_update = output_update;
+    winmgr->layer_update = layer_update;
+    winmgr->window_update = window_update;
+
+    mrp_wayland_output_register(wl);
+    mrp_ico_window_manager_register(wl);
+
+    mrp_wayland_register_output_update_callback(wl, output_update_callback);
+    mrp_wayland_register_layer_update_callback(wl, layer_update_callback);
+    mrp_wayland_register_window_update_callback(wl, window_update_callback);
+
+    mrp_wayland_set_scripting_data(wl, winmgr);
+
+    mrp_wayland_create_scripting_windows(wl, true);
+    mrp_wayland_create_scripting_outputs(wl, true);
+    mrp_wayland_create_scripting_areas(wl, true);
+    mrp_wayland_create_scripting_layers(wl, true);
+
+    if (layers) {
+        memset(&lu, 0, sizeof(lu));
+        lu.mask = MRP_WAYLAND_LAYER_LAYERID_MASK |
+                  MRP_WAYLAND_LAYER_NAME_MASK    |
+                  MRP_WAYLAND_LAYER_TYPE_MASK    ;
+
+        for (l = layers;  l->name;  l++) {
+            lu.layerid = l->id;
+            lu.name = l->name;
+            lu.type = l->type;
+            mrp_wayland_layer_create(wl, &lu);
+        }
+
+        layer_def_free(layers);
+    }
+
+    lua_settop(L, table);
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int window_manager_connect(lua_State *L)
+{
+    scripting_winmgr_t *wmgr;
+    bool success;
+
+    MRP_LUA_ENTER;
+
+    wmgr = window_manager_check(L, 1);
+
+    if (wmgr->wl != NULL)
+        success = mrp_wayland_connect(wmgr->wl);
+    else
+        success = false;
+
+    lua_pushboolean(L, success);
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int  window_manager_canonical_name(lua_State *L)
+{
+    const char *name;
+    char *canonical;
+    char buf[2048];
+
+    MRP_LUA_ENTER;
+
+    *(canonical = buf) = 0;
+
+    if ((name = luaL_checkstring(L, 2)))
+        canonical = mrp_wayland_scripting_canonical_name(name,buf,sizeof(buf));
+
+    lua_pushstring(L, canonical);
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int window_manager_getfield(lua_State *L)
+{
+    scripting_winmgr_t *wmgr;
+    const char *fldnam;
+    mrp_wayland_scripting_field_t fld;
+
+    MRP_LUA_ENTER;
+
+    fld = mrp_wayland_scripting_field_check(L, 2, &fldnam);
+    lua_pop(L, 1);
+
+    wmgr = window_manager_check(L, 1);
+
+    if (!wmgr)
+        lua_pushnil(L);
+    else {
+        switch (fld) {
+
+        case DISPLAY:
+            lua_pushstring(L, wmgr->display);
+            break;
+
+        case OUTPUT_REQUEST:
+            mrp_funcbridge_push(L, output_request);
+            break;
+
+        case OUTPUT_UPDATE:
+            mrp_funcbridge_push(L, wmgr->output_update);
+            break;
+
+        case AREA_CREATE:
+            mrp_funcbridge_push(L, area_create);
+            break;
+
+        case LAYER_REQUEST:
+            mrp_funcbridge_push(L, layer_request);
+            break;
+
+        case LAYER_UPDATE:
+            mrp_funcbridge_push(L, wmgr->layer_update);
+            break;
+
+        case WINDOW_REQUEST:
+            mrp_funcbridge_push(L, window_request);
+            break;
+
+        case WINDOW_UPDATE:
+            mrp_funcbridge_push(L, wmgr->window_update);
+            break;
+
+        default:
+            lua_pushstring(L, fldnam);
+            lua_rawget(L, 1);
+            break;
+        }
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int  window_manager_setfield(lua_State *L)
+{
+    scripting_winmgr_t *wmgr;
+
+    MRP_LUA_ENTER;
+
+    wmgr = window_manager_check(L, 1);
+    luaL_error(L, "window manager '%s' is read-only", wmgr->display);
+
+    MRP_LUA_LEAVE(0);
+}
+
+static void window_manager_destroy(void *data)
+{
+    scripting_winmgr_t *winmgr = (scripting_winmgr_t *)data;
+
+    MRP_LUA_ENTER;
+
+    if (winmgr) {
+        mrp_free((void *)winmgr->name);
+        mrp_free((void *)winmgr->display);
+    }
+
+    MRP_LUA_LEAVE_NOARG;
+}
+
+static scripting_winmgr_t *window_manager_check(lua_State *L, int idx)
+{
+
+    return (scripting_winmgr_t *)mrp_lua_check_object(L, WINDOW_MANAGER_CLASS,
+                                                      idx);
+}
+
+static layer_def_t *layer_def_check(lua_State *L, int t)
+{
+    size_t tlen, dlen;
+    size_t size;
+    layer_def_t *layers, *l;
+    size_t i, j;
+
+    t = (t < 0) ? lua_gettop(L) + t + 1 : t;
+
+    luaL_checktype(L, t, LUA_TTABLE);
+    tlen  = lua_objlen(L, t);
+    size = sizeof(layer_def_t) * (tlen + 1);
+
+    if (!(layers = mrp_allocz(size)))
+        luaL_error(L, "can't allocate %d byte long memory", size);
+    else {
+        for (i = 0;  i < tlen;  i++) {
+            l = layers + i;
+
+            lua_pushinteger(L, (int)(i+1));
+            lua_gettable(L, t);
+
+            if (!lua_istable(L, -1))
+                goto error;
+
+            dlen = lua_objlen(L, -1);
+
+            for (j = 0;  j < dlen;  j++) {
+                lua_pushnumber(L, (int)(j+1));
+                lua_gettable(L, -2);
+
+                switch (j) {
+                case 0:    l->id = lua_tointeger(L, -1);               break;
+                case 1:    l->name = mrp_strdup(lua_tostring(L, -1));  break;
+                case 2:    l->type = lua_tointeger(L, -1);             break;
+                default:   goto error;
+                }
+
+                lua_pop(L, 1);
+            }
+
+            lua_pop(L, 1);
+
+            if (!l->name || l->id < 0 || l->id > 0x10000)
+                goto error;
+        }
+    }
+
+    return layers;
+
+ error:
+    layer_def_free(layers);
+    luaL_argerror(L, i+1, "malformed layer definition");
+    return NULL;
+}
+
+static void layer_def_free(layer_def_t *layers)
+{
+    layer_def_t *l;
+
+    if (layers) {
+        for (l = layers;  l->name;  l++)
+            mrp_free((void *)l->name);
+        mrp_free((void *)layers);
+    }
+}
+
+static bool window_request_bridge(lua_State *L,
+                                  void *data,
+                                  const char *signature,
+                                  mrp_funcbridge_value_t *args,
+                                  char *ret_type,
+                                  mrp_funcbridge_value_t *ret_val)
+{
+#define FIELD(f) MRP_OFFSET(mrp_wayland_window_update_t, f)
+#define MASK(m)  MRP_WAYLAND_WINDOW_ ## m ## _MASK
+#define TYPE(t)  mrp_wayland_json_ ## t ## _copy
+
+    static request_def_t   fields[] = {
+        { "surface", FIELD(surfaceid), MASK(SURFACEID), TYPE(integer) },
+        { "layer"  , FIELD(layer)    , MASK(LAYER)    , TYPE(layer)   },
+        { "node"   , FIELD(nodeid)   , MASK(NODEID)   , TYPE(integer) },
+        { "pos_x"  , FIELD(x)        , MASK(X)        , TYPE(integer) },
+        { "pos_y"  , FIELD(y)        , MASK(Y)        , TYPE(integer) },
+        { "width"  , FIELD(width)    , MASK(WIDTH)    , TYPE(integer) },
+        { "height" , FIELD(height)   , MASK(HEIGHT)   , TYPE(integer) },
+        { "raise"  , FIELD(raise)    , MASK(RAISE)    , TYPE(integer) },
+        { "visible", FIELD(visible)  , MASK(VISIBLE)  , TYPE(integer) },
+        { "active" , FIELD(active)   , MASK(ACTIVE)   , TYPE(integer) },
+        { "area"   , FIELD(area)     , MASK(AREA)     , TYPE(area)    },
+        {   NULL   ,        0        ,      0         ,      NULL     }
+    };
+
+#undef FIELD
+#undef MASK
+#undef TYPE
+
+    mrp_wayland_t *wl;
+    mrp_wayland_animation_t *anims;
+    mrp_wayland_window_update_t u;
+    uint32_t framerate;
+    mrp_json_t *json;
+
+    MRP_UNUSED(L);
+    MRP_UNUSED(data);
+    MRP_UNUSED(ret_val);
+    MRP_ASSERT(signature && args && ret_type, "invalid argument");
+
+    *ret_type = MRP_FUNCBRIDGE_NO_DATA;
+
+    if (strcmp(signature, "oood")) {
+        mrp_log_error("bad signature: expected 'oood' got '%s'",signature);
+        return false;
+    }
+
+    if (!(wl = mrp_wayland_scripting_window_manager_unwrap(args[0].pointer))) {
+        mrp_log_error("argument 1 is not a 'window_manager' class object");
+        return false;
+    }
+
+    if (!(json = mrp_json_lua_unwrap(args[1].pointer))) {
+        mrp_log_error("argument 2 is not a 'JSON' class object");
+        return false;
+    }
+
+    if (!(anims = mrp_wayland_scripting_animation_unwrap(args[2].pointer))) {
+        mrp_log_error("argument 3 is not an 'animation' class object");
+        return false;
+    }
+
+    if ((framerate = args[3].integer) > MRP_WAYLAND_FRAMERATE_MAX) {
+        mrp_log_error("argument 3 is not valid framerate (out of range 0-%d)",
+                      MRP_WAYLAND_FRAMERATE_MAX);
+        return false;
+    }
+
+        
+    memset(&u, 0, sizeof(u));
+    u.mask = copy_json_fields(wl, json, fields, &u);
+
+    mrp_wayland_window_request(wl, &u, anims, framerate);
+
+    return true;
+}
+
+
+static void window_update_callback(mrp_wayland_t *wl,
+                                   mrp_wayland_window_operation_t oper,
+                                   mrp_wayland_window_update_mask_t mask,
+                                   mrp_wayland_window_t *win)
+{
+    lua_State *L;
+    scripting_winmgr_t *winmgr;
+    mrp_funcbridge_value_t args[4], ret;
+    char t;
+    bool success;
+
+    MRP_ASSERT(wl && win, "invalid argument");
+
+    if (!(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("can't update window %u: LUA is not initialesed",
+                      win->surfaceid);
+        return;
+    }
+
+    if (!(winmgr = (scripting_winmgr_t *)wl->scripting_data)) {
+        mrp_log_error("window manager scripting is not initialized");
+        return;
+    }
+
+    MRP_ASSERT(wl == winmgr->wl, "confused with data structures");
+
+    if (!win->scripting_data) {
+        mrp_log_error("no scripting data for window %d", win->surfaceid);
+        return;
+    }
+
+    args[0].pointer = winmgr;
+    args[1].integer = oper;
+    args[2].pointer = win->scripting_data;
+    args[3].pointer = mrp_wayland_scripting_window_mask_create_from_c(L, mask);
+
+    memset(&ret, 0, sizeof(ret));
+
+    success = mrp_funcbridge_call_from_c(L, winmgr->window_update, "odoo",
+                                         args, &t, &ret);
+    if (!success) {
+        mrp_log_error("failed to call window_manager.%s.window_update method "
+                      "(%s)", winmgr->name, ret.string ? ret.string : "NULL");
+        mrp_free((void *)ret.string);
+    }
+}
+
+static bool output_request_bridge(lua_State *L,
+                                  void *data,
+                                  const char *signature,
+                                  mrp_funcbridge_value_t *args,
+                                  char *ret_type,
+                                  mrp_funcbridge_value_t *ret_val)
+{
+#define FIELD(f) MRP_OFFSET(mrp_wayland_output_update_t, f)
+#define MASK(m)  MRP_WAYLAND_OUTPUT_ ## m ## _MASK
+#define TYPE(t)  mrp_wayland_json_ ## t ## _copy
+
+    static request_def_t   fields[] = {
+        { "index" , FIELD(index)     , MASK(INDEX)   , TYPE(integer) },
+        { "id"    , FIELD(outputid)  , MASK(OUTPUTID), TYPE(integer) },
+        { "name"  , FIELD(outputname), MASK(NAME)    , TYPE(string)  },
+        {  NULL   ,        0         ,      0        ,     NULL      }
+    };
+
+#undef FIELD
+#undef MASK
+#undef TYPE
+    
+    mrp_wayland_t *wl;
+    mrp_wayland_output_update_t u;
+    mrp_json_t *json;
+
+    MRP_UNUSED(L);
+    MRP_UNUSED(data);
+    MRP_UNUSED(ret_val);
+    MRP_ASSERT(signature && args && ret_type, "invalid argument");
+
+    *ret_type = MRP_FUNCBRIDGE_NO_DATA;
+
+    if (strcmp(signature, "oo")) {
+        mrp_log_error("bad signature: expected 'oo' got '%s'",signature);
+        return false;
+    }
+
+    if (!(wl = mrp_wayland_scripting_window_manager_unwrap(args[0].pointer))) {
+        mrp_log_error("argument 1 is not a 'window_manager' class object");
+        return false;
+    }
+
+    if (!(json = mrp_json_lua_unwrap(args[1].pointer))) {
+        mrp_log_error("argument 2 is not a 'JSON' class object");
+        return false;
+    }
+
+
+    memset(&u, 0, sizeof(u));
+    u.mask = copy_json_fields(wl, json, fields, &u);
+
+    mrp_wayland_output_request(wl, &u);
+
+    return true;
+}
+
+static void output_update_callback(mrp_wayland_t *wl,
+                                  mrp_wayland_output_operation_t oper,
+                                  mrp_wayland_output_update_mask_t mask,
+                                  mrp_wayland_output_t *out)
+{
+    lua_State *L;
+    scripting_winmgr_t *winmgr;
+    mrp_funcbridge_value_t args[4], ret;
+    char t;
+    bool success;
+
+    MRP_ASSERT(wl && out, "invalid argument");
+
+    if (!(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("can't update output %d '%s': LUA is not initialesed",
+                      out->outputid, out->outputname);
+        return;
+    }
+
+    if (!(winmgr = (scripting_winmgr_t *)wl->scripting_data)) {
+        mrp_log_error("window manager scripting is not initialized");
+        return;
+    }
+
+    MRP_ASSERT(wl == winmgr->wl, "confused with data structures");
+
+    if (!out->scripting_data) {
+        mrp_log_error("no scripting data for output %d '%s'",
+                      out->outputid, out->outputname);
+        return;
+    }
+
+    args[0].pointer = winmgr;
+    args[1].integer = oper;
+    args[2].pointer = out->scripting_data;
+    args[3].pointer = mrp_wayland_scripting_output_mask_create_from_c(L, mask);
+
+    memset(&ret, 0, sizeof(ret));
+
+    success = mrp_funcbridge_call_from_c(L, winmgr->output_update, "odoo",
+                                         args, &t, &ret);
+    if (!success) {
+        mrp_log_error("failed to call window_manager.%s.output_update method "
+                      "(%s)", winmgr->name, ret.string ? ret.string : "NULL");
+        mrp_free((void *)ret.string);
+    }
+}
+
+static bool area_create_bridge(lua_State *L,
+                               void *data,
+                               const char *signature,
+                               mrp_funcbridge_value_t *args,
+                               char *ret_type,
+                               mrp_funcbridge_value_t *ret_val)
+{
+#define FIELD(f) MRP_OFFSET(mrp_wayland_area_update_t, f)
+#define MASK(m)  MRP_WAYLAND_AREA_ ## m ## _MASK
+#define TYPE(t)  mrp_wayland_json_ ## t ## _copy
+
+    static request_def_t   fields[] = {
+        { "id"        , FIELD(areaid)   , MASK(AREAID)   , TYPE(integer) },
+        { "name"      , FIELD(name)     , MASK(NAME)     , TYPE(string)  },
+        { "output"    , FIELD(output)   , MASK(OUTPUT)   , TYPE(output)  },
+        { "pos_x"     , FIELD(x)        , MASK(X)        , TYPE(integer) },
+        { "pos_y"     , FIELD(y)        , MASK(Y)        , TYPE(integer) },
+        { "width"     , FIELD(width)    , MASK(WIDTH)    , TYPE(integer) },
+        { "height"    , FIELD(height)   , MASK(HEIGHT)   , TYPE(integer) },
+        { "keep_ratio", FIELD(keepratio), MASK(KEEPRATIO), TYPE(boolean) },
+        { "align"     , FIELD(align)    , MASK(ALIGN)    , TYPE(align)   },
+        {  NULL       ,       0         ,       0        ,     NULL      }
+    };
+
+#undef FIELD
+#undef MASK
+#undef TYPE
+
+    mrp_wayland_t *wl;
+    mrp_wayland_area_update_t u;
+    mrp_json_t *json;
+
+    MRP_UNUSED(L);
+    MRP_UNUSED(data);
+    MRP_UNUSED(ret_val);
+    MRP_ASSERT(signature && args && ret_type, "invalid argument");
+
+    *ret_type = MRP_FUNCBRIDGE_NO_DATA;
+
+
+    if (strcmp(signature, "oo")) {
+        mrp_log_error("bad signature: expected 'oo' got '%s'",signature);
+        return false;
+    }
+
+    if (!(wl = mrp_wayland_scripting_window_manager_unwrap(args[0].pointer))) {
+        mrp_log_error("argument 1 is not a 'window_manager' class object");
+        return false;
+    }
+
+    if (!(json = mrp_json_lua_unwrap(args[1].pointer))) {
+        mrp_log_error("argument 2 is not a 'JSON' class object");
+        return false;
+    }
+
+    memset(&u, 0, sizeof(u));
+    u.mask = copy_json_fields(wl, json, fields, &u);
+
+    mrp_wayland_area_create(wl, &u);
+
+    return true;
+}
+
+static bool layer_request_bridge(lua_State *L,
+                                 void *data,
+                                 const char *signature,
+                                 mrp_funcbridge_value_t *args,
+                                 char *ret_type,
+                                 mrp_funcbridge_value_t *ret_val)
+{
+#define FIELD(f) MRP_OFFSET(mrp_wayland_layer_update_t, f)
+#define MASK(m)  MRP_WAYLAND_LAYER_ ## m ## _MASK
+#define TYPE(t)  mrp_wayland_json_ ## t ## _copy
+
+    static request_def_t   fields[] = {
+        { "layer"  , FIELD(layerid)  , MASK(LAYERID), TYPE(integer) },
+        { "visible", FIELD(visible)  , MASK(VISIBLE), TYPE(integer) },
+        {   NULL   ,        0        ,      0       ,      NULL     }
+    };
+
+#undef FIELD
+#undef MASK
+#undef TYPE
+
+    mrp_wayland_t *wl;
+    mrp_wayland_layer_update_t u;
+    mrp_json_t *json;
+
+    MRP_UNUSED(L);
+    MRP_UNUSED(data);
+    MRP_UNUSED(ret_val);
+    MRP_ASSERT(signature && args && ret_type, "invalid argument");
+
+    *ret_type = MRP_FUNCBRIDGE_NO_DATA;
+
+    if (strcmp(signature, "oo")) {
+        mrp_log_error("bad signature: expected 'oo' got '%s'",signature);
+        return false;
+    }
+
+    if (!(wl = mrp_wayland_scripting_window_manager_unwrap(args[0].pointer))) {
+        mrp_log_error("argument 1 is not a 'window_manager' class object");
+        return false;
+    }
+
+    if (!(json = mrp_json_lua_unwrap(args[1].pointer))) {
+        mrp_log_error("argument 2 is not a 'JSON' class object");
+        return false;
+    }
+
+    memset(&u, 0, sizeof(u));
+    u.mask = copy_json_fields(wl, json, fields, &u);
+
+    return true;
+}
+
+static void layer_update_callback(mrp_wayland_t *wl,
+                                  mrp_wayland_layer_operation_t oper,
+                                  mrp_wayland_layer_update_mask_t mask,
+                                  mrp_wayland_layer_t *layer)
+{
+    lua_State *L;
+    scripting_winmgr_t *winmgr;
+    mrp_funcbridge_value_t args[4], ret;
+    char t;
+    bool success;
+
+    MRP_ASSERT(wl && layer, "invalid argument");
+
+    if (!(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("can't update layer %u: LUA is not initialesed",
+                      layer->layerid);
+        return;
+    }
+
+    if (!(winmgr = (scripting_winmgr_t *)wl->scripting_data)) {
+        mrp_log_error("window manager scripting is not initialized");
+        return;
+    }
+
+    MRP_ASSERT(wl == winmgr->wl, "confused with data structures");
+
+    if (!layer->scripting_data) {
+        mrp_log_error("no scripting data for layer %d", layer->layerid);
+        return;
+    }
+
+    args[0].pointer = winmgr;
+    args[1].integer = oper;
+    args[2].pointer = layer->scripting_data;
+    args[3].pointer = mrp_wayland_scripting_layer_mask_create_from_c(L, mask);
+
+    memset(&ret, 0, sizeof(ret));
+
+    success = mrp_funcbridge_call_from_c(L, winmgr->layer_update, "odoo",
+                                         args, &t, &ret);
+    if (!success) {
+        mrp_log_error("failed to call window_manager.%s.output_update method "
+                      "(%s)", winmgr->name, ret.string ? ret.string : "NULL");
+        mrp_free((void *)ret.string);
+    }
+}
+
+
+static uint32_t copy_json_fields(mrp_wayland_t *wl,
+                                 mrp_json_t *json,
+                                 request_def_t *fields,
+                                 void *copy)
+{
+    const char *key;
+    mrp_json_t *val;
+    mrp_json_iter_t it;
+    request_def_t *f;
+    uint32_t m, mask;
+
+    mask = 0;
+
+    mrp_json_foreach_member(json, key,val, it) {
+        for (f = fields;   f->name;   f++) {
+            if (!strcmp(key, f->name)) {
+                if ((m = f->copy(wl, copy + f->offset, val, f->mask)))
+                    mask |= m;
+                else
+                    mrp_debug("'%s' field has invalid value", key);
+                break;
+            }
+        }
+    }
+
+    return mask;
+}
+
+
+static bool register_methods(lua_State *L)
+{
+#define FUNCBRIDGE(n,s,d) { #n, s, n##_bridge, d, &n }
+#define FUNCBRIDGE_END    { NULL, NULL, NULL, NULL, NULL }
+
+    static funcbridge_def_t funcbridge_defs[] = {
+        FUNCBRIDGE(output_request, "oo"  , NULL),
+        FUNCBRIDGE(area_create   , "oo"  , NULL),
+        FUNCBRIDGE(layer_request , "oo"  , NULL),
+        FUNCBRIDGE(window_request, "oood", NULL),
+        FUNCBRIDGE_END
+    };
+
+    mrp_funcbridge_t *f;
+    funcbridge_def_t *d;
+    bool success = true;
+
+    for (d = funcbridge_defs;   d->name;    d++) {
+        *(d->ptr) = f = mrp_funcbridge_create_cfunc(L, d->name, d->sign,
+                                                    d->func, d->data);
+        if (!f) {
+            mrp_log_error("failed to register builtin function '%s'", d->name);
+            success = false;
+        }
+    }
+
+    return success;
+
+#undef FUNCBRIDGE_END
+#undef FUNCBRIDGE
+}
diff --git a/src/plugins/system-controller/wayland/scripting-window.c b/src/plugins/system-controller/wayland/scripting-window.c
new file mode 100644 (file)
index 0000000..5aac1bb
--- /dev/null
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+#include <murphy/core/lua-bindings/murphy.h>
+#include <murphy/core/lua-utils/error.h>
+#include <murphy/core/lua-utils/object.h>
+#include <murphy/core/lua-utils/funcbridge.h>
+
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include "scripting-wayland.h"
+#include "window.h"
+#include "area.h"
+
+#define WINDOW_CLASS       MRP_LUA_CLASS_SIMPLE(window)
+#define WINDOW_MASK_CLASS  MRP_LUA_CLASS_SIMPLE(window_mask)
+
+typedef struct scripting_window_s  scripting_window_t;
+typedef struct scripting_window_mask_s  scripting_window_mask_t;
+
+struct scripting_window_s {
+    mrp_wayland_window_t *win;
+};
+
+struct scripting_window_mask_s {
+    uint32_t mask;
+};
+
+static int  window_create_from_lua(lua_State *);
+static int  window_getfield(lua_State *);
+static int  window_setfield(lua_State *);
+static int  window_stringify(lua_State *);
+static void window_destroy_from_lua(void *);
+
+static scripting_window_t *window_check(lua_State *L, int idx);
+
+static int  window_mask_create_from_lua(lua_State *);
+static int  window_mask_getfield(lua_State *);
+static int  window_mask_setfield(lua_State *);
+static int  window_mask_stringify(lua_State *);
+static void window_mask_destroy(void *);
+
+static scripting_window_mask_t *window_mask_check(lua_State *, int);
+
+static uint32_t get_window_mask(mrp_wayland_scripting_field_t);
+
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    window,                     /* class name */
+    scripting_window_t,         /* userdata type */
+    window_destroy_from_lua,    /* userdata destructor */
+    MRP_LUA_METHOD_LIST (       /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR (window_create_from_lua)
+    ),
+    MRP_LUA_METHOD_LIST (       /* overrides */
+       MRP_LUA_OVERRIDE_CALL      (window_create_from_lua)
+       MRP_LUA_OVERRIDE_GETFIELD  (window_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD  (window_setfield)
+       MRP_LUA_OVERRIDE_STRINGIFY (window_stringify)
+    )
+);
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    window_mask,                /* class name */
+    scripting_window_mask_t,    /* userdata type */
+    window_mask_destroy,        /* userdata destructor */
+    MRP_LUA_METHOD_LIST (       /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR (window_mask_create_from_lua)
+    ),
+    MRP_LUA_METHOD_LIST (       /* overrides */
+       MRP_LUA_OVERRIDE_CALL      (window_mask_create_from_lua)
+       MRP_LUA_OVERRIDE_GETFIELD  (window_mask_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD  (window_mask_setfield)
+       MRP_LUA_OVERRIDE_STRINGIFY (window_mask_stringify)
+    )
+);
+
+
+
+void mrp_wayland_scripting_window_init(lua_State *L)
+{
+    MRP_ASSERT(L, "invalid argument");
+
+    mrp_lua_create_object_class(L, WINDOW_CLASS);
+    mrp_lua_create_object_class(L, WINDOW_MASK_CLASS);
+}
+
+mrp_wayland_window_t *mrp_wayland_scripting_window_check(lua_State *L, int idx)
+{
+    scripting_window_t *w;
+    mrp_wayland_window_t *win;
+
+    if ((w = window_check(L, idx)) && (win = w->win)) {
+        MRP_ASSERT(win->scripting_data == (void *)w,
+                   "confused with data structures");
+        return win;
+    }
+
+    return NULL;
+}
+
+mrp_wayland_window_t *mrp_wayland_scripting_window_unwrap(void *void_w)
+{
+    scripting_window_t *w = (scripting_window_t *)void_w;
+
+    if (w && mrp_lua_get_object_classdef(w) == WINDOW_CLASS)
+        return w->win;
+
+    return NULL;
+}
+
+
+void *mrp_wayland_scripting_window_create_from_c(lua_State *L,
+                                                 mrp_wayland_window_t *win)
+{
+    scripting_window_t *w;
+
+    MRP_ASSERT(win, "invald argument");
+    
+    if (!L && !(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("can't create scripting window %d: LUA is "
+                      "not initialized", win->surfaceid);
+        return NULL;
+    }
+
+    w = (scripting_window_t *)mrp_lua_create_object(L, WINDOW_CLASS, NULL,
+                                                    win->surfaceid + 1);
+    if (!w) {
+        mrp_log_error("can't create scripting window %d: LUA object "
+                      "creation failed", win->surfaceid);
+        return NULL;
+    }
+
+    w->win = win;
+
+    return w;
+}
+
+void mrp_wayland_scripting_window_destroy_from_c(lua_State *L,
+                                                 mrp_wayland_window_t *win)
+{
+    scripting_window_t *w;
+
+    MRP_ASSERT(win, "invalid argument");
+
+    if (!L && !(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("can't destroy scripting window %d: LUA is "
+                      "not initialized", win->surfaceid);
+        win->scripting_data = NULL;
+        return;
+    }
+
+    if ((w = win->scripting_data)) {
+        mrp_debug("destroy scripting window %d", win->surfaceid);
+
+         w->win = NULL;
+
+         mrp_lua_destroy_object(L, NULL,win->surfaceid+1, win->scripting_data);
+
+         win->scripting_data = NULL;
+    }
+}
+
+
+static int window_create_from_lua(lua_State *L)
+{
+    MRP_LUA_ENTER;
+
+    luaL_error(L, "can't create window from lua");
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int window_getfield(lua_State *L)
+{
+    scripting_window_t *w;
+    mrp_wayland_window_t *win;
+    const char *fldnam;
+    mrp_wayland_scripting_field_t fld;
+
+    MRP_LUA_ENTER;
+
+    fld = mrp_wayland_scripting_field_check(L, 2, &fldnam);
+    lua_pop(L, 1);
+
+    w = window_check(L, 1);
+
+    if (!w || !(win = w->win))
+        lua_pushnil(L);
+    else {
+        switch (fld) {
+        case SURFACE:   lua_pushinteger(L, win->surfaceid);              break;
+        case NAME:      lua_pushstring(L, win->name ? win->name : "");   break;
+        case APPID:     lua_pushstring(L, win->appid ? win->appid : ""); break;
+        case PID:       lua_pushinteger(L, win->pid);                    break;
+        case NODE:      lua_pushinteger(L, win->nodeid);                 break;
+        case LAYER:     lua_pushinteger(L, win->layer ?
+                                        win->layer->layerid : -1);       break;
+        case POS_X:     lua_pushinteger(L, win->x);                      break;
+        case POS_Y:     lua_pushinteger(L, win->y);                      break;
+        case WIDTH:     lua_pushinteger(L, win->width);                  break;
+        case HEIGHT:    lua_pushinteger(L, win->height);                 break;
+        case VISIBLE:   lua_pushinteger(L, win->visible ? 1 : 0);        break;
+        case RAISE:     lua_pushinteger(L, win->raise ? 1 : 0);          break;
+        case MAPPED:    lua_pushinteger(L, win->mapped ? 1 : 0);         break;
+        case ACTIVE:    lua_pushinteger(L, win->active);                 break;
+        case LAYERTYPE: lua_pushinteger(L, win->layertype);              break;
+        case AREA:      lua_pushstring(L, win->area && win->area->fullname ?
+                                       win->area->fullname : "");        break;
+        default:        lua_pushnil(L);                                  break;
+        }
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int  window_setfield(lua_State *L)
+{
+    MRP_LUA_ENTER;
+
+    window_check(L, 1);
+    luaL_error(L, "window objects are read-only");
+
+    MRP_LUA_LEAVE(0);
+}
+
+static int  window_stringify(lua_State *L)
+{
+#define ALL_FIELDS (MRP_WAYLAND_WINDOW_END_MASK - 1)
+
+    scripting_window_t *w;
+    mrp_wayland_window_t *win;
+    char *p, *e;
+    char buf[4096];
+
+    MRP_LUA_ENTER;
+
+    w = window_check(L, 1);
+
+    if (!(win = w->win))
+        lua_pushnil(L);
+    else {
+        e = (p = buf) + sizeof(buf);
+        p += snprintf(p, e-p, "window %d", win->surfaceid);
+        p += mrp_wayland_window_print(win, ALL_FIELDS, p, e-p);
+
+        lua_pushlstring(L, buf, p-buf);
+    }
+
+    MRP_LUA_LEAVE(1);
+
+#undef ALL_FIELDS
+}
+
+static void window_destroy_from_lua(void *data)
+{
+    scripting_window_t *w = (scripting_window_t *)data;
+
+    MRP_LUA_ENTER;
+
+    if (w && w->win) {
+        mrp_wayland_window_set_scripting_data(w->win, NULL);
+    }
+
+    MRP_LUA_LEAVE_NOARG;
+}
+
+
+static scripting_window_t *window_check(lua_State *L, int idx)
+{
+    return (scripting_window_t *)mrp_lua_check_object(L, WINDOW_CLASS, idx);
+}
+
+
+uint32_t mrp_wayland_scripting_window_mask_check(lua_State *L, int idx)
+{
+    scripting_window_mask_t *um = window_mask_check(L, idx);
+
+    return um ? um->mask : 0;
+}
+
+uint32_t mrp_wayland_scripting_window_mask_unwrap(void *void_um)
+{
+    scripting_window_mask_t *um = (scripting_window_mask_t *)void_um;
+
+    return um ? um->mask : 0;
+}
+
+
+void *mrp_wayland_scripting_window_mask_create_from_c(lua_State *L,
+                                                      uint32_t mask)
+{
+    scripting_window_mask_t *um;
+
+    if (!L && !(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("can't create scripting window mask: "
+                      "LUA is not initialized");
+        return NULL;
+    }
+
+    um = (scripting_window_mask_t *)mrp_lua_create_object(L, WINDOW_MASK_CLASS,
+                                                          NULL, 0);
+    if (!um)
+        mrp_log_error("can't create window_mask");
+    else
+        um->mask = mask;
+
+    return um;
+}
+
+static int window_mask_create_from_lua(lua_State *L)
+{
+    size_t fldnamlen;
+    const char *fldnam;
+    scripting_window_mask_t *um;
+    mrp_wayland_scripting_field_t fld;
+    uint32_t m;
+    uint32_t mask = 0;
+
+    MRP_LUA_ENTER;
+
+    luaL_checktype(L, 2, LUA_TTABLE);
+
+    MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
+        fld = mrp_wayland_scripting_field_name_to_type(fldnam, fldnamlen);
+
+        if (fld == MASK)
+            mask = lua_tointeger(L, -1);
+        else if ((m = get_window_mask(fld)))
+            mask |= m;
+        else
+            luaL_error(L, "bad field '%s'", fldnam);
+    }
+
+    um = (scripting_window_mask_t *)mrp_lua_create_object(L, WINDOW_MASK_CLASS,
+                                                          NULL, 0);
+    if (!um)
+        luaL_error(L, "can't create window_mask");
+
+    um->mask = mask;
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int window_mask_getfield(lua_State *L)
+{
+    scripting_window_mask_t *um;
+    mrp_wayland_scripting_field_t fld;
+    uint32_t m;
+
+    MRP_LUA_ENTER;
+
+    um = window_mask_check(L, 1);
+    fld = mrp_wayland_scripting_field_check(L, 2, NULL);
+
+    lua_pop(L, 1);
+
+    if (!um)
+        lua_pushnil(L);
+    else {
+        if (fld == MASK)
+            lua_pushinteger(L, um->mask);
+        else if ((m = get_window_mask(fld)))
+            lua_pushboolean(L, (um->mask & m) ? 1 : 0);
+        else
+            lua_pushnil(L);
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int window_mask_setfield(lua_State *L)
+{
+    scripting_window_mask_t *um;
+    uint32_t m;
+    mrp_wayland_scripting_field_t fld;
+
+    MRP_LUA_ENTER;
+
+    um = window_mask_check(L, 1);
+    fld = mrp_wayland_scripting_field_check(L, 2, NULL);
+
+    lua_pop(L, 2);
+
+    if (um) {
+        if (fld == MASK)
+            um->mask = lua_tointeger(L, 3);
+        else if ((m = get_window_mask(fld))) {
+            um->mask &= ~m;
+
+            if (lua_toboolean(L, 3))
+                um->mask |= m;
+        }
+    }
+
+    MRP_LUA_LEAVE(0);
+}
+
+static int window_mask_stringify(lua_State *L)
+{
+    scripting_window_mask_t *um;
+    uint32_t m, mask;
+    char buf[4096];
+    char *p, *e;
+    const char *name;
+
+
+    MRP_LUA_ENTER;
+
+    um = window_mask_check(L, 1);
+    e = (p = buf) + sizeof(buf);
+    *p = 0;
+
+    mask = um->mask;
+
+    for (m = 1;  mask && m < MRP_WAYLAND_WINDOW_END_MASK && p < e;   m <<= 1) {
+        if ((mask & m)) {
+            mask &= ~m;
+
+            if ((name = mrp_wayland_window_update_mask_str(m)))
+                p += snprintf(p, e-p, "%s%s", p > buf ? " | " : "", name);
+        }
+    }
+
+    lua_pushstring(L, (p > buf) ? buf : "<empty>");
+
+    MRP_LUA_LEAVE(1);
+}
+
+static void window_mask_destroy(void *data)
+{
+    scripting_window_mask_t *um = (scripting_window_mask_t *)data;
+
+    MRP_UNUSED(um);
+}
+
+
+static scripting_window_mask_t *window_mask_check(lua_State *L, int idx)
+{
+    return (scripting_window_mask_t*)mrp_lua_check_object(L, WINDOW_MASK_CLASS,
+                                                          idx);
+}
+
+
+static uint32_t get_window_mask(mrp_wayland_scripting_field_t fld)
+{
+    switch (fld) {
+    case SURFACE:   return MRP_WAYLAND_WINDOW_SURFACEID_MASK;
+    case APPID:     return MRP_WAYLAND_WINDOW_APPID_MASK;
+    case PID:       return MRP_WAYLAND_WINDOW_PID_MASK;
+    case NODE:      return MRP_WAYLAND_WINDOW_NODEID_MASK;
+    case LAYER:     return MRP_WAYLAND_WINDOW_LAYER_MASK;
+    case POS_X:     return MRP_WAYLAND_WINDOW_X_MASK;
+    case POS_Y:     return MRP_WAYLAND_WINDOW_Y_MASK;
+    case POSITION:  return MRP_WAYLAND_WINDOW_POSITION_MASK;
+    case WIDTH:     return MRP_WAYLAND_WINDOW_WIDTH_MASK;
+    case HEIGHT:    return MRP_WAYLAND_WINDOW_HEIGHT_MASK;
+    case SIZE:      return MRP_WAYLAND_WINDOW_SIZE_MASK;
+    case VISIBLE:   return MRP_WAYLAND_WINDOW_VISIBLE_MASK;
+    case RAISE:     return MRP_WAYLAND_WINDOW_RAISE_MASK;
+    case ACTIVE:    return MRP_WAYLAND_WINDOW_ACTIVE_MASK;
+    case LAYERTYPE: return MRP_WAYLAND_WINDOW_LAYERTYPE_MASK;
+    case AREA:      return MRP_WAYLAND_WINDOW_AREA_MASK;
+    default:        return 0;
+    }
+}
diff --git a/src/plugins/system-controller/wayland/wayland.c b/src/plugins/system-controller/wayland/wayland.c
new file mode 100644 (file)
index 0000000..7914ca3
--- /dev/null
@@ -0,0 +1,582 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+
+#include "wayland.h"
+#include "output.h"
+#include "layer.h"
+
+
+static uint32_t oid_hash(const void *);
+static uint32_t wid_hash(const void *);
+static uint32_t lid_hash(const void *);
+static int id_compare(const void *, const void *);
+
+static const char *get_display_name(mrp_wayland_t *w);
+static void display_io_watch(mrp_io_watch_t *, int, mrp_io_event_t, void *);
+static void object_create(mrp_wayland_interface_t *, uint32_t, uint32_t);
+static void global_available_callback(void *, struct wl_registry *, uint32_t,
+                                      const char *, uint32_t);
+static void global_remove_callback(void *, struct wl_registry *, uint32_t);
+
+static mrp_wayland_t **instances;
+static size_t ninstance;
+
+
+mrp_wayland_t *mrp_wayland_create(const char *display_name, mrp_mainloop_t *ml)
+{
+    mrp_wayland_t *wl;
+    mrp_htbl_config_t icfg, ocfg, wcfg, lcfg, acfg;
+
+    MRP_ASSERT(ml, "invalid argument");
+
+    if (!(wl = mrp_allocz(sizeof(mrp_wayland_t))))
+        mrp_log_error("can't allocate memory for wayland");
+    else {
+        memset(&icfg, 0, sizeof(icfg));
+        icfg.nentry = MRP_WAYLAND_INTERFACE_MAX;
+        icfg.comp = mrp_string_comp;
+        icfg.hash = mrp_string_hash;
+        icfg.nbucket = MRP_WAYLAND_INTERFACE_BUCKETS;
+
+        memset(&ocfg, 0, sizeof(ocfg));
+        ocfg.nentry = MRP_WAYLAND_OUTPUT_MAX;
+        ocfg.comp = id_compare;
+        ocfg.hash = oid_hash;
+        ocfg.nbucket = MRP_WAYLAND_OUTPUT_BUCKETS;
+
+        memset(&wcfg, 0, sizeof(wcfg));
+        wcfg.nentry = MRP_WAYLAND_WINDOW_MAX;
+        wcfg.comp = id_compare;
+        wcfg.hash = wid_hash;
+        wcfg.nbucket = MRP_WAYLAND_WINDOW_BUCKETS;
+
+        memset(&lcfg, 0, sizeof(lcfg));
+        lcfg.nentry = MRP_WAYLAND_LAYER_MAX + MRP_WAYLAND_LAYER_BUILTIN;
+        lcfg.comp = id_compare;
+        lcfg.hash = lid_hash;
+        lcfg.nbucket = MRP_WAYLAND_LAYER_BUCKETS;
+
+        memset(&acfg, 0, sizeof(acfg));
+        acfg.nentry = MRP_WAYLAND_AREA_MAX;
+        acfg.comp = mrp_string_comp;
+        acfg.hash = mrp_string_hash;
+        acfg.nbucket = MRP_WAYLAND_AREA_BUCKETS;
+
+        wl->display_name = display_name ? mrp_strdup(display_name) : NULL;
+        wl->ml = ml;
+
+        wl->registry_listener.global = global_available_callback;
+        wl->registry_listener.global_remove = global_remove_callback;
+
+        wl->interfaces = mrp_htbl_create(&icfg);
+        wl->outputs = mrp_htbl_create(&ocfg);
+        wl->windows = mrp_htbl_create(&wcfg);
+        wl->layers = mrp_htbl_create(&lcfg);
+        wl->areas = mrp_htbl_create(&acfg);
+
+        instances = mrp_reallocz(instances, ninstance, ninstance + 2);
+        instances[ninstance++] = wl;
+    }
+
+    return wl;
+}
+
+void mrp_wayland_destroy(mrp_wayland_t *wl)
+{
+    size_t i;
+
+    if (wl) {
+        for (i = 0;  i < ninstance;  i++) {
+            if (instances[i] == wl) {
+                if (i < ninstance-1) {
+                    memmove(instances + i, instances + i + 1,
+                            (ninstance - (i + 1)) * sizeof(*instances));
+                }
+                instances[--ninstance] = NULL;
+                break;
+            }
+        }
+    }
+}
+
+mrp_wayland_t *mrp_wayland_iterate(void **cursor)
+{
+    ptrdiff_t i;
+
+    if (cursor) {
+        i = *cursor - NULL;
+
+        if (i >= 0 && i < (ptrdiff_t)ninstance) {
+            *cursor = NULL + (i + 1);
+            return instances[i];
+        }
+    }
+
+    return NULL;
+}
+
+bool mrp_wayland_connect(mrp_wayland_t *wl)
+{
+#define IO_EVENTS MRP_IO_EVENT_IN | MRP_IO_EVENT_ERR | MRP_IO_EVENT_HUP
+
+    struct wl_display *display;
+    struct wl_registry *registry;
+    mrp_io_watch_t *iow;
+    int fd;
+
+    MRP_ASSERT(wl, "invalid argument");
+    MRP_ASSERT(wl->ml, "no mainloop");
+
+    if (wl->iow)
+        return true; /* we are already connected */
+
+    if (!(display = wl_display_connect(wl->display_name))) {
+        mrp_debug("attempt to connect to display '%s' failed",
+                  get_display_name(wl));
+        return false;
+    }
+
+    fd = wl_display_get_fd(display);
+
+    MRP_ASSERT(fd >= 0, "fd for wayland display < 0");
+
+    if (!(registry = wl_display_get_registry(display))) {
+        mrp_log_error("can't get registry for display '%s'",
+                      get_display_name(wl));
+        wl_display_disconnect(display);
+        return false;
+    }
+
+     if (wl_registry_add_listener(registry, &wl->registry_listener, wl) < 0) {
+        mrp_log_error("can't add listener for registry (display '%s')",
+                      get_display_name(wl));
+        wl_registry_destroy(registry);
+        wl_display_disconnect(display);
+        return false;
+    }
+
+     if (!(iow = mrp_add_io_watch(wl->ml,fd,IO_EVENTS,display_io_watch,wl))) {
+        mrp_log_error("can't add io watch for display '%s')",
+                      get_display_name(wl));
+        wl_registry_destroy(registry);
+        wl_display_disconnect(display);
+        return false;
+    }
+
+    wl->iow = iow;
+    wl->display = display;
+    wl->registry = registry;
+
+    mrp_log_info("connecting to wayland display '%s'", get_display_name(wl));
+
+    wl_display_roundtrip(display);
+
+    mrp_debug("queried interfaces");
+
+    wl_display_roundtrip(display);
+
+    mrp_log_info("display '%s' is up and running", get_display_name(wl));
+
+    return true;
+
+#undef IO_EVENTS
+}
+
+void mrp_wayland_flush(mrp_wayland_t *wl)
+{
+    MRP_ASSERT(wl, "invalid argument");
+
+    if (wl->display) {
+        mrp_debug("calling wl_display_flush()");
+        wl_display_flush(wl->display);
+    }
+}
+
+
+static int update_layers(void *key, void *object, void *ud)
+{
+    mrp_wayland_window_manager_t *wm = (mrp_wayland_window_manager_t *)ud;
+    mrp_wayland_layer_t *layer = (mrp_wayland_layer_t *)object;
+
+    MRP_UNUSED(key);
+
+    mrp_debug("register window manager to layer %u/'%s'",
+              layer->layerid, layer->name);
+
+    layer->wm = wm;
+
+    return MRP_HTBL_ITER_MORE;
+}
+
+
+void mrp_wayland_register_window_manager(mrp_wayland_t *wl,
+                                         mrp_wayland_window_manager_t *wm)
+{
+    wl->wm = wm;
+
+    mrp_htbl_foreach(wl->layers, update_layers, wm);
+}
+
+
+bool mrp_wayland_register_interface(mrp_wayland_t *wl,
+                                    mrp_wayland_factory_t *factory)
+{
+    mrp_wayland_interface_t *wif;
+    const char *name;
+
+    MRP_ASSERT(wl && factory, "invalid argument");
+    MRP_ASSERT(factory->size >= sizeof(mrp_wayland_object_t),
+               "invalid object size in factory");
+    MRP_ASSERT(factory->interface, "missing factory interface");
+
+    name = factory->interface->name;
+
+    MRP_ASSERT(name, "broken factory interface");
+
+    if (!(wif = mrp_allocz(sizeof(mrp_wayland_interface_t)))) {
+        mrp_log_error("can't allocate memory for wayland interface '%s'",
+                      name);
+        return false;
+    }
+
+    wif->wl = wl;
+    wif->name = mrp_strdup(name);
+    wif->object_factory = *factory;
+
+    mrp_list_init(&wif->object_list);
+
+    if (!mrp_htbl_insert(wl->interfaces, (void *)wif->name, wif)) {
+        mrp_log_error("failed to add interface '%s' to hashtable. "
+                      "Perhaps already registered ...", wif->name);
+        mrp_free((void *)wif->name);
+        mrp_free(wif);
+        return false;
+    }
+
+    mrp_log_info("registered wayland interface '%s'", wif->name);
+
+    return true;
+}
+
+void mrp_wayland_register_output_update_callback(mrp_wayland_t *wl,
+                               mrp_wayland_output_update_callback_t callback)
+{
+    MRP_ASSERT(wl, "invalid aruments");
+
+    mrp_debug("registering output_update_callback");
+
+    wl->output_update_callback = callback;
+}
+
+void mrp_wayland_register_window_update_callback(mrp_wayland_t *wl,
+                               mrp_wayland_window_update_callback_t callback)
+{
+    MRP_ASSERT(wl, "invalid aruments");
+
+    mrp_debug("registering window_update_callback");
+
+    wl->window_update_callback = callback;
+}
+
+void mrp_wayland_register_layer_update_callback(mrp_wayland_t *wl,
+                               mrp_wayland_layer_update_callback_t callback)
+{
+    MRP_ASSERT(wl, "invalid aruments");
+
+    mrp_debug("registering layer_update_callback");
+
+    wl->layer_update_callback = callback;
+}
+
+void mrp_wayland_register_area_update_callback(mrp_wayland_t *wl,
+                               mrp_wayland_area_update_callback_t callback)
+{
+    MRP_ASSERT(wl, "invalid aruments");
+
+    mrp_debug("registering area_update_callback");
+
+    wl->area_update_callback = callback;
+}
+
+void mrp_wayland_set_scripting_data(mrp_wayland_t *wl, void *data)
+{
+    MRP_ASSERT(wl, "invalid argument");
+
+    mrp_debug("%sset scripting data", data ? "" : "re");
+
+    wl->scripting_data = data;
+}
+
+void mrp_wayland_create_scripting_windows(mrp_wayland_t *wl, bool create)
+{
+    MRP_ASSERT(wl, "invalid argument");
+
+    mrp_debug("%screate scripting windows", create ? "" : "do not ");
+
+    wl->create_scripting_windows = create;
+}
+
+
+void mrp_wayland_create_scripting_outputs(mrp_wayland_t *wl, bool create)
+{
+    MRP_ASSERT(wl, "invalid argument");
+
+    mrp_debug("%screate scripting outputs", create ? "" : "do not ");
+
+    wl->create_scripting_outputs = create;
+}
+
+
+void mrp_wayland_create_scripting_areas(mrp_wayland_t *wl, bool create)
+{
+    MRP_ASSERT(wl, "invalid argument");
+
+    mrp_debug("%screate scripting areas", create ? "" : "do not ");
+
+    wl->create_scripting_areas = create;
+}
+
+
+void mrp_wayland_create_scripting_layers(mrp_wayland_t *wl, bool create)
+{
+    MRP_ASSERT(wl, "invalid argument");
+
+    mrp_debug("%screate scripting layers", create ? "" : "do not ");
+
+    wl->create_scripting_layers = create;
+}
+
+
+static uint32_t oid_hash(const void *pkey)
+{
+    uint32_t key = *(uint32_t *)pkey;
+
+    return key % MRP_WAYLAND_OUTPUT_BUCKETS;
+}
+
+static uint32_t wid_hash(const void *pkey)
+{
+    uint32_t key = *(uint32_t *)pkey;
+
+    return key % MRP_WAYLAND_WINDOW_BUCKETS;
+}
+
+static uint32_t lid_hash(const void *pkey)
+{
+    uint32_t key = *(uint32_t *)pkey;
+
+    return key % MRP_WAYLAND_LAYER_BUCKETS;
+}
+
+static int id_compare(const void *pkey1, const void *pkey2)
+{
+    int32_t key1 = *(int32_t *)pkey1;
+    int32_t key2 = *(int32_t *)pkey2;
+
+    return (key1 == key2) ? 0 : ((key1 < key2) ? -1 : 1);
+}
+
+static const char *get_display_name(mrp_wayland_t *wl)
+{
+    const char *display_name;
+
+    MRP_ASSERT(wl, "invalid argument");
+
+    if (wl->display_name)
+        return wl->display_name;
+
+    if ((display_name = getenv("WAYLAND_DISPLAY")) != NULL)
+        return display_name;
+
+    return "wayland-0";
+}
+
+static void display_io_watch(mrp_io_watch_t *iow,
+                             int fd,
+                             mrp_io_event_t events,
+                             void *ud)
+{
+    mrp_wayland_t *wl = (mrp_wayland_t *)ud;
+    char evnam[32];
+    char evlist[1024];
+    char *p, *e;
+
+    MRP_UNUSED(fd);
+
+    MRP_ASSERT(wl, "invalid user data");
+    MRP_ASSERT(iow == wl->iow, "mismatching io watch");
+
+    if ((events & MRP_IO_EVENT_HUP)) {
+        mrp_log_info("display '%s' is gone", get_display_name(wl));
+
+        wl_registry_destroy(wl->registry);
+        wl_display_disconnect(wl->display);
+
+        return;
+    }
+
+    if ((events & MRP_IO_EVENT_ERR)) {
+        mrp_log_error("I/O error on display '%s'", get_display_name(wl));
+        return;
+    }
+
+    if ((events & MRP_IO_EVENT_IN)) {
+        events &= ~MRP_IO_EVENT_IN;
+
+        mrp_debug("dispatching inputs from display '%s'",get_display_name(wl));
+
+        if (wl_display_dispatch(wl->display) < 0) {
+            mrp_log_error("failed to dispatch events of display '%s'",
+                          get_display_name(wl));
+        }
+
+        wl_display_flush(wl->display);
+    }
+
+    if (events) {
+#       define PRINT(w)                                                    \
+            if (p < e) {                                                   \
+                p += snprintf(p, e-p, "%s%s", p > evlist ? " " : "", w);   \
+            }
+#       define CHECK_EVENT(e)                                              \
+            if ((events & MRP_IO_EVENT_ ## e)) {                           \
+                char *evnam = #e;                                          \
+                PRINT(evnam);                                              \
+                events &= ~MRP_IO_EVENT_ ## e;                             \
+            }
+
+        e = (p = evlist) + (sizeof(evlist) - 1);
+
+        CHECK_EVENT(PRI);
+        CHECK_EVENT(OUT);
+
+        if (events) {
+            snprintf(evnam, sizeof(evnam), "<unknown 0x%x>", events);
+            PRINT(evnam);
+        }
+
+        mrp_debug("unhandled io events: %s", evlist);
+
+#       undef CHECK_EVENT
+#       undef PRINT
+    }
+}
+
+static void object_create(mrp_wayland_interface_t *wif,
+                          uint32_t name,
+                          uint32_t version)
+{
+    mrp_wayland_t *wl;
+    mrp_wayland_factory_t *factory;
+    mrp_wayland_object_t *obj;
+    struct wl_proxy *proxy;
+
+    MRP_ASSERT(wif, "invalid argument");
+
+    wl = wif->wl;
+    factory = &wif->object_factory;
+
+    if (!(obj = mrp_allocz(factory->size))) {
+        mrp_log_error("can't allocate %zd byte memory for %u/'%s' object",
+                      factory->size, (unsigned int)name, wif->name);
+        return;
+    }
+
+    proxy = wl_registry_bind(wl->registry, name, factory->interface, 1);
+
+    if (!proxy) {
+        mrp_log_error("failed to create proxy for object %u/'%s' on "
+                      "display '%s'", name, wif->name, get_display_name(wl));
+        mrp_free(obj);
+        return;
+    }
+
+    mrp_list_init(&obj->interface_link);
+    obj->interface = wif;
+    obj->name = name;
+    obj->version = version;
+    obj->proxy = proxy;
+
+    if (factory->constructor) {
+        if (!factory->constructor(wl, obj)) {
+            mrp_log_error("failed to construct object %u/'%s' on "
+                          "display '%s'",name,wif->name, get_display_name(wl));
+            wl_proxy_destroy(proxy);
+            mrp_free(obj);
+        }
+    }
+
+    /* TODO: register the object by name */
+
+    mrp_debug("object %u/'%s' on display '%s' created", name, wif->name,
+              get_display_name(wl));
+}
+
+
+static void global_available_callback(void *data,
+                                      struct wl_registry *registry,
+                                      uint32_t name,
+                                      const char *interface,
+                                      uint32_t version)
+{
+    mrp_wayland_t *wl = (mrp_wayland_t *)data;
+    mrp_wayland_interface_t *wif;
+
+    MRP_ASSERT(wl && registry && interface, "invalid argument");
+    MRP_ASSERT(registry == wl->registry, "confused with data structures");
+
+    wif = mrp_htbl_lookup(wl->interfaces, (void *)interface);
+
+    mrp_debug("object %u/%s is up%s", name, interface,
+              wif ? "" : " (interface unknown)");
+
+    if (wif) {
+        MRP_ASSERT(wif->wl == wl, "confused with data structures");
+        object_create(wif, name, version);
+    }
+}
+
+static void global_remove_callback(void *data,
+                                   struct wl_registry *wl_registry,
+                                   uint32_t name)
+{
+    MRP_UNUSED(data);
+    MRP_UNUSED(wl_registry);
+
+    mrp_debug("object %u is down", name);
+}
diff --git a/src/plugins/system-controller/wayland/wayland.h b/src/plugins/system-controller/wayland/wayland.h
new file mode 100644 (file)
index 0000000..d284a1d
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_WAYLAND_H__
+#define __MURPHY_WAYLAND_H__
+
+#include <wayland-client.h>
+
+#include <murphy/common/hashtbl.h>
+
+#include "data-types.h"
+
+#define MRP_WAYLAND_INTERFACE_MAX   64
+#define MRP_WAYLAND_OUTPUT_MAX      16
+#define MRP_WAYLAND_WINDOW_MAX      256
+#define MRP_WAYLAND_LAYER_MAX       32
+#define MRP_WAYLAND_LAYER_BUILTIN   8
+#define MRP_WAYLAND_AREA_MAX        32
+#define MRP_WAYLAND_FRAMERATE_MAX   100
+
+#define MRP_WAYLAND_INTERFACE_BUCKETS   (MRP_WAYLAND_INTERFACE_MAX / 2)
+#define MRP_WAYLAND_OUTPUT_BUCKETS      (MRP_WAYLAND_OUTPUT_MAX / 4)
+#define MRP_WAYLAND_WINDOW_BUCKETS      (MRP_WAYLAND_WINDOW_MAX / 2)
+#define MRP_WAYLAND_LAYER_BUCKETS       ((MRP_WAYLAND_LAYER_MAX + \
+                                          MRP_WAYLAND_LAYER_BUILTIN)/ 4)
+#define MRP_WAYLAND_AREA_BUCKETS        (MRP_WAYLAND_AREA_MAX / 4)
+
+#define MRP_WAYLAND_NO_UPDATE INT32_MIN
+
+#define MRP_WAYLAND_OBJECT_COMMON               \
+    mrp_list_hook_t interface_link;             \
+    mrp_wayland_interface_t *interface;         \
+    uint32_t name;                              \
+    uint32_t version;                           \
+    struct wl_proxy *proxy
+
+
+typedef enum mrp_sysctl_scripting_field_e     mrp_wayland_scripting_field_t;
+typedef enum mrp_wayland_output_operation_e   mrp_wayland_output_operation_t;
+typedef enum mrp_wayland_output_update_mask_e mrp_wayland_output_update_mask_t;
+typedef enum mrp_wayland_layer_type_e         mrp_wayland_layer_type_t;
+typedef enum mrp_wayland_layer_operation_e    mrp_wayland_layer_operation_t;
+typedef enum mrp_wayland_layer_update_mask_e  mrp_wayland_layer_update_mask_t;
+typedef enum mrp_wayland_window_update_mask_e mrp_wayland_window_update_mask_t;
+typedef enum mrp_wayland_window_operation_e   mrp_wayland_window_operation_t;
+typedef enum mrp_wayland_animation_type_e     mrp_wayland_animation_type_t;
+typedef enum mrp_wayland_active_e             mrp_wayland_active_t;
+typedef enum mrp_wayland_area_operation_e     mrp_wayland_area_operation_t;
+typedef enum mrp_wayland_area_align_e         mrp_wayland_area_align_t;
+typedef enum mrp_wayland_area_update_mask_e   mrp_wayland_area_update_mask_t;
+
+typedef struct mrp_wayland_s                  mrp_wayland_t;
+typedef struct mrp_wayland_factory_s          mrp_wayland_factory_t;
+typedef struct mrp_wayland_interface_s        mrp_wayland_interface_t;
+typedef struct mrp_wayland_object_s           mrp_wayland_object_t;
+typedef struct mrp_wayland_animation_s        mrp_wayland_animation_t;
+typedef struct mrp_wayland_output_s           mrp_wayland_output_t;
+typedef struct mrp_wayland_output_update_s    mrp_wayland_output_update_t;
+typedef struct mrp_wayland_layer_s            mrp_wayland_layer_t;
+typedef struct mrp_wayland_layer_update_s     mrp_wayland_layer_update_t;
+typedef struct mrp_wayland_window_s           mrp_wayland_window_t;
+typedef struct mrp_wayland_window_update_s    mrp_wayland_window_update_t;
+typedef struct mrp_wayland_area_s             mrp_wayland_area_t;
+typedef struct mrp_wayland_area_update_s      mrp_wayland_area_update_t;
+typedef struct mrp_wayland_window_manager_s   mrp_wayland_window_manager_t;
+typedef struct mrp_wayland_input_manager_s    mrp_wayland_input_manager_t;
+
+#include "application/application.h"
+
+typedef bool (*mrp_wayland_constructor_t)(mrp_wayland_t *,
+                                          mrp_wayland_object_t *);
+typedef void (*mrp_wayland_destructor_t)(mrp_wayland_object_t *);
+
+typedef void (*mrp_wayland_output_update_callback_t)(mrp_wayland_t *,
+                                              mrp_wayland_output_operation_t,
+                                              mrp_wayland_output_update_mask_t,
+                                              mrp_wayland_output_t *);
+typedef void (*mrp_wayland_layer_update_callback_t)(mrp_wayland_t *,
+                                              mrp_wayland_layer_operation_t,
+                                              mrp_wayland_layer_update_mask_t,
+                                              mrp_wayland_layer_t *);
+typedef void (*mrp_wayland_area_update_callback_t)(mrp_wayland_t *,
+                                              mrp_wayland_area_operation_t,
+                                              mrp_wayland_area_update_mask_t,
+                                              mrp_wayland_area_t *);
+typedef void (*mrp_wayland_window_update_callback_t)(mrp_wayland_t *,
+                                              mrp_wayland_window_operation_t,
+                                              mrp_wayland_window_update_mask_t,
+                                              mrp_wayland_window_t *);
+typedef void (*mrp_wayland_app_update_callback_t)(mrp_wayland_t *,
+                                              mrp_application_operation_t,
+                                              mrp_application_update_mask_t,
+                                              mrp_application_t *);
+
+
+struct mrp_wayland_s {
+    const char *display_name;
+
+    mrp_mainloop_t *ml;
+    mrp_io_watch_t *iow;
+
+    struct wl_display *display;
+    struct wl_registry *registry;
+
+    struct wl_registry_listener registry_listener;
+
+    mrp_htbl_t *interfaces;
+    mrp_htbl_t *outputs;
+    mrp_htbl_t *windows;
+    mrp_htbl_t *layers;
+    mrp_htbl_t *areas;
+
+    mrp_wayland_window_manager_t *wm;
+    mrp_wayland_input_manager_t *im;
+
+    mrp_wayland_output_update_callback_t output_update_callback;
+    mrp_wayland_window_update_callback_t window_update_callback;
+    mrp_wayland_layer_update_callback_t layer_update_callback;
+    mrp_wayland_area_update_callback_t area_update_callback;
+    mrp_wayland_app_update_callback_t application_update_callback;
+    void *scripting_data;
+
+    bool create_scripting_windows;
+    bool create_scripting_outputs;
+    bool create_scripting_areas;
+    bool create_scripting_layers;
+};
+
+struct mrp_wayland_factory_s {
+    size_t size;
+    const struct wl_interface *interface;
+    mrp_wayland_constructor_t constructor;
+    mrp_wayland_destructor_t destructor;
+};
+
+struct mrp_wayland_interface_s {
+    mrp_wayland_t *wl;
+    const char *name;
+    mrp_wayland_factory_t object_factory;
+    mrp_list_hook_t object_list;
+};
+
+struct mrp_wayland_object_s {
+    MRP_WAYLAND_OBJECT_COMMON;
+};
+
+
+mrp_wayland_t *mrp_wayland_create(const char *display_name,mrp_mainloop_t *ml);
+void mrp_wayland_destroy(mrp_wayland_t *wl);
+
+mrp_wayland_t *mrp_wayland_iterate(void **cursor);
+
+bool mrp_wayland_connect(mrp_wayland_t *wl);
+void mrp_wayland_flush(mrp_wayland_t *wl);
+
+void mrp_wayland_register_window_manager(mrp_wayland_t *wl,
+                                         mrp_wayland_window_manager_t *wm);
+bool mrp_wayland_register_interface(mrp_wayland_t *wl,
+                                    mrp_wayland_factory_t *factory);
+void mrp_wayland_register_output_update_callback(mrp_wayland_t *wl,
+                               mrp_wayland_output_update_callback_t callback);
+void mrp_wayland_register_window_update_callback(mrp_wayland_t *wl,
+                               mrp_wayland_window_update_callback_t callback);
+void mrp_wayland_register_layer_update_callback(mrp_wayland_t *wl,
+                               mrp_wayland_layer_update_callback_t callback);
+void mrp_wayland_register_area_update_callback(mrp_wayland_t *wl,
+                               mrp_wayland_area_update_callback_t callback);
+void mrp_wayland_set_scripting_data(mrp_wayland_t *, void *);
+
+void mrp_wayland_create_scripting_windows(mrp_wayland_t *wl, bool create);
+void mrp_wayland_create_scripting_outputs(mrp_wayland_t *wl, bool create);
+void mrp_wayland_create_scripting_areas(mrp_wayland_t *wl, bool create);
+void mrp_wayland_create_scripting_layers(mrp_wayland_t *wl, bool create);
+
+#define mrp_wayland_foreach(_wl, _i) \
+    for ((_i) = NULL;  (_wl = mrp_wayland_iterate(&(_i)));)
+
+#endif /* __MURPHY_WAYLAND_H__ */
diff --git a/src/plugins/system-controller/wayland/window-manager.h b/src/plugins/system-controller/wayland/window-manager.h
new file mode 100644 (file)
index 0000000..90032e1
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_WAYLAND_WINDOW_MANAGER_H__
+#define __MURPHY_WAYLAND_WINDOW_MANAGER_H__
+
+#include <sys/types.h>
+
+#include "wayland/wayland.h"
+
+#define MRP_WAYLAND_WINDOW_MANAGER_COMMON                               \
+    MRP_WAYLAND_OBJECT_COMMON;                                          \
+    void (*layer_request)(mrp_wayland_layer_t *,                        \
+                          mrp_wayland_layer_update_t *);                \
+    void (*window_request)(mrp_wayland_window_t *,                      \
+                           mrp_wayland_window_update_t *,               \
+                           mrp_wayland_animation_t *,                   \
+                           uint32_t)
+
+struct mrp_wayland_window_manager_s {
+    MRP_WAYLAND_WINDOW_MANAGER_COMMON;
+};
+
+#endif /* __MURPHY_WAYLAND_WINDOW_MANAGER_H__ */
diff --git a/src/plugins/system-controller/wayland/window.c b/src/plugins/system-controller/wayland/window.c
new file mode 100644 (file)
index 0000000..76c38cc
--- /dev/null
@@ -0,0 +1,796 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+
+#include "window.h"
+#include "layer.h"
+#include "animation.h"
+#include "window-manager.h"
+#include "area.h"
+#include "scripting-wayland.h"
+
+typedef struct {
+    mrp_wayland_window_t *win;
+    int32_t state;
+} update_active_t;
+
+static mrp_wayland_window_update_mask_t update(mrp_wayland_window_t *,
+                                               mrp_wayland_window_update_t *);
+
+static mrp_wayland_window_update_mask_t set_appid(mrp_wayland_window_t *,
+                                                mrp_wayland_window_update_t *);
+
+static char *active_str(mrp_wayland_active_t, char *, size_t);
+
+
+mrp_wayland_window_t *
+mrp_wayland_window_create(mrp_wayland_t *wl, mrp_wayland_window_update_t *u)
+{
+    mrp_wayland_window_t *win;
+    mrp_wayland_window_update_mask_t mask;
+    char buf[2048];
+
+    MRP_ASSERT(wl && u && (u->mask & MRP_WAYLAND_WINDOW_SURFACEID_MASK),
+               "invalid argument");
+
+    if (!wl->wm) {
+        mrp_log_error("failed to create window %d: no window manager",
+                      u->surfaceid);
+        return NULL;
+    }
+
+    if (!(win = mrp_allocz(sizeof(mrp_wayland_window_t)))) {
+        mrp_log_error("failed to create window %d: out of memory",
+                      u->surfaceid);
+        return NULL;
+    }
+
+    win->wm = wl->wm;
+    win->surfaceid = u->surfaceid;
+    win->name = mrp_strdup("");
+    win->appid = mrp_strdup("");
+    win->nodeid = -1;
+    win->x = win->y = -1;
+    win->width = win->height = -1;
+
+    if (!mrp_htbl_insert(wl->windows, &win->surfaceid, win)) {
+        mrp_log_error("failed to create window: already exists");
+        mrp_free(win->name);
+        mrp_free(win->appid);
+        mrp_free(win);
+        return NULL;
+    }
+
+    if (wl->create_scripting_windows) {
+        win->scripting_data = mrp_wayland_scripting_window_create_from_c(NULL,
+                                                                         win);
+    }
+
+    mask = update(win, u);
+
+    mrp_wayland_window_print(win, mask, buf,sizeof(buf));
+    mrp_debug("window %d created%s", win->surfaceid, buf);
+
+    if (win->scripting_data && wl->window_update_callback)
+        wl->window_update_callback(wl, MRP_WAYLAND_WINDOW_CREATE, mask, win);
+
+    return win;
+}
+
+void mrp_wayland_window_destroy(mrp_wayland_window_t *win)
+{
+    mrp_wayland_window_manager_t *wm;
+    mrp_wayland_interface_t *interface;
+    mrp_wayland_t *wl;
+    char buf[1024];
+
+    MRP_ASSERT(win && win->wm && win->wm->interface &&
+               win->wm->interface->wl, "invalid argument");
+
+    wm = win->wm;
+    interface = wm->interface;
+    wl = interface->wl;
+
+    mrp_wayland_window_print(win, MRP_WAYLAND_WINDOW_APPID_MASK |
+                             MRP_WAYLAND_WINDOW_NAME_MASK,
+                             buf, sizeof(buf));
+    mrp_debug("destroying window %d%s", win->surfaceid, buf);
+
+    if (win->scripting_data) {
+        if (wl->window_update_callback)
+            wl->window_update_callback(wl, MRP_WAYLAND_WINDOW_DESTROY, 0, win);
+
+        mrp_wayland_scripting_window_destroy_from_c(NULL, win);
+    }
+    
+
+    mrp_free(win->name);
+    mrp_free(win->appid);
+
+    if ((void *)win != mrp_htbl_remove(wl->windows, &win->surfaceid, false)) {
+        mrp_log_error("failed to destroy window %d: confused with "
+                      "data structures", win->surfaceid);
+        return;
+    }
+
+    free(win);
+}
+
+mrp_wayland_window_t *mrp_wayland_window_find(mrp_wayland_t *wl,
+                                              int32_t surfaceid)
+{
+    MRP_ASSERT(wl, "invalid argument");
+
+    return (mrp_wayland_window_t *)mrp_htbl_lookup(wl->windows, &surfaceid);
+}
+
+
+#if 0
+void mrp_wayland_window_visibility_request(mrp_wayland_window_t *win,
+                                           int32_t visible,
+                                           int32_t raise,
+                                           const char *animation,
+                                           int32_t time)
+{
+    mrp_wayland_window_manager_t *wm;
+    mrp_wayland_window_update_t u;
+    mrp_wayland_animation_t *anims;
+    mrp_wayland_animation_type_t at;
+
+    MRP_ASSERT(win && win->wm, "invalid argument");
+
+    wm = win->wm;
+
+    memset(&u, 0, sizeof(u));
+
+    if (visible >= 0) {
+        u.mask |= MRP_WAYLAND_WINDOW_VISIBLE_MASK;
+        u.visible = visible ? true : false;
+    }
+
+    if (raise >= 0) {
+        u.mask |= MRP_WAYLAND_WINDOW_RAISE_MASK;
+        u.raise = raise ? true : false;
+    }
+
+    if ((anims = mrp_wayland_animation_create())) {
+        at = visible ? MRP_WAYLAND_ANIMATION_SHOW : MRP_WAYLAND_ANIMATION_HIDE;
+        mrp_wayland_animation_set(anims, at, animation, time);
+    }
+
+    wm->window_request(win, &u, anims, 0);
+
+    mrp_wayland_animation_destroy(anims);
+}
+
+void mrp_wayland_window_active_request(mrp_wayland_window_t *win,
+                                       mrp_wayland_active_t active)
+{
+    mrp_wayland_window_manager_t *wm;
+    mrp_wayland_window_update_t u;
+
+    MRP_ASSERT(win && win->wm, "invalid argument");
+
+    wm = win->wm;
+
+    memset(&u, 0, sizeof(u));
+    u.mask = MRP_WAYLAND_WINDOW_ACTIVE_MASK;
+    u.active = active;
+
+    wm->window_request(win, &u, NULL, 0);
+}
+
+void mrp_wayland_window_map_request(mrp_wayland_window_t *win,
+                                    bool map,
+                                    uint32_t framerate)
+{
+    mrp_wayland_window_manager_t *wm;
+    mrp_wayland_window_update_t u;
+
+    MRP_ASSERT(win && win->wm && framerate <= MRP_WAYLAND_FRAMERATE_MAX,
+               "invalid argument");
+
+    wm = win->wm;
+
+    memset(&u, 0, sizeof(u));
+    u.mask = MRP_WAYLAND_WINDOW_MAPPED_MASK;
+    u.mapped = map;
+
+    wm->window_request(win, &u, NULL, framerate);
+}
+
+void mrp_wayland_window_geometry_request(mrp_wayland_window_t *win,
+                                         int32_t nodeid,
+                                         int32_t x,
+                                         int32_t y,
+                                         int32_t width,
+                                         int32_t height,
+                                         const char *move_animation,
+                                         int32_t move_time,
+                                         const char *resize_animation,
+                                         int32_t resize_time)
+{
+    mrp_wayland_window_manager_t *wm;
+    mrp_wayland_window_update_t u;
+    mrp_wayland_animation_t *anims;
+    bool have_move_animation;
+    bool have_resize_animation;
+
+    MRP_ASSERT(win && win->wm, "invalid argument");
+
+    wm = win->wm;
+
+    memset(&u, 0, sizeof(u));
+
+    if (nodeid >= 0) {
+        u.mask |= MRP_WAYLAND_WINDOW_NODEID_MASK;
+        u.nodeid = nodeid;
+    }
+    else if (win->nodeid >= 0) {
+        u.mask |= MRP_WAYLAND_WINDOW_NODEID_MASK;
+        u.nodeid = win->nodeid;
+    }
+
+    if (x != MRP_WAYLAND_NO_UPDATE) {
+        u.mask |= MRP_WAYLAND_WINDOW_X_MASK;
+        u.x = x;
+    }
+    if (y != MRP_WAYLAND_NO_UPDATE) {
+        u.mask |= MRP_WAYLAND_WINDOW_Y_MASK;
+        u.y = y;
+    }
+
+    if (width > 0) {
+        u.mask |= MRP_WAYLAND_WINDOW_WIDTH_MASK;
+        u.width = width;
+    }
+    if (height > 0) {
+        u.mask |= MRP_WAYLAND_WINDOW_HEIGHT_MASK;
+        u.height = height;
+    }
+
+    have_move_animation = (move_animation && move_animation[0] &&
+                           move_time > 0);
+    have_resize_animation = (resize_animation && resize_animation[0] &&
+                             resize_time > 0);
+
+    if (!have_move_animation && !have_resize_animation)
+        anims = NULL;
+    else {
+        if ((anims = mrp_wayland_animation_create())) {
+            if (have_move_animation) {
+                mrp_wayland_animation_set(anims, MRP_WAYLAND_ANIMATION_MOVE,
+                                          move_animation, move_time);
+            }
+            if (have_resize_animation) {
+                mrp_wayland_animation_set(anims, MRP_WAYLAND_ANIMATION_RESIZE,
+                                          resize_animation, resize_time);
+            }
+        }
+    }
+
+    wm->window_request(win, &u, NULL, 0);
+
+    mrp_wayland_animation_destroy(anims);
+}
+
+
+void mrp_wayland_window_layer_request(mrp_wayland_window_t *win,
+                                      int32_t layerid)
+{
+    mrp_wayland_window_manager_t *wm;
+    mrp_wayland_t *wl;
+    mrp_wayland_layer_t *layer;
+    mrp_wayland_window_update_t u;
+
+    MRP_ASSERT(win && win->wm && win->wm->interface && win->wm->interface->wl,
+               "invalid argument");
+
+    wm = win->wm;
+    wl = wm->interface->wl;
+
+    if (!(layer = mrp_wayland_layer_find(wl, layerid))) {
+        mrp_log_error("can't find layer %d", layerid);
+        return;
+    }
+
+    memset(&u, 0, sizeof(u));
+    u.mask = MRP_WAYLAND_WINDOW_LAYER_MASK;
+    u.layer = layer;
+
+    wm->window_request(win, &u, NULL, 0);
+}
+#endif
+
+void mrp_wayland_window_request(mrp_wayland_t *wl,
+                                mrp_wayland_window_update_t *u,
+                                mrp_wayland_animation_t *anims,
+                                uint32_t framerate)
+{
+    mrp_wayland_window_t *win;
+    mrp_wayland_window_manager_t *wm;
+
+    MRP_ASSERT(wl && u, "invalid arguments");
+
+    if (!(u->mask & MRP_WAYLAND_WINDOW_SURFACEID_MASK) ||
+        !(win = mrp_wayland_window_find(wl, u->surfaceid)))
+    {
+        mrp_debug("can't find window %u: request rejected", u->surfaceid);
+        return;
+    }
+
+    MRP_ASSERT(win->wm, "confused with data structures");
+
+    wm = win->wm;
+
+    wm->window_request(win, u, anims, framerate);
+}
+
+static int update_active(void *key, void *object, void *ud)
+{
+    mrp_wayland_window_t *win = (mrp_wayland_window_t *)object;
+    update_active_t *active = (update_active_t *)ud;
+
+    MRP_UNUSED(key);
+
+    if (win != active->win) {
+        if (active->state == 0)
+            win->active = 0;
+        else
+            win->active &= ~active->state;
+
+        mrp_debug("setting window %d 'active' to 0x%x",
+                  win->surfaceid, win->active); 
+    }
+
+    return MRP_HTBL_ITER_MORE;
+}
+
+void mrp_wayland_window_update(mrp_wayland_window_t *win,
+                               mrp_wayland_window_operation_t oper,
+                               mrp_wayland_window_update_t *u)
+{
+    mrp_wayland_window_manager_t *wm;
+    mrp_wayland_interface_t *interface;
+    mrp_wayland_t *wl;
+    int32_t surfaceid;
+    mrp_wayland_window_update_mask_t mask;
+    char buf[2048];
+    update_active_t active;
+
+    MRP_ASSERT(win && win->wm && win->wm->interface &&
+               win->wm->interface->wl && u, "invalid argument");
+
+    wm = win->wm;
+    interface = wm->interface;
+    wl = interface->wl;
+
+    surfaceid = win->surfaceid;
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_SURFACEID_MASK)) {
+        if (u->surfaceid != surfaceid) {
+            mrp_log_error("attempt to change surfaceid to %d of "
+                          "existing window %d", u->surfaceid, surfaceid);
+            return;
+        }
+    }
+
+     mask = update(win, u);
+
+    if (!mask)
+        mrp_debug("window %d update requested but nothing changed", surfaceid);
+    else {
+        mrp_wayland_window_print(win, mask, buf,sizeof(buf));
+        mrp_debug("window %d updated%s", surfaceid, buf);
+    }
+
+    if (win->scripting_data && wl->window_update_callback)
+        wl->window_update_callback(wl, oper, mask, win);
+
+    if (oper == MRP_WAYLAND_WINDOW_ACTIVE) {
+        active.win = win;
+        active.state = win->active;
+        mrp_htbl_foreach(wl->windows, update_active, &active);
+    }
+}
+
+size_t mrp_wayland_window_print(mrp_wayland_window_t *win,
+                                mrp_wayland_window_update_mask_t mask,
+                                char *buf,
+                                size_t len)
+{
+#define PRINT(fmt, args...) \
+    if (p < e) { p += snprintf(p, e-p, "\n      " fmt , ## args); }
+
+    char *p, *e;
+    char as[256];
+
+    e = (p = buf) + len;
+
+    *p = 0;
+
+    if ((mask & MRP_WAYLAND_WINDOW_NAME_MASK))
+        PRINT("name: '%s'", win->name);
+    if ((mask & MRP_WAYLAND_WINDOW_APPID_MASK))
+        PRINT("appid: '%s'", win->appid);
+    if ((mask & MRP_WAYLAND_WINDOW_PID_MASK))
+        PRINT("pid: %u", win->pid);
+    if ((mask & MRP_WAYLAND_WINDOW_NODEID_MASK))
+        PRINT("nodeid: %d", win->nodeid);
+    if ((mask & MRP_WAYLAND_WINDOW_LAYER_MASK))
+        PRINT("layer: '%s'", win->layer ? win->layer->name : "<not set>");
+    if ((mask & MRP_WAYLAND_WINDOW_POSITION_MASK))
+        PRINT("position: %d,%d", win->x, win->y);
+    if ((mask & MRP_WAYLAND_WINDOW_SIZE_MASK))
+        PRINT("size: %dx%d", win->width, win->height);
+    if ((mask & MRP_WAYLAND_WINDOW_VISIBLE_MASK))
+        PRINT("visible: %s", win->visible ? "yes" : "no");
+    if ((mask & MRP_WAYLAND_WINDOW_RAISE_MASK))
+        PRINT("raise: %s", win->raise ? "yes" : "no");
+    if ((mask & MRP_WAYLAND_WINDOW_MAPPED_MASK))
+        PRINT("mapped: %s", win->mapped ? "yes" : "no");
+    if ((mask & MRP_WAYLAND_WINDOW_ACTIVE_MASK)) {
+        PRINT("active: 0x%x =%s", win->active, active_str(win->active,
+                                                          as, sizeof(as)));
+    }
+    if ((mask & MRP_WAYLAND_WINDOW_LAYERTYPE_MASK)) {
+        PRINT("layertype: %d - %s",win->layertype,
+                                   mrp_wayland_layer_type_str(win->layertype));
+    }
+    if ((mask & MRP_WAYLAND_WINDOW_APP_MASK)) {
+        PRINT("application: '%s'", win->application ? win->application->appid :
+                                                      "<unknown>");
+    }
+    if ((mask & MRP_WAYLAND_WINDOW_AREA_MASK)) {
+        PRINT("area: '%s'", win->area ? win->area->name : "<unknown>");
+    }
+
+    return p - buf;
+
+#undef PRINT
+}
+
+size_t mrp_wayland_window_request_print(mrp_wayland_window_update_t *u,
+                                        char *buf, size_t len)
+{
+#define PRINT(fmt, args...) \
+    if (p < e) { p += snprintf(p, e-p, "\n      " fmt , ## args); }
+
+    mrp_wayland_window_update_mask_t mask;
+    char *p, *e;
+    char as[256];
+
+    mask = u->mask;
+    e = (p = buf) + len;
+
+    *p = 0;
+
+    if ((mask & MRP_WAYLAND_WINDOW_NAME_MASK))
+        PRINT("name: '%s'", u->name);
+    if ((mask & MRP_WAYLAND_WINDOW_APPID_MASK))
+        PRINT("appid: '%s'", u->appid);
+    if ((mask & MRP_WAYLAND_WINDOW_PID_MASK))
+        PRINT("pid: %u", u->pid);
+    if ((mask & MRP_WAYLAND_WINDOW_NODEID_MASK))
+        PRINT("nodeid: %d", u->nodeid);
+    if ((mask & MRP_WAYLAND_WINDOW_LAYER_MASK))
+        PRINT("layer: '%s'", u->layer ? u->layer->name : "<not set>");
+    if ((mask & MRP_WAYLAND_WINDOW_POSITION_MASK))
+        PRINT("position: %d,%d", u->x, u->y);
+    if ((mask & MRP_WAYLAND_WINDOW_SIZE_MASK))
+        PRINT("size: %dx%d", u->width, u->height);
+    if ((mask & MRP_WAYLAND_WINDOW_VISIBLE_MASK))
+        PRINT("visible: %s", u->visible ? "yes" : "no");
+    if ((mask & MRP_WAYLAND_WINDOW_RAISE_MASK))
+        PRINT("raise: %s", u->raise ? "yes" : "no");
+    if ((mask & MRP_WAYLAND_WINDOW_MAPPED_MASK))
+        PRINT("mapped: %s", u->mapped ? "yes" : "no");
+    if ((mask & MRP_WAYLAND_WINDOW_ACTIVE_MASK)) {
+        PRINT("active: 0x%x =%s", u->active, active_str(u->active,
+                                                        as, sizeof(as)));
+    }
+    if ((mask & MRP_WAYLAND_WINDOW_LAYERTYPE_MASK)) {
+        PRINT("layertype: %d - %s", u->layertype,
+                                    mrp_wayland_layer_type_str(u->layertype));
+    }
+
+   return p - buf;
+
+#undef PRINT
+}
+
+const char *
+mrp_wayland_window_update_mask_str(mrp_wayland_window_update_mask_t mask)
+{
+    switch (mask) {
+    case MRP_WAYLAND_WINDOW_SURFACEID_MASK: return "surfaceid";
+    case MRP_WAYLAND_WINDOW_NAME_MASK:      return "name";
+    case MRP_WAYLAND_WINDOW_APPID_MASK:     return "appid";
+    case MRP_WAYLAND_WINDOW_PID_MASK:       return "pid";
+    case MRP_WAYLAND_WINDOW_NODEID_MASK:    return "nodeid";
+    case MRP_WAYLAND_WINDOW_LAYER_MASK:     return "layer";
+    case MRP_WAYLAND_WINDOW_X_MASK:         return "x";
+    case MRP_WAYLAND_WINDOW_Y_MASK:         return "y";
+    case MRP_WAYLAND_WINDOW_POSITION_MASK:  return "position";
+    case MRP_WAYLAND_WINDOW_WIDTH_MASK:     return "width";
+    case MRP_WAYLAND_WINDOW_HEIGHT_MASK:    return "height";
+    case MRP_WAYLAND_WINDOW_SIZE_MASK:      return "size";
+    case MRP_WAYLAND_WINDOW_VISIBLE_MASK:   return "visible";
+    case MRP_WAYLAND_WINDOW_RAISE_MASK:     return "raise";
+    case MRP_WAYLAND_WINDOW_ACTIVE_MASK:    return "active";
+    case MRP_WAYLAND_WINDOW_MAPPED_MASK:    return "mapped";
+    case MRP_WAYLAND_WINDOW_LAYERTYPE_MASK: return "layertype";
+    case MRP_WAYLAND_WINDOW_APP_MASK:       return "application";
+    case MRP_WAYLAND_WINDOW_AREA_MASK:      return "area";
+    default:                                return "<unknown>";
+    }
+}
+
+void mrp_wayland_window_set_scripting_data(mrp_wayland_window_t *win,
+                                           void *data)
+{
+    MRP_ASSERT(win, "Invalid Argument");
+
+    mrp_debug("%sset scripting data", data ? "" : "re");
+
+    win->scripting_data = data;
+}
+
+
+static mrp_wayland_window_update_mask_t update(mrp_wayland_window_t *win,
+                                               mrp_wayland_window_update_t *u)
+{
+    mrp_wayland_window_update_mask_t mask = 0;
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_NAME_MASK)) {
+        if (!win->name || strcmp(u->name, win->name)) {
+            mask |= MRP_WAYLAND_WINDOW_NAME_MASK;
+            mrp_free(win->name);
+            win->name = mrp_strdup(u->name);
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_APPID_MASK)) {
+        if (!win->appid || strcmp(u->appid, win->appid)) {
+            mask |= MRP_WAYLAND_WINDOW_APPID_MASK;
+            mrp_free(win->appid);
+            win->appid = mrp_strdup(u->appid);
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_PID_MASK)) {
+        if (u->pid != win->pid) {
+            mask |= MRP_WAYLAND_WINDOW_PID_MASK;
+            win->pid = u->pid;
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_NODEID_MASK)) {
+        if (u->nodeid != win->nodeid) {
+            mask |= MRP_WAYLAND_WINDOW_NODEID_MASK;
+            win->nodeid = u->nodeid;
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_LAYER_MASK)) {
+        if (u->layer != win->layer) {
+            mask |= MRP_WAYLAND_WINDOW_LAYER_MASK;
+            win->layer = u->layer;
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_X_MASK)) {
+        if (u->x != win->x) {
+            mask |= MRP_WAYLAND_WINDOW_POSITION_MASK;
+            win->x = u->x;
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_Y_MASK)) {
+        if (u->y != win->y) {
+            mask |= MRP_WAYLAND_WINDOW_POSITION_MASK;
+            win->y = u->y;
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_WIDTH_MASK)) {
+        if (u->width != win->width) {
+            mask |= MRP_WAYLAND_WINDOW_SIZE_MASK;
+            win->width = u->width;
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_HEIGHT_MASK)) {
+        if (u->height != win->height) {
+            mask |= MRP_WAYLAND_WINDOW_SIZE_MASK;
+            win->height = u->height;
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_VISIBLE_MASK)) {
+        if ((u->visible && !win->visible) || (!u->visible && win->visible)) {
+            mask |= MRP_WAYLAND_WINDOW_VISIBLE_MASK |
+                    MRP_WAYLAND_WINDOW_RAISE_MASK   ;
+            win->visible = u->visible;
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_RAISE_MASK)) {
+        if ((u->raise && !win->raise) || (!u->raise && win->raise)) {
+            mask |= MRP_WAYLAND_WINDOW_RAISE_MASK   |
+                    MRP_WAYLAND_WINDOW_VISIBLE_MASK ;
+            win->raise = u->raise;
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_MAPPED_MASK)) {
+        if ((u->mapped && !win->mapped) || (!u->mapped && win->mapped)) {
+            mask |= MRP_WAYLAND_WINDOW_MAPPED_MASK;
+            win->mapped = u->mapped;
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_ACTIVE_MASK)) {
+        if ((u->active && !win->active) || (!u->active && win->active)) {
+            mask |= MRP_WAYLAND_WINDOW_ACTIVE_MASK;
+            win->active = u->active;
+        }
+    }
+
+    if ((u->mask & MRP_WAYLAND_WINDOW_LAYERTYPE_MASK)) {
+        if ((u->layertype != win->layertype)) {
+            mask |= MRP_WAYLAND_WINDOW_LAYERTYPE_MASK;
+            win->layertype = u->layertype;
+        }
+    }
+
+    if ((mask & MRP_WAYLAND_WINDOW_APPID_MASK)) {
+        mask |= set_appid(win, u);
+    }
+
+    return mask;
+}
+
+static mrp_wayland_window_update_mask_t set_appid(mrp_wayland_window_t *win,
+                                                mrp_wayland_window_update_t *u)
+{
+    mrp_wayland_window_update_mask_t mask = 0;
+    mrp_wayland_window_manager_t *wm = win->wm;
+    mrp_wayland_window_update_t u2;
+
+    if (win->application || !u->appid)
+        return mask;
+
+    win->application = mrp_application_find(win->appid);
+    win->area = NULL;
+
+    if (!win->application)
+        win->application = mrp_application_find("default");
+
+    if (!win->application) {
+        mrp_log_error("system-controller: can't find application '%s'",
+                      win->appid);
+        return mask;
+    }
+
+    mrp_debug("found application '%s'", win->application->appid);
+
+    mask |= MRP_WAYLAND_WINDOW_APP_MASK; 
+
+    memset(&u2, 0, sizeof(u2));
+
+    if (!(u2.area = win->application->area)) {
+        mrp_log_error("system-controller: no area for application '%s'",
+                      win->application->appid);
+        return mask;
+    }
+
+    mrp_debug("found area '%s'", u2.area->name);
+
+    u2.mask |= MRP_WAYLAND_WINDOW_AREA_MASK;
+
+    if (!(mask & MRP_WAYLAND_WINDOW_POSITION_MASK)) {
+        u2.mask |= MRP_WAYLAND_WINDOW_POSITION_MASK;
+        u2.x = u2.area->x;
+        u2.y = u2.area->y;
+    }
+
+    if (!(mask & MRP_WAYLAND_WINDOW_SIZE_MASK)) {
+        u2.mask |= MRP_WAYLAND_WINDOW_SIZE_MASK;
+        u2.width  = u2.area->width;
+        u2.height = u2.area->height;
+    }
+
+    wm->window_request(win, &u2, NULL, 0);
+
+    if ((u2.mask & MRP_WAYLAND_WINDOW_POSITION_MASK)) {
+        mask |= MRP_WAYLAND_WINDOW_POSITION_MASK;
+        win->x = u2.x;
+        win->y = u2.y;
+    }
+                
+    if ((u2.mask & MRP_WAYLAND_WINDOW_SIZE_MASK)) {
+        mask |= MRP_WAYLAND_WINDOW_SIZE_MASK;
+        win->width  = u2.width;
+        win->height = u2.height;
+    }
+
+    return mask;
+}
+                                   
+
+static char *active_str(mrp_wayland_active_t active, char *buf, size_t len)
+{
+#define PRINT(fmt, args... ) \
+    if (p < e) { p += snprintf(p, e-p, " " fmt , ## args); }
+
+    typedef struct {
+        mrp_wayland_active_t mask;
+        const char *name;
+    } map_t;
+
+    static map_t map[] = {
+        { MRP_WAYLAND_WINDOW_ACTIVE_POINTER,  "pointer"  },
+        { MRP_WAYLAND_WINDOW_ACTIVE_KEYBOARD, "keyboard" },
+        { MRP_WAYLAND_WINDOW_ACTIVE_SELECTED, "selected" },
+        {                 0,                      NULL   }
+    };
+
+    map_t *m;
+    char *p, *e;
+
+    e = (p = buf) + len;
+
+    if (!active) {
+        PRINT("<none>");
+    }
+    else {
+        for (m = map;   active && m->name;   m++) {
+            if ((active & m->mask)) {
+                PRINT("%s", m->name);
+                active &= ~m->mask;
+            }
+        }
+
+        if (active)
+            PRINT("<unknown 0x%x>", active);
+    }
+
+    return buf;
+
+#undef PRINT
+}
diff --git a/src/plugins/system-controller/wayland/window.h b/src/plugins/system-controller/wayland/window.h
new file mode 100644 (file)
index 0000000..bc34304
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2013, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of Intel Corporation nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MURPHY_WAYLAND_WINDOW_H__
+#define __MURPHY_WAYLAND_WINDOW_H__
+
+#include <sys/types.h>
+
+#include "wayland/layer.h"
+
+enum mrp_wayland_active_e {
+    MRP_WAYLAND_WINDOW_ACTIVE_NONE = 0,
+    MRP_WAYLAND_WINDOW_ACTIVE_POINTER = 1,
+    MRP_WAYLAND_WINDOW_ACTIVE_KEYBOARD = 2,
+    MRP_WAYLAND_WINDOW_ACTIVE_SELECTED = 4,
+};
+
+enum mrp_wayland_window_operation_e {
+    MRP_WAYLAND_WINDOW_OPERATION_NONE = 0,
+    MRP_WAYLAND_WINDOW_CREATE,       /* 1 */
+    MRP_WAYLAND_WINDOW_DESTROY,      /* 2 */
+    MRP_WAYLAND_WINDOW_NAMECHANGE,   /* 3 */
+    MRP_WAYLAND_WINDOW_VISIBLE,      /* 4 */
+    MRP_WAYLAND_WINDOW_CONFIGURE,    /* 5 */
+    MRP_WAYLAND_WINDOW_ACTIVE        /* 6 */
+};
+
+
+struct mrp_wayland_window_s {
+    mrp_wayland_window_manager_t *wm;
+    int32_t surfaceid;
+    char *name;
+
+    char *appid;
+    pid_t pid;
+
+    int32_t nodeid;
+    mrp_wayland_layer_t *layer;
+    int32_t x, y;
+    int32_t width, height;
+    bool visible;
+    bool raise;
+    bool mapped;
+    mrp_wayland_active_t active;
+    mrp_wayland_layer_type_t layertype;
+
+    mrp_application_t *application;
+    mrp_wayland_area_t *area;
+
+    void *scripting_data;
+};
+
+
+enum mrp_wayland_window_update_mask_e {
+    MRP_WAYLAND_WINDOW_SURFACEID_MASK   = 0x00001,
+    MRP_WAYLAND_WINDOW_NAME_MASK        = 0x00002,
+    MRP_WAYLAND_WINDOW_APPID_MASK       = 0x00004,
+    MRP_WAYLAND_WINDOW_PID_MASK         = 0x00008,
+    MRP_WAYLAND_WINDOW_NODEID_MASK      = 0x00010,
+    MRP_WAYLAND_WINDOW_LAYER_MASK       = 0x00020,
+    MRP_WAYLAND_WINDOW_X_MASK           = 0x00040,
+    MRP_WAYLAND_WINDOW_Y_MASK           = 0x00080,
+    MRP_WAYLAND_WINDOW_POSITION_MASK    = 0x000C0,
+    MRP_WAYLAND_WINDOW_WIDTH_MASK       = 0x00100,
+    MRP_WAYLAND_WINDOW_HEIGHT_MASK      = 0x00200,
+    MRP_WAYLAND_WINDOW_SIZE_MASK        = 0x00300,
+    MRP_WAYLAND_WINDOW_VISIBLE_MASK     = 0x00400,
+    MRP_WAYLAND_WINDOW_RAISE_MASK       = 0x00800,
+    MRP_WAYLAND_WINDOW_MAPPED_MASK      = 0x01000,
+    MRP_WAYLAND_WINDOW_ACTIVE_MASK      = 0x02000,
+    MRP_WAYLAND_WINDOW_LAYERTYPE_MASK   = 0x04000,
+    MRP_WAYLAND_WINDOW_APP_MASK         = 0x08000,
+    MRP_WAYLAND_WINDOW_AREA_MASK        = 0x10000,
+
+    MRP_WAYLAND_WINDOW_END_MASK         = 0x20000
+};
+
+
+struct mrp_wayland_window_update_s {
+    mrp_wayland_window_update_mask_t mask;
+    int32_t surfaceid;
+    const char *name;
+    const char *appid;
+    pid_t pid;
+    int32_t nodeid;
+    mrp_wayland_layer_t *layer;
+    int32_t x, y;
+    int32_t width, height;
+    bool visible;
+    bool raise;
+    bool mapped;
+    mrp_wayland_active_t active;
+    mrp_wayland_layer_type_t layertype;
+    mrp_wayland_area_t *area;
+};
+
+mrp_wayland_window_t *
+mrp_wayland_window_create(mrp_wayland_t *wl, mrp_wayland_window_update_t *u);
+
+void mrp_wayland_window_destroy(mrp_wayland_window_t *win);
+
+mrp_wayland_window_t *mrp_wayland_window_find(mrp_wayland_t *wl,
+                                              int32_t surfaceid);
+
+#if 0
+void mrp_wayland_window_visibility_request(mrp_wayland_window_t *win,
+                                           int32_t visible, int32_t raise,
+                                           const char *animation_name,
+                                           int32_t animation_time);
+void mrp_wayland_window_active_request(mrp_wayland_window_t *win,
+                                       mrp_wayland_active_t active);
+void mrp_wayland_window_map_request(mrp_wayland_window_t *win,
+                                    bool map, uint32_t framerate);
+void mrp_wayland_window_geometry_request(mrp_wayland_window_t *win,
+                                         int32_t nodeid,
+                                         int32_t x, int32_t y,
+                                         int32_t width, int32_t height,
+                                         const char *move_animation,
+                                         int32_t move_time,
+                                         const char *resize_animation,
+                                         int32_t resize_time);
+void mrp_wayland_window_layer_request(mrp_wayland_window_t *win,
+                                      int32_t layerid);
+#endif
+
+void mrp_wayland_window_request(mrp_wayland_t *wl,
+                                mrp_wayland_window_update_t *u,
+                                mrp_wayland_animation_t *anims,
+                                uint32_t framerate);
+
+void mrp_wayland_window_update(mrp_wayland_window_t *win,
+                               mrp_wayland_window_operation_t oper,
+                               mrp_wayland_window_update_t *u);
+
+size_t mrp_wayland_window_print(mrp_wayland_window_t *win,
+                                mrp_wayland_window_update_mask_t mask,
+                                char *buf,
+                                size_t len);
+size_t mrp_wayland_window_request_print(mrp_wayland_window_update_t *u,
+                                        char *buf, size_t len);
+
+const char *mrp_wayland_window_update_mask_str(
+                                        mrp_wayland_window_update_mask_t mask);
+
+void mrp_wayland_window_set_scripting_data(mrp_wayland_window_t *win,
+                                           void *data);
+
+#endif /* __MURPHY_WAYLAND_WINDOW_H__ */
index d8b9c64..1cf3be0 100644 (file)
@@ -27,8 +27,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef __MURPHY_DATA_TYPES_H__
-#define __MURPHY_DATA_TYPES_H__
+#ifndef __MURPHY_RESOURCE_DATA_TYPES_H__
+#define __MURPHY_RESOURCE_DATA_TYPES_H__
 
 #include <stdint.h>
 #include <stdbool.h>
@@ -160,7 +160,7 @@ struct mrp_resource_set_definition_s {
     uint32_t    priority;
 };
 
-#endif  /* __MURPHY_DATA_TYPES_H__ */
+#endif  /* __MURPHY_RESOURCE_DATA_TYPES_H__ */
 
 /*
  * Local Variables: