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