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:
parent
0bac2c0150
commit
3bc0bfe8c3
@ -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"/>
|
||||
|
||||
@ -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 );
|
||||
|
||||
@ -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...">
|
||||
|
||||
@ -28,6 +28,13 @@ REQUIRES = xpcom \
|
||||
intl \
|
||||
appshell \
|
||||
necko \
|
||||
layout \
|
||||
content \
|
||||
widget \
|
||||
imglib2 \
|
||||
gfx \
|
||||
gfx2 \
|
||||
locale \
|
||||
$(NULL)
|
||||
DEPTH=..\..\..
|
||||
|
||||
|
||||
@ -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++
|
||||
|
||||
@ -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"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user