diff --git a/GMAP-MACRO-DICTIONARY.txt b/GMAP-MACRO-DICTIONARY.txt
index 91d43e7..dc77bb6 100644
--- a/GMAP-MACRO-DICTIONARY.txt
+++ b/GMAP-MACRO-DICTIONARY.txt
@@ -46,6 +46,11 @@ Description:	id for the rendered map element, to distinguish the map from other
 Example:			id=mymap
 Notes:				use if you need to access the map from a script, or if you plan to have multiple maps on a page. As of Gmap 1.0, this is no longer required.
 
+Attribute:    extinfowindow
+Values:       exinfowindow theme name
+Description:  the name of the extinfowindow theme you want to use. if multiple maps are on a page they will all use the theme for the first map.
+Example:      extinfowindow=light
+
 --------
 OVERLAYS
 --------
diff --git a/gmap.module b/gmap.module
index 767d7cc..f008b20 100644
--- a/gmap.module
+++ b/gmap.module
@@ -163,6 +163,11 @@ function gmap_gmap($op, &$map) {
       if (isset($map['feed']) && is_array($map['feed'])) {
         drupal_add_js($path . 'markerloader_georss.js');
       }
+      // ExtInfoWindow.
+      if (variable_get('gmap_extinfowindow_active', FALSE)) {
+        $extinfowindow_theme = isset($map['extinfowindow']) ? $map['extinfowindow'] : '';
+        gmap_add_extinfowindow($extinfowindow_theme);
+      }
       break;
     case 'macro_multiple':
       return array('points', 'markers', 'feed', 'circle', 'rpolygon', 'polygon', 'line', 'style');
@@ -839,7 +844,7 @@ function gmap_map_cleanup(&$map) {
       unset($map['extent']);
     }
   }
-    
+
   if (isset($map['latlon']) && (!isset($map['latitude']) || !isset($map['longitude']))) {
     list($map['latitude'], $map['longitude']) = explode(',', $map['latlon']);
   }
