Skip to content

Commit 7ba0750

Browse files
committed
Refactor tool panel DnD functionality (#252).
This commit refactors two elements of the drag-n-drop tool docking to work under Wayland: 1) Replace popup "DockSite" windows used to display drop zones and shadow with an imposter which displays then over a screenshot of the (hidden) tabs. The original "DockSite" code is retained and enabled on macOS, as the screenshots don't seem to work properly on macOS 10.13. 2) Add alternate window dragging using DnD rather than mouse capture and window repositioning which is used under Wayland only.
1 parent c8fcc66 commit 7ba0750

File tree

8 files changed

+1104
-57
lines changed

8 files changed

+1104
-57
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ APP_OBJS := \
440440
src/PopupTipWindow.$(BUILD_TYPE).o \
441441
src/ProceduralBitmap.$(BUILD_TYPE).o \
442442
src/profile.$(BUILD_TYPE).o \
443+
src/ProxyDropTarget.$(BUILD_TYPE).o \
443444
src/RangeChoiceLinear.$(BUILD_TYPE).o \
444445
src/RangeDialog.$(BUILD_TYPE).o \
445446
src/RangeProcessor.$(BUILD_TYPE).o \
@@ -563,6 +564,7 @@ TEST_OBJS := \
563564
src/Palette.$(BUILD_TYPE).o \
564565
src/PopupTipWindow.$(BUILD_TYPE).o \
565566
src/ProceduralBitmap.$(BUILD_TYPE).o \
567+
src/ProxyDropTarget.$(BUILD_TYPE).o \
566568
src/RangeDialog.$(BUILD_TYPE).o \
567569
src/RangeProcessor.$(BUILD_TYPE).o \
568570
src/search.$(BUILD_TYPE).o \

src/ProxyDropTarget.cpp

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/* Reverse Engineer's Hex Editor
2+
* Copyright (C) 2025 Daniel Collins <solemnwarning@solemnwarning.net>
3+
*
4+
* This program is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 as published by
6+
* the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope that it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11+
* more details.
12+
*
13+
* You should have received a copy of the GNU General Public License along with
14+
* this program; if not, write to the Free Software Foundation, Inc., 51
15+
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16+
*/
17+
18+
#include "platform.hpp"
19+
20+
#include <assert.h>
21+
22+
#include "ProxyDropTarget.hpp"
23+
24+
wxDEFINE_EVENT(REHex::DROP_ENTER, REHex::DropEvent);
25+
wxDEFINE_EVENT(REHex::DROP_LEAVE, REHex::DropEvent);
26+
wxDEFINE_EVENT(REHex::DROP_MOTION, REHex::DropEvent);
27+
wxDEFINE_EVENT(REHex::DROP_DROP, REHex::DropEvent);
28+
wxDEFINE_EVENT(REHex::DROP_DATA, REHex::DropEvent);
29+
30+
REHex::ProxyDropTarget::ProxyDropTarget(wxEvtHandler *handler, wxDataObject *data):
31+
wxDropTarget(data),
32+
m_handler(handler) {}
33+
34+
wxDragResult REHex::ProxyDropTarget::OnData(wxCoord x, wxCoord y, wxDragResult defResult)
35+
{
36+
DropEvent event(DROP_DATA, x, y, defResult);
37+
m_handler->ProcessEvent(event);
38+
39+
return event.m_result;
40+
}
41+
42+
wxDragResult REHex::ProxyDropTarget::OnDragOver(wxCoord x, wxCoord y, wxDragResult defResult)
43+
{
44+
DropEvent event(DROP_MOTION, x, y, defResult);
45+
m_handler->ProcessEvent(event);
46+
47+
return event.m_result;
48+
}
49+
50+
bool REHex::ProxyDropTarget::OnDrop(wxCoord x, wxCoord y)
51+
{
52+
DropEvent event(DROP_DROP, x, y, wxDragNone);
53+
m_handler->ProcessEvent(event);
54+
55+
return event.m_accept;
56+
}
57+
58+
wxDragResult REHex::ProxyDropTarget::OnEnter(wxCoord x, wxCoord y, wxDragResult defResult)
59+
{
60+
DropEvent event(DROP_ENTER, x, y, defResult);
61+
m_handler->ProcessEvent(event);
62+
63+
return event.m_result;
64+
}
65+
66+
void REHex::ProxyDropTarget::OnLeave()
67+
{
68+
DropEvent event(DROP_LEAVE, -1, -1, wxDragNone);
69+
m_handler->ProcessEvent(event);
70+
}
71+
72+
REHex::DropEvent::DropEvent(wxEventType eventType, wxCoord x, wxCoord y, wxDragResult defResult):
73+
wxEvent(0, eventType),
74+
m_x(x),
75+
m_y(y),
76+
m_default_result(defResult),
77+
m_result(defResult),
78+
m_accept(true) {}
79+
80+
wxEvent *REHex::DropEvent::Clone() const
81+
{
82+
return new DropEvent(*this);
83+
}
84+
85+
wxCoord REHex::DropEvent::GetX() const
86+
{
87+
assert(GetEventType() == DROP_ENTER || GetEventType() == DROP_MOTION || GetEventType() == DROP_DROP || GetEventType() == DROP_DATA);
88+
return m_x;
89+
}
90+
91+
wxCoord REHex::DropEvent::GetY() const
92+
{
93+
assert(GetEventType() == DROP_ENTER || GetEventType() == DROP_MOTION || GetEventType() == DROP_DROP || GetEventType() == DROP_DATA);
94+
return m_y;
95+
}
96+
97+
wxDragResult REHex::DropEvent::GetDefaultResult() const
98+
{
99+
assert(GetEventType() == DROP_ENTER || GetEventType() == DROP_MOTION || GetEventType() == DROP_DATA);
100+
return m_default_result;
101+
}
102+
103+
void REHex::DropEvent::SetResult(wxDragResult result)
104+
{
105+
assert(GetEventType() == DROP_ENTER || GetEventType() == DROP_MOTION || GetEventType() == DROP_DATA);
106+
m_result = result;
107+
}
108+
109+
void REHex::DropEvent::AcceptData(bool accept)
110+
{
111+
assert(GetEventType() == DROP_DROP);
112+
m_accept = accept;
113+
}
114+
115+
void REHex::DropEvent::RejectData()
116+
{
117+
assert(GetEventType() == DROP_DROP);
118+
m_accept = false;
119+
}

