My favorites | English | Sign in

Google Desktop APIs (Labs)

Writing a Cross-Platform Gadget

By following a few rules, you can create Desktop gadgets that work on multiple platforms.

Once you've written your gadget, you need to test it and specify the platforms that can execute the gadget.

Use JavaScript, not JScript

The general rule is to follow the JavaScript conventions that are documented in David Flanagan's JavaScript, The Definitive Guide.

Use the proper case

Although JScript is case insensitive, JavaScript is not. Take care to use the capitalization specified in the API reference documentation.

Example:

view.settimeout(update, 1000);
view.SetTimeout(callback, 1000);
view.setTimeOut(callback, 1000);
view.SetTimeOut(callback, 1000);
view.setTimeout(callback, 1000); //setTimeout is the proper capitalization.

Note: Google Gadgets for Mac checks for common capitalization mistakes and corrects them. However, it can't catch every mistake.

Avoid JScript-only features

JScript features such as collections and (with one exception) ActiveXObject work only on Windows. You can find a partial list of JScript-only features by searching for microsoft jscript "not compliant".

Example:

If you have code that uses collections syntax, change it to use an accessor method such as putValue().

options("foo") = "bar"; //Collections syntax is BAD.
options.putValue("foo", "bar"); //GOOD!

Use the standard JavaScript APIs

Use the core JavaScript API, the standard XMLHttpRequest class, and the W3C Level 1 DOM. Avoid IE-specific DOM extensions, just as if you were writing a multi-browser web application. Also avoid non-standard properties such as parseError.

Exceptions: You can load images using the responseStream property of an XMLHttpRequest, as described later. You can also use the JScript Enumerator object.

One common problem that causes gadgets to fail on the Mac is using the text property of Node. Instead, use a standard property such as the XMLHttpRequest properties responseText and responseXML.

Example:

req = new XMLHttpRequest();
req.onreadystatechange = processXML;
req.open("GET", url, true);
req.send();
  
function processXML() {
  if (req.readyState == 4) { //request is finished
    if (req.status == 200) { //and successful
      var result = req.text; //text property is Windows only (BAD!)
      var result = req.responseText; //standard properties are GOOD
    }
  }
}

The one exception to the rule of avoiding IE-specific DOM extensions is that you can use a limited form of the responseStream property in an XMLHttpRequest. Specifically, although you can't use any of the Windows stream class methods, you can use the responseStream property with framework.graphics.loadImage() and img.src.

Example:

//responseStream is OK only for getting image data.
imageRequest = new XMLHttpRequest();
//... get the data and confirm it's good. Then:
image.src = imageRequest.responseStream; //use image data

Finally, the isArray() method is not standard JavaScript. To detect whether an array contains any entries, use standard JavaScript instead.

Example:

found = someString.match(expr);
if (!isArray(found)) { //BAD: breaks on Mac
if (found == null || !found.length) { //GOOD: cross-platform 

Back to top

Avoid Windows-specific APIs

If you must use Windows-specific APIs to write your gadget, go ahead. Just be sure to mark your gadget as Windows only, and please post to the developer group if a change to the Google Desktop APIs would allow your gadget to be cross-platform.

Don't rely on Google Talk

Desktop gadgets communicate with other gadget instances using the googleTalk object, but Google Talk is supported only on Windows. If your gadget absolutely needs Google Talk to work, mark your gadget as Windows only. If Google Talk isn't always essential for your gadget's operation, then make sure your gadget behaves well when Google Talk is unavailable.

The googleTalk object is present on Mac, but it doesn't do anything. Friends always appear to be offline, and any data that's "sent" doesn't actually go anywhere.

Don't use framework.system.perfmon

Much of the information returned by the Windows-specific framework.system.perfmon object is available through platform-independent API. For example, to get information about system memory, use the framework.system.memory object instead of perfmon.

Don't rely on any other Windows-only Google Desktop API

Cross-platform gadgets cannot count on having access to any Google Desktop API that's marked as "Windows only" in the API reference documentation. Besides the Google Talk and perfmon interfaces, the major APIs that aren't supported for the Mac are the Query API and the Event API.

Note: For the first release of gadgets for the Mac, don't use any API introduced in Google Desktop for Windows 5.5. The 1.0 Mac gadgets API is equivalent to the Google Desktop for Windows 5.1 API, with no support for any API added in 5.5.

Don't use DLLs

Gadgets that use native libraries such as DLLs are known as hybrid gadgets. A hybrid gadget can't be cross-platform.

Don't use ActiveX

With one exception, cross-platform gadgets cannot use ActiveXObject. The exception is that you can use the following code to open a URL in an external web browser.

//The ONLY acceptable use of ActiveXObject in a cross-platform
//gadget is opening a URL in a browser.
var foo = new ActiveXObject('WScript.Shell');
foo.run(someURL);

Back to top

Avoid features that Dashboard doesn't support

Desktop gadgets run as widgets within the Dashboard application. This integration with Dashboard has two major consequences for Desktop gadgets:

  • Gadgets are subject to security restrictions imposed by Dashboard.
  • Gadgets appear and execute only when Dashboard is showing. The user shows Dashboard by pressing F12 or clicking the Dashboard icon. When Dashboard is showing, it overlays the user's desktop, permitting the user to interact only with widgets. The user returns to the desktop by pressing F12 or Esc, or by clicking anywhere that's not a widget.

For your gadget to not only run, but to be useful on the Mac, follow these guidelines.

Don't rely on drag and drop

Dashboard doesn't support drag or drop operations, so make sure your gadget has another way for the user to set its data.

Don't rely on file system access

For security reasons, Dashboard doesn't allow Desktop gadgets to have read or write file system access. The result is that function calls such as gadget.storage.extract(), framework.system.getFileIcon(), framework.BrowseForFile(), and framework.BrowseForFiles() don't work on the Mac. If a gadget tries to browse the file system, an error sheet shows up, stating that file browsing isn't allowed.

Note: Your gadget has access to all files inside its .gg archive.

Don't connect or disconnect wireless

For security reasons, you can't invoke the framework.system.network.wireless.connect() and framework.system.network.wireless.disconnect() methods.

Don't rely on mouse-down event timing

In Dashboard, a dragged gadget doesn't fire a mouse-down event until just before the mouse-up event. As a consequence, a gadget that performs animation on mouse-down on Windows might have no visible animation on the Mac.

Don't rely on the gadget always executing or being visible

Gadgets that rely on continual execution typically don't work well on the Mac. For example, a gadget that uses a continuously running timer, instead of the system clock, might have problems because the timer can't execute when Dashboard is hidden.

Gadgets that attempt to notify the user of events are also doomed to failure on the Mac, since a gadget can't make itself run or appear.

Back to top

Isolate any platform-specific code

A gadget can have platform-specific code if you isolate that code, executing it only when the gadget is running on the relevant platform. To detect the platform, you can use the framework.system.machine.manufacturer property, which returns "Apple" if the gadget is running on a Mac.

Note: For the first release of Google Gadgets for Mac, don't use the framework.runtime.osName property or any other API introduced in Google Desktop for Windows 5.5. The 1.0 Mac gadgets API is equivalent to the Google Desktop for Windows 5.1 API, with no support for any API added in 5.5.

Example:

function onMac() {
  return (framework.system.machine.manufacturer == "Apple");
}
...
if (onMac()) {
  //mac code goes here
} else {
  //win code goes here
}

Back to top

Test the gadget

Even if your gadget breaks some cross-platform rules, it might still work everywhere, thanks to Google Gadgets for Mac's automatic correction of common problems. Testing your gadget is the only sure way to be sure that it works on both Windows and Mac. If you don't have access to a Mac, consider asking the developer group for testing help.

Run the gadget on the Mac

To run your gadget on the Mac, just open the gadget's .gg archive by double-clicking or downloading it. Google Gadgets for Mac automatically converts the gadget into a Dashboard widget, adds it to Dashboard, and shows Dashboard.

Optional: Tweak the gadget on the Mac

When you run your gadget, you might discover some flaws that you can fix by hand editing the gadget's files. Here's how you can change your gadget and run the new version on the Mac without rebuilding the gadget's .gg file.

  1. If you haven't already run the most recent version of your gadget in Dashboard, do so by double-clicking or downloading the gadget's .gg archive. The gadget is converted to a widget and appears in Dashboard. Press F12 or click the background to hide Dashboard.
  2. Under your home folder, go to the Library/Widgets folder. Find the .wdgt package that corresponds to your gadget.
  3. Ctrl-click your gadget's .wdgt package and choose Show Package Contents. A Finder window appears that contains several files, including an archive named gadget.gg that contains the Google Desktop files for your gadget.
  4. Create a copy of the gadget.gg file and unzip it. You can unzip it by renaming the copy to gadget.zip and double-clicking it.
  5. Hide the original gadget.gg file by renaming it to gadget.gg.orig..
  6. Rename the unzipped folder (gadget) to gadget.gg.
  7. Open the gadget.gg folder. Although you can edit any of the files under this folder, first go to the next step to confirm that you can load a new copy of the existing gadget.
  8. Press F12, and then click the + sign at the bottom left to bring up the gadget bar in Dashboard. Click the icon in the gadget bar that corresponds to your gadget. A new copy of your gadget appears.
  9. Test your gadget. Once you've finished, hide Dashboard by clicking the background or pressing F12.
  10. Modify your gadget's files however you like — for example, you can edit the .js or .xml files under the gadget.gg folder.

Repeat steps 8 through 10 as necessary. Once you've finished making changes, copy the changed files to your gadget's project folder and rebuild your gadget's .gg file. Be sure to test the new .gg file by opening it on both Windows and the Mac.

Back to top

Specify supported platforms

To specify the platforms your gadget works with, use the <platform> tag in the gadget manifest file. To allow pre-5.5 versions of Google Desktop for Windows to read the version, you also need to specify the minimumGoogleDesktopVersion attribute of the gadget tag.

Windows and Mac

If you know that your gadget works on both Windows and Mac, specify minimumGadgetHostVersion attributes for both the windows and mac tags.

<gadget minimumGoogleDesktopVersion="5.1.0.0">
  <platform>
    <windows minimumGadgetHostVersion="5.1.0.0"/>
    <mac minimumGadgetHostVersion="1.0.0.0"/>
  </platform>
  ...
</gadget>

Windows only

If you're sure that your gadget doesn't work on Mac, specify <mac supported="no"/>.

<gadget minimumGoogleDesktopVersion="5.1.0.0">
  <platform>
    <windows minimumGadgetHostVersion="5.1.0.0"/>
    <mac supported="no"/>
  </platform>
  ...
</gadget>

Windows and maybe Mac

If you're not sure whether your gadget works on Mac, don't specify a <mac> tag.

<gadget minimumGoogleDesktopVersion="5.1.0.0">
  <platform>
    <windows minimumGadgetHostVersion="5.1.0.0"/>
  </platform>
  ...
</gadget>

Back to top