func (m *EntryManager) listenDockedApp() {
	if DOCKED_APP_MANAGER == nil {
		var err error
		DOCKED_APP_MANAGER, err = dock.NewDockedAppManager(
			"com.deepin.daemon.Dock",
			"/dde/dock/DockedAppManager",
		)
		if err != nil {
			logger.Warning("get DockedAppManager failed", err)
			return
		}
	}

	DOCKED_APP_MANAGER.ConnectDocked(func(id string) {
		if _, ok := m.normalApps[id]; ok {
			logger.Info(id, "is already docked")
			return
		}
		m.createNormalApp(id)
	})

	DOCKED_APP_MANAGER.ConnectUndocked(func(id string) {
		// undocked is operated on normal app
		logger.Info("ConnectUndocked: Undock", id)
		if app, ok := m.normalApps[id]; ok {
			logger.Info("destroy normal app")
			m.destroyNormalApp(app)
		}
	})
}
func loadAll() []string {
	DOCKED_APP_MANAGER, err := dock.NewDockedAppManager(
		"com.deepin.daemon.Dock",
		"/dde/dock/DockedAppManager",
	)
	if err != nil {
		logger.Warning("get DockedAppManager failed", err)
		return make([]string, 0)
	}

	l, _ := DOCKED_APP_MANAGER.DockedAppList()
	return l
}
func (app *RuntimeApp) buildMenu() {
	app.coreMenu = NewMenu()
	itemName := strings.Title(app.Id)
	core := app.createDesktopAppInfo()
	if core != nil {
		itemName = strings.Title(core.GetDisplayName())
		defer core.Unref()
	}
	app.coreMenu.AppendItem(NewMenuItem(
		itemName,
		func() {
			var a *gio.AppInfo
			logger.Debug(itemName)
			core := app.createDesktopAppInfo()
			if core != nil {
				logger.Debug("DesktopAppInfo")
				a = (*gio.AppInfo)(core.DesktopAppInfo)
				defer core.Unref()
			} else {
				logger.Debug("Non-DesktopAppInfo", app.exec)
				var err error = nil
				a, err = gio.AppInfoCreateFromCommandline(
					app.exec,
					"",
					gio.AppInfoCreateFlagsNone,
				)
				if err != nil {
					logger.Warning("Launch App Falied: ", err)
					return
				}

				defer a.Unref()
			}

			if a == nil {
				logger.Warning("create app info to run program failed")
				return
			}

			_, err := a.Launch(make([]*gio.File, 0), nil)
			if err != nil {
				logger.Warning("Launch App Failed: ", err)
			}
		},
		true,
	))
	app.coreMenu.AddSeparator()
	if core != nil {
		for _, actionName := range core.ListActions() {
			name := actionName //NOTE: don't directly use 'actionName' with closure in an forloop
			app.coreMenu.AppendItem(NewMenuItem(
				core.GetActionName(actionName),
				func() {
					core := app.createDesktopAppInfo()
					if core == nil {
						return
					}
					defer core.Unref()
					core.LaunchAction(name, nil)
				},
				true,
			))
		}
		app.coreMenu.AddSeparator()
	}
	closeItem := NewMenuItem(
		Tr("_Close All"),
		func() {
			logger.Debug("Close All")
			for xid := range app.xids {
				ewmh.CloseWindow(XU, xid)
			}
		},
		true,
	)
	app.coreMenu.AppendItem(closeItem)
	var err error
	if DOCKED_APP_MANAGER == nil {
		DOCKED_APP_MANAGER, err = dock.NewDockedAppManager(
			"com.deepin.daemon.Dock",
			"/dde/dock/DockedAppManager",
		)
		if err != nil {
			logger.Warning("get DockedAppManager failed", err)
			return
		}
	}
	isDocked, err := DOCKED_APP_MANAGER.IsDocked(app.Id)
	if err != nil {
		isDocked = false
		logger.Warning("get docked status failed:", err)
	}
	logger.Info(app.Id, "Item is docked:", isDocked)
	var message string = ""
	var action func() = nil
	if isDocked {
		logger.Info(app.Id, "change to undock")
		message = Tr("_Undock")
		action = func(id string) func() {
			return func() {
				app, ok := ENTRY_MANAGER.runtimeApps[id]
				if !ok {
					return
				}
				DOCKED_APP_MANAGER.Undock(app.Id)
			}
		}(app.Id)
	} else {
		logger.Info(app.Id, "change to dock")
		message = Tr("_Dock")
		action = actionGenarator(app.Id)
	}

	logger.Debug(app.Id, "New Menu Item:", message)
	dockItem := NewMenuItem(message, action, true)
	app.coreMenu.AppendItem(dockItem)

	app.Menu = app.coreMenu.GenerateJSON()
	app.notifyChanged()
}