Index: openttd-1.0.2/src/viewport.cpp
===================================================================
--- openttd-1.0.2.orig/src/viewport.cpp	2010-05-18 23:38:09.000000000 +0200
+++ openttd-1.0.2/src/viewport.cpp	2010-06-28 23:00:09.000000000 +0200
@@ -1518,6 +1518,7 @@
 
 		w->viewport->scrollpos_x = pt.x;
 		w->viewport->scrollpos_y = pt.y;
+		StopAllInertia(w);
 		SetViewportPosition(w, pt.x, pt.y);
 	} else {
 		/* Ensure the destination location is within the map */
@@ -1527,6 +1528,7 @@
 		int delta_y = w->viewport->dest_scrollpos_y - w->viewport->scrollpos_y;
 
 		if (delta_x != 0 || delta_y != 0) {
+			StopAllInertia(w);
 			if (_settings_client.gui.smooth_scroll) {
 				int max_scroll = ScaleByMapSize1D(512);
 				/* Not at our desired positon yet... */
@@ -1879,6 +1881,8 @@
 		w->viewport->scrollpos_y = pt.y;
 	}
 
+	StopAllInertia(w);
+
 	w->viewport->dest_scrollpos_x = pt.x;
 	w->viewport->dest_scrollpos_y = pt.y;
 	return true;
Index: openttd-1.0.2/src/window.cpp
===================================================================
--- openttd-1.0.2.orig/src/window.cpp	2010-05-18 23:30:56.000000000 +0200
+++ openttd-1.0.2/src/window.cpp	2010-06-28 23:00:09.000000000 +0200
@@ -11,6 +11,8 @@
 
 #include "stdafx.h"
 #include <stdarg.h>
+#include <stdlib.h>
+#include <math.h>
 #include "company_func.h"
 #include "gfx_func.h"
 #include "console_func.h"
@@ -58,6 +60,70 @@
 bool _scrolling_viewport;  ///< A viewport is being scrolled with the mouse.
 bool _mouse_hovering;      ///< The mouse is hovering over the same point. 

+static struct panning {
+	unsigned int x, y;
+	float vel_x, vel_y;
+	float old_vel_x, old_vel_y;
+	unsigned long ticks;
+	bool moved;
+	bool click_allowed;
+} mw_pan = { 0, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0, false, false };
+
+/**  Inertia of the cursor dragging
+ *   Percentage of the calculated speed in each moment we are are going to use
+ *   to calculate the launch speed, the other part would be the speed"
+ *   calculated previously.
+ */
+static const float drag_inertia = 0.85f;
+/** Amount of pixels to consider a motion event an scroll, if it is less
+ *  it is a click detected incorrectly by the touch screen. */
+static const int panning_threshold = 25;
+
+/* Minimum distance the child widget should scroll per frame */
+static const float vmin = 10.0f;
+/* Maximum distance the child widget should scroll per frame */
+static const float vmax = 500.0f;
+/** Minimum velocity that is considered 'fast':
+ *  Children widgets won't receive button presses.
+ *  Expressed as a fraction of the maximum velocity.
+ */
+static const float vfast_factor = 0.1f;
+static const float vfast = vmax * vfast_factor;
+/** Deceleration multiplier
+ *  The multiplier used when decelerating when in
+ *  acceleration scrolling mode.
+ */
+static const float decel = 0.95f;
+
+static void PanCalculateSpeed(float* vel, unsigned int delta, int dist)
+{
+	if (abs(dist) > 0) {
+		float rawvel = (float)dist / (float)delta;
+		*vel = *vel * (1.0f - drag_inertia) + rawvel * drag_inertia;
+		*vel = *vel > 0 ? fminf(*vel, vmax) : fmaxf(*vel, -vmax);
+	} else {
+		*vel *= drag_inertia;
+	}
+}
+
+static bool PanHandleMove(const Point& delta, const unsigned long ticks)
+{
+	bool moved = abs(delta.x) > panning_threshold ||
+	  	abs(delta.y) > panning_threshold;
+	if (ticks > 0 && (mw_pan.moved || moved)) {
+		PanCalculateSpeed(&mw_pan.vel_x, ticks, delta.x);
+		PanCalculateSpeed(&mw_pan.vel_y, ticks, delta.y);
+		mw_pan.x = _cursor.pos.x;
+		mw_pan.y = _cursor.pos.y;
+		mw_pan.ticks = 0;
+		mw_pan.moved = true;
+		return true;
+	} else {
+		/* not moved enough */
+		return false;
+	}
+}
+
 SpecialMouseMode _special_mouse_mode; ///< Mode of the mouse.
 
 /** Window description constructor. */
@@ -1781,14 +1847,37 @@
 	* When the last scroll window and this are not the same we went
 	* outside of the window and should not left-mouse scroll anymore. */
 	if (_last_scroll_window == NULL) _last_scroll_window = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
+	const Window *mw = FindWindowById(WC_MAIN_WINDOW, 0);

 	if (_last_scroll_window == NULL || !(_right_button_down || scrollwheel_scrolling || (_settings_client.gui.left_mouse_btn_scrolling && _left_button_down))) {
+		// mouse release
+		if (_last_scroll_window == mw) {
+			if (!mw_pan.moved) {
+				if (mw_pan.click_allowed) {
+					HandleViewportClicked(_last_scroll_window->viewport,
+						_cursor.pos.x, _cursor.pos.y);
+					mw_pan.click_allowed = false;
+				}
+			} else {
+				Point delta;
+				delta.x = mw_pan.x - _cursor.pos.x;
+				delta.y = mw_pan.y - _cursor.pos.y;
+
+				PanHandleMove(delta, mw_pan.ticks);
+
+				// TODO If you want to put extra acceleration.
+
+				_cursor.delta.x = 0;
+				_cursor.delta.y = 0;
+			}
+		}
+		mw_pan.moved = false;
 		_cursor.fix_at = false;
 		_scrolling_viewport = false;
 		_last_scroll_window = NULL;
 		return ES_NOT_HANDLED;
 	}
 
-	if (_last_scroll_window == FindWindowById(WC_MAIN_WINDOW, 0) && _last_scroll_window->viewport->follow_vehicle != INVALID_VEHICLE) {
+	if (_last_scroll_window == mw && _last_scroll_window->viewport->follow_vehicle != INVALID_VEHICLE) {
 		/* If the main window is following a vehicle, then first let go of it! */
 		const Vehicle *veh = Vehicle::Get(_last_scroll_window->viewport->follow_vehicle);
@@ -1812,6 +1901,21 @@
 		_cursor.h_wheel = 0;
 	}
 
+	/* Scrolling in main window */
+	if (_last_scroll_window == mw) {
+		/* we prefer our own deltas */
+		delta.x = mw_pan.x - _cursor.pos.x;
+		delta.y = mw_pan.y - _cursor.pos.y;
+
+		if (PanHandleMove(delta, mw_pan.ticks)) {
+			_last_scroll_window->OnScroll(delta);
+		}
+
+		_cursor.delta.x = 0;
+		_cursor.delta.y = 0;
+		return ES_HANDLED;
+	}
+
 	/* Create a scroll-event and send it to the window */
 	if (delta.x != 0 || delta.y != 0) w->OnScroll(delta);
 
@@ -1820,6 +1924,44 @@
 	return ES_HANDLED;
 }
 
+static void HandleViewportKineticScroll()
+{
+	if (_scrolling_viewport) {
+		/* Finger still down */
+		mw_pan.ticks++;
+		return;
+	}
+
+	if (mw_pan.vel_x == 0.0f && mw_pan.vel_y == 0.0f) {
+		/** Not moving */
+		return;
+	}
+
+	/* Get main window */
+	Window * w = FindWindowById(WC_MAIN_WINDOW, 0);
+
+	/* Create a scroll-event and send it to the window */
+	Point speed = { lroundf(mw_pan.vel_x), lroundf(mw_pan.vel_y) };
+	w->OnScroll(speed);
+
+	/* Apply friction */
+	mw_pan.vel_x *= decel;
+	mw_pan.vel_y *= decel;
+
+	if (fabsf(mw_pan.vel_x) < 1.0f && fabsf(mw_pan.vel_y) < 1.0f) {
+		mw_pan.vel_x = 0.0f;
+		mw_pan.vel_y = 0.0f;
+	}
+}
+
+void StopAllInertia(Window *w)
+{
+	if (w == FindWindowById(WC_MAIN_WINDOW, 0)) {
+		mw_pan.vel_x = 0.0f;
+		mw_pan.vel_y = 0.0f;
+	}
+}
+
 /**
  * Check if a window can be made top-most window, and if so do
  * it. If a window does not obscure any other windows, it will not
@@ -2058,12 +2200,12 @@
 	if (!HandleViewportScroll())     return;
 	if (!HandleMouseOver())          return;
 
-	bool scrollwheel_scrolling = _settings_client.gui.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
-	if (click == MC_NONE && mousewheel == 0 && !scrollwheel_scrolling) return;
+	if (click == MC_NONE) return;
 
 	int x = _cursor.pos.x;
 	int y = _cursor.pos.y;
 	Window *w = FindWindowFromPt(x, y);
+	const Window* mw = FindWindowById(WC_MAIN_WINDOW, 0);
 	if (w == NULL) return;
 
 	if (!MaybeBringWindowToFront(w)) return;
@@ -2083,7 +2225,6 @@
 	}
 
 	if (vp != NULL) {
-		if (scrollwheel_scrolling) click = MC_RIGHT; // we are using the scrollwheel in a viewport, so we emulate right mouse button
 		switch (click) {
 			case MC_DOUBLE_LEFT:
 			case MC_LEFT:
@@ -2098,7 +2239,29 @@
 			case MC_DOUBLE_LEFT:
 			case MC_LEFT: 
 				DEBUG(misc, 2, "Cursor: 0x%X (%d)", _cursor.sprite, _cursor.sprite);
-				if (!HandleViewportClicked(vp, x, y) &&
+					if (w == mw && ((_thd.drawstyle & HT_DRAG_MASK) == HT_NONE)) {
+						/* Clicking in the main window, not in Place mode. */
+						mw_pan.x = x;
+						mw_pan.y = y;
+						mw_pan.ticks = 1;
+						/* 1 works better when the user scrolls fast */
+
+						/* Only allow clicking if we're going slowly enough
+						   and we're not following a vehicle. */
+						mw_pan.click_allowed = fabsf(mw_pan.vel_x) <= vfast &&
+												fabsf(mw_pan.vel_y) <= vfast &&
+								w->viewport->follow_vehicle == INVALID_VEHICLE;
+
+						/* Stop scrolling on mouse down */
+						mw_pan.old_vel_x = mw_pan.vel_x;
+						mw_pan.old_vel_y = mw_pan.vel_y;
+						mw_pan.vel_x = 0.0f;
+						mw_pan.vel_y = 0.0f;
+
+						/* React to button release, not press. */
+						_scrolling_viewport = true;
+						_cursor.fix_at = false;
+					} else if (!HandleViewportClicked(vp, x, y) &&
 						!(w->flags4 & WF_DISABLE_VP_SCROLL) &&
 						_settings_client.gui.left_mouse_btn_scrolling) {
 					_scrolling_viewport = true;
@@ -2130,13 +2293,10 @@
 				DispatchLeftClickEvent(w, x - w->left, y - w->top, click == MC_DOUBLE_LEFT ? 2 : 1);
 				break;
 
-			default:
-				if (!scrollwheel_scrolling || w == NULL || w->window_class != WC_SMALLMAP) break;
-				/* We try to use the scrollwheel to scroll since we didn't touch any of the buttons.
-				 * Simulate a right button click so we can get started. */
-				/* FALL THROUGH */
-
 			case MC_RIGHT: DispatchRightClickEvent(w, x - w->left, y - w->top); break;
 
 			case MC_HOVER: DispatchHoverEvent(w, x - w->left, y - w->top); break;
+
+			default:
+				break;
 		}
@@ -2265,6 +2425,7 @@
 	/* HandleMouseEvents was already called for this tick */
 	HandleMouseEvents();
 	HandleAutoscroll();
+	HandleViewportKineticScroll();
 }
 
 /**
Index: openttd-1.0.2/src/window_func.h
===================================================================
--- openttd-1.0.2.orig/src/window_func.h	2009-11-29 01:41:08.000000000 +0100
+++ openttd-1.0.2/src/window_func.h	2010-06-28 23:00:09.000000000 +0200
@@ -31,6 +31,8 @@
 void SetupColoursAndInitialWindow();
 void InputLoop();
 
+void StopAllInertia(Window *w);
+
 void InvalidateWindowData(WindowClass cls, WindowNumber number, int data = 0, bool gui_scope = false);
 void InvalidateWindowClassesData(WindowClass cls, int data = 0, bool gui_scope = false);
 
