changeset 4719:02fb2f850a8a draft

(svn r6631) -Codechange: Use accessors for click_state. Another step toward merging XTDwidget. The only two files not converted (window.h and widget.c) will be done at the very last commit)
author belugas <belugas@openttd.org>
date Tue, 03 Oct 2006 20:16:20 +0000
parents b5cc546b1ebb
children 363907847ea9
files airport_gui.c depot_gui.c dock_gui.c genworld_gui.c graph_gui.c industry_gui.c intro_gui.c main_gui.c misc_gui.c music_gui.c network_gui.c news_gui.c order_gui.c player_gui.c rail_gui.c road_gui.c settings_gui.c smallmap_gui.c station_gui.c terraform_gui.c widget.c window.c window.h
diffstat 23 files changed, 313 insertions(+), 185 deletions(-) [+]
line wrap: on
line diff
--- a/airport_gui.c
+++ b/airport_gui.c
@@ -99,8 +99,8 @@
 		break;
 
 	case WE_ABORT_PLACE_OBJ:
-		UnclickWindowButtons(w);
-		SetWindowDirty(w);
+		RaiseWindowButtons(w);
+
 		w = FindWindowById(WC_BUILD_STATION, 0);
 		if (w != 0)
 			WP(w,def_d).close = true;
@@ -142,20 +142,26 @@
 static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE:
