Index: django/contrib/gis/maps/google/gmap.py
===================================================================
--- django/contrib/gis/maps/google/gmap.py	(revision 7829)
+++ django/contrib/gis/maps/google/gmap.py	(working copy)
@@ -4,7 +4,7 @@
 from django.utils.safestring import mark_safe
 
 class GoogleMapException(Exception): pass
-from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline
+from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, GMarker
 
 # The default Google Maps URL (for the API javascript)
 # TODO: Internationalize for Japan, UK, etc.
@@ -20,7 +20,7 @@
 
     def __init__(self, key=None, api_url=None, version=None, 
                  center=None, zoom=None, dom_id='map', load_func='gmap_load', 
-                 kml_urls=[], polygons=[], polylines=[],
+                 kml_urls=[], polygons=[], polylines=[], points=[],
                  template='gis/google/js/google-map.js',
                  extra_context={}):
 
@@ -56,7 +56,13 @@
         self.kml_urls = kml_urls
         
         # Does the user want any GPolygon or GPolyline overlays?
-        self.polygons, self.polylines = [], []
+        self.polygons, self.polylines, self.points = [], [], []
+        if points:
+            for point in points:
+                if isinstance(point, GMarker): 
+                    self.points.append(point)
+                else:
+                    self.points.append(GMarker(point))
         if polygons:
             for poly in polygons:
                 if isinstance(poly, GPolygon): 
@@ -70,12 +76,13 @@
                 else:
                     self.polylines.append(GPolyline(pline))
        
-        # If GPolygons and/or GPolylines are used the zoom will be automatically
+        # If GPolygons and/or GPolylines and/or GPOints 
+        # are used the zoom will be automatically
         # calculated via the Google Maps API.  If both a zoom level and a
         # center coordinate are provided with polygons/polylines, no automatic
         # determination will occur.
         self.calc_zoom = False
-        if self.polygons or self.polylines:
+        if self.polygons or self.polylines  or self.points:
             if center is None or zoom is None:
                 self.calc_zoom = True
     
@@ -95,6 +102,7 @@
                   'zoom' : self.zoom,
                   'polygons' : self.polygons,
                   'polylines' : self.polylines,
+                  'points' : self.points,
                   }
         params.update(extra_context)
         self.js = render_to_string(self.template, params)
Index: django/contrib/gis/maps/google/overlays.py
===================================================================
--- django/contrib/gis/maps/google/overlays.py	(revision 7829)
+++ django/contrib/gis/maps/google/overlays.py	(working copy)
@@ -1,10 +1,69 @@
-from django.contrib.gis.geos import LineString, LinearRing, Polygon
+from django.contrib.gis.geos import LineString, LinearRing, Polygon, Point
 from django.utils.safestring import mark_safe
 
+class GEvent(object):
+    """A Python wrapper for the Google GEvent object. For more information
+    please see the Google Maps API Reference:
+    http://code.google.com/apis/maps/documentation/reference.html#GEvent
+    Events can be attached to any object derived from GOverlayBase with the
+    add_event() call.
+
+    Example:
+
+      from django.shortcuts import render_to_response
+      from django.contrib.gis.maps.google.gmap import GoogleMap
+      from django.contrib.gis.maps.google.overlays import GPolyline, GEvent
+      from django.contrib.gis.geos import fromstr
+
+      def sample_request(request):
+          polylines = []
+          location = fromstr('LINESTRING(101 26, 112 26, 102 31)')
+          polyline = GPolyline(location)
+          event = GEvent('click', 
+            'function() { location.href = "http://www.google.com"}')
+          polyline.add_event(event)
+          polylines.append(polyline)
+          return render_to_response('mytemplate.html', 
+          {'google' : GoogleMap(polylines=polylines)})
+      
+
+    """
+
+    def __init__(self, event, action):
+        """Initializes a GEvent object. 
+        
+        Parameters:
+
+          event: 
+            string for the event, such as 'click'. The event must be a valid
+            event for the object in the Google Maps API. 
+            There is no validation of the event type within Django.
+
+          action:
+            string containing a Javascript function, such as 
+            'function() { location.href = "newurl";}'
+            The string must be a valid Javascript function. Again there is no 
+            validation fo the function within Django.
+        """
+        self.event = event
+        self.action = action
+
+    def __unicode__(self):
+        """Returns the parameter part of a GEvent."""
+        return mark_safe('"%s", %s' %(self.event, self.action))
+
 class GOverlayBase(object):
+    def __init__(self):
+        self.events = []
+
     def latlng_from_coords(self, coords):
         return '[%s]' % ','.join(['new GLatLng(%s,%s)' % (y, x) for x, y in coords])
 
+    def add_event(self, event):
+        """Attaches a GEvent to the overlay object."""
+
+        self.events.append(event)
+
     def __unicode__(self):
         "The string representation is the JavaScript API call."
         return mark_safe('%s(%s)' % (self.__class__.__name__, self.js_params))
@@ -40,6 +99,8 @@
             The opacity of the polygon fill.  Defaults to 0.4.
         """
 
+        GOverlayBase.__init__(self)
+
         # TODO: Take other types of geometries.
         if not isinstance(poly, Polygon): 
             raise TypeError('GPolygon may only initialize on GEOS Polygons.')
@@ -85,6 +146,7 @@
           opacity:
             The opacity of the polyline, between 0 and 1.  Defaults to 1.
         """
+        GOverlayBase.__init__(self)
         if isinstance(geom, (LineString, LinearRing)):
             self.latlngs = self.latlng_from_coords(geom.coords)
         elif isinstance(geom, Polygon):
@@ -99,3 +161,59 @@
     @property
     def js_params(self):
         return '%s, "%s", %s, %s' % (self.latlngs, self.color, self.weight, self.opacity)
+
+
+class GMarker(GOverlayBase):
+    """
+    A Python wrapper for the Google GMarker object.  For more information
+    please see the Google Maps API Reference:
+     http://code.google.com/apis/maps/documentation/reference.html#GMarker
+
+    Example:
+
+      from django.shortcuts import render_to_response
+      from django.contrib.gis.maps.google.gmap import GoogleMap
+      from django.contrib.gis.maps.google.overlays import GMarker, GEvent
+      from django.contrib.gis.geos import fromstr
+
+      def sample_request(request):
+          points = []
+          location = fromstr('POINT(101 26)')
+          point = GMarker(location)
+          event = GEvent('click', 
+            'function() { location.href = "http://www.google.com"}')
+          point.add_event(event)
+          points.append(point)
+          return render_to_response('mytemplate.html', 
+          {'google' : GoogleMap(points=points)})
+
+
+    """
+    def __init__(self, geom, title = None):
+        """
+        The GMarker object may initialize on GEOS Point objects.
+
+          title:
+            title option for GMarker, will be displayed as a tooltip
+        """
+        GOverlayBase.__init__(self)
+        if isinstance(geom, Point):
+            self.latlng = self.latlng_from_coords(geom.coords)
+        else:
+            raise TypeError('GMarker may only initialize on GEOS Point geometry.')
+        # Getting the envelope for automatic zoom determination.
+        self.envelope = geom.envelope
+        self.title = title
+
+    def latlng_from_coords(self, coords):
+        return 'new GLatLng(%s,%s)' %(coords[1], coords[0])
+    
+    def options(self):
+        result = ''
+        if self.title:
+            result += 'title: "%s"' %self.title
+        return result
+        
+    @property
+    def js_params(self):
+        return '%s, {%s}' % (self.latlng, self.options())
Index: django/contrib/gis/templates/gis/google/js/google-map.js
===================================================================
--- django/contrib/gis/templates/gis/google/js/google-map.js	(revision 7829)
+++ django/contrib/gis/templates/gis/google/js/google-map.js	(working copy)
@@ -8,12 +8,30 @@
     {% if calc_zoom %}var bounds = new GLatLngBounds(); var tmp_bounds = new GLatLngBounds();{% else %}map.setCenter(new GLatLng({{ center.1 }}, {{ center.0 }}), {{ zoom }});{% endif %}
     {% for kml_url in kml_urls %}var kml{{ forloop.counter }} = new GGeoXml("{{ kml_url }}");
     map.addOverlay(kml{{ forloop.counter }});{% endfor %}
+
     {% for polygon in polygons %}var poly{{ forloop.counter }} = new {{ polygon }};
-    map.addOverlay(poly{{ forloop.counter }});{% if calc_zoom %}
+    map.addOverlay(poly{{ forloop.counter }});
+    {% for event in polygon.events %}
+    GEvent.addListener(poly{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
+    {% if calc_zoom %}
     tmp_bounds = poly{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %}
+
     {% for polyline in polylines %}var polyline{{ forloop.counter }} = new {{ polyline }};
-    map.addOverlay(polyline{{ forloop.counter }});{% if calc_zoom %}
+    map.addOverlay(polyline{{ forloop.counter }});
+    {% for event in polyline.events %}
+    GEvent.addListener(polyline{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
+    {% if calc_zoom %}
     tmp_bounds = polyline{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %}
+
+
+    {% for point in points %}var point{{ forloop.counter }} = new {{ point }};
+    {% for event in point.events %}
+    GEvent.addListener(point{{ forloop.parentloop.counter }}, {{ event }}); 
+    {% endfor %}
+    {% if calc_zoom %}map.setCenter(new GLatLng(point{{ forloop.counter }}.getLatLng())); {% endif %}
+    map.addOverlay(point{{ forloop.counter }});
+    {% if calc_zoom %}bounds.extend(point{{ forloop.counter }}.getLatLng()); {% endif %}{% endfor %}
+
     {% if calc_zoom %}map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));{% endif %}
     {% block load_extra %}{% endblock %}
   }else {
