Index: trac/search/web_ui.py
===================================================================
--- trac/search/web_ui.py	(revision 4320)
+++ trac/search/web_ui.py	(working copy)
@@ -65,6 +65,10 @@
     def process_request(self, req):
         req.perm.assert_permission('SEARCH_VIEW')
 
+        if req.path_info == '/search/opensearch':
+            return ('opensearch.xml', {},
+                    'application/opensearchdescription+xml')
+
         available_filters = []
         for source in self.search_sources:
             available_filters += source.get_search_filters(req)
Index: trac/web/chrome.py
===================================================================
--- trac/web/chrome.py	(revision 4320)
+++ trac/web/chrome.py	(working copy)
@@ -323,16 +323,13 @@
         add_script(fakereq, 'common/js/trac.js')
         add_script(fakereq, 'common/js/search.js')
 
-        icon = self.env.project_icon
-        if icon:
-            if not icon.startswith('/') and icon.find('://') == -1:
-                if '/' in icon:
-                    icon = req.href.chrome(icon)
-                else:
-                    icon = req.href.chrome('common', icon)
-            mimetype = mimeview.get_mimetype(icon)
-            add_link(fakereq, 'icon', icon, mimetype=mimetype)
-            add_link(fakereq, 'shortcut icon', icon, mimetype=mimetype)
+        # Shortcut icon
+        chrome['icon'] = self.get_icon_data(req)
+        if chrome['icon']:
+            src = chrome['icon']['src']
+            mimetype = chrome['icon']['mimetype']
+            add_link(fakereq, 'icon', src, mimetype=mimetype)
+            add_link(fakereq, 'shortcut icon', src, mimetype=mimetype)
 
         # Logo image
         chrome['logo'] = self.get_logo_data(req.href)
@@ -369,6 +366,23 @@
 
         return chrome
 
+
+    def get_icon_data(self, req):
+        icon = {}
+        icon_src = icon_abs_src = self.env.project_icon
+        if icon_src:
+            if not icon_src.startswith('/') and icon_src.find('://') == -1:
+                if '/' in icon_src:
+                    icon_abs_src = req.abs_href.chrome(icon_src)
+                    icon_src = req.href.chrome(icon_src)
+                else:
+                    icon_abs_src = req.abs_href.chrome('common', icon_src)
+                    icon_src = req.href.chrome('common', icon_src)
+            mimetype = mimeview.get_mimetype(icon_src)
+            icon = {'src': icon_src, 'abs_src': icon_abs_src,
+                    'mimetype': mimetype}
+        return icon
+
     def get_logo_data(self, href):
         logo = {}
         logo_src = self.logo_src
Index: templates/search.html
===================================================================
--- templates/search.html	(revision 4320)
+++ templates/search.html	(working copy)
@@ -7,6 +7,11 @@
   <xi:include href="layout.html" />
   <head>
     <title>Search<py:if test="query"> Results</py:if></title>
+    <py:if test="results">
+        <meta name="totalResults" content="$results.num_items"/>
+        <meta name="startIndex" content="${results.span[0] + 1}"/>
+        <meta name="itemsPerPage" content="$results.max_per_page"/>
+    </py:if>
     <script type="text/javascript">
       $(document).ready(function() {$("#q").get(0).focus()});
     </script>
Index: templates/layout.html
===================================================================
--- templates/layout.html	(revision 4320)
+++ templates/layout.html	(working copy)
@@ -16,6 +16,10 @@
         <link rel="${rel}" py:for="link in links" py:attrs="link" />
       </py:for>
     </py:if>
+    <py:if test="'SEARCH_VIEW' in perm" id="search">
+      <link type="application/opensearchdescription+xml" rel="search" 
+            href="${href.search('opensearch')}" title="Search $project.name"/>
+    </py:if>
     <script py:for="script in chrome.scripts"
             type="${script.type}" src="${script.href}"></script>
     ${select("*[local-name() != 'title']")}
Index: templates/opensearch.xml
===================================================================
--- templates/opensearch.xml	(revision 0)
+++ templates/opensearch.xml	(revision 0)
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<OpenSearchDescription xmlns:py="http://genshi.edgewall.org/"
+                       xmlns="http://a9.com/-/spec/opensearch/1.1/">
+  <ShortName>Search $project.name</ShortName>
+  <InputEncoding>UTF-8</InputEncoding>
+  <Image py:if="chrome.icon.abs_src" width="16" height="16"
+         type="$chrome.icon.mimetype">$chrome.icon.abs_src</Image>
+  <Url type="text/html"
+       template="${abs_href.search()}?q={searchTerms}&amp;page={startPage}"/>
+</OpenSearchDescription>
