(svn r13029) -Codechange: more work in the road to getting the WP macros and byte[WINDOW_CUSTOM_SIZE] removed. This step changes the event handling to work directly on the Window class instead of via a function pointer and big switches while keeping backward compatability while we're rewriting the Windows to the new scheme.
authorrubidium
Sat, 10 May 2008 13:46:36 +0000
changeset 9166 dce886fc5eeb
parent 9165 6f26cc347e7a
child 9167 f99163cc2832
(svn r13029) -Codechange: more work in the road to getting the WP macros and byte[WINDOW_CUSTOM_SIZE] removed. This step changes the event handling to work directly on the Window class instead of via a function pointer and big switches while keeping backward compatability while we're rewriting the Windows to the new scheme.
src/misc_gui.cpp
src/osk_gui.cpp
src/viewport.cpp
src/widgets/dropdown.cpp
src/window.cpp
src/window_gui.h
--- a/src/misc_gui.cpp	Sat May 10 12:30:27 2008 +0000
+++ b/src/misc_gui.cpp	Sat May 10 13:46:36 2008 +0000
@@ -80,10 +80,8 @@
 public:
 	char landinfo_data[LAND_INFO_LINES][LAND_INFO_LINE_BUFF_SIZE];
 
-	virtual void HandleWindowEvent(WindowEvent *e)
+	virtual void HandlePaintEvent()
 	{
-		if (e->event != WE_PAINT) return;
-
 		DrawWindowWidgets(this);
 
 		DoDrawStringCentered(140, 16, this->landinfo_data[0], TC_LIGHT_BLUE);
@@ -1008,10 +1006,7 @@
 						/* If the parent is NULL, the editbox is handled by general function
 						 * HandleOnEditText */
 						if (parent != NULL) {
-							WindowEvent e;
-							e.event = WE_ON_EDIT_TEXT;
-							e.we.edittext.str = qs->text.buf;
-							parent->HandleWindowEvent(&e);
+							parent->OnQueryTextFinished(qs->text.buf);
 						} else {
 							HandleOnEditText(qs->text.buf);
 						}
@@ -1036,17 +1031,12 @@
 
 		case WE_DESTROY: // Call cancellation of query, if we have not handled it before
 			if (!qs->handled && w->parent != NULL) {
-				WindowEvent e;
-				Window *parent = w->parent;
-
 				qs->handled = true;
-				e.event = WE_ON_EDIT_TEXT;
-				e.we.edittext.str = NULL;
-				parent->HandleWindowEvent(&e);
+				w->parent->OnQueryTextFinished(NULL);
 			}
 			ClrBit(_no_scroll, SCROLL_EDIT);
 			break;
-		}
+	}
 }
 
 static const Widget _query_string_widgets[] = {
--- a/src/osk_gui.cpp	Sat May 10 12:30:27 2008 +0000
+++ b/src/osk_gui.cpp	Sat May 10 13:46:36 2008 +0000
@@ -157,11 +157,7 @@
 					if (qs->orig == NULL || strcmp(qs->text.buf, qs->orig) != 0) {
 						/* pass information by simulating a button press on parent window */
 						if (WP(w, osk_d).ok_btn != 0) {
-							Window *parent = w->parent;
-							WindowEvent e;
-							e.event = WE_CLICK;
-							e.we.click.widget = WP(w, osk_d).ok_btn;
-							parent->HandleWindowEvent(&e);
+							w->parent->OnClick(e->we.click.pt, WP(w, osk_d).ok_btn);
 						}
 					}
 					delete w;
@@ -169,11 +165,7 @@
 
 				case OSK_WIDGET_CANCEL:
 					if (WP(w, osk_d).cancel_btn != 0) { // pass a cancel event to the parent window
-						Window *parent = w->parent;
-						WindowEvent e;
-						e.event = WE_CLICK;
-						e.we.click.widget = WP(w, osk_d).cancel_btn;
-						parent->HandleWindowEvent(&e);
+						w->parent->OnClick(e->we.click.pt, WP(w, osk_d).cancel_btn);
 					} else { // or reset to original string
 						strcpy(qs->text.buf, WP(w, osk_d).orig);
 						UpdateTextBufferSize(&qs->text);
--- a/src/viewport.cpp	Sat May 10 12:30:27 2008 +0000
+++ b/src/viewport.cpp	Sat May 10 13:46:36 2008 +0000
@@ -2057,14 +2057,7 @@
 	_tile_fract_coords.y = pt.y & 0xF;
 
 	w = GetCallbackWnd();
-	if (w != NULL) {
-		WindowEvent e;
-
-		e.event = WE_PLACE_OBJ;
-		e.we.place.pt = pt;
-		e.we.place.tile = TileVirtXY(pt.x, pt.y);
-		w->HandleWindowEvent(&e);
-	}
+	if (w != NULL) w->OnPlaceObject(pt, TileVirtXY(pt.x, pt.y));
 }
 
 
@@ -2695,16 +2688,10 @@
 /** while dragging */
 bool VpHandlePlaceSizingDrag()
 {
-	Window *w;
-	WindowEvent e;
-
 	if (_special_mouse_mode != WSM_SIZING) return true;
 
-	e.we.place.select_method = _thd.select_method;
-	e.we.place.select_proc   = _thd.select_proc;
-
 	/* stop drag mode if the window has been closed */
-	w = FindWindowById(_thd.window_class, _thd.window_number);
+	Window *w = FindWindowById(_thd.window_class, _thd.window_number);
 	if (w == NULL) {
 		ResetObjectToPlace();
 		return false;
@@ -2712,9 +2699,7 @@
 
 	/* while dragging execute the drag procedure of the corresponding window (mostly VpSelectTilesWithMethod() ) */
 	if (_left_button_down) {
-		e.event = WE_PLACE_DRAG;
-		e.we.place.pt = GetTileBelowCursor();
-		w->HandleWindowEvent(&e);
+		w->OnPlaceDrag(_thd.select_method, _thd.select_proc, GetTileBelowCursor());
 		return false;
 	}
 
@@ -2723,7 +2708,7 @@
 	_special_mouse_mode = WSM_NONE;
 	if (_thd.next_drawstyle == HT_RECT) {
 		_thd.place_mode = VHM_RECT;
-	} else if (e.we.place.select_method == VPM_SIGNALDIRS) { // some might call this a hack... -- Dominik
+	} else if (_thd.select_method == VPM_SIGNALDIRS) { // some might call this a hack... -- Dominik
 		_thd.place_mode = VHM_RECT;
 	} else if (_thd.next_drawstyle & HT_LINE) {
 		_thd.place_mode = VHM_RAIL;
@@ -2734,12 +2719,7 @@
 	}
 	SetTileSelectSize(1, 1);
 
-	/* and call the mouseup event. */
-	e.event = WE_PLACE_MOUSEUP;
-	e.we.place.pt = _thd.selend;
-	e.we.place.tile = TileVirtXY(e.we.place.pt.x, e.we.place.pt.y);
-	e.we.place.starttile = TileVirtXY(_thd.selstart.x, _thd.selstart.y);
-	w->HandleWindowEvent(&e);
+	w->OnPlaceMouseUp(_thd.select_method, _thd.select_proc, _thd.selend, TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y));
 
 	return false;
 }
@@ -2758,7 +2738,7 @@
 	/* undo clicking on button and drag & drop */
 	if (_thd.place_mode != VHM_NONE || _special_mouse_mode == WSM_DRAGDROP) {
 		w = FindWindowById(_thd.window_class, _thd.window_number);
-		if (w != NULL) CallWindowEventNP(w, WE_ABORT_PLACE_OBJ);
+		if (w != NULL) w->OnPlaceObjectAbort();
 	}
 
 	SetTileSelectSize(1, 1);
--- a/src/widgets/dropdown.cpp	Sat May 10 12:30:27 2008 +0000
+++ b/src/widgets/dropdown.cpp	Sat May 10 13:46:36 2008 +0000
@@ -177,11 +177,7 @@
 			}
 
 			if (WP(w, dropdown_d).click_delay != 0 && --WP(w,dropdown_d).click_delay == 0) {
-				WindowEvent e;
-				e.event = WE_DROPDOWN_SELECT;
-				e.we.dropdown.button = WP(w, dropdown_d).parent_button;
-				e.we.dropdown.index  = WP(w, dropdown_d).selected_index;
-				w2->HandleWindowEvent(&e);
+				w2->OnDropdownSelect(WP(w, dropdown_d).parent_button, WP(w, dropdown_d).selected_index);
 				delete w;
 				return;
 			}
