← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~gamag/widelands/Bug916814 into lp:widelands

 

Gabriel Margiani has proposed merging lp:~gamag/widelands/Bug916814 into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #672085 in widelands: "New stock menu layout too high for small resolutions"
  https://bugs.launchpad.net/widelands/+bug/672085
  Bug #916814 in widelands: "Zooming the minimap on "Dry Riverbed" will crash the game on lower resolutions (800x600)"
  https://bugs.launchpad.net/widelands/+bug/916814

For more details, see:
https://code.launchpad.net/~gamag/widelands/Bug916814/+merge/93857

Implements alt-dragging and allows windows to
be dragged out of the screen/grow bigger than the screen.
Fixes bug916814 and related.
 
-- 
https://code.launchpad.net/~gamag/widelands/Bug916814/+merge/93857
Your team Widelands Developers is requested to review the proposed merge of lp:~gamag/widelands/Bug916814 into lp:widelands.
=== modified file 'src/graphic/render/gameview.cc'
--- src/graphic/render/gameview.cc	2012-02-12 17:17:26 +0000
+++ src/graphic/render/gameview.cc	2012-02-20 14:59:27 +0000
@@ -976,7 +976,10 @@
 	 Point                               const viewpoint,
 	 uint32_t                            const flags)
 {
-	draw_minimap(egbase, player, m_rect, viewpoint - m_offset, flags);
+	draw_minimap
+		(egbase, player, m_rect, viewpoint -
+			((flags & MiniMap::Zoom2) ? Point(m_offset.x / 2, m_offset.y / 2) : m_offset),
+				viewpoint, flags);
 }
 
 
@@ -1219,26 +1222,27 @@
 	 Widelands::Player           const * const player,
 	 Rect                                const rc,
 	 Point                               const viewpoint,
+	 Point                               const framepoint,
 	 uint32_t                            const flags)
 {
 	Widelands::Map const & map = egbase.map();
 
-	int32_t mapheight = (flags & MiniMap::Zoom2 ? rc.h / 2 : rc.h);
+	int32_t mapheight = map.get_height();
 
 	// size of the display frame
 	int32_t xsize = g_gr->get_xres() / TRIANGLE_WIDTH / 2;
 	int32_t ysize = g_gr->get_yres() / TRIANGLE_HEIGHT / 2;
 
 	Point ptopleft; // top left point of the current display frame
-	ptopleft.x = viewpoint.x + mapwidth / 2 - xsize;
+	ptopleft.x = framepoint.x + mapwidth / 2 - xsize;
 	if (ptopleft.x < 0) ptopleft.x += mapwidth;
-	ptopleft.y = viewpoint.y + mapheight / 2 - ysize;
+	ptopleft.y = framepoint.y + mapheight / 2 - ysize;
 	if (ptopleft.y < 0) ptopleft.y += mapheight;
 
 	Point pbottomright; // bottom right point of the current display frame
-	pbottomright.x = viewpoint.x + mapwidth / 2 + xsize;
+	pbottomright.x = framepoint.x + mapwidth / 2 + xsize;
 	if (pbottomright.x >= mapwidth) pbottomright.x -= mapwidth;
-	pbottomright.y = viewpoint.y + mapheight / 2 + ysize;
+	pbottomright.y = framepoint.y + mapheight / 2 + ysize;
 	if (pbottomright.y >= mapheight) pbottomright.y -= mapheight;
 
 	uint32_t modx = pbottomright.x % 2;
@@ -1324,6 +1328,7 @@
 	 Widelands::Player           const * const player,
 	 Rect                                const rc,
 	 Point                               const viewpt,
+	 Point                               const framept,
 	 uint32_t                            const flags)
 {
 	// First create a temporary SDL Surface to draw the minimap. This Surface is
@@ -1359,12 +1364,12 @@
 	case sizeof(Uint16):
 		draw_minimap_int<Uint16>
 			(pixels, surface->pitch, *surface->format,
-			 w, egbase, player, rc2, viewpt, flags);
+			 w, egbase, player, rc2, viewpt, framept, flags);
 		break;
 	case sizeof(Uint32):
 		draw_minimap_int<Uint32>
 			(pixels, surface->pitch, *surface->format,
-			 w, egbase, player, rc2, viewpt, flags);
+			 w, egbase, player, rc2, viewpt, framept, flags);
 		break;
 	default:
 		assert (false);