src/ProxyDropTarget.hpp

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/* Reverse Engineer's Hex Editor
2+
* Copyright (C) 2025 Daniel Collins <solemnwarning@solemnwarning.net>
3+
*
4+
* This program is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 as published by
6+
* the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope that it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11+
* more details.
12+
*
13+
* You should have received a copy of the GNU General Public License along with
14+
* this program; if not, write to the Free Software Foundation, Inc., 51
15+
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16+
*/
17+
18+
#ifndef REHEX_PROXYDROPTARGET_HPP
19+
#define REHEX_PROXYDROPTARGET_HPP
20+
21+
#include <wx/dnd.h>
22+
#include <wx/event.h>
23+
24+
namespace REHex
25+
{
26+
class DropEvent;
27+
28+
wxDECLARE_EVENT(DROP_ENTER, DropEvent);
29+
wxDECLARE_EVENT(DROP_LEAVE, DropEvent);
30+
wxDECLARE_EVENT(DROP_MOTION, DropEvent);
31+
wxDECLARE_EVENT(DROP_DROP, DropEvent);
32+
wxDECLARE_EVENT(DROP_DATA, DropEvent);
33+
34+
/**
35+
* @brief wxDropTarget implementation which raises events in a target wxEvtHandler
36+
*
37+
* @param handler wxEvtHandler to receive events.
38+
* @param data Initial wxDataObject to receive data.
39+
*
40+
* This class proxies wxDropTarget to a wxWindow or other wxEvtHandler to be processed there.
41+
*
42+
* The following events will be raised:
43+
*
44+
* DROP_ENTER - Pointer entered drop target.
45+
* DROP_LEAVE - Pointer left drop target.
46+
* DROP_MOTION - Pointer moved within drop target.
47+
* DROP_DROP - Mouse button was released over drop target.
48+
* DROP_DATA - Raised after DROP_DROP accepts the data.
49+
*/
50+
class ProxyDropTarget: public wxDropTarget
51+
{
52+
private:
53+
wxEvtHandler *m_handler;
54+
55+
public:
56+
ProxyDropTarget(wxEvtHandler *handler, wxDataObject *data = NULL);
57+
58+
virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult defResult) override;
59+
virtual wxDragResult OnDragOver(wxCoord x, wxCoord y, wxDragResult defResult) override;
60+
virtual bool OnDrop(wxCoord x, wxCoord y) override;
61+
virtual wxDragResult OnEnter(wxCoord x, wxCoord y, wxDragResult defResult) override;
62+
virtual void OnLeave() override;
63+
};
64+
65+
/**
66+
* @brief Event object raised by ProxyDropTarget
67+
*/
68+
class DropEvent: public wxEvent
69+
{
70+
private:
71+
wxCoord m_x, m_y;
72+
73+
wxDragResult m_default_result;
74+
wxDragResult m_result;
75+
76+
bool m_accept;
77+
78+
public:
79+
DropEvent(wxEventType eventType, wxCoord x, wxCoord y, wxDragResult defResult);
80+
virtual ~DropEvent() override = default;
81+
82+
virtual wxEvent *Clone() const override;
83+
84+
/**
85+
* @brief Returns the mouse position within the drop target.
86+
*
87+
* Valid for DROP_ENTER, DROP_MOTION, DROP_DROP and DROP_DATA events.
88+
*/
89+
wxCoord GetX() const;
90+
91+
/**
92+
* @brief Returns the mouse position within the drop target.
93+
*
94+
* Valid for DROP_ENTER, DROP_MOTION, DROP_DROP and DROP_DATA events.
95+
*/
96+
wxCoord GetY() const;
97+
98+
/**
99+
* @brief Returns the requested drag type (move/copy/etc).
100+
*
101+
* Valid for DROP_ENTER, DROP_MOTION and DROP_DATA events.
102+
*/
103+
wxDragResult GetDefaultResult() const;
104+
105+
/**
106+
* @brief Set the drag event type.
107+
*
108+
* Valid for DROP_ENTER, DROP_MOTION and DROP_DATA events. Defaults to the value
109+
* returned by GetDefaultResult().
110+
*/
111+
void SetResult(wxDragResult result);
112+
113+
/**
114+
* @brief Accept the data in a DROP_DROP event.
115+
*
116+
* The default behaviour is to accept data if AcceptData() or RejectData() is not
117+
* called within the DROP_DROP event.
118+
*/
119+
void AcceptData(bool accept = true);
120+
121+
/**
122+
* @brief Reject the data in a DROP_DROP event.
123+
* * The default behaviour is to accept data if AcceptData() or RejectData() is not
124+
* called within the DROP_DROP event.
125+
*/
126+
void RejectData();
127+
128+
friend ProxyDropTarget;
129+
};
130+
}
131+
132+
#endif /* !REHEX_PROXYDROPTARGET_HPP */

0 commit comments

Comments
 (0)