<commit_before>// -------------------------------------------------------------------------
//    @FileName             NFIClusterClientModule.hpp
//    @Author               LvSheng.Huang
//    @Date                 2015-01-4
//    @Module               NFIClusterClientModule
//
// -------------------------------------------------------------------------

#ifndef _NFI_CLUSTER_CLIENT_MODULE_H
#define _NFI_CLUSTER_CLIENT_MODULE_H

#include <iostream>
#include "NFILogicModule.h"
#include "NFINetModule.h"
#include "NFComm/NFCore/NFCConsistentHash.hpp"

enum ConnectDataState
{
	DISCONNECT,
	NORMAL,
	RECONNECT,

};
struct ConnectData
{
	ConnectData()
	{
		nGameID = 0;
		nPort = 0;
		strName = "";
		strIP = "";
		eServerType = NFST_NONE;
		eState = ConnectDataState::DISCONNECT;
		mfLastActionTime = 0;
	}

	int nGameID;
	NF_SERVER_TYPE eServerType;
	std::string strIP;
	int nPort;
	std::string strName;
	ConnectDataState eState;
	float mfLastActionTime;

	NF_SHARE_PTR<NFINetModule> mxNetModule;
};

class NFIClusterClientModule : public NFILogicModule
{
public:
    enum EConstDefine
    {
        EConstDefine_DefaultWeith = 500,
    };

public:

    void AddServer(const ConnectData& xInfo)
    {
        mxTempNetList.push_back(xInfo);
    }

	//,ʱ
    void SendByServerID(const int nServerID, const int nMsgID, const std::string& strData)
    {
        NF_SHARE_PTR<ConnectData> pServer = mxServerMap.GetElement(nServerID);
        if (pServer)
        {
            NF_SHARE_PTR<NFINetModule> pNetModule = pServer->mxNetModule;
            if (pNetModule.get())
            {
                pNetModule->SendMsgWithOutHead(nMsgID, strData, 0);
            }
        }
    }

	//,ʱ
	void SendToAllServer(const int nMsgID, const std::string& strData)
	{
		NF_SHARE_PTR<ConnectData> pServer = mxServerMap.First();
		while (pServer)
		{
			NF_SHARE_PTR<NFINetModule> pNetModule = pServer->mxNetModule;
			if (pNetModule.get())
			{
				pNetModule->SendMsgWithOutHead(nMsgID, strData, 0);
			}

			pServer = mxServerMap.Next();
		}
	}

	void SendToServerByPB(const int nServerID, const uint16_t nMsgID, google::protobuf::Message& xData, const int nSockIndex = 0, const NFGUID nPlayer = NFGUID(), const std::vector<NFGUID>* pClientIDList = NULL, bool bBroadcast = false)
	{
		NF_SHARE_PTR<ConnectData> pServer = mxServerMap.GetElement(nServerID);
		if (pServer)
		{
			NF_SHARE_PTR<NFINetModule> pNetModule = pServer->mxNetModule;
			if (pNetModule.get())
			{
				pNetModule->SendMsgPB(nMsgID, xData, nSockIndex, nPlayer, pClientIDList);
			}
		}
	}

    void SendByServerID(const int nServerID, const int nSockIndex, const int nMsgID, const char* msg, const uint32_t nLen)
    {
        NF_SHARE_PTR<ConnectData> pServer = mxServerMap.GetElement(nServerID);
        if (pServer)
        {
            NF_SHARE_PTR<NFINetModule> pNetModule = pServer->mxNetModule;
            if (pNetModule.get())
            {
                pNetModule->GetNet()->SendMsgWithOutHead(nMsgID, msg, nLen, 0);
            }
        }
    }

	void SendToAllServerByPB(const uint16_t nMsgID, google::protobuf::Message& xData, const NFGUID nPlayer = NFGUID(), const std::vector<NFGUID>* pClientIDList = NULL)
	{
		NF_SHARE_PTR<ConnectData> pServer = mxServerMap.First();
		while (pServer)
		{
			NF_SHARE_PTR<NFINetModule> pNetModule = pServer->mxNetModule;
			if (pNetModule.get())
			{
				pNetModule->SendMsgPB(nMsgID, xData, 0, nPlayer, pClientIDList);
			}

			pServer = mxServerMap.Next();
		}

	}

    void SendBySuit(const int& nHashKey, const int nMsgID, const std::string& strData)
    {
        if (mxConsistentHash.Size() <= 0)
        {
            return;
        }

        NFCMachineNode xNode;
        if (!GetServerMachineData(boost::lexical_cast<std::string> (nHashKey), xNode))
        {
            return ;
        }

        SendByServerID(nMsgID, xNode.nMachineID, strData);
    }

    void SendBySuit(const int& nHashKey, const int nSockIndex, const int nMsgID, const char* msg, const uint32_t nLen)
    {
        if (mxConsistentHash.Size() <= 0)
        {
            return;
        }

        NFCMachineNode xNode;
        if (!GetServerMachineData(boost::lexical_cast<std::string>(nHashKey), xNode))
        {
            return ;
        }

        SendByServerID(xNode.nMachineID, nSockIndex, nMsgID, msg, nLen);
    }

	void SendSuitByPB(const int& nHashKey, const uint16_t nMsgID, google::protobuf::Message& xData, const int nSockIndex = 0, const NFGUID nPlayer = NFGUID(), const std::vector<NFGUID>* pClientIDList = NULL)
	{
		if (mxConsistentHash.Size() <= 0)
		{
			return;
		}

		NFCMachineNode xNode;
		if (!GetServerMachineData(boost::lexical_cast<std::string> (nHashKey), xNode))
		{
			return ;
		}

		SendToServerByPB(xNode.nMachineID, nMsgID, xData, nSockIndex, nPlayer, pClientIDList);
	}

	void SendSuitByPB(const uint16_t nMsgID, google::protobuf::Message& xData, const int nSockIndex = 0, const NFGUID nPlayer = NFGUID(), const std::vector<NFGUID>* pClientIDList = NULL)
	{
		if (mxConsistentHash.Size() <= 0)
		{
			return;
		}

		const int nHashKey = 0;

		SendSuitByPB(nHashKey, nMsgID, xData, nSockIndex, nPlayer, pClientIDList);
	}

	NF_SHARE_PTR<ConnectData> GetServerNetInfo(const int nServerID)
	{
		return mxServerMap.GetElement(nServerID);
	}