=== modified file 'src/graphic/render/gameview.h'
--- src/graphic/render/gameview.h	2012-01-09 21:10:43 +0000
+++ src/graphic/render/gameview.h	2012-02-20 14:59:27 +0000
@@ -104,6 +104,7 @@
 		 Widelands::Player           const *,
 		 Rect                                rc,
 		 Point                               viewpt,
+		 Point                               framept,
 		 uint32_t                            flags);
 
 	/**

=== modified file 'src/ui_basic/panel.cc'
--- src/ui_basic/panel.cc	2012-01-10 21:40:17 +0000
+++ src/ui_basic/panel.cc	2012-02-20 14:59:27 +0000
@@ -663,6 +663,17 @@
 }
 
 /**
+ * Called whenever the user presses a mouse button in the panel while pressing the alt-key.
+ * This function is called first on the parent panels.
+ * It should be only overwritten by the UI::Window class.
+ * \return true if the click was processed, false otherwise
+ */
+bool Panel::handle_alt_drag(int32_t x, int32_t y)
+{
+	return false;
+}
+
+/**
  * Enable/Disable mouse handling by this panel
  * Default is enabled. Note that when mouse handling is disabled, child panels
  * don't receive mouse events either.
@@ -921,6 +932,18 @@
 	y -= _tborder;
 	if (_flags & pf_top_on_click)
 		move_to_top();
+
+	//  FIXME This code is erroneous. It checks the current key state. What it
+	//  FIXME needs is the key state at the time the mouse was clicked. See the
+	//  FIXME usage comment for get_key_state.
+	//  Some window managers use alt-drag, so we can't only use the alt keys
+	if
+		((not _g_mousegrab) && (btn == SDL_BUTTON_LEFT) &&
+		 ((get_key_state(SDLK_LALT) | get_key_state(SDLK_RALT) |
+		   get_key_state(SDLK_MODE) | get_key_state(SDLK_LSHIFT))))
+		if (handle_alt_drag(x, y))
+			return true;
+
 	if (_g_mousegrab != this)
 		for
 			(Panel * child = _fchild;

=== modified file 'src/ui_basic/panel.h'
--- src/ui_basic/panel.h	2011-11-30 21:38:37 +0000
+++ src/ui_basic/panel.h	2012-02-20 14:59:27 +0000
@@ -189,6 +189,7 @@
 	virtual bool handle_mousemove
 		(Uint8 state, int32_t x, int32_t y, int32_t xdiff, int32_t ydiff);
 	virtual bool handle_key(bool down, SDL_keysym code);
+	virtual bool handle_alt_drag(int32_t x, int32_t y);
 
 	/// \returns whether a certain given is currently down.
 	///

=== modified file 'src/ui_basic/unique_window.cc'
--- src/ui_basic/unique_window.cc	2011-11-30 21:38:37 +0000
+++ src/ui_basic/unique_window.cc	2012-02-20 14:59:27 +0000
@@ -84,7 +84,7 @@
 		delete m_registry->window;
 
 		m_registry->window = this;
-		if (m_registry->x >= 0) {
+		if (m_registry->valid_pos) {
 			set_pos(Point(m_registry->x, m_registry->y));
 			m_usedefaultpos = false;
 		}
@@ -106,6 +106,7 @@
 		m_registry->window = 0;
 		m_registry->x = get_x();
 		m_registry->y = get_y();
+		m_registry->valid_pos = true;
 
 		if (m_registry->onDelete) {
 			m_registry->onDelete();

=== modified file 'src/ui_basic/unique_window.h'
--- src/ui_basic/unique_window.h	2011-11-30 21:38:37 +0000
+++ src/ui_basic/unique_window.h	2012-02-20 14:59:27 +0000
@@ -47,8 +47,9 @@
 		void toggle();
 
 		int32_t x, y;
+		bool valid_pos;
 
-		Registry() : window(0), x(-1), y(-1) {}
+		Registry() : window(0), x(0), y(0), valid_pos(false) {}
 		~Registry();
 	};
 

=== modified file 'src/ui_basic/window.cc'
--- src/ui_basic/window.cc	2011-11-30 21:38:37 +0000
+++ src/ui_basic/window.cc	2012-02-20 14:59:27 +0000
@@ -138,16 +138,6 @@
 	if (m_center_panel) {
 		uint32_t innerw, innerh;
 		m_center_panel->get_desired_size(innerw, innerh);
-
-		// Never bigger than maximum available size
-		// TODO fix this properly with a scrollbar after release of build16
-		// -->
-		if ((innerh + get_tborder() + get_bborder()) > get_parent()->get_h())
-			innerh = get_parent()->get_h() - get_tborder() - get_bborder();
-		if ((innerw + get_lborder() + get_rborder()) > get_parent()->get_w())
-			innerw = get_parent()->get_w() - get_lborder() - get_rborder();
-		// <--
-
 		set_desired_size
 			(innerw + get_lborder() + get_rborder(),
 			 innerh + get_tborder() + get_bborder());
@@ -214,33 +204,44 @@
 	if (Panel * const parent = get_parent()) {
 		int32_t px = get_x();
 		int32_t py = get_y();
-		if (px < 0) {
-			px = 0;
-			if (parent->get_dock_windows_to_edges() and not _docked_left)
-				dock_left();
-		} else if (px + static_cast<uint32_t>(get_w()) >= parent->get_inner_w()) {
-			assert (parent->get_inner_w() > static_cast<uint32_t>(get_w()));
-			px = parent->get_inner_w() - static_cast<uint32_t>(get_w());
-			if (parent->get_dock_windows_to_edges() and not _docked_right)
-				dock_right();
-		}
-		if (py < 0)
-			py = 0;
-		else if (py + static_cast<uint32_t>(get_h()) > parent->get_inner_h()) {
-			assert(parent->get_inner_h() >= static_cast<uint32_t>(get_h()));
-			py = parent->get_inner_h() - static_cast<uint32_t>(get_h());
-			if
-				(not _is_minimal
-				 and
-				 parent->get_dock_windows_to_edges() and not _docked_bottom)
-				dock_bottom();
-		}
-		if      (_docked_left)
-			px = 0;
-		else if (_docked_right)
-			px = parent->get_inner_w() - get_w();
-		if      (_docked_bottom)
-			py = parent->get_inner_h() - get_h();
+		if
+			((parent->get_inner_w() < static_cast<uint32_t>(get_w())) and
+			(px + get_w() <= static_cast<int32_t>(parent->get_inner_w()) or px >= 0))
+			px = (static_cast<int32_t>(parent->get_inner_w()) - get_w()) / 2;
+		if
+			((parent->get_inner_h() < static_cast<uint32_t>(get_h())) and
+			(py + get_h() < static_cast<int32_t>(parent->get_inner_h()) or py > 0))
+				py = 0;
+
+		if (parent->get_inner_w() >= static_cast<uint32_t>(get_w())) {
+			if (px < 0) {
+				px = 0;
+				if (parent->get_dock_windows_to_edges() and not _docked_left)
+					_docked_left =  true;
+			} else if (px + static_cast<uint32_t>(get_w()) >= parent->get_inner_w()) {
+				px = static_cast<int32_t>(parent->get_inner_w()) - get_w();
+				if (parent->get_dock_windows_to_edges() and not _docked_right)
+					_docked_right = true;
+			}
+			if (_docked_left)
+				px -= VT_B_PIXMAP_THICKNESS;
+			else if (_docked_right)
+				px += VT_B_PIXMAP_THICKNESS;
+		}
+		if (parent->get_inner_h() >= static_cast<uint32_t>(get_h())) {
+			if (py < 0)
+				py = 0;
+			else if (py + static_cast<uint32_t>(get_h()) > parent->get_inner_h()) {
+				py = static_cast<int32_t>(parent->get_inner_h()) - get_h();
+				if
+					(not _is_minimal
+					and
+					parent->get_dock_windows_to_edges() and not _docked_bottom)
+					_docked_bottom = true;
+			}
+			if (_docked_bottom)
+				py += BT_B_PIXMAP_THICKNESS;
+		}
 		set_pos(Point(px, py));
 	}
 }
@@ -255,8 +256,8 @@
 
 	set_pos
 		(Point
-		 	((parent.get_inner_w() - get_w()) / 2,
-		 	 (parent.get_inner_h() - get_h()) / 2));
+		((static_cast<int32_t>(parent.get_inner_w()) - get_w()) / 2,
+		 (static_cast<int32_t>(parent.get_inner_h()) - get_h()) / 2));
 }
 
 
@@ -281,22 +282,18 @@
 	assert(HZ_B_CORNER_PIXMAP_LEN >= VT_B_PIXMAP_THICKNESS);
 	assert(HZ_B_MIDDLE_PIXMAP_LEN > 0);
 
-	const uint32_t hidden_width_left  = _docked_left  ?
-		VT_B_PIXMAP_THICKNESS : 0;
-	const uint32_t hidden_width_right = _docked_right ?
-		VT_B_PIXMAP_THICKNESS : 0;
 	const int32_t hz_bar_end = get_w() -
-		HZ_B_CORNER_PIXMAP_LEN + hidden_width_right;
+		HZ_B_CORNER_PIXMAP_LEN;
 	const int32_t hz_bar_end_minus_middle = hz_bar_end -
 		HZ_B_MIDDLE_PIXMAP_LEN;
 
 	{ //  Top border.
-		int32_t pos = HZ_B_CORNER_PIXMAP_LEN - hidden_width_left;
+		int32_t pos = HZ_B_CORNER_PIXMAP_LEN;
 
 		dst.blitrect //  top left corner
 			(Point(0, 0),
 			 m_pic_top,
-			 Rect(Point(hidden_width_left, 0), pos, TP_B_PIXMAP_THICKNESS));
+			 Rect(Point(0, 0), pos, TP_B_PIXMAP_THICKNESS));
 
 		//  top bar
 		compile_assert(0 <= HZ_B_CORNER_PIXMAP_LEN);
@@ -316,7 +313,7 @@
 			 m_pic_top,
 			 Rect
 			 	(Point(HZ_B_TOTAL_PIXMAP_LEN - width, 0),
-			 	 width - hidden_width_right, TP_B_PIXMAP_THICKNESS));
+			 	 width, TP_B_PIXMAP_THICKNESS));
 	}
 
 	// draw the title if we have one
@@ -332,7 +329,7 @@
 		const int32_t vt_bar_end_minus_middle =
 			vt_bar_end - VT_B_MIDDLE_PIXMAP_LEN;
 
-		if (not _docked_left) {
+		{ // Left border
 
 			compile_assert(0 <= VT_B_PIXMAP_THICKNESS);
 			dst.blitrect // left top thingy
@@ -364,7 +361,7 @@
 		}
 
 
-		if (not _docked_right) {
+		{ // Right border
 			const int32_t right_border_x = get_w() - VT_B_PIXMAP_THICKNESS;
 
 			dst.blitrect // right top thingy
@@ -393,13 +390,14 @@
 				 	(Point(0, VT_B_TOTAL_PIXMAP_LEN - height),
 				 	 VT_B_PIXMAP_THICKNESS, height));
 		}
-		if (not _docked_bottom) {
-			int32_t pos = HZ_B_CORNER_PIXMAP_LEN - hidden_width_left;
+
+		{ // Bottom border
+			int32_t pos = HZ_B_CORNER_PIXMAP_LEN;
 
 			dst.blitrect //  bottom left corner
 				(Point(0, get_h() - BT_B_PIXMAP_THICKNESS),
 				 m_pic_bottom,
-				 Rect(Point(hidden_width_left, 0), pos, BT_B_PIXMAP_THICKNESS));
+				 Rect(Point(0, 0), pos, BT_B_PIXMAP_THICKNESS));
 
 			//  bottom bar
 			for (; pos < hz_bar_end_minus_middle; pos += HZ_B_MIDDLE_PIXMAP_LEN)
@@ -417,7 +415,7 @@
 				 m_pic_bottom,
 				 Rect
 				 	(Point(HZ_B_TOTAL_PIXMAP_LEN - width, 0),
-				 	 width - hidden_width_right, BT_B_PIXMAP_THICKNESS));
+				 	 width, BT_B_PIXMAP_THICKNESS));
 		}
 	}
 }
@@ -472,85 +470,44 @@
 	return true;
 }
 
+bool Window::handle_alt_drag(int32_t mx, int32_t my)
+{
+	_dragging = true;
+	_drag_start_win_x = get_x();
+	_drag_start_win_y = get_y();
+	_drag_start_mouse_x = get_x() + get_lborder() + mx;
+	_drag_start_mouse_y = get_y() + get_tborder() + my;
+	grab_mouse(true);
+	return true;
+}
+
 void Window::restore() {
 	assert(_is_minimal);
 	_is_minimal = false;
 	set_border
 		(get_lborder(), get_rborder(),
-		 get_tborder(), _docked_bottom ? 0 : BT_B_PIXMAP_THICKNESS);
+		 get_tborder(), BT_B_PIXMAP_THICKNESS);
 	set_inner_size(get_inner_w(), _oldh);
 	move_inside_parent();
 }
 void Window::minimize() {
 	assert(not _is_minimal);
-	if (_docked_bottom) undock_bottom(); //  Minimal can not be bottom-docked.
+	int32_t y = get_y(), x = get_x();
+	if (_docked_bottom) {
+		y -= BT_B_PIXMAP_THICKNESS; //  Minimal can not be bottom-docked.
+		_docked_bottom = false;
+	}
+	if (y < 0) y = 0; //  Move into the screen
 	_oldh = get_inner_h();
 	_is_minimal = true;
 	set_border(get_lborder(), get_rborder(), get_tborder(), 0);
 	set_size(get_w(), TP_B_PIXMAP_THICKNESS);
-	set_pos(Point(get_x(), get_y())); // If on border, this feels more natural
-}
-
-inline void Window::dock_left() {
-	assert(not _docked_left);
-	_docked_left = true;
-	set_size(get_inner_w() + get_rborder(), get_h());
-	set_border(0, get_rborder(), get_tborder(), get_bborder());
-	layout();
-	assert(get_lborder() == 0);
-}
-
-inline void Window::undock_left() {
-	assert(_docked_left);
-	_docked_left = false;
-	set_size(VT_B_PIXMAP_THICKNESS + get_inner_w() + get_rborder(), get_h());
-	set_border
-		(VT_B_PIXMAP_THICKNESS, get_rborder(),
-		 get_tborder(), get_bborder());
-	layout();
-}
-
-inline void Window::dock_right() {
-	assert(not _docked_right);
-	_docked_right = true;
-	set_size(get_lborder() + get_inner_w(), get_h());
-	set_border(get_lborder(), 0, get_tborder(), get_bborder());
-	layout();
-}
-
-inline void Window::undock_right() {
-	assert(_docked_right);
-	_docked_right = false;
-	set_size(get_lborder() + get_inner_w() + VT_B_PIXMAP_THICKNESS, get_h());
-	set_border
-		(get_lborder(), VT_B_PIXMAP_THICKNESS,
-		 get_tborder(), get_bborder());
-	layout();
-}
-
-inline void Window::dock_bottom() {
-	assert(not _docked_bottom);
-	assert(not _is_minimal); //  Minimal windows can not be bottom-docked.
-	_docked_bottom = true;
-	set_size(get_w(), get_tborder() + get_inner_h());
-	set_border(get_lborder(), get_rborder(), get_tborder(), 0);
-	layout();
-}
-
-inline void Window::undock_bottom() {
-	assert(_docked_bottom);
-	_docked_bottom = false;
-	set_size(get_w(), get_tborder() + get_inner_h() + BT_B_PIXMAP_THICKNESS);
-	set_border
-		(get_lborder(), get_rborder(),
-		 get_tborder(), BT_B_PIXMAP_THICKNESS);
-	layout();
-}
-
+	set_pos(Point(x, y)); // If on border, this feels more natural
+}
 
 /**
  * Drag the mouse if the left mouse button is clicked.
- * Ensure that the window isn't dragged out of the screen.
+ * Ensure that the window isn't fully dragged out of the screen.
  */
 bool Window::handle_mousemove
 		(const Uint8, int32_t mx, int32_t my, int32_t, int32_t)
