diff --git a/builtin/modmgr.lua b/builtin/modmgr.lua
index 9f5e687b2bc4d38fe381524bed4ef18ef9559f50..81ac94c0ea2fed5d7cb8c173b135351f4dc80bf0 100644
--- a/builtin/modmgr.lua
+++ b/builtin/modmgr.lua
@@ -329,6 +329,8 @@ function modmgr.render_modlist(render_list)
 		if retval ~= "" then
 			retval = retval ..","
 		end
+
+		local color = ""
 		
 		if v.is_modpack then
 			local rawlist = filterlist.get_raw_list(render_list)
@@ -343,19 +345,21 @@ function modmgr.render_modlist(render_list)
 			end
 			
 			if all_enabled == false then
-				retval = retval .. mt_color_grey
+				color = mt_color_grey
 			else
-				retval = retval .. mt_color_dark_green
+				color = mt_color_dark_green
 			end
 		end
 		
 		if v.typ == "game_mod" then
-			retval = retval .. mt_color_blue
+			color = mt_color_blue
 		else
 			if v.enabled then
-				retval = retval .. mt_color_green
+				color = mt_color_green
 			end
 		end
+
+		retval = retval .. color
 		if v.modpack  ~= nil then
 			retval = retval .. "    "
 		end
@@ -401,7 +405,7 @@ function modmgr.dialog_configure_world()
 		"button[9.25,6.35;2,0.5;btn_config_world_save;" .. fgettext("Save") .. "]" ..
 		"button[7.4,6.35;2,0.5;btn_config_world_cancel;" .. fgettext("Cancel") .. "]"
 	
-	if mod ~= nil and mod.name ~= "" then
+	if mod ~= nil and mod.name ~= "" and mod.typ ~= "game_mod" then
 		if mod.is_modpack then
 			local rawlist = filterlist.get_raw_list(modmgr.modlist)
 			
@@ -662,57 +666,23 @@ function modmgr.handle_configure_world_buttons(fields)
 		modmgr.world_config_selected_mod = event.index
 
 		if event.typ == "DCL" then
-			local mod = filterlist.get_list(modmgr.modlist)[event.index]
-			
-			if mod.typ == "game_mod" then
-				return nil
-			end
-			
-			if not mod.is_modpack then
-				mod.enabled = not mod.enabled
-			else
-				local list = filterlist.get_raw_list(modmgr.modlist)
-				local toset = nil
-				
-				for i=1,#list,1 do
-					if list[i].modpack == mod.name then
-						if toset == nil then
-							toset = not list[i].enabled
-						end
-						
-						list[i].enabled = toset
-					end
-				end
-			end
+			modmgr.world_config_enable_mod(nil)
 		end
 	end
 	
+	if fields["key_enter"] ~= nil then
+		modmgr.world_config_enable_mod(nil)
+	end
+	
 	if fields["cb_mod_enable"] ~= nil then
-		local mod = filterlist.get_list(modmgr.modlist)
-			[engine.get_textlist_index("world_config_modlist")]
-		if fields["cb_mod_enable"] == "true" then
-			mod.enabled = true
-		else
-			mod.enabled = false
-		end
+		local toset = (fields["cb_mod_enable"] == "true")
+		modmgr.world_config_enable_mod(toset)
 	end
 	
 	if fields["btn_mp_enable"] ~= nil or
 		fields["btn_mp_disable"] then
-		local mod = filterlist.get_list(modmgr.modlist)
-			[engine.get_textlist_index("world_config_modlist")]
-		
-		local toset=false
-		if fields["btn_mp_enable"] ~= nil then
-			toset = true
-		end
-		local list = filterlist.get_raw_list(modmgr.modlist)
-		
-		for i=1,#list,1 do
-			if list[i].modpack == mod.name then
-				list[i].enabled = toset
-			end
-		end
+		local toset = (fields["btn_mp_enable"] ~= nil)
+		modmgr.world_config_enable_mod(toset)
 	end
 	
 	if fields["cb_hide_gamemods"] ~= nil then
@@ -818,6 +788,31 @@ function modmgr.handle_configure_world_buttons(fields)
 	return nil
 end
 --------------------------------------------------------------------------------
+function modmgr.world_config_enable_mod(toset)
+	local mod = filterlist.get_list(modmgr.modlist)
+		[engine.get_textlist_index("world_config_modlist")]
+
+	if mod.typ == "game_mod" then
+		-- game mods can't be enabled or disabled
+	elseif not mod.is_modpack then
+		if toset == nil then
+			mod.enabled = not mod.enabled
+		else
+			mod.enabled = toset
+		end
+	else
+		local list = filterlist.get_raw_list(modmgr.modlist)
+		for i=1,#list,1 do
+			if list[i].modpack == mod.name then
+				if toset == nil then
+					toset = not list[i].enabled
+				end
+				list[i].enabled = toset
+			end
+		end
+	end
+end
+--------------------------------------------------------------------------------
 function modmgr.handle_delete_mod_buttons(fields)
 	local mod = filterlist.get_list(modmgr.global_mods)[modmgr.selected_mod]
 	
diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp
index b0cfa38c20783cbc05d87d79190df55bd2a72f2e..1da923cd17686df84fa061cb1f293b60e132eede 100644
--- a/src/guiFormSpecMenu.cpp
+++ b/src/guiFormSpecMenu.cpp
@@ -131,6 +131,81 @@ void GUIFormSpecMenu::removeChildren()
 	}
 }
 
+void GUIFormSpecMenu::setInitialFocus()
+{
+	// Set initial focus according to following order of precedence:
+	// 1. first empty editbox
+	// 2. first editbox
+	// 3. first listbox
+	// 4. last button
+	// 5. first focusable (not statictext, not tabheader)
+	// 6. first child element
+
+	core::list<gui::IGUIElement*> children = getChildren();
+
+	// in case "children" contains any NULL elements, remove them
+	for (core::list<gui::IGUIElement*>::Iterator it = children.begin();
+			it != children.end();) {
+		if (*it)
+			++it;
+		else
+			it = children.erase(it);
+	}
+
+	// 1. first empty editbox
+	for (core::list<gui::IGUIElement*>::Iterator it = children.begin();
+			it != children.end(); ++it) {
+		if ((*it)->getType() == gui::EGUIET_EDIT_BOX
+				&& (*it)->getText()[0] == 0) {
+			Environment->setFocus(*it);
+			return;
+		}
+	}
+
+	// 2. first editbox
+	for (core::list<gui::IGUIElement*>::Iterator it = children.begin();
+			it != children.end(); ++it) {
+		if ((*it)->getType() == gui::EGUIET_EDIT_BOX) {
+			Environment->setFocus(*it);
+			return;
+		}
+	}
+
+	// 3. first listbox
+	for (core::list<gui::IGUIElement*>::Iterator it = children.begin();
+			it != children.end(); ++it) {
+		if ((*it)->getType() == gui::EGUIET_LIST_BOX) {
+			Environment->setFocus(*it);
+			return;
+		}
+	}
+
+	// 4. last button
+	for (core::list<gui::IGUIElement*>::Iterator it = children.getLast();
+			it != children.end(); --it) {
+		if ((*it)->getType() == gui::EGUIET_BUTTON) {
+			Environment->setFocus(*it);
+			return;
+		}
+	}
+
+	// 5. first focusable (not statictext, not tabheader)
+	for (core::list<gui::IGUIElement*>::Iterator it = children.begin();
+			it != children.end(); ++it) {
+		if ((*it)->getType() != gui::EGUIET_STATIC_TEXT &&
+				(*it)->getType() != gui::EGUIET_TAB_CONTROL) {
+			Environment->setFocus(*it);
+			return;
+		}
+	}
+
+	// 6. first child element
+	if (children.empty())
+		Environment->setFocus(this);
+	else
+		Environment->setFocus(*(children.begin()));
+}
+
 int GUIFormSpecMenu::getListboxIndex(std::string listboxname) {
 
 	std::wstring wlistboxname = narrow_to_wide(listboxname.c_str());
@@ -387,6 +462,11 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element) {
 		spec.flabel = wlabel; //Needed for displaying text on MSVC
 		gui::IGUICheckBox* e = Environment->addCheckBox(fselected, rect, this,
 					spec.fid, spec.flabel.c_str());
+
+		if (spec.fname == data->focused_fieldname) {
+			Environment->setFocus(e);
+		}
+
 		m_checkboxes.push_back(std::pair<FieldSpec,gui::IGUICheckBox*>(spec,e));
 		m_fields.push_back(spec);
 		return;
@@ -503,7 +583,13 @@ void GUIFormSpecMenu::parseButton(parserData* data,std::string element,std::stri
 		if(type == "button_exit")
 			spec.is_exit = true;
 
-		Environment->addButton(rect, this, spec.fid, spec.flabel.c_str());
+		gui::IGUIButton* e = Environment->addButton(rect, this, spec.fid,
+				spec.flabel.c_str());
+
+		if (spec.fname == data->focused_fieldname) {
+			Environment->setFocus(e);
+		}
+
 		m_fields.push_back(spec);
 		return;
 	}
@@ -582,9 +668,8 @@ void GUIFormSpecMenu::parseTextList(parserData* data,std::string element) {
 		//now really show list
 		gui::IGUIListBox *e = Environment->addListBox(rect, this,spec.fid);
 
-		//don't reset if we already have a user specified selection
-		if (data->listbox_selections.find(fname_w) == data->listbox_selections.end()) {
-			e->setAutoScrollEnabled(false);
+		if (spec.fname == data->focused_fieldname) {
+			Environment->setFocus(e);
 		}
 
 		if (str_transparent == "false")
@@ -670,10 +755,9 @@ void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element) {
 		//now really show list
 		gui::IGUIComboBox *e = Environment->addComboBox(rect, this,spec.fid);
 
-		//don't reset if we already have a user specified selection
-		//if (data->combobox_selections.find(fname_w) == data->listbox_selections.end()) {
-		//	e->setAutoScrollEnabled(false);
-		//}
+		if (spec.fname == data->focused_fieldname) {
+			Environment->setFocus(e);
+		}
 
 		for (unsigned int i=0; i < items.size(); i++) {
 			e->addItem(narrow_to_wide(items[i]).c_str());
@@ -732,7 +816,10 @@ void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element) {
 
 		spec.send = true;
 		gui::IGUIEditBox * e = Environment->addEditBox(0, rect, true, this, spec.fid);
-		Environment->setFocus(e);
+
+		if (spec.fname == data->focused_fieldname) {
+			Environment->setFocus(e);
+		}
 
 		if (label.length() > 1)
 		{
@@ -811,7 +898,10 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data,std::vector<std::string>
 	{
 		spec.send = true;
 		gui::IGUIEditBox *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid);
-		Environment->setFocus(e);
+
+		if (spec.fname == data->focused_fieldname) {
+			Environment->setFocus(e);
+		}
 
 		irr::SEvent evt;
 		evt.EventType            = EET_KEY_INPUT_EVENT;
@@ -894,7 +984,10 @@ void GUIFormSpecMenu::parseTextArea(parserData* data,std::vector<std::string>& p
 	{
 		spec.send = true;
 		gui::IGUIEditBox *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid);
-		Environment->setFocus(e);
+
+		if (spec.fname == data->focused_fieldname) {
+			Environment->setFocus(e);
+		}
 
 		if (type == "textarea")
 		{
@@ -1091,6 +1184,11 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element,std:
 			pressed_texture = texture;
 
 		gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, spec.flabel.c_str());
+
+		if (spec.fname == data->focused_fieldname) {
+			Environment->setFocus(e);
+		}
+
 		e->setUseAlphaChannel(true);
 		e->setImage(texture);
 		e->setPressedImage(pressed_texture);
@@ -1146,6 +1244,10 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element) {
 
 		gui::IGUITabControl *e = Environment->addTabControl(rect,this,show_background,show_border,spec.fid);
 
+		if (spec.fname == data->focused_fieldname) {
+			Environment->setFocus(e);
+		}
+
 		e->setNotClipped(true);
 
 		for (unsigned int i=0; i< buttons.size(); i++) {
@@ -1213,6 +1315,11 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
 		);
 
 		gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, spec.flabel.c_str());
+
+		if (spec.fname == data->focused_fieldname) {
+			Environment->setFocus(e);
+		}
+
 		e->setUseAlphaChannel(true);
 		e->setImage(texture);
 		e->setPressedImage(texture);
@@ -1400,6 +1507,21 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
 		}
 	}
 
+	//preserve focus
+	gui::IGUIElement *focused_element = Environment->getFocus();
+	if (focused_element && focused_element->getParent() == this) {
+		s32 focused_id = focused_element->getID();
+		if (focused_id > 257) {
+			for (u32 i=0; i<m_fields.size(); i++) {
+				if (m_fields[i].fid == focused_id) {
+					mydata.focused_fieldname =
+						m_fields[i].fname;
+					break;
+				}
+			}
+		}
+	}
+
 	// Remove children
 	removeChildren();
 
@@ -1485,6 +1607,13 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
 		m_tooltip_element->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
 		m_tooltip_element->setWordWrap(false);
 	}
+
+	//set initial focus if parser didn't set it
+	focused_element = Environment->getFocus();
+	if (!focused_element
+			|| !isMyChild(focused_element)
+			|| focused_element->getType() == gui::EGUIET_TAB_CONTROL)
+		setInitialFocus();
 }
 
 GUIFormSpecMenu::ItemSpec GUIFormSpecMenu::getItemAtPos(v2s32 p) const
@@ -2041,6 +2170,41 @@ void GUIFormSpecMenu::acceptInput()
 	}
 }
 
+bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
+{
+	// Fix Esc/Return key being eaten by checkboxen and listboxen
+	if(event.EventType==EET_KEY_INPUT_EVENT)
+	{
+		KeyPress kp(event.KeyInput);
+		if (kp == EscapeKey || kp == getKeySetting("keymap_inventory")
+				|| event.KeyInput.Key==KEY_RETURN)
+		{
+			gui::IGUIElement *focused = Environment->getFocus();
+			if (focused && isMyChild(focused) &&
+					(focused->getType() == gui::EGUIET_LIST_BOX ||
+					 focused->getType() == gui::EGUIET_CHECK_BOX)) {
+				OnEvent(event);
+				return true;
+			}
+		}
+	}
+	// Mouse wheel events: send to hovered element instead of focused
+	if(event.EventType==EET_MOUSE_INPUT_EVENT
+			&& event.MouseInput.Event == EMIE_MOUSE_WHEEL)
+	{
+		s32 x = event.MouseInput.X;
+		s32 y = event.MouseInput.Y;
+		gui::IGUIElement *hovered =
+			Environment->getRootGUIElement()->getElementFromPoint(
+				core::position2d<s32>(x, y));
+		if (hovered && isMyChild(hovered)) {
+			hovered->OnEvent(event);
+			return true;
+		}
+	}
+	return false;
+}
+
 bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 {
 	if(event.EventType==EET_KEY_INPUT_EVENT)
@@ -2391,8 +2555,6 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 					s.send = true;
 					acceptInput();
 					s.send = false;
-					// Restore focus to the full form
-					Environment->setFocus(this);
 					return true;
 				}
 			}
