system-controller: add screen resource support
authorJanos Kovacs <jankovac503@gmail.com>
Sat, 14 Dec 2013 00:19:25 +0000 (02:19 +0200)
committerKrisztian Litkey <krisztian.litkey@intel.com>
Thu, 8 Jan 2015 16:37:12 +0000 (18:37 +0200)
Change-Id: I9738c71923fc7e1ed305f3ab9a1fcd79fbfea30d

32 files changed:
packaging.in/murphy.lua
src/Makefile.am
src/core/lua-utils/object.c
src/plugins/system-controller/application/application.c
src/plugins/system-controller/application/application.h
src/plugins/system-controller/application/scripting-application.c
src/plugins/system-controller/data-types.h
src/plugins/system-controller/plugin-system-controller.c
src/plugins/system-controller/resource-client/resource-client.c [new file with mode: 0644]
src/plugins/system-controller/resource-client/resource-client.h [new file with mode: 0644]
src/plugins/system-controller/resource-client/scripting-resource-client.c [new file with mode: 0644]
src/plugins/system-controller/resource-client/scripting-resource-client.h [new file with mode: 0644]
src/plugins/system-controller/resource-manager/notifier.c [new file with mode: 0644]
src/plugins/system-controller/resource-manager/notifier.h [new file with mode: 0644]
src/plugins/system-controller/resource-manager/resource-manager.c
src/plugins/system-controller/resource-manager/resource-manager.h
src/plugins/system-controller/resource-manager/screen.c [new file with mode: 0644]
src/plugins/system-controller/resource-manager/screen.h [new file with mode: 0644]
src/plugins/system-controller/resource-manager/scripting-notifier.c [new file with mode: 0644]
src/plugins/system-controller/resource-manager/scripting-resource-manager.c
src/plugins/system-controller/resource-manager/scripting-resource-manager.h
src/plugins/system-controller/wayland/ico-window-manager.c
src/plugins/system-controller/wayland/layer.c
src/plugins/system-controller/wayland/layer.h
src/plugins/system-controller/wayland/scripting-wayland.c
src/plugins/system-controller/wayland/scripting-window-manager.c
src/plugins/system-controller/wayland/scripting-window.c
src/plugins/system-controller/wayland/wayland.c
src/plugins/system-controller/wayland/wayland.h
src/plugins/system-controller/wayland/window-manager.h
src/plugins/system-controller/wayland/window.c
src/plugins/system-controller/wayland/window.h

index 2b130dc..17a70ff 100644 (file)
@@ -1,4 +1,5 @@
 with_system_controller = true
+verbose = 0
 
 m = murphy.get()
 
@@ -452,13 +453,23 @@ m:try_load_plugin('telephony')
 
 -- system controller test setup
 
-if not with_system_controller or
-   not m:plugin_exists('system-controller') then
+if not with_system_controller or not m:plugin_exists('system-controller') then
    return
 end
 
 m:load_plugin('system-controller')
 
+window_manager_operation_names = {
+    [1] = "create",
+    [2] = "destroy"
+}
+
+function window_manager_operation_name(oper)
+    local name = window_manager_operation_names[oper]
+    if name then return name end
+    return "<unknown " .. tostring(oper) .. ">"
+end
+
 window_operation_names = {
     [1] = "create",
     [2] = "destroy",
@@ -474,6 +485,18 @@ function window_operation_name(oper)
     return "<unknown " .. tostring(oper) .. ">"
 end
 
+layer_operation_names = {
+    [1] = "create",
+    [2] = "destroy",
+    [3] = "visible"
+}
+
+function layer_operation_name(oper)
+    local name = layer_operation_names[oper]
+    if name then return name end
+    return "<unknown " .. tostring(oper) .. ">"
+end
+
 command_names = {
     [0x00001] = "send_appid",
     [0x10001] = "create",
@@ -492,7 +515,17 @@ command_names = {
     [0x10022] = "change_layer_attr",
     [0x20001] = "add_input",
     [0x20002] = "del_input",
-    [0x20003] = "send_input"
+    [0x20003] = "send_input",
+    [0x40001] = "acquire_res",
+    [0x40002] = "release_res",
+    [0x40003] = "deprive_res",
+    [0x40004] = "waiting_res",
+    [0x40005] = "revert_res",
+    [0x40011] = "create_res",
+    [0x40012] = "destroy_res",
+    [0x50001] = "set_region",
+    [0x50002] = "unset_region",
+    [0x60001] = "change_state"
 }
 
 function command_name(command)
@@ -501,7 +534,45 @@ function command_name(command)
     return "<unknown " .. tostring(command) .. ">"
 end
 
-wmgr = window_manager({
+input_layer = {
+   [3] = true, -- input
+   [4] = true, -- touch
+   [5] = true  -- cursor
+}
+
+resmgr = resource_manager {
+  screen_event_handler = function(self, ev)
+                             local event = ev.event
+                             local surface = ev.surface
+
+                             if event == "grant" then
+                                 if verbose > 0 then
+                                    print("*** make visible surface "..surface)
+                                 end
+                                 local a = animation({})
+                                 local r = m:JSON({surface = surface,
+                                                   visible = 1,
+                                                   raise   = 1})
+                                 wmgr:window_request(r,a,0)
+                                 elseif event == "revoke" then
+                                 if verbose > 0 then
+                                    print("*** hide surface "..surface)
+                                 end
+                                 local a = animation({})
+                                 local r = m:JSON({surface = ev.surface,
+                                                   visible = 0})
+                                 wmgr:window_request(r,a,0)
+                             else
+                                 if verbose > 0 then
+                                    print("*** resource event: "..tostring(ev))
+                                 end
+                             end
+                         end
+}
+
+resclnt = resource_client {}
+
+wmgr = window_manager {
   geometry = function(self, w,h, v)
                   if type(v) == "function" then
                       return v(w,h)
@@ -509,10 +580,22 @@ wmgr = window_manager({
                   return v
              end,
 
+  application = function(self, appid)
+                     if appid then
+                         local app = application_lookup(appid)
+                         if not app then
+                             app = application_lookup("default")
+                         end
+                         return app
+                     end
+                     return { privileges = {screen="none", audio="none"} }
+                end,
+
   outputs = { { name  = "Center",
                 id    = 0,
+                zone  = "driver",
                 areas = { Status = {
-                              id     = 100,
+                              id     = 0,
                               pos_x  = 0,
                               pos_y  = 0,
                               width  = function(w,h) return w end,
@@ -591,6 +674,7 @@ wmgr = window_manager({
                         }
                },
                { name  = "Mid",
+                 zone  = "driver",
                  id    = 1
                }
 
@@ -603,8 +687,8 @@ wmgr = window_manager({
              {      5, "InterruptApp" , 2 },
              {      6, "OnScreen"     , 2 },
              {    101, "Input"        , 3 },
-             {    102, "Touch"        , 4 },
-             {    103, "Cursor"       , 5 },
+             {    102, "Cursor"       , 5 },
+             {    103, "Startup"      , 6 },
              { 0x1000, "Background"   , 1 },
              { 0x2000, "Normal"       , 2 },
              { 0x3000, "Fullscreen"   , 2 },
@@ -615,10 +699,32 @@ wmgr = window_manager({
   },
 
 
+  manager_update = function(self, oper)
+                       if verbose > 0 then
+                           print("### <== WINDOW MANAGER UPDATE:" ..
+                                 window_manager_operation_name(oper))
+                       end
+                       if oper == 1 then
+                           local umask = window_mask { raise   = true,
+                                                       visible = true,
+                                                       active  = true }
+                           local rmask = window_mask { active  = true }
+                           local req = m:JSON({
+                                       passthrough_update  = umask:tointeger(),
+                                       passthrough_request = rmask:tointeger()
+                           })
+                           self:manager_request(req)
+                       end
+                   end,
+
   window_update = function(self, oper, win, mask)
-                      if (verbose) then
-                          print("*** WINDOW UPDATE oper:"..window_operation_name(oper).." mask: "..tostring(mask))
-                          print(win)
+                      if verbose > 0 then
+                          print("### <== WINDOW UPDATE oper:" ..
+                                window_operation_name(oper) ..
+                                " mask: " .. tostring(mask))
+                          if verbose > 1 then
+                              print(win)
+                          end
                       end
 
                       local arg = m:JSON({ surface = win.surface,
@@ -627,8 +733,11 @@ wmgr = window_manager({
                       local command = 0
 
                       if oper == 1 then -- create
-                           if win.layertype and win.layertype == 3 then
-                               print("ignoring input panel window creation")
+                           local layertype = win.layertype
+                           if layertype and input_layer[layertype] then
+                               if verbose > 0 then
+                                   print("ignoring input panel creation")
+                               end
                                return
                            end
                            command     = 0x10001
@@ -649,13 +758,12 @@ wmgr = window_manager({
                            arg.visible = win.visible
                            arg.active  = win.active
                       elseif oper == 6 then -- active
-                           if false and win.active ~= 0 then
-                               print("### already active")
-                               return
-                           end
-                           command = 0x10006
+                           command     = 0x10006
+                           arg.active  = win.active
                       else
-                           print("### nothing to do")
+                           if verbose > 0 then
+                               print("### nothing to do")
+                           end
                            return
                       end
 
@@ -664,33 +772,98 @@ wmgr = window_manager({
                                            pid     = win.pid,
                                            arg     = arg
                       })
-                      print("### sending window message: " .. command_name(msg.command))
-                      print(msg)
-                      sc:send_message(msg.appid, msg)
+                      if verbose > 0 then
+                          print("### <== sending " ..
+                                command_name(msg.command) ..
+                                " window message to '" .. win.name .. "'")
+                          if verbose > 1 then
+                              print(msg)
+                          end
+                      end
+                      sc:send_message(sysctlid, msg)
 
-                      if (oper == 1) then -- create
-                          local a = animation({})
-                          local r = m:JSON({surface = win.surface,
-                                            visible = 1,
-                                            raise   = 1})
-                          self:window_request(r,a,0)
+                      if oper == 1 then -- create
+                          local i = input_layer[win.layertype]
+                          local p = self:application(win.appid)
+                          local s = p.privileges.screen
+
+                          if s == "system" then
+                              local a = animation({})
+                              local r = m:JSON({surface = win.surface,
+                                                visible = 1,
+                                                raise   = 1})
+                              self:window_request(r,a,0)
+                          else
+                              if i then
+                                  if verbose > 0 then
+                                      print("do not make resource for " ..
+                                            "input window")
+                                  end
+                              else
+                                  resclnt:resource_set_create("screen",
+                                                               "driver",
+                                                               win.appid,
+                                                               win.surface)
+                              end
+                          end
+                      elseif oper == 2 then -- destroy
+                          resclnt:resource_set_destroy("screen", win.surface)
+                      elseif oper == 6 then -- active
+                          if win.active then
+                              local i = input_layer[win.layertype]
+                              local p = self:application(win.appid)
+                              local s = p.privileges.screen
+                              local surface = win.surface
+                              if not i and s ~= "system" then
+                                 resclnt:resource_set_acquire("screen",surface)
+                                 resmgr:window_raise(win.appid, surface, 1)
+                              end
+                          end
                       end
                   end,
 
-  layer_update = function(self, oper, j, mask)
-                      if verbose then
-                          print("*** LAYER UPDATE oper:"..oper.." mask: "..tostring(mask))
-                          print(j)
+  layer_update = function(self, oper, layer, mask)
+                      if verbose > 0 then
+                          print("### LAYER UPDATE:" .. 
+                                layer_operation_name(oper) ..
+                                " mask: " .. tostring(mask))
+                          if verbose > 1 then
+                              print(layer)
+                          end
+                      end
+                      if oper == 3 then -- visible
+                         local command = 0x10022
+                         local msg = m:JSON({
+                                         command = command,
+                                         appid = "",
+                                         arg = m:JSON({layer = layer.id,
+                                                       visible = layer.visible
+                                         })
+                                })
+                         if verbose > 0 then
+                            print("### <== sending "..command_name(command)..
+                                  " layer message")
+                            if verbose > 1 then
+                                print(msg)
+                            end
+                         end
+                         sc:send_message(sysctlid, msg)
+                      else
+                           if verbose > 0 then
+                               print("### nothing to do")
+                           end
                       end
                  end,
+
   output_update = function(self, oper, out, mask)
                       local idx = out.index
-                      if verbose then
-                          print("*** OUTPUT UPDATE oper:"..oper.." mask: "..tostring(mask))
+                      if verbose > 0 then
+                          print("### OUTPUT UPDATE:" .. oper ..
+                                " mask: "..tostring(mask))
                       end
                       print(out)
+                      local outdef = self.outputs[idx+1]
                       if (oper == 1) then -- create
-                          local outdef = self.outputs[idx+1]
                           if outdef then
                               self:output_request(m:JSON({index = idx,
                                                           id    = outdef.id,
@@ -698,19 +871,25 @@ wmgr = window_manager({
                                                           }))
                           end
                       elseif (oper == 5) then -- done
-                          local ads = self.outputs[idx+1].areas
+                          local ads = outdef.areas
+                          local on = outdef.name
                           if ads then
-                              for name,area in pairs(ads) do
-                                  local a = m:JSON({name=name,output=out.index})
-                                  for fld,val in pairs(area) do
-                                      a[fld] = self:geometry(out.width,out.height,val)
+                              for name,ad in pairs(ads) do
+                                  local can = wmgr:canonical_name(on.."."..name)
+                                  local a = m:JSON({name   = name,
+                                                    output = out.index})
+                                  for fld,val in pairs(ad) do
+                                      a[fld] = self:geometry(out.width,
+                                                             out.height,
+                                                             val) 
                                    end
                                    self:area_create(a)
+                                   resmgr:area_create(area[can], outdef.zone)
                               end
                           end
                       end
                   end
-})
+}
 
 
 sc = m:get_system_controller()
@@ -719,100 +898,207 @@ sc = m:get_system_controller()
 sets = {}
 
 connected = false
+sysctlid = ""
 
 -- these shoud be before wmgr:connect() is called
-print("====== creating applications")
+if verbose > 0 then
+   print("====== creating applications ======")
+end
 application {
-    appid      = "default",
-    area       = "Center.Full",
-    privileges = { screen = "none", audio = "none" }
+    appid          = "default",
+    area           = "Center.Full",
+    privileges     = { screen = "none", audio = "none" },
+    resource_class = "player",
+    screen_priority = 0
 }
 
 application {
-    appid      = "org.tizen.ico.homescreen",
-    area       = "Center.Full",
-    privileges = { screen = "system", audio = "system" }
+    appid           = "weston",
+    area            = "Center.Full",
+    privileges      = { screen = "system", audio = "none" },
+    resource_class  = "implicit",
+    screen_priority = 30
 }
 
 application {
-    appid      = "org.tizen.ico.statusbar",
-    area       = "Center.Status",
-    privileges = { screen = "system", audio = "none" }
+    appid           = "org.tizen.ico.homescreen",
+    area            = "Center.Full",
+    privileges      = { screen = "system", audio = "system" },
+    resource_class  = "player",
+    screen_priority = 20
+}
+
+application {
+    appid           = "org.tizen.ico.statusbar",
+    area            = "Center.Status",
+    privileges      = { screen = "system", audio = "none" },
+    resource_class  = "player",
+    screen_priority = 20 
 }
 
 
 if sc then
     sc.client_handler = function (self, cid, msg)
-        print('*** client handler: ' .. tostring(msg))
+        local command = msg.command
+        if verbose > 0 then
+            print('### ==> client handler:')
+            if verbose > 1 then
+                print(msg)
+            end
+        end
         if not connected then
+            print('Setting sysctlid='..msg.appid)
+            sysctlid = msg.appid
             print('Trying to connect to wayland...')
             connected = wmgr:connect()
-        else
-            print('Window manager already connected...')
+        end
+        if connected and command then
+            if command == 1 then -- send_appid
+                local reply = m:JSON({ command = 0x60001,
+                                       arg     = m:JSON({ stateid = 1,
+                                                          state   = 0})
+                                     })
+                 if verbose > 0 then
+                     print("### <== sending " ..
+                           command_name(command) .. " message")
+                     if verbose > 1 then
+                         print(reply)
+                     end
+                 end
+                 sc:send_message(sysctlid, reply)
+
+                 reply = m:JSON({ command = 0x60001,
+                                  arg     = m:JSON({ stateid = 2,
+                                                     state   = 0})
+                                })
+                 if verbose > 0 then
+                     print("### <== sending " ..
+                           command_name(command) .. " message")
+                     if verbose > 1 then
+                         print(reply)
+                     end
+                 end
+                 sc:send_message(sysctlid, reply)
+            end
         end
     end
 
     sc.generic_handler = function (self, cid, msg)
-        print('*** generic handler: ' .. tostring(msg))
+        if verbose > 0 then
+            print('### ==> generic handler:')
+            if verbose > 1 then
+               print(msg)
+            end
+        end
     end
 
     sc.window_handler = function (self, cid, msg)
-        print('*** window handler: ' .. command_name(msg.command) .. ' ' .. tostring(msg))
+        if verbose > 0 then
+            print('### ==> received ' ..
+                   command_name(msg.command) .. ' message')
+            if verbose > 1 then
+                print(tostring(msg))
+            end
+        end
 
         local a = animation({})
+        local nores = false
         if msg.command == 0x10003 then       -- ico SHOW command
             local raise_mask = 0x01000000
             local lower_mask = 0x02000000
+            local nores_mask = 0x40000000
+            local time_mask  = 0x00ffffff
             msg.arg.visible = 1
-            if msg.arg and msg.arg.anim_name then
-                local time = msg.arg.time
-                time = m:AND(time, m:NEG(m:OR(raise_mask, lower_mask)))
-                time = 200
-                if m:AND(msg.arg.anim_time, raise_mask) then
-                    msg.arg.raise = 1
-                elseif m:AND(msg.arg.anim_time, lower_mask) then
-                    msg.arg.raise = 0
+            if msg.arg then
+                local time = 200
+                if  msg.arg.anim_time then
+                    local t = msg.arg.anim_time
+                    time = m:AND(t, time_mask)
+                    nores = m:AND(t, nores_mask)
+                    if m:AND(t, raise_mask) then
+                        msg.arg.raise = 1
+                    elseif m:AND(t, lower_mask) then
+                        msg.arg.raise = 0
+                    end
+                end
+                if msg.arg.anim_name then
+                    a.show = { msg.arg.anim_name, time }
+                    print('time: ' .. tostring(a.show[2]))
                 end
-                a.show = { msg.arg.anim_name, time }
-                print('time: ' .. tostring(a.show[2]))
             end
-            print('##### SHOW')
-            print(tostring(msg.arg))
-            wmgr:window_request(msg.arg, a, 0)
+            if not nores then
+                local p = wmgr:application(msg.appid)
+                local s = p.privileges.screen
+                if s == "system" then
+                    nores = true
+                end
+            end
+            if verbose > 2 then
+                print('### ==> SHOW')
+                print(tostring(msg.arg))
+            end
+            if nores then
+                wmgr:window_request(msg.arg, a, 0)
+            else
+                local surface = msg.arg.surface
+                resclnt:resource_set_acquire("screen", surface)
+                resmgr:window_raise(msg.appid, surface, 1)
+            end
         elseif msg.command == 0x10004 then   -- ico HIDE command
             local raise_mask = 0x01000000
             local lower_mask = 0x02000000
+            local nores_mask = 0x40000000
+            local time_mask  = 0x00ffffff
             msg.arg.visible = 0
-            if msg.arg and msg.arg.anim_name then
-                local time = msg.arg.time
-                time = m:AND(time, m:NEG(m:OR(raise_mask, lower_mask)))
-                time = 200
-                if m:AND(msg.arg.anim_time, raise_mask) then
-                    msg.arg.raise = 1
+            if msg.arg then
+                local time = 200
+                if msg.arg.anim_time then
+                    local t = msg.arg.anim_time
+                    time = m:AND(t, time_mask)
+                    nores = m:AND(t, nores_mask)
                 end
-                if m:AND(msg.arg.anim_time, lower_mask) then
-                    msg.arg.raise = 0
+                if msg.arg.anim_name then
+                    a.hide = { msg.arg.anim_name, time }
+                    print('hide animation time: ' .. tostring(a.hide[2]))
                 end
-                a.hide = { msg.arg.anim_name, time }
-                print('hide animation time: ' .. tostring(a.hide[2]))
             end
-            print('##### HIDE')
-            print(tostring(msg.arg))
-            wmgr:window_request(msg.arg, a, 0)
+            if not nores then
+                local p = wmgr:application(msg.appid)
+                local s = p.privileges.screen
+                if s == "system" then
+                    nores = true
+                end
+            end
+            if verbose > 2 then
+                print('### ==> HIDE REQUEST')
+                print(tostring(msg.arg))
+            end
+            if nores then
+                wmgr:window_request(msg.arg, a, 0)
+            else
+                resmgr:window_raise(msg.appid, msg.arg.surface, -1)
+            end
         elseif msg.command == 0x10005 then   -- ico MOVE
-            print('##### MOVE')
-            print(tostring(msg.arg))
+            if verbose > 2 then
+                print('### ==> MOVE REQUEST')
+                print(tostring(msg.arg))
+            end
             wmgr:window_request(msg.arg, a, 0)
+            -- TODO: handle if area changed
         elseif msg.command == 0x10006 then   -- ico ACTIVE
-            print('##### ACTIVE')
             if not msg.arg.active then
-                msg.arg.active = 0
+                msg.arg.active = 3 -- pointer + keyboard
+            end
+            if verbose > 2 then
+                print('### ==> ACTIVE REQUEST')
+                print(tostring(msg.arg))
             end
-            print(tostring(msg.arg))
             wmgr:window_request(msg.arg, a, 0)
         elseif msg.command == 0x10007 then   -- ico CHANGE_LAYER
-            print('##### CHANGE_LAYER')
-            print(tostring(msg.arg))
+            if verbose > 2 then
+                print('### ==> CHANGE_LAYER REQUEST')
+                print(tostring(msg.arg))
+            end
             --[[
             if msg.arg.layer ~= 4 or msg.arg.layer ~= 5 then
                 print("do not change layer for other than cursor or touch")
@@ -822,30 +1108,65 @@ if sc then
             wmgr:window_request(msg.arg, a, 0)
         elseif msg.command == 0x10011 then   -- ico MAP_THUMB
             local framerate = msg.arg.framerate
-            print('##### MAP_THUMB')
-            msg.arg.map = 1
             if not framerate or framerate < 0 then
                 framerate = 0
             end
+            msg.arg.map = 1
+            if verbose > 2 then
+                print('### ==> MAP_THUMB REQUEST')
+                print(msg.arg)
+                print('framerate: '..framerate)
+            end
             wmgr:window_request(msg.arg, a, framerate)
         elseif msg.command == 0x10012 then   -- ico UNMAP_THUMB
-            print('##### UNMAP_THUMB')
             msg.arg.map = 0
+            if verbose > 2 then
+                print('### ==> UNMAP_THUMB REQUEST')
+                print(msg.arg)
+            end
             wmgr:window_request(msg.arg, a, 0)
         elseif msg.command == 0x10020 then   -- ico SHOW_LAYER command
             msg.arg.visible = 1
-            print('##### SHOW_LAYER')
+            if verbose > 2 then
+                print('### ==> SHOW_LAYER REQUEST')
+                print(msg.arg)
+            end
+            wmgr:layer_request(msg.arg)
+        elseif msg.command == 0x10021 then   -- ico HIDE_LAYER command
+            msg.arg.visible = 0
+            if verbose > 2 then
+                print('### ==> HIDE_LAYER REQUEST')
+                print(msg.arg)
+            end
             wmgr:layer_request(msg.arg)
         end
     end
+
     sc.input_handler = function (self, cid, msg)
-        print('*** input handler: ' .. tostring(msg))
+        if verbose > 0 then
+            print('### ==> input handler: ' .. command_name(msg.comand))
+            if verbose > 1 then
+                print(msg)
+            end
+        end
     end
+
     sc.user_handler = function (self, cid, msg)
-        print('*** user handler: ' .. tostring(msg))
+        if verbose > 0 then
+            print('### ==> user handler: ' .. command_name(msg.command))
+            if verbose > 1 then
+                print(msg)
+            end
+        end
     end
+
     sc.resource_handler = function (self, cid, msg)
-        print('*** resource handler: ' .. tostring(msg))
+        if verbose > 0 then
+            print('### ==> resource handler: ' .. command_name(msg.command))
+            if verbose > 1 then
+                print(msg)
+            end
+        end
 
         createResourceSet = function (ctl, client, msg)
             cb = function(rset, data)
@@ -1003,7 +1324,13 @@ if sc then
             print("command REVERT")
         end
     end
+
     sc.inputdev_handler = function (self, cid, msg)
-        print('*** inputdev handler: ' .. tostring(msg))
+        if verbose > 0 then
+            print('*** inputdev handler: ' .. command_name(msg.command))
+            if verbose > 1 then
+                print(msg)
+            end
+        end
     end
 end
index 54954f7..b8c249b 100644 (file)
@@ -1524,6 +1524,11 @@ 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)/resource-manager/screen.c                     \
+       $(SYSTEMCTL_DIR)/resource-manager/notifier.c                   \
+       $(SYSTEMCTL_DIR)/resource-manager/scripting-notifier.c         \
+       $(SYSTEMCTL_DIR)/resource-client/resource-client.c             \
+       $(SYSTEMCTL_DIR)/resource-client/scripting-resource-client.c   \
        $(SYSTEMCTL_DIR)/application/application.c                     \
        $(SYSTEMCTL_DIR)/application/scripting-application.c           \
        $(SYSTEMCTL_DIR)/wayland/wayland.c                             \
index c0bc029..be4a367 100644 (file)
@@ -80,7 +80,7 @@ static void object_create_exttbl(userdata_t *u, lua_State *L);
 static void object_delete_exttbl(userdata_t *u, lua_State *L);
 static int  override_setfield(lua_State *L);
 static int  override_getfield(lua_State *L);
-static int override_tostring(lua_State *L);
+static int  override_tostring(lua_State *L);
 static int  object_setup_bridges(userdata_t *u, lua_State *L);
 
 static void invalid_destructor(void *data);
index 22ec565..c590314 100644 (file)
@@ -47,7 +47,7 @@ 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)
+#define IF_PRESENT(u,n) if ((u->mask & MRP_APPLICATION_ ## n ## _MASK))
 
     mrp_application_update_mask_t mask;
     mrp_application_t *app;
@@ -56,15 +56,25 @@ mrp_application_t *mrp_application_create(mrp_application_update_t *u,
     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");
+    MRP_ASSERT(u, "invalid argument");
 
     mask = u->mask;
 
+    if (!(mask & MRP_APPLICATION_APPID_MASK) || !u->appid) {
+        mrp_log_error("system-controller: failed to create application: "
+                      "no appid");
+        return NULL;
+    }
+
+    if (!(mask & MRP_APPLICATION_AREA_NAME_MASK) || !u->area_name) {
+        mrp_log_error("system-controller: failed to create application '%s': "
+                      "no area name", u->appid);
+        return NULL;
+    }
+
     if (!(app = mrp_allocz(sizeof(mrp_application_t)))) {
-        mrp_log_error("failed to create application '%s': out of memory",
-                      u->appid);
+        mrp_log_error("system-controller: failed to create application '%s': "
+                      "out of memory", u->appid);
         return NULL;
     }
 
@@ -90,10 +100,14 @@ mrp_application_t *mrp_application_create(mrp_application_update_t *u,
         app->area = area;
     }
 
-    if ((mask & MRP_APPLICATION_SCREEN_PRIVILEGE_MASK))
+    IF_PRESENT(u, SCREEN_PRIVILEGE)
         app->privileges.screen = u->privileges.screen;
-    if ((mask & MRP_APPLICATION_AUDIO_PRIVILEGE_MASK))
+    IF_PRESENT(u, AUDIO_PRIVILEGE)
         app->privileges.audio = u->privileges.audio;
+    IF_PRESENT(u, RESOURCE_CLASS)
+        app->resource_class = mrp_strdup(u->resource_class);
+    IF_PRESENT(u, SCREEN_PRIORITY)
+        app->screen_priority = u->screen_priority;
 
     if (!scripting_data)
         scripting_data = mrp_application_scripting_app_create_from_c(app);
@@ -183,6 +197,13 @@ size_t mrp_application_print(mrp_application_t *app,
               mrp_application_privilege_str(app->privileges.screen),
               mrp_application_privilege_str(app->privileges.audio));
     }
+    if ((mask & MRP_APPLICATION_RESOURCE_CLASS_MASK)) {
+        PRINT("resource_class: '%s'",app->resource_class ? app->resource_class:
+                                                           "<unknown>"       );
+    }
+    if ((mask & MRP_APPLICATION_SCREEN_PRIORITY_MASK)) {
+        PRINT("screen_priority: %d", app->screen_priority);
+    }
 
     return p - buf;
 
@@ -238,9 +259,11 @@ static mrp_wayland_area_t *area_find(const char *fullname)
     mrp_wayland_area_t *area;
     void *it;
 
-    mrp_wayland_foreach(wl, it) {
-        if ((area = mrp_wayland_area_find(wl, fullname)))
-            return area;
+    if (fullname) {
+        mrp_wayland_foreach(wl, it) {
+            if ((area = mrp_wayland_area_find(wl, fullname)))
+                return area;
+        }
     }
 
     return NULL;
index 0c73ce6..d43004f 100644 (file)
@@ -76,6 +76,8 @@ struct mrp_application_s {
 
     mrp_wayland_area_t *area;
     mrp_application_privileges_t privileges;
+    const char *resource_class;
+    int32_t screen_priority;
 
     void *scripting_data;
 };
@@ -86,16 +88,20 @@ enum mrp_application_update_mask_e {
     MRP_APPLICATION_AREA_MASK       = 0x04,
     MRP_APPLICATION_SCREEN_PRIVILEGE_MASK = 0x08,
     MRP_APPLICATION_AUDIO_PRIVILEGE_MASK  = 0x10,
-    MRP_APPLICATION_PRIVILEGES_MASK = 0x18,
+    MRP_APPLICATION_PRIVILEGES_MASK       = 0x18,
+    MRP_APPLICATION_RESOURCE_CLASS_MASK   = 0x20,
+    MRP_APPLICATION_SCREEN_PRIORITY_MASK  = 0x40,
 
-    MRP_APPLICATION_END_MASK        = 0x20
+    MRP_APPLICATION_END_MASK        = 0x80
 };
 
 struct mrp_application_update_s {
     mrp_application_update_mask_t mask;    
     const char *appid;
     const char *area_name;
+    const char *resource_class;
     mrp_application_privileges_t privileges;
+    int32_t screen_priority;
 };
 
 mrp_application_t *mrp_application_create(mrp_application_update_t *u,
index a06386c..d7fa70a 100644 (file)
@@ -71,6 +71,7 @@ static int  app_stringify(lua_State *);
 static void app_destroy_from_lua(void *);
 
 static scripting_app_t *app_check(lua_State *, int);
+static int  app_lookup(lua_State *L);
 
 static mrp_application_privileges_t *priv_check(lua_State *, int);
 static void priv_free(mrp_application_privileges_t *);
@@ -99,6 +100,9 @@ MRP_LUA_CLASS_DEF_SIMPLE (
 void mrp_application_scripting_init(lua_State *L)
 {
     mrp_lua_create_object_class(L, APPLICATION_CLASS);
+
+    lua_pushcfunction(L, app_lookup);
+    lua_setglobal(L, "application_lookup");
 }
 
 mrp_application_t *mrp_application_scripting_app_check(lua_State *L, int idx)
@@ -192,6 +196,8 @@ static int app_create_from_lua(lua_State *L)
     const char *fldnam;
     const char *appid = NULL;
     const char *arnam = "default";
+    const char *class = NULL;
+    int32_t spri = 0;
     mrp_application_privileges_t *privs = NULL;
     char *id;
     char buf[4096];
@@ -204,16 +210,21 @@ static int app_create_from_lua(lua_State *L)
     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;
+        case APPID:           appid = luaL_checkstring(L, -1);           break;
+        case AREA:            arnam = luaL_checkstring(L, -1);           break;
+        case PRIVILEGES:      privs = priv_check(L, -1);                 break;
+        case RESOURCE_CLASS:  class = luaL_checkstring(L, -1);           break;
+        case SCREEN_PRIORITY: spri  = luaL_checkinteger(L, -1);          break;
+        default:              luaL_error(L, "bad field '%s'", fldnam);   break;
         }
     }
 
     if (!appid)
         luaL_error(L, "'appid' field is missing"); 
-
+    if (!class)
+        luaL_error(L, "'resource_class' field is missing");
+    if (spri < 0 || spri > 255)
+        luaL_error(L, "'screen_priority' is out of range (0 - 255)");
 
     id = mrp_wayland_scripting_canonical_name(appid, buf, sizeof(buf));
     a = (scripting_app_t*)mrp_lua_create_object(L, APPLICATION_CLASS, id, 0);
@@ -221,9 +232,14 @@ static int app_create_from_lua(lua_State *L)
     if (!(a))
         luaL_error(L, "can't create scripting application '%s'", appid);
 
-    u.mask = MRP_APPLICATION_APPID_MASK | MRP_APPLICATION_AREA_NAME_MASK ;
+    u.mask = MRP_APPLICATION_APPID_MASK           |
+             MRP_APPLICATION_AREA_NAME_MASK       |
+             MRP_APPLICATION_RESOURCE_CLASS_MASK  |
+             MRP_APPLICATION_SCREEN_PRIORITY_MASK ;
     u.appid = appid;
     u.area_name = arnam;
+    u.resource_class = class;
+    u.screen_priority = spri;
 
     if (privs) {
         u.mask |= MRP_APPLICATION_PRIVILEGES_MASK;
@@ -265,10 +281,24 @@ static int app_getfield(lua_State *L)
         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;
+        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;
+        case RESOURCE_CLASS:
+            lua_pushstring(L, app->resource_class ? app->resource_class : "");
+            break;
+        case SCREEN_PRIORITY:
+            lua_pushinteger(L, app->screen_priority);
+            break;
+        default:
+            lua_pushnil(L);
+            break;
         }
     }
 
@@ -337,6 +367,28 @@ static scripting_app_t *app_check(lua_State *L, int idx)
     return (scripting_app_t *)mrp_lua_check_object(L, APPLICATION_CLASS, idx);
 }
 
+static int app_lookup(lua_State *L)
+{
+    mrp_application_t *app;
+    const char *appid;
+    void *sa;
+
+    MRP_LUA_ENTER;
+
+    if (!lua_isstring(L, 1))
+        lua_pushnil(L);
+    else {
+        appid = lua_tostring(L, 1);
+
+        if ((app = mrp_application_find(appid)) && (sa = app->scripting_data))
+            mrp_lua_push_object(L, sa);
+        else
+            lua_pushnil(L);
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
 
 static mrp_application_privileges_t *priv_check(lua_State *L, int idx)
 {
@@ -486,6 +538,16 @@ static field_t field_name_to_type(const char *name, ssize_t len)
             return PRIVILEGES;
         break;
 
+    case 14:
+        if (!strcmp(name, "resource_class"))
+            return RESOURCE_CLASS;
+        break;
+
+    case 15:
+        if (!strcmp(name, "screen_priority"))
+            return SCREEN_PRIORITY;
+        break;
+
     default:
         break;
     }
index e9734ec..fdefcd5 100644 (file)
 #ifndef __MURPHY_SYSTEM_CONTROLLER_DATA_TYPES_H__
 #define __MURPHY_SYSTEM_CONTROLLER_DATA_TYPES_H__
 
+#define MRP_SYSCTL_APPID_DEFAULT    "default"
+
+#define MRP_SYSCTL_SCREEN_RESOURCE  "screen"
+#define MRP_SYSCTL_AUDIO_RESOURCE   "audio_playback"
+#define MRP_SYSCTL_INPUT_RESOURCE   "input"
+
+
 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,
+    /*  5 */ ALIGN, APPID, AUDIO, EVENT, INDEX, INPUT, LAYER, MODEL, POS_X,
+             POS_Y, RAISE, RIGHT, TYPE, WIDTH,
     /*  6 */ ACTIVE, BOTTOM, HEIGHT, LAYERS, MAPPED, MIDDLE, OUTPUT, RESIZE,
              ROTATE, SCREEN,
     /*  7 */ CLASSES, DISPLAY, PIXEL_X, PIXEL_Y, SURFACE, VISIBLE,
@@ -45,9 +53,15 @@ enum mrp_sysctl_scripting_field_e {
     /*  9 */ LAYERTYPE, SHAREABLE,
     /* 10 */ ATTRIBUTES, HORIZONTAL, KEEPRATIO, PRIVILEGES,
     /* 11 */ AREA_CREATE, PIXEL_WIDTH,
-    /* 12 */ PIXEL_HEIGHT, LAYER_UPDATE,
+    /* 12 */ PIXEL_HEIGHT, LAYER_UPDATE, WINDOW_RAISE,
     /* 13 */ LAYER_REQUEST, OUTPUT_UPDATE, WINDOW_UPDATE,
-    /* 14 */ OUTPUT_REQUEST, WINDOW_MANAGER, WINDOW_REQUEST,
+    /* 14 */ MANAGER_UPDATE, OUTPUT_REQUEST, RESOURCE_CLASS, WINDOW_MANAGER,
+             WINDOW_REQUEST,
+    /* 15 */ MANAGER_REQUEST, SCREEN_PRIORITY,
+    /* 18 */ PASSTHROUGH_UPDATE,
+    /* 19 */ PASSTHROUGH_REQUEST, RESOURCE_SET_CREATE,
+    /* 20 */ RESOURCE_SET_ACQUIRE, RESOURCE_SET_DESTROY, RESOURCE_SET_RELEASE,
+             SCREEN_EVENT_HANDLER,
 };
 
 #endif /* __MURPHY_SYSTEM_CONTROLLER_DATA_TYPES_H__ */
index 856966d..d04301d 100644 (file)
@@ -43,6 +43,7 @@
 #include "system-controller.h"
 
 #include "resource-manager/scripting-resource-manager.h"
+#include "resource-client/scripting-resource-client.h"
 #include "application/scripting-application.h"
 #include "wayland/scripting-wayland.h"
 
@@ -662,6 +663,7 @@ static int register_lua_bindings(sysctl_t *sc)
         return FALSE;
 
     mrp_resmgr_scripting_init(sc->L);
+    mrp_resclnt_scripting_init(sc->L);
     mrp_application_scripting_init(sc->L);
     mrp_wayland_scripting_init(sc->L);
 
diff --git a/src/plugins/system-controller/resource-client/resource-client.c b/src/plugins/system-controller/resource-client/resource-client.c
new file mode 100644 (file)
index 0000000..dc6aeac
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * 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-client.h"
+#include "wayland/wayland.h"
+
+static int hash_compare(const void *, const void *);
+static uint32_t hash_function(const void *);
+
+static void event_cb(uint32_t, mrp_resource_set_t *, void *);
+
+static const char *type_str(mrp_resclnt_resource_set_type_t);
+
+mrp_resclnt_t *mrp_resclnt_create(void)
+{
+    mrp_resclnt_t *resclnt;
+    mrp_htbl_config_t cfg;
+
+    if (!(resclnt = mrp_allocz(sizeof(mrp_resclnt_t)))) {
+        mrp_log_error("system-controller: failed to allocate private data "
+                      "resource manager");
+        return NULL;
+    }
+
+    cfg.nentry = MRP_RESCLNT_RESOURCE_SET_MAX;
+    cfg.comp = hash_compare;
+    cfg.hash = hash_function;
+    cfg.free = NULL;
+    cfg.nbucket = MRP_RESCLNT_RESOURCE_SET_BUCKETS;
+
+    resclnt->client = mrp_resource_client_create("system-controller", resclnt);
+    resclnt->rsets.screen = mrp_htbl_create(&cfg);
+    resclnt->rsets.audio  = mrp_htbl_create(&cfg);
+    resclnt->rsets.input  = mrp_htbl_create(&cfg);
+
+    if (!resclnt->client) {
+        mrp_log_error("system-controller: failed to create resource client");
+        mrp_resclnt_destroy(resclnt);
+        return NULL;
+    }
+
+    return resclnt;
+}
+
+void mrp_resclnt_destroy(mrp_resclnt_t *resclnt)
+{
+    if (resclnt) {
+        mrp_resource_client_destroy(resclnt->client);
+
+        mrp_htbl_destroy(resclnt->rsets.screen, false);
+        mrp_htbl_destroy(resclnt->rsets.audio, false);
+        mrp_htbl_destroy(resclnt->rsets.input, false);
+
+        mrp_free(resclnt);
+    }
+}
+
+bool mrp_resclnt_add_resource_set(mrp_resclnt_t *resclnt,
+                                  mrp_resclnt_resource_set_type_t type,
+                                  const char *zone_name,
+                                  const char *appid,
+                                  void *key)
+{
+    mrp_application_t *app;
+    mrp_resource_set_t *rset;
+    const char *name;
+    bool shared;
+    mrp_htbl_t *htbl;
+    mrp_attr_t attr[16];
+    int sts;
+
+    MRP_ASSERT(resclnt && resclnt->client && zone_name && key,
+               "invalid argument");
+    MRP_ASSERT(resclnt->rsets.screen && resclnt->rsets.audio &&
+               resclnt->rsets.input, "uninitialised data structure");
+
+    if (!(app = mrp_application_find(appid)) &&
+        !(app = mrp_application_find(MRP_SYSCTL_APPID_DEFAULT)))
+    {
+        mrp_debug("failed to add %s resource set: can't find "
+                  "application '%s'", type_str(type), appid);
+        return false;
+    }
+
+    memset(attr, 0, sizeof(attr));
+
+    switch (type) {
+
+    case MRP_RESCLIENT_RESOURCE_SET_SCREEN:
+        name = MRP_SYSCTL_SCREEN_RESOURCE;
+        htbl = resclnt->rsets.screen;
+        shared = true;
+
+        attr[0].name = "classpri";
+        attr[0].type = mqi_integer;
+        attr[0].value.integer = app->screen_priority;
+
+        attr[1].name = "area";
+        attr[1].type = mqi_string;
+        attr[1].value.string = app->area_name;
+
+        attr[2].name = "appid";
+        attr[2].type = mqi_string;
+        attr[2].value.string = appid;
+
+        attr[3].name = "surface";
+        attr[3].type = mqi_integer;
+        attr[3].value.integer = (int32_t)(key - NULL);
+        break;
+
+    case MRP_RESCLIENT_RESOURCE_SET_AUDIO:
+        name = MRP_SYSCTL_AUDIO_RESOURCE;
+        htbl = resclnt->rsets.audio;
+        shared = false;
+        break;
+
+    case MRP_RESCLIENT_RESOURCE_SET_INPUT:
+        name = MRP_SYSCTL_INPUT_RESOURCE;
+        htbl = resclnt->rsets.input;
+        shared = true;
+        break;
+
+    default:
+        mrp_log_error("system-controller: failed to add resource: "
+                      "invalid resource type %d", type);
+        return false;
+    }
+
+    rset = mrp_resource_set_create(resclnt->client, false, false, 0,
+                                   event_cb, resclnt);
+    if (!rset) {
+        mrp_debug("system-controller: failed to add %s resource set: "
+                  "can't create resource set", type_str(type));
+        return false;
+    }
+
+    sts = mrp_resource_set_add_resource(rset, name, shared, attr, true);
+
+    if (sts < 0) {
+        mrp_log_error("system-controller: failed to add %s resource set: "
+                      "can't create resource '%s'", type_str(type), name);
+        mrp_resource_set_destroy(rset);
+        return false;
+    }
+
+    sts = mrp_application_class_add_resource_set(app->resource_class,
+                                                 zone_name, rset,
+                                                 ++(resclnt->reqno));
+    if (sts < 0) {
+        mrp_log_error("system-controller: failed to add %s resource set: "
+                      "can't add resource to application class",
+                      type_str(type));
+        mrp_resource_set_destroy(rset);
+        return false;
+    }
+
+    mrp_htbl_insert(htbl, key, rset);
+
+    return true;
+}
+
+void mrp_resclnt_remove_resource_set(mrp_resclnt_t *resclnt,
+                                     mrp_resclnt_resource_set_type_t type,
+                                     void *key)
+{
+    mrp_htbl_t *htbl;
+    mrp_resource_set_t *rset;
+
+    MRP_ASSERT(resclnt && key, "invalid argument");
+    MRP_ASSERT(resclnt->rsets.screen && resclnt->rsets.audio &&
+               resclnt->rsets.input, "uninitialised data structure");
+
+
+    switch (type) {
+
+    case MRP_RESCLIENT_RESOURCE_SET_SCREEN:
+        htbl = resclnt->rsets.screen;
+        break;
+
+    case MRP_RESCLIENT_RESOURCE_SET_AUDIO:
+        htbl = resclnt->rsets.audio;
+        break;
+
+    case MRP_RESCLIENT_RESOURCE_SET_INPUT:
+        htbl = resclnt->rsets.input;
+        break;
+
+    default:
+        mrp_log_error("system-controller: failed to remove resource: "
+                      "invalid resource type %d", type);
+        return;
+    }
+
+    if (!(rset = mrp_htbl_remove(htbl, key, false))) {
+        mrp_log_error("system-controller: failed to remove %s resource set: "
+                      "can't find it", type_str(type));
+        return;
+    }
+
+    mrp_resource_set_release(rset, ++(resclnt->reqno));
+    mrp_resource_set_destroy(rset);
+}
+
+bool mrp_resclnt_acquire_resource_set(mrp_resclnt_t *resclnt,
+                                      mrp_resclnt_resource_set_type_t type,
+                                      void *key)
+{
+    mrp_resource_set_t *rset;
+    mrp_htbl_t *htbl;
+
+    MRP_ASSERT(resclnt && resclnt->client, "invalid argument");
+    MRP_ASSERT(resclnt->rsets.screen && resclnt->rsets.audio &&
+               resclnt->rsets.input, "uninitialised data structure");
+
+    switch (type) {
+
+    case MRP_RESCLIENT_RESOURCE_SET_SCREEN:
+        htbl = resclnt->rsets.screen;
+        break;
+
+    case MRP_RESCLIENT_RESOURCE_SET_AUDIO:
+        htbl = resclnt->rsets.audio;
+        break;
+
+    case MRP_RESCLIENT_RESOURCE_SET_INPUT:
+        htbl = resclnt->rsets.input;
+        break;
+
+    default:
+        mrp_log_error("system-controller: failed to acquire resource: "
+                      "invalid resource type %d", type);
+        return false;
+    }
+
+    if (!(rset = mrp_htbl_lookup(htbl, key))) {
+        mrp_log_error("system-controller: failed to acquire resource set: "
+                      "can't find it (key=%p)", key);
+        return false;
+    }
+
+    mrp_resource_set_acquire(rset, ++(resclnt->reqno));
+
+    return true;
+}
+
+
+bool mrp_resclnt_release_resource_set(mrp_resclnt_t *resclnt,
+                                      mrp_resclnt_resource_set_type_t type,
+                                      void *key)
+{
+    mrp_resource_set_t *rset;
+    mrp_htbl_t *htbl;
+
+    MRP_ASSERT(resclnt && resclnt->client, "invalid argument");
+    MRP_ASSERT(resclnt->rsets.screen && resclnt->rsets.audio &&
+               resclnt->rsets.input, "uninitialised data structure");
+
+    switch (type) {
+
+    case MRP_RESCLIENT_RESOURCE_SET_SCREEN:
+        htbl = resclnt->rsets.screen;
+        break;
+
+    case MRP_RESCLIENT_RESOURCE_SET_AUDIO:
+        htbl = resclnt->rsets.audio;
+        break;
+
+    case MRP_RESCLIENT_RESOURCE_SET_INPUT:
+        htbl = resclnt->rsets.input;
+        break;
+
+    default:
+        mrp_log_error("system-controller: failed to acquire resource: "
+                      "invalid resource type %d", type);
+        return false;
+    }
+
+    if (!(rset = mrp_htbl_lookup(htbl, key))) {
+        mrp_log_error("system-controller: failed to release resource set: "
+                      "can't find it (key=%p)", key);
+        return false;
+    }
+
+    mrp_resource_set_release(rset, ++(resclnt->reqno));
+
+    return true;
+}
+
+
+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 >> 3) & (ptrdiff_t)0xffffffff);
+}
+
+
+static void event_cb(uint32_t reqid, mrp_resource_set_t *rset, void *u)
+{
+    mrp_resource_client_t *resclnt = (mrp_resource_client_t *)u;
+
+    MRP_UNUSED(reqid);
+    MRP_UNUSED(rset);
+    MRP_UNUSED(resclnt);
+}
+
+static const char *type_str(mrp_resclnt_resource_set_type_t type)
+{
+    switch (type) {
+    case MRP_RESCLIENT_RESOURCE_SET_SCREEN:    return "screen";
+    case MRP_RESCLIENT_RESOURCE_SET_AUDIO:     return "audio";
+    case MRP_RESCLIENT_RESOURCE_SET_INPUT:     return "input";
+    default:                                   return "<unknown>";
+    }
+}
diff --git a/src/plugins/system-controller/resource-client/resource-client.h b/src/plugins/system-controller/resource-client/resource-client.h
new file mode 100644 (file)
index 0000000..55e5a94
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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_CLIENT_H__
+#define __MURPHY_SYSTEM_CONTROLLER_RESOURCE_CLIENT_H__
+
+#include <sys/types.h>
+
+#include <murphy/common/hashtbl.h>
+
+#include <murphy/resource/data-types.h>
+
+#include "data-types.h"
+
+#define MRP_RESCLNT_RESOURCE_SET_MAX      256
+
+#define MRP_RESCLNT_RESOURCE_SET_BUCKETS  (MRP_RESCLNT_RESOURCE_SET_MAX / 8)
+
+typedef enum mrp_sysctl_scripting_field_e      mrp_resclnt_scripting_field_t;
+typedef enum mrp_resclnt_resource_set_type_e   mrp_resclnt_resource_set_type_t;
+
+typedef struct mrp_resclnt_s                   mrp_resclnt_t;
+
+
+enum mrp_resclnt_resource_set_type_e {
+    MRP_RESCLIENT_RESOURCE_SET_UNKNOWN = 0,
+    MRP_RESCLIENT_RESOURCE_SET_SCREEN,
+    MRP_RESCLIENT_RESOURCE_SET_AUDIO,
+    MRP_RESCLIENT_RESOURCE_SET_INPUT,
+
+    MRP_RESCLIENT_RESOURCE_SET_MAX
+};
+
+
+struct mrp_resclnt_s {
+    mrp_resource_client_t *client;
+    uint32_t reqno;
+
+    struct {
+        mrp_htbl_t *screen;
+        mrp_htbl_t *audio;
+        mrp_htbl_t *input;
+    } rsets;
+
+    void *scripting_data;
+};
+
+
+mrp_resclnt_t *mrp_resclnt_create(void);
+void mrp_resclnt_destroy(mrp_resclnt_t *resclnt);
+
+bool mrp_resclnt_add_resource_set(mrp_resclnt_t *resclnt,
+                                  mrp_resclnt_resource_set_type_t type,
+                                  const char *zone_name,
+                                  const char *appid,
+                                  void *key);
+void mrp_resclnt_remove_resource_set(mrp_resclnt_t *resclnt,
+                                     mrp_resclnt_resource_set_type_t type,
+                                     void *key);
+
+bool mrp_resclnt_acquire_resource_set(mrp_resclnt_t *resclnt,
+                                      mrp_resclnt_resource_set_type_t type,
+                                      void *key);
+bool mrp_resclnt_release_resource_set(mrp_resclnt_t *resclnt,
+                                      mrp_resclnt_resource_set_type_t type,
+                                      void *key);
+
+
+#endif /* __MURPHY_SYSTEM_CONTROLLER_RESOURCE_CLIENT_H__ */
diff --git a/src/plugins/system-controller/resource-client/scripting-resource-client.c b/src/plugins/system-controller/resource-client/scripting-resource-client.c
new file mode 100644 (file)
index 0000000..364d547
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ * 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-client.h"
+#include "wayland/scripting-wayland.h"
+
+#define RESOURCE_CLIENT_CLASS   MRP_LUA_CLASS_SIMPLE(resource_client)
+
+typedef struct scripting_resclnt_s  scripting_resclnt_t;
+typedef struct funcbridge_def_s     funcbridge_def_t;
+
+struct scripting_resclnt_s {
+    mrp_resclnt_t *resclnt;
+};
+
+struct funcbridge_def_s {
+    const char *name;
+    const char *sign;
+    mrp_funcbridge_cfunc_t func;
+    void *data;
+    mrp_funcbridge_t **ptr;
+};
+
+static int  resclnt_create(lua_State *);
+static int  resclnt_getfield(lua_State *);
+static int  resclnt_setfield(lua_State *);
+static void resclnt_destroy(void *);
+
+static scripting_resclnt_t *resclnt_check(lua_State *, int);
+
+static mrp_resclnt_resource_set_type_t str_to_type(const char *);
+
+static bool register_methods(lua_State *);
+
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    resource_client,               /* class name */
+    scripting_resclnt_t,           /* userdata type */
+    resclnt_destroy,               /* userdata destructor */
+    MRP_LUA_METHOD_LIST (          /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR    (resclnt_create)
+    ),
+    MRP_LUA_METHOD_LIST (          /* overrides */
+       MRP_LUA_OVERRIDE_CALL         (resclnt_create)
+       MRP_LUA_OVERRIDE_GETFIELD     (resclnt_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD     (resclnt_setfield)
+    )
+);
+
+
+static mrp_funcbridge_t *resource_set_create;
+static mrp_funcbridge_t *resource_set_destroy;
+static mrp_funcbridge_t *resource_set_acquire;
+static mrp_funcbridge_t *resource_set_release;
+
+
+void mrp_resclnt_scripting_init(lua_State *L)
+{
+    MRP_ASSERT(L, "invalid argument");
+
+    mrp_lua_create_object_class(L, RESOURCE_CLIENT_CLASS);
+    register_methods(L);
+}
+
+
+mrp_resclnt_t *mrp_resclnt_scripting_check(lua_State *L, int idx)
+{
+    scripting_resclnt_t *rc;
+    mrp_resclnt_t *resclnt;
+
+    if ((rc = resclnt_check(L, idx)) && (resclnt = rc->resclnt)) {
+        MRP_ASSERT(resclnt->scripting_data == (void *)rc,
+                   "confused with data structures");
+        return resclnt;
+    }
+
+    return NULL;
+}
+
+mrp_resclnt_t *mrp_resclnt_scripting_unwrap(void *void_rc)
+{
+    scripting_resclnt_t *rc = (scripting_resclnt_t *)void_rc;
+
+    if (rc && mrp_lua_get_object_classdef(rc) == RESOURCE_CLIENT_CLASS)
+        return rc->resclnt;
+
+    return NULL;
+}
+
+static int resclnt_create(lua_State *L)
+{
+    mrp_resclnt_t *resclnt;
+    size_t fldnamlen;
+    const char *fldnam;
+    scripting_resclnt_t *rc;
+    int table;
+
+    MRP_LUA_ENTER;
+
+    luaL_checktype(L, 2, LUA_TTABLE);
+
+    rc = (scripting_resclnt_t *)mrp_lua_create_object(L, RESOURCE_CLIENT_CLASS,
+                                                     NULL, 1);
+
+    if (!rc)
+        luaL_error(L, "failed to create resource client");
+
+    table = lua_gettop(L);
+
+    MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
+        switch (mrp_resclnt_scripting_field_name_to_type(fldnam, fldnamlen)) {
+
+        default:
+            lua_pushvalue(L, -2);
+            lua_pushvalue(L, -2);
+            lua_rawset(L, table);
+            break;
+        }
+    }
+
+    if (!(resclnt = mrp_resclnt_create()))
+        luaL_error(L, "can't create resclnt object");
+
+    rc->resclnt = resclnt;
+
+    resclnt->scripting_data = rc;
+
+    lua_settop(L, table);
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int resclnt_getfield(lua_State *L)
+{
+    scripting_resclnt_t *rc;
+    const char *fldnam;
+    mrp_resclnt_scripting_field_t fld;
+
+    MRP_LUA_ENTER;
+
+    fld = mrp_resclnt_scripting_field_check(L, 2, &fldnam);
+    lua_pop(L, 1);
+
+    rc = resclnt_check(L, 1);
+
+    if (!rc)
+        lua_pushnil(L);
+    else {
+        switch (fld) {
+
+        case RESOURCE_SET_CREATE:
+            mrp_funcbridge_push(L, resource_set_create);
+            break;
+
+        case RESOURCE_SET_DESTROY:
+            mrp_funcbridge_push(L, resource_set_destroy);
+            break;
+
+        case RESOURCE_SET_ACQUIRE:
+            mrp_funcbridge_push(L, resource_set_acquire);
+            break;
+
+        case RESOURCE_SET_RELEASE:
+            mrp_funcbridge_push(L, resource_set_release);
+            break;
+
+        default:
+            lua_pushstring(L, fldnam);
+            lua_rawget(L, 1);
+            break;
+        }
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int  resclnt_setfield(lua_State *L)
+{
+    MRP_LUA_ENTER;
+
+    resclnt_check(L, 1);
+    luaL_error(L, "resource client is read-only");
+
+    MRP_LUA_LEAVE(0);
+}
+
+static void resclnt_destroy(void *data)
+{
+    scripting_resclnt_t *rc = (scripting_resclnt_t *)data;
+
+    MRP_UNUSED(data);
+    MRP_UNUSED(rc);
+
+    MRP_LUA_ENTER;
+
+    MRP_LUA_LEAVE_NOARG;
+}
+
+static scripting_resclnt_t *resclnt_check(lua_State *L, int idx)
+{
+
+    return (scripting_resclnt_t*)mrp_lua_check_object(L, RESOURCE_CLIENT_CLASS,
+                                                      idx);
+}
+
+static mrp_resclnt_resource_set_type_t str_to_type(const char *str)
+{
+    if (str) {
+        if (!strcmp(str, "screen"))
+            return MRP_RESCLIENT_RESOURCE_SET_SCREEN;
+        else if (!strcmp(str, "audio"))
+            return MRP_RESCLIENT_RESOURCE_SET_AUDIO;
+        else if (!strcmp(str, "input"))
+            return MRP_RESCLIENT_RESOURCE_SET_INPUT;
+    }
+
+    return MRP_RESCLIENT_RESOURCE_SET_UNKNOWN; /* == 0 */
+}
+
+static bool resource_set_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_resclnt_t *resclnt;
+    mrp_resclnt_resource_set_type_t type;
+    const char *zone;
+    const char *appid;
+    int32_t objid;
+
+    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, "osssd")) {
+        mrp_log_error("bad signature: expected 'osssd' got '%s'", signature);
+        return false;
+    }
+
+    if (!(resclnt = mrp_resclnt_scripting_unwrap(args[0].pointer))) {
+        mrp_log_error("argument 1 is not a 'resource_client' class object");
+        return false;
+    }
+
+    if (!(type = str_to_type(args[1].string))) {
+        mrp_log_error("argument 2 is not a valid resource type string");
+        return false;
+    }
+
+    zone  = args[2].string;
+    appid = args[3].string;
+    objid = args[4].integer;
+
+    mrp_resclnt_add_resource_set(resclnt, type, zone, appid, NULL + objid);
+
+    return true;
+}
+
+
+static bool resource_set_destroy_bridge(lua_State *L,
+                                        void *data,
+                                        const char *signature,
+                                        mrp_funcbridge_value_t *args,
+                                        char *ret_type,
+                                        mrp_funcbridge_value_t *ret_val)
+{
+    mrp_resclnt_t *resclnt;
+    mrp_resclnt_resource_set_type_t type;
+    int32_t objid;
+
+    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, "osd")) {
+        mrp_log_error("bad signature: expected 'osd' got '%s'", signature);
+        return false;
+    }
+
+    if (!(resclnt = mrp_resclnt_scripting_unwrap(args[0].pointer))) {
+        mrp_log_error("argument 1 is not a 'resource_client' class object");
+        return false;
+    }
+
+    if (!(type = str_to_type(args[1].string))) {
+        mrp_log_error("argument 2 is not a valid resource type string");
+        return false;
+    }
+
+    objid = args[2].integer;
+
+    mrp_resclnt_remove_resource_set(resclnt, type, NULL + objid);
+
+    return true;
+}
+
+
+static bool resource_set_acquire_bridge(lua_State *L,
+                                        void *data,
+                                        const char *signature,
+                                        mrp_funcbridge_value_t *args,
+                                        char *ret_type,
+                                        mrp_funcbridge_value_t *ret_val)
+{
+    mrp_resclnt_t *resclnt;
+    mrp_resclnt_resource_set_type_t type;
+    int32_t objid;
+
+    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, "osd")) {
+        mrp_log_error("bad signature: expected 'osd' got '%s'", signature);
+        return false;
+    }
+
+    if (!(resclnt = mrp_resclnt_scripting_unwrap(args[0].pointer))) {
+        mrp_log_error("argument 1 is not a 'resource_client' class object");
+        return false;
+    }
+
+    if (!(type = str_to_type(args[1].string))) {
+        mrp_log_error("argument 2 is not a valid resource type string");
+        return false;
+    }
+
+    objid = args[2].integer;
+
+    mrp_resclnt_acquire_resource_set(resclnt, type, NULL + objid);
+
+    return true;
+}
+
+
+static bool resource_set_release_bridge(lua_State *L,
+                                        void *data,
+                                        const char *signature,
+                                        mrp_funcbridge_value_t *args,
+                                        char *ret_type,
+                                        mrp_funcbridge_value_t *ret_val)
+{
+    mrp_resclnt_t *resclnt;
+    mrp_resclnt_resource_set_type_t type;
+    int32_t objid;
+
+    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, "osd")) {
+        mrp_log_error("bad signature: expected 'osd' got '%s'", signature);
+        return false;
+    }
+
+    if (!(resclnt = mrp_resclnt_scripting_unwrap(args[0].pointer))) {
+        mrp_log_error("argument 1 is not a 'resource_client' class object");
+        return false;
+    }
+
+    if (!(type = str_to_type(args[1].string))) {
+        mrp_log_error("argument 2 is not a valid resource type string");
+        return false;
+    }
+
+    objid = args[2].integer;
+
+    mrp_resclnt_release_resource_set(resclnt, type, NULL + objid);
+
+    return true;
+}
+
+
+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(resource_set_create   , "osssd", NULL),
+        FUNCBRIDGE(resource_set_destroy  , "osd"  , NULL),
+        FUNCBRIDGE(resource_set_acquire  , "osd"  , NULL),
+        FUNCBRIDGE(resource_set_release  , "osd"  , 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
+}
+
+
+mrp_resclnt_scripting_field_t
+mrp_resclnt_scripting_field_check(lua_State *L,int idx,const char **ret_fldnam)
+{
+    const char *fldnam;
+    size_t fldnamlen;
+    mrp_resclnt_scripting_field_t fldtyp;
+
+    if (!(fldnam = lua_tolstring(L, idx, &fldnamlen)))
+        fldtyp = 0;
+    else
+        fldtyp = mrp_resclnt_scripting_field_name_to_type(fldnam, fldnamlen);
+
+    if (ret_fldnam)
+        *ret_fldnam = fldnam;
+
+    return fldtyp;
+}
+
+mrp_resclnt_scripting_field_t
+mrp_resclnt_scripting_field_name_to_type(const char *name, ssize_t len)
+{
+    if (len < 0)
+        len = strlen(name);
+
+    switch (len) {
+
+    case 19:
+        if (!strcmp(name, "resource_set_create"))
+            return RESOURCE_SET_CREATE;
+        break;
+
+    case 20:
+        switch (name[13]) {
+        case 'a':
+            if (!strcmp(name, "resource_set_acquire"))
+                return RESOURCE_SET_ACQUIRE;
+            break;
+        case 'd':
+            if (!strcmp(name, "resource_set_destroy"))
+                return RESOURCE_SET_DESTROY;
+            break;
+        case 'r':
+            if (!strcmp(name, "resource_set_release"))
+                return RESOURCE_SET_RELEASE;
+            break;
+        default:
+            break;
+        }
+        break;
+
+    default:
+        break;
+    }
+
+    return 0;
+}
diff --git a/src/plugins/system-controller/resource-client/scripting-resource-client.h b/src/plugins/system-controller/resource-client/scripting-resource-client.h
new file mode 100644 (file)
index 0000000..8679062
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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_CLIENT_SCRIPTING_H__
+#define __MURPHY_SYSTEM_CONTROLLER_RESOURCE_CLIENT_SCRIPTING_H__
+
+#include <lua.h>
+
+#include "resource-client/resource-client.h"
+
+void mrp_resclnt_scripting_init(lua_State *L);
+
+mrp_resclnt_t *mrp_resclnt_scripting_check(lua_State *L, int idx);
+mrp_resclnt_t *mrp_resclnt_scripting_unwrap(void *void_rm);
+
+
+/* internal for scripting-xxx.c */
+mrp_resclnt_scripting_field_t
+mrp_resclnt_scripting_field_check(lua_State *, int, const char **);
+
+mrp_resclnt_scripting_field_t
+mrp_resclnt_scripting_field_name_to_type(const char *, ssize_t);
+
+
+#endif /* __MURPHY_SYSTEM_CONTROLLER_RESOURCE_CLIENT_SCRIPTING_H__ */
diff --git a/src/plugins/system-controller/resource-manager/notifier.c b/src/plugins/system-controller/resource-manager/notifier.c
new file mode 100644 (file)
index 0000000..c532a0b
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+
+#include "notifier.h"
+
+static void event_destroy(mrp_resmgr_event_t *);
+
+static const char *type_str(mrp_resmgr_event_type_t);
+static const char *eventid_str(mrp_resmgr_eventid_t);
+
+
+mrp_resmgr_notifier_t *mrp_resmgr_notifier_create(mrp_resmgr_t *resmgr)
+{
+    mrp_resmgr_notifier_t *notifier;
+    mrp_resmgr_notifier_zone_t *nz;
+    int i;
+
+    MRP_ASSERT(resmgr, "invalid argument");
+
+    if ((notifier = mrp_allocz(sizeof(mrp_resmgr_notifier_t)))) {
+        notifier->resmgr = resmgr;
+
+        for (i = 0;  i < MRP_ZONE_MAX;  i++) {
+            nz = notifier->zones + i;
+            mrp_list_init(&nz->events);
+        }
+    }
+
+    return notifier;
+}
+
+void mrp_resmgr_notifier_destroy(mrp_resmgr_notifier_t *notifier)
+{
+    mrp_list_hook_t *events, *entry, *n;
+    mrp_resmgr_notifier_zone_t *nz;
+    mrp_resmgr_event_t *ev;
+    int i;
+
+    if (notifier) {
+
+        for (i = 0;  i < MRP_ZONE_MAX;  i++) {
+            nz = notifier->zones + i;
+            events = &nz->events;
+
+            mrp_list_foreach(events, entry, n) {
+                ev = mrp_list_entry(entry, mrp_resmgr_event_t, link);
+                event_destroy(ev);
+            }
+        }
+
+        mrp_free((void *)notifier);
+    }
+}
+
+void mrp_resmgr_notifier_register_event_callback(mrp_resmgr_t *resmgr,
+                                mrp_resmgr_notifier_event_callback_t callback)
+{
+    mrp_resmgr_notifier_t *notifier;
+
+    MRP_ASSERT(resmgr && resmgr->notifier, "invalid argument");
+
+    notifier = resmgr->notifier;
+    notifier->callback = callback;
+}
+
+void mrp_resmgr_notifier_queue_screen_event(mrp_resmgr_t *resmgr,
+                                            uint32_t zoneid,
+                                            mrp_resmgr_eventid_t eventid,
+                                            const char *appid,
+                                            int32_t surfaceid,
+                                            int32_t layerid,
+                                            const char *area)
+{
+    mrp_resmgr_notifier_t *notifier;
+    mrp_resmgr_notifier_zone_t *nz;
+    mrp_resmgr_event_t *ev;
+
+    MRP_ASSERT(resmgr && resmgr->notifier && zoneid < MRP_ZONE_MAX && appid,
+               "invalid argument");
+
+    notifier = resmgr->notifier;
+    nz = notifier->zones + zoneid;
+
+    if ((ev = mrp_allocz(sizeof(mrp_resmgr_event_t)))) {
+
+        ev->type = MRP_RESMGR_EVENT_SCREEN;
+        ev->eventid = eventid;
+        ev->appid = mrp_strdup(appid);
+        ev->surfaceid = surfaceid;
+        ev->layerid = layerid;
+        ev->area = mrp_strdup(area ? area : "<unknown>");
+
+        mrp_list_append(&nz->events, &ev->link);
+
+        mrp_debug("queued screen event in zone %u (eventid=%s appid='%s' "
+                  "surfaceid=%d layerid=%d, area='%s'",
+                  zoneid, eventid_str(ev->eventid), ev->appid,
+                  ev->surfaceid, ev->layerid, ev->area);
+
+        nz->nevent.screen++;
+    }
+}
+
+void mrp_notifier_remove_last_event(mrp_resmgr_t *resmgr,
+                                    uint32_t zoneid,
+                                    mrp_resmgr_event_type_t type)
+{
+    mrp_resmgr_notifier_t *notifier;
+    mrp_resmgr_notifier_zone_t *nz;
+    mrp_list_hook_t *events, *entry, *n;
+    mrp_resmgr_event_t *ev;
+    size_t *nevent_ptr;
+    int it;
+
+    MRP_ASSERT(resmgr && resmgr->notifier && zoneid < MRP_ZONE_MAX,
+               "invalid argument");
+
+    notifier = resmgr->notifier;
+    nz = notifier->zones + zoneid;
+
+    switch (type) {
+
+    case MRP_RESMGR_EVENT_SCREEN:   nevent_ptr = &nz->nevent.screen;   break;
+    case MRP_RESMGR_EVENT_AUDIO:    nevent_ptr = &nz->nevent.audio;    break;
+    case MRP_RESMGR_EVENT_INPUT:    nevent_ptr = &nz->nevent.input;    break;
+
+    default:
+        mrp_log_error("system-controller: failed to remove last resource "
+                      "manager event: invalid event type %d", type);
+        return;
+    }
+
+    it = 0;
+    events = &nz->events;
+
+    mrp_list_foreach(events, entry, n) {
+        ev = mrp_list_entry(entry, mrp_resmgr_event_t, link);
+
+        if (++it > MRP_RESMGR_EVENT_MAX)
+            break;
+        
+        if (type == ev->type) {
+            mrp_debug("removing %s event in zone %u (eventid=%s "
+                      "appid='%s' surfaceid=%d layerid=%d, area='%s'",
+                      type_str(ev->type), zoneid, eventid_str(ev->eventid),
+                      ev->appid, ev->surfaceid, ev->layerid, ev->area);
+
+            event_destroy(ev);
+
+            (*nevent_ptr)--;
+
+            return;
+        }
+    }
+
+    mrp_log_error("system-controller: failed to remove last %s event: "
+                  "non-existent event", type_str(type));
+}
+
+void mrp_resmgr_notifier_flush_events(mrp_resmgr_t *resmgr,
+                                      uint32_t zoneid,
+                                      mrp_resmgr_event_type_t type)
+{
+    mrp_resmgr_notifier_t *notifier;
+    mrp_resmgr_notifier_zone_t *nz;
+    mrp_list_hook_t *events, *entry, *n;
+    mrp_resmgr_event_t *ev;
+    size_t nevent, *nevent_ptr;
+
+    MRP_ASSERT(resmgr && resmgr->notifier && zoneid < MRP_ZONE_MAX,
+               "invalid argument");
+
+    notifier = resmgr->notifier;
+    nz = notifier->zones + zoneid;
+
+    switch (type) {
+
+    case MRP_RESMGR_EVENT_ALL:
+        nevent = nz->nevent.screen + nz->nevent.audio  + nz->nevent.input;
+        nevent_ptr = NULL;
+        break;
+
+    case MRP_RESMGR_EVENT_SCREEN:
+        nevent = nz->nevent.screen;
+        nevent_ptr = &nz->nevent.screen;
+        break;
+
+    case MRP_RESMGR_EVENT_AUDIO:
+        nevent = nz->nevent.audio;
+        nevent_ptr = &nz->nevent.audio;
+        break;
+
+    case MRP_RESMGR_EVENT_INPUT:
+        nevent = nz->nevent.input;
+        nevent_ptr = &nz->nevent.input;
+        break;
+
+    default:
+        mrp_log_error("system-controller: failed to flush resource manager "
+                      "events: invalid event type %d", type);
+        return;
+    }
+
+    if (!nevent) {
+        mrp_debug("%s event queue in zone %u is empty: nothing to flush",
+                  type_str(type), zoneid);
+        return;
+    }
+
+    mrp_debug("%s %d events in zone %u",
+              notifier->callback ? "forwarding" : "throwing away",
+              nevent, zoneid);
+
+    events = &nz->events;
+
+    mrp_list_foreach(events, entry, n) {
+        ev = mrp_list_entry(entry, mrp_resmgr_event_t, link);
+
+        if (type == MRP_RESMGR_EVENT_ALL || type == ev->type) {
+            if (notifier->callback)
+                notifier->callback(resmgr, ev);
+
+            event_destroy(ev);
+
+            if (nevent_ptr)
+                (*nevent_ptr)--;
+        }
+    }
+
+    if (!nevent_ptr) {
+        MRP_ASSERT(mrp_list_empty(&nz->events),
+                   "confused with data structures");
+        memset(&nz->nevent, 0, sizeof(nz->nevent));
+    }
+}
+
+static void event_destroy(mrp_resmgr_event_t *ev)
+{
+    if (ev) {
+        mrp_list_delete(&ev->link);
+
+        mrp_free((void *)ev->appid);
+
+        switch (ev->type) {
+
+        case MRP_RESMGR_EVENT_SCREEN:
+            mrp_free((void *)ev->area);
+            break;
+
+        case MRP_RESMGR_EVENT_AUDIO:
+            break;
+
+        case MRP_RESMGR_EVENT_INPUT:
+            break;
+
+        default:
+            mrp_log_error("system-controller: confused with data structures: "
+                          "invalid resource manager event type %d", ev->type);
+            break;
+        }
+
+        mrp_free(ev);
+    }
+}
+
+
+static const char *type_str(mrp_resmgr_event_type_t type)
+{
+    switch (type) {
+    case MRP_RESMGR_EVENT_ALL:     return "all";
+    case MRP_RESMGR_EVENT_SCREEN:  return "screen";
+    case MRP_RESMGR_EVENT_AUDIO:   return "audio";
+    case MRP_RESMGR_EVENT_INPUT:   return "input";
+    default:                       return "<unknown>";
+    }
+}
+
+static const char *eventid_str(mrp_resmgr_eventid_t eventid)
+{
+    switch (eventid) {
+    case MRP_RESMGR_EVENTID_GRANT:    return "grant";
+    case MRP_RESMGR_EVENTID_REVOKE:   return "revoke";
+    default:                          return "<unknown>";
+    }
+}
diff --git a/src/plugins/system-controller/resource-manager/notifier.h b/src/plugins/system-controller/resource-manager/notifier.h
new file mode 100644 (file)
index 0000000..4a695c0
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * 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_NOTIFICATION_H__
+#define __MURPHY_SYSTEM_CONTROLLER_NOTIFICATION_H__
+
+#include <sys/types.h>
+
+#include <murphy/resource/data-types.h>
+
+#include "resource-manager.h"
+
+enum mrp_resmgr_event_type_e {
+    MRP_RESMGR_EVENT_UNKNOWN = 0,
+    MRP_RESMGR_EVENT_ALL     = 0,
+    MRP_RESMGR_EVENT_SCREEN,
+    MRP_RESMGR_EVENT_AUDIO,
+    MRP_RESMGR_EVENT_INPUT,
+
+    MRP_RESMGR_EVENT_MAX
+};
+
+enum mrp_resmgr_eventid_e {
+    MRP_RESMGR_EVENTID_UNKNOWN = 0,
+    MRP_RESMGR_EVENTID_GRANT,
+    MRP_RESMGR_EVENTID_REVOKE,
+};
+
+struct mrp_resmgr_notifier_zone_s {
+    mrp_list_hook_t events;
+    struct {
+        size_t screen;
+        size_t audio;
+        size_t input;
+    } nevent;
+};
+
+struct mrp_resmgr_notifier_s {
+    mrp_resmgr_t *resmgr;
+    mrp_resmgr_notifier_zone_t zones[MRP_ZONE_MAX];
+    mrp_resmgr_notifier_event_callback_t callback;
+};
+
+struct mrp_resmgr_event_s {
+    mrp_list_hook_t link;
+    mrp_resmgr_event_type_t type;
+    mrp_resmgr_eventid_t eventid;
+    char *appid;
+
+    /* screen specific fields */
+    struct {
+        int32_t surfaceid;
+        int32_t layerid;
+        char *area;
+    };
+};
+
+
+
+mrp_resmgr_notifier_t *mrp_resmgr_notifier_create(mrp_resmgr_t *resmgr);
+void mrp_resmgr_notifier_destroy(mrp_resmgr_notifier_t *notif);
+
+void mrp_resmgr_notifier_register_event_callback(mrp_resmgr_t *resmgr,
+                                mrp_resmgr_notifier_event_callback_t callback);
+
+void mrp_resmgr_notifier_queue_screen_event(mrp_resmgr_t *resmgr,
+                                            uint32_t zoneid,
+                                            mrp_resmgr_eventid_t eventid,
+                                            const char *appid,
+                                            int32_t surfaceid,
+                                            int32_t layerid,
+                                            const char *area);
+
+void mrp_notifier_remove_last_event(mrp_resmgr_t *resmgr,
+                                    uint32_t zoneid,
+                                    mrp_resmgr_event_type_t type);
+
+#define mrp_notifier_remove_last_screen_event(_resmgr, _zoneid)         \
+    mrp_notifier_remove_last_event(_resmgr, _zoneid, MRP_RESMGR_EVENT_SCREEN)
+
+#define mrp_notifier_remove_last_audio_event(_resmgr, _zoneid)          \
+    mrp_notifier_remove_last_event(_resmgr, _zoneid, MRP_RESMGR_EVENT_AUDIO)
+
+#define mrp_notifier_remove_last_input_event(_resmgr, _zoneid)          \
+    mrp_notifier_remove_last_event(_resmgr, _zoneid, MRP_RESMGR_EVENT_INPUT)
+
+void mrp_resmgr_notifier_flush_events(mrp_resmgr_t *resmgr,
+                                      uint32_t zoneid,
+                                      mrp_resmgr_event_type_t evtype);
+
+#define mrp_resmgr_notifier_flush_screen_events(_resmgr, _zoneid)       \
+    mrp_resmgr_notifier_flush_events(_resmgr, _zoneid, MRP_RESMGR_EVENT_SCREEN)
+
+#define mrp_resmgr_notifier_flush_audio_events(_resmgr, _zoneid)        \
+    mrp_resmgr_notifier_flush_events(_resmgr, _zoneid, MRP_RESMGR_EVENT_AUDIO)
+
+#define mrp_resmgr_notifier_flush_input_events(_resmgr, _zoneid)        \
+    mrp_resmgr_notifier_flush_events(_resmgr, _zoneid, MRP_RESMGR_EVENT_INPUT)
+
+#define mrp_resmgr_notifier_flush_all_events(_resmgr) \
+    mrp_resmgr_notifier_flush_events(_resmgr, MRP_RESMGR_EVENT_ALL)
+
+#endif /* __MURPHY_SYSTEM_CONTROLLER_NOTIFICATION_H__ */
index 155dc35..f190535 100644 (file)
@@ -45,6 +45,8 @@
 #include <murphy/resource/protocol.h>
 
 #include "resource-manager.h"
+#include "screen.h"
+#include "notifier.h"
 
 static int hash_compare(const void *, const void *);
 static uint32_t hash_function(const void *);
@@ -67,6 +69,8 @@ mrp_resmgr_t *mrp_resmgr_create(void)
     cfg.nbucket = MRP_RESMGR_RESOURCE_BUCKETS;
 
     resmgr->resources = mrp_htbl_create(&cfg);
+    resmgr->screen = mrp_resmgr_screen_create(resmgr);
+    resmgr->notifier = mrp_resmgr_notifier_create(resmgr);
 
     return resmgr;
 }
index 2fb1fbe..4eadc83 100644 (file)
 
 #include "data-types.h"
 
+#define MRP_RESMGR_RESOURCE_MAX            256
+#define MRP_RESMGR_ACTIVE_SCREEN_MAX       128
+
+#define MRP_RESMGR_RESOURCE_BUCKETS        (MRP_RESMGR_RESOURCE_MAX / 4)
+
 typedef enum mrp_sysctl_scripting_field_e  mrp_resmgr_scripting_field_t;
+typedef enum mrp_resmgr_event_type_e       mrp_resmgr_event_type_t;
+typedef enum mrp_resmgr_eventid_e          mrp_resmgr_eventid_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;
+typedef struct mrp_resmgr_class_s          mrp_resmgr_class_t;
+typedef struct mrp_resmgr_window_s         mrp_resmgr_window_t;
+typedef struct mrp_resmgr_screen_area_s    mrp_resmgr_screen_area_t;
+typedef struct mrp_resmgr_notifier_s       mrp_resmgr_notifier_t;
+typedef struct mrp_resmgr_notifier_zone_s  mrp_resmgr_notifier_zone_t;
+typedef struct mrp_resmgr_event_s          mrp_resmgr_event_t;
 
-#define MRP_RESMGR_RESOURCE_MAX            256
-#define MRP_RESMGR_RESOURCE_BUCKETS        (MRP_RESMGR_RESOURCE_MAX / 4)
+typedef void (*mrp_resmgr_notifier_event_callback_t)(mrp_resmgr_t *,
+                                                     mrp_resmgr_event_t *);
 
 struct mrp_resmgr_s {
     mrp_htbl_t *resources;
@@ -56,6 +69,8 @@ struct mrp_resmgr_s {
     mrp_resmgr_audio_t *audio;
     mrp_resmgr_input_t *input;
 
+    mrp_resmgr_notifier_t *notifier;
+
     void *scripting_data;
 };
 
diff --git a/src/plugins/system-controller/resource-manager/screen.c b/src/plugins/system-controller/resource-manager/screen.c
new file mode 100644 (file)
index 0000000..c321a7d
--- /dev/null
@@ -0,0 +1,1147 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <murphy/common.h>
+
+#include <murphy-db/mqi.h>
+
+#include <murphy/resource/config-api.h>
+#include <murphy/resource/manager-api.h>
+#include <murphy/resource/client-api.h>
+
+#include "screen.h"
+#include "notifier.h"
+#include "wayland/area.h"
+#include "wayland/output.h"
+#include "application/application.h"
+
+
+#ifdef BIT
+#undef BIT
+#endif
+#ifdef MASK
+#undef MASK
+#endif
+#ifdef MAX
+#undef MAX
+#endif
+
+#define BIT(i)                ((uint32_t)1 << (i))
+#define MASK(w)               (((uint32_t)1 << (w)) - 1)
+#define MAX(w)                (((uint32_t)1 << (w)))
+
+#define PRIORITY_BITS         8
+#define CLASSPRI_BITS         8
+#define ZORDER_BITS           16
+
+#define PRIORITY_POSITION     0
+#define CLASSPRI_POSITION     (PRIORITY_POSITION + PRIORITY_BITS)
+#define ZORDER_POSITION       (CLASSPRI_POSITION + CLASSPRI_BITS)
+
+#define PRIORITY_MASK         MASK(PRIORITY_BITS)
+#define CLASSPRI_MASK         MASK(CLASSPRI_BITS)
+#define ZORDER_MASK           MASK(ZORDER_BITS)
+
+#define PRIORITY_MAX          MAX(PRIORITY_BITS)
+#define CLASSPRI_MAX          MAX(CLASSPRI_BITS)
+#define ZORDER_MAX            MAX(ZORDER_BITS)
+
+
+#define ATTRIBUTE(n,t,v)    {n, MRP_RESOURCE_RW, mqi_##t, {.t=v}}
+#define ATTR_END            {NULL, 0, 0, {.string=NULL}}
+
+typedef struct screen_resource_s   screen_resource_t;
+
+
+struct screen_resource_s {
+    mrp_list_hook_t link;
+    mrp_resmgr_screen_t *screen;
+    mrp_resource_t *res;
+    uint32_t zoneid;
+    size_t areaid;
+    uint32_t key;
+    bool acquire;
+    bool grant;
+    uint32_t grantid;
+};
+
+static int hash_compare(const void *, const void *);
+static uint32_t hash_function(const void *);
+
+static void overlap_add(mrp_resmgr_screen_area_t *, size_t);
+static void overlap_remove(mrp_resmgr_screen_area_t *, size_t);
+
+static const char *get_appid_for_resource(mrp_resource_t *);
+static int32_t get_surfaceid_for_resource(mrp_resource_t *);
+static int32_t get_layerid_for_resource(mrp_resource_t *);
+static const char *get_areaname_for_resource(mrp_resource_t *);
+static mrp_application_t *get_application_for_resource(mrp_resource_t *);
+static int32_t get_area_for_resource(mrp_resource_t *);
+static uint32_t get_priority_for_resource(mrp_resource_t *);
+static uint32_t get_class_priority_for_resource(mrp_resource_t *,
+                                                mrp_application_class_t *);
+static int32_t get_zone_id(const char *);
+
+
+static screen_resource_t *screen_resource_create(mrp_resmgr_screen_t *,
+                                                 mrp_zone_t *,mrp_resource_t *,
+                                                 mrp_application_class_t *);
+static void screen_resource_destroy(mrp_resmgr_screen_t *,  mrp_zone_t *,
+                                    mrp_resource_t *);
+static screen_resource_t *screen_resource_lookup(mrp_resmgr_screen_t *,
+                                                 mrp_resource_t *);
+static bool screen_resource_is_on_top(mrp_resmgr_screen_t *,
+                                      screen_resource_t *);
+static void screen_resource_raise_to_top(mrp_resmgr_screen_t *,
+                                         screen_resource_t *);
+static void screen_resource_lower_to_bottom(mrp_resmgr_screen_t *,
+                                            screen_resource_t *);
+
+
+static uint32_t zorder_new_top_value(mrp_resmgr_screen_area_t *);
+
+static void screen_grant_resources(mrp_resmgr_screen_t *, mrp_zone_t *);
+static void screen_queue_events(mrp_resmgr_screen_t *, mrp_zone_t *);
+
+static void area_insert_resource(mrp_resmgr_screen_area_t*,screen_resource_t*);
+static uint32_t resource_key(mrp_resource_t *, mrp_application_class_t *);
+
+static void screen_notify(mrp_resource_event_t, mrp_zone_t *,
+                          mrp_application_class_t *, mrp_resource_t *, void *);
+static void screen_init(mrp_zone_t *, void *);
+static bool screen_allocate(mrp_zone_t *, mrp_resource_t *, void *);
+static void screen_free(mrp_zone_t *, mrp_resource_t *, void *);
+static bool screen_advice(mrp_zone_t *, mrp_resource_t *, void *);
+static void screen_commit(mrp_zone_t *, void *);
+
+#define PRIORITY_ATTRIDX  0
+#define CLASSPRI_ATTRIDX  1
+#define AREA_ATTRIDX      2
+#define APPID_ATTRIDX     3
+#define SURFACE_ATTRIDX   4
+
+static mrp_attr_def_t screen_attrs[] = {
+    ATTRIBUTE("priority" , integer,       0      ),
+    ATTRIBUTE("classpri" , integer,      -1      ),
+    ATTRIBUTE("area"     , string , "<undefined>"),
+    ATTRIBUTE("appid"    , string , "<undefined>"),
+    ATTRIBUTE("surface"  , integer,       0      ),
+    ATTR_END
+};
+
+static mrp_resource_mgr_ftbl_t screen_ftbl = {
+    screen_notify,
+    screen_init,
+    screen_allocate,
+    screen_free,
+    screen_advice,
+    screen_commit
+};
+
+mrp_resmgr_screen_t *mrp_resmgr_screen_create(mrp_resmgr_t *resmgr)
+{
+    mrp_resmgr_screen_t *screen;
+    mrp_htbl_config_t cfg;
+    uint32_t resid;
+    size_t i;
+
+    if ((screen = mrp_allocz(sizeof(mrp_resmgr_screen_t)))) {
+        resid = mrp_resource_definition_create(MRP_SYSCTL_SCREEN_RESOURCE,
+                                               true,screen_attrs,
+                                               &screen_ftbl,screen);
+        mrp_lua_resclass_create_from_c(resid);
+
+        cfg.nentry = MRP_RESMGR_RESOURCE_MAX;
+        cfg.comp = hash_compare;
+        cfg.hash = hash_function;
+        cfg.free = NULL;
+        cfg.nbucket = MRP_RESMGR_RESOURCE_BUCKETS;
+
+        screen->resmgr = resmgr;
+        screen->resid = resid;
+        screen->resources = mrp_htbl_create(&cfg);
+
+        for (i = 0;  i < MRP_ZONE_MAX;  i++)
+            mrp_list_init(screen->zones + i);
+    }
+
+    return screen;
+}
+
+
+void mrp_resmgr_screen_destroy(mrp_resmgr_screen_t *screen)
+{
+    if (screen) {
+        mrp_htbl_destroy(screen->resources, false);
+        mrp_free(screen);
+    }
+}
+
+int mrp_resmgr_screen_print(mrp_resmgr_screen_t *screen,
+                            uint32_t zoneid,
+                            char *buf, int len)
+{
+#define PRINT(...)                              \
+    do {                                        \
+        p += snprintf(p, e-p, __VA_ARGS__);     \
+        if (p >= e)                             \
+            return p - buf;                     \
+    } while (0)
+
+    char *p, *e;
+    uint32_t grantid;
+    mrp_resmgr_screen_area_t *area;
+    mrp_list_hook_t *areas, *aentry, *an;
+    mrp_list_hook_t *resources, *rentry, *rn;
+    screen_resource_t *sr;
+    mrp_attr_t a;
+    size_t i;
+
+    MRP_ASSERT(screen && buf && len > 0, "invalid argument");
+
+    e = (p = buf) + len;
+    *p = 0;
+    
+    if (zoneid < MRP_ZONE_MAX) {
+        areas = screen->zones + zoneid;
+        grantid = screen->grantids[zoneid];
+    }
+    else {
+        areas = NULL;
+        grantid = 0;
+    }
+
+    PRINT("      Resource 'screen' - grantid:%u\n", grantid);
+
+    if (!areas || mrp_list_empty(areas))
+        PRINT("         No resources\n");
+    else {
+        mrp_list_foreach_back(areas, aentry, an) {
+            area = mrp_list_entry(aentry, mrp_resmgr_screen_area_t, link);
+            resources = &area->resources;
+
+            PRINT("         Area '%s':\n", area->name);
+
+            mrp_list_foreach_back(resources, rentry, rn) {
+                sr = mrp_list_entry(rentry, screen_resource_t, link);
+
+                PRINT("            0x%08x %s %u",
+                      sr->key, sr->acquire ? "acquire":"release", sr->grantid);
+
+                for (i = 0;  i < MRP_ARRAY_SIZE(screen_attrs) - 1;  i++) {
+                    if ((mrp_resource_read_attribute(sr->res, i, &a))) {
+                        PRINT(" %s:", a.name);
+
+                        switch (a.type) {
+                        case mqi_string:   PRINT("'%s'",a.value.string); break;
+                        case mqi_integer:  PRINT("%d",a.value.integer);  break;
+                        case mqi_unsignd:  PRINT("%u",a.value.unsignd);  break;
+                        case mqi_floating: PRINT("%lf",a.value.floating);break;
+                        default:           PRINT("<unsupported type>");  break;
+                        }
+                    }
+                }
+
+                PRINT("\n");
+            } /* mrp_list_foreach_back - resources */
+        }  /* mrp_list_foreach_back - areas */
+    }
+
+    return p - buf;
+}
+
+
+void mrp_resmgr_screen_area_create(mrp_resmgr_screen_t *screen,
+                                   mrp_wayland_area_t *wlarea,
+                                   const char *zonename)
+{
+    mrp_resmgr_screen_area_t *rmarea, *a;
+    int32_t zoneid;
+    size_t areaid;
+    const char *name;
+    int32_t outputid;
+    size_t i;
+    int32_t x, x0, x1, y, y0, y1;
+
+    MRP_ASSERT(screen && wlarea && wlarea->output && zonename,
+               "invalid argument");
+
+    if (wlarea->areaid < 0 || wlarea->areaid >= MRP_WAYLAND_AREA_MAX) {
+        mrp_log_error("system-controller: refuse to create screen area '%s': "
+                      "id %d is out of range (0 - %d)",
+                      wlarea->name, wlarea->areaid, MRP_WAYLAND_AREA_MAX - 1);
+        return;
+    }
+
+    areaid   = wlarea->areaid;
+    name     = wlarea->name ? wlarea->name : "<unknown>";
+    outputid = wlarea->output->outputid;
+
+    if ((zoneid = get_zone_id(zonename))) {
+        mrp_log_error("system-controller: can't create resource manager area "
+                      "%d: can't find zone '%s' for it", areaid, zonename);
+        return;
+    }
+
+    if (areaid >= screen->narea) {
+        screen->areas = mrp_reallocz(screen->areas, screen->narea, areaid + 1);
+
+        MRP_ASSERT(screen->areas, "can't allocate memory for screen areas");
+
+        screen->narea = areaid + 1;
+    }
+
+    if (screen->areas[areaid]) {
+        mrp_log_error("system-controller: attempt to redefine "
+                      "resource manager area %d", areaid);
+        return;
+    }
+
+    screen->areas[areaid] = rmarea = mrp_allocz(sizeof(*rmarea));
+
+    mrp_list_append(screen->zones + zoneid, &rmarea->link);
+    rmarea->name = mrp_strdup(name);
+    rmarea->outputid = outputid;
+    rmarea->x = wlarea->x;
+    rmarea->y = wlarea->y;
+    rmarea->width = wlarea->width;
+    rmarea->height = wlarea->height;
+    mrp_list_init(&rmarea->resources);
+
+    x1 = (x0 = rmarea->x) + rmarea->width;
+    y1 = (y0 = rmarea->y) + rmarea->height;
+
+    for (i = 0;  i < screen->narea; i++) {
+        if ((a = screen->areas[i]) && i != areaid) {
+            if ((      a->outputid == outputid        ) &&
+                (((x  = a->x     ) >= x0 && x < x1) ||
+                 ((x += a->width ) >= x0 && x < x1) ||
+                 ((y  = a->y     ) >= y0 && y < y1) ||
+                 ((y += a->height) >= y0 && y < y1)   )   )
+            {
+                overlap_add(a, areaid);
+                overlap_add(rmarea, i);
+            }
+        }
+    }
+
+    mrp_log_info("system-controller: resource manager registered screen area "
+                 "%d - '%s'", areaid, name);
+}
+
+void mrp_screen_area_destroy(mrp_resmgr_screen_t *screen, int32_t areaid)
+{
+    mrp_resmgr_screen_area_t *area;
+    size_t i;
+
+    MRP_ASSERT(screen && areaid >= 0 && areaid < MRP_WAYLAND_AREA_MAX,
+               "invalid argument");
+
+    if (areaid >= (int32_t)screen->narea || !(area = screen->areas[areaid])) {
+        mrp_log_error("system-controller: attempt to destroy non-existent "
+                      "resource manager area %d", areaid);
+    }
+    else {
+        screen->areas[areaid] = NULL;
+
+        for (i = 0;  i < area->noverlap;  i++)
+            overlap_remove(screen->areas[area->overlaps[i]], areaid);
+
+        mrp_free((void *)area->name);
+        mrp_free((void *)area->overlaps);
+        mrp_free(area);
+    }
+}
+
+void mrp_screen_resource_raise(mrp_resmgr_screen_t *screen,
+                               const char *appid,
+                               int32_t surfaceid)
+{
+    mrp_resmgr_screen_area_t *area;
+    mrp_list_hook_t *resources, *entry, *n;
+    screen_resource_t *sr;
+    mrp_resource_t *res;
+    const char *id;
+    size_t i, cnt;
+    size_t zmax, zmin;
+    bool zones[MRP_ZONE_MAX];
+
+    MRP_ASSERT(screen && screen->resources && appid, "invalid argument");
+
+    if (surfaceid == 0) {
+        cnt = 0;
+        zmax = 0;
+        zmin = MRP_ZONE_MAX-1;
+
+        for (i = cnt = 0;  i < screen->narea;  i++) {
+            area = screen->areas[i];
+            resources = &area->resources;
+
+            mrp_list_foreach(resources, entry, n) {
+                sr = mrp_list_entry(entry, screen_resource_t, link);
+                res = sr->res;
+
+                if ((id = get_appid_for_resource(res)) && !strcmp(id, appid)) {
+                    mrp_debug("raise surface %d to top", surfaceid);
+
+                    if (!screen_resource_is_on_top(screen, sr)) {
+                        screen_resource_raise_to_top(screen, sr);
+
+                        cnt++;
+                        zones[sr->zoneid] = true;
+                        if (zmax < sr->zoneid)  zmax = sr->zoneid;
+                        if (zmin > sr->zoneid)  zmin = sr->zoneid;
+                    }
+                    break;
+                }
+            }
+        }
+
+        if (!cnt)
+            mrp_debug("nothing to be raised");
+        else {
+            for (i = zmin;  i <= zmax;  i++) {
+                if (zones[i])
+                    mrp_resource_owner_recalc(i);
+            }
+        }
+    }
+    else {
+        if ((sr = mrp_htbl_lookup(screen->resources, NULL + surfaceid))) {
+            res = sr->res;
+
+            if (!(id = get_appid_for_resource(res)) || strcmp(id, appid)) {
+                mrp_log_error("system-controller: can't raise window %u: "
+                              "appid mismatch ('%s' vs. '%s')",
+                              surfaceid, id, appid);
+            }
+            else {
+                if (screen_resource_is_on_top(screen, sr)) {
+                    mrp_debug("nothing to be raised: surface %d "
+                              "is already on top", surfaceid);
+                }
+                else {
+                    mrp_debug("raise surface %d to top", surfaceid);
+                    screen_resource_raise_to_top(screen, sr);
+                    mrp_resource_owner_recalc(sr->zoneid);
+                }
+            }
+        }
+    }
+}
+
+void mrp_screen_resource_lower(mrp_resmgr_screen_t *screen,
+                               const char *appid,
+                               int32_t surfaceid)
+{
+    mrp_resmgr_screen_area_t *area;
+    mrp_list_hook_t *resources, *entry, *n;
+    screen_resource_t *sr;
+    mrp_resource_t *res;
+    const char *id;
+    size_t i, cnt;
+    size_t zmax, zmin;
+    bool zones[MRP_ZONE_MAX];
+
+    MRP_ASSERT(screen && screen->resources && appid, "invalid argument");
+
+    if (surfaceid == 0) {
+        cnt = 0;
+        zmax = 0;
+        zmin = MRP_ZONE_MAX-1;
+
+        for (i = cnt = 0;  i < screen->narea;  i++) {
+            area = screen->areas[i];
+            resources = &area->resources;
+
+            mrp_list_foreach_back(resources, entry, n) {
+                sr = mrp_list_entry(entry, screen_resource_t, link);
+                res = sr->res;
+
+                if ((id = get_appid_for_resource(res)) && !strcmp(id, appid)) {
+                    mrp_debug("lower surface %d to bottom", surfaceid);
+
+                    screen_resource_lower_to_bottom(screen, sr);
+
+                    cnt++;
+                    zones[sr->zoneid] = true;
+                    if (zmax < sr->zoneid)  zmax = sr->zoneid;
+                    if (zmin > sr->zoneid)  zmin = sr->zoneid;
+                }
+            }
+        }
+
+        if (!cnt)
+            mrp_debug("nothing to be lowered");
+        else {
+            for (i = zmin;  i <= zmax;  i++) {
+                if (zones[i])
+                    mrp_resource_owner_recalc(i);
+            }
+        }
+    }
+    else {
+        if ((sr = mrp_htbl_lookup(screen->resources, NULL + surfaceid))) {
+            res = sr->res;
+
+            if (!(id = get_appid_for_resource(res)) || strcmp(id, appid)) {
+                mrp_log_error("system-controller: can't lower window %u: "
+                              "appid mismatch ('%s' vs. '%s')",
+                              surfaceid, id, appid);
+            }
+            else {
+                mrp_debug("lower surface %d to bottom", surfaceid);
+                screen_resource_lower_to_bottom(screen, sr);
+                mrp_resource_owner_recalc(sr->zoneid);
+            }
+        }
+    }
+}
+
+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)(key - (const void *)0);
+}
+
+static void overlap_add(mrp_resmgr_screen_area_t *area, size_t overlapid)
+{
+    size_t i;
+
+    for (i = 0;  i < area->noverlap;  i++) {
+        if (area->overlaps[i] == overlapid)
+            return;
+    }
+
+    area->overlaps = mrp_realloc(area->overlaps, sizeof(size_t *) * (i + 1));
+
+    MRP_ASSERT(area->overlaps, "can't allocate memory for overalapping "
+               "resource manager areas");
+
+    area->overlaps[i] = overlapid;
+    area->noverlap++;
+}
+
+static void overlap_remove(mrp_resmgr_screen_area_t *area, size_t overlapid)
+{
+    size_t i;
+
+    for (i = 0;  i < area->noverlap;  i++) {
+        if (area->overlaps[i] == overlapid) {
+            for (i++; i < area->noverlap; i++)
+                area->overlaps[i-1] = area->overlaps[i];
+            area->noverlap--;
+            return;
+        }
+    }
+
+    mrp_log_error("system-controller: attempt to remove unregistered "
+                  "overlapping area");
+}
+
+static const char *get_appid_for_resource(mrp_resource_t *res)
+{
+    mrp_attr_t attr;
+    const char *appid;
+
+    if (!mrp_resource_read_attribute(res, APPID_ATTRIDX, &attr) ||
+        attr.type != mqi_string || !(appid = attr.value.string)  )
+        appid = NULL;
+
+    return appid;
+}
+
+static int32_t get_surfaceid_for_resource(mrp_resource_t *res)
+{
+    mrp_attr_t attr;
+
+    if (mrp_resource_read_attribute(res, SURFACE_ATTRIDX, &attr)) {
+        if (attr.type == mqi_integer)
+            return attr.value.integer;
+    }
+
+    return 0;
+}
+
+static int32_t get_layerid_for_resource(mrp_resource_t *res)
+{
+    MRP_UNUSED(res);
+
+    return -1;
+}
+
+static const char *get_areaname_for_resource(mrp_resource_t *res)
+{
+    mrp_attr_t attr;
+
+    if (mrp_resource_read_attribute(res, AREA_ATTRIDX, &attr)) {
+        if (attr.type == mqi_string)
+            return attr.value.string;
+    }
+
+    return NULL;
+}
+
+static mrp_application_t *get_application_for_resource(mrp_resource_t *res)
+{
+    const char        *appid = get_appid_for_resource(res);
+    mrp_application_t *app   = NULL;
+
+    if (!appid || !(app = mrp_application_find(appid)))
+        app = mrp_application_find(MRP_SYSCTL_APPID_DEFAULT);
+
+    return app;
+}
+
+static int32_t get_area_for_resource(mrp_resource_t *res)
+{
+    mrp_wayland_t *wl;
+    mrp_wayland_area_t *a;
+    const char *areaname;
+    void *it;
+
+    if ((areaname = get_areaname_for_resource(res))) {
+        mrp_wayland_foreach(wl, it) {
+            if ((a = mrp_wayland_area_find(wl, areaname)))
+                return a->areaid;
+        }
+    }
+
+    return -1;
+}
+
+
+static uint32_t get_priority_for_resource(mrp_resource_t *res)
+{
+    mrp_attr_t attr;
+    uint32_t priority = 0;
+
+    if (mrp_resource_read_attribute(res, PRIORITY_ATTRIDX, &attr)) {
+        if (attr.type == mqi_integer && attr.value.integer >= 0)
+            priority = attr.value.integer;
+    }
+
+    return priority;
+}
+
+static uint32_t get_class_priority_for_resource(mrp_resource_t *res,
+                                                mrp_application_class_t *ac)
+{
+    mrp_attr_t attr;
+    uint32_t priority;
+
+    priority = mrp_application_class_get_priority(ac);
+
+    if (mrp_resource_read_attribute(res, CLASSPRI_ATTRIDX, &attr)) {
+        if (attr.type == mqi_integer && attr.value.integer >= 0)
+            priority = attr.value.integer;
+    }
+
+    return priority;
+}
+
+static int32_t get_zone_id(const char *name)
+{
+    const char *zones[MRP_ZONE_MAX + 1];
+    const char *zone;
+    int32_t id;
+
+    if (mrp_zone_get_all_names(MRP_ZONE_MAX + 1, zones)) {
+        for (id = 0;   (zone = zones[id]);  id++) {
+            if (!strcmp(name, zone))
+                return id;
+        }
+    }
+
+    return -1;
+}
+
+
+
+static screen_resource_t *screen_resource_create(mrp_resmgr_screen_t *screen,
+                                                 mrp_zone_t *zone,
+                                                 mrp_resource_t *res,
+                                                 mrp_application_class_t *ac)
+{
+    mrp_resmgr_t *resmgr;
+    mrp_application_t *app;
+    mrp_resmgr_screen_area_t *area;
+    int32_t areaid;
+    int32_t surfaceid;
+    screen_resource_t *sr;
+    void *hk;
+
+    MRP_ASSERT(screen && screen->resources && zone && res && ac,
+               "invalid argument");
+    MRP_ASSERT(screen->resmgr, "confused with data structures");
+
+    resmgr = screen->resmgr;
+    sr = NULL;
+
+    if (!(app = get_application_for_resource(res))) {
+        mrp_log_error("system-controller: failed to create screen resource: "
+                      "can't find app");
+        return NULL;
+    }
+            
+    if ((areaid = get_area_for_resource(res)) < 0 ||
+        (size_t)areaid >= screen->narea           ||
+        !(area = screen->areas[areaid])            )
+    {
+        mrp_log_error("system-controller: failed to create screen resource: "
+                      "can't find area");
+        return NULL;
+    }
+
+    if (!(surfaceid = get_surfaceid_for_resource(res))) {
+        mrp_log_error("system-controller: failed to create screen resource: "
+                      "invalid surface attribute");
+        return NULL;
+    }
+
+    if (!(sr = mrp_allocz(sizeof(*sr)))) {
+        mrp_log_error("system-controller: failed to create screen resource: "
+                      "can't allocate memory");
+        return NULL;
+    }
+
+    mrp_list_init(&sr->link);
+    sr->screen = screen;
+    sr->res    = res;
+    sr->zoneid = mrp_zone_get_id(zone);
+    sr->areaid = areaid;
+    sr->key    = resource_key(res, ac);
+                    
+    area_insert_resource(area, sr);
+
+    mrp_debug("inserting resource to hash table: key=%p value=%p", res, sr);
+    mrp_resmgr_insert_resource(resmgr, zone, res, sr);
+
+    hk = NULL + surfaceid;
+    mrp_debug("inserting surface to hash table: key=%p value=%p", hk, sr);
+    mrp_htbl_insert(screen->resources, hk, sr);
+
+    return sr;
+}
+
+
+static void screen_resource_destroy(mrp_resmgr_screen_t *screen,
+                                    mrp_zone_t *zone,
+                                    mrp_resource_t *res)
+{
+    screen_resource_t *sr;
+    int32_t surfaceid;
+
+    MRP_ASSERT(res && screen && screen->resources, "invalid argument");
+    MRP_ASSERT(screen->resmgr, "confused with data structures");
+
+    if ((sr = mrp_resmgr_remove_resource(screen->resmgr, zone, res))) {
+
+        if ((surfaceid = get_surfaceid_for_resource(res)))
+            mrp_htbl_remove(screen->resources, NULL + surfaceid, false);
+
+        mrp_list_delete(&sr->link);
+        mrp_free(sr);
+    }
+}
+
+
+static screen_resource_t *screen_resource_lookup(mrp_resmgr_screen_t *screen,
+                                                 mrp_resource_t *res)
+{
+    screen_resource_t *sr;
+
+    MRP_ASSERT(res && screen, "invalid argument");
+    MRP_ASSERT(screen->resmgr, "confused with data structures");
+
+    sr = mrp_resmgr_lookup_resource(screen->resmgr, res);
+
+    return sr;
+}
+
+static bool screen_resource_is_on_top(mrp_resmgr_screen_t *screen,
+                                         screen_resource_t *sr)
+{
+    mrp_resmgr_screen_area_t *area;
+    bool on_top;
+
+    if (sr->areaid >= screen->narea || !(area = screen->areas[sr->areaid]))
+        on_top = false;
+    else
+        on_top = (area->resources.prev == &sr->link);
+
+    return on_top;
+}
+
+static void screen_resource_raise_to_top(mrp_resmgr_screen_t *screen,
+                                         screen_resource_t *sr)
+{
+    mrp_resmgr_screen_area_t *area;
+
+    if (sr->areaid >= screen->narea || !(area = screen->areas[sr->areaid])) {
+        mrp_log_error("system-controller: failed to raise screen resource: "
+                      "can't find area for screen");
+    }
+    else {
+        sr->key &= ~(ZORDER_MASK << ZORDER_POSITION);
+        sr->key |= zorder_new_top_value(area);
+    
+        area_insert_resource(area, sr);
+    }
+
+    sr->acquire = true;
+}
+
+
+static void screen_resource_lower_to_bottom(mrp_resmgr_screen_t *screen,
+                                            screen_resource_t *sr)
+{
+    mrp_resmgr_screen_area_t *area;
+
+    if (sr->areaid >= screen->narea || !(area = screen->areas[sr->areaid])) {
+        mrp_log_error("system-controller: failed to lower screen resource: "
+                      "can't find area for screen");
+    }
+    else {
+        sr->key &= ~(ZORDER_MASK << ZORDER_POSITION);
+
+        area_insert_resource(area, sr);
+    }
+
+    sr->acquire = false;
+}
+
+
+static uint32_t zorder_new_top_value(mrp_resmgr_screen_area_t *area)
+{
+    mrp_list_hook_t *resources, *entry, *n;
+    screen_resource_t *sr;
+    uint32_t new_top, min, max, z;
+
+    if ((new_top = ++(area->zorder)) >= ZORDER_MAX) {
+        /*
+         * we get here in the unlikely event of z-order value overflow
+         * what we try to do here is to find out the range of the z values
+         * and subtract from all the minimum value, ie. move the whole range
+         * to start from zero.
+         */
+        resources = &area->resources;
+
+        if (mrp_list_empty(resources))
+            new_top = area->zorder = 1;
+        else {
+            min = ZORDER_MAX;
+            max = 0;
+
+            mrp_list_foreach(resources, entry, n) {
+                sr = mrp_list_entry(entry, screen_resource_t, link);
+                z = ((sr->key >> ZORDER_POSITION) & ZORDER_MASK);
+
+                if (z < min)   min = z;
+                if (z > max)   max = z;
+            }
+
+            /* assert if the range moving would not help */
+            MRP_ASSERT(min < ZORDER_MAX-1, "Z-order overflow");
+
+            mrp_list_foreach(resources, entry, n) {
+                sr = mrp_list_entry(entry, screen_resource_t, link);
+                z = ((sr->key >> ZORDER_POSITION) & ZORDER_MASK) - min;
+
+                sr->key &= ~(ZORDER_MASK << ZORDER_POSITION);
+                sr->key |= (z << ZORDER_POSITION);
+            }
+
+            new_top = area->zorder = (max - min) + 1;
+        }
+    }
+
+    return (new_top << ZORDER_POSITION);
+}
+
+
+static void screen_grant_resources(mrp_resmgr_screen_t *screen,
+                                   mrp_zone_t *zone)
+{
+    uint32_t zoneid;
+    uint32_t grantid;
+    mrp_list_hook_t *areas, *aentry, *an;
+    mrp_list_hook_t *resources, *rentry , *rn;
+    mrp_resmgr_screen_area_t *area;
+    screen_resource_t *sr;
+
+    zoneid  = mrp_zone_get_id(zone);
+    areas   = screen->zones + zoneid;
+    grantid = ++(screen->grantids[zoneid]);
+    
+    mrp_list_foreach(areas, aentry, an) {
+        area = mrp_list_entry(aentry, mrp_resmgr_screen_area_t, link);
+        resources = &area->resources;
+
+        mrp_list_foreach_back(resources, rentry, rn) {
+            sr = mrp_list_entry(rentry, screen_resource_t, link);
+
+            if (sr->acquire) {
+                sr->grantid = grantid;
+                break;
+            }
+        }
+    }
+}
+
+static void screen_queue_events(mrp_resmgr_screen_t *screen, mrp_zone_t *zone)
+{
+    uint32_t zoneid;
+    uint32_t grantid;
+    mrp_list_hook_t *areas, *aentry, *an;
+    mrp_list_hook_t *resources, *rentry, *rn;
+    mrp_resmgr_screen_area_t *area;
+    screen_resource_t *sr;
+    bool grant;
+    mrp_resmgr_eventid_t eventid;
+    const char *appid, *areaname;
+    int32_t surfaceid, layerid;
+
+    zoneid  = mrp_zone_get_id(zone);
+    areas   = screen->zones + zoneid;
+    grantid = screen->grantids[zoneid];
+    
+    mrp_list_foreach(areas, aentry, an) {
+        area = mrp_list_entry(aentry, mrp_resmgr_screen_area_t, link);
+        resources = &area->resources;
+
+
+        mrp_list_foreach_back(resources, rentry, rn) {
+            sr = mrp_list_entry(rentry, screen_resource_t, link);
+            grant = (grantid == sr->grantid);
+
+            if ((grant && !sr->grant) || (!grant && sr->grant)) {
+
+                eventid   = grant ? MRP_RESMGR_EVENTID_GRANT :
+                                    MRP_RESMGR_EVENTID_REVOKE;
+                appid     = get_appid_for_resource(sr->res);
+                surfaceid = get_surfaceid_for_resource(sr->res);
+                layerid   = get_layerid_for_resource(sr->res);
+                areaname  = get_areaname_for_resource(sr->res);
+
+                mrp_resmgr_notifier_queue_screen_event(screen->resmgr,
+                                                       zoneid, eventid,
+                                                       appid, surfaceid,
+                                                       layerid, areaname);
+            }
+
+            sr->grant = grant;
+        }
+    }
+}
+
+
+static void area_insert_resource(mrp_resmgr_screen_area_t *area,
+                                 screen_resource_t *resource)
+{
+    mrp_list_hook_t *resources, *insert_after, *n;
+    screen_resource_t *sr;
+    uint32_t key;
+
+    mrp_list_delete(&resource->link);
+
+    resources = &area->resources;
+    key = resource->key;
+    insert_after = resources;   /* keep the compiler happy: foreach below
+                                   will do it anyways */
+
+    mrp_list_foreach_back(resources, insert_after, n) {
+        sr = mrp_list_entry(insert_after, screen_resource_t, link);
+        if (key >= sr->key)
+            break;
+    }
+
+    mrp_list_insert_after(insert_after, &resource->link);
+}
+
+static uint32_t resource_key(mrp_resource_t *res, mrp_application_class_t *ac)
+{
+    uint32_t priority;
+    uint32_t classpri;
+    uint32_t key = 0;
+
+    if (res && ac) {
+        priority = get_priority_for_resource(res);
+        classpri = get_class_priority_for_resource(res, ac);
+        key = ((priority & PRIORITY_MASK) << PRIORITY_POSITION) |
+              ((classpri & CLASSPRI_MASK) << CLASSPRI_POSITION) ;
+    }
+
+    return key;
+}
+
+static void screen_notify(mrp_resource_event_t event,
+                          mrp_zone_t *zone,
+                          mrp_application_class_t *ac,
+                          mrp_resource_t *res,
+                          void *userdata)
+{
+    mrp_resmgr_screen_t *screen = (mrp_resmgr_screen_t *)userdata;
+    const char *zonename = mrp_zone_get_name(zone);
+    screen_resource_t *sr;
+
+    MRP_ASSERT(zone && ac && res && screen, "invalid argument");
+
+    switch (event) {
+
+    case MRP_RESOURCE_EVENT_CREATED:
+        mrp_debug("screen resource in zone '%s' created", zonename);
+        screen_resource_create(screen, zone, res, ac);
+        break;
+
+    case MRP_RESOURCE_EVENT_DESTROYED:
+        mrp_debug("screen resource in zone '%s' destroyed", zonename);
+        screen_resource_destroy(screen, zone, res);
+        break;
+
+    case MRP_RESOURCE_EVENT_ACQUIRE:
+        mrp_debug("screen resource in zone '%s' is acquiring", zonename);
+        if (!(sr = screen_resource_lookup(screen, res)))
+            goto no_screen_resource;
+        else
+            screen_resource_raise_to_top(screen, sr);
+        break;
+
+    case MRP_RESOURCE_EVENT_RELEASE:
+        mrp_debug("screen resource in zone '%s' is released", zonename);
+        if (!(sr = screen_resource_lookup(screen, res)))
+            goto no_screen_resource;
+        else
+            screen_resource_lower_to_bottom(screen, sr);
+        break;
+
+    no_screen_resource:
+        mrp_debug("resource lookup in hash table failed: key=%p", res);
+        mrp_log_error("system-controller: can't find screen resource "
+                      "in zone '%s'", zonename);
+        break;
+
+    default:
+        mrp_log_error("system-controller: invalid event %d at screen "
+                      "notification (zone '%s')", event, zonename);
+        break;
+    }
+}
+
+static void screen_init(mrp_zone_t *zone, void *userdata)
+{
+    mrp_resmgr_screen_t *screen = (mrp_resmgr_screen_t *)userdata;
+    const char *zonename = mrp_zone_get_name(zone);
+
+    MRP_ASSERT(screen, "invalid argument");
+
+    mrp_debug("screen init in zone '%s'", zonename);
+
+    screen_grant_resources(screen, zone);
+}
+
+static bool screen_allocate(mrp_zone_t *zone,
+                            mrp_resource_t *res,
+                            void *userdata)
+{
+    mrp_resmgr_screen_t *screen = (mrp_resmgr_screen_t *)userdata;
+    uint32_t zoneid;
+    screen_resource_t *sr;
+    uint32_t grantid;
+
+    MRP_ASSERT(zone && res && screen && screen->resmgr, "invalid argument");
+
+    zoneid  = mrp_zone_get_id(zone);
+    grantid = screen->grantids[zoneid];
+
+    if ((sr = screen_resource_lookup(screen, res)))
+        return (sr->grantid == grantid);
+
+    mrp_log_error("system-controller: attempt to allocate untracked resource");
+
+    return FALSE;
+}
+
+static void screen_free(mrp_zone_t *zone, mrp_resource_t *res, void *userdata)
+{
+    mrp_resmgr_screen_t *screen = (mrp_resmgr_screen_t *)userdata;
+    const char *zonename = mrp_zone_get_name(zone);
+    screen_resource_t *sr;
+
+    MRP_ASSERT(screen && res, "invalid argument");
+
+    mrp_debug("screen free in zone '%s'", zonename);
+
+    if ((sr = screen_resource_lookup(screen, res)))
+        sr->grantid = 0;
+}
+
+static bool screen_advice(mrp_zone_t *zone,mrp_resource_t *res,void *userdata)
+{
+    mrp_resmgr_screen_t *screen = (mrp_resmgr_screen_t *)userdata;
+    const char *zonename = mrp_zone_get_name(zone);
+
+    MRP_UNUSED(res);
+
+    MRP_ASSERT(screen, "invalid argument");
+
+    mrp_debug("screen advice in zone '%s'", zonename);
+
+    return TRUE;
+}
+
+static void screen_commit(mrp_zone_t *zone, void *userdata)
+{
+    mrp_resmgr_screen_t *screen = (mrp_resmgr_screen_t *)userdata;
+    const char *zonename;
+    uint32_t zoneid;
+
+    MRP_ASSERT(zone && screen && screen->resmgr, "invalid argument");
+
+    zonename = mrp_zone_get_name(zone);
+    zoneid  = mrp_zone_get_id(zone);
+
+    mrp_debug("screen commit in zone '%s'", zonename);
+
+    screen_queue_events(screen, zone);
+    mrp_resmgr_notifier_flush_screen_events(screen->resmgr, zoneid);
+}
diff --git a/src/plugins/system-controller/resource-manager/screen.h b/src/plugins/system-controller/resource-manager/screen.h
new file mode 100644 (file)
index 0000000..01056f9
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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_SCREEN_H__
+#define __MURPHY_SYSTEM_CONTROLLER_SCREEN_H__
+
+#include <sys/types.h>
+
+#include <murphy/common/hashtbl.h>
+
+#include "resource-manager.h"
+#include "wayland/wayland.h"
+
+struct mrp_resmgr_screen_area_s {
+    mrp_list_hook_t link;       /* to maintain the list of areas in a zone */
+    const char *name;
+    int32_t outputid;
+    int32_t x, y;
+    int32_t width, height;
+    mrp_list_hook_t resources;
+    size_t noverlap;
+    size_t *overlaps;
+    int32_t zorder;
+};
+
+struct mrp_resmgr_screen_s {
+    mrp_resmgr_t *resmgr;
+    uint32_t resid;
+    mrp_htbl_t *resources;               /* to access resources by surfaceid */
+    mrp_list_hook_t zones[MRP_ZONE_MAX]; /* list of areas in the zones */
+    uint32_t grantids[MRP_ZONE_MAX];
+    size_t narea;
+    mrp_resmgr_screen_area_t **areas;    /* areas to access by index */
+};
+
+
+mrp_resmgr_screen_t *mrp_resmgr_screen_create(mrp_resmgr_t *resmgr);
+void mrp_resmgr_screen_destroy(mrp_resmgr_screen_t *screen);
+
+int mrp_resmgr_screen_print(mrp_resmgr_screen_t *screen, uint32_t areaid,
+                            char *buf, int len);
+
+void mrp_resmgr_screen_area_create(mrp_resmgr_screen_t *screen,
+                                   mrp_wayland_area_t *wlarea,
+                                   const char *zonename);
+void mrp_screen_area_destroy(mrp_resmgr_screen_t *screen,
+                             int32_t areaid);
+
+void mrp_screen_resource_raise(mrp_resmgr_screen_t *screen,
+                               const char *appid,
+                               int32_t surfaceid);
+void mrp_screen_resource_lower(mrp_resmgr_screen_t *screen,
+                               const char *appid,
+                               int32_t surfaceid);
+
+
+#endif /* __MURPHY_SYSTEM_CONTROLLER_SCREEN_H__ */
diff --git a/src/plugins/system-controller/resource-manager/scripting-notifier.c b/src/plugins/system-controller/resource-manager/scripting-notifier.c
new file mode 100644 (file)
index 0000000..86a87e1
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * 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 "notifier.h"
+
+#define SCREEN_EVENT_CLASS   MRP_LUA_CLASS_SIMPLE(screen_event)
+
+typedef struct scripting_screen_event_s  scripting_screen_event_t;
+
+struct scripting_screen_event_s {
+    const char *eventid;
+    const char *appid;
+    int32_t surfaceid;
+    int32_t layerid;
+    const char *area;
+};
+
+static int  screen_event_create_from_lua(lua_State *);
+static int  screen_event_getfield(lua_State *);
+static int  screen_event_setfield(lua_State *);
+static int  screen_event_stringify(lua_State *);
+static void screen_event_destroy_from_lua(void *);
+
+static scripting_screen_event_t *screen_event_check(lua_State *, int);
+
+MRP_LUA_CLASS_DEF_SIMPLE (
+    screen_event,                  /* class name */
+    scripting_screen_event_t,      /* userdata type */
+    screen_event_destroy_from_lua, /* userdata destructor */
+    MRP_LUA_METHOD_LIST (          /* methods */
+       MRP_LUA_METHOD_CONSTRUCTOR (screen_event_create_from_lua)
+    ),
+    MRP_LUA_METHOD_LIST (       /* overrides */
+       MRP_LUA_OVERRIDE_CALL      (screen_event_create_from_lua)
+       MRP_LUA_OVERRIDE_GETFIELD  (screen_event_getfield)
+       MRP_LUA_OVERRIDE_SETFIELD  (screen_event_setfield)
+       MRP_LUA_OVERRIDE_STRINGIFY (screen_event_stringify)
+    )
+);
+
+void mrp_resmgr_scripting_notifier_init(lua_State *L)
+{
+    mrp_lua_create_object_class(L, SCREEN_EVENT_CLASS);
+}
+
+
+void *mrp_resmgr_scripting_screen_event_create_from_c(lua_State *L,
+                                                     mrp_resmgr_event_t *event)
+{
+    scripting_screen_event_t *sev;
+    const char *eventid;
+
+    MRP_ASSERT(event, "invald argument");
+    
+    if (!L && !(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("system-controller: can't create scripting screen event:"
+                      " LUA is not initialized");
+        return NULL;
+    }
+
+    switch (event->eventid) {
+
+    case MRP_RESMGR_EVENTID_GRANT:   eventid = "grant";   break;
+    case MRP_RESMGR_EVENTID_REVOKE:  eventid = "revoke";  break;
+
+    default:
+        mrp_log_error("system-controller: can't create scripting screen event:"
+                      " invalid event ID %d", event->eventid);
+        return NULL;
+    }
+
+    sev = (scripting_screen_event_t *)mrp_lua_create_object(L,
+                                                            SCREEN_EVENT_CLASS,
+                                                            NULL, 0);
+    if (!sev) {
+        mrp_log_error("system-controller: can't create scripting screen event:"
+                      " LUA object creation failed");
+        return NULL;
+    }
+
+    sev->eventid   = eventid;
+    sev->appid     = mrp_strdup(event->appid);
+    sev->surfaceid = event->surfaceid;
+    sev->layerid   = event->layerid;
+    sev->area      = mrp_strdup(event->area);
+
+    return sev;
+}
+
+
+static int screen_event_create_from_lua(lua_State *L)
+{
+    MRP_LUA_ENTER;
+
+    luaL_error(L, "screen_event can't be created from LUA");
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int screen_event_getfield(lua_State *L)
+{
+    scripting_screen_event_t *sev;
+    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);
+
+    if (!(sev = screen_event_check(L, 1)))
+        lua_pushnil(L);
+    else {
+        switch (fld) {
+        case TYPE:      lua_pushstring(L, "screen");          break;
+        case EVENT:     lua_pushstring(L, sev->eventid);      break;
+        case APPID:     lua_pushstring(L, sev->appid);        break;
+        case SURFACE:   lua_pushinteger(L, sev->surfaceid);   break;
+        case LAYER:     lua_pushinteger(L, sev->layerid);     break;
+        case AREA:      lua_pushstring(L, sev->area);         break;
+        default:        lua_pushnil(L);                       break;
+        }
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static int  screen_event_setfield(lua_State *L)
+{
+    MRP_LUA_ENTER;
+
+    screen_event_check(L, 1);
+    luaL_error(L, "screen_event objects are read-only");
+
+    MRP_LUA_LEAVE(0);
+}
+
+static int  screen_event_stringify(lua_State *L)
+{
+    scripting_screen_event_t *sev;
+    char *p, *e;
+    char buf[4096];
+
+    MRP_LUA_ENTER;
+
+    if (!(sev = screen_event_check(L, 1)))
+        lua_pushnil(L);
+    else {
+        e = (p = buf) + sizeof(buf);
+        p += snprintf(p, e-p, "screen_event %s\n   appid: '%s'\n"
+                      "   surface: %d\n   layer: %d\n   area: '%s'",
+                      sev->eventid, sev->appid, sev->surfaceid, sev->layerid,
+                      sev->area);
+
+        lua_pushlstring(L, buf, p-buf);
+    }
+
+    MRP_LUA_LEAVE(1);
+}
+
+static void screen_event_destroy_from_lua(void *data)
+{
+    scripting_screen_event_t *sev = (scripting_screen_event_t *)data;
+
+    MRP_LUA_ENTER;
+
+    if (sev) {
+        mrp_free((void *)sev->appid);
+        mrp_free((void *)sev->area);
+        mrp_free((void *)sev);
+    }
+
+    MRP_LUA_LEAVE_NOARG;
+}
+
+
+static scripting_screen_event_t *screen_event_check(lua_State *L, int idx)
+{
+    return (scripting_screen_event_t *)mrp_lua_check_object(L,
+                                                            SCREEN_EVENT_CLASS,
+                                                            idx);
+}
index e809c80..a501be7 100644 (file)
@@ -46,6 +46,8 @@
 
 #include "scripting-resource-manager.h"
 #include "wayland/scripting-wayland.h"
+#include "screen.h"
+#include "notifier.h"
 
 #define RESOURCE_MANAGER_CLASS   MRP_LUA_CLASS_SIMPLE(resource_manager)
 
@@ -54,6 +56,7 @@ typedef struct funcbridge_def_s    funcbridge_def_t;
 
 struct scripting_resmgr_s {
     mrp_resmgr_t *resmgr;
+    mrp_funcbridge_t *screen_event_handler;
 };
 
 struct funcbridge_def_s {
@@ -65,13 +68,14 @@ struct funcbridge_def_s {
 };
 
 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 void screen_event_handler_callback(mrp_resmgr_t *,mrp_resmgr_event_t *);
+
 static bool register_methods(lua_State *);
 
 
@@ -91,7 +95,7 @@ MRP_LUA_CLASS_DEF_SIMPLE (
 
 
 static mrp_funcbridge_t *area_create;
-
+static mrp_funcbridge_t *window_raise;
 
 void mrp_resmgr_scripting_init(lua_State *L)
 {
@@ -99,6 +103,8 @@ void mrp_resmgr_scripting_init(lua_State *L)
 
     mrp_lua_create_object_class(L, RESOURCE_MANAGER_CLASS);
     register_methods(L);
+
+    mrp_resmgr_scripting_notifier_init(L);
 }
 
 
@@ -133,6 +139,7 @@ static int resmgr_create(lua_State *L)
     const char *fldnam;
     scripting_resmgr_t *rm;
     int table;
+    mrp_funcbridge_t *screen_event_handler = NULL;
 
     MRP_LUA_ENTER;
 
@@ -149,6 +156,10 @@ static int resmgr_create(lua_State *L)
     MRP_LUA_FOREACH_FIELD(L, 2, fldnam, fldnamlen) {
         switch (mrp_resmgr_scripting_field_name_to_type(fldnam, fldnamlen)) {
 
+        case SCREEN_EVENT_HANDLER:
+            screen_event_handler = mrp_funcbridge_create_luafunc(L, -1);
+            break;
+
         default:
             lua_pushvalue(L, -2);
             lua_pushvalue(L, -2);
@@ -161,7 +172,12 @@ static int resmgr_create(lua_State *L)
         luaL_error(L, "can't create resmgr object");
 
     rm->resmgr = resmgr;
+    rm->screen_event_handler = screen_event_handler;
 
+    resmgr->scripting_data = rm;
+
+    mrp_resmgr_notifier_register_event_callback(resmgr,
+                                                screen_event_handler_callback);
     lua_settop(L, table);
 
     MRP_LUA_LEAVE(1);
@@ -189,6 +205,14 @@ static int resmgr_getfield(lua_State *L)
             mrp_funcbridge_push(L, area_create);
             break;
 
+        case WINDOW_RAISE:
+            mrp_funcbridge_push(L, window_raise);
+            break;
+
+        case SCREEN_EVENT_HANDLER:
+            mrp_funcbridge_push(L, rm->screen_event_handler);
+            break;
+
         default:
             lua_pushstring(L, fldnam);
             lua_rawget(L, 1);
@@ -229,6 +253,69 @@ static scripting_resmgr_t *resmgr_check(lua_State *L, int idx)
 }
 
 
+static void screen_event_handler_callback(mrp_resmgr_t *resmgr,
+                                   mrp_resmgr_event_t *event)
+{
+    lua_State *L;
+    scripting_resmgr_t *rm;
+    void *sev;
+    mrp_funcbridge_value_t args[4], ret;
+    char t;
+    bool success;
+
+    MRP_ASSERT(resmgr && event, "invalid argument");
+
+    if (!(rm = resmgr->scripting_data)) {
+        mrp_debug("can't deliver resource events to LUA: "
+                  "scripting resource manager was not created yet");
+        return;
+    }
+
+    if (!(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("can't deliver resource events: LUA is not initialesed");
+        return;
+    }
+
+    switch (event->type) {
+
+    case MRP_RESMGR_EVENT_SCREEN:
+        sev = mrp_resmgr_scripting_screen_event_create_from_c(L, event);
+        break;
+
+    case MRP_RESMGR_EVENT_AUDIO:
+        sev = NULL;
+        break;
+
+    case MRP_RESMGR_EVENT_INPUT:
+        sev = NULL;
+        break;
+
+    default:
+        sev = NULL;
+        break;
+    }
+
+    if (!sev) {
+        mrp_debug("can't deliver resource events to LUA: "
+                  "failed to create scripting event");
+        return;
+    }
+
+    args[0].pointer = rm;
+    args[1].pointer = sev;
+
+    memset(&ret, 0, sizeof(ret));
+
+    success = mrp_funcbridge_call_from_c(L, rm->screen_event_handler, "oo",
+                                         args, &t, &ret);
+    if (!success) {
+        mrp_log_error("failed to call resource_manager.screen_event_handler method "
+                      "(%s)", ret.string ? ret.string : "NULL");
+        mrp_free((void *)ret.string);
+    }
+}
+
+
 static bool area_create_bridge(lua_State *L,
                                void *data,
                                const char *signature,
@@ -238,6 +325,7 @@ static bool area_create_bridge(lua_State *L,
 {
     mrp_wayland_area_t *area;
     mrp_resmgr_t *resmgr;
+    const char *zonename;
 
     MRP_UNUSED(L);
     MRP_UNUSED(data);
@@ -246,8 +334,8 @@ static bool area_create_bridge(lua_State *L,
 
     *ret_type = MRP_FUNCBRIDGE_NO_DATA;
 
-    if (strcmp(signature, "oo")) {
-        mrp_log_error("bad signature: expected 'oo' got '%s'",signature);
+    if (strcmp(signature, "oos")) {
+        mrp_log_error("bad signature: expected 'oos' got '%s'",signature);
         return false;
     }
 
@@ -261,11 +349,94 @@ static bool area_create_bridge(lua_State *L,
         return false;
     }
 
+    zonename = args[2].string;
+
+    mrp_resmgr_screen_area_create(resmgr->screen, area, zonename);
 
     return true;
 }
 
 
+static bool window_raise_bridge(lua_State *L,
+                               void *data,
+                               const char *signature,
+                               mrp_funcbridge_value_t *args,
+                               char *ret_type,
+                               mrp_funcbridge_value_t *ret_val)
+{
+    mrp_resmgr_t *resmgr;
+    const char *appid;
+    int32_t surfaceid;
+    int32_t direction;
+
+    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, "osdd")) {
+        mrp_log_error("bad signature: expected 'osdd' 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 (!(appid = args[1].string)) {
+        mrp_log_error("argument 2 is an invalid appid string");
+        return false;
+    }
+
+    if ((surfaceid = args[2].integer) < 0) {
+        mrp_log_error("argument 3 is an invalid surfaceid");
+        return false;
+    }
+
+    direction = args[3].integer;
+
+    if (direction > 0)
+        mrp_screen_resource_raise(resmgr->screen, appid, surfaceid);
+    else if (direction < 0)
+        mrp_screen_resource_lower(resmgr->screen, appid, surfaceid);
+
+    return true;
+}
+
+
+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   , "oos" , NULL),
+        FUNCBRIDGE(window_raise  , "osdd", 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
+}
+
 
 mrp_resmgr_scripting_field_t
 mrp_resmgr_scripting_field_check(lua_State *L,int idx,const char **ret_fldnam)
@@ -294,8 +465,20 @@ mrp_resmgr_scripting_field_name_to_type(const char *name, ssize_t len)
     switch (len) {
 
     case 4:
-        if (!strcmp(name, "name"))
-            return NAME;
+        switch (name[0]) {
+        case 'a':
+            if (!strcmp(name, "appid"))
+                return APPID;
+            if (!strcmp(name, "area"))
+                return AREA;
+            break;
+        case 'n':
+            if (!strcmp(name, "name"))
+                return NAME;
+            break;
+        default:
+            break;
+        }
         break;
 
     case 5:
@@ -304,10 +487,22 @@ mrp_resmgr_scripting_field_name_to_type(const char *name, ssize_t len)
             if (!strcmp(name, "AUDIO"))
                 return AUDIO;
             break;
+        case 'e':
+            if (!strcmp(name, "event"))
+                return EVENT;
+            break;
         case 'i':
             if (!strcmp(name, "input"))
                 return INPUT;
             break;
+        case 'l':
+            if (!strcmp(name, "layer"))
+                return LAYER;
+            break;
+        case 't':
+            if (!strcmp(name, "type"))
+                return TYPE;
+            break;
         default:
             break;
         }
@@ -319,8 +514,18 @@ mrp_resmgr_scripting_field_name_to_type(const char *name, ssize_t len)
         break;
 
     case 7:
-        if (!strcmp(name, "classes"))
-            return CLASSES;
+        switch (name[0]) {
+        case 'c':
+            if (!strcmp(name, "classes"))
+                return CLASSES;
+            break;
+        case 's':
+            if (!strcmp(name, "surface"))
+                return SURFACE;
+            break;
+        default:
+            break;
+        }
         break;
 
     case 9:
@@ -338,38 +543,19 @@ mrp_resmgr_scripting_field_name_to_type(const char *name, ssize_t len)
             return AREA_CREATE;
         break;
 
-    default:
+    case 12:
+        if (!strcmp(name, "window_raise"))
+            return WINDOW_RAISE;
         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;
+    case 20:
+        if (!strcmp(name, "screen_event_handler"))
+            return SCREEN_EVENT_HANDLER;
+        break;
 
-    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;
-        }
+    default:
+        break;
     }
 
-    return success;
-
-#undef FUNCBRIDGE_END
-#undef FUNCBRIDGE
+    return 0;
 }
index da4a4d2..64dd8b4 100644 (file)
@@ -39,7 +39,13 @@ 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);
 
+/* scripting-notifier.c */
+void  mrp_resmgr_scripting_notifier_init(lua_State *L);
+void *mrp_resmgr_scripting_screen_event_create_from_c(lua_State *L,
+                                                    mrp_resmgr_event_t *event);
 
+
+/* internal for scripting-xxx.c */
 mrp_resmgr_scripting_field_t
 mrp_resmgr_scripting_field_check(lua_State *, int, const char **);
 
index d221b90..7c6a1db 100644 (file)
@@ -88,22 +88,29 @@ 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_layer_update_mask_t,
                             mrp_wayland_window_update_t *,
                             mrp_wayland_animation_t *);
 static void set_window_geometry(mrp_wayland_window_t *,
+                                mrp_wayland_layer_update_mask_t,
                                 mrp_wayland_window_update_t *,
                                 mrp_wayland_animation_t *);
 static void set_window_alignment(mrp_wayland_window_t *,
+                                 mrp_wayland_layer_update_mask_t,
                                  mrp_wayland_window_update_t *);
 static void set_window_visible(mrp_wayland_window_t *,
+                               mrp_wayland_layer_update_mask_t,
                                mrp_wayland_window_update_t *,
                                mrp_wayland_animation_t *);
 static void set_window_active(mrp_wayland_window_t *,
+                              mrp_wayland_layer_update_mask_t,
                               mrp_wayland_window_update_t *);
 static void set_window_mapped(mrp_wayland_window_t *,
+                              mrp_wayland_layer_update_mask_t,
                               mrp_wayland_window_update_t *,
                               uint32_t);
 static void set_window_layer(mrp_wayland_window_t *,
+                             mrp_wayland_layer_update_mask_t,
                              mrp_wayland_window_update_t *);
 static void window_request(mrp_wayland_window_t *,
                            mrp_wayland_window_update_t *,
@@ -196,7 +203,7 @@ static void window_created_callback(void *data,
     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);
+              u.surfaceid, u.name, u.pid, u.appid, layertype);
 
     mrp_wayland_window_create(wl, &u);
 }
@@ -215,7 +222,8 @@ static void window_name_callback(void *data,
                "confused with data structures");
 
     if (!winname) {
-        mrp_log_error("Missing window name in %s()", __FUNCTION__);
+        mrp_log_error("system-controller: Missing window name in %s()",
+                      __FUNCTION__);
         return;
     }
 
@@ -261,8 +269,6 @@ static void window_visible_callback(void *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");
@@ -306,9 +312,6 @@ static void window_configure_callback(void *data,
     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");
@@ -326,7 +329,7 @@ static void window_configure_callback(void *data,
     u.mask = MRP_WAYLAND_WINDOW_NODEID_MASK    |
              MRP_WAYLAND_WINDOW_LAYERTYPE_MASK ;
     u.nodeid = node;
-    u.layertype = layertype;
+    u.layertype = get_layer_type(layertype);
 
     if (hint == ICO_WINDOW_MGR_HINT_CHANGE) {
         if (x <= MAX_COORDINATE) {
@@ -348,7 +351,7 @@ static void window_configure_callback(void *data,
     }
 
     if (!(u.layer = mrp_wayland_layer_find(wl, layer)))
-        mrp_log_error("can't find layer %u", layer);
+        mrp_log_error("system-controller: can't find layer %u", layer);
     else
         u.mask |= MRP_WAYLAND_WINDOW_LAYER_MASK;
 
@@ -370,6 +373,11 @@ static void window_active_callback(void *data,
 
     mrp_debug("surfaceid=%u active=%d", surfaceid, active);
 
+    if (!active) {
+        mrp_debug("ignoring active=0 events");
+        return;
+    }
+
     if (!(win = find_window(wm, surfaceid, "state update")))
         return;
 
@@ -377,13 +385,18 @@ static void window_active_callback(void *data,
     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;
+    if ((active & ICO_WINDOW_MGR_ACTIVE_POINTER))
+        u.active |= MRP_WAYLAND_WINDOW_ACTIVE_POINTER;
+    if ((active & ICO_WINDOW_MGR_ACTIVE_KEYBOARD))
+        u.active |= MRP_WAYLAND_WINDOW_ACTIVE_KEYBOARD;
+    if ((active & ICO_WINDOW_MGR_ACTIVE_SELECTED))
+        u.active |= MRP_WAYLAND_WINDOW_ACTIVE_SELECTED;
 
+    if ((win->active & u.active) == u.active) {
+        mrp_debug("window %u already active: nothing to do", surfaceid);
+        return;
+    }
+    
     mrp_wayland_window_update(win, MRP_WAYLAND_WINDOW_ACTIVE, &u);
 }
 
@@ -410,7 +423,7 @@ static void layer_visible_callback(void *data,
     u.visible = visible;
 
     if (!(layer = mrp_wayland_layer_find(wl, layerid))) {
-        mrp_log_error("can't find layer %u", layerid);
+        mrp_log_error("system-controller: can't find layer %u", layerid);
         return;
     }
 
@@ -541,7 +554,8 @@ static mrp_wayland_window_t *find_window(mrp_ico_window_manager_t *wm,
     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);
+        mrp_log_error("system-controller: window %d not found. No %s",
+                      surfaceid, operation);
     }
 
     return win;
@@ -583,6 +597,7 @@ static int32_t set_window_animation(mrp_wayland_window_t *win,
 }
 
 static void set_window_area(mrp_wayland_window_t *win,
+                            mrp_wayland_layer_update_mask_t passthrough,
                             mrp_wayland_window_update_t *u,
                             mrp_wayland_animation_t *anims)
 {
@@ -612,11 +627,13 @@ static void set_window_area(mrp_wayland_window_t *win,
     u->width  = area->width;
     u->height = area->height;
 
-    set_window_geometry(win, u, anims);
+    set_window_geometry(win, passthrough, u, anims);
+    set_window_alignment(win, passthrough, u);
 }
 
 
 static void set_window_geometry(mrp_wayland_window_t *win,
+                                mrp_wayland_layer_update_mask_t passthrough,
                                 mrp_wayland_window_update_t *u,
                                 mrp_wayland_animation_t *anims)
 {
@@ -643,7 +660,9 @@ static void set_window_geometry(mrp_wayland_window_t *win,
                         node != win->nodeid;
 
     need_positioning = false;
-    if (!(mask & MRP_WAYLAND_WINDOW_X_MASK) || (u->x == win->x)) {
+    if (!(mask & MRP_WAYLAND_WINDOW_X_MASK) ||
+        ((u->x == win->x) && !(passthrough & MRP_WAYLAND_WINDOW_X_MASK)))
+    {
         if (!first_time)
             x = ICO_WINDOW_MGR_V_NOCHANGE;
         else {
@@ -655,7 +674,9 @@ static void set_window_geometry(mrp_wayland_window_t *win,
         x = u->x;
         need_positioning = true;
     }
-    if (!(mask & MRP_WAYLAND_WINDOW_Y_MASK) || (u->y == win->y)) {
+    if (!(mask & MRP_WAYLAND_WINDOW_Y_MASK) ||
+        ((u->y == win->y) && !(passthrough & MRP_WAYLAND_WINDOW_Y_MASK)))
+    {
         if (!first_time)
             y = ICO_WINDOW_MGR_V_NOCHANGE;
         else {
@@ -669,24 +690,30 @@ static void set_window_geometry(mrp_wayland_window_t *win,
     }
 
     need_resizing = false;
-    if (!(mask & MRP_WAYLAND_WINDOW_WIDTH_MASK) || (u->width == win->width)) {
+    if (!(mask & MRP_WAYLAND_WINDOW_WIDTH_MASK) ||
+        ((u->width == win->width) &&
+         !(passthrough & MRP_WAYLAND_WINDOW_WIDTH_MASK)))
+    {
         if (!first_time)
             width = ICO_WINDOW_MGR_V_NOCHANGE;
         else {
             width = win->width;
-            need_positioning = true;
+            need_resizing = true;
         }
     }
     else {
         width = u->width;
         need_resizing = true;
     }
-    if (!(mask&MRP_WAYLAND_WINDOW_HEIGHT_MASK) || (u->height == win->height)) {
+    if (!(mask & MRP_WAYLAND_WINDOW_HEIGHT_MASK) ||
+        ((u->height == win->height) &&
+         !(passthrough && MRP_WAYLAND_WINDOW_HEIGHT_MASK)))
+    {
         if (!first_time)
             height = ICO_WINDOW_MGR_V_NOCHANGE;
         else {
             height = win->height;
-            need_positioning = true;
+            need_resizing = true;
         }
     }
     else {
@@ -716,16 +743,19 @@ static void set_window_geometry(mrp_wayland_window_t *win,
 }
 
 static void set_window_alignment(mrp_wayland_window_t *win,
+                                 mrp_wayland_layer_update_mask_t passthrough,
                                  mrp_wayland_window_update_t *u)
 {
     struct ico_window_mgr *ico_window_mgr;
     mrp_wayland_area_t *area;
     uint32_t attrs;
 
+    MRP_UNUSED(passthrough);
+
     ico_window_mgr = (struct ico_window_mgr *)win->wm->proxy;
 
     if (!(area = u->area)) {
-        mrp_log_error("attempt to set NULL area");
+        mrp_log_error("system-controller: attempt to set NULL area");
         return;
     }
 
@@ -777,6 +807,7 @@ static void set_window_alignment(mrp_wayland_window_t *win,
 }
 
 static void set_window_visible(mrp_wayland_window_t *win,
+                               mrp_wayland_layer_update_mask_t passthrough,
                                mrp_wayland_window_update_t *u,
                                mrp_wayland_animation_t *anims)
 {
@@ -794,7 +825,8 @@ static void set_window_visible(mrp_wayland_window_t *win,
 
     need_visibility_change = false;
     if (!(mask & MRP_WAYLAND_WINDOW_VISIBLE_MASK) ||
-        (u->visible && win->visible) || (!u->visible && !win->visible))
+        (((u->visible && win->visible) || (!u->visible && !win->visible)) &&
+         !(passthrough & MRP_WAYLAND_WINDOW_VISIBLE_MASK)))
     {
         visible = ICO_WINDOW_MGR_V_NOCHANGE;
         anim_type = 0;
@@ -810,7 +842,8 @@ static void set_window_visible(mrp_wayland_window_t *win,
 
     need_raising = false;
     if (!(mask & MRP_WAYLAND_WINDOW_RAISE_MASK) ||
-        (u->raise && win->raise) || (!u->raise && !win->raise))
+        (((u->raise && win->raise) || (!u->raise && !win->raise)) &&
+         !(passthrough & MRP_WAYLAND_WINDOW_RAISE_MASK)))
     {
         raise = ICO_WINDOW_MGR_V_NOCHANGE;
     }
@@ -840,33 +873,38 @@ static void set_window_visible(mrp_wayland_window_t *win,
 }
 
 static void set_window_active(mrp_wayland_window_t *win,
+                              mrp_wayland_layer_update_mask_t passthrough,
                               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)
+    if ((u->active == win->active) &&
+        !(passthrough & MRP_WAYLAND_WINDOW_ACTIVE_MASK))
+    {
         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;
+        return;
+    }
+
+    active = 0;
 
-        mrp_debug("calling ico_window_mgr_set_active"
-                  "(surfaceid=%d, active=0x%x)",
-                  win->surfaceid, active);
+    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;
 
-        ico_window_mgr_set_active(ico_window_mgr, win->surfaceid, active);
-    }
+    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_layer_update_mask_t passthrough,
                               mrp_wayland_window_update_t *u,
                               uint32_t framerate)
 {
@@ -874,8 +912,11 @@ static void set_window_mapped(mrp_wayland_window_t *win,
 
     ico_window_mgr = (struct ico_window_mgr *)win->wm->proxy;
 
-    if ((u->mapped && win->mapped) || (!u->mapped && !win->mapped))
+    if (((u->mapped && win->mapped) || (!u->mapped && !win->mapped)) &&
+        !(passthrough & MRP_WAYLAND_WINDOW_MAPPED_MASK))
+    {
         mrp_debug("nothing to do");
+    }
     else {
         if (u->mapped) {
             mrp_debug("calling ico_window_mgr_map_surface"
@@ -895,6 +936,7 @@ static void set_window_mapped(mrp_wayland_window_t *win,
 }
 
 static void set_window_layer(mrp_wayland_window_t *win,
+                             mrp_wayland_layer_update_mask_t passthrough,
                              mrp_wayland_window_update_t *u)
 {
     struct ico_window_mgr *ico_window_mgr;
@@ -902,7 +944,9 @@ static void set_window_layer(mrp_wayland_window_t *win,
 
     ico_window_mgr = (struct ico_window_mgr *)win->wm->proxy;
 
-    if (win->layer && (u->layer == win->layer)) {
+    if (win->layer && (u->layer == win->layer) &&
+        !(passthrough & MRP_WAYLAND_WINDOW_LAYER_MASK))
+    {
         mrp_debug("nothing to do");
     }
     else {
@@ -935,10 +979,10 @@ static void window_request(mrp_wayland_window_t *win,
         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_manager_t *wm;
+    mrp_wayland_layer_update_mask_t passthrough;
     mrp_wayland_window_update_mask_t mask;
     char wbuf[2048];
     char abuf[1024];
@@ -946,7 +990,9 @@ static void window_request(mrp_wayland_window_t *win,
     MRP_ASSERT(win && win->wm && win->wm->proxy && win->wm->interface &&
                win->wm->interface->wl, "invalid argument");
 
-    wl = win->wm->interface->wl;
+    wm = win->wm;
+    wl = wm->interface->wl;
+    passthrough = wm->passthrough.request;
     mask = u->mask;
 
     mrp_wayland_window_request_print(u, wbuf, sizeof(wbuf));
@@ -956,31 +1002,27 @@ static void window_request(mrp_wayland_window_t *win,
 
     while (mask) {
         if ((mask & layer_mask)) {
-            set_window_layer(win, u);
+            set_window_layer(win, passthrough, u);
             mask &= ~layer_mask;
         }
         else if ((mask & mapped_mask)) {
-            set_window_mapped(win, u, framerate);
+            set_window_mapped(win, passthrough, u, framerate);
             mask &= ~mapped_mask;
         }
         else if ((mask & area_mask))  {
-            set_window_area(win, u, anims);
+            set_window_area(win, passthrough, u, anims);
             mask &= ~(area_mask | geometry_mask);
         }
         else if ((mask & geometry_mask)) {
-            set_window_geometry(win, u, anims);
+            set_window_geometry(win, passthrough, 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);
+            set_window_visible(win, passthrough, u, anims);
             mask &= ~visible_mask;
         }
         else if ((mask & active_mask)) {
-            set_window_active(win, u);
+            set_window_active(win, passthrough, u);
             mask &= ~active_mask;
         }
         else {
index a5a4fef..2984b97 100644 (file)
@@ -125,28 +125,6 @@ mrp_wayland_layer_t *mrp_wayland_layer_find(mrp_wayland_t *wl, int32_t layerid)
     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;
index 7e6e658..5dc783d 100644 (file)
@@ -48,9 +48,9 @@ enum mrp_wayland_layer_type_e {
 
 enum mrp_wayland_layer_operation_e {
     MRP_WAYLAND_LAYER_OPERATION_NONE = 0,
-    MRP_WAYLAND_LAYER_CREATE,
-    MRP_WAYLAND_LAYER_DESTROY,
-    MRP_WAYLAND_LAYER_VISIBLE
+    MRP_WAYLAND_LAYER_CREATE,       /* 1 */
+    MRP_WAYLAND_LAYER_DESTROY,      /* 2 */
+    MRP_WAYLAND_LAYER_VISIBLE       /* 3 */
 };
 
 struct mrp_wayland_layer_s {
@@ -91,8 +91,6 @@ 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);
index bac8e7a..629e297 100644 (file)
@@ -274,8 +274,6 @@ int mrp_wayland_json_align_copy(mrp_wayland_t *wl, void *uval,
     return mask;
 }
 
-
-
 mrp_wayland_scripting_field_t
 mrp_wayland_scripting_field_check(lua_State *L,int idx,const char **ret_fldnam)
 {
@@ -560,6 +558,10 @@ mrp_wayland_scripting_field_name_to_type(const char *name, ssize_t len)
 
     case 14:
         switch (name[0]) {
+        case 'm':
+            if (!strcmp(name, "manager_update"))
+                return MANAGER_UPDATE;
+            break;
         case 'o':
             if (!strcmp(name, "output_request"))
                 return OUTPUT_REQUEST;
@@ -575,6 +577,21 @@ mrp_wayland_scripting_field_name_to_type(const char *name, ssize_t len)
         }
         break;
 
+    case 15:
+        if (!strcmp(name, "manager_request"))
+            return MANAGER_REQUEST;
+        break;
+
+    case 18:
+        if (!strcmp(name, "passthrough_update"))
+            return PASSTHROUGH_UPDATE;
+        break;
+
+    case 19:
+        if (!strcmp(name, "passthrough_request"))
+            return PASSTHROUGH_REQUEST;
+        break;
+
     default:
         break;
     }
index 5443eae..652fc32 100644 (file)
@@ -50,6 +50,7 @@
 #include "layer.h"
 #include "output.h"
 #include "area.h"
+#include "window-manager.h"
 #include "ico-window-manager.h"
 
 #define WINDOW_MANAGER_CLASS   MRP_LUA_CLASS_SIMPLE(window_manager)
@@ -63,6 +64,7 @@ struct scripting_winmgr_s {
     mrp_wayland_t *wl;
     const char *name;
     const char *display;
+    mrp_funcbridge_t *manager_update;
     mrp_funcbridge_t *output_update;
     mrp_funcbridge_t *layer_update;
     mrp_funcbridge_t *window_update;
@@ -104,6 +106,13 @@ static layer_def_t *layer_def_check(lua_State *, int);
 static void layer_def_free(layer_def_t *);
 
 
+static bool manager_request_bridge(lua_State *, void *,
+                                   const char *, mrp_funcbridge_value_t *,
+                                   char *, mrp_funcbridge_value_t *);
+static void manager_update_callback(mrp_wayland_t *,
+                                    mrp_wayland_window_manager_operation_t,
+                                    mrp_wayland_window_manager_t *);
+
 static bool window_request_bridge(lua_State *, void *,
                                   const char *, mrp_funcbridge_value_t *,
                                   char *, mrp_funcbridge_value_t *);
@@ -153,6 +162,7 @@ MRP_LUA_CLASS_DEF_SIMPLE (
     )
 );
 
+static mrp_funcbridge_t *manager_request;
 static mrp_funcbridge_t *output_request;
 static mrp_funcbridge_t *area_create;
 static mrp_funcbridge_t *layer_request;
@@ -202,6 +212,7 @@ static int window_manager_create(lua_State *L)
     char *name;
     const char *display = NULL;
     layer_def_t *layers = NULL;
+    mrp_funcbridge_t *manager_update = NULL;
     mrp_funcbridge_t *output_update = NULL;
     mrp_funcbridge_t *layer_update = NULL;
     mrp_funcbridge_t *window_update = NULL;
@@ -235,6 +246,10 @@ static int window_manager_create(lua_State *L)
             layers = layer_def_check(L, -1);
             break;
 
+        case MANAGER_UPDATE:
+            manager_update = mrp_funcbridge_create_luafunc(L, -1);
+            break;
+
         case OUTPUT_UPDATE:
             output_update = mrp_funcbridge_create_luafunc(L, -1);
             break;
@@ -245,7 +260,7 @@ static int window_manager_create(lua_State *L)
 
         case WINDOW_UPDATE:
             window_update = mrp_funcbridge_create_luafunc(L, -1);
-            break;            
+            break;
 
         default:
             lua_pushvalue(L, -2);
@@ -271,6 +286,7 @@ static int window_manager_create(lua_State *L)
     winmgr->wl = wl;
     winmgr->name = mrp_strdup(name);
     winmgr->display = mrp_strdup(display);
+    winmgr->manager_update = manager_update;
     winmgr->output_update = output_update;
     winmgr->layer_update = layer_update;
     winmgr->window_update = window_update;
@@ -278,6 +294,8 @@ static int window_manager_create(lua_State *L)
     mrp_wayland_output_register(wl);
     mrp_ico_window_manager_register(wl);
 
+    mrp_wayland_register_window_manager_update_callback(wl,
+                                                   manager_update_callback);
     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);
@@ -350,8 +368,10 @@ static int  window_manager_canonical_name(lua_State *L)
 static int window_manager_getfield(lua_State *L)
 {
     scripting_winmgr_t *wmgr;
+    mrp_wayland_t *wl;
     const char *fldnam;
     mrp_wayland_scripting_field_t fld;
+    uint32_t mask;
 
     MRP_LUA_ENTER;
 
@@ -360,7 +380,7 @@ static int window_manager_getfield(lua_State *L)
 
     wmgr = window_manager_check(L, 1);
 
-    if (!wmgr)
+    if (!wmgr || !(wl = wmgr->wl))
         lua_pushnil(L);
     else {
         switch (fld) {
@@ -369,6 +389,14 @@ static int window_manager_getfield(lua_State *L)
             lua_pushstring(L, wmgr->display);
             break;
 
+        case MANAGER_REQUEST:
+            mrp_funcbridge_push(L, manager_request);
+            break;
+
+        case MANAGER_UPDATE:
+            mrp_funcbridge_push(L, wmgr->manager_update);
+            break;
+
         case OUTPUT_REQUEST:
             mrp_funcbridge_push(L, output_request);
             break;
@@ -397,6 +425,19 @@ static int window_manager_getfield(lua_State *L)
             mrp_funcbridge_push(L, wmgr->window_update);
             break;
 
+        case PASSTHROUGH_REQUEST:
+            mask = (wl->wm ? wl->wm->passthrough.request : 0);
+            goto push_mask;
+
+        case PASSTHROUGH_UPDATE:
+            mask = (wl->wm ? wl->wm->passthrough.update : 0);
+            goto push_mask;
+
+        push_mask:
+            if (!mrp_wayland_scripting_window_mask_create_from_c(L, mask))
+                lua_pushnil(L);
+            break;
+
         default:
             lua_pushstring(L, fldnam);
             lua_rawget(L, 1);
@@ -507,6 +548,121 @@ static void layer_def_free(layer_def_t *layers)
     }
 }
 
+static bool manager_request_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_t *wl;
+    mrp_wayland_window_manager_t *wm;
+    mrp_json_t *json;
+    const char *key;
+    mrp_json_t *val;
+    mrp_json_iter_t it;
+    int32_t mask;
+
+    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("system-controller: bad signature: "
+                      "expected 'oo' got '%s'", signature);
+        return false;
+    }
+
+    if (!(wl = mrp_wayland_scripting_window_manager_unwrap(args[0].pointer))) {
+        mrp_log_error("system-controller: argument 1 is not a "
+                      "'window_manager' class object");
+        return false;
+    }
+
+    if (!(wm = wl->wm)) {
+        mrp_log_error("system-controller: 'window_manager' is not initilized");
+        return false;
+    }
+
+    if (!(json = mrp_json_lua_unwrap(args[1].pointer))) {
+        mrp_log_error("system-controller: argument 2 is not a "
+                      "'JSON' class object");
+        return false;
+    }
+
+    mrp_json_foreach_member(json, key,val, it) {
+        switch (mrp_wayland_scripting_field_name_to_type(key, -1)) {
+
+        case PASSTHROUGH_REQUEST:
+            if (!mrp_wayland_json_integer_copy(wl, &mask, val, 1))
+                mrp_debug("'%s' field has invalid value", key);
+            else {
+                mrp_debug("set passthrough.request to 0x%x", mask);
+                wm->passthrough.request = mask;
+            }
+            break;
+
+        case PASSTHROUGH_UPDATE:
+            if (!mrp_wayland_json_integer_copy(wl, &mask, val, 1))
+                mrp_debug("'%s' field has invalid value", key);
+            else {
+                mrp_debug("set passthrough.update to 0x%x", mask);
+                wm->passthrough.update = mask;
+            }
+            break;
+
+        default:
+            mrp_debug("ignoring JSON field '%s'", key);
+            break;
+        }
+    }
+
+    return true;
+}
+
+static void manager_update_callback(mrp_wayland_t *wl,
+                                   mrp_wayland_window_manager_operation_t oper,
+                                   mrp_wayland_window_manager_t *wm)
+{
+    lua_State *L;
+    scripting_winmgr_t *winmgr;
+    mrp_funcbridge_value_t args[4], ret;
+    char t;
+    bool success;
+
+    MRP_ASSERT(wl && wm, "invalid argument");
+
+    if (!(L = mrp_lua_get_lua_state())) {
+        mrp_log_error("sysem-controller: can't update manager: "
+                      "LUA is not initialesed");
+        return;
+    }
+
+    if (!(winmgr = (scripting_winmgr_t *)wl->scripting_data)) {
+        mrp_log_error("system-controller: window manager "
+                      "scripting is not initialized");
+        return;
+    }
+
+    MRP_ASSERT(wl == winmgr->wl, "confused with data structures");
+
+    args[0].pointer = winmgr;
+    args[1].integer = oper;
+
+    memset(&ret, 0, sizeof(ret));
+
+    success = mrp_funcbridge_call_from_c(L, winmgr->manager_update, "od",
+                                         args, &t, &ret);
+    if (!success) {
+        mrp_log_error("failed to call window_manager.%s.manager_update method "
+                      "(%s)", winmgr->name, ret.string ? ret.string : "NULL");
+        mrp_free((void *)ret.string);
+    }
+}
+
 static bool window_request_bridge(lua_State *L,
                                   void *data,
                                   const char *signature,
@@ -551,28 +707,32 @@ static bool window_request_bridge(lua_State *L,
     *ret_type = MRP_FUNCBRIDGE_NO_DATA;
 
     if (strcmp(signature, "oood")) {
-        mrp_log_error("bad signature: expected 'oood' got '%s'",signature);
+        mrp_log_error("system-controller: 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");
+        mrp_log_error("system-controller: 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");
+        mrp_log_error("system-controller: 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");
+        mrp_log_error("system-controller: 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);
+        mrp_log_error("system-controller: argument 3 is not valid framerate "
+                      "(out of range 0-%d)", MRP_WAYLAND_FRAMERATE_MAX);
         return false;
     }
 
@@ -600,20 +760,22 @@ static void window_update_callback(mrp_wayland_t *wl,
     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);
+        mrp_log_error("system-controller: 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");
+        mrp_log_error("system-controller: 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);
+        mrp_log_error("system-controller: no scripting data for "
+                      "window %d", win->surfaceid);
         return;
     }
 
@@ -851,6 +1013,8 @@ static bool layer_request_bridge(lua_State *L,
     memset(&u, 0, sizeof(u));
     u.mask = copy_json_fields(wl, json, fields, &u);
 
+    mrp_wayland_layer_request(wl, &u);
+
     return true;
 }
 
@@ -912,12 +1076,14 @@ static uint32_t copy_json_fields(mrp_wayland_t *wl,
     mrp_json_iter_t it;
     request_def_t *f;
     uint32_t m, mask;
+    bool found;
 
     mask = 0;
 
     mrp_json_foreach_member(json, key,val, it) {
-        for (f = fields;   f->name;   f++) {
+        for (f = fields, found = false;   f->name;   f++) {
             if (!strcmp(key, f->name)) {
+                found = true;
                 if ((m = f->copy(wl, copy + f->offset, val, f->mask)))
                     mask |= m;
                 else
@@ -925,6 +1091,8 @@ static uint32_t copy_json_fields(mrp_wayland_t *wl,
                 break;
             }
         }
+        if (!found)
+            mrp_debug("ignoring JSON field '%s'", key);
     }
 
     return mask;
@@ -937,10 +1105,11 @@ static bool register_methods(lua_State *L)
 #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(manager_request, "oo"  , NULL),
+        FUNCBRIDGE(output_request , "oo"  , NULL),
+        FUNCBRIDGE(area_create    , "oo"  , NULL),
+        FUNCBRIDGE(layer_request  , "oo"  , NULL),
+        FUNCBRIDGE(window_request , "oood", NULL),
         FUNCBRIDGE_END
     };
 
index 5aac1bb..af637ed 100644 (file)
@@ -74,6 +74,7 @@ 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 int  window_mask_tointeger(lua_State *);
 static void window_mask_destroy(void *);
 
 static scripting_window_mask_t *window_mask_check(lua_State *, int);
@@ -102,6 +103,7 @@ MRP_LUA_CLASS_DEF_SIMPLE (
     window_mask_destroy,        /* userdata destructor */
     MRP_LUA_METHOD_LIST (       /* methods */
        MRP_LUA_METHOD_CONSTRUCTOR (window_mask_create_from_lua)
+       MRP_LUA_METHOD(tointeger,   window_mask_tointeger)
     ),
     MRP_LUA_METHOD_LIST (       /* overrides */
        MRP_LUA_OVERRIDE_CALL      (window_mask_create_from_lua)
@@ -363,7 +365,7 @@ static int window_mask_create_from_lua(lua_State *L)
         if (fld == MASK)
             mask = lua_tointeger(L, -1);
         else if ((m = get_window_mask(fld)))
-            mask |= m;
+            mask |= lua_toboolean(L, -1) ? m : 0;
         else
             luaL_error(L, "bad field '%s'", fldnam);
     }
@@ -463,6 +465,18 @@ static int window_mask_stringify(lua_State *L)
     MRP_LUA_LEAVE(1);
 }
 
+static int window_mask_tointeger(lua_State *L)
+{
+    scripting_window_mask_t *um;
+
+    MRP_LUA_ENTER;
+
+    um = window_mask_check(L, 1);
+    lua_pushinteger(L, um->mask);
+
+    MRP_LUA_LEAVE(1);
+}
+
 static void window_mask_destroy(void *data)
 {
     scripting_window_mask_t *um = (scripting_window_mask_t *)data;
index 7914ca3..965cffe 100644 (file)
@@ -39,6 +39,7 @@
 #include "wayland.h"
 #include "output.h"
 #include "layer.h"
+#include "window-manager.h"
 
 
 static uint32_t oid_hash(const void *);
@@ -250,6 +251,12 @@ void mrp_wayland_register_window_manager(mrp_wayland_t *wl,
     wl->wm = wm;
 
     mrp_htbl_foreach(wl->layers, update_layers, wm);
+
+    if (wl->window_manager_update_callback) {
+        wl->window_manager_update_callback(wl,
+                                           MRP_WAYLAND_WINDOW_MANAGER_CREATE,
+                                           wm);
+    }
 }
 
 
@@ -293,6 +300,16 @@ bool mrp_wayland_register_interface(mrp_wayland_t *wl,
     return true;
 }
 
+void mrp_wayland_register_window_manager_update_callback(mrp_wayland_t *wl,
+                         mrp_wayland_window_manager_update_callback_t callback)
+{
+    MRP_ASSERT(wl, "invalid aruments");
+
+    mrp_debug("registering window_manager_update_callback");
+
+    wl->window_manager_update_callback = callback;
+}
+
 void mrp_wayland_register_output_update_callback(mrp_wayland_t *wl,
                                mrp_wayland_output_update_callback_t callback)
 {
index d284a1d..5676471 100644 (file)
@@ -74,6 +74,8 @@ 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 enum mrp_wayland_window_manager_operation_e
+                                              mrp_wayland_window_manager_operation_t;
 
 typedef struct mrp_wayland_s                  mrp_wayland_t;
 typedef struct mrp_wayland_factory_s          mrp_wayland_factory_t;
@@ -97,26 +99,29 @@ 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_window_manager_update_callback_t)(mrp_wayland_t *,
+                                        mrp_wayland_window_manager_operation_t,
+                                        mrp_wayland_window_manager_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 *);
+                                        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 *);
+                                        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 *);
+                                        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 *);
+                                        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 *);
+                                        mrp_application_operation_t,
+                                        mrp_application_update_mask_t,
+                                        mrp_application_t *);
 
 
 struct mrp_wayland_s {
@@ -139,6 +144,7 @@ struct mrp_wayland_s {
     mrp_wayland_window_manager_t *wm;
     mrp_wayland_input_manager_t *im;
 
+    mrp_wayland_window_manager_update_callback_t window_manager_update_callback;
     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;
@@ -183,14 +189,17 @@ 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_window_manager_update_callback(mrp_wayland_t *wl,
+                        mrp_wayland_window_manager_update_callback_t callback);
 void mrp_wayland_register_output_update_callback(mrp_wayland_t *wl,
-                               mrp_wayland_output_update_callback_t callback);
+                        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);
+                        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);
+                        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);
+                        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);
index 90032e1..d2410a0 100644 (file)
 
 #include <sys/types.h>
 
-#include "wayland/wayland.h"
+#include "wayland/window.h"
+
+enum mrp_wayland_window_manager_operation_e {
+    MRP_WAYLAND_WINDOW_MANAGER_OPERATION_NONE = 0,
+    MRP_WAYLAND_WINDOW_MANAGER_CREATE,       /* 1 */
+    MRP_WAYLAND_WINDOW_MANAGER_DESTROY,      /* 2 */
+};
 
 #define MRP_WAYLAND_WINDOW_MANAGER_COMMON                               \
     MRP_WAYLAND_OBJECT_COMMON;                                          \
     void (*window_request)(mrp_wayland_window_t *,                      \
                            mrp_wayland_window_update_t *,               \
                            mrp_wayland_animation_t *,                   \
-                           uint32_t)
+                           uint32_t);                                   \
+    struct {                                                            \
+        mrp_wayland_window_update_mask_t request;                       \
+        mrp_wayland_window_update_mask_t update;                        \
+    } passthrough
+
 
 struct mrp_wayland_window_manager_s {
     MRP_WAYLAND_WINDOW_MANAGER_COMMON;
index 76c38cc..bfbc7b2 100644 (file)
 
 typedef struct {
     mrp_wayland_window_t *win;
+    mrp_wayland_window_operation_t oper;
     int32_t state;
-} update_active_t;
+    bool raise;
+} update_others_t;
 
 static mrp_wayland_window_update_mask_t update(mrp_wayland_window_t *,
                                                mrp_wayland_window_update_t *);
@@ -159,182 +161,6 @@ mrp_wayland_window_t *mrp_wayland_window_find(mrp_wayland_t *wl,
 }
 
 
-#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,
@@ -343,6 +169,7 @@ void mrp_wayland_window_request(mrp_wayland_t *wl,
 {
     mrp_wayland_window_t *win;
     mrp_wayland_window_manager_t *wm;
+    char buf[4096];
 
     MRP_ASSERT(wl && u, "invalid arguments");
 
@@ -355,26 +182,45 @@ void mrp_wayland_window_request(mrp_wayland_t *wl,
 
     MRP_ASSERT(win->wm, "confused with data structures");
 
+    mrp_wayland_window_request_print(u, buf,sizeof(buf));
+    mrp_debug("window %d%s", u->surfaceid, buf);
+
     wm = win->wm;
 
     wm->window_request(win, u, anims, framerate);
 }
 
-static int update_active(void *key, void *object, void *ud)
+static int update_others(void *key, void *object, void *ud)
 {
     mrp_wayland_window_t *win = (mrp_wayland_window_t *)object;
-    update_active_t *active = (update_active_t *)ud;
+    update_others_t *uo = (update_others_t *)ud;
 
     MRP_UNUSED(key);
 
-    if (win != active->win) {
-        if (active->state == 0)
-            win->active = 0;
-        else
-            win->active &= ~active->state;
+    if (win != uo->win) {        
+        switch (uo->oper) {
+
+        case MRP_WAYLAND_WINDOW_ACTIVE:
+            if (uo->state == 0)
+                win->active = 0;
+            else
+                win->active &= ~uo->state;
+
+            mrp_debug("setting window %d 'active' to 0x%x",
+                      win->surfaceid, win->active);
+            break;
+
+        case MRP_WAYLAND_WINDOW_VISIBLE:
+            if (uo->raise)
+                win->raise = false;
 
-        mrp_debug("setting window %d 'active' to 0x%x",
-                  win->surfaceid, win->active); 
+            mrp_debug("setting window %d 'raise' to %s",
+                      win->surfaceid, win->raise ? "true" : "false");
+            break;
+
+        default:
+            break;
+        }
     }
 
     return MRP_HTBL_ITER_MORE;
@@ -390,7 +236,7 @@ void mrp_wayland_window_update(mrp_wayland_window_t *win,
     int32_t surfaceid;
     mrp_wayland_window_update_mask_t mask;
     char buf[2048];
-    update_active_t active;
+    update_others_t uo;
 
     MRP_ASSERT(win && win->wm && win->wm->interface &&
                win->wm->interface->wl && u, "invalid argument");
@@ -411,20 +257,42 @@ void mrp_wayland_window_update(mrp_wayland_window_t *win,
 
      mask = update(win, u);
 
-    if (!mask)
+     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);
-    }
+        return;
+     }
+
+     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);
+
+    memset(&uo, 0, sizeof(uo));
+    uo.win = win;
+    uo.oper = oper;
+
+    switch (oper) {
+
+    case MRP_WAYLAND_WINDOW_ACTIVE:
+        uo.state = win->active;
+        goto update_loop;
+
+    case MRP_WAYLAND_WINDOW_VISIBLE:
+        if ((mask & MRP_WAYLAND_WINDOW_RAISE_MASK) && win->raise) {
+            uo.raise = true;
+            goto update_loop;
+        }
+        break;
+
+
+    default:
+        break;
+
+    update_loop:
+        mrp_htbl_foreach(wl->windows, update_others, &uo);
+        break;
     }
 }
 
@@ -575,9 +443,12 @@ 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;
+    mrp_wayland_window_update_mask_t passthrough = win->wm->passthrough.update;
 
     if ((u->mask & MRP_WAYLAND_WINDOW_NAME_MASK)) {
-        if (!win->name || strcmp(u->name, win->name)) {
+        if (!win->name || strcmp(u->name, win->name) ||
+            (passthrough & MRP_WAYLAND_WINDOW_NAME_MASK))
+        {
             mask |= MRP_WAYLAND_WINDOW_NAME_MASK;
             mrp_free(win->name);
             win->name = mrp_strdup(u->name);
@@ -585,7 +456,8 @@ static mrp_wayland_window_update_mask_t update(mrp_wayland_window_t *win,
     }
 
     if ((u->mask & MRP_WAYLAND_WINDOW_APPID_MASK)) {
-        if (!win->appid || strcmp(u->appid, win->appid)) {
+        if (!win->appid || strcmp(u->appid, win->appid) ||
+            (passthrough & MRP_WAYLAND_WINDOW_APPID_MASK)) {
             mask |= MRP_WAYLAND_WINDOW_APPID_MASK;
             mrp_free(win->appid);
             win->appid = mrp_strdup(u->appid);
@@ -593,56 +465,72 @@ static mrp_wayland_window_update_mask_t update(mrp_wayland_window_t *win,
     }
 
     if ((u->mask & MRP_WAYLAND_WINDOW_PID_MASK)) {
-        if (u->pid != win->pid) {
+        if (u->pid != win->pid ||
+            (passthrough & MRP_WAYLAND_WINDOW_PID_MASK))
+        {
             mask |= MRP_WAYLAND_WINDOW_PID_MASK;
             win->pid = u->pid;
         }
     }
 
     if ((u->mask & MRP_WAYLAND_WINDOW_NODEID_MASK)) {
-        if (u->nodeid != win->nodeid) {
+        if (u->nodeid != win->nodeid ||
+            (passthrough & MRP_WAYLAND_WINDOW_NODEID_MASK))
+        {
             mask |= MRP_WAYLAND_WINDOW_NODEID_MASK;
             win->nodeid = u->nodeid;
         }
     }
 
     if ((u->mask & MRP_WAYLAND_WINDOW_LAYER_MASK)) {
-        if (u->layer != win->layer) {
+        if (u->layer != win->layer ||
+            (passthrough & MRP_WAYLAND_WINDOW_LAYER_MASK))
+        {
             mask |= MRP_WAYLAND_WINDOW_LAYER_MASK;
             win->layer = u->layer;
         }
     }
 
     if ((u->mask & MRP_WAYLAND_WINDOW_X_MASK)) {
-        if (u->x != win->x) {
+        if (u->x != win->x ||
+            (passthrough & MRP_WAYLAND_WINDOW_X_MASK))
+        {
             mask |= MRP_WAYLAND_WINDOW_POSITION_MASK;
             win->x = u->x;
         }
     }
 
     if ((u->mask & MRP_WAYLAND_WINDOW_Y_MASK)) {
-        if (u->y != win->y) {
+        if (u->y != win->y ||
+            (passthrough & MRP_WAYLAND_WINDOW_Y_MASK))
+        {
             mask |= MRP_WAYLAND_WINDOW_POSITION_MASK;
             win->y = u->y;
         }
     }
 
     if ((u->mask & MRP_WAYLAND_WINDOW_WIDTH_MASK)) {
-        if (u->width != win->width) {
+        if (u->width != win->width ||
+            (passthrough & MRP_WAYLAND_WINDOW_WIDTH_MASK))
+        {
             mask |= MRP_WAYLAND_WINDOW_SIZE_MASK;
             win->width = u->width;
         }
     }
 
     if ((u->mask & MRP_WAYLAND_WINDOW_HEIGHT_MASK)) {
-        if (u->height != win->height) {
+        if (u->height != win->height ||
+            (passthrough & MRP_WAYLAND_WINDOW_HEIGHT_MASK))
+        {
             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)) {
+        if ((u->visible && !win->visible) || (!u->visible && win->visible) ||
+            (passthrough & MRP_WAYLAND_WINDOW_VISIBLE_MASK))
+        {
             mask |= MRP_WAYLAND_WINDOW_VISIBLE_MASK |
                     MRP_WAYLAND_WINDOW_RAISE_MASK   ;
             win->visible = u->visible;
@@ -650,7 +538,9 @@ static mrp_wayland_window_update_mask_t update(mrp_wayland_window_t *win,
     }
 
     if ((u->mask & MRP_WAYLAND_WINDOW_RAISE_MASK)) {
-        if ((u->raise && !win->raise) || (!u->raise && win->raise)) {
+        if ((u->raise && !win->raise) || (!u->raise && win->raise) ||
+            (passthrough & MRP_WAYLAND_WINDOW_RAISE_MASK))
+        {
             mask |= MRP_WAYLAND_WINDOW_RAISE_MASK   |
                     MRP_WAYLAND_WINDOW_VISIBLE_MASK ;
             win->raise = u->raise;
@@ -658,21 +548,27 @@ static mrp_wayland_window_update_mask_t update(mrp_wayland_window_t *win,
     }
 
     if ((u->mask & MRP_WAYLAND_WINDOW_MAPPED_MASK)) {
-        if ((u->mapped && !win->mapped) || (!u->mapped && win->mapped)) {
+        if ((u->mapped && !win->mapped) || (!u->mapped && win->mapped) ||
+            (passthrough & MRP_WAYLAND_WINDOW_MAPPED_MASK))
+        {
             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)) {
+        if (u->active != win->active ||
+            (passthrough & MRP_WAYLAND_WINDOW_ACTIVE_MASK))
+        {
             mask |= MRP_WAYLAND_WINDOW_ACTIVE_MASK;
             win->active = u->active;
         }
     }
 
     if ((u->mask & MRP_WAYLAND_WINDOW_LAYERTYPE_MASK)) {
-        if ((u->layertype != win->layertype)) {
+        if (u->layertype != win->layertype ||
+            (passthrough & MRP_WAYLAND_WINDOW_LAYERTYPE_MASK))
+        {
             mask |= MRP_WAYLAND_WINDOW_LAYERTYPE_MASK;
             win->layertype = u->layertype;
         }
@@ -721,6 +617,21 @@ static mrp_wayland_window_update_mask_t set_appid(mrp_wayland_window_t *win,
 
     mrp_debug("found area '%s'", u2.area->name);
 
+#if 0
+    if (u->layertype == MRP_WAYLAND_LAYER_TYPE_UNKNOWN ||
+        u->layertype == MRP_WAYLAND_LAYER_INPUT        ||
+        u->layertype == MRP_WAYLAND_LAYER_TOUCH        ||
+        u->layertype == MRP_WAYLAND_LAYER_CURSOR        )
+    {
+        win->area = u2.area;
+        win->x = u2.area->x;
+        win->y = u2.area->y;
+        win->width = u2.area->width;
+        win->height = u2.area->height;
+        return mask;
+    }
+#endif
+
     u2.mask |= MRP_WAYLAND_WINDOW_AREA_MASK;
 
     if (!(mask & MRP_WAYLAND_WINDOW_POSITION_MASK)) {
@@ -751,7 +662,7 @@ static mrp_wayland_window_update_mask_t set_appid(mrp_wayland_window_t *win,
 
     return mask;
 }
-                                   
+
 
 static char *active_str(mrp_wayland_active_t active, char *buf, size_t len)
 {
index bc34304..210de6c 100644 (file)
@@ -128,27 +128,6 @@ 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,