Hyprland/src/protocols/core/DataDevice.hpp

199 lines
6 KiB
C++
Raw Normal View History

2024-05-11 18:13:20 +02:00
#pragma once
/*
Implementations for:
- wl_data_offer
- wl_data_source
- wl_data_device
- wl_data_device_manager
*/
#include <memory>
#include <vector>
#include <cstdint>
#include "../WaylandProtocol.hpp"
#include <wayland-server-protocol.h>
#include "wayland.hpp"
#include "../../helpers/signal/Signal.hpp"
#include "../../helpers/math/Math.hpp"
2024-05-11 18:13:20 +02:00
#include "../types/DataDevice.hpp"
class CWLDataDeviceResource;
class CWLDataDeviceManagerResource;
class CWLDataSourceResource;
class CWLDataOfferResource;
class CWLSurfaceResource;
2024-05-11 18:13:20 +02:00
class CMonitor;
class CWLDataOfferResource {
public:
CWLDataOfferResource(SP<CWlDataOffer> resource_, SP<IDataSource> source_);
~CWLDataOfferResource();
2024-05-11 18:13:20 +02:00
bool good();
void sendData();
WP<IDataSource> source;
bool dead = false;
bool accepted = false;
bool recvd = false;
uint32_t actions = 0;
private:
SP<CWlDataOffer> resource;
wl_client* pClient = nullptr;
friend class CWLDataDeviceResource;
};
class CWLDataSourceResource : public IDataSource {
public:
CWLDataSourceResource(SP<CWlDataSource> resource_, SP<CWLDataDeviceResource> device_);
~CWLDataSourceResource();
static SP<CWLDataSourceResource> fromResource(wl_resource*);
bool good();
virtual std::vector<std::string> mimes();
virtual void send(const std::string& mime, uint32_t fd);
virtual void accepted(const std::string& mime);
virtual void cancelled();
virtual bool hasDnd();
virtual bool dndDone();
virtual void error(uint32_t code, const std::string& msg);
virtual void sendDndFinished();
2024-05-11 18:13:20 +02:00
void sendDndDropPerformed();
void sendDndAction(wl_data_device_manager_dnd_action a);
bool used = false;
bool dnd = false;
bool dndSuccess = false;
bool dropped = false;
2024-05-11 18:13:20 +02:00
WP<CWLDataDeviceResource> device;
WP<CWLDataSourceResource> self;
std::vector<std::string> mimeTypes;
uint32_t actions = 0;
private:
SP<CWlDataSource> resource;
wl_client* pClient = nullptr;
friend class CWLDataDeviceProtocol;
};
class CWLDataDeviceResource {
public:
CWLDataDeviceResource(SP<CWlDataDevice> resource_);
bool good();
wl_client* client();
void sendDataOffer(SP<CWLDataOfferResource> offer);
void sendEnter(uint32_t serial, SP<CWLSurfaceResource> surf, const Vector2D& local, SP<CWLDataOfferResource> offer);
2024-05-11 18:13:20 +02:00
void sendLeave();
void sendMotion(uint32_t timeMs, const Vector2D& local);
void sendDrop();
void sendSelection(SP<CWLDataOfferResource> offer);
WP<CWLDataDeviceResource> self;
private:
SP<CWlDataDevice> resource;
wl_client* pClient = nullptr;
friend class CWLDataDeviceProtocol;
};
class CWLDataDeviceManagerResource {
public:
CWLDataDeviceManagerResource(SP<CWlDataDeviceManager> resource_);
bool good();
WP<CWLDataDeviceResource> device;
std::vector<WP<CWLDataSourceResource>> sources;
private:
SP<CWlDataDeviceManager> resource;
};
class CWLDataDeviceProtocol : public IWaylandProtocol {
public:
CWLDataDeviceProtocol(const wl_interface* iface, const int& ver, const std::string& name);
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
// renders and damages the dnd icon, if present
void renderDND(CMonitor* pMonitor, timespec* when);
// for inputmgr to force refocus
// TODO: move handling to seatmgr
bool dndActive();
private:
void destroyResource(CWLDataDeviceManagerResource* resource);
void destroyResource(CWLDataDeviceResource* resource);
void destroyResource(CWLDataSourceResource* resource);
void destroyResource(CWLDataOfferResource* resource);
//
std::vector<SP<CWLDataDeviceManagerResource>> m_vManagers;
std::vector<SP<CWLDataDeviceResource>> m_vDevices;
std::vector<SP<CWLDataSourceResource>> m_vSources;
std::vector<SP<CWLDataOfferResource>> m_vOffers;
//
void onDestroyDataSource(WP<CWLDataSourceResource> source);
void setSelection(SP<IDataSource> source);
void sendSelectionToDevice(SP<CWLDataDeviceResource> dev, SP<IDataSource> sel);
void updateSelection();
void onKeyboardFocus();
struct {
WP<CWLDataDeviceResource> focusedDevice;
WP<CWLDataSourceResource> currentSource;
WP<CWLSurfaceResource> dndSurface;
WP<CWLSurfaceResource> originSurface;
2024-05-11 18:13:20 +02:00
bool overriddenCursor = false;
CHyprSignalListener dndSurfaceDestroy;
CHyprSignalListener dndSurfaceCommit;
2024-05-11 18:13:20 +02:00
// for ending a dnd
SP<HOOK_CALLBACK_FN> mouseMove;
SP<HOOK_CALLBACK_FN> mouseButton;
SP<HOOK_CALLBACK_FN> touchUp;
SP<HOOK_CALLBACK_FN> touchMove;
} dnd;
void abortDrag();
void initiateDrag(WP<CWLDataSourceResource> currentSource, SP<CWLSurfaceResource> dragSurface, SP<CWLSurfaceResource> origin);
2024-05-11 18:13:20 +02:00
void updateDrag();
void dropDrag();
void completeDrag();
void resetDndState();
bool wasDragSuccessful();
2024-05-11 18:13:20 +02:00
//
SP<CWLDataDeviceResource> dataDeviceForClient(wl_client*);
friend class CSeatManager;
friend class CWLDataDeviceManagerResource;
friend class CWLDataDeviceResource;
friend class CWLDataSourceResource;
friend class CWLDataOfferResource;
struct {
CHyprSignalListener onKeyboardFocusChange;
} listeners;
};
namespace PROTO {
inline UP<CWLDataDeviceProtocol> data;
};