aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/protocols/core/DataDevice.hpp
blob: ae22e47449a5e4aa3c0b5d39740c768359b1f9cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#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"
#include "../types/DataDevice.hpp"

class CWLDataDeviceResource;
class CWLDataDeviceManagerResource;
class CWLDataSourceResource;
class CWLDataOfferResource;

class CWLSurfaceResource;
class CMonitor;

class CWLDataOfferResource : public IDataOffer {
  public:
    CWLDataOfferResource(SP<CWlDataOffer> resource_, SP<IDataSource> source_);
    ~CWLDataOfferResource();

    bool                             good();
    void                             sendData();

    virtual eDataSourceType          type();
    virtual SP<CWLDataOfferResource> getWayland();
    virtual SP<CX11DataOffer>        getX11();
    virtual SP<IDataSource>          getSource();

    WP<IDataSource>                  source;
    WP<CWLDataOfferResource>         self;

    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();
    virtual uint32_t                 actions(); // wl_data_device_manager.dnd_action
    virtual eDataSourceType          type();
    virtual void                     sendDndDropPerformed();
    virtual void                     sendDndAction(wl_data_device_manager_dnd_action a);

    bool                             used       = false;
    bool                             dnd        = false;
    bool                             dndSuccess = false;
    bool                             dropped    = false;

    WP<CWLDataDeviceResource>        device;
    WP<CWLDataSourceResource>        self;

    std::vector<std::string>         mimeTypes;
    uint32_t                         supportedActions = 0;

  private:
    SP<CWlDataSource> resource;
    wl_client*        pClient = nullptr;

    friend class CWLDataDeviceProtocol;
};

class CWLDataDeviceResource : public IDataDevice {
  public:
    CWLDataDeviceResource(SP<CWlDataDevice> resource_);

    bool                              good();
    wl_client*                        client();

    virtual SP<CWLDataDeviceResource> getWayland();
    virtual SP<CX11DataDevice>        getX11();
    virtual void                      sendDataOffer(SP<IDataOffer> offer);
    virtual void                      sendEnter(uint32_t serial, SP<CWLSurfaceResource> surf, const Vector2D& local, SP<IDataOffer> offer);
    virtual void                      sendLeave();
    virtual void                      sendMotion(uint32_t timeMs, const Vector2D& local);
    virtual void                      sendDrop();
    virtual void                      sendSelection(SP<IDataOffer> offer);
    virtual eDataSourceType           type();

    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(PHLMONITOR 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<IDataDevice> dev, SP<IDataSource> sel);
    void updateSelection();
    void onKeyboardFocus();
    void onDndPointerFocus();

    struct {
        WP<IDataDevice>        focusedDevice;
        WP<IDataSource>        currentSource;
        WP<CWLSurfaceResource> dndSurface;
        WP<CWLSurfaceResource> originSurface;
        bool                   overriddenCursor = false;
        CHyprSignalListener    dndSurfaceDestroy;
        CHyprSignalListener    dndSurfaceCommit;

        // 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);
    void updateDrag();
    void dropDrag();
    void completeDrag();
    void resetDndState();
    bool wasDragSuccessful();

    //
    SP<IDataDevice> dataDeviceForClient(wl_client*);

    friend class CSeatManager;
    friend class CWLDataDeviceManagerResource;
    friend class CWLDataDeviceResource;
    friend class CWLDataSourceResource;
    friend class CWLDataOfferResource;

    struct {
        CHyprSignalListener onKeyboardFocusChange;
        CHyprSignalListener onDndPointerFocusChange;
    } listeners;
};

namespace PROTO {
    inline UP<CWLDataDeviceProtocol> data;
};