@@ -558,10 +515,8 @@
 	if (_dragging) {
 		const int32_t mouse_x = get_x() + get_lborder() + mx;
 		const int32_t mouse_y = get_y() + get_tborder() + my;
-		int32_t left = std::max
-			(0, _drag_start_win_x + mouse_x - _drag_start_mouse_x);
-		int32_t top  = std::max
-			(0, _drag_start_win_y + mouse_y - _drag_start_mouse_y);
+		int32_t left = _drag_start_win_x + mouse_x - _drag_start_mouse_x;
+		int32_t top  = _drag_start_win_y + mouse_y - _drag_start_mouse_y;
 		int32_t new_left = left, new_top = top;
 
 		if (const Panel * const parent = get_parent()) {
@@ -569,40 +524,47 @@
 			const int32_t h = get_h();
 			const int32_t max_x = parent->get_inner_w();
 			const int32_t max_y = parent->get_inner_h();
-			assert(w <= max_x); //  These assertions will fail when having too
-			assert(h <= max_y); //  low resolution and opening a large window.
-			int32_t max_x_minus_w = max_x - w;
-			int32_t max_y_minus_h = max_y - h;
-			left = std::min(max_x_minus_w, left);
-			top  = std::min(max_y_minus_h, top);
+
+			left = std::min(static_cast<int32_t>(max_x - get_lborder()), left);
+			top  = std::min(static_cast<int32_t>(max_y - get_tborder()), top);
+			left = std::max(-static_cast<int32_t>(w - get_rborder()), left);
+			top  = std::max
+				(-static_cast<int32_t>(h - ((_is_minimal) ? get_tborder() : get_bborder())), top);
+			new_left = left; new_top = top;
+
 			const uint8_t psnap = parent->get_panel_snap_distance ();
 			const uint8_t bsnap = parent->get_border_snap_distance();
 
+			const uint32_t pborder_distance_l = abs(left);
+			const uint32_t pborder_distance_t = abs(top);
+			const uint32_t pborder_distance_r = abs(max_x - (left + w));
+			const uint32_t pborder_distance_b = abs(max_y - (top  + h));
+
 			//  These are needed to prefer snapping a shorter distance over a
 			//  longer distance, when there are several things to snap to.
 			uint8_t nearest_snap_distance_x = bsnap;
 			uint8_t nearest_snap_distance_y = bsnap;
 
 			//  Snap to parent borders.
-			if (left < nearest_snap_distance_x) {
-				nearest_snap_distance_x = left;
+			if (pborder_distance_l < nearest_snap_distance_x) {
+				nearest_snap_distance_x = pborder_distance_l;
 				assert(nearest_snap_distance_x < bsnap);
 				new_left = 0;
 			}
-			if (left + nearest_snap_distance_x > max_x_minus_w) {
-				nearest_snap_distance_x = max_x_minus_w - left;
+			if (pborder_distance_r < nearest_snap_distance_x) {
+				nearest_snap_distance_x = pborder_distance_r;
 				assert(nearest_snap_distance_x < bsnap);
-				new_left = max_x_minus_w;
+				new_left = max_x - w;
 			}
-			if (top < nearest_snap_distance_y) {
-				nearest_snap_distance_y = top;
+			if (pborder_distance_t < nearest_snap_distance_y) {
+				nearest_snap_distance_y = pborder_distance_t;
 				assert(nearest_snap_distance_y < bsnap);
 				new_top = 0;
 			}
-			if (top + nearest_snap_distance_y > max_y_minus_h) {
-				nearest_snap_distance_y = max_y_minus_h - top;
+			if (pborder_distance_b < nearest_snap_distance_y) {
+				nearest_snap_distance_y = pborder_distance_b;
 				assert(nearest_snap_distance_y < bsnap);
-				new_top = max_y_minus_h;
+				new_top = max_y - h;
 			}
 
 			if (nearest_snap_distance_x == bsnap)
@@ -669,41 +631,25 @@
 				}
 			}
 
-			if (new_left < 0)             new_left = 0;
-			if (new_top  < 0)             new_top  = 0;
-			if (new_left > max_x_minus_w) new_left = max_x_minus_w;
-			if (new_top  > max_y_minus_h) new_top  = max_y_minus_h;
-
 			if (parent->get_dock_windows_to_edges()) {
-				if (new_left == 0) {
-					if (not _docked_left)
-						dock_left();
-				} else if (_docked_left)
-					undock_left();
-				if (new_left == max_x_minus_w) {
-					if (not _docked_right) {
-						dock_right();
-						new_left += VT_B_PIXMAP_THICKNESS;
-						_drag_start_win_x += VT_B_PIXMAP_THICKNESS; //  avoid jumping
-					}
+				if (new_left <= 0 and new_left >= -VT_B_PIXMAP_THICKNESS) {
+						new_left = -VT_B_PIXMAP_THICKNESS;
+						_docked_left = true;
+				} else if (_docked_left) {
+					_docked_left = false;
+				}
+				if (new_left >= (max_x - w) and new_left <= (max_x - w) + VT_B_PIXMAP_THICKNESS) {
+					new_left = (max_x - w) + VT_B_PIXMAP_THICKNESS;
+						_docked_right = true;
 				} else if (_docked_right) {
-					undock_right();
-					new_left -= VT_B_PIXMAP_THICKNESS;
-					_drag_start_win_x -= VT_B_PIXMAP_THICKNESS; //  avoid jumping
+					_docked_right = false;
 				}
 				if (not _is_minimal) { //  minimal windows can not be bottom-docked
-					if (new_top == max_y_minus_h) {
-						if (not _docked_bottom) {
-							dock_bottom();
-							new_top += BT_B_PIXMAP_THICKNESS;
-
-							//  avoid jumping
-							_drag_start_win_y += BT_B_PIXMAP_THICKNESS;
-						}
+					if (new_top >= (max_y - h) and new_top <= (max_y - h) + BT_B_PIXMAP_THICKNESS) {
+						new_top = (max_y - h) + BT_B_PIXMAP_THICKNESS;
+							_docked_bottom = true;
 					} else if (_docked_bottom) {
-						undock_bottom();
-						new_top -= BT_B_PIXMAP_THICKNESS;
-						_drag_start_win_y -= BT_B_PIXMAP_THICKNESS; //  avoid jumping
+						_docked_bottom = false;
 					}
 				}
 			}

=== modified file 'src/ui_basic/window.h'
--- src/ui_basic/window.h	2011-11-30 21:38:37 +0000
+++ src/ui_basic/window.h	2012-02-20 14:59:27 +0000
@@ -85,18 +85,13 @@
 	bool handle_mouserelease(Uint8 btn, int32_t mx, int32_t my);
 	bool handle_mousemove
 		(Uint8 state, int32_t mx, int32_t my, int32_t xdiff, int32_t ydiff);
+	bool handle_alt_drag (int32_t mx, int32_t my);
 
 protected:
 	virtual void layout();
 	virtual void update_desired_size();
 
 private:
-	void dock_left();
-	void undock_left();
-	void dock_right();
-	void undock_right();
-	void dock_bottom();
-	void undock_bottom();
 	bool _is_minimal;
 	uint32_t _oldw, _oldh;  // if it is, these are the old formats
 	bool _dragging, _docked_left, _docked_right, _docked_bottom;


Follow ups