+		SetWidgetLoweredState(w, 16, !_station_show_coverage);
+		SetWidgetLoweredState(w, 17, _station_show_coverage);
+		LowerWindowWidget(w, _selected_airport_type + 7);
+		break;
+
 	case WE_PAINT: {
 		int i; // airport enabling loop
-		int sel;
 		int rad = 4; // default catchment radious
 		uint32 avail_airports;
 		const AirportFTAClass *airport;
 
 		if (WP(w,def_d).close) return;
 
-		sel = _selected_airport_type;
 		avail_airports = GetValidAirports();
 
-		if (!HASBIT(avail_airports, 0) && sel == AT_SMALL) sel = AT_LARGE;
-		if (!HASBIT(avail_airports, 1) && sel == AT_LARGE) sel = AT_SMALL;
+		RaiseWindowWidget(w, _selected_airport_type + 7);
+		if (!HASBIT(avail_airports, 0) && _selected_airport_type == AT_SMALL) _selected_airport_type = AT_LARGE;
+		if (!HASBIT(avail_airports, 1) && _selected_airport_type == AT_LARGE) _selected_airport_type = AT_SMALL;
+		LowerWindowWidget(w, _selected_airport_type + 7);
 
 		/* 'Country Airport' starts at widget 7, and if its bit is set, it is
 		 * available, so take its opposite value to set the disabled state.
@@ -165,14 +171,12 @@
 		 */
 		for (i = 0; i < 9; i++) SetWindowWidgetDisabledState(w, i + 7, !HASBIT(avail_airports, i));
 
-		_selected_airport_type = sel;
 		// select default the coverage area to 'Off' (16)
-		w->click_state = ((1<<7) << sel) | ((1<<16) << _station_show_coverage);
-		airport = GetAirport(sel);
+		airport = GetAirport(_selected_airport_type);
 		SetTileSelectSize(airport->size_x, airport->size_y);
 
 		if (_patches.modified_catchment) {
-			switch (sel) {
+			switch (_selected_airport_type) {
 				case AT_OILRIG:        rad = CA_AIR_OILPAD;   break;
 				case AT_HELIPORT:      rad = CA_AIR_HELIPORT; break;
 				case AT_SMALL:         rad = CA_AIR_SMALL;    break;
@@ -198,12 +202,16 @@
 	case WE_CLICK: {
 		switch (e->we.click.widget) {
 		case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
+			RaiseWindowWidget(w, _selected_airport_type + 7);
 			_selected_airport_type = e->we.click.widget - 7;
+			LowerWindowWidget(w, _selected_airport_type + 7);
 			SndPlayFx(SND_15_BEEP);
 			SetWindowDirty(w);
 			break;
 		case 16: case 17:
 			_station_show_coverage = e->we.click.widget - 16;
+			SetWidgetLoweredState(w, 16, !_station_show_coverage);
+			SetWidgetLoweredState(w, 17, _station_show_coverage);
 			SndPlayFx(SND_15_BEEP);
 			SetWindowDirty(w);
 			break;
--- a/depot_gui.c
+++ b/depot_gui.c
@@ -692,7 +692,7 @@
 		} break;
 
 		case WE_ABORT_PLACE_OBJ: {
-			CLRBIT(w->click_state, DEPOT_WIDGET_CLONE);
+			RaiseWindowWidget(w, DEPOT_WIDGET_CLONE);
 			InvalidateWidget(w, DEPOT_WIDGET_CLONE);
 		} break;
 
@@ -701,7 +701,7 @@
 			const Vehicle *v = _place_clicked_vehicle;
 
 			/* since OTTD checks all open depot windows, we will make sure that it triggers the one with a clicked clone button */
-			if (v != NULL && HASBIT(w->click_state, DEPOT_WIDGET_CLONE)) {
+			if (v != NULL && IsWindowWidgetLowered(w, DEPOT_WIDGET_CLONE)) {
 				_place_clicked_vehicle = NULL;
 				HandleCloneVehClick(v, w);
 			}
--- a/dock_gui.c
+++ b/dock_gui.c
@@ -157,8 +157,7 @@
 		break;
 
 	case WE_ABORT_PLACE_OBJ:
-		UnclickWindowButtons(w);
-		SetWindowDirty(w);
+		RaiseWindowButtons(w);
 
 		w = FindWindowById(WC_BUILD_STATION, 0);
 		if (w != NULL) WP(w,def_d).close = true;
@@ -224,11 +223,12 @@
 static void BuildDockStationWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE: LowerWindowWidget(w, _station_show_coverage + 3); break;
+
 	case WE_PAINT: {
 		int rad;
 
 		if (WP(w,def_d).close) return;
-		w->click_state = (1<<3) << _station_show_coverage;
 		DrawWindowWidgets(w);
 
 		rad = (_patches.modified_catchment) ? CA_DOCK : 4;
@@ -243,7 +243,9 @@
 		switch (e->we.click.widget) {
 			case 3:
 			case 4:
+				RaiseWindowWidget(w, _station_show_coverage + 3);
 				_station_show_coverage = e->we.click.widget - 3;
+				LowerWindowWidget(w, _station_show_coverage + 3);
 				SndPlayFx(SND_15_BEEP);
 				SetWindowDirty(w);
 				break;
@@ -300,8 +302,9 @@
 static void BuildDocksDepotWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE: LowerWindowWidget(w, _ship_depot_direction + 3); break;
+
 	case WE_PAINT:
-		w->click_state = (1<<3) << _ship_depot_direction;
 		DrawWindowWidgets(w);
 
 		DrawShipDepotSprite(67, 35, 0);
@@ -314,7 +317,9 @@
 		switch (e->we.click.widget) {
 		case 3:
 		case 4:
+			RaiseWindowWidget(w, _ship_depot_direction + 3);
 			_ship_depot_direction = e->we.click.widget - 3;
+			LowerWindowWidget(w, _ship_depot_direction + 3);
 			SndPlayFx(SND_15_BEEP);
 			UpdateDocksDirection();
 			SetWindowDirty(w);
--- a/genworld_gui.c
+++ b/genworld_gui.c
@@ -208,6 +208,8 @@
 	uint y;
 
 	switch (e->event) {
+	case WE_CREATE: LowerWindowWidget(w, _opt_newgame.landscape + 3); break;
+
 	case WE_PAINT:
 		/* TODO -- Above and below you see some lines commented out with '//' in
 		 *  front of it. This is because currently the widget system can't handle
@@ -239,6 +241,7 @@
 		SetWindowWidgetDisabledState(w, 21, _patches_newgame.snow_line_height <= 2 || _opt_newgame.landscape != LT_HILLY);
 		SetWindowWidgetDisabledState(w, 23, _patches_newgame.snow_line_height >= 13 || _opt_newgame.landscape != LT_HILLY);
 
+		LowerWindowWidget(w, _opt_newgame.landscape + 3); // All buttons get automagically unclicked
 		DrawWindowWidgets(w);
 
 		y = (mode == GLWP_HEIGHTMAP) ? 22 : 0;
@@ -325,7 +328,9 @@
 		switch (e->we.click.widget) {
 		case 0: DeleteWindow(w); break;
 		case 3: case 4: case 5: case 6:
+			RaiseWindowWidget(w, _opt_newgame.landscape + 3);
 			SetNewLandscapeType(e->we.click.widget - 3);
+			LowerWindowWidget(w, _opt_newgame.landscape + 3);
 			break;
 		case 7: case 8: // Mapsize X
 			ShowDropDownMenu(w, mapsizes, _patches_newgame.map_x - 6, 8, 0, 0);
@@ -579,13 +584,15 @@
 	static const StringID mapsizes[] = {STR_64, STR_128, STR_256, STR_512, STR_1024, STR_2048, INVALID_STRING_ID};
 
 	switch (e->event) {
+	case WE_CREATE: LowerWindowWidget(w, _opt_newgame.landscape + 3); break;
+
 	case WE_PAINT:
 		SetWindowWidgetDisabledState(w, 14, _patches_newgame.starting_year <= MIN_YEAR);
 		SetWindowWidgetDisabledState(w, 16, _patches_newgame.starting_year >= MAX_YEAR);
 		SetWindowWidgetDisabledState(w, 17, _patches_newgame.se_flat_world_height <= 0);
 		SetWindowWidgetDisabledState(w, 19, _patches_newgame.se_flat_world_height >= 15);
 
-		w->click_state = (w->click_state & ~(0xF << 3)) | (1 << (_opt_newgame.landscape + 3));
+		LowerWindowWidget(w, _opt_newgame.landscape + 3); // All buttons get automagically unclicked
 		DrawWindowWidgets(w);
 
 		DrawString( 12,  96, STR_MAPSIZE, 0);
@@ -606,7 +613,9 @@
 		switch (e->we.click.widget) {
 		case 0: DeleteWindow(w); break;
 		case 3: case 4: case 5: case 6:
+			RaiseWindowWidget(w, _opt_newgame.landscape + 3);
 			SetNewLandscapeType(e->we.click.widget - 3);
+			LowerWindowWidget(w, _opt_newgame.landscape + 3);
 			break;
 		case 7: case 8: // Mapsize X
 			ShowDropDownMenu(w, mapsizes, _patches_newgame.map_x - 6, 8, 0, 0);
--- a/graph_gui.c
+++ b/graph_gui.c
@@ -223,11 +223,22 @@
 	const Player* p;
 
 	switch (e->event) {
+	case WE_CREATE: {
+		uint include_bits = ~_legend_excludebits;
+		int i;
+		for (i = 0; include_bits != 0; i++, include_bits >>= 1) {
+			if (HASBIT(include_bits, 0)) LowerWindowWidget(w, i + 3);
+		}
+		break;
+	}
+
 	case WE_PAINT:
 		FOR_ALL_PLAYERS(p) {
-			if (!p->is_active) SETBIT(_legend_excludebits, p->index);
+			if (!p->is_active) {
+				SETBIT(_legend_excludebits, p->index);
+				RaiseWindowWidget(w, p->index + 3);
+			}
 		}
-		w->click_state = (~_legend_excludebits) << 3;
 		DrawWindowWidgets(w);
 
 		FOR_ALL_PLAYERS(p) {
@@ -245,6 +256,7 @@
 	case WE_CLICK:
 		if (IS_INT_INSIDE(e->we.click.widget, 3, 11)) {
 			_legend_excludebits ^= (1 << (e->we.click.widget - 3));
+			ToggleWidgetLoweredState(w, e->we.click.widget);
 			SetWindowDirty(w);
 			InvalidateWindow(WC_INCOME_GRAPH, 0);
 			InvalidateWindow(WC_OPERATING_PROFIT, 0);
@@ -693,18 +705,26 @@
 static void CargoPaymentRatesWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE: {
+		uint to_select = ~_legend_cargobits;
+		int i;
+		for (i = 0; to_select != 0; i++, to_select >>= 1) {
+			if (HASBIT(to_select, 0)) LowerWindowWidget(w, i + 3);
+		}
+		break;
+	}
+
 	case WE_PAINT: {
 		int j, x, y;
 		CargoID i;
 		GraphDrawer gd;
 
-		gd.sel = _legend_cargobits;
-		w->click_state = (~_legend_cargobits) << 3;
 		DrawWindowWidgets(w);
 
 		x = 495;
 		y = 25;
 
+		gd.sel = _legend_cargobits;
 		gd.left = 2;
 		gd.top = 24;
 		gd.height = 104;
@@ -743,7 +763,8 @@
 		case 3: case 4: case 5: case 6:
 		case 7: case 8: case 9: case 10:
 		case 11: case 12: case 13: case 14:
-			_legend_cargobits ^= 1 << (e->we.click.widget - 3);
+			TOGGLEBIT(_legend_cargobits, e->we.click.widget - 3);
+			ToggleWidgetLoweredState(w, e->we.click.widget);
 			SetWindowDirty(w);
 			break;
 		}
@@ -881,10 +902,12 @@
 
 static void PerformanceRatingDetailWndProc(Window *w, WindowEvent *e)
 {
+	static PlayerID _performance_rating_detail_player = 0;
+
 	switch (e->event) {
 		case WE_PAINT: {
 			int i;
-			byte owner, x;
+			byte x;
 			uint16 y = 14;
 			int total_score = 0;
 			int color_done, color_notdone;
@@ -892,9 +915,6 @@
 			// Draw standard stuff
 			DrawWindowWidgets(w);
 
-			// The player of which we check the detail performance rating
-			owner = FindFirstBit(w->click_state) - 13;
-
 			// Paint the player icons
 			for (i = 0; i < MAX_PLAYERS; i++) {
 				if (!GetPlayer(i)->is_active) {
@@ -903,7 +923,11 @@
 						// Bah, player gone :(
 						DisableWindowWidget(w, i + 13);
 						// Is this player selected? If so, select first player (always save? :s)
-						if (w->click_state == 1U << (i + 13)) w->click_state = 1 << 13;
+						if (IsWindowWidgetLowered(w, i + 13)) {
+							RaiseWindowWidget(w, i + 13);
+							LowerWindowWidget(w, 13);
+							_performance_rating_detail_player = 0;
+						}
 						// We need a repaint
 						SetWindowDirty(w);
 					}
@@ -918,7 +942,7 @@
 					SetWindowDirty(w);
 				}
 
-				x = (i == owner) ? 1 : 0;
+				x = (i == _performance_rating_detail_player) ? 1 : 0;
 				DrawPlayerIcon(i, i * 37 + 13 + x, 16 + x);
 			}
 
@@ -928,7 +952,7 @@
 
 			// Draw all the score parts
 			for (i = 0; i < NUM_SCORE; i++) {
-				int val    = _score_part[owner][i];
+				int val    = _score_part[_performance_rating_detail_player][i];
 				int needed = _score_info[i].needed;
 				int score  = _score_info[i].score;
 
@@ -1001,7 +1025,9 @@
 			if (IS_INT_INSIDE(e->we.click.widget, 13, 21)) {
 				// Is it no on disable?
 				if (!IsWindowWidgetDisabled(w, e->we.click.widget)) {
-					w->click_state = 1 << e->we.click.widget;
+					RaiseWindowWidget(w, _performance_rating_detail_player + 13);
+					_performance_rating_detail_player = e->we.click.widget - 13;
+					LowerWindowWidget(w, _performance_rating_detail_player + 13);
 					SetWindowDirty(w);
 				}
 			}
@@ -1015,8 +1041,8 @@
 			for (i = 0; i < MAX_PLAYERS; i++) {
 				SetWindowWidgetDisabledState(w, i + 13, !GetPlayer(i)->is_active);
 			}
-			// Update all player stats with the current data
-			//  (this is because _score_info is not saved to a savegame)
+			/* Update all player stats with the current data
+			 * (this is because _score_info is not saved to a savegame) */
 			FOR_ALL_PLAYERS(p2) {
 				if (p2->is_active) UpdateCompanyRatingAndValue(p2, false);
 			}
@@ -1024,8 +1050,8 @@
 			w->custom[0] = DAY_TICKS;
 			w->custom[1] = 5;
 
-			w->click_state = 1 << 13;
-
+			_performance_rating_detail_player = 0;
+			LowerWindowWidget(w, _performance_rating_detail_player + 13);
 			SetWindowDirty(w);
 
 			break;
--- a/industry_gui.c
+++ b/industry_gui.c
@@ -50,8 +50,7 @@
 		break;
 
 	case WE_ABORT_PLACE_OBJ:
-		w->click_state = 0;
-		SetWindowDirty(w);
+		RaiseWindowButtons(w);
 		break;
 	}
 }
--- a/intro_gui.c
+++ b/intro_gui.c
@@ -47,8 +47,10 @@
 static void SelectGameWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE: LowerWindowWidget(w, _opt_newgame.landscape + 8); break;
+
 	case WE_PAINT:
-		w->click_state = (w->click_state & ~(0xF << 8)) | (1 << (_opt_newgame.landscape + 8));
+		LowerWindowWidget(w, _opt_newgame.landscape + 8); // All buttons get automagically unclicked
 		SetDParam(0, STR_6801_EASY + _opt_newgame.diff_level);
 		DrawWindowWidgets(w);
 		break;
@@ -72,6 +74,7 @@
 #endif
 			break;
 		case 8: case 9: case 10: case 11:
+			RaiseWindowWidget(w, _opt_newgame.landscape + 8);
 			SetNewLandscapeType(e->we.click.widget - 8);
 			break;
 		case 12: ShowGameOptions(); break;
--- a/main_gui.c
+++ b/main_gui.c
@@ -44,6 +44,7 @@
 
 static byte _terraform_size = 1;
 static RailType _last_built_railtype;
+static int _scengen_town_size = 1;
 
 extern void GenerateIndustries(void);
 extern bool GenerateTowns(void);
@@ -105,20 +106,18 @@
  */
 bool HandlePlacePushButton(Window *w, int widget, CursorID cursor, int mode, PlaceProc *placeproc)
 {
-	uint32 mask = 1 << widget;
-
 	if (IsWindowWidgetDisabled(w, widget)) return false;
 
 	SndPlayFx(SND_15_BEEP);
 	SetWindowDirty(w);
 
-	if (w->click_state & mask) {
+	if (IsWindowWidgetLowered(w, widget)) {
 		ResetObjectToPlace();
 		return false;
 	}
 
 	SetObjectToPlace(cursor, mode, w->window_class, w->window_number);
-	w->click_state |= mask;
+	LowerWindowWidget(w, widget);
 	_place_proc = placeproc;
 	return true;
 }
@@ -470,7 +469,7 @@
 
 	case WE_DESTROY: {
 			Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0);
-			v->click_state &= ~(1 << WP(w,menu_d).main_button);
+			RaiseWindowWidget(v, WP(w,menu_d).main_button);
 			SetWindowDirty(v);
 			return;
 		}
@@ -607,7 +606,7 @@
 
 	case WE_DESTROY: {
 		Window *v = FindWindowById(WC_MAIN_TOOLBAR, 0);
-		v->click_state &= ~(1 << WP(w,menu_d).main_button);
+		RaiseWindowWidget(v, WP(w,menu_d).main_button);
 		SetWindowDirty(v);
 		return;
 		}
@@ -664,8 +663,8 @@
 {
 	x += w->left;
 
-	SETBIT(w->click_state, (byte)main_button);
-	InvalidateWidget(w, (byte)main_button);
+	LowerWindowWidget(w, main_button);
+	InvalidateWidget(w, main_button);
 
 	DeleteWindowById(WC_TOOLBAR_MENU, 0);
 
@@ -692,7 +691,7 @@
 {
 	x += w->left;
 
-	SETBIT(w->click_state, main_button);
+	LowerWindowWidget(w, main_button);
 	InvalidateWidget(w, main_button);
 
 	DeleteWindowById(WC_TOOLBAR_MENU, 0);
@@ -1254,7 +1253,7 @@
 			} while (--n);
 		}
 
-		if (w->click_state & ( 1 << 5 | 1 << 6)) // change area-size if raise/lower corner is selected
+		if (IsWindowWidgetLowered(w, 5) || IsWindowWidgetLowered(w, 6)) // change area-size if raise/lower corner is selected
 			SetTileSelectSize(_terraform_size, _terraform_size);
 
 		break;
@@ -1294,9 +1293,17 @@
 		}
 		break;
 
-	case WE_TIMEOUT:
-		UnclickSomeWindowButtons(w, ~(1<<4 | 1<<5 | 1<<6 | 1<<7 | 1<<8 | 1<<9 | 1<<10 | 1<<11));
+	case WE_TIMEOUT: {
+		int i;
+		for (i = 0; w->widget[i].type != WWT_LAST; i++) {
+			if (IsWindowWidgetLowered(w, i)) {
+				RaiseWindowWidget(w, i);
+				InvalidateWidget(w, i);
+			}
+			if (i == 3) i = 11;
+		}
 		break;
+	}
 	case WE_PLACE_OBJ:
 		_place_proc(e->we.place.tile);
 		break;
@@ -1312,7 +1319,7 @@
 		break;
 
 	case WE_ABORT_PLACE_OBJ:
-		w->click_state = 0;
+		RaiseWindowButtons(w);
 		SetWindowDirty(w);
 		break;
 	}
@@ -1349,8 +1356,7 @@
 
 static void PlaceProc_Town(TileIndex tile)
 {
-	Window *w = FindWindowById(WC_SCEN_TOWN_GEN, 0);
-	DoCommandP(tile, 1 + FIND_FIRST_BIT(w->click_state >> 7), 0, CcBuildTown, CMD_BUILD_TOWN | CMD_MSG(STR_0236_CAN_T_BUILD_TOWN_HERE));
+	DoCommandP(tile, _scengen_town_size, 0, CcBuildTown, CMD_BUILD_TOWN | CMD_MSG(STR_0236_CAN_T_BUILD_TOWN_HERE));
 }
 
 
@@ -1377,7 +1383,7 @@
 		break;
 
 	case WE_CREATE:
-		w->click_state = 1 << 8; /* medium town size selected */
+		LowerWindowWidget(w, _scengen_town_size + 7);
 		break;
 
 	case WE_CLICK:
@@ -1390,7 +1396,7 @@
 
 			HandleButtonClick(w, 5);
 			_generating_world = true;
-			t = CreateRandomTown(20, 1 + FIND_FIRST_BIT(w->click_state >> 7));
+			t = CreateRandomTown(20, _scengen_town_size);
 			_generating_world = false;
 
 			if (t == NULL) {
@@ -1411,20 +1417,25 @@
 		}
 
 		case 7: case 8: case 9:
-			w->click_state = 1 << e->we.click.widget;
+			RaiseWindowWidget(w, _scengen_town_size + 7);
+			_scengen_town_size = e->we.click.widget - 7;
+			LowerWindowWidget(w, _scengen_town_size + 7);
 			SetWindowDirty(w);
 			break;
 		}
 		break;
 
 	case WE_TIMEOUT:
-		UnclickSomeWindowButtons(w, 1<<5 | 1<<6);
+		RaiseWindowWidget(w, 5);
+		RaiseWindowWidget(w, 6);
+		SetWindowDirty(w);
 		break;
 	case WE_PLACE_OBJ:
 		_place_proc(e->we.place.tile);
 		break;
 	case WE_ABORT_PLACE_OBJ:
-		w->click_state &= (1 << 7 | 1 << 8 | 1 << 9);
+		RaiseWindowButtons(w);
+		LowerWindowWidget(w, _scengen_town_size + 7);
 		SetWindowDirty(w);
 		break;
 	}
@@ -1633,11 +1644,11 @@
 		break;
 	}
 	case WE_ABORT_PLACE_OBJ:
-		w->click_state = 0;
+		RaiseWindowButtons(w);
 		SetWindowDirty(w);
 		break;
 	case WE_TIMEOUT:
-		UnclickSomeWindowButtons(w, 1<<3);
+		RaiseWindowWidget(w, 3);
 		break;
 	}
 }
@@ -1820,28 +1831,35 @@
 	} break;
 
 	case WE_ABORT_PLACE_OBJ: {
-		w->click_state &= ~(1<<25);
+		RaiseWindowWidget(w, 25);
 		SetWindowDirty(w);
 	} break;
 
 	case WE_ON_EDIT_TEXT: HandleOnEditText(e); break;
 
 	case WE_MOUSELOOP:
-		if (((w->click_state) & 1) != (uint)!!_pause) {
-			w->click_state ^= (1 << 0);
+		if (IsWindowWidgetLowered(w, 0) != _pause) {
+			ToggleWidgetLoweredState(w, 0);
 			SetWindowDirty(w);
 		}
 
-		if (((w->click_state >> 1) & 1) != (uint)!!_fast_forward) {
-			w->click_state ^= (1 << 1);
+		if (IsWindowWidgetLowered(w, 1) != _fast_forward) {
+			ToggleWidgetLoweredState(w, 1);
 			SetWindowDirty(w);
 		}
 		break;
 
-	case WE_TIMEOUT:
-		UnclickSomeWindowButtons(w, ~(1<<0 | 1<<1));
+	case WE_TIMEOUT: {
+		int i;
+		for (i = 2; w->widget[i].type != WWT_LAST; i++) {
+			if (IsWindowWidgetLowered(w, i)) {
+				RaiseWindowWidget(w, i);
+				InvalidateWidget(w, i);
+			}
+		}
 		break;
 	}
+	}
 }
 
 static const Widget _toolb_normal_widgets[] = {
@@ -2008,20 +2026,20 @@
 	} break;
 
 	case WE_ABORT_PLACE_OBJ: {
-		w->click_state &= ~(1<<25);
+		RaiseWindowWidget(w, 25);
 		SetWindowDirty(w);
 	} break;
 
 	case WE_ON_EDIT_TEXT: HandleOnEditText(e); break;
 
 	case WE_MOUSELOOP:
-		if (((w->click_state) & 1) != (uint)!!_pause) {
-			w->click_state ^= (1 << 0);
+		if (IsWindowWidgetLowered(w, 0) != _pause) {
+			ToggleWidgetLoweredState(w, 0);
 			SetWindowDirty(w);
 		}
 
-		if (((w->click_state >> 1) & 1) != (uint)!!_fast_forward) {
-			w->click_state ^= (1 << 1);
+		if (IsWindowWidgetLowered(w, 1) != _fast_forward) {
+			ToggleWidgetLoweredState(w, 1);
 			SetWindowDirty(w);
 		}
 		break;
--- a/misc_gui.c
+++ b/misc_gui.c
@@ -355,7 +355,7 @@
 			break;
 
 		case 16: /* place trees randomly over the landscape*/
-			w->click_state |= 1 << 16;
+			LowerWindowWidget(w, 16);
 			w->flags4 |= 5 << WF_TIMEOUT_SHL;
 			SndPlayFx(SND_15_BEEP);
 			PlaceTreesRandomly();
@@ -381,12 +381,11 @@
 		break;
 
 	case WE_TIMEOUT:
-		UnclickSomeWindowButtons(w, 1<<16);
+		RaiseWindowWidget(w, 16);
 		break;
 
 	case WE_ABORT_PLACE_OBJ:
-		w->click_state = 0;
-		SetWindowDirty(w);
+		RaiseWindowButtons(w);
 		break;
 	}
 }
@@ -734,25 +733,6 @@
 	}
 }
 
-
-void UnclickSomeWindowButtons(Window *w, uint32 mask)
-{
-	uint32 x = w->click_state & mask;
-	uint i = 0;
-
-	w->click_state ^= x;
-	do {
-		if (x & 1) InvalidateWidget(w, i);
-	} while (i++, x >>= 1);
-}
-
-
-void UnclickWindowButtons(Window *w)
-{
-	UnclickSomeWindowButtons(w, (uint32)-1);
-}
-
-
 void SetVScrollCount(Window *w, int num)
 {
 	w->vscroll.count = num;
@@ -1086,7 +1066,7 @@
 		WP(w, querystr_d).orig = _orig_str_buf;
 	}
 
-	w->click_state = 1 << 5;
+	LowerWindowWidget(w, 5);
 	WP(w, querystr_d).caption = caption;
 	WP(w, querystr_d).wnd_class = window_class;
 	WP(w, querystr_d).wnd_num = window_number;
@@ -1154,7 +1134,7 @@
 
 	w = AllocateWindowDesc(&_query_desc);
 
-	w->click_state = 1 << 5;
+	LowerWindowWidget(w, 5);
 	WP(w, query_d).caption            = caption;
 	WP(w, query_d).message            = message;
 	WP(w, query_d).wnd_class          = window_class;
@@ -1460,7 +1440,7 @@
 		}
 		break;
 	case WE_TIMEOUT:
-		if (HASBIT(w->click_state, 11)) { /* Delete button clicked */
+		if (IsWindowWidgetLowered(w, 11)) { /* Delete button clicked */
 			if (!FiosDelete(OTTD2FS(WP(w,querystr_d).text.buf))) {
 				ShowErrorMessage(INVALID_STRING_ID, STR_4008_UNABLE_TO_DELETE_FILE, 0, 0);
 			} else {
@@ -1471,7 +1451,7 @@
 
 			UpdateTextBufferSize(&WP(w, querystr_d).text);
 			SetWindowDirty(w);
-		} else if (HASBIT(w->click_state, 12)) { /* Save button clicked */
+		} else if (IsWindowWidgetLowered(w, 12)) { /* Save button clicked */
 			_switch_mode = SM_SAVE;
 			FiosMakeSavegameName(_file_to_saveload.name, WP(w,querystr_d).text.buf, sizeof(_file_to_saveload.name));
 
@@ -1575,7 +1555,7 @@
 	w->resize.step_width = 2;
 	w->resize.step_height = 10;
 	w->resize.height = w->height - 14 * 10; // Minimum of 10 items
-	SETBIT(w->click_state, 7);
+	LowerWindowWidget(w, 7);
 	WP(w,querystr_d).text.caret = false;
 	WP(w,querystr_d).text.maxlength = lengthof(_edit_str_buf);
 	WP(w,querystr_d).text.maxwidth = 240;
--- a/music_gui.c
+++ b/music_gui.c
@@ -200,7 +200,8 @@
 		int y;
 
 		SetWindowWidgetDisabledState(w, 11, msf.playlist <= 3);
-		w->click_state |= 0x18;
+		LowerWindowWidget(w, 3);
+		LowerWindowWidget(w, 4);
 		DrawWindowWidgets(w);
 
 		GfxFillRect(3, 23, 3+177,23+191,0);
@@ -341,7 +342,8 @@
 		uint i;
 		StringID str;
 
-		w->click_state |= 0x280;
+		RaiseWindowWidget(w, 7);
+		RaiseWindowWidget(w, 9);
 		DrawWindowWidgets(w);
 
 		GfxFillRect(187, 16, 200, 33, 0);
--- a/network_gui.c
+++ b/network_gui.c
@@ -1710,7 +1710,7 @@
 
 	w = AllocateWindowDesc(&_chat_window_desc);
 
-	w->click_state = 1 << 1;
+	LowerWindowWidget(w, 1);
 	WP(w,querystr_d).caption = STR_NULL;
 	WP(w,querystr_d).wnd_class = WC_MAIN_TOOLBAR;
 	WP(w,querystr_d).wnd_num = 0;
--- a/news_gui.c
+++ b/news_gui.c
@@ -711,7 +711,7 @@
 		int click_state = WP(w, def_d).data_1;
 		int i, y;
 
-		if (_news_ticker_sound) SETBIT(w->click_state, 25);
+		if (_news_ticker_sound) LowerWindowWidget(w, 25);
 		DrawWindowWidgets(w);
 
 		/* XXX - Draw the fake widgets-buttons. Can't add these to the widget-desc since
@@ -750,7 +750,7 @@
 			break;
 		case 25: /* Change ticker sound on/off */
 			_news_ticker_sound ^= 1;
-			TOGGLEBIT(w->click_state, e->we.click.widget);
+			ToggleWidgetLoweredState(w, e->we.click.widget);
 			InvalidateWidget(w, e->we.click.widget);
 			break;
 		default: { /* Clicked on the [<] .. [>] widgets */
--- a/order_gui.c
+++ b/order_gui.c
@@ -349,8 +349,8 @@
 static void OrderClick_Goto(Window *w, const Vehicle *v)
 {
 	InvalidateWidget(w, 7);
-	TOGGLEBIT(w->click_state, 7);
-	if (HASBIT(w->click_state, 7)) {
+	ToggleWidgetLoweredState(w, 7);
+	if (IsWindowWidgetLowered(w, 7)) {
 		_place_clicked_vehicle = NULL;
 		SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, 1, w);
 	} else {
@@ -532,7 +532,7 @@
 	} break;
 
 	case WE_ABORT_PLACE_OBJ: {
-		CLRBIT(w->click_state, 7);
+		RaiseWindowWidget(w, 7);
 		InvalidateWidget(w, 7);
 	} break;
 
@@ -547,7 +547,7 @@
 		 * the order is copied to the last open window instead of the
 		 * one where GOTO is enalbed
 		 */
-		if (v != NULL && HASBIT(w->click_state, 7)) {
+		if (v != NULL && IsWindowWidgetLowered(w, 7)) {
 			_place_clicked_vehicle = NULL;
 			HandleOrderVehClick(GetVehicle(w->window_number), v, w);
 		}
--- a/player_gui.c
+++ b/player_gui.c
@@ -317,6 +317,8 @@
 static void SelectPlayerLiveryWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+		case WE_CREATE: LowerWindowWidget(w, WP(w, livery_d).livery_class + 2); break;
+
 		case WE_PAINT: {
 			const Player *p = GetPlayer(w->window_number);
 			LiveryScheme scheme = LS_DEFAULT;
@@ -372,8 +374,10 @@
 				case 6: {
 					LiveryScheme scheme;
 
+					RaiseWindowWidget(w, WP(w, livery_d).livery_class + 2);
 					WP(w, livery_d).livery_class = e->we.click.widget - 2;
 					WP(w, livery_d).sel = 0;
+					LowerWindowWidget(w, WP(w, livery_d).livery_class + 2);
 
 					/* Select the first item in the list */
 					for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
@@ -382,7 +386,6 @@
 							break;
 						}
 					}
-					w->click_state = 1 << e->we.click.widget;
 					w->height = 49 + livery_height[WP(w, livery_d).livery_class] * 14;
 					w->widget[13].bottom = w->height - 1;
 					w->widget[13].data = livery_height[WP(w, livery_d).livery_class] << 8 | 1;
@@ -469,9 +472,10 @@
 static void SelectPlayerFaceWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE: LowerWindowWidget(w, WP(w, facesel_d).gender + 5); break;
+
 	case WE_PAINT: {
 		Player *p;
-		w->click_state = (w->click_state & ~(1<<5|1<<6)) | ((1<<5) << WP(w,facesel_d).gender);
 		DrawWindowWidgets(w);
 		p = GetPlayer(w->window_number);
 		DrawPlayerFace(WP(w,facesel_d).face, p->player_color, 2, 16);
@@ -486,7 +490,9 @@
 			break;
 		case 5: /* male click */
 		case 6: /* female click */
-			WP(w,facesel_d).gender = e->we.click.widget - 5;
+			RaiseWindowWidget(w, WP(w, facesel_d).gender + 5);
+			WP(w, facesel_d).gender = e->we.click.widget - 5;
+			LowerWindowWidget(w, WP(w, facesel_d).gender + 5);
 			SetWindowDirty(w);
 			break;
 		case 7:
@@ -721,7 +727,7 @@
 				wf->caption_color = wf->window_number;
 				WP(wf,livery_d).livery_class = LC_OTHER;
 				WP(wf,livery_d).sel = 1;
-				wf->click_state = 1 << 2;
+				LowerWindowWidget(wf, 2);
 			}
 		} break;
 
--- a/rail_gui.c
+++ b/rail_gui.c
@@ -296,17 +296,13 @@
 	SetWindowDirty(w);
 	SndPlayFx(SND_15_BEEP);
 
-	TOGGLEBIT(w->click_state, 16);
-	_remove_button_clicked = HASBIT(w->click_state, 16);
-	SetSelectionRed(HASBIT(w->click_state, 16));
+	ToggleWidgetLoweredState(w, 16);
+	_remove_button_clicked = IsWindowWidgetLowered(w, 16);
+	SetSelectionRed(_remove_button_clicked);
 
 	// handle station builder
-	if (HASBIT(w->click_state, 16)) {
-		if (_remove_button_clicked) {
-			SetTileSelectSize(1, 1);
-		} else {
-			BringWindowToFrontById(WC_BUILD_STATION, 0);
-		}
+	if (_remove_button_clicked) {
+		SetTileSelectSize(1, 1);
 	}
 }
 
@@ -409,7 +405,7 @@
 {
 	switch (clicked_widget) {
 		case 4: case 5: case 6: case 7: case 8: case 11: case 12: case 13: EnableWindowWidget(w, 16); break;
-		default: DisableWindowWidget(w, 16); w->click_state &= ~(1 << 16); break;
+		default: DisableWindowWidget(w, 16); LowerWindowWidget(w, 16); break;
 	}
 }
 
@@ -479,8 +475,7 @@
 		break;
 
 	case WE_ABORT_PLACE_OBJ:
-		UnclickWindowButtons(w);
-		SetWindowDirty(w);
+		RaiseWindowButtons(w);
 
 		w = FindWindowById(WC_BUILD_STATION, 0);
 		if (w != NULL) WP(w,def_d).close = true;
@@ -618,6 +613,18 @@
 static void StationBuildWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE:
+		LowerWindowWidget(w, _railstation.orientation + 3);
+		if (_railstation.dragdrop) {
+			LowerWindowWidget(w, 19);
+		} else {
+			LowerWindowWidget(w, _railstation.numtracks + 4);
+			LowerWindowWidget(w, _railstation.platlength + 11);
+		}
+		SetWidgetLoweredState(w, 20, !_station_show_coverage);
+		SetWidgetLoweredState(w, 21, _station_show_coverage);
+		break;
+
 	case WE_PAINT: {
 		int rad;
 		uint bits;
@@ -627,16 +634,6 @@
 
 		if (WP(w,def_d).close) return;
 
-		bits = (1<<3) << ( _railstation.orientation);
-		if (_railstation.dragdrop) {
-			bits |= (1<<19);
-		} else {
-			bits |= (1<<(5-1)) << (_railstation.numtracks);
-			bits |= (1<<(12-1)) << (_railstation.platlength);
-		}
-		bits |= (1<<20) << (_station_show_coverage);
-		w->click_state = bits;
-
 		if (_railstation.dragdrop) {
 			SetTileSelectSize(1, 1);
 		} else {
@@ -727,7 +724,9 @@
 		switch (e->we.click.widget) {
 		case 3:
 		case 4:
+			RaiseWindowWidget(w, _railstation.orientation + 3);
 			_railstation.orientation = e->we.click.widget - 3;
+			LowerWindowWidget(w, _railstation.orientation + 3);
 			SndPlayFx(SND_15_BEEP);
 			SetWindowDirty(w);
 			break;
@@ -739,8 +738,12 @@
 		case 9:
 		case 10:
 		case 11:
+			RaiseWindowWidget(w, _railstation.numtracks + 4);
+			RaiseWindowWidget(w, 19);
 			_railstation.numtracks = (e->we.click.widget - 5) + 1;
 			_railstation.dragdrop = false;
+			LowerWindowWidget(w, _railstation.platlength + 11);
+			LowerWindowWidget(w, _railstation.numtracks + 4);
 			SndPlayFx(SND_15_BEEP);
 			SetWindowDirty(w);
 			break;
@@ -752,14 +755,21 @@
 		case 16:
 		case 17:
 		case 18:
+			RaiseWindowWidget(w, _railstation.platlength + 11);
+			RaiseWindowWidget(w, 19);
 			_railstation.platlength = (e->we.click.widget - 12) + 1;
 			_railstation.dragdrop = false;
+			LowerWindowWidget(w, _railstation.platlength + 11);
+			LowerWindowWidget(w, _railstation.numtracks + 4);
 			SndPlayFx(SND_15_BEEP);
 			SetWindowDirty(w);
 			break;
 
 		case 19:
 			_railstation.dragdrop ^= true;
+			ToggleWidgetLoweredState(w, 19);
+			SetWidgetLoweredState(w, _railstation.numtracks + 4, !_railstation.dragdrop);
+			SetWidgetLoweredState(w, _railstation.platlength + 11, !_railstation.dragdrop);
 			SndPlayFx(SND_15_BEEP);
 			SetWindowDirty(w);
 			break;
@@ -767,6 +777,8 @@
 		case 20:
 		case 21:
 			_station_show_coverage = e->we.click.widget - 20;
+			SetWidgetLoweredState(w, 20, !_station_show_coverage);
+			SetWidgetLoweredState(w, 21, _station_show_coverage);
 			SndPlayFx(SND_15_BEEP);
 			SetWindowDirty(w);
 			break;
@@ -926,10 +938,11 @@
 static void BuildTrainDepotWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE: LowerWindowWidget(w, _build_depot_direction + 3); break;
+
 	case WE_PAINT: {
 		RailType r;
 
-		w->click_state = (1 << 3) << _build_depot_direction;
 		DrawWindowWidgets(w);
 
 		r = _cur_railtype;
@@ -946,7 +959,9 @@
 			case 4:
 			case 5:
 			case 6:
+				RaiseWindowWidget(w, _build_depot_direction + 3);
 				_build_depot_direction = e->we.click.widget - 3;
+				LowerWindowWidget(w, _build_depot_direction + 3);
 				SndPlayFx(SND_15_BEEP);
 				SetWindowDirty(w);
 				break;
@@ -991,10 +1006,11 @@
 static void BuildWaypointWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE: LowerWindowWidget(w, _cur_waypoint_type - w->hscroll.pos); break;
+
 	case WE_PAINT: {
 		uint i;
 
-		w->click_state = (1 << 3) << (_cur_waypoint_type - w->hscroll.pos);
 		DrawWindowWidgets(w);
 
 		for (i = 0; i < 5; i++) {
@@ -1023,7 +1039,9 @@
 					HASBIT(statspec->callbackmask, CBM_STATION_AVAIL) &&
 					GetStationCallback(CBID_STATION_AVAILABILITY, 0, 0, statspec, NULL, INVALID_TILE) == 0) return;
 
+			RaiseWindowWidget(w, _cur_waypoint_type - w->hscroll.pos);
 			_cur_waypoint_type = type;
+			LowerWindowWidget(w, _cur_waypoint_type - w->hscroll.pos);
 			SndPlayFx(SND_15_BEEP);
 			SetWindowDirty(w);
 			break;
--- a/road_gui.c
+++ b/road_gui.c
@@ -158,8 +158,8 @@
 	if (IsWindowWidgetDisabled(w, 11)) return;
 	SetWindowDirty(w);
 	SndPlayFx(SND_15_BEEP);
-	TOGGLEBIT(w->click_state, 11);
-	SetSelectionRed(HASBIT(w->click_state, 11));
+	ToggleWidgetLoweredState(w, 11);
+	SetSelectionRed(IsWindowWidgetLowered(w, 11));
 }
 
 static void BuildRoadClick_Landscaping(Window *w)
@@ -184,11 +184,11 @@
 {
 	switch (e->event) {
 	case WE_PAINT:
-		if (!(w->click_state & ((1<<3)|(1<<4)))) {
+		if (IsWindowWidgetLowered(w, 3) || IsWindowWidgetLowered(w, 4)) {
+			EnableWindowWidget(w, 11);
+		} else {
 			DisableWindowWidget(w, 11);
-			w->click_state &= ~(1<<11);
-		} else {
-			EnableWindowWidget(w, 11);
+			RaiseWindowWidget(w, 11);
 		}
 		DrawWindowWidgets(w);
 		break;
@@ -216,13 +216,12 @@
 		break;
 
 	case WE_PLACE_OBJ:
-		_remove_button_clicked = (w->click_state & (1 << 11)) != 0;
+		_remove_button_clicked = IsWindowWidgetLowered(w, 11);
 		_place_proc(e->we.place.tile);
 		break;
 
 	case WE_ABORT_PLACE_OBJ:
-		UnclickWindowButtons(w);
-		SetWindowDirty(w);
+		RaiseWindowButtons(w);
 
 		w = FindWindowById(WC_BUS_STATION, 0);
 		if (w != NULL) WP(w,def_d).close = true;
@@ -359,8 +358,9 @@
 static void BuildRoadDepotWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE: LowerWindowWidget(w, _road_depot_orientation + 3); break;
+
 	case WE_PAINT:
-		w->click_state = (1<<3) << _road_depot_orientation;
 		DrawWindowWidgets(w);
 
 		DrawRoadDepotSprite(70, 17, DIAGDIR_NE);
@@ -372,7 +372,9 @@
 	case WE_CLICK: {
 		switch (e->we.click.widget) {
 		case 3: case 4: case 5: case 6:
+			RaiseWindowWidget(w, _road_depot_orientation + 3);
 			_road_depot_orientation = e->we.click.widget - 3;
+			LowerWindowWidget(w, _road_depot_orientation + 3);
 			SndPlayFx(SND_15_BEEP);
 			SetWindowDirty(w);
 			break;
@@ -416,13 +418,16 @@
 static void RoadStationPickerWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE:
+		LowerWindowWidget(w, _road_station_picker_orientation + 3);
+		LowerWindowWidget(w, _station_show_coverage + 7);
+		break;
+
 	case WE_PAINT: {
 		int image;
 
 		if (WP(w,def_d).close) return;
 
-		w->click_state = ((1<<3) << _road_station_picker_orientation) |
-										 ((1<<7) << _station_show_coverage);
 		DrawWindowWidgets(w);
 
 		if (_station_show_coverage) {
@@ -448,12 +453,16 @@
 	case WE_CLICK: {
 		switch (e->we.click.widget) {
 		case 3: case 4: case 5: case 6:
+			RaiseWindowWidget(w, _road_station_picker_orientation + 3);
 			_road_station_picker_orientation = e->we.click.widget - 3;
+			LowerWindowWidget(w, _road_station_picker_orientation + 3);
 			SndPlayFx(SND_15_BEEP);
 			SetWindowDirty(w);
 			break;
 		case 7: case 8:
+			RaiseWindowWidget(w, _station_show_coverage + 7);
 			_station_show_coverage = e->we.click.widget - 7;
+			LowerWindowWidget(w, _station_show_coverage + 7);
 			SndPlayFx(SND_15_BEEP);
 			SetWindowDirty(w);
 			break;
--- a/settings_gui.c
+++ b/settings_gui.c
@@ -108,7 +108,7 @@
 		i = GetCurRes();
 		SetDParam(7, i == _num_resolutions ? STR_RES_OTHER : SPECSTR_RESOLUTION_START + i);
 		SetDParam(8, SPECSTR_SCREENSHOT_START + _cur_screenshot_format);
-		(_fullscreen) ? SETBIT(w->click_state, 28) : CLRBIT(w->click_state, 28); // fullscreen button
+		SetWidgetLoweredState(w, 28, _fullscreen);
 
 		DrawWindowWidgets(w);
 		DrawString(20, 175, STR_OPTIONS_FULLSCREEN, 0); // fullscreen
@@ -152,7 +152,7 @@
 			ShowDropDownMenu(w, BuildDynamicDropdown(SPECSTR_RESOLUTION_START, _num_resolutions), GetCurRes(), 27, 0, 0);
 			return;
 		case 28: /* Click fullscreen on/off */
-			(_fullscreen) ? CLRBIT(w->click_state, 28) : SETBIT(w->click_state, 28);
+			SetWidgetLoweredState(w, 28, !_fullscreen);
 			ToggleFullScreen(!_fullscreen); // toggle full-screen on/off
 			SetWindowDirty(w);
 			return;
@@ -398,7 +398,6 @@
 		int i;
 		int y, value;
 
-		w->click_state = (1 << 3) << _opt_mod_temp.diff_level; // have current difficulty button clicked
 		DrawWindowWidgets(w);
 
 		click_a = _difficulty_click_a;
@@ -484,7 +483,9 @@
 		}	break;
 		case 3: case 4: case 5: case 6: /* Easy / Medium / Hard / Custom */
 			// temporarily change difficulty level
+			RaiseWindowWidget(w, _opt_mod_temp.diff_level + 3);
 			SetDifficultyLevel(e->we.click.widget - 3, &_opt_mod_temp);
+			LowerWindowWidget(w, _opt_mod_temp.diff_level + 3);
 			SetWindowDirty(w);
 			break;
 		case 7: /* Highscore Table */
@@ -700,6 +701,7 @@
 			}
 			first_time = false;
 		}
+		LowerWindowWidget(w, 4);
 	} break;
 
 	case WE_PAINT: {
@@ -708,7 +710,6 @@
 		uint i;
 
 		/* Set up selected category */
-		w->click_state = 1 << (WP(w, def_d).data_1 + 4);
 		DrawWindowWidgets(w);
 
 		x = 5;
@@ -848,7 +849,9 @@
 			break;
 		}
 		case 4: case 5: case 6: case 7: case 8: case 9:
-			WP(w,def_d).data_1 = e->we.click.widget - 4;
+			RaiseWindowWidget(w, WP(w, def_d).data_1 + 4);
+			WP(w, def_d).data_1 = e->we.click.widget - 4;
+			LowerWindowWidget(w, WP(w, def_d).data_1 + 4);
 			DeleteWindowById(WC_QUERY_STRING, 0);
 			SetWindowDirty(w);
 			break;
--- a/smallmap_gui.c
+++ b/smallmap_gui.c
@@ -865,9 +865,9 @@
 				case 8:  // Show transport routes
 				case 9:  // Show vegetation
 				case 10: // Show land owners
-					w->click_state &= ~( 1 << 5 |  1 << 6 | 1 << 7 | 1 << 8 | 1 << 9 | 1 << 10);
-					w->click_state |= 1 << e->we.click.widget;
+					RaiseWindowWidget(w, _smallmap_type + 5);
 					_smallmap_type = e->we.click.widget - 5;
+					LowerWindowWidget(w, _smallmap_type + 5);
 
 					SetWindowDirty(w);
 					SndPlayFx(SND_15_BEEP);
@@ -881,8 +881,8 @@
 					break;
 
 				case 12: // Toggle town names
-					w->click_state ^= (1 << 12);
-					_smallmap_show_towns = (w->click_state >> 12) & 1;
+					ToggleWidgetLoweredState(w, 12);
+					_smallmap_show_towns = IsWindowWidgetLowered(w, 12);
 
 					SetWindowDirty(w);
 					SndPlayFx(SND_15_BEEP);
@@ -982,7 +982,8 @@
 	w = AllocateWindowDescFront(&_smallmap_desc, 0);
 	if (w == NULL) return;
 
-	w->click_state = ((1 << 5) << _smallmap_type) | (_smallmap_show_towns << 12);
+	LowerWindowWidget(w, _smallmap_type + 5);
+	SetWidgetLoweredState(w, 12, _smallmap_show_towns);
 	w->resize.width = 350;
 	w->resize.height = 250;
 
--- a/station_gui.c
+++ b/station_gui.c
@@ -247,13 +247,6 @@
 
 	switch (e->event) {
 	case WE_PAINT: {
-		/* Set up cargo click-states. Toggle the all-vehicle and all-cargo types button
-		 * depending on if all types are clicked or not */
-		SB(w->click_state, 6, 5, facilities);
-		SB(w->click_state, 26, 1, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK));
-		SB(w->click_state, 12, NUM_CARGO + 1, cargo_filter);
-		SB(w->click_state, 27, 1, cargo_filter == 0x1FFF);
-
 		BuildStationsList(sl, owner, facilities, cargo_filter);
 		SortStationsList(sl);
 
@@ -353,23 +346,43 @@
 		case 10: /* dock */
 			if (_ctrl_pressed) {
 				TOGGLEBIT(facilities, e->we.click.widget - 6);
+				ToggleWidgetLoweredState(w, e->we.click.widget);
 			} else {
-				facilities = 0;
+				int i;
+				for (i = 0; facilities != 0; i++, facilities >>= 1) {
+					if (HASBIT(facilities, 0)) RaiseWindowWidget(w, i + 6);
+				}
 				SETBIT(facilities, e->we.click.widget - 6);
+				LowerWindowWidget(w, e->we.click.widget);
 			}
+			SetWidgetLoweredState(w, 26, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK));
 			sl->flags |= SL_REBUILD;
 			SetWindowDirty(w);
 		break;
-		case 26:
+		case 26: {
+			int i;
+			for (i = 0; i < 5; i++) {
+				LowerWindowWidget(w, i + 6);
+			}
+			LowerWindowWidget(w, 26);
+
 			facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK;
 			sl->flags |= SL_REBUILD;
 			SetWindowDirty(w);
 			break;
-		case 27:
+		}
+		case 27: {
+			int i;
+			for (i = 0; i < NUM_CARGO; i++) {
+				LowerWindowWidget(w, i + 12);
+			}
+			LowerWindowWidget(w, 27);
+
 			cargo_filter = 0x1FFF; /* select everything */
 			sl->flags |= SL_REBUILD;
 			SetWindowDirty(w);
 			break;
+		}
 		case 28: /*flip sorting method asc/desc*/
 			TOGGLEBIT(sl->flags, 0); //DESC-flag
 			sl->flags |= SL_RESORT;
@@ -382,11 +395,17 @@
 			if (e->we.click.widget >= 12 && e->we.click.widget <= 24) { //change cargo_filter
 				if (_ctrl_pressed) {
 					TOGGLEBIT(cargo_filter, e->we.click.widget - 12);
+					ToggleWidgetLoweredState(w, e->we.click.widget);
 				} else {
-					cargo_filter = 0;
+					int i;
+					for (i = 0; cargo_filter != 0; i++, cargo_filter >>= 1) {
+						if (HASBIT(cargo_filter, 0)) RaiseWindowWidget(w, i + 12);
+					}
 					SETBIT(cargo_filter, e->we.click.widget - 12);
+					LowerWindowWidget(w, e->we.click.widget);
 				}
 				sl->flags |= SL_REBUILD;
+				SetWidgetLoweredState(w, 27, cargo_filter == 0x1FFF);
 				SetWindowDirty(w);
 			}
 		}
@@ -409,12 +428,22 @@
 		}
 		break;
 
-	case WE_CREATE: /* set up resort timer */
+	case WE_CREATE: { /* set up resort timer */
+		int i;
+		for (i = 0; i < 5; i++) {
+			if (HASBIT(facilities, i)) LowerWindowWidget(w, i + 6);
+		}
+		for (i = 0; i < NUM_CARGO; i++) {
+			if (HASBIT(cargo_filter, i)) LowerWindowWidget(w, i + 12);
+		}
+		SetWidgetLoweredState(w, 26, facilities == (FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK));
+		SetWidgetLoweredState(w, 27, cargo_filter == 0x1FFF);
 		sl->sort_list = NULL;
 		sl->flags = SL_REBUILD;
 		sl->sort_type = 0;
 		sl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS;
 		break;
+	}
 
 	case WE_RESIZE:
 		w->vscroll.cap += e->we.sizing.diff.y / 10;
--- a/terraform_gui.c
+++ b/terraform_gui.c
@@ -242,8 +242,7 @@
 		break;
 
 	case WE_ABORT_PLACE_OBJ:
-		UnclickWindowButtons(w);
-		SetWindowDirty(w);
+		RaiseWindowButtons(w);
 		break;
 	}
 }
--- a/widget.c
+++ b/widget.c
@@ -188,6 +188,7 @@
 	const DrawPixelInfo* dpi = _cur_dpi;
 	Rect r;
 	uint32 cur_click, cur_disabled, cur_hidden;
+	int i = 0;
 
 	wi = w->widget;
 
@@ -196,7 +197,7 @@
 	cur_hidden = w->hidden_state;
 
 	do {
-		bool clicked = (cur_click & 1);
+		bool clicked = IsWindowWidgetLowered((Window*)w, i);
 
 		if (dpi->left > (r.right=/*w->left + */wi->right) ||
 				dpi->left + dpi->width <= (r.left=wi->left/* + w->left*/) ||
@@ -464,7 +465,7 @@
 			}
 		}
 		}
-	} while (cur_click>>=1, cur_disabled>>=1, cur_hidden >>= 1, (++wi)->type != WWT_LAST);
+	} while (i++, cur_click>>=1, cur_disabled>>=1, cur_hidden >>= 1, (++wi)->type != WWT_LAST);
 
 
 	if (w->flags4 & WF_WHITE_BORDER_MASK) {
@@ -588,7 +589,7 @@
 		case WE_DESTROY: {
 			Window *w2 = FindWindowById(WP(w,dropdown_d).parent_wnd_class, WP(w,dropdown_d).parent_wnd_num);
 			if (w2 != NULL) {
-				CLRBIT(w2->click_state, WP(w,dropdown_d).parent_button);
+				RaiseWindowWidget(w2, WP(w,dropdown_d).parent_button);
 				InvalidateWidget(w2, WP(w,dropdown_d).parent_button);
 			}
 		} break;
@@ -602,16 +603,16 @@
 	int i;
 	const Widget *wi;
 	Window *w2;
-	uint32 old_click_state = w->click_state;
+	bool is_dropdown_menu_shown = IsWindowWidgetLowered(w, button);
 
 	cls = w->window_class;
 	num = w->window_number;
 	DeleteWindowById(WC_DROPDOWN_MENU, 0);
 	w = FindWindowById(cls, num);
 
-	if (HASBIT(old_click_state, button)) return;
+	if (is_dropdown_menu_shown) return;
 
-	SETBIT(w->click_state, button);
+	LowerWindowWidget(w, button);
 
 	InvalidateWidget(w, button);
 
--- a/window.c
+++ b/window.c
@@ -17,9 +17,22 @@
 // delta between mouse cursor and upper left corner of dragged window
 static Point _drag_delta;
 
+void RaiseWindowButtons(Window *w)
+{
+	const Widget *wi = w->widget;
+	uint i = 0;
+
+	for (i = 0; wi->type != WWT_LAST; i++, wi++) {
+		if (IsWindowWidgetLowered(w, i)) {
+			RaiseWindowWidget(w, i);
+			InvalidateWidget(w, i);
+		}
+	}
+}
+
 void HandleButtonClick(Window *w, byte widget)
 {
-	w->click_state |= (1 << widget);
+	LowerWindowWidget(w, widget);
 	w->flags4 |= 5 << WF_TIMEOUT_SHL;
 	InvalidateWidget(w, widget);
 }
@@ -754,7 +767,7 @@
 
 		if (w->flags4&WF_TIMEOUT_MASK && !(--w->flags4&WF_TIMEOUT_MASK)) {
 			CallWindowEventNP(w, WE_TIMEOUT);
-			if (w->desc_flags & WDF_UNCLICK_BUTTONS) UnclickWindowButtons(w);
+			if (w->desc_flags & WDF_UNCLICK_BUTTONS) RaiseWindowButtons(w);
 		}
 	}
 }
--- a/window.h
+++ b/window.h
@@ -748,14 +748,13 @@
 void InputLoop(void);
 void UpdateWindows(void);
 void InvalidateWidget(const Window *w, byte widget_index);
-
-void GuiShowTooltips(StringID string_id);
-
-void UnclickWindowButtons(Window *w);
-void UnclickSomeWindowButtons(Window *w, uint32 mask);
+void RaiseWindowButtons(Window *w);
 void RelocateAllWindows(int neww, int newh);
 int PositionMainToolbar(Window *w);
 
+/* misc_gui.c*/
+void GuiShowTooltips(StringID string_id);
+
 /* widget.c */
 int GetWidgetFromPos(const Window *w, int x, int y);
 void DrawWindowWidgets(const Window *w);