@@ -1277,6 +1282,97 @@ function gmap_views_plugins() {
 }
 
 /**
+ * Function that adds the required js and css for extinfowindow pop-ups.
+ *
+ * @param $theme_name
+ *   The name of the theme to use.
+ *   If omitted it will be the extinfowindow theme set on the gmap settings page.
+ */
+function gmap_add_extinfowindow($theme_name = '') {
+  // Due to the way these themes work (css) we can only reliably have one theme
+  // used on a page at any one time.
+  // So if we have already loaded a theme then skip this.
+  $themes = gmap_extinfowindow_themes(FALSE);
+  $css = drupal_add_css();
+  $found = FALSE;
+  foreach ($themes as $theme) {
+    if (array_key_exists($theme['css_path'], $css['all']['module'])) {
+      $found = TRUE;
+    }
+  }
+  if (!$found) {
+    if (!$theme_name) {
+      $theme_name = variable_get('gmap_extinfowindow_theme', 'dark');
+    }
+
+    // Add the js extinfowindow enabled/disabled setting.
+    drupal_add_js(array('gmap' => array('extinfowindow' => variable_get('gmap_extinfowindow_active', FALSE))), 'setting');
+    // Add the extinfowindow js.
+
+    drupal_add_js(libraries_get_path('extinfowindow') .'/'. variable_get('gmap_extinfowindow_filename', 'extinfowindow_packed.js'));
+    // Get the active theme.
+    $theme = gmap_extinfowindow_themes(FALSE, $theme_name);
+    // Add the theme css.
+    drupal_add_css($theme['css_path']);
+  }
+}
+
+/**
+ * Get the themes for ExtInfoWindow.
+ *
+ * Gets default themes from the gmap module and additional themes from the
+ * active theme.
+ * An ext theme in the active theme will override one in the gmap module.
+ *
+ * @param $names
+ *   Whether to return names only or names with their paths.
+ * @param $theme_name
+ *   The name of a specific theme to return.
+ *   If omitted all themes will be returned.
+ *
+ * @return
+ *   Depending on parameters it could be:
+ *   - An array of theme names;
+ *   - An array of themes, with their name and the patch to their css;
+ *   - A single theme name string;
+ *   - An array of a single theme's name and path to css.
+ */
+function gmap_extinfowindow_themes($names = TRUE, $theme_name = '') {
+  global $theme;
+
+  // Get theme directories.
+  $theme_path = drupal_get_path('theme', $theme);
+  $default_path = libraries_get_path('extinfowindow') . '/themes';
+
+  // Get themes from the theme directories.
+  $default_themes = file_scan_directory($default_path, '.css$');
+  $themes = file_scan_directory($theme_path . '/extinfowindow', '.css$');
+
+  $themes = array_merge($default_themes, $themes);
+  $available_names = array();
+  $ext_themes = array();
+  foreach ($themes as $ext_theme) {
+    if (file_exists($ext_theme->filename)) {
+      $available_names[] = $ext_theme->name;
+      if ($names) {
+        $ext_themes[$ext_theme->name] = $ext_theme->name;
+      }
+      else {
+        $ext_themes[$ext_theme->name] = array(
+          'name' => $ext_theme->name,
+          'css_path' => $ext_theme->filename,
+        );
+      }
+    }
+  }
+  if ($theme_name && ! in_array($theme_name, $available_names)) {
+    $theme_name = 'dark';
+  }
+
+  return $theme_name ? $ext_themes[$theme_name] : $ext_themes;
+}
+
+/**
  * Implementation of hook_views_pre_render().
  */
 function gmap_views_pre_render(&$view) {
diff --git a/gmap_plugin_style_gmap.inc b/gmap_plugin_style_gmap.inc
index a4d9e55..2c3f899 100644
--- a/gmap_plugin_style_gmap.inc
+++ b/gmap_plugin_style_gmap.inc
@@ -46,6 +46,8 @@ class gmap_plugin_style_gmap extends views_plugin_style {
     $options['tooltipenabled'] = array('default' => 0);
     $options['tooltipfield'] = array('default' => '');
 
+    $options['extinfowindow_theme'] = array('default' => '');
+
     return $options;
   }
 
@@ -242,6 +244,10 @@ class gmap_plugin_style_gmap extends views_plugin_style {
         }
 
         $map['markers'] = $markers;
+
+        if ($this->options['extinfowindow_theme']) {
+          $map['extinfowindow'] = $this->options['extinfowindow_theme'];
+        }
         $output .= theme($this->theme_functions(), $this->view, $this->options, $map, $title);
       }
     }
@@ -422,6 +428,17 @@ class gmap_plugin_style_gmap extends views_plugin_style {
       '#process' => array('views_process_dependency'),
       '#dependency' => array('edit-style-options-tooltipenabled' => array(TRUE)),
     );
+
+    if (variable_get('gmap_extinfowindow_active', FALSE)) {
+      $form['extinfowindow_theme'] = array(
+        '#title' => t('Extinfowindow theme'),
+        '#description' => t("The extinfowindow theme to use for this view.") . '<br />' .
+                          t("If multiple maps maps a page they will all use the theme for the first map."),
+        '#type' => 'select',
+        '#options' => gmap_extinfowindow_themes(),
+        '#default_value' => isset($this->options['extinfowindow_theme']) ? $this->options['extinfowindow_theme'] : variable_get('gmap_extinfowindow_theme', 'dark'),
+      );
+    }
   }
 
   /**
diff --git a/gmap_settings_ui.inc b/gmap_settings_ui.inc
index 90b5c9f..0ed77fe 100644
--- a/gmap_settings_ui.inc
+++ b/gmap_settings_ui.inc
@@ -313,7 +313,7 @@ function gmap_admin_settings(&$form_state) {
     'markerMinZoom' => 4,
     'markerMaxZoom' => 0,
   ), $opts['markermanager']);
-  
+
   $opts['markerclusterer'] = array_merge(array(
     'filename' => 'markerclusterer_packed.js',
     'gridSize' => 60,
@@ -619,6 +619,40 @@ function gmap_admin_settings(&$form_state) {
     '#size' => 4,
     '#maxlength' => 4,
   );
+  // ExtInfoWindow Settings
+  if (module_exists('libraries')) {
+    $library_path = libraries_get_path('extinfowindow');
+    $form['gmap_extinfowindow'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('ExtInfoWindow'),
+      '#description' => t('ExtInfoWindow enables you to theme the pop info window using CSS.') . '<br />' .
+                        t('To use, you must download it from <a href="@url">here</a> and extract the appropriate file to the <em>@path</em> folder.', array('@url' => 'http://gmaps-utility-library-dev.googlecode.com/svn/tags/extinfowindow/1.2/src/', '@path' => $library_path )),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+    );
+    $form['gmap_extinfowindow']['gmap_extinfowindow_filename'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Filename'),
+      '#description' => t('Name of downloaded file in the @path folder. Default: %default', array('@path' => $library_path, '%default' => 'extinfowindow_packed.js')),
+      '#default_value' => variable_get('gmap_extinfowindow_filename', 'extinfowindow_packed.js'),
+    );
+    $form['gmap_extinfowindow']['gmap_extinfowindow_active'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Enable GMap Ext Window'),
+      '#default_value' => variable_get('gmap_extinfowindow_active', FALSE),
+      '#description' => t('Enable/disable the GMap Ext Info Window'),
+    );
+    $form['gmap_extinfowindow']['gmap_extinfowindow_theme'] = array(
+      '#type' => 'select',
+      '#title' => t('Theme'),
+      '#default_value' => variable_get('gmap_extinfowindow_theme', 'dark'),
+      '#options' => gmap_extinfowindow_themes(),
+      '#description' => t('The theme to use for the ext window inplementation.')
+    );
+  }
+  else {
+    variable_set('gmap_extinfowindow_active', FALSE);
+  }
 
   // @@@ Convert to element level validation.
   $form['#validate'][] = 'gmap_admin_settings_validate';
diff --git a/js/marker.js b/js/marker.js
index d4aa100..ff52e36 100644
--- a/js/marker.js
+++ b/js/marker.js
@@ -60,7 +60,18 @@ Drupal.gmap.addHandler('gmap', function (elem) {
   obj.bind('clickmarker', function (marker) {
     // Local/stored content
     if (marker.text) {
-      marker.marker.openInfoWindowHtml(marker.text);
+      // ExtInfoWindow implementation.
+      if (Drupal.settings.gmap.extinfowindow) {
+        marker.marker.openExtInfoWindow(
+          obj.map,
+          'opacity_window',
+          marker.text,
+          {beakOffset: 2}
+        );
+      }
+      else {
+        marker.marker.openInfoWindowHtml(marker.text);
+      }
     }
     // Info Window Query / Info Window Offset
     if (marker.iwq || (obj.vars.iwq && typeof marker.iwo != 'undefined')) {
@@ -87,7 +98,18 @@ Drupal.gmap.addHandler('gmap', function (elem) {
       
       // Cached RMT.
       if (obj.rmtcache[marker.rmt]) {
-        marker.marker.openInfoWindowHtml(obj.rmtcache[marker.rmt]);
+        // ExtInfoWindow implementation.
+        if (Drupal.settings.gmap.extinfowindow) {
+          marker.marker.openExtInfoWindow(
+            obj.map,
+            'opacity_window',
+            obj.rmtcache[marker.rmt],
+            {beakOffset: 2}
+          );
+        }
+        else {
+          marker.marker.openInfoWindowHtml(obj.rmtcache[marker.rmt]);
+        }
       }
       else {
         var uri = marker.rmt;
@@ -105,7 +127,18 @@ Drupal.gmap.addHandler('gmap', function (elem) {
         //}
         $.get(uri, {}, function (data) {
           obj.rmtcache[marker.rmt] = data;
-          marker.marker.openInfoWindowHtml(data);
+          // ExtInfoWindow implementation.
+          if (Drupal.settings.gmap.extinfowindow) {
+            marker.marker.openExtInfoWindow(
+              obj.map,
+              'opacity_window',
+              data,
+              {beakOffset: 2}
+            );
+          }
+          else {
+            marker.marker.openInfoWindowHtml(data);
+          }
         });
       }
     }