--- a/src/window.cpp	Sat May 10 12:30:27 2008 +0000
+++ b/src/window.cpp	Sat May 10 13:46:36 2008 +0000
@@ -49,7 +49,11 @@
 
 
 /**
- * Call the window event handler for handling event \a e
+ * Call the window event handler for handling event \a e.
+ * This is a temporary helper functions that will be removed
+ * once all windows that still rely on WindowEvent and
+ * WindowEventCodes have been rewritten to use the 'OnXXX'
+ * event handlers.
  * @param e Window event to handle
  */
 void Window::HandleWindowEvent(WindowEvent *e)
@@ -57,6 +61,208 @@
 	if (wndproc != NULL) wndproc(this, e);
 }
 
+void Window::OnPaint()
+{
+	WindowEvent e;
+	e.event = WE_PAINT;
+	this->HandleWindowEvent(&e);
+}
+
+bool Window::OnKeyPress(uint16 key, uint16 keycode)
+{
+	WindowEvent e;
+	e.event = WE_KEYPRESS;
+	e.we.keypress.key     = key;
+	e.we.keypress.keycode = keycode;
+	e.we.keypress.cont    = true;
+	this->HandleWindowEvent(&e);
+
+	return e.we.keypress.cont;
+}
+
+bool Window::OnCTRLStateChange()
+{
+	WindowEvent e;
+	e.event = WE_CTRL_CHANGED;
+	e.we.ctrl.cont = true;
+	this->HandleWindowEvent(&e);
+
+	return e.we.ctrl.cont;
+}
+
+void Window::OnClick(Point pt, int widget)
+{
+	WindowEvent e;
+	e.event = WE_CLICK;
+	e.we.click.pt     = pt;
+	e.we.click.widget = widget;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnDoubleClick(Point pt, int widget)
+{
+	WindowEvent e;
+	e.event = WE_DOUBLE_CLICK;
+	e.we.click.pt     = pt;
+	e.we.click.widget = widget;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnRightClick(Point pt, int widget)
+{
+	WindowEvent e;
+	e.event = WE_RCLICK;
+	e.we.click.pt     = pt;
+	e.we.click.widget = widget;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnDragDrop(Point pt, int widget)
+{
+	WindowEvent e;
+	e.event = WE_DRAGDROP;
+	e.we.click.pt     = pt;
+	e.we.click.widget = widget;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnScroll(Point delta)
+{
+	WindowEvent e;
+	e.event = WE_SCROLL;
+	e.we.scroll.delta = delta;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnMouseOver(Point pt, int widget)
+{
+	WindowEvent e;
+	e.event = WE_MOUSEOVER;
+	e.we.click.pt     = pt;
+	e.we.click.widget = widget;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnMouseWheel(int wheel)
+{
+	WindowEvent e;
+	e.event = WE_MOUSEWHEEL;
+	e.we.wheel.wheel = wheel;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnMouseLoop()
+{
+	WindowEvent e;
+	e.event = WE_MOUSELOOP;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnTick()
+{
+	WindowEvent e;
+	e.event = WE_TICK;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnHundredthTick()
+{
+	WindowEvent e;
+	e.event = WE_100_TICKS;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnTimeout()
+{
+	WindowEvent e;
+	e.event = WE_TIMEOUT;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnResize(Point new_size, Point delta)
+{
+	WindowEvent e;
+	e.event = WE_RESIZE;
+	e.we.sizing.size = new_size;
+	e.we.sizing.diff = delta;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnDropdownSelect(int widget, int index)
+{
+	WindowEvent e;
+	e.event = WE_DROPDOWN_SELECT;
+	e.we.dropdown.button = widget;
+	e.we.dropdown.index  = index;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnQueryTextFinished(char *str)
+{
+	WindowEvent e;
+	e.event = WE_ON_EDIT_TEXT;
+	e.we.edittext.str = str;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnInvalidateData(int data)
+{
+	WindowEvent e;
+	e.event = WE_INVALIDATE_DATA;
+	e.we.invalidate.data = data;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnPlaceObject(Point pt, TileIndex tile)
+{
+	WindowEvent e;
+	e.event = WE_PLACE_OBJ;
+	e.we.place.pt   = pt;
+	e.we.place.tile = tile;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnPlaceObjectAbort()
+{
+	WindowEvent e;
+	e.event = WE_ABORT_PLACE_OBJ;
+	this->HandleWindowEvent(&e);
+}
+
+
+void Window::OnPlaceDrag(ViewportPlaceMethod select_method, byte select_proc, Point pt)
+{
+	WindowEvent e;
+	e.event = WE_PLACE_DRAG;
+	e.we.place.select_method = select_method;
+	e.we.place.select_proc   = select_proc;
+	e.we.place.pt            = pt;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnPlaceMouseUp(ViewportPlaceMethod select_method, byte select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
+{
+	WindowEvent e;
+	e.event = WE_PLACE_MOUSEUP;
+	e.we.place.select_method = select_method;
+	e.we.place.select_proc   = select_proc;
+	e.we.place.pt            = pt;
+	e.we.place.tile          = end_tile;
+	e.we.place.starttile     = start_tile;
+	this->HandleWindowEvent(&e);
+}
+
+void Window::OnPlacePresize(Point pt, TileIndex tile)
+{
+	WindowEvent e;
+	e.event = WE_PLACE_PRESIZE;
+	e.we.place.pt   = pt;
+	e.we.place.tile = tile;
+	this->HandleWindowEvent(&e);
+}
+
+
+
 void CDECL Window::SetWidgetsDisabledState(bool disab_stat, int widgets, ...)
 {
 	va_list wdg_list;
@@ -138,19 +344,15 @@
  */
 static void DispatchLeftClickEvent(Window *w, int x, int y, bool double_click)
 {
-	WindowEvent e;
-	e.we.click.pt.x = x;
-	e.we.click.pt.y = y;
-	e.event = double_click ? WE_DOUBLE_CLICK : WE_CLICK;
-
+	int widget = 0;
 	if (w->desc_flags & WDF_DEF_WIDGET) {
-		e.we.click.widget = GetWidgetFromPos(w, x, y);
-		if (e.we.click.widget < 0) return; // exit if clicked outside of widgets
+		widget = GetWidgetFromPos(w, x, y);
+		if (widget < 0) return; // exit if clicked outside of widgets
 
 		/* don't allow any interaction if the button has been disabled */
-		if (w->IsWidgetDisabled(e.we.click.widget)) return;
+		if (w->IsWidgetDisabled(widget)) return;
 
-		const Widget *wi = &w->widget[e.we.click.widget];
+		const Widget *wi = &w->widget[widget];
 
 		if (wi->type & WWB_MASK) {
 			/* special widget handling for buttons*/
@@ -158,20 +360,20 @@
 				case WWT_PANEL   | WWB_PUSHBUTTON: /* WWT_PUSHBTN */
 				case WWT_IMGBTN  | WWB_PUSHBUTTON: /* WWT_PUSHIMGBTN */
 				case WWT_TEXTBTN | WWB_PUSHBUTTON: /* WWT_PUSHTXTBTN */
-					w->HandleButtonClick(e.we.click.widget);
+					w->HandleButtonClick(widget);
 					break;
 			}
 		} else if (wi->type == WWT_SCROLLBAR || wi->type == WWT_SCROLL2BAR || wi->type == WWT_HSCROLLBAR) {
-			ScrollbarClickHandler(w, wi, e.we.click.pt.x, e.we.click.pt.y);
+			ScrollbarClickHandler(w, wi, x, y);
 		}
 
 		if (w->desc_flags & WDF_STD_BTN) {
-			if (e.we.click.widget == 0) { /* 'X' */
+			if (widget == 0) { /* 'X' */
 				delete w;
 				return;
 			}
 
-			if (e.we.click.widget == 1) { /* 'Title bar' */
+			if (widget == 1) { /* 'Title bar' */
 				StartWindowDrag(w);
 				return;
 			}
@@ -179,18 +381,24 @@
 
 		if (w->desc_flags & WDF_RESIZABLE && wi->type == WWT_RESIZEBOX) {
 			StartWindowSizing(w);
-			w->InvalidateWidget(e.we.click.widget);
+			w->InvalidateWidget(widget);
 			return;
 		}
 
 		if (w->desc_flags & WDF_STICKY_BUTTON && wi->type == WWT_STICKYBOX) {
 			w->flags4 ^= WF_STICKY;
-			w->InvalidateWidget(e.we.click.widget);
+			w->InvalidateWidget(widget);
 			return;
 		}
 	}
 
-	w->HandleWindowEvent(&e);
+	Point pt = { x, y };
+
+	if (double_click) {
+		w->OnDoubleClick(pt, widget);
+	} else {
+		w->OnClick(pt, widget);
+	}
 }
 
 /**
@@ -201,23 +409,21 @@
  */
 static void DispatchRightClickEvent(Window *w, int x, int y)
 {
-	WindowEvent e;
+	int widget = 0;
 
 	/* default tooltips handler? */
 	if (w->desc_flags & WDF_STD_TOOLTIPS) {
-		e.we.click.widget = GetWidgetFromPos(w, x, y);
-		if (e.we.click.widget < 0) return; // exit if clicked outside of widgets
+		widget = GetWidgetFromPos(w, x, y);
+		if (widget < 0) return; // exit if clicked outside of widgets
 
-		if (w->widget[e.we.click.widget].tooltips != 0) {
-			GuiShowTooltips(w->widget[e.we.click.widget].tooltips);
+		if (w->widget[widget].tooltips != 0) {
+			GuiShowTooltips(w->widget[widget].tooltips);
 			return;
 		}
 	}
 
-	e.event = WE_RCLICK;
-	e.we.click.pt.x = x;
-	e.we.click.pt.y = y;
-	w->HandleWindowEvent(&e);
+	Point pt = { x, y };
+	w->OnRightClick(pt, widget);
 }
 
 /**
@@ -315,7 +521,7 @@
 	dp->pitch = _screen.pitch;
 	dp->dst_ptr = BlitterFactoryBase::GetCurrentBlitter()->MoveTo(_screen.dst_ptr, left, top);
 	dp->zoom = ZOOM_LVL_NORMAL;
-	CallWindowEventNP(*wz, WE_PAINT);
+	(*wz)->OnPaint();
 }
 
 /**
@@ -345,20 +551,6 @@
 }
 
 /**
- * Dispatch an event to a possibly non-existing window.
- * If the window pointer w is \c NULL, the event is not dispatched
- * @param w Window to dispatch the event to, may be \c NULL
- * @param event Event to dispatch
- */
-void CallWindowEventNP(Window *w, int event)
-{
-	WindowEvent e;
-
-	e.event = event;
-	w->HandleWindowEvent(&e);
-}
-
-/**
  * Mark entire window as dirty (in need of re-paint)
  * @param w Window to redraw
  * @ingroup dirty
@@ -437,7 +629,9 @@
 	/* Delete any children a window might have in a head-recursive manner */
 	delete FindChildWindow(this);
 
-	CallWindowEventNP(this, WE_DESTROY);
+	WindowEvent e;
+	e.event = WE_DESTROY;
+	this->HandleWindowEvent(&e);
 	if (this->viewport != NULL) DeleteWindowViewport(this);
 
 	this->SetDirty();
@@ -770,13 +964,13 @@
 
 		ResizeWindow(this, enlarge_x, enlarge_y);
 
-		WindowEvent e;
-		e.event = WE_RESIZE;
-		e.we.sizing.size.x = this->width;
-		e.we.sizing.size.y = this->height;
-		e.we.sizing.diff.x = enlarge_x;
-		e.we.sizing.diff.y = enlarge_y;
-		this->HandleWindowEvent(&e);
+		Point size;
+		Point diff;
+		size.x = this->width;
+		size.y = this->height;
+		diff.x = enlarge_x;
+		diff.y = enlarge_y;
+		this->OnResize(size, diff);
 	}
 
 	int nx = this->left;
@@ -1072,14 +1266,14 @@
 			w->flags4 &= ~(WF_SCROLL_DOWN | WF_SCROLL_UP);
 			w->SetDirty();
 		}
-		CallWindowEventNP(w, WE_MOUSELOOP);
+		w->OnMouseLoop();
 	}
 
 	for (wz = _last_z_window; wz != _z_windows;) {
 		Window *w = *--wz;
 
 		if (w->flags4 & WF_TIMEOUT_MASK && !(--w->flags4 & WF_TIMEOUT_MASK)) {
-			CallWindowEventNP(w, WE_TIMEOUT);
+			w->OnTimeout();
 			if (w->desc_flags & WDF_UNCLICK_BUTTONS) w->RaiseButtons();
 		}
 	}
@@ -1097,15 +1291,13 @@
 	Window *w = GetCallbackWnd();
 	if (w == NULL) return;
 
-	WindowEvent e;
-	e.we.place.pt = GetTileBelowCursor();
-	if (e.we.place.pt.x == -1) {
+	Point pt = GetTileBelowCursor();
+	if (pt.x == -1) {
 		_thd.selend.x = -1;
 		return;
 	}
-	e.we.place.tile = TileVirtXY(e.we.place.pt.x, e.we.place.pt.y);
-	e.event = WE_PLACE_PRESIZE;
-	w->HandleWindowEvent(&e);
+
+	w->OnPlacePresize(pt, TileVirtXY(pt.x, pt.y));
 }
 
 static bool HandleDragDrop()
@@ -1117,12 +1309,10 @@
 
 	if (w != NULL) {
 		/* send an event in client coordinates. */
-		WindowEvent e;
-		e.event = WE_DRAGDROP;
-		e.we.dragdrop.pt.x = _cursor.pos.x - w->left;
-		e.we.dragdrop.pt.y = _cursor.pos.y - w->top;
-		e.we.dragdrop.widget = GetWidgetFromPos(w, e.we.dragdrop.pt.x, e.we.dragdrop.pt.y);
-		w->HandleWindowEvent(&e);
+		Point pt;
+		pt.x = _cursor.pos.x - w->left;
+		pt.y = _cursor.pos.y - w->top;
+		w->OnDragDrop(pt, GetWidgetFromPos(w, pt.x, pt.y));
 	}
 
 	ResetObjectToPlace();
@@ -1137,11 +1327,8 @@
 	/* We changed window, put a MOUSEOVER event to the last window */
 	if (_mouseover_last_w != NULL && _mouseover_last_w != w) {
 		/* Reset mouse-over coordinates of previous window */
-		WindowEvent e;
-		e.event = WE_MOUSEOVER;
-		e.we.mouseover.pt.x = -1;
-		e.we.mouseover.pt.y = -1;
-		_mouseover_last_w->HandleWindowEvent(&e);
+		Point pt = { -1, -1 };
+		_mouseover_last_w->OnMouseOver(pt, 0);
 	}
 
 	/* _mouseover_last_w will get reset when the window is deleted, see DeleteWindow() */
@@ -1149,14 +1336,12 @@
 
 	if (w != NULL) {
 		/* send an event in client coordinates. */
-		WindowEvent e;
-		e.event = WE_MOUSEOVER;
-		e.we.mouseover.pt.x = _cursor.pos.x - w->left;
-		e.we.mouseover.pt.y = _cursor.pos.y - w->top;
+		Point pt = { _cursor.pos.x - w->left, _cursor.pos.y - w->top };
+		int widget = 0;
 		if (w->widget != NULL) {
-			e.we.mouseover.widget = GetWidgetFromPos(w, e.we.mouseover.pt.x, e.we.mouseover.pt.y);
+			widget = GetWidgetFromPos(w, pt.x, pt.y);
 		}
-		w->HandleWindowEvent(&e);
+		w->OnMouseOver(pt, widget);
 	}
 
 	/* Mouseover never stops execution */
@@ -1360,7 +1545,6 @@
 			w->SetDirty();
 			return false;
 		} else if (w->flags4 & WF_SIZING) {
-			WindowEvent e;
 			int x, y;
 
 			/* Stop the sizing if the left mouse button was released */
@@ -1397,12 +1581,13 @@
 			/* ResizeWindow sets both pre- and after-size to dirty for redrawal */
 			ResizeWindow(w, x, y);
 
-			e.event = WE_RESIZE;
-			e.we.sizing.size.x = x + w->width;
-			e.we.sizing.size.y = y + w->height;
-			e.we.sizing.diff.x = x;
-			e.we.sizing.diff.y = y;
-			w->HandleWindowEvent(&e);
+			Point size;
+			Point diff;
+			size.x = x + w->width;
+			size.y = y + w->height;
+			diff.x = x;
+			diff.y = y;
+			w->OnResize(size, diff);
 			return false;
 		}
 	}
@@ -1493,8 +1678,6 @@
 
 static bool HandleViewportScroll()
 {
-	WindowEvent e;
-
 	bool scrollwheel_scrolling = _patches.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
 
 	if (!_scrolling_viewport) return true;
@@ -1514,25 +1697,25 @@
 		return true;
 	}
 
+	Point delta;
 	if (_patches.reverse_scroll) {
-		e.we.scroll.delta.x = -_cursor.delta.x;
-		e.we.scroll.delta.y = -_cursor.delta.y;
+		delta.x = -_cursor.delta.x;
+		delta.y = -_cursor.delta.y;
 	} else {
-		e.we.scroll.delta.x = _cursor.delta.x;
-		e.we.scroll.delta.y = _cursor.delta.y;
+		delta.x = _cursor.delta.x;
+		delta.y = _cursor.delta.y;
 	}
 
 	if (scrollwheel_scrolling) {
 		/* We are using scrollwheels for scrolling */
-		e.we.scroll.delta.x = _cursor.h_wheel;
-		e.we.scroll.delta.y = _cursor.v_wheel;
+		delta.x = _cursor.h_wheel;
+		delta.y = _cursor.v_wheel;
 		_cursor.v_wheel = 0;
 		_cursor.h_wheel = 0;
 	}
 
 	/* Create a scroll-event and send it to the window */
-	e.event = WE_SCROLL;
-	w->HandleWindowEvent(&e);
+	w->OnScroll(delta);
 
 	_cursor.delta.x = 0;
 	_cursor.delta.y = 0;
@@ -1592,11 +1775,10 @@
 }
 
 /** Handle keyboard input.
- * @param key Lower 8 bits contain the ASCII character, the higher 16 bits the keycode
+ * @param raw_key Lower 8 bits contain the ASCII character, the higher 16 bits the keycode
  */
-void HandleKeypress(uint32 key)
+void HandleKeypress(uint32 raw_key)
 {
-	WindowEvent e;
 	/* Stores if a window with a textfield for typing is open
 	 * If this is the case, keypress events are only passed to windows with text fields and
 	 * to thein this main toolbar. */
@@ -1614,10 +1796,8 @@
 	if (!IsGeneratingWorld()) _current_player = _local_player;
 
 	/* Setup event */
-	e.event = WE_KEYPRESS;
-	e.we.keypress.key     = GB(key,  0, 16);
-	e.we.keypress.keycode = GB(key, 16, 16);
-	e.we.keypress.cont = true;
+	uint16 key     = GB(raw_key,  0, 16);
+	uint16 keycode = GB(raw_key, 16, 16);
 
 	/*
 	 * The Unicode standard defines an area called the private use area. Code points in this
@@ -1626,12 +1806,12 @@
 	 * on a system running OS X. We don't want these keys to show up in text fields and such,
 	 * and thus we have to clear the unicode character when we encounter such a key.
 	 */
-	if (e.we.keypress.key >= 0xE000 && e.we.keypress.key <= 0xF8FF) e.we.keypress.key = 0;
+	if (key >= 0xE000 && key <= 0xF8FF) key = 0;
 
 	/*
 	 * If both key and keycode is zero, we don't bother to process the event.
 	 */
-	if (e.we.keypress.key == 0 && e.we.keypress.keycode == 0) return;
+	if (key == 0 && keycode == 0) return;
 
 	/* check if we have a query string window open before allowing hotkeys */
 	if (FindWindowById(WC_QUERY_STRING,            0) != NULL ||
@@ -1657,15 +1837,13 @@
 				w->window_class != WC_COMPANY_PASSWORD_WINDOW) {
 			continue;
 		}
-		w->HandleWindowEvent(&e);
-		if (!e.we.keypress.cont) break;
+		;
+		if (!w->OnKeyPress(key, keycode)) return;
 	}
 
-	if (e.we.keypress.cont) {
-		Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
-		/* When there is no toolbar w is null, check for that */
-		if (w != NULL) w->HandleWindowEvent(&e);
-	}
+	Window *w = FindWindowById(WC_MAIN_TOOLBAR, 0);
+	/* When there is no toolbar w is null, check for that */
+	if (w != NULL) w->OnKeyPress(key, keycode);
 }
 
 /**
@@ -1673,16 +1851,10 @@
  */
 void HandleCtrlChanged()
 {
-	WindowEvent e;
-
-	e.event = WE_CTRL_CHANGED;
-	e.we.ctrl.cont = true;
-
 	/* Call the event, start with the uppermost window. */
 	for (Window* const *wz = _last_z_window; wz != _z_windows;) {
 		Window *w = *--wz;
-		w->HandleWindowEvent(&e);
-		if (!e.we.ctrl.cont) break;
+		if (!w->OnCTRLStateChange()) break;
 	}
 }
 
@@ -1775,13 +1947,8 @@
 
 	if (mousewheel != 0) {
 		if (_patches.scrollwheel_scrolling == 0) {
-			/* Scrollwheel is in zoom mode. Make the zoom event. */
-			WindowEvent e;
-
 			/* Send WE_MOUSEWHEEL event to window */
-			e.event = WE_MOUSEWHEEL;
-			e.we.wheel.wheel = mousewheel;
-			w->HandleWindowEvent(&e);
+			w->OnMouseWheel(mousewheel);
 		}
 
 		/* Dispatch a MouseWheelEvent for widgets if it is not a viewport */
@@ -1910,7 +2077,7 @@
 
 	if (t >= 100) {
 		for (wz = _last_z_window; wz != _z_windows;) {
-			CallWindowEventNP(*--wz, WE_100_TICKS);
+			(*--wz)->OnHundredthTick();
 		}
 		t = 0;
 	}
@@ -1987,12 +2154,7 @@
  */
 void InvalidateThisWindowData(Window *w, int data)
 {
-	WindowEvent e;
-
-	e.event = WE_INVALIDATE_DATA;
-	e.we.invalidate.data = data;
-
-	w->HandleWindowEvent(&e);
+	w->OnInvalidateData(data);
 	w->SetDirty();
 }
 
@@ -2030,7 +2192,7 @@
 void CallWindowTickEvent()
 {
 	for (Window * const *wz = _last_z_window; wz != _z_windows;) {
-		CallWindowEventNP(*--wz, WE_TICK);
+		(*--wz)->OnTick();
 	}
 }
 
@@ -2147,13 +2309,13 @@
 				if (neww - w->width != 0) {
 					ResizeWindow(w, min(neww, 640) - w->width, 0);
 
-					WindowEvent e;
-					e.event = WE_RESIZE;
-					e.we.sizing.size.x = w->width;
-					e.we.sizing.size.y = w->height;
-					e.we.sizing.diff.x = neww - w->width;
-					e.we.sizing.diff.y = 0;
-					w->HandleWindowEvent(&e);
+					Point size;
+					Point delta;
+					size.x = w->width;
+					size.y = w->height;
+					delta.x = neww - w->width;
+					delta.y = 0;
+					w->OnResize(size, delta);
 				}
 
 				top = w->top;
--- a/src/window_gui.h	Sat May 10 12:30:27 2008 +0000
+++ b/src/window_gui.h	Sat May 10 13:46:36 2008 +0000
@@ -276,6 +276,7 @@
 struct Window : ZeroedMemoryAllocator {
 private:
 	WindowProc *wndproc;   ///< Event handler function for the window. Do not use directly, call HandleWindowEvent() instead.
+	void HandleWindowEvent(WindowEvent *e);
 
 protected:
 	void Initialize(int x, int y, int min_width, int min_height, int def_width, int def_height,
@@ -336,7 +337,173 @@
 
 	void SetDirty() const;
 
-	virtual void HandleWindowEvent(WindowEvent *e);
+	/*** Event handling ***/
+
+	/**
+	 * This window is currently being repainted.
+	 */
+	virtual void OnPaint();
+
+
+	/**
+	 * A key has been pressed.
+	 * @param key     the Unicode value of the key.
+	 * @param keycode the untranslated key code including shift state.
+	 * @return true if the key press has been handled and no other
+	 *         window should receive the event.
+	 */
+	virtual bool OnKeyPress(uint16 key, uint16 keycode);
+
+	/**
+	 * The state of the control key has changed
+	 * @return true if the change has been handled and no other
+	 *         window should receive the event.
+	 */
+	virtual bool OnCTRLStateChange();
+
+
+	/**
+	 * A click with the left mouse button has been made on the window.
+	 * @param pt     the point inside the window that has been clicked.
+	 * @param widget the clicked widget.
+	 */
+	virtual void OnClick(Point pt, int widget);
+
+	/**
+	 * A double click with the left mouse button has been made on the window.
+	 * @param pt     the point inside the window that has been clicked.
+	 * @param widget the clicked widget.
+	 */
+	virtual void OnDoubleClick(Point pt, int widget);
+
+	/**
+	 * A click with the right mouse button has been made on the window.
+	 * @param pt     the point inside the window that has been clicked.
+	 * @param widget the clicked widget.
+	 */
+	virtual void OnRightClick(Point pt, int widget);
+
+	/**
+	 * A dragged 'object' has been released.
+	 * @param pt     the point inside the window where the release took place.
+	 * @param widget the widget where the release took place.
+	 */
+	virtual void OnDragDrop(Point pt, int widget);
+
+	/**
+	 * Handle the request for (viewport) scrolling.
+	 * @param delta the amount the viewport must be scrolled.
+	 */
+	virtual void OnScroll(Point delta);
+
+	/**
+	 * The mouse is currently moving over the window or has just moved outside
+	 * of the window. In the latter case pt is (-1, -1).
+	 * @param pt     the point inside the window that the mouse hovers over.
+	 * @param widget the widget the mouse hovers over.
+	 */
+	virtual void OnMouseOver(Point pt, int widget);
+
+	/**
+	 * The mouse wheel has been turned.
+	 * @param wheel the amount of movement of the mouse wheel.
+	 */
+	virtual void OnMouseWheel(int wheel);
+
+
+	/**
+	 * Called for every mouse loop run, which is at least once per (game) tick.
+	 */
+	virtual void OnMouseLoop();
+
+	/**
+	 * Called once per (game) tick.
+	 */
+	virtual void OnTick();
+
+	/**
+	 * Called once every 100 (game) ticks.
+	 */
+	virtual void OnHundredthTick();
+
+	/**
+	 * Called when this window's timeout has been reached.
+	 */
+	virtual void OnTimeout();
+
+
+	/**
+	 * Called when the window got resized.
+	 * @param new_size the new size of the window.
+	 * @param delta    the amount of which the window size changed.
+	 */
+	virtual void OnResize(Point new_size, Point delta);
+
+	/**
+	 * A dropdown option associated to this window has been selected.
+	 * @param widget the widget (button) that the dropdown is associated with.
+	 * @param index  the element in the dropdown that is selected.
+	 */
+	virtual void OnDropdownSelect(int widget, int index);
+
+	/**
+	 * The query window opened from this window has closed.
+	 * @param str the new value of the string or NULL if the window
+	 *            was cancelled.
+	 */
+	virtual void OnQueryTextFinished(char *str);
+
+	/**
+	 * Some data on this window has become invalid.
+	 * @param data information about the changed data.
+	 */
+	virtual void OnInvalidateData(int data = 0);
+
+
+	/**
+	 * The user clicked some place on the map when a tile highlight mode
+	 * has been set.
+	 * @param pt   the exact point on the map that has been clicked.
+	 * @param tile the tile on the map that has been clicked.
+	 */
+	virtual void OnPlaceObject(Point pt, TileIndex tile);
+
+	/**
+	 * The user cancelled a tile highlight mode that has been set.
+	 */
+	virtual void OnPlaceObjectAbort();
+
+
+	/**
+	 * The user is dragging over the map when the tile highlight mode
+	 * has been set.
+	 * @param select_method the method of selection (allowed directions)
+	 * @param select_proc   what will be created when the drag is over.
+	 * @param pt            the exact point on the map where the mouse is.
+	 */
+	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, byte select_proc, Point pt);
+
+	/**
+	 * The user has dragged over the map when the tile highlight mode
+	 * has been set.
+	 * @param select_method the method of selection (allowed directions)
+	 * @param select_proc   what should be created.
+	 * @param pt            the exact point on the map where the mouse was released.
+	 * @param start_tile    the begin tile of the drag.
+	 * @param end_tile      the end tile of the drag.
+	 */
+	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, byte select_proc, Point pt, TileIndex start_tile, TileIndex end_tile);
+
+	/**
+	 * The user moves over the map when a tile highlight mode has been set
+	 * when the special mouse mode has been set to 'PRESIZE' mode. An
+	 * example of this is the tile highlight for dock building.
+	 * @param pt   the exact point on the map where the mouse is.
+	 * @param tile the tile on the map where the mouse is.
+	 */
+	virtual void OnPlacePresize(Point pt, TileIndex tile);
+
+	/*** End of the event handling ***/
 };
 
 struct menu_d {
@@ -481,9 +648,6 @@
 	WF_SCROLL2           = 1 << 13,
 };
 
-/* window.cpp */
-void CallWindowEventNP(Window *w, int event);
-
 Window *BringWindowToFrontById(WindowClass cls, WindowNumber number);
 Window *FindWindowFromPt(int x, int y);