@@ -2442,8 +2604,6 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 						return true;
 					}else{
 						s.send = false;
-						// Restore focus to the full form
-						Environment->setFocus(this);
 						return true;
 					}
 				}
@@ -2488,8 +2648,6 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
 						s.send = true;
 						acceptInput();
 						s.send=false;
-						// Restore focus to the full form
-						Environment->setFocus(this);
 					}
 				}
 				return true;
diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h
index 640c35c0a407139ca2ac705ea3f06bd0e5e9397e..73c21b72decab7f2ebb3fac5043272746bfc43ab 100644
--- a/src/guiFormSpecMenu.h
+++ b/src/guiFormSpecMenu.h
@@ -212,6 +212,7 @@ class GUIFormSpecMenu : public GUIModalMenu
 	}
 
 	void removeChildren();
+	void setInitialFocus();
 	/*
 		Remove and re-add (or reposition) stuff
 	*/
@@ -225,6 +226,7 @@ class GUIFormSpecMenu : public GUIModalMenu
 	ItemStack verifySelectedItem();
 
 	void acceptInput();
+	bool preprocessEvent(const SEvent& event);
 	bool OnEvent(const SEvent& event);
 
 	int getListboxIndex(std::string listboxname);
@@ -288,6 +290,7 @@ class GUIFormSpecMenu : public GUIModalMenu
 		v2s32 basepos;
 		int bp_set;
 		v2u32 screensize;
+		std::wstring focused_fieldname;
 		std::map<std::wstring,int> listbox_selections;
 		std::map<std::wstring,int> listbox_scroll;
 	} parserData;
diff --git a/src/main.cpp b/src/main.cpp
index 7450593d326d380b6fc4d63e661dbaf671da0646..05a7dd1630e1f4ebc1d3b1fbd708c14006a19fc2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -244,7 +244,7 @@ class MyEventReceiver : public IEventReceiver
 		*/
 		if(noMenuActive() == false)
 		{
-			return false;
+			return g_menumgr.preprocessEvent(event);
 		}
 
 		// Remember whether each key is down or up
diff --git a/src/mainmenumanager.h b/src/mainmenumanager.h
index a3133686bb69e32735f6d336288785f45a0710cc..d151cf48d663b33958e8be9defacb316b9f81e0a 100644
--- a/src/mainmenumanager.h
+++ b/src/mainmenumanager.h
@@ -77,6 +77,15 @@ class MainMenuManager : public IMenuManager
 			m_stack.back()->setVisible(true);
 	}
 
+	// Returns true to prevent further processing
+	virtual bool preprocessEvent(const SEvent& event)
+	{
+		if(m_stack.size() != 0)
+			return m_stack.back()->preprocessEvent(event);
+		else
+			return false;
+	}
+
 	u32 menuCount()
 	{
 		return m_stack.size();
diff --git a/src/modalMenu.h b/src/modalMenu.h
index 62bfabc06b7c9818bc4b6538b3d1db253c58631c..c8b45a247a8cb233de94e1eb0b790deecb9190f4 100644
--- a/src/modalMenu.h
+++ b/src/modalMenu.h
@@ -122,6 +122,7 @@ class GUIModalMenu : public gui::IGUIElement
 
 	virtual void regenerateGui(v2u32 screensize) = 0;
 	virtual void drawMenu() = 0;
+	virtual bool preprocessEvent(const SEvent& event) { return false; };
 	virtual bool OnEvent(const SEvent& event) { return false; };
 
 protected: