diff --git a/.travis.yml b/.travis.yml
index d98c0dcf..47cc31ef 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,6 +20,7 @@ matrix:
             - alsa-oss
             - libx11-dev
             - libxft-dev
+            - libxcursor-dev
           sources: 
             - ubuntu-toolchain-r-test
             
@@ -36,6 +37,7 @@ matrix:
             - alsa-oss
             - libx11-dev
             - libxft-dev
+            - libxcursor-dev
           sources: 
             - ubuntu-toolchain-r-test
             - llvm-toolchain-precise 
diff --git a/build/codeblocks/nana.cbp b/build/codeblocks/nana.cbp
index 18c78755..d48270ec 100644
--- a/build/codeblocks/nana.cbp
+++ b/build/codeblocks/nana.cbp
@@ -66,6 +66,7 @@
 		
 		
 		
+		
 		
 		
 		
diff --git a/build/vc2013/nana.vcxproj b/build/vc2013/nana.vcxproj
index 8501f83f..4051495b 100644
--- a/build/vc2013/nana.vcxproj
+++ b/build/vc2013/nana.vcxproj
@@ -202,6 +202,7 @@
     
     
     
+    
     
     
     
diff --git a/build/vc2013/nana.vcxproj.filters b/build/vc2013/nana.vcxproj.filters
index 6fe722eb..4c14b4d7 100644
--- a/build/vc2013/nana.vcxproj.filters
+++ b/build/vc2013/nana.vcxproj.filters
@@ -333,6 +333,9 @@
     
       Source Files\nana\detail
     
+    
+      Source Files\nana\gui
+    
   
   
     
diff --git a/build/vc2015/nana.vcxproj b/build/vc2015/nana.vcxproj
index 3ec4cf7d..f271092c 100644
--- a/build/vc2015/nana.vcxproj
+++ b/build/vc2015/nana.vcxproj
@@ -196,6 +196,7 @@
     
     
     
+    
     
     
     
diff --git a/build/vc2015/nana.vcxproj.filters b/build/vc2015/nana.vcxproj.filters
index d1d7ba78..c0cfcbdc 100644
--- a/build/vc2015/nana.vcxproj.filters
+++ b/build/vc2015/nana.vcxproj.filters
@@ -291,6 +291,9 @@
     
       Source Files\detail
     
+    
+      Source Files\gui
+    
   
   
     
diff --git a/build/vc2017/nana.vcxproj b/build/vc2017/nana.vcxproj
index cc3c70dc..39d61fe8 100644
--- a/build/vc2017/nana.vcxproj
+++ b/build/vc2017/nana.vcxproj
@@ -179,6 +179,7 @@
     
     
     
+    
     
     
     
diff --git a/build/vc2017/nana.vcxproj.filters b/build/vc2017/nana.vcxproj.filters
index 10e92180..65431a04 100644
--- a/build/vc2017/nana.vcxproj.filters
+++ b/build/vc2017/nana.vcxproj.filters
@@ -292,6 +292,9 @@
     
       Sources\gui
     
+    
+      Sources\gui
+    
   
   
     
diff --git a/include/nana/gui/basis.hpp b/include/nana/gui/basis.hpp
index a582d7b9..f7ed845d 100644
--- a/include/nana/gui/basis.hpp
+++ b/include/nana/gui/basis.hpp
@@ -65,6 +65,13 @@ namespace nana
 		blend
 	};
 
+	enum class dragdrop_status
+	{
+		not_ready,
+		ready,
+		in_progress
+	};
+
 	namespace category
 	{
 		enum class flags
diff --git a/include/nana/gui/detail/basic_window.hpp b/include/nana/gui/detail/basic_window.hpp
index 6c5bc202..5911b598 100644
--- a/include/nana/gui/detail/basic_window.hpp
+++ b/include/nana/gui/detail/basic_window.hpp
@@ -1,7 +1,7 @@
 /**
  *	A Basic Window Widget Definition
  *	Nana C++ Library(http://www.nanapro.org)
- *	Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
+ *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
  *
  *	Distributed under the Boost Software License, Version 1.0.
  *	(See accompanying file LICENSE_1_0.txt or copy at
@@ -179,7 +179,8 @@ namespace detail
 			bool ignore_menubar_focus	: 1;	///< A flag indicates whether the menubar sets the focus.
 			bool ignore_mouse_focus		: 1;	///< A flag indicates whether the widget accepts focus when clicking on it
 			bool space_click_enabled : 1;		///< A flag indicates whether enable mouse_down/click/mouse_up when pressing and releasing whitespace key.
-			unsigned Reserved	:18;
+			bool draggable : 1;
+			unsigned Reserved	:17;
 			unsigned char tab;		///< indicate a window that can receive the keyboard TAB
 			mouse_action	action;
 			mouse_action	action_before;
@@ -234,6 +235,7 @@ namespace detail
 											///< if the active_window is null, the parent of this window keeps focus.
 			paint::graphics glass_buffer;	///< if effect.bground is avaiable. Refer to window_layout::make_bground.
 			update_state	upd_state;
+			dragdrop_status	dnd_state{ dragdrop_status::not_ready };
 
 			union
 			{
diff --git a/include/nana/gui/dragdrop.hpp b/include/nana/gui/dragdrop.hpp
new file mode 100644
index 00000000..e68279b8
--- /dev/null
+++ b/include/nana/gui/dragdrop.hpp
@@ -0,0 +1,45 @@
+/**
+*	Drag and Drop 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/gui/dragdrop.hpp
+*	@author: Jinhao(cnjinhao@hotmail.com)
+*/
+#ifndef NANA_GUI_DRAGDROP_INCLUDED
+#define NANA_GUI_DRAGDROP_INCLUDED
+
+#include 
+#include 
+#include "basis.hpp"
+
+#include 
+
+namespace nana
+{
+	class simple_dragdrop
+	{
+		struct implementation;
+
+		simple_dragdrop(const simple_dragdrop&) = delete;
+		simple_dragdrop& operator=(const simple_dragdrop&) = delete;
+
+		simple_dragdrop(simple_dragdrop&&) = delete;
+		simple_dragdrop& operator=(simple_dragdrop&&) = delete;
+	public:
+		simple_dragdrop(window drag_wd);
+		~simple_dragdrop();
+
+		/// Sets a condition that determines whether the drag&drop can start
+		void condition(std::function predicate_fn);
+		void make_drop(window target, std::function drop_fn);
+	private:
+		implementation* const impl_;
+	};
+}
+
+#endif
\ No newline at end of file
diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp
index 134b0082..56c3ec7d 100644
--- a/include/nana/gui/programming_interface.hpp
+++ b/include/nana/gui/programming_interface.hpp
@@ -1,7 +1,7 @@
 /*
  *	Nana GUI Programming Interface Implementation
  *	Nana C++ Library(http://www.nanapro.org)
- *	Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
+ *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
  *
  *	Distributed under the Boost Software License, Version 1.0.
  *	(See accompanying file LICENSE_1_0.txt or copy at
@@ -117,6 +117,9 @@ namespace API
 		void lazy_refresh();
 
 		void draw_shortkey_underline(paint::graphics&, const std::string& text, wchar_t shortkey, std::size_t shortkey_position, const point& text_pos, const color&);
+
+		void window_draggable(window, bool enabled);
+		bool window_draggable(window);
 	}//end namespace dev
 
 
@@ -476,6 +479,8 @@ namespace API
 	::std::optional> content_extent(window wd, unsigned limited_px, bool limit_width);
 
 	unsigned screen_dpi(bool x_requested);
+
+	dragdrop_status window_dragdrop_status(::nana::window);
 }//end namespace API
 
 }//end namespace nana
diff --git a/include/nana/gui/widgets/listbox.hpp b/include/nana/gui/widgets/listbox.hpp
index a2eee239..dde46edc 100644
--- a/include/nana/gui/widgets/listbox.hpp
+++ b/include/nana/gui/widgets/listbox.hpp
@@ -1497,6 +1497,9 @@ the nana::detail::basic_window member pointer scheme
 		void erase(index_pairs indexes);	///dispatch(reinterpret_cast(modal));
 	}
 
+	void platform_spec::msg_dispatch(std::function msg_filter_fn)
+	{
+		msg_dispatcher_->dispatch(msg_filter_fn);
+
+	}
+
 	void* platform_spec::request_selection(native_window_type requestor, Atom type, size_t& size)
 	{
 		if(requestor)
@@ -1104,6 +1110,40 @@ namespace detail
 		return graph;
 	}
 
+
+	bool platform_spec::register_dragdrop(native_window_type wd, dragdrop_interface* ddrop)
+	{
+		platform_scope_guard lock;
+		if(0 != xdnd_.dragdrop.count(wd))
+			return false;
+
+		int dndver = 4;
+		::XChangeProperty(display_, reinterpret_cast(wd), atombase_.xdnd_aware, XA_ATOM, sizeof(int) * 8,
+			PropModeReplace, reinterpret_cast(&dndver), 1);
+
+		auto & ref_drop = xdnd_.dragdrop[wd];
+		ref_drop.dragdrop = ddrop;
+		ref_drop.ref_count = 1;
+		return true;
+	}
+
+	dragdrop_interface* platform_spec::remove_dragdrop(native_window_type wd)
+	{
+		platform_scope_guard lock;
+		auto i = xdnd_.dragdrop.find(wd);
+		if(i == xdnd_.dragdrop.end())
+			return nullptr;
+
+		auto ddrop = i->second;
+		if(ddrop.ref_count <= 1)
+		{
+			xdnd_.dragdrop.erase(i);
+			return ddrop.dragdrop;
+		}
+		--ddrop.ref_count;
+		return nullptr;
+	}
+
 	//_m_msg_filter
 	//@return:	_m_msg_filter returns three states
 	//		0 = msg_dispatcher dispatches the XEvent
@@ -1163,7 +1203,7 @@ namespace detail
 				else if(evt.xselection.property == self.atombase_.xdnd_selection)
 				{
 					bool accepted = false;
-					msg.kind = msg.kind_mouse_drop;
+					msg.kind = msg_packet_tag::pkt_family::mouse_drop;
 					msg.u.mouse_drop.window = 0;
 					if(bytes_left > 0 && type == self.xdnd_.good_type)
 					{
diff --git a/source/detail/posix/msg_dispatcher.hpp b/source/detail/posix/msg_dispatcher.hpp
index 9ba12ad1..f5b13bb9 100644
--- a/source/detail/posix/msg_dispatcher.hpp
+++ b/source/detail/posix/msg_dispatcher.hpp
@@ -143,7 +143,7 @@ namespace detail
 				{
 					//Make a cleanup msg packet to infor the dispatcher the window is closed.
 					msg_packet_tag msg;
-					msg.kind = msg.kind_cleanup;
+					msg.kind = msg_packet_tag::pkt_family::cleanup;
 					msg.u.packet_window = wd;
 					thr->msg_queue.push_back(msg);
 				}
@@ -171,6 +171,30 @@ namespace detail
 				}
 			}
 		}
+
+		template
+		void dispatch(MsgFilter msg_filter_fn)
+		{
+			auto tid = nana::system::this_thread_id();
+			msg_packet_tag msg;
+			int qstate;
+
+			//Test whether the thread is registered for window, and retrieve the queue state for event
+			while((qstate = _m_read_queue(tid, msg, 0)))
+			{
+				//the queue is empty
+				if(-1 == qstate)
+				{
+					if(false == _m_wait_for_queue(tid))
+						proc_.timer_proc(tid);
+				}
+				else
+				{
+					if(msg_filter_fn(msg))
+						return;
+				}
+			}
+		}
 	private:
 		void _m_msg_driver()
 		{
@@ -220,7 +244,7 @@ namespace detail
 					switch(proc_.filter_proc(event, msg_pack))
 					{
 					case 0:
-						msg_pack.kind = msg_pack.kind_xevent;
+						msg_pack.kind = msg_packet_tag::pkt_family::xevent;
 						msg_pack.u.xevent = event;
 						_m_msg_dispatch(msg_pack);
 						break;
@@ -246,9 +270,9 @@ namespace detail
 		{
 			switch(pack.kind)
 			{
-			case msg_packet_tag::kind_xevent:
+			case msg_packet_tag::pkt_family::xevent:
 				return _m_event_window(pack.u.xevent);
-			case msg_packet_tag::kind_mouse_drop:
+			case msg_packet_tag::pkt_family::mouse_drop:
 				return pack.u.mouse_drop.window;
 			default:
 				break;
@@ -294,7 +318,7 @@ namespace detail
 							//Check whether the event dispatcher is used for the modal window
 							//and when the modal window is closing, the event dispatcher would
 							//stop event pumping.
-							if((modal == msg.u.packet_window) && (msg.kind == msg.kind_cleanup))
+							if((modal == msg.u.packet_window) && (msg.kind == msg_packet_tag::pkt_family::cleanup))
 								return 0;
 
 							return 1;
diff --git a/source/detail/posix/msg_packet.hpp b/source/detail/posix/msg_packet.hpp
index ea24091f..fbc0848f 100644
--- a/source/detail/posix/msg_packet.hpp
+++ b/source/detail/posix/msg_packet.hpp
@@ -10,8 +10,8 @@ namespace detail
 {
 	struct msg_packet_tag
 	{
-		enum kind_t{kind_xevent, kind_mouse_drop, kind_cleanup};
-		kind_t kind;
+		enum class pkt_family{xevent, mouse_drop, cleanup};
+		pkt_family kind;
 		union
 		{
 			XEvent xevent;
diff --git a/source/detail/posix/platform_spec.hpp b/source/detail/posix/platform_spec.hpp
index 3191ddb1..af472a92 100644
--- a/source/detail/posix/platform_spec.hpp
+++ b/source/detail/posix/platform_spec.hpp
@@ -36,6 +36,7 @@
 
 #include 
 #include