add support XDND for X
This commit is contained in:
parent
dec3bdc350
commit
07a971c6ef
@ -103,12 +103,29 @@ namespace std {
|
|||||||
|
|
||||||
} // filesystem
|
} // filesystem
|
||||||
} // experimental
|
} // experimental
|
||||||
|
|
||||||
|
namespace filesystem
|
||||||
|
{
|
||||||
|
using namespace experimental::filesystem;
|
||||||
|
}
|
||||||
} // std
|
} // std
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# undef NANA_USING_STD_FILESYSTEM
|
# undef NANA_USING_STD_FILESYSTEM
|
||||||
# define NANA_USING_STD_FILESYSTEM 1
|
# define NANA_USING_STD_FILESYSTEM 1
|
||||||
|
# if ((defined(_MSC_VER) && (_MSC_VER >= 1912) && defined(_MSVC_LANG) && _MSVC_LANG >= 201703)) || \
|
||||||
|
((__cplusplus >= 201703L) && \
|
||||||
|
(defined(__clang__) && (__clang_major__ >= 7) || \
|
||||||
|
(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 8))) )
|
||||||
|
# include <filesystem>
|
||||||
|
# else
|
||||||
# include <experimental/filesystem>
|
# include <experimental/filesystem>
|
||||||
|
namespace std{
|
||||||
|
namespace filesystem{
|
||||||
|
using namespace std::experimental::filesystem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -508,8 +525,13 @@ namespace std {
|
|||||||
# endif
|
# endif
|
||||||
} // filesystem
|
} // filesystem
|
||||||
} // experimental
|
} // experimental
|
||||||
|
|
||||||
|
namespace filesystem {
|
||||||
|
using namespace std::experimental::filesystem;
|
||||||
|
}
|
||||||
} // std
|
} // std
|
||||||
|
|
||||||
|
|
||||||
#endif //NANA_USING_NANA_FILESYSTEM
|
#endif //NANA_USING_NANA_FILESYSTEM
|
||||||
|
|
||||||
#include <nana/pop_ignore_diagnostic>
|
#include <nana/pop_ignore_diagnostic>
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
#include "basis.hpp"
|
#include "basis.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <nana/filesystem/filesystem.hpp>
|
||||||
|
|
||||||
namespace nana
|
namespace nana
|
||||||
{
|
{
|
||||||
@ -41,22 +42,48 @@ namespace nana
|
|||||||
implementation* const impl_;
|
implementation* const impl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct dragdrop_data;
|
||||||
|
}
|
||||||
|
|
||||||
class dragdrop
|
class dragdrop
|
||||||
{
|
{
|
||||||
struct implementation;
|
struct implementation;
|
||||||
|
|
||||||
|
/// Non-copyable
|
||||||
dragdrop(const dragdrop&) = delete;
|
dragdrop(const dragdrop&) = delete;
|
||||||
dragdrop& operator=(const dragdrop&) = delete;
|
dragdrop& operator=(const dragdrop&) = delete;
|
||||||
|
|
||||||
|
/// Non-movable
|
||||||
dragdrop(dragdrop&&) = delete;
|
dragdrop(dragdrop&&) = delete;
|
||||||
dragdrop& operator=(dragdrop&&) = delete;
|
dragdrop& operator=(dragdrop&&) = delete;
|
||||||
public:
|
public:
|
||||||
|
class data
|
||||||
|
{
|
||||||
|
friend struct dragdrop::implementation;
|
||||||
|
|
||||||
|
/// Non-copyable
|
||||||
|
data(const data&) = delete;
|
||||||
|
data& operator=(const data&) = delete;
|
||||||
|
public:
|
||||||
|
data();
|
||||||
|
data(data&&);
|
||||||
|
~data();
|
||||||
|
|
||||||
|
data& operator=(data&& rhs);
|
||||||
|
|
||||||
|
void insert(std::filesystem::path);
|
||||||
|
private:
|
||||||
|
detail::dragdrop_data* real_data_;
|
||||||
|
};
|
||||||
|
|
||||||
dragdrop(window source);
|
dragdrop(window source);
|
||||||
~dragdrop();
|
~dragdrop();
|
||||||
|
|
||||||
void condition(std::function<bool()> predicate_fn);
|
void condition(std::function<bool()> predicate_fn);
|
||||||
|
void prepare_data(std::function<data()> generator);
|
||||||
void make_data(std::function<void()> generator);
|
void drop_finished(std::function<void(bool)> finish_fn);
|
||||||
private:
|
private:
|
||||||
implementation* const impl_;
|
implementation* const impl_;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -36,6 +36,8 @@
|
|||||||
|
|
||||||
#include "posix/msg_dispatcher.hpp"
|
#include "posix/msg_dispatcher.hpp"
|
||||||
|
|
||||||
|
#include <iostream> //debug
|
||||||
|
|
||||||
namespace nana
|
namespace nana
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
@ -500,11 +502,11 @@ namespace detail
|
|||||||
atombase_.net_wm_window_type_dialog = ::XInternAtom(display_, "_NET_WM_WINDOW_TYPE_DIALOG", False);
|
atombase_.net_wm_window_type_dialog = ::XInternAtom(display_, "_NET_WM_WINDOW_TYPE_DIALOG", False);
|
||||||
atombase_.motif_wm_hints = ::XInternAtom(display_, "_MOTIF_WM_HINTS", False);
|
atombase_.motif_wm_hints = ::XInternAtom(display_, "_MOTIF_WM_HINTS", False);
|
||||||
|
|
||||||
atombase_.clipboard = ::XInternAtom(display_, "CLIPBOARD", True);
|
atombase_.clipboard = ::XInternAtom(display_, "CLIPBOARD", False);
|
||||||
atombase_.text = ::XInternAtom(display_, "TEXT", True);
|
atombase_.text = ::XInternAtom(display_, "TEXT", False);
|
||||||
atombase_.text_uri_list = ::XInternAtom(display_, "text/uri-list", True);
|
atombase_.text_uri_list = ::XInternAtom(display_, "text/uri-list", False);
|
||||||
atombase_.utf8_string = ::XInternAtom(display_, "UTF8_STRING", True);
|
atombase_.utf8_string = ::XInternAtom(display_, "UTF8_STRING", False);
|
||||||
atombase_.targets = ::XInternAtom(display_, "TARGETS", True);
|
atombase_.targets = ::XInternAtom(display_, "TARGETS", False);
|
||||||
|
|
||||||
atombase_.xdnd_aware = ::XInternAtom(display_, "XdndAware", False);
|
atombase_.xdnd_aware = ::XInternAtom(display_, "XdndAware", False);
|
||||||
atombase_.xdnd_enter = ::XInternAtom(display_, "XdndEnter", False);
|
atombase_.xdnd_enter = ::XInternAtom(display_, "XdndEnter", False);
|
||||||
@ -514,6 +516,7 @@ namespace detail
|
|||||||
atombase_.xdnd_drop = ::XInternAtom(display_, "XdndDrop", False);
|
atombase_.xdnd_drop = ::XInternAtom(display_, "XdndDrop", False);
|
||||||
atombase_.xdnd_selection = ::XInternAtom(display_, "XdndSelection", False);
|
atombase_.xdnd_selection = ::XInternAtom(display_, "XdndSelection", False);
|
||||||
atombase_.xdnd_typelist = ::XInternAtom(display_, "XdndTypeList", False);
|
atombase_.xdnd_typelist = ::XInternAtom(display_, "XdndTypeList", False);
|
||||||
|
atombase_.xdnd_leave = ::XInternAtom(display_, "XdndLeave", False);
|
||||||
atombase_.xdnd_finished = ::XInternAtom(display_, "XdndFinished", False);
|
atombase_.xdnd_finished = ::XInternAtom(display_, "XdndFinished", False);
|
||||||
|
|
||||||
msg_dispatcher_ = new msg_dispatcher(display_);
|
msg_dispatcher_ = new msg_dispatcher(display_);
|
||||||
@ -1041,7 +1044,7 @@ namespace detail
|
|||||||
msg_dispatcher_->dispatch(reinterpret_cast<Window>(modal));
|
msg_dispatcher_->dispatch(reinterpret_cast<Window>(modal));
|
||||||
}
|
}
|
||||||
|
|
||||||
void platform_spec::msg_dispatch(std::function<bool(const msg_packet_tag&)> msg_filter_fn)
|
void platform_spec::msg_dispatch(std::function<propagation_chain(const msg_packet_tag&)> msg_filter_fn)
|
||||||
{
|
{
|
||||||
msg_dispatcher_->dispatch(msg_filter_fn);
|
msg_dispatcher_->dispatch(msg_filter_fn);
|
||||||
|
|
||||||
@ -1116,15 +1119,49 @@ namespace detail
|
|||||||
platform_scope_guard lock;
|
platform_scope_guard lock;
|
||||||
if(0 != xdnd_.dragdrop.count(wd))
|
if(0 != xdnd_.dragdrop.count(wd))
|
||||||
return false;
|
return false;
|
||||||
|
#if 0 //deprecated
|
||||||
|
std::cout<<"ChangeProperty XdndAware"<<std::endl;
|
||||||
int dndver = 4;
|
int dndver = 4;
|
||||||
::XChangeProperty(display_, reinterpret_cast<Window>(wd), atombase_.xdnd_aware, XA_ATOM, sizeof(int) * 8,
|
::XChangeProperty(display_, reinterpret_cast<Window>(wd), atombase_.xdnd_aware, XA_ATOM, sizeof(int) * 8,
|
||||||
PropModeReplace, reinterpret_cast<unsigned char*>(&dndver), 1);
|
PropModeReplace, reinterpret_cast<unsigned char*>(&dndver), 1);
|
||||||
|
#endif
|
||||||
xdnd_.dragdrop[wd] = ddrop;
|
xdnd_.dragdrop[wd] = ddrop;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t platform_spec::dragdrop_target(native_window_type wd, bool insert, std::size_t count)
|
||||||
|
{
|
||||||
|
std::size_t new_val = 0;
|
||||||
|
platform_scope_guard lock;
|
||||||
|
if(insert)
|
||||||
|
{
|
||||||
|
new_val = (xdnd_.targets[wd] += count);
|
||||||
|
if(1 == new_val)
|
||||||
|
{
|
||||||
|
std::cout<<"ChangeProperty XdndAware"<<std::endl;
|
||||||
|
int dndver = 5;
|
||||||
|
::XChangeProperty(display_, reinterpret_cast<Window>(wd), atombase_.xdnd_aware, XA_ATOM, sizeof(int) * 8,
|
||||||
|
PropModeReplace, reinterpret_cast<unsigned char*>(&dndver), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto i = xdnd_.targets.find(wd);
|
||||||
|
if(i == xdnd_.targets.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
new_val = (i->second > count ? i->second - count : 0);
|
||||||
|
if(0 == new_val)
|
||||||
|
{
|
||||||
|
xdnd_.targets.erase(wd);
|
||||||
|
::XDeleteProperty(display_, reinterpret_cast<Window>(wd), atombase_.xdnd_aware);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
i->second = new_val;
|
||||||
|
}
|
||||||
|
return new_val;
|
||||||
|
}
|
||||||
|
|
||||||
x11_dragdrop_interface* platform_spec::remove_dragdrop(native_window_type wd)
|
x11_dragdrop_interface* platform_spec::remove_dragdrop(native_window_type wd)
|
||||||
{
|
{
|
||||||
platform_scope_guard lock;
|
platform_scope_guard lock;
|
||||||
@ -1196,6 +1233,7 @@ namespace detail
|
|||||||
}
|
}
|
||||||
else if(evt.xselection.property == self.atombase_.xdnd_selection)
|
else if(evt.xselection.property == self.atombase_.xdnd_selection)
|
||||||
{
|
{
|
||||||
|
std::cout<<"Platform SelectionNotfy by XdndSelection, type="<<type<<", good_type="<<self.xdnd_.good_type<<", bytes_left="<<bytes_left<<std::endl;
|
||||||
bool accepted = false;
|
bool accepted = false;
|
||||||
msg.kind = msg_packet_tag::pkt_family::mouse_drop;
|
msg.kind = msg_packet_tag::pkt_family::mouse_drop;
|
||||||
msg.u.mouse_drop.window = 0;
|
msg.u.mouse_drop.window = 0;
|
||||||
@ -1209,6 +1247,8 @@ namespace detail
|
|||||||
{
|
{
|
||||||
auto files = new std::vector<std::string>;
|
auto files = new std::vector<std::string>;
|
||||||
std::stringstream ss(reinterpret_cast<char*>(data));
|
std::stringstream ss(reinterpret_cast<char*>(data));
|
||||||
|
|
||||||
|
std::cout<<" data:["<<ss.str()<<"]"<<std::endl;
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
std::string file;
|
std::string file;
|
||||||
@ -1228,6 +1268,8 @@ namespace detail
|
|||||||
|
|
||||||
files->push_back(file);
|
files->push_back(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout<<" file size:"<<files->size()<<std::endl;
|
||||||
if(files->size())
|
if(files->size())
|
||||||
{
|
{
|
||||||
msg.u.mouse_drop.window = evt.xselection.requestor;
|
msg.u.mouse_drop.window = evt.xselection.requestor;
|
||||||
@ -1241,9 +1283,12 @@ namespace detail
|
|||||||
accepted = true;
|
accepted = true;
|
||||||
::XFree(data);
|
::XFree(data);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
std::cout<<" invalid property"<<std::endl;
|
||||||
}
|
}
|
||||||
XEvent respond;
|
::XEvent respond;
|
||||||
::memset(respond.xclient.data.l, 0, sizeof(respond.xclient.data.l));
|
::memset(respond.xclient.data.l, 0, sizeof(respond.xclient.data.l));
|
||||||
|
respond.xany.type = ClientMessage;
|
||||||
respond.xclient.display = self.display_;
|
respond.xclient.display = self.display_;
|
||||||
respond.xclient.window = self.xdnd_.wd_src;
|
respond.xclient.window = self.xdnd_.wd_src;
|
||||||
respond.xclient.message_type = self.atombase_.xdnd_finished;
|
respond.xclient.message_type = self.atombase_.xdnd_finished;
|
||||||
@ -1266,6 +1311,16 @@ namespace detail
|
|||||||
}
|
}
|
||||||
else if(SelectionRequest == evt.type)
|
else if(SelectionRequest == evt.type)
|
||||||
{
|
{
|
||||||
|
std::cout<<"Event SelectionRequest in platform spec";
|
||||||
|
//Skip if it is requested by XDND, it will be processed by dragdrop's xdnd_protocol
|
||||||
|
if(self.atombase_.xdnd_selection == evt.xselectionrequest.selection)
|
||||||
|
{
|
||||||
|
std::cout<<", xdnd_selection"<<std::endl;
|
||||||
|
return 0; //
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout<<std::endl;
|
||||||
|
|
||||||
auto disp = evt.xselectionrequest.display;
|
auto disp = evt.xselectionrequest.display;
|
||||||
XEvent respond;
|
XEvent respond;
|
||||||
|
|
||||||
@ -1311,6 +1366,7 @@ namespace detail
|
|||||||
{
|
{
|
||||||
if(self.atombase_.xdnd_enter == evt.xclient.message_type)
|
if(self.atombase_.xdnd_enter == evt.xclient.message_type)
|
||||||
{
|
{
|
||||||
|
std::cout<<"Platform: XdndEnter";
|
||||||
const Atom * atoms = reinterpret_cast<const Atom*>(&(evt.xclient.data.l[2]));
|
const Atom * atoms = reinterpret_cast<const Atom*>(&(evt.xclient.data.l[2]));
|
||||||
unsigned long len = 3;
|
unsigned long len = 3;
|
||||||
unsigned char * data = 0;
|
unsigned char * data = 0;
|
||||||
@ -1322,54 +1378,119 @@ namespace detail
|
|||||||
Atom type;
|
Atom type;
|
||||||
int format;
|
int format;
|
||||||
unsigned long bytes_left;
|
unsigned long bytes_left;
|
||||||
::XGetWindowProperty(self.display_, self.xdnd_.wd_src, self.atombase_.xdnd_typelist, 0, 0, False,
|
auto status = ::XGetWindowProperty(self.display_, self.xdnd_.wd_src, self.atombase_.xdnd_typelist, 0, 0, False,
|
||||||
XA_ATOM, &type, &format, &len, &bytes_left, &data);
|
XA_ATOM, &type, &format, &len, &bytes_left, &data);
|
||||||
|
|
||||||
|
std::cout<<", XGetWindowProperty xdnd_typelist = "<<status<<" bytes_left="<<bytes_left<<std::endl;
|
||||||
|
|
||||||
if(bytes_left > 0)
|
if(bytes_left > 0)
|
||||||
{
|
{
|
||||||
::XGetWindowProperty(self.display_, self.xdnd_.wd_src, self.atombase_.xdnd_typelist,
|
::XGetWindowProperty(self.display_, self.xdnd_.wd_src, self.atombase_.xdnd_typelist,
|
||||||
0, bytes_left, False, XA_ATOM,
|
0, bytes_left, False, XA_ATOM,
|
||||||
&type, &format, &len, &bytes_left, &data);
|
&type, &format, &len, &bytes_left, &data);
|
||||||
|
|
||||||
|
std::cout<<" format="<<format<<" len="<<len<<" bytes_left="<<bytes_left;
|
||||||
|
auto type_name = ::XGetAtomName(self.display_, type);
|
||||||
|
if(type_name)
|
||||||
|
{
|
||||||
|
std::cout<<" type="<<type_name;
|
||||||
|
::XFree(type_name);
|
||||||
|
}
|
||||||
|
std::cout<<std::endl;
|
||||||
|
|
||||||
if(XA_ATOM == type && len > 0)
|
if(XA_ATOM == type && len > 0)
|
||||||
atoms = reinterpret_cast<const Atom*>(data);
|
atoms = reinterpret_cast<const Atom*>(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
std::cout<<", less than 3 types"<<std::endl;
|
||||||
|
|
||||||
|
#define DEBUG_XdndDirectSave
|
||||||
|
#ifdef DEBUG_XdndDirectSave
|
||||||
|
Atom XdndDirectSave = 0;
|
||||||
|
#endif
|
||||||
self.xdnd_.good_type = None;
|
self.xdnd_.good_type = None;
|
||||||
for(unsigned long i = 0; i < len; ++i)
|
for(unsigned long i = 0; i < len; ++i)
|
||||||
{
|
{
|
||||||
|
auto name = XGetAtomName(self.display_, atoms[i]); //debug
|
||||||
|
if(name)
|
||||||
|
{
|
||||||
|
std::cout<<" Supported type: "<<name<<std::endl;
|
||||||
|
#ifdef DEBUG_XdndDirectSave
|
||||||
|
if(strstr(name, "XdndDirectSave"))
|
||||||
|
XdndDirectSave = atoms[i];
|
||||||
|
#endif
|
||||||
|
::XFree(name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
std::cout<<" Supported type: no name("<<atoms[i]<<")"<<std::endl;
|
||||||
|
|
||||||
if(atoms[i] == self.atombase_.text_uri_list)
|
if(atoms[i] == self.atombase_.text_uri_list)
|
||||||
{
|
{
|
||||||
self.xdnd_.good_type = self.atombase_.text_uri_list;
|
self.xdnd_.good_type = self.atombase_.text_uri_list;
|
||||||
break;
|
//break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data)
|
if(data)
|
||||||
::XFree(data);
|
::XFree(data);
|
||||||
|
|
||||||
|
#ifdef DEBUG_XdndDirectSave //debug
|
||||||
|
if(XdndDirectSave)
|
||||||
|
{
|
||||||
|
Atom type;
|
||||||
|
int format;
|
||||||
|
unsigned long bytes_left;
|
||||||
|
|
||||||
|
auto status = ::XGetWindowProperty(self.display_, self.xdnd_.wd_src, XdndDirectSave, 0, 0, False, XA_ATOM, &type, &format, &len, &bytes_left, &data);
|
||||||
|
auto name = XGetAtomName(self.display_, type); //debug
|
||||||
|
if(name)
|
||||||
|
{
|
||||||
|
std::cout<<" XdndDirectSave text/plain Atom: "<<name<<std::endl;
|
||||||
|
::XFree(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout<<", XGetWindowProperty XdndDirectSave = "<<status<<" bytes_left="<<bytes_left<<std::endl;
|
||||||
|
|
||||||
|
if(bytes_left > 0)
|
||||||
|
{
|
||||||
|
::XGetWindowProperty(self.display_, self.xdnd_.wd_src, XdndDirectSave,
|
||||||
|
0, bytes_left, False, type,
|
||||||
|
&type, &format, &len, &bytes_left, &data);
|
||||||
|
|
||||||
|
std::cout<<" XdndDirectSave Data:["<<(char*)data<<"]"<<std::endl;
|
||||||
|
std::system("cp xds.txt /home/jinhao/xds.txt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
else if(self.atombase_.xdnd_position == evt.xclient.message_type)
|
else if(self.atombase_.xdnd_position == evt.xclient.message_type)
|
||||||
{
|
{
|
||||||
|
std::cout<<"Platform: XdndPosition"<<std::endl;
|
||||||
|
|
||||||
Window wd_src = evt.xclient.data.l[0];
|
Window wd_src = evt.xclient.data.l[0];
|
||||||
int x = (evt.xclient.data.l[2] >> 16);
|
int x = (evt.xclient.data.l[2] >> 16);
|
||||||
int y = (evt.xclient.data.l[2] & 0xFFFF);
|
int y = (evt.xclient.data.l[2] & 0xFFFF);
|
||||||
|
|
||||||
bool accepted = false;
|
int accepted = 0; //0 means refusing, 1 means accpeting
|
||||||
//We have got the type what we want.
|
//We have got the type what we want.
|
||||||
if(self.xdnd_.good_type != None)
|
if(self.xdnd_.good_type != None)
|
||||||
{
|
{
|
||||||
Window child;
|
Window child;
|
||||||
::XTranslateCoordinates(self.display_, self.root_window(), evt.xclient.window, x, y, &self.xdnd_.pos.x, &self.xdnd_.pos.y, &child);
|
::XTranslateCoordinates(self.display_, self.root_window(), evt.xclient.window, x, y, &self.xdnd_.pos.x, &self.xdnd_.pos.y, &child);
|
||||||
|
|
||||||
|
std::cout<<" find_window"<<std::endl;
|
||||||
auto wd = bedrock.wd_manager().find_window(reinterpret_cast<native_window_type>(evt.xclient.window), self.xdnd_.pos);
|
auto wd = bedrock.wd_manager().find_window(reinterpret_cast<native_window_type>(evt.xclient.window), self.xdnd_.pos);
|
||||||
if(wd && wd->flags.dropable)
|
if(wd && wd->flags.dropable)
|
||||||
{
|
{
|
||||||
accepted = true;
|
//Cache the time stamp in XdndPosition, and the time stamp must be passed to XConvertSelection for requesting selection
|
||||||
self.xdnd_.timestamp = evt.xclient.data.l[3];
|
self.xdnd_.timestamp = evt.xclient.data.l[3];
|
||||||
self.xdnd_.pos = wd->pos_root;
|
self.xdnd_.pos = wd->pos_root;
|
||||||
|
accepted = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout<<" return,"<<wd<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEvent respond;
|
XEvent respond;
|
||||||
@ -1383,18 +1504,30 @@ namespace detail
|
|||||||
//Target window
|
//Target window
|
||||||
respond.xclient.data.l[0] = evt.xclient.window;
|
respond.xclient.data.l[0] = evt.xclient.window;
|
||||||
//Accept set
|
//Accept set
|
||||||
respond.xclient.data.l[1] = (accepted ? 1 : 0);
|
respond.xclient.data.l[1] = accepted;
|
||||||
respond.xclient.data.l[2] = 0;
|
respond.xclient.data.l[2] = 0;
|
||||||
respond.xclient.data.l[3] = 0;
|
respond.xclient.data.l[3] = 0;
|
||||||
respond.xclient.data.l[4] = self.atombase_.xdnd_action_copy;
|
respond.xclient.data.l[4] = self.atombase_.xdnd_action_copy;
|
||||||
|
|
||||||
|
std::cout<<" Target XdndStatus begin to send. Accepted"<<accepted<<std::endl;
|
||||||
::XSendEvent(self.display_, wd_src, True, NoEventMask, &respond);
|
::XSendEvent(self.display_, wd_src, True, NoEventMask, &respond);
|
||||||
|
std::cout<<" Target XdndStatus ed"<<std::endl;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
else if(self.atombase_.xdnd_status == evt.xclient.message_type)
|
||||||
|
{
|
||||||
|
std::cout<<"Platform Recv XdndStatus"<<std::endl;
|
||||||
|
}
|
||||||
else if(self.atombase_.xdnd_drop == evt.xclient.message_type)
|
else if(self.atombase_.xdnd_drop == evt.xclient.message_type)
|
||||||
{
|
{
|
||||||
|
Window owner = ::XGetSelectionOwner(self.display_, self.atombase_.xdnd_selection);
|
||||||
|
std::cout<<"Platform XdndDrop: XdndSelectionOwner = "<<owner<<std::endl;
|
||||||
|
|
||||||
::XConvertSelection(self.display_, self.atombase_.xdnd_selection, self.xdnd_.good_type, self.atombase_.xdnd_selection,
|
::XConvertSelection(self.display_, self.atombase_.xdnd_selection, self.xdnd_.good_type, self.atombase_.xdnd_selection,
|
||||||
evt.xclient.window, self.xdnd_.timestamp);
|
evt.xclient.window, self.xdnd_.timestamp);
|
||||||
|
|
||||||
|
std::cout<<" XConvertSelection ed"<<std::endl;
|
||||||
|
|
||||||
//The XdndDrop should send a XdndFinished to source window.
|
//The XdndDrop should send a XdndFinished to source window.
|
||||||
//This operation is implemented in SelectionNotify, because
|
//This operation is implemented in SelectionNotify, because
|
||||||
//XdndFinished should be sent after retrieving data.
|
//XdndFinished should be sent after retrieving data.
|
||||||
|
|||||||
@ -28,6 +28,8 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
|
#include <iostream> //debug
|
||||||
|
|
||||||
namespace nana
|
namespace nana
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
@ -190,8 +192,15 @@ namespace detail
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(msg_filter_fn(msg))
|
switch(msg_filter_fn(msg))
|
||||||
|
{
|
||||||
|
case propagation_chain::exit:
|
||||||
return;
|
return;
|
||||||
|
case propagation_chain::stop:
|
||||||
|
break;
|
||||||
|
case propagation_chain::pass:
|
||||||
|
proc_.event_proc(display_, msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,6 +231,10 @@ namespace detail
|
|||||||
if(keymap[event.xkey.keycode / 8] & (1 << (event.xkey.keycode % 8)))
|
if(keymap[event.xkey.keycode / 8] & (1 << (event.xkey.keycode % 8)))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if(SelectionRequest == event.type)
|
||||||
|
{
|
||||||
|
std::cout<<"Dispatcher SelectionRequest"<<std::endl; //debug
|
||||||
|
}
|
||||||
|
|
||||||
if(::XFilterEvent(&event, None))
|
if(::XFilterEvent(&event, None))
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -8,6 +8,13 @@ namespace nana
|
|||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
enum class propagation_chain
|
||||||
|
{
|
||||||
|
exit, //Exit the chain
|
||||||
|
stop, //Stop propagating
|
||||||
|
pass //propagate
|
||||||
|
};
|
||||||
|
|
||||||
struct msg_packet_tag
|
struct msg_packet_tag
|
||||||
{
|
{
|
||||||
enum class pkt_family{xevent, mouse_drop, cleanup};
|
enum class pkt_family{xevent, mouse_drop, cleanup};
|
||||||
|
|||||||
@ -162,6 +162,7 @@ namespace detail
|
|||||||
Atom xdnd_drop;
|
Atom xdnd_drop;
|
||||||
Atom xdnd_selection;
|
Atom xdnd_selection;
|
||||||
Atom xdnd_typelist;
|
Atom xdnd_typelist;
|
||||||
|
Atom xdnd_leave;
|
||||||
Atom xdnd_finished;
|
Atom xdnd_finished;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -256,7 +257,7 @@ namespace detail
|
|||||||
void msg_insert(native_window_type);
|
void msg_insert(native_window_type);
|
||||||
void msg_set(timer_proc_type, event_proc_type);
|
void msg_set(timer_proc_type, event_proc_type);
|
||||||
void msg_dispatch(native_window_type modal);
|
void msg_dispatch(native_window_type modal);
|
||||||
void msg_dispatch(std::function<bool(const msg_packet_tag&)>);
|
void msg_dispatch(std::function<propagation_chain(const msg_packet_tag&)>);
|
||||||
|
|
||||||
//X Selections
|
//X Selections
|
||||||
void* request_selection(native_window_type requester, Atom type, size_t & bufsize);
|
void* request_selection(native_window_type requester, Atom type, size_t & bufsize);
|
||||||
@ -268,6 +269,7 @@ namespace detail
|
|||||||
const nana::paint::graphics& keep_window_icon(native_window_type, const nana::paint::image&);
|
const nana::paint::graphics& keep_window_icon(native_window_type, const nana::paint::image&);
|
||||||
|
|
||||||
bool register_dragdrop(native_window_type, x11_dragdrop_interface*);
|
bool register_dragdrop(native_window_type, x11_dragdrop_interface*);
|
||||||
|
std::size_t dragdrop_target(native_window_type, bool insert, std::size_t count);
|
||||||
x11_dragdrop_interface* remove_dragdrop(native_window_type);
|
x11_dragdrop_interface* remove_dragdrop(native_window_type);
|
||||||
private:
|
private:
|
||||||
static int _m_msg_filter(XEvent&, msg_packet_tag&);
|
static int _m_msg_filter(XEvent&, msg_packet_tag&);
|
||||||
@ -327,6 +329,7 @@ namespace detail
|
|||||||
nana::point pos;
|
nana::point pos;
|
||||||
|
|
||||||
std::map<native_window_type, x11_dragdrop_interface*> dragdrop;
|
std::map<native_window_type, x11_dragdrop_interface*> dragdrop;
|
||||||
|
std::map<native_window_type, std::size_t> targets;
|
||||||
}xdnd_;
|
}xdnd_;
|
||||||
|
|
||||||
msg_dispatcher * msg_dispatcher_;
|
msg_dispatcher * msg_dispatcher_;
|
||||||
|
|||||||
314
source/detail/posix/xdnd_protocol.hpp
Normal file
314
source/detail/posix/xdnd_protocol.hpp
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
/*
|
||||||
|
* X-Window XDND Protocol Implementation
|
||||||
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
|
* Copyright(C) 2018 Jinhao(cnjinhao@hotmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* @file: nana/detail/posix/xdnd_protocol.hpp
|
||||||
|
*
|
||||||
|
* The XDS is not supported.
|
||||||
|
*/
|
||||||
|
#ifndef NANA_DETAIL_POSIX_XDND_PROTOCOL_INCLUDED
|
||||||
|
#define NANA_DETAIL_POSIX_XDND_PROTOCOL_INCLUDED
|
||||||
|
|
||||||
|
#include "platform_spec.hpp"
|
||||||
|
#include <nana/filesystem/filesystem.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream> //debug
|
||||||
|
|
||||||
|
namespace nana{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
struct xdnd_data
|
||||||
|
{
|
||||||
|
std::vector<std::filesystem::path> files;
|
||||||
|
};
|
||||||
|
|
||||||
|
class xdnd_protocol
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class xdnd_status_state
|
||||||
|
{
|
||||||
|
normal,
|
||||||
|
position_sent,
|
||||||
|
status_ignore
|
||||||
|
};
|
||||||
|
|
||||||
|
xdnd_protocol(Window source):
|
||||||
|
spec_(nana::detail::platform_spec::instance()),
|
||||||
|
source_(source)
|
||||||
|
{
|
||||||
|
detail::platform_scope_guard lock;
|
||||||
|
::XSetSelectionOwner(spec_.open_display(), spec_.atombase().xdnd_selection, source, CurrentTime);
|
||||||
|
std::cout<<"XSetSelectionOwner "<<source<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_move(Window wd, const nana::point& pos)
|
||||||
|
{
|
||||||
|
if(wd != target_)
|
||||||
|
{
|
||||||
|
_m_xdnd_leave();
|
||||||
|
|
||||||
|
if(_m_xdnd_enter(wd))
|
||||||
|
_m_xdnd_position(pos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_m_xdnd_position(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_leave()
|
||||||
|
{
|
||||||
|
_m_xdnd_leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_release()
|
||||||
|
{
|
||||||
|
_m_xdnd_drop();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Return true to exit xdnd_protocol event handler
|
||||||
|
bool client_message(const ::XClientMessageEvent& xclient)
|
||||||
|
{
|
||||||
|
auto & atombase = spec_.atombase();
|
||||||
|
|
||||||
|
if(atombase.xdnd_status == xclient.message_type)
|
||||||
|
{
|
||||||
|
std::cout<<"Event: XdndStatus"<<std::endl;
|
||||||
|
|
||||||
|
if(xdnd_status_state::position_sent != xstate_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Window target_wd = static_cast<Window>(xclient.data.l[0]);
|
||||||
|
bool is_accepted_by_target = (xclient.data.l[1] & 1);
|
||||||
|
|
||||||
|
std::cout<<"XdndStatus: Accepted="<<is_accepted_by_target<<std::endl;
|
||||||
|
|
||||||
|
if(xclient.data.l[1] & 0x2)
|
||||||
|
{
|
||||||
|
rectangle rct{
|
||||||
|
static_cast<int>(xclient.data.l[2] >> 16),
|
||||||
|
static_cast<int>(xclient.data.l[2] & 0xFFFF),
|
||||||
|
static_cast<unsigned>(xclient.data.l[3] >> 16),
|
||||||
|
static_cast<unsigned>(xclient.data.l[3] & 0xFFFF)
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!rct.empty())
|
||||||
|
{
|
||||||
|
mvout_table_[target_wd] = rct;
|
||||||
|
std::cout<<". rct=("<<rct.x<<","<<rct.y<<","<<rct.width<<","<<rct.height<<")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout<<std::endl;
|
||||||
|
|
||||||
|
xstate_ = xdnd_status_state::normal;
|
||||||
|
|
||||||
|
if(!is_accepted_by_target)
|
||||||
|
{
|
||||||
|
_m_xdnd_leave();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(atombase.xdnd_finished == xclient.message_type)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void selection_request(const ::XSelectionRequestEvent& xselectionrequest, const xdnd_data& data)
|
||||||
|
{
|
||||||
|
if(spec_.atombase().xdnd_selection == xselectionrequest.selection)
|
||||||
|
{
|
||||||
|
std::cout<<"Event SelectionRequest: XdndSelection"<<std::endl;
|
||||||
|
|
||||||
|
::XEvent evt;
|
||||||
|
evt.xselection.type = SelectionNotify;
|
||||||
|
evt.xselection.display = xselectionrequest.display;
|
||||||
|
evt.xselection.requestor = xselectionrequest.requestor;
|
||||||
|
evt.xselection.selection = xselectionrequest.selection;
|
||||||
|
evt.xselection.target = 0;
|
||||||
|
evt.xselection.property = 0;
|
||||||
|
evt.xselection.time = xselectionrequest.time;
|
||||||
|
|
||||||
|
auto property_name = ::XGetAtomName(spec_.open_display(), xselectionrequest.property); //debug
|
||||||
|
|
||||||
|
std::cout<<"SelectionRequest"<<std::endl;
|
||||||
|
std::cout<<" xdnd_selection:"<<spec_.atombase().xdnd_selection<<std::endl;
|
||||||
|
std::cout<<" text_uri_list :"<<spec_.atombase().text_uri_list<<std::endl;
|
||||||
|
std::cout<<" selection="<<xselectionrequest.selection<<std::endl;
|
||||||
|
std::cout<<" property ="<<xselectionrequest.property<<", name="<<property_name<<std::endl;
|
||||||
|
std::cout<<" target ="<<xselectionrequest.target<<std::endl;
|
||||||
|
::XFree(property_name);
|
||||||
|
|
||||||
|
if(xselectionrequest.target == spec_.atombase().text_uri_list)
|
||||||
|
{
|
||||||
|
std::cout<<"SelectionRequest target = text_uri_list";
|
||||||
|
|
||||||
|
if(data.files.size())
|
||||||
|
{
|
||||||
|
std::string uri_list;
|
||||||
|
for(auto& file : data.files)
|
||||||
|
{
|
||||||
|
uri_list += "file://";
|
||||||
|
uri_list += file.u8string();
|
||||||
|
uri_list += "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout<<". URIs="<<uri_list<<std::endl;
|
||||||
|
|
||||||
|
::XChangeProperty (spec_.open_display(),
|
||||||
|
xselectionrequest.requestor,
|
||||||
|
xselectionrequest.property,
|
||||||
|
xselectionrequest.target,
|
||||||
|
8, PropModeReplace,
|
||||||
|
reinterpret_cast<unsigned char*>(&uri_list.front()), uri_list.size() + 1);
|
||||||
|
|
||||||
|
evt.xselection.property = xselectionrequest.property;
|
||||||
|
evt.xselection.target = xselectionrequest.target;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
std::cout<<"SelectionRequest target = "<<xselectionrequest.target<<std::endl;
|
||||||
|
|
||||||
|
platform_scope_guard lock;
|
||||||
|
::XSendEvent(spec_.open_display(), xselectionrequest.requestor, False, 0, &evt);
|
||||||
|
::XFlush(spec_.open_display());
|
||||||
|
|
||||||
|
if(0 == evt.xselection.target)
|
||||||
|
_m_xdnd_leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool _m_xdnd_enter(Window wd)
|
||||||
|
{
|
||||||
|
//xdnd version of the window
|
||||||
|
auto xdnd_ver = _m_xdnd_aware(wd);
|
||||||
|
if(0 == xdnd_ver)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
target_ = wd;
|
||||||
|
std::cout<<"Send XdndEnter, text/uri-list="<<spec_.atombase().text_uri_list<<std::endl;
|
||||||
|
_m_client_msg(spec_.atombase().xdnd_enter, (xdnd_ver << 24), spec_.atombase().text_uri_list, XA_STRING);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _m_xdnd_position(const nana::point& pos)
|
||||||
|
{
|
||||||
|
if(xdnd_status_state::normal != xstate_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto i = mvout_table_.find(target_);
|
||||||
|
if(i != mvout_table_.end() && i->second.is_hit(pos))
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::cout<<"Send: XdndPosition"<<std::endl;
|
||||||
|
|
||||||
|
xstate_ = xdnd_status_state::position_sent;
|
||||||
|
//Send XdndPosition
|
||||||
|
long position = (pos.x << 16 | pos.y);
|
||||||
|
_m_client_msg(spec_.atombase().xdnd_position, 0, position, CurrentTime, spec_.atombase().xdnd_action_copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _m_xdnd_leave()
|
||||||
|
{
|
||||||
|
if(target_)
|
||||||
|
{
|
||||||
|
std::cout<<"Send: XdndLeave"<<std::endl;
|
||||||
|
_m_client_msg(spec_.atombase().xdnd_leave, 0, 0, 0);
|
||||||
|
target_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _m_xdnd_drop()
|
||||||
|
{
|
||||||
|
std::cout<<"Send: XdndDrop"<<std::endl;
|
||||||
|
_m_client_msg(spec_.atombase().xdnd_drop, 0, CurrentTime, 0);
|
||||||
|
target_ = 0;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
//dndversion<<24, fl_XdndURIList, XA_STRING, 0
|
||||||
|
void _m_client_msg(Atom xdnd_atom, long data1, long data2, long data3, long data4 = 0)
|
||||||
|
{
|
||||||
|
auto const display = spec_.open_display();
|
||||||
|
XEvent evt;
|
||||||
|
::memset(&evt, 0, sizeof evt);
|
||||||
|
evt.xany.type = ClientMessage;
|
||||||
|
evt.xany.display = display;
|
||||||
|
evt.xclient.window = target_;
|
||||||
|
evt.xclient.message_type = xdnd_atom;
|
||||||
|
evt.xclient.format = 32;
|
||||||
|
|
||||||
|
//Target window
|
||||||
|
evt.xclient.data.l[0] = source_;
|
||||||
|
|
||||||
|
evt.xclient.data.l[1] = data1;
|
||||||
|
evt.xclient.data.l[2] = data2;
|
||||||
|
evt.xclient.data.l[3] = data3;
|
||||||
|
evt.xclient.data.l[4] = data4;
|
||||||
|
|
||||||
|
::XSendEvent(display, target_, True, NoEventMask, &evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the XDND version of specified window
|
||||||
|
//@return the XDND version. If the specified window does not have property XdndAware, it returns 0
|
||||||
|
int _m_xdnd_aware(Window wd)
|
||||||
|
{
|
||||||
|
Atom actual; int format; unsigned long count, remaining;
|
||||||
|
unsigned char *data = 0;
|
||||||
|
::XGetWindowProperty(spec_.open_display(), wd, spec_.atombase().xdnd_aware,
|
||||||
|
0, 4, False, XA_ATOM, &actual, &format, &count, &remaining, &data);
|
||||||
|
|
||||||
|
int version = 0;
|
||||||
|
if ((actual == XA_ATOM) && (format==32) && count && data)
|
||||||
|
{
|
||||||
|
version = int(*(Atom*)data);
|
||||||
|
std::cout<<"Get:XdndAware version:"<<version<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
::XFree(data);
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 //deprecated
|
||||||
|
//Check if window has a property
|
||||||
|
static bool _m_has_property(Window wd, Atom atom, unsigned char** data)
|
||||||
|
{
|
||||||
|
Atom type = 0;
|
||||||
|
int f;
|
||||||
|
unsigned long n, a;
|
||||||
|
|
||||||
|
unsigned char * data_back = nullptr;
|
||||||
|
if(nullptr == data)
|
||||||
|
data = &data_back;
|
||||||
|
|
||||||
|
if (::XGetWindowProperty(spec_.open_display(), wd, atom, 0, 0, False, AnyPropertyType, &type, &f,&n,&a,data) == Success)
|
||||||
|
{
|
||||||
|
//release the *data if failed to get the property or unspecified output buffer
|
||||||
|
if((0 == type) || data_back)
|
||||||
|
::XFree(*data);
|
||||||
|
|
||||||
|
return (0 != type);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
private:
|
||||||
|
nana::detail::platform_spec& spec_;
|
||||||
|
Window const source_;
|
||||||
|
Window target_{ 0 };
|
||||||
|
xdnd_status_state xstate_{xdnd_status_state::normal};
|
||||||
|
std::map<Window, nana::rectangle> mvout_table_;
|
||||||
|
}; //end class xdnd_protocol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -21,6 +21,7 @@
|
|||||||
#include "inner_fwd_implement.hpp"
|
#include "inner_fwd_implement.hpp"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iostream> //debug
|
||||||
|
|
||||||
namespace nana
|
namespace nana
|
||||||
{
|
{
|
||||||
@ -443,6 +444,8 @@ namespace detail
|
|||||||
{
|
{
|
||||||
case nana::detail::msg_packet_tag::pkt_family::mouse_drop:
|
case nana::detail::msg_packet_tag::pkt_family::mouse_drop:
|
||||||
msgwd = brock.wd_manager().find_window(native_window, {msg.u.mouse_drop.x, msg.u.mouse_drop.y});
|
msgwd = brock.wd_manager().find_window(native_window, {msg.u.mouse_drop.x, msg.u.mouse_drop.y});
|
||||||
|
|
||||||
|
std::cout<<" MouseDrop msgwd="<<msgwd<<", ("<<msg.u.mouse_drop.x<<","<<msg.u.mouse_drop.y<<")"<<std::endl;
|
||||||
if(msgwd)
|
if(msgwd)
|
||||||
{
|
{
|
||||||
arg_dropfiles arg;
|
arg_dropfiles arg;
|
||||||
@ -1248,10 +1251,12 @@ namespace detail
|
|||||||
default:
|
default:
|
||||||
if(message == ClientMessage)
|
if(message == ClientMessage)
|
||||||
{
|
{
|
||||||
auto & atoms = nana::detail::platform_spec::instance().atombase();
|
auto & spec = ::nana::detail::platform_spec::instance();
|
||||||
if(atoms.wm_protocols == xevent.xclient.message_type)
|
auto & xclient = xevent.xclient;
|
||||||
|
auto & atoms = spec.atombase();
|
||||||
|
if(atoms.wm_protocols == xclient.message_type)
|
||||||
{
|
{
|
||||||
if(msgwnd->flags.enabled && (atoms.wm_delete_window == static_cast<Atom>(xevent.xclient.data.l[0])))
|
if(msgwnd->flags.enabled && (atoms.wm_delete_window == static_cast<Atom>(xclient.data.l[0])))
|
||||||
{
|
{
|
||||||
arg_unload arg;
|
arg_unload arg;
|
||||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -609,7 +609,6 @@ namespace nana
|
|||||||
auto last_pos = tree.distance_if(last(true), pred_allow_child{});
|
auto last_pos = tree.distance_if(last(true), pred_allow_child{});
|
||||||
|
|
||||||
auto const capacity = screen_capacity(true);
|
auto const capacity = screen_capacity(true);
|
||||||
auto const item_px = data.comp_placer->item_height(*data.graph);
|
|
||||||
|
|
||||||
//If use_bearing is false, it calculates a bearing depending on the current
|
//If use_bearing is false, it calculates a bearing depending on the current
|
||||||
//position of the requested item.
|
//position of the requested item.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user