	NFMapEx<int, ConnectData>& GetServerList()
	{
		return mxServerMap;
	}

protected:
	template<typename BaseType>
	void Bind(BaseType* pBaseType, void (BaseType::*handleRecieve)(const int nSockIndex, const int nMsgID, const char* msg, const uint32_t nLen), void (BaseType::*handleEvent)(const int, const NF_NET_EVENT, NFINet*))
	{
		mRecvCB = std::bind(handleRecieve, pBaseType, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
		mEventCB = std::bind(handleEvent, pBaseType, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
	}

    bool Execute(const float fLastFrametime, const float fStartedTime)
    {
        ConnectData* pServerData = mxServerMap.FirstNude();
        while (pServerData)
        {
			switch (pServerData->eState)
			{
			case ConnectDataState::DISCONNECT:
				{
					if (NULL != pServerData->mxNetModule)
					{
						pServerData->mxNetModule = nullptr;
						pServerData->eState = ConnectDataState::RECONNECT;
						pServerData->mfLastActionTime = 0.0f;
					}
				}
				break;
			case ConnectDataState::NORMAL:
				{
					if (pServerData->mxNetModule)
					{
						pServerData->mxNetModule->Execute(fLastFrametime, fStartedTime);

						KeepState(pServerData, fLastFrametime, fStartedTime);
					}
				}
				break;
			case ConnectDataState::RECONNECT:
				{
					//ʱ
					if (pServerData->mfLastActionTime < 30.0f)
					{
						pServerData->mfLastActionTime += fLastFrametime;
						break;
					}

					pServerData->mfLastActionTime = 0.0f;
					pServerData->eState = ConnectDataState::NORMAL;

					pServerData->mxNetModule->Initialization(this, &NFIClusterClientModule::OnRecivePack, &NFIClusterClientModule::OnSocketEvent, pServerData->strIP.c_str(), pServerData->nPort);
				}
				break;
			default:
				break;
			}

            pServerData = mxServerMap.NextNude();
        }

        ProcessAddNetConnect();

        return true;
    }

	NF_SHARE_PTR<ConnectData> GetServerNetInfo(const NFINet* pNet)
	{
		int nServerID = 0;
		for (NF_SHARE_PTR<ConnectData> pData = mxServerMap.First(nServerID); pData != NULL; pData = mxServerMap.Next(nServerID))
		{
			if (pData->mxNetModule.get() && pNet == pData->mxNetModule->GetNet())
			{
				return pData;
			}
		}

		return NF_SHARE_PTR<ConnectData> (NULL);
	}

	virtual void KeepReport(ConnectData* pServerData){};
	virtual void LogServerInfo(const std::string& strServerInfo){};

private:
	virtual void LogServerInfo()
	{
		LogServerInfo("This is a client, begin to Printf Server Info----------------------------------");

		ConnectData* pServerData = mxServerMap.FirstNude();
		while (pServerData)
		{
			std::ostringstream stream;
			stream << "Type: " << pServerData->eServerType << " ProxyServer ID: " << pServerData->nGameID << " State: " <<  pServerData->eState << " IP: " << pServerData->strIP << " Port: " << pServerData->nPort;

			LogServerInfo(stream.str());

			pServerData = mxServerMap.NextNude();
		}

		LogServerInfo("This is a client, end to Printf Server Info----------------------------------");
	};

	void KeepState(ConnectData* pServerData, const float fLastFrametime, const float fStartedTime)
	{
		if (pServerData->mfLastActionTime < 10.0f)
		{
			pServerData->mfLastActionTime += fLastFrametime;
			return;
		}

		pServerData->mfLastActionTime = 0.0f;

		KeepReport(pServerData);
		LogServerInfo();
	}

	void OnSocketEvent(const int fd, const NF_NET_EVENT eEvent, NFINet* pNet)
	{
		if (eEvent & BEV_EVENT_CONNECTED)
		{
			OnConnected(fd, pNet);
		}
		else
		{
			OnDisConnected(fd, pNet);
		}

		if (mEventCB)
		{
			mEventCB(fd, eEvent, pNet);
		}
	}

	void OnRecivePack(const int nSockIndex, const int nMsgID, const char* msg, const uint32_t nLen)
	{
		if (mRecvCB)
		{
			mRecvCB(nSockIndex, nMsgID, msg, nLen);
		}

	}

    int OnConnected(const int fd, NFINet* pNet)
    {
        NF_SHARE_PTR<ConnectData> pServerInfo = GetServerNetInfo(pNet);
        if (pServerInfo.get())
        {
            AddServerWeightData(pServerInfo);
            pServerInfo->eState = ConnectDataState::NORMAL;
        }

        return 0;
    }

    int OnDisConnected(const int fd, NFINet* pNet)
    {
        NF_SHARE_PTR<ConnectData> pServerInfo = GetServerNetInfo(pNet);
        if (pServerInfo.get())
        {
            RemoveServerWeightData(pServerInfo);
            pServerInfo->eState = ConnectDataState::DISCONNECT;
        }

        return 0;
    }

    void ProcessAddNetConnect()
    {
        std::list<ConnectData>::iterator it = mxTempNetList.begin();
        for (; it != mxTempNetList.end(); ++it)
        {
            const ConnectData& xInfo = *it;
            NF_SHARE_PTR<ConnectData> xServerData = mxServerMap.GetElement(xInfo.nGameID);
            if (nullptr == xServerData)
            {
				//·
				xServerData = NF_SHARE_PTR<ConnectData>(NF_NEW ConnectData());

				xServerData->nGameID = xInfo.nGameID;
				xServerData->eServerType = xInfo.eServerType;
				xServerData->strIP = xInfo.strIP;
				xServerData->strName = xInfo.strName;
				xServerData->eState = ConnectDataState::NORMAL;
				xServerData->nPort = xInfo.nPort;

				xServerData->mxNetModule = NF_SHARE_PTR<NFINetModule>(NF_NEW NFINetModule());
				xServerData->mxNetModule->Initialization(this, &NFIClusterClientModule::OnRecivePack, &NFIClusterClientModule::OnSocketEvent, xServerData->strIP.c_str(), xServerData->nPort);

				mxServerMap.AddElement(xInfo.nGameID, xServerData);
            }
        }

        mxTempNetList.clear();
    }

    bool GetServerMachineData(const std::string& strServerID, NFCMachineNode& xMachineData)
    {
        boost::crc_32_type ret;
        ret.process_bytes(strServerID.c_str(), strServerID.length());
        uint32_t nCRC32 = ret.checksum();

        if (mxConsistentHash.GetSuitNode(nCRC32, xMachineData))
        {
            return true;
        }

        return false;
    }

    void AddServerWeightData(NF_SHARE_PTR<ConnectData> xInfo)
    {
        //Ȩشڵ
        for (int j = 0; j < EConstDefine_DefaultWeith; ++j)
        {
            NFCMachineNode vNode(j);

            vNode.nMachineID = xInfo->nGameID;
            vNode.strIP = xInfo->strIP;
            vNode.nPort = xInfo->nPort;
            vNode.nWeight = EConstDefine_DefaultWeith;
            mxConsistentHash.Insert(vNode);
        }
    }

    void RemoveServerWeightData(NF_SHARE_PTR<ConnectData> xInfo)
    {
        for (int j = 0; j < EConstDefine_DefaultWeith; ++j)
        {
            NFCMachineNode vNode(j);

            vNode.nMachineID = xInfo->nGameID;
            vNode.strIP = xInfo->strIP;
            vNode.nPort = xInfo->nPort;
            vNode.nWeight = EConstDefine_DefaultWeith;
            mxConsistentHash.Erase(vNode);
        }
    }

private:
	NET_RECIEVE_FUNCTOR mRecvCB;
	NET_EVENT_FUNCTOR mEventCB;

	NFMapEx<int, ConnectData> mxServerMap;
	NFCConsistentHash mxConsistentHash;

    std::list<ConnectData> mxTempNetList;
};

#endif<commit_msg>modify a bug of cluster client module<commit_after>// -------------------------------------------------------------------------
//    @FileName             NFIClusterClientModule.hpp
//    @Author               LvSheng.Huang
//    @Date                 2015-01-4
//    @Module               NFIClusterClientModule
//
// -------------------------------------------------------------------------

#ifndef _NFI_CLUSTER_CLIENT_MODULE_H
#define _NFI_CLUSTER_CLIENT_MODULE_H

#include <iostream>
#include "NFILogicModule.h"
#include "NFINetModule.h"
#include "NFComm/NFCore/NFCConsistentHash.hpp"

enum ConnectDataState
{
	DISCONNECT,
	NORMAL,
	RECONNECT,

};
struct ConnectData
{
	ConnectData()
	{
		nGameID = 0;
		nPort = 0;
		strName = "";
		strIP = "";
		eServerType = NFST_NONE;
		eState = ConnectDataState::DISCONNECT;
		mfLastActionTime = 0;
	}

	int nGameID;
	NF_SERVER_TYPE eServerType;
	std::string strIP;
	int nPort;
	std::string strName;
	ConnectDataState eState;
	float mfLastActionTime;

	NF_SHARE_PTR<NFINetModule> mxNetModule;
};

class NFIClusterClientModule : public NFILogicModule
{
public:
    enum EConstDefine
    {
        EConstDefine_DefaultWeith = 500,
    };

public:

    void AddServer(const ConnectData& xInfo)
    {
        mxTempNetList.push_back(xInfo);
    }

	//,ʱ
    void SendByServerID(const int nServerID, const int nMsgID, const std::string& strData)
    {
        NF_SHARE_PTR<ConnectData> pServer = mxServerMap.GetElement(nServerID);
        if (pServer)
        {
            NF_SHARE_PTR<NFINetModule> pNetModule = pServer->mxNetModule;
            if (pNetModule.get())
            {
                pNetModule->SendMsgWithOutHead(nMsgID, strData, 0);
            }
        }
    }

	//,ʱ
	void SendToAllServer(const int nMsgID, const std::string& strData)
	{
		NF_SHARE_PTR<ConnectData> pServer = mxServerMap.First();
		while (pServer)
		{
			NF_SHARE_PTR<NFINetModule> pNetModule = pServer->mxNetModule;
			if (pNetModule.get())
			{
				pNetModule->SendMsgWithOutHead(nMsgID, strData, 0);
			}

			pServer = mxServerMap.Next();
		}
	}

	void SendToServerByPB(const int nServerID, const uint16_t nMsgID, google::protobuf::Message& xData, const int nSockIndex = 0, const NFGUID nPlayer = NFGUID(), const std::vector<NFGUID>* pClientIDList = NULL, bool bBroadcast = false)
	{
		NF_SHARE_PTR<ConnectData> pServer = mxServerMap.GetElement(nServerID);
		if (pServer)
		{
			NF_SHARE_PTR<NFINetModule> pNetModule = pServer->mxNetModule;
			if (pNetModule.get())
			{
				pNetModule->SendMsgPB(nMsgID, xData, nSockIndex, nPlayer, pClientIDList);
			}
		}
	}

    void SendByServerID(const int nServerID, const int nSockIndex, const int nMsgID, const char* msg, const uint32_t nLen)
    {
        NF_SHARE_PTR<ConnectData> pServer = mxServerMap.GetElement(nServerID);
        if (pServer)
        {
            NF_SHARE_PTR<NFINetModule> pNetModule = pServer->mxNetModule;
            if (pNetModule.get())
            {
                pNetModule->GetNet()->SendMsgWithOutHead(nMsgID, msg, nLen, 0);
            }
        }
    }

	void SendToAllServerByPB(const uint16_t nMsgID, google::protobuf::Message& xData, const NFGUID nPlayer = NFGUID(), const std::vector<NFGUID>* pClientIDList = NULL)
	{
		NF_SHARE_PTR<ConnectData> pServer = mxServerMap.First();
		while (pServer)
		{
			NF_SHARE_PTR<NFINetModule> pNetModule = pServer->mxNetModule;
			if (pNetModule.get())
			{
				pNetModule->SendMsgPB(nMsgID, xData, 0, nPlayer, pClientIDList);
			}

			pServer = mxServerMap.Next();
		}

	}

    void SendBySuit(const int& nHashKey, const int nMsgID, const std::string& strData)
    {
        if (mxConsistentHash.Size() <= 0)
        {
            return;
        }

        NFCMachineNode xNode;
        if (!GetServerMachineData(boost::lexical_cast<std::string> (nHashKey), xNode))
        {
            return ;
        }

        SendByServerID(nMsgID, xNode.nMachineID, strData);
    }

    void SendBySuit(const int& nHashKey, const int nSockIndex, const int nMsgID, const char* msg, const uint32_t nLen)
    {
        if (mxConsistentHash.Size() <= 0)
        {
            return;
        }

        NFCMachineNode xNode;
        if (!GetServerMachineData(boost::lexical_cast<std::string>(nHashKey), xNode))
        {
            return ;
        }

        SendByServerID(xNode.nMachineID, nSockIndex, nMsgID, msg, nLen);
    }

	void SendSuitByPB(const int& nHashKey, const uint16_t nMsgID, google::protobuf::Message& xData, const int nSockIndex = 0, const NFGUID nPlayer = NFGUID(), const std::vector<NFGUID>* pClientIDList = NULL)
	{
		if (mxConsistentHash.Size() <= 0)
		{
			return;
		}

		NFCMachineNode xNode;
		if (!GetServerMachineData(boost::lexical_cast<std::string> (nHashKey), xNode))
		{
			return ;
		}

		SendToServerByPB(xNode.nMachineID, nMsgID, xData, nSockIndex, nPlayer, pClientIDList);
	}

	void SendSuitByPB(const uint16_t nMsgID, google::protobuf::Message& xData, const int nSockIndex = 0, const NFGUID nPlayer = NFGUID(), const std::vector<NFGUID>* pClientIDList = NULL)
	{
		if (mxConsistentHash.Size() <= 0)
		{
			return;
		}

		const int nHashKey = 0;

		SendSuitByPB(nHashKey, nMsgID, xData, nSockIndex, nPlayer, pClientIDList);
	}

	NF_SHARE_PTR<ConnectData> GetServerNetInfo(const int nServerID)
	{
		return mxServerMap.GetElement(nServerID);
	}

	NFMapEx<int, ConnectData>& GetServerList()
	{
		return mxServerMap;
	}

protected:
	template<typename BaseType>
	void Bind(BaseType* pBaseType, void (BaseType::*handleRecieve)(const int nSockIndex, const int nMsgID, const char* msg, const uint32_t nLen), void (BaseType::*handleEvent)(const int, const NF_NET_EVENT, NFINet*))
	{
		mRecvCB = std::bind(handleRecieve, pBaseType, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
		mEventCB = std::bind(handleEvent, pBaseType, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
	}

    bool Execute(const float fLastFrametime, const float fStartedTime)
    {
        ConnectData* pServerData = mxServerMap.FirstNude();
        while (pServerData)
        {
			switch (pServerData->eState)
			{
			case ConnectDataState::DISCONNECT:
				{
					if (NULL != pServerData->mxNetModule)
					{
						pServerData->mxNetModule = nullptr;
						pServerData->eState = ConnectDataState::RECONNECT;
						pServerData->mfLastActionTime = 0.0f;
					}
				}
				break;
			case ConnectDataState::NORMAL:
				{
					if (pServerData->mxNetModule)
					{
						pServerData->mxNetModule->Execute(fLastFrametime, fStartedTime);

						KeepState(pServerData, fLastFrametime, fStartedTime);
					}
				}
				break;
			case ConnectDataState::RECONNECT:
				{
					//ʱ
					if (pServerData->mfLastActionTime < 30.0f)
					{
						pServerData->mfLastActionTime += fLastFrametime;
						break;
					}

                    if (nullptr != pServerData->mxNetModule)
                    {
                        pServerData->mxNetModule = nullptr;
                    }

					pServerData->mfLastActionTime = 0.0f;
					pServerData->eState = ConnectDataState::NORMAL;
                    pServerData->mxNetModule = NF_SHARE_PTR<NFINetModule> (NF_NEW NFINetModule());
					pServerData->mxNetModule->Initialization(this, &NFIClusterClientModule::OnRecivePack, &NFIClusterClientModule::OnSocketEvent, pServerData->strIP.c_str(), pServerData->nPort);
				}
				break;
			default:
				break;
			}

            pServerData = mxServerMap.NextNude();
        }

        ProcessAddNetConnect();

        return true;
    }

	NF_SHARE_PTR<ConnectData> GetServerNetInfo(const NFINet* pNet)
	{
		int nServerID = 0;
		for (NF_SHARE_PTR<ConnectData> pData = mxServerMap.First(nServerID); pData != NULL; pData = mxServerMap.Next(nServerID))
		{
			if (pData->mxNetModule.get() && pNet == pData->mxNetModule->GetNet())
			{
				return pData;
			}
		}

		return NF_SHARE_PTR<ConnectData> (NULL);
	}

	virtual void KeepReport(ConnectData* pServerData){};
	virtual void LogServerInfo(const std::string& strServerInfo){};

private:
	virtual void LogServerInfo()
	{
		LogServerInfo("This is a client, begin to Printf Server Info----------------------------------");

		ConnectData* pServerData = mxServerMap.FirstNude();
		while (pServerData)
		{
			std::ostringstream stream;
			stream << "Type: " << pServerData->eServerType << " ProxyServer ID: " << pServerData->nGameID << " State: " <<  pServerData->eState << " IP: " << pServerData->strIP << " Port: " << pServerData->nPort;

			LogServerInfo(stream.str());

			pServerData = mxServerMap.NextNude();
		}

		LogServerInfo("This is a client, end to Printf Server Info----------------------------------");
	};

	void KeepState(ConnectData* pServerData, const float fLastFrametime, const float fStartedTime)
	{
		if (pServerData->mfLastActionTime < 10.0f)
		{
			pServerData->mfLastActionTime += fLastFrametime;
			return;
		}

		pServerData->mfLastActionTime = 0.0f;

		KeepReport(pServerData);
		LogServerInfo();
	}

	void OnSocketEvent(const int fd, const NF_NET_EVENT eEvent, NFINet* pNet)
	{
		if (eEvent & BEV_EVENT_CONNECTED)
		{
			OnConnected(fd, pNet);
		}
		else
		{
			OnDisConnected(fd, pNet);
		}

		if (mEventCB)
		{
			mEventCB(fd, eEvent, pNet);
		}
	}

	void OnRecivePack(const int nSockIndex, const int nMsgID, const char* msg, const uint32_t nLen)
	{
		if (mRecvCB)
		{
			mRecvCB(nSockIndex, nMsgID, msg, nLen);
		}

	}

    int OnConnected(const int fd, NFINet* pNet)
    {
        NF_SHARE_PTR<ConnectData> pServerInfo = GetServerNetInfo(pNet);
        if (pServerInfo.get())
        {
            AddServerWeightData(pServerInfo);
            pServerInfo->eState = ConnectDataState::NORMAL;
        }

        return 0;
    }

    int OnDisConnected(const int fd, NFINet* pNet)
    {
        NF_SHARE_PTR<ConnectData> pServerInfo = GetServerNetInfo(pNet);
        if (pServerInfo.get())
        {
            RemoveServerWeightData(pServerInfo);
            pServerInfo->eState = ConnectDataState::DISCONNECT;
        }

        return 0;
    }

    void ProcessAddNetConnect()
    {
        std::list<ConnectData>::iterator it = mxTempNetList.begin();
        for (; it != mxTempNetList.end(); ++it)
        {
            const ConnectData& xInfo = *it;
            NF_SHARE_PTR<ConnectData> xServerData = mxServerMap.GetElement(xInfo.nGameID);
            if (nullptr == xServerData)
            {
				//·
				xServerData = NF_SHARE_PTR<ConnectData>(NF_NEW ConnectData());

				xServerData->nGameID = xInfo.nGameID;
				xServerData->eServerType = xInfo.eServerType;
				xServerData->strIP = xInfo.strIP;
				xServerData->strName = xInfo.strName;
				xServerData->eState = ConnectDataState::NORMAL;
				xServerData->nPort = xInfo.nPort;

				xServerData->mxNetModule = NF_SHARE_PTR<NFINetModule>(NF_NEW NFINetModule());
				xServerData->mxNetModule->Initialization(this, &NFIClusterClientModule::OnRecivePack, &NFIClusterClientModule::OnSocketEvent, xServerData->strIP.c_str(), xServerData->nPort);

				mxServerMap.AddElement(xInfo.nGameID, xServerData);
            }
        }

        mxTempNetList.clear();
    }

    bool GetServerMachineData(const std::string& strServerID, NFCMachineNode& xMachineData)
    {
        boost::crc_32_type ret;
        ret.process_bytes(strServerID.c_str(), strServerID.length());
        uint32_t nCRC32 = ret.checksum();

        if (mxConsistentHash.GetSuitNode(nCRC32, xMachineData))
        {
            return true;
        }

        return false;
    }

    void AddServerWeightData(NF_SHARE_PTR<ConnectData> xInfo)
    {
        //Ȩشڵ
        for (int j = 0; j < EConstDefine_DefaultWeith; ++j)
        {
            NFCMachineNode vNode(j);

            vNode.nMachineID = xInfo->nGameID;
            vNode.strIP = xInfo->strIP;
            vNode.nPort = xInfo->nPort;
            vNode.nWeight = EConstDefine_DefaultWeith;
            mxConsistentHash.Insert(vNode);
        }
    }

    void RemoveServerWeightData(NF_SHARE_PTR<ConnectData> xInfo)
    {
        for (int j = 0; j < EConstDefine_DefaultWeith; ++j)
        {
            NFCMachineNode vNode(j);

            vNode.nMachineID = xInfo->nGameID;
            vNode.strIP = xInfo->strIP;
            vNode.nPort = xInfo->nPort;
            vNode.nWeight = EConstDefine_DefaultWeith;
            mxConsistentHash.Erase(vNode);
        }
    }

private:
	NET_RECIEVE_FUNCTOR mRecvCB;
	NET_EVENT_FUNCTOR mEventCB;

	NFMapEx<int, ConnectData> mxServerMap;
	NFCConsistentHash mxConsistentHash;

    std::list<ConnectData> mxTempNetList;
};

#endif<|endoftext|>


<commit_before>#include "stdafx.h"
#include "Frame.h"

WORD BORDER_COLOR = FOREGROUND_GREEN | FOREGROUND_RED;

Frame::Frame() :
    m_hStdIn(INVALID_HANDLE_VALUE),
    m_hStdOut(INVALID_HANDLE_VALUE),
    m_width(0),
    m_height(0)
{
    // Nothing to do
}

Frame::~Frame()
{
    // Nothing to do
}

HRESULT Frame::RuntimeClassInitialize(HANDLE hStdIn, HANDLE hStdOut, WORD width, WORD height)
{
    ChkIf(hStdIn != INVALID_HANDLE_VALUE);
    ChkIf(hStdOut != INVALID_HANDLE_VALUE);
    ChkIf(width >= 1);
    ChkIf(height >= 1);

    m_hStdIn = hStdIn;
    m_hStdOut = hStdOut;
    m_width = width;
    m_height = height;

    return S_OK;
}

void Frame::InitializeFrame()
{
    DisplayBorders();
}

void Frame::DisplayBorders()
{
    DisplayVerticalBorders();
    DisplayHorizontalBorders();
}

void Frame::DisplayVerticalBorders()
{
    CHAR_INFO* chars = new CHAR_INFO[m_height];
    ChkIf(chars);

    for (size_t i = 0; i < m_height; i++)
    {
        CHAR_INFO* pChar = chars + i;
        pChar->Char.UnicodeChar = L'|';
        pChar->Attributes = BORDER_COLOR;
    }

    COORD buffer_size = {1, m_height};
    COORD origin = {0, 0};

    SMALL_RECT left_rect = {0, 0, 0, m_height - 1};
    ChkIf(WriteConsoleOutputW(m_hStdOut,
        chars,
        buffer_size,
        origin,
        &left_rect));

    SMALL_RECT right_rect = {m_width - 1, 0, m_width - 1, m_height - 1};
    ChkIf(WriteConsoleOutputW(m_hStdOut,
        chars,
        buffer_size,
        origin,
        &right_rect));
}

void Frame::DisplayHorizontalBorders()
{
    CHAR_INFO* chars = new CHAR_INFO[m_width];
    ChkIf(chars);

    for (size_t i = 0; i < m_width; i++)
    {
        CHAR_INFO* pChar = chars + i;
        pChar->Char.UnicodeChar = L'=';
        pChar->Attributes = BORDER_COLOR;
    }

    COORD buffer_size = {m_width, 1};
    COORD origin = {0, 0};

    SMALL_RECT top_rect = {0, 0, m_width - 1, 0};
    ChkIf(WriteConsoleOutputW(m_hStdOut,
        chars,
        buffer_size,
        origin,
        &top_rect));

    SMALL_RECT bottom_rect = {0, m_height - 1, m_width - 1, m_height - 1};
    ChkIf(WriteConsoleOutputW(m_hStdOut,
        chars,
        buffer_size,
        origin,
        &bottom_rect));
}
<commit_msg>Making vertical lines in a loop<commit_after>#include "stdafx.h"
#include "Frame.h"

WORD BORDER_COLOR = FOREGROUND_GREEN | FOREGROUND_RED;

Frame::Frame() :
    m_hStdIn(INVALID_HANDLE_VALUE),
    m_hStdOut(INVALID_HANDLE_VALUE),
    m_width(0),
    m_height(0)
{
    // Nothing to do
}

Frame::~Frame()
{
    // Nothing to do
}

HRESULT Frame::RuntimeClassInitialize(HANDLE hStdIn, HANDLE hStdOut, WORD width, WORD height)
{
    ChkIf(hStdIn != INVALID_HANDLE_VALUE);
    ChkIf(hStdOut != INVALID_HANDLE_VALUE);
    ChkIf(width >= 1);
    ChkIf(height >= 1);

    m_hStdIn = hStdIn;
    m_hStdOut = hStdOut;
    m_width = width;
    m_height = height;

    return S_OK;
}

void Frame::InitializeFrame()
{
    DisplayBorders();
}

void Frame::DisplayBorders()
{
    DisplayVerticalBorders();
    DisplayHorizontalBorders();
}

struct VerticalBorderInfo
{
    SHORT Row;
    SHORT Top;
    SHORT Length;
};

void Frame::DisplayVerticalBorders()
{
    VerticalBorderInfo lines[] = {
        {0, 0, m_height - 1},
        {m_width - 1, 0, m_height - 1},
        {m_width/2 - 1, m_height - 10, 7},
    };
    CHAR_INFO* chars = new CHAR_INFO[m_height];
    ChkIf(chars);

    for (size_t i = 0; i < m_height; i++)
    {
        CHAR_INFO* pChar = chars + i;
        pChar->Char.UnicodeChar = L'|';
        pChar->Attributes = BORDER_COLOR;
    }

    COORD buffer_size = {1, m_height};
    COORD origin = {0, 0};

    for (size_t i = 0; i < ARRAYSIZE(lines); i++)
    {
        VerticalBorderInfo *pLine = lines + i;
        SMALL_RECT rect = {};
        rect.Left = pLine->Row;
        rect.Right = pLine->Row;
        rect.Top = pLine->Top;
        rect.Bottom = pLine->Top + pLine->Length - 1;

        ChkIf(WriteConsoleOutputW(m_hStdOut,
            chars,
            buffer_size,
            origin,
            &rect));
    }
}

void Frame::DisplayHorizontalBorders()
{
    CHAR_INFO* chars = new CHAR_INFO[m_width];
    ChkIf(chars);

    for (size_t i = 0; i < m_width; i++)
    {
        CHAR_INFO* pChar = chars + i;
        pChar->Char.UnicodeChar = L'=';
        pChar->Attributes = BORDER_COLOR;
    }

    COORD buffer_size = {m_width, 1};
    COORD origin = {0, 0};

    SMALL_RECT top_rect = {0, 0, m_width - 1, 0};
    ChkIf(WriteConsoleOutputW(m_hStdOut,
        chars,
        buffer_size,
        origin,
        &top_rect));

    SMALL_RECT bottom_rect = {0, m_height - 1, m_width - 1, m_height - 1};
    ChkIf(WriteConsoleOutputW(m_hStdOut,
        chars,
        buffer_size,
        origin,
        &bottom_rect));
}
<|endoftext|>


<commit_before><commit_msg>[asan] Return sizeof missed by r309914<commit_after><|endoftext|>


<commit_before>#include "cursor.hpp"
#include "core.hpp"
#include "input-manager.hpp"
#include "workspace-manager.hpp"
#include "debug.hpp"
#include "compositor-surface.hpp"

static void handle_pointer_button_cb(wl_listener*, void *data)
{
    auto ev = static_cast<wlr_event_pointer_button*> (data);
    core->input->handle_pointer_button(ev);
    wlr_seat_pointer_notify_button(core->input->seat, ev->time_msec, ev->button, ev->state);
    wlr_idle_notify_activity(core->protocols.idle, core->get_current_seat());
}

static void handle_pointer_motion_cb(wl_listener*, void *data)
{
    auto ev = static_cast<wlr_event_pointer_motion*> (data);
    core->input->handle_pointer_motion(ev);
    wlr_idle_notify_activity(core->protocols.idle, core->get_current_seat());
}

static void handle_pointer_motion_absolute_cb(wl_listener*, void *data)
{
    auto ev = static_cast<wlr_event_pointer_motion_absolute*> (data);
    core->input->handle_pointer_motion_absolute(ev);
    wlr_idle_notify_activity(core->protocols.idle, core->get_current_seat());
}

static void handle_pointer_axis_cb(wl_listener*, void *data)
{
    auto ev = static_cast<wlr_event_pointer_axis*> (data);
    core->input->handle_pointer_axis(ev);
    wlr_idle_notify_activity(core->protocols.idle, core->get_current_seat());
}

void input_manager::handle_pointer_button(wlr_event_pointer_button *ev)
{
    in_mod_binding = false;

    if (ev->state == WLR_BUTTON_PRESSED)
    {
        count_other_inputs++;

        GetTuple(gx, gy, core->get_cursor_position());
        auto output = core->get_output_at(gx, gy);
        core->focus_output(output);

        GetTuple(ox, oy, core->get_active_output()->get_cursor_position());
        std::vector<std::function<void()>> callbacks;

        auto mod_state = get_modifiers();
        for (auto& binding : bindings[WF_BINDING_BUTTON])
        {
            if (binding->output == core->get_active_output() &&
                binding->value->as_cached_button().matches(
                    {mod_state, ev->button}))
            {
                auto callback = binding->call.button;
                callbacks.push_back([=] () {(*callback) (ev->button, ox, oy);});
            }
        }

        for (auto& binding : bindings[WF_BINDING_ACTIVATOR])
        {
            if (binding->output == core->get_active_output() &&
                binding->value->matches_button({mod_state, ev->button}))
            {
                callbacks.push_back(*binding->call.activator);
            }
        }

        for (auto call : callbacks)
            call();
    }
    else
    {
        count_other_inputs--;
    }

    if (active_grab)
    {
        if (active_grab->callbacks.pointer.button)
            active_grab->callbacks.pointer.button(ev->button, ev->state);
    } else if (cursor_focus)
    {
        auto custom = wf_compositor_surface_from_surface(cursor_focus);
        if (custom)
            custom->on_pointer_button(ev->button, ev->state);
    }
}

void input_manager::update_cursor_focus(wayfire_surface_t *focus, int x, int y)
{
    if (focus && !can_focus_surface(focus))
        return;

    wayfire_compositor_surface_t *compositor_surface = wf_compositor_surface_from_surface(cursor_focus);
    if (compositor_surface)
        compositor_surface->on_pointer_leave();

    if (cursor_focus != focus)
        log_info("change cursor focus %p -> %p", cursor_focus, focus);

    cursor_focus = focus;
    if (focus && !wf_compositor_surface_from_surface(focus))
    {
        wlr_seat_pointer_notify_enter(seat, focus->surface, x, y);
    } else
    {
        wlr_seat_pointer_clear_focus(seat);
    }

    if ((compositor_surface = wf_compositor_surface_from_surface(focus)))
        compositor_surface->on_pointer_enter(x, y);
}

void input_manager::update_cursor_position(uint32_t time_msec, bool real_update)
{
    GetTuple(x, y, core->get_cursor_position());
    if (input_grabbed() && real_update)
    {
        GetTuple(sx, sy, core->get_active_output()->get_cursor_position());
        if (active_grab->callbacks.pointer.motion)
            active_grab->callbacks.pointer.motion(sx, sy);
        return;
    }

    int lx, ly;
    wayfire_surface_t *new_focus = input_surface_at(x, y, lx, ly);
    update_cursor_focus(new_focus, lx, ly);

    auto compositor_surface = wf_compositor_surface_from_surface(new_focus);
    if (compositor_surface)
    {
        compositor_surface->on_pointer_motion(lx, ly);
    }
    else if (real_update)
    {
        wlr_seat_pointer_notify_motion(core->input->seat, time_msec, lx, ly);
    }

    update_drag_icons();
}

void input_manager::handle_pointer_motion(wlr_event_pointer_motion *ev)
{
    if (input_grabbed() && active_grab->callbacks.pointer.relative_motion)
        active_grab->callbacks.pointer.relative_motion(ev);

    wlr_cursor_move(cursor->cursor, ev->device, ev->delta_x, ev->delta_y);
    update_cursor_position(ev->time_msec);
}

void input_manager::handle_pointer_motion_absolute(wlr_event_pointer_motion_absolute *ev)
{
    wlr_cursor_warp_absolute(cursor->cursor, ev->device, ev->x, ev->y);
    update_cursor_position(ev->time_msec);
}

void input_manager::handle_pointer_axis(wlr_event_pointer_axis *ev)
{
    std::vector<axis_callback*> callbacks;

    auto mod_state = get_modifiers();

    for (auto& binding : bindings[WF_BINDING_AXIS])
    {
        if (binding->output == core->get_active_output() &&
            binding->value->as_cached_key().matches({mod_state, 0}))
            callbacks.push_back(binding->call.axis);
    }

    for (auto call : callbacks)
        (*call) (ev);

    /* reset modifier bindings */
    in_mod_binding = false;
    if (active_grab)
    {
        if (active_grab->callbacks.pointer.axis)
            active_grab->callbacks.pointer.axis(ev);

        return;
    }

    double mult = ev->source == WLR_AXIS_SOURCE_FINGER ?
        cursor->touchpad_scroll_speed->as_cached_double() :
        cursor->mouse_scroll_speed->as_cached_double();
    wlr_seat_pointer_notify_axis(seat, ev->time_msec, ev->orientation,
                                 mult * ev->delta, mult * ev->delta_discrete, ev->source);
}

wf_cursor::wf_cursor()
{
    cursor = wlr_cursor_create();

    wlr_cursor_attach_output_layout(cursor, core->output_layout);
    wlr_cursor_map_to_output(cursor, NULL);
    wlr_cursor_warp(cursor, NULL, cursor->x, cursor->y);

    button.notify             = handle_pointer_button_cb;
    motion.notify             = handle_pointer_motion_cb;
    motion_absolute.notify    = handle_pointer_motion_absolute_cb;
    axis.notify               = handle_pointer_axis_cb;

    wl_signal_add(&cursor->events.button, &button);
    wl_signal_add(&cursor->events.motion, &motion);
    wl_signal_add(&cursor->events.motion_absolute, &motion_absolute);
    wl_signal_add(&cursor->events.axis, &axis);

    init_xcursor();

    config_reloaded = [=] (signal_data*) {
        init_xcursor();
    };

    auto section = core->config->get_section("input");
    mouse_scroll_speed    = section->get_option("mouse_scroll_speed", "1");
    touchpad_scroll_speed = section->get_option("touchpad_scroll_speed", "1");

    core->connect_signal("reload-config", &config_reloaded);
}

void wf_cursor::init_xcursor()
{
    auto section = core->config->get_section("input");

    auto theme = section->get_option("cursor_theme", "default")->as_string();
    auto size = section->get_option("cursor_size", "24");

    auto theme_ptr = (theme == "default") ? NULL : theme.c_str();

    if (xcursor)
        wlr_xcursor_manager_destroy(xcursor);

    xcursor = wlr_xcursor_manager_create(theme_ptr, size->as_int());
    wlr_xcursor_manager_load(xcursor, 1);

    set_cursor("default");
}

void wf_cursor::attach_device(wlr_input_device *device)
{
    wlr_cursor_attach_input_device(cursor, device);
}

void wf_cursor::detach_device(wlr_input_device *device)
{
    wlr_cursor_detach_input_device(cursor, device);
}

void wf_cursor::set_cursor(std::string name)
{
    if (name == "default")
        name = "left_ptr";

    wlr_xcursor_manager_set_cursor_image(xcursor, name.c_str(), cursor);
}

void wf_cursor::hide_cursor()
{
    wlr_cursor_set_surface(cursor, NULL, 0, 0);
}

void wf_cursor::warp_cursor(int x, int y)
{
    wlr_cursor_warp(cursor, NULL, x, y);
    core->input->update_cursor_position(get_current_time());
}

void wf_cursor::set_cursor(wlr_seat_pointer_request_set_cursor_event *ev)
{
    auto focused_surface = ev->seat_client->seat->pointer_state.focused_surface;
    auto client = focused_surface ? wl_resource_get_client(focused_surface->resource) : NULL;

    if (client == ev->seat_client->client && !core->input->input_grabbed())
        wlr_cursor_set_surface(cursor, ev->surface, ev->hotspot_x, ev->hotspot_y);
}

wf_cursor::~wf_cursor()
{
    wl_list_remove(&button.link);
    wl_list_remove(&motion.link);
    wl_list_remove(&motion_absolute.link);
    wl_list_remove(&axis.link);

    core->disconnect_signal("reload-config", &config_reloaded);
}

<commit_msg>cursor: do not set axis events if an axis binding has consumed it<commit_after>#include "cursor.hpp"
#include "core.hpp"
#include "input-manager.hpp"
#include "workspace-manager.hpp"
#include "debug.hpp"
#include "compositor-surface.hpp"

static void handle_pointer_button_cb(wl_listener*, void *data)
{
    auto ev = static_cast<wlr_event_pointer_button*> (data);
    core->input->handle_pointer_button(ev);
    wlr_seat_pointer_notify_button(core->input->seat, ev->time_msec, ev->button, ev->state);
    wlr_idle_notify_activity(core->protocols.idle, core->get_current_seat());
}

static void handle_pointer_motion_cb(wl_listener*, void *data)
{
    auto ev = static_cast<wlr_event_pointer_motion*> (data);
    core->input->handle_pointer_motion(ev);
    wlr_idle_notify_activity(core->protocols.idle, core->get_current_seat());
}

static void handle_pointer_motion_absolute_cb(wl_listener*, void *data)
{
    auto ev = static_cast<wlr_event_pointer_motion_absolute*> (data);
    core->input->handle_pointer_motion_absolute(ev);
    wlr_idle_notify_activity(core->protocols.idle, core->get_current_seat());
}

static void handle_pointer_axis_cb(wl_listener*, void *data)
{
    auto ev = static_cast<wlr_event_pointer_axis*> (data);
    core->input->handle_pointer_axis(ev);
    wlr_idle_notify_activity(core->protocols.idle, core->get_current_seat());
}

void input_manager::handle_pointer_button(wlr_event_pointer_button *ev)
{
    in_mod_binding = false;

    if (ev->state == WLR_BUTTON_PRESSED)
    {
        count_other_inputs++;

        GetTuple(gx, gy, core->get_cursor_position());
        auto output = core->get_output_at(gx, gy);
        core->focus_output(output);

        GetTuple(ox, oy, core->get_active_output()->get_cursor_position());
        std::vector<std::function<void()>> callbacks;

        auto mod_state = get_modifiers();
        for (auto& binding : bindings[WF_BINDING_BUTTON])
        {
            if (binding->output == core->get_active_output() &&
                binding->value->as_cached_button().matches(
                    {mod_state, ev->button}))
            {
                auto callback = binding->call.button;
                callbacks.push_back([=] () {(*callback) (ev->button, ox, oy);});
            }
        }

        for (auto& binding : bindings[WF_BINDING_ACTIVATOR])
        {
            if (binding->output == core->get_active_output() &&
                binding->value->matches_button({mod_state, ev->button}))
            {
                callbacks.push_back(*binding->call.activator);
            }
        }

        for (auto call : callbacks)
            call();
    }
    else
    {
        count_other_inputs--;
    }

    if (active_grab)
    {
        if (active_grab->callbacks.pointer.button)
            active_grab->callbacks.pointer.button(ev->button, ev->state);
    } else if (cursor_focus)
    {
        auto custom = wf_compositor_surface_from_surface(cursor_focus);
        if (custom)
            custom->on_pointer_button(ev->button, ev->state);
    }
}

void input_manager::update_cursor_focus(wayfire_surface_t *focus, int x, int y)
{
    if (focus && !can_focus_surface(focus))
        return;

    wayfire_compositor_surface_t *compositor_surface = wf_compositor_surface_from_surface(cursor_focus);
    if (compositor_surface)
        compositor_surface->on_pointer_leave();

    if (cursor_focus != focus)
        log_info("change cursor focus %p -> %p", cursor_focus, focus);

    cursor_focus = focus;
    if (focus && !wf_compositor_surface_from_surface(focus))
    {
        wlr_seat_pointer_notify_enter(seat, focus->surface, x, y);
    } else
    {
        wlr_seat_pointer_clear_focus(seat);
    }

    if ((compositor_surface = wf_compositor_surface_from_surface(focus)))
        compositor_surface->on_pointer_enter(x, y);
}

void input_manager::update_cursor_position(uint32_t time_msec, bool real_update)
{
    GetTuple(x, y, core->get_cursor_position());
    if (input_grabbed() && real_update)
    {
        GetTuple(sx, sy, core->get_active_output()->get_cursor_position());
        if (active_grab->callbacks.pointer.motion)
            active_grab->callbacks.pointer.motion(sx, sy);
        return;
    }

    int lx, ly;
    wayfire_surface_t *new_focus = input_surface_at(x, y, lx, ly);
    update_cursor_focus(new_focus, lx, ly);

    auto compositor_surface = wf_compositor_surface_from_surface(new_focus);
    if (compositor_surface)
    {
        compositor_surface->on_pointer_motion(lx, ly);
    }
    else if (real_update)
    {
        wlr_seat_pointer_notify_motion(core->input->seat, time_msec, lx, ly);
    }

    update_drag_icons();
}

void input_manager::handle_pointer_motion(wlr_event_pointer_motion *ev)
{
    if (input_grabbed() && active_grab->callbacks.pointer.relative_motion)
        active_grab->callbacks.pointer.relative_motion(ev);

    wlr_cursor_move(cursor->cursor, ev->device, ev->delta_x, ev->delta_y);
    update_cursor_position(ev->time_msec);
}

void input_manager::handle_pointer_motion_absolute(wlr_event_pointer_motion_absolute *ev)
{
    wlr_cursor_warp_absolute(cursor->cursor, ev->device, ev->x, ev->y);
    update_cursor_position(ev->time_msec);
}

void input_manager::handle_pointer_axis(wlr_event_pointer_axis *ev)
{
    std::vector<axis_callback*> callbacks;

    auto mod_state = get_modifiers();

    for (auto& binding : bindings[WF_BINDING_AXIS])
    {
        if (binding->output == core->get_active_output() &&
            binding->value->as_cached_key().matches({mod_state, 0}))
            callbacks.push_back(binding->call.axis);
    }

    for (auto call : callbacks)
        (*call) (ev);

    /* reset modifier bindings */
    in_mod_binding = false;
    if (active_grab)
    {
        if (active_grab->callbacks.pointer.axis)
            active_grab->callbacks.pointer.axis(ev);

        return;
    }

    /* Do not send scroll events to clients if an axis binding has used up the event */
    if (callbacks.size())
        return;

    double mult = ev->source == WLR_AXIS_SOURCE_FINGER ?
        cursor->touchpad_scroll_speed->as_cached_double() :
        cursor->mouse_scroll_speed->as_cached_double();
    wlr_seat_pointer_notify_axis(seat, ev->time_msec, ev->orientation,
                                 mult * ev->delta, mult * ev->delta_discrete, ev->source);
}

wf_cursor::wf_cursor()
{
    cursor = wlr_cursor_create();

    wlr_cursor_attach_output_layout(cursor, core->output_layout);
    wlr_cursor_map_to_output(cursor, NULL);
    wlr_cursor_warp(cursor, NULL, cursor->x, cursor->y);

    button.notify             = handle_pointer_button_cb;
    motion.notify             = handle_pointer_motion_cb;
    motion_absolute.notify    = handle_pointer_motion_absolute_cb;
    axis.notify               = handle_pointer_axis_cb;

    wl_signal_add(&cursor->events.button, &button);
    wl_signal_add(&cursor->events.motion, &motion);
    wl_signal_add(&cursor->events.motion_absolute, &motion_absolute);
    wl_signal_add(&cursor->events.axis, &axis);

    init_xcursor();

    config_reloaded = [=] (signal_data*) {
        init_xcursor();
    };

    auto section = core->config->get_section("input");
    mouse_scroll_speed    = section->get_option("mouse_scroll_speed", "1");
    touchpad_scroll_speed = section->get_option("touchpad_scroll_speed", "1");

    core->connect_signal("reload-config", &config_reloaded);
}

void wf_cursor::init_xcursor()
{
    auto section = core->config->get_section("input");

    auto theme = section->get_option("cursor_theme", "default")->as_string();
    auto size = section->get_option("cursor_size", "24");

    auto theme_ptr = (theme == "default") ? NULL : theme.c_str();

    if (xcursor)
        wlr_xcursor_manager_destroy(xcursor);

    xcursor = wlr_xcursor_manager_create(theme_ptr, size->as_int());
    wlr_xcursor_manager_load(xcursor, 1);

    set_cursor("default");
}

void wf_cursor::attach_device(wlr_input_device *device)
{
    wlr_cursor_attach_input_device(cursor, device);
}

void wf_cursor::detach_device(wlr_input_device *device)
{
    wlr_cursor_detach_input_device(cursor, device);
}

void wf_cursor::set_cursor(std::string name)
{
    if (name == "default")
        name = "left_ptr";

    wlr_xcursor_manager_set_cursor_image(xcursor, name.c_str(), cursor);
}

void wf_cursor::hide_cursor()
{
    wlr_cursor_set_surface(cursor, NULL, 0, 0);
}

void wf_cursor::warp_cursor(int x, int y)
{
    wlr_cursor_warp(cursor, NULL, x, y);
    core->input->update_cursor_position(get_current_time());
}

void wf_cursor::set_cursor(wlr_seat_pointer_request_set_cursor_event *ev)
{
    auto focused_surface = ev->seat_client->seat->pointer_state.focused_surface;
    auto client = focused_surface ? wl_resource_get_client(focused_surface->resource) : NULL;

    if (client == ev->seat_client->client && !core->input->input_grabbed())
        wlr_cursor_set_surface(cursor, ev->surface, ev->hotspot_x, ev->hotspot_y);
}

wf_cursor::~wf_cursor()
{
    wl_list_remove(&button.link);
    wl_list_remove(&motion.link);
    wl_list_remove(&motion_absolute.link);
    wl_list_remove(&axis.link);

    core->disconnect_signal("reload-config", &config_reloaded);
}

<|endoftext|>