41526 - implement 'Set As Wallpaper' on windows, r=pavlov, sr=blake

git-svn-id: svn://10.0.0.236/trunk@114907 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
hewitt%netscape.com 2002-02-19 08:12:22 +00:00
parent 0bac2c0150
commit 3bc0bfe8c3
6 changed files with 187 additions and 0 deletions

View File

@ -141,6 +141,9 @@
<menuitem id="context-saveimage"
accesskey="&saveImageCmd.accesskey;"
oncommand="gContextMenu.saveImage();"/>
<menuitem id="context-setWallpaper"
label="&setWallpaperCmd.label;"
oncommand="gContextMenu.setWallpaper();"/>
<menuseparator id="context-sep-save"/>
<!-- Application Integration ================= -->
<menuseparator id="context-sep-apps"/>

View File

@ -145,6 +145,9 @@ nsContextMenu.prototype = {
// View Frame Info depends on whether we're in a frame
this.showItem( "context-viewframeinfo", this.inFrame );
// Set As Wallpaper depends on whether an image was clicked on, and only works on Windows.
this.showItem( "context-setWallpaper", this.onImage && navigator.appVersion.indexOf("Windows") != -1);
// View Image depends on whether an image was clicked on.
this.showItem( "context-viewimage", this.onImage );
@ -483,6 +486,12 @@ nsContextMenu.prototype = {
viewBGImage : function () {
openTopWin( this.bgImageURL );
},
setWallpaper: function() {
var winhooks = Components.classes[ "@mozilla.org/winhooks;1" ].
getService(Components.interfaces.nsIWindowsHooks);
winhooks.setImageAsWallpaper(this.target, false);
},
// Save URL of clicked-on frame.
saveFrame : function () {
saveDocument( this.target.ownerDocument );

View File

@ -34,6 +34,7 @@
<!ENTITY viewImageCmd.accesskey "w">
<!ENTITY viewBGImageCmd.label "View Background Image">
<!ENTITY viewBGImageCmd.accesskey "w">
<!ENTITY setWallpaperCmd.label "Set As Wallpaper">
<!ENTITY bookmarkPageCmd.label "Bookmark this Page">
<!ENTITY bookmarkPageCmd.accesskey "b">
<!ENTITY bookmarkLinkCmd.label "File Bookmark for Link...">

View File

@ -28,6 +28,13 @@ REQUIRES = xpcom \
intl \
appshell \
necko \
layout \
content \
widget \
imglib2 \
gfx \
gfx2 \
locale \
$(NULL)
DEPTH=..\..\..

View File

@ -107,6 +107,7 @@
*/
interface nsIDOMWindowInternal;
interface nsIDOMElement;
/* nsIWindowsHooksSettings
*
@ -189,6 +190,13 @@ interface nsIWindowsHooks : nsISupports {
* if not done already.
*/
void startupTurboDisable();
/**
* Accepts an element, either an HTML img element or an element with
* a background image, serializes the image to a bitmap file
* in the windows directory, and sets it to be the desktop wallpaper.
*/
void setImageAsWallpaper(in nsIDOMElement aImageElement, in boolean useBackground);
};
%{C++

View File

@ -62,6 +62,20 @@
#include <shlobj.h>
#include <shlguid.h>
// for set as wallpaper
#include "nsIDocument.h"
#include "nsIContent.h"
#include "nsIDOMElement.h"
#include "nsIDOMDocument.h"
#include "nsIFrame.h"
#include "nsIPresShell.h"
#include "nsIImageFrame.h"
#include "imgIRequest.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsIFileStream.h"
#include "nsFileSpec.h"
// Objects that describe the Windows registry entries that we need to tweak.
static ProtocolRegistryEntry
http( "http" ),
@ -684,6 +698,151 @@ NS_IMETHODIMP nsWindowsHooks::StartupTurboDisable()
return NS_OK;
}
nsresult
WriteBitmap(nsString& aPath, gfxIImageFrame* aImage)
{
PRInt32 width, height;
aImage->GetWidth(&width);
aImage->GetHeight(&height);
PRUint8* bits;
PRUint32 length;
aImage->GetImageData(&bits, &length);
if (!bits) return NS_ERROR_FAILURE;
PRUint32 bpr;
aImage->GetImageBytesPerRow(&bpr);
PRInt32 bitCount = bpr/width;
// initialize these bitmap structs which we will later
// serialize directly to the head of the bitmap file
LPBITMAPINFOHEADER bmi = (LPBITMAPINFOHEADER)new BITMAPINFO;
bmi->biSize = sizeof(BITMAPINFOHEADER);
bmi->biWidth = width;
bmi->biHeight = height;
bmi->biPlanes = 1;
bmi->biBitCount = (WORD)bitCount*8;
bmi->biCompression = BI_RGB;
bmi->biSizeImage = 0; // don't need to set this if bmp is uncompressed
bmi->biXPelsPerMeter = 0;
bmi->biYPelsPerMeter = 0;
bmi->biClrUsed = 0;
bmi->biClrImportant = 0;
BITMAPFILEHEADER bf;
bf.bfType = 0x4D42; // 'BM'
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bf.bfSize = bf.bfOffBits + bmi->biSizeImage;
// get a file output stream
nsFileSpec path(aPath);
nsCOMPtr<nsISupports> streamSupports;
NS_NewTypicalOutputFileStream(getter_AddRefs(streamSupports), path);
nsCOMPtr<nsIOutputStream> stream = do_QueryInterface(streamSupports);
// write the bitmap headers and rgb pixel data to the file
nsresult rv = NS_ERROR_FAILURE;
PRUint32 written;
stream->Write((const char*)&bf, sizeof(BITMAPFILEHEADER), &written);
if (written == sizeof(BITMAPFILEHEADER)) {
stream->Write((const char*)bmi, sizeof(BITMAPINFOHEADER), &written);
if (written == sizeof(BITMAPINFOHEADER)) {
stream->Write((const char*)bits, length, &written);
if (written == length)
rv = NS_OK;
}
}
stream->Close();
return rv;
}
NS_IMETHODIMP
nsWindowsHooks::SetImageAsWallpaper(nsIDOMElement* aElement, PRBool aUseBackground)
{
nsresult rv;
// get the document so we can get the presShell from it
nsCOMPtr<nsIDOMDocument> domDoc;
rv = aElement->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
if (!doc) return rv;
// get the presShell so we can get the frame from it
nsCOMPtr<nsIPresShell> presShell;
rv = doc->GetShellAt(0, getter_AddRefs(presShell));
if (!presShell) return rv;
nsCOMPtr<gfxIImageFrame> gfxFrame;
if (aUseBackground) {
// XXX write background loading stuff!
} else {
// get the frame for the image element
nsIFrame* frame = nsnull;
nsCOMPtr<nsIContent> imageContent = do_QueryInterface(aElement);
rv = presShell->GetPrimaryFrameFor(imageContent, &frame);
if (!frame) return rv;
// if it was an html:img element, it will QI to nsIImageFrame
void* voidFrame;
frame->QueryInterface(NS_GET_IID(nsIImageFrame), &voidFrame);
nsIImageFrame* imageFrame = NS_STATIC_CAST(nsIImageFrame*, voidFrame);
if (!imageFrame) return NS_ERROR_FAILURE;
// get the image container
nsCOMPtr<imgIRequest> request;
rv = imageFrame->GetImageRequest(getter_AddRefs(request));
if (!request) return rv;
nsCOMPtr<imgIContainer> container;
rv = request->GetImage(getter_AddRefs(container));
if (!request) return rv;
// get the current frame, which holds the image data
container->GetCurrentFrame(getter_AddRefs(gfxFrame));
}
if (!gfxFrame)
return NS_ERROR_FAILURE;
// get the windows directory ('c:\windows' usually)
char winDir[256];
::GetWindowsDirectory(winDir, sizeof(winDir));
nsAutoString winPath;
winPath.AssignWithConversion(winDir);
// get the product brand name from localized strings
nsXPIDLString brandName;
nsCID bundleCID = NS_STRINGBUNDLESERVICE_CID;
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(bundleCID));
if (bundleService) {
nsCOMPtr<nsIStringBundle> brandBundle;
rv = bundleService->CreateBundle("chrome://global/locale/brand.properties",
getter_AddRefs(brandBundle));
if (NS_SUCCEEDED(rv) && brandBundle) {
if (NS_FAILED(rv = brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
getter_Copies(brandName))))
return rv;
}
}
// build the file name
winPath.Append(NS_LITERAL_STRING("\\").get());
winPath.Append(brandName);
winPath.Append(NS_LITERAL_STRING(" Wallpaper.bmp").get());
// write the bitmap to a file in the windows dir
rv = WriteBitmap(winPath, gfxFrame);
// if the file was written successfully, set it as the system wallpaper
if (NS_SUCCEEDED(rv))
::SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, ToNewCString(winPath), SPIF_UPDATEINIFILE);
return rv;
}
#if (_MSC_VER == 1100)
#define INITGUID
#include "objbase.h"