sbMacWindowTitlebarService.mm
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 :miv */
3 /*
4  *=BEGIN SONGBIRD GPL
5  *
6  * This file is part of the Songbird web player.
7  *
8  * Copyright(c) 2005-2010 POTI, Inc.
9  * http://www.songbirdnest.com
10  *
11  * This file may be licensed under the terms of of the
12  * GNU General Public License Version 2 (the ``GPL'').
13  *
14  * Software distributed under the License is distributed
15  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
16  * express or implied. See the GPL for the specific language
17  * governing rights and limitations.
18  *
19  * You should have received a copy of the GPL along with this
20  * program. If not, go to http://www.gnu.org/licenses/gpl.html
21  * or write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  *
24  *=END SONGBIRD GPL
25  */
26 
27 //------------------------------------------------------------------------------
28 //------------------------------------------------------------------------------
29 //
30 // Songbird Mac window titlebar service.
31 //
32 //------------------------------------------------------------------------------
33 //------------------------------------------------------------------------------
34 
40 //------------------------------------------------------------------------------
41 //
42 // Songbird Mac window titlebar imported services.
43 //
44 //------------------------------------------------------------------------------
45 
46 // Self imports.
48 
49 // Local imports.
50 #include "../NativeWindowFromNode.h"
51 
52 // Songbird imports.
53 #include <sbFileUtils.h>
54 
55 // Mozilla imports.
56 #include <nsColor.h>
57 #include <nsICategoryManager.h>
58 #include <nsIDOMDocument.h>
59 #include <nsIDOMElement.h>
60 #include <nsIDOMWindow.h>
61 #include <nsIWindowWatcher.h>
62 #include <nsNetUtil.h>
63 #include <nsServiceManagerUtils.h>
64 #include <nsStringGlue.h>
65 
66 // Mac OS/X imports.
67 #include <objc/objc-runtime.h>
68 
69 
70 //------------------------------------------------------------------------------
71 //
72 // Internal Songbird Mac window titlebar services prototypes.
73 //
74 //------------------------------------------------------------------------------
75 
76 static nsresult GetDOMWindowFromNativeWindow(NATIVEWINDOW aNativeWindow,
77  nsIDOMWindow** aDOMWindow);
78 
79 static nsresult GetSBTitlebarColor(NSWindow* aWindow,
80  NSColor** aColor);
81 
82 static nsresult GetSBTitlebarImage(NSWindow* aWindow,
83  NSImage** aImage);
84 
85 static nsresult GetSBTitlebarTextColor(NSWindow* aWindow,
86  NSColor** aColor);
87 
88 static nsresult GetWindowAttribute(NSWindow* aWindow,
89  const nsAString& aAttributeName,
90  nsAString& aAttributeValue);
91 
92 static nsresult GetWindowAttribute(NSWindow* aWindow,
93  const nsAString& aAttributeName,
94  NSColor** aColor);
95 
96 static nsresult GetWindowAttribute(NSWindow* aWindow,
97  const nsAString& aAttributeName,
98  NSImage** aImage);
99 
100 static NSImage* GetImageFromURL(const nsAString& aImageURL);
101 
102 static PRBool SBParseColor(const nsAString& aColorString,
103  nscolor* aColor);
104 
105 
106 //------------------------------------------------------------------------------
107 //
108 // Songbird Mac window titlebar service nsISupports implementation.
109 //
110 //------------------------------------------------------------------------------
111 
113 
114 
115 //------------------------------------------------------------------------------
116 //
117 // Songbird Mac window titlebar service public services.
118 //
119 //------------------------------------------------------------------------------
120 
121 //-------------------------------------
122 //
123 // sbMacWindowTitlebarService
124 //
125 
127  mInitialized(PR_FALSE)
128 {
129 }
130 
131 
132 //-------------------------------------
133 //
134 // ~sbMacWindowTitlebarService
135 //
136 
138 {
139  // Finalize the Songbird Mac window titlebar service.
140  Finalize();
141 }
142 
143 
144 //-------------------------------------
145 //
146 // RegisterSelf
147 //
148 
149 /* static */ NS_METHOD
151  RegisterSelf(nsIComponentManager* aCompMgr,
152  nsIFile* aPath,
153  const char* aLoaderStr,
154  const char* aType,
155  const nsModuleComponentInfo* aInfo)
156 {
157  nsresult rv;
158 
159  // Get the category manager.
160  nsCOMPtr<nsICategoryManager> categoryManager =
161  do_GetService(NS_CATEGORYMANAGER_CONTRACTID,
162  &rv);
163  NS_ENSURE_SUCCESS(rv, rv);
164 
165  // Add self to the application startup category.
166  rv = categoryManager->AddCategoryEntry
167  ("app-startup",
170  PR_TRUE,
171  PR_TRUE,
172  nsnull);
173  NS_ENSURE_SUCCESS(rv, rv);
174 
175  return NS_OK;
176 }
177 
178 
179 /* static */ NS_METHOD
181  UnregisterSelf(nsIComponentManager* aCompMgr,
182  nsIFile* aPath,
183  const char* aLoaderStr,
184  const nsModuleComponentInfo* aInfo)
185 {
186  nsresult rv;
187 
188  // Get the category manager.
189  nsCOMPtr<nsICategoryManager> categoryManager =
190  do_GetService(NS_CATEGORYMANAGER_CONTRACTID,
191  &rv);
192  NS_ENSURE_SUCCESS(rv, rv);
193 
194  // Delete self from the application startup category.
195  rv = categoryManager->DeleteCategoryEntry
196  ("app-startup",
198  PR_TRUE);
199  NS_ENSURE_SUCCESS(rv, rv);
200 
201  return NS_OK;
202 }
203 
204 
205 //-------------------------------------
206 //
207 // Initialize
208 //
209 
210 nsresult
212 {
213  // Do nothing if already initialized.
214  if (mInitialized)
215  return NS_OK;
216 
217  // Get the original, Songbird, and placeholder versions of the
218  // NSGrayFrame drawRect: method.
219  Method origMethod = class_getInstanceMethod([NSGrayFrame class],
220  @selector(drawRect:));
221  Method sbMethod = class_getInstanceMethod([NSGrayFrame class],
222  @selector(_sbDrawRect:));
223  Method origPlaceholderMethod =
224  class_getInstanceMethod([NSGrayFrame class], @selector(_sbOrigDrawRect:));
225 
226  // Replace the original placeholder method with the original method and
227  // replace the original method with the Songbird method.
228  origPlaceholderMethod->method_imp = origMethod->method_imp;
229  origMethod->method_imp = sbMethod->method_imp;
230 
231  // Services are now initialized.
232  mInitialized = PR_TRUE;
233 
234  return NS_OK;
235 }
236 
237 
238 //-------------------------------------
239 //
240 // Finalize
241 //
242 
243 void
245 {
246  // Do nothing if not initialized.
247  if (!mInitialized)
248  return;
249 
250  // Get the original and placeholder versions of the NSGrayFrame drawRect:
251  // method.
252  Method origMethod = class_getInstanceMethod([NSGrayFrame class],
253  @selector(drawRect:));
254  Method origPlaceholderMethod = class_getInstanceMethod
255  ([NSGrayFrame class],
256  @selector(_sbOrigDrawRect:));
257 
258  // Restore the original method from the original placeholder method.
259  origMethod->method_imp = origPlaceholderMethod->method_imp;
260 
261  // No longer initialized.
262  mInitialized = PR_FALSE;
263 }
264 
265 
266 //------------------------------------------------------------------------------
267 //
268 // Songbird Mac window titlebar NSGrayFrame services.
269 //
270 //------------------------------------------------------------------------------
271 
272 @implementation NSGrayFrame (SBGrayFrame)
273 
274 - (void)_sbDrawRect:(NSRect)aDirtyRect
275 {
276  // Let original method draw.
277  [self _sbOrigDrawRect: aDirtyRect];
278 
279  // Fill titlebar with the Songbird titlebar color. Only draw where the
280  // titlebar is opaque to preserve rounded corners.
281  NSColor* titlebarColor = nil;
282  GetSBTitlebarColor([self window], &titlebarColor);
283  if (titlebarColor) {
284  [titlebarColor set];
285  NSRectFillUsingOperation([self titlebarRect], NSCompositeSourceIn);
286  }
287 
288  // Fill the titlebar with the Songbird titlebar image. Only draw where the
289  // titlebar is opaque to preserve rounded corners. Draw using
290  // NSCompositeSourceAtop so that a translucent gradient image may be applied
291  // over the titlebar color.
292  NSImage* titlebarImage = nil;
293  GetSBTitlebarImage([self window], &titlebarImage);
294  if (titlebarImage) {
295  // Set the image pattern to start at the top of the titlebar.
296  NSGraphicsContext* currentContext = [NSGraphicsContext currentContext];
297  float titlebarTop = [self titlebarRect].origin.y +
298  [self titlebarRect].size.height;
299  [currentContext saveGraphicsState];
300  [currentContext setPatternPhase: NSMakePoint(0, titlebarTop)];
301 
302  // Fill titlebar with the image.
303  [[NSColor colorWithPatternImage: titlebarImage] set];
304  NSRectFillUsingOperation([self titlebarRect], NSCompositeSourceAtop);
305 
306  // Restore the graphics state.
307  [currentContext restoreGraphicsState];
308  }
309 
310  // Get the titlebar text color.
311  NSColor* textColor = nil;
312  GetSBTitlebarTextColor([self window], &textColor);
313 
314  // Draw the titlebar text in the Songbird color.
315  if (textColor) {
316  // Get the default sized titlebar font.
317  NSFont *titleFont = [NSFont titleBarFontOfSize:0];
318 
319  // Get the titlebar paragraph style.
320  NSMutableParagraphStyle
321  *paraStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
322  [paraStyle setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]];
323  [paraStyle setAlignment:NSCenterTextAlignment];
324  [paraStyle setLineBreakMode:NSLineBreakByTruncatingTail];
325 
326  // Set up the title attributes.
327  NSMutableDictionary *titleAttrs =
328  [NSMutableDictionary dictionaryWithObjectsAndKeys:
329  titleFont, NSFontAttributeName,
330  textColor, NSForegroundColorAttributeName,
331  [[paraStyle copy] autorelease], NSParagraphStyleAttributeName,
332  nil];
333 
334  // Draw the title.
335  [[[self window] title] drawInRect: [self _titlebarTitleRect]
336  withAttributes: titleAttrs];
337  }
338 }
339 
340 - (void)_sbOrigDrawRect:(NSRect)aDirtyRect
341 {
342 }
343 
344 @end
345 
346 
347 //------------------------------------------------------------------------------
348 //
349 // Internal Songbird Mac window titlebar services.
350 //
351 //------------------------------------------------------------------------------
352 
365 nsresult
367  nsIDOMWindow** aDOMWindow)
368 {
369  // Validate arguments.
370  NS_ENSURE_ARG_POINTER(aDOMWindow);
371 
372  // Function variables.
373  nsresult rv;
374 
375  // Get the list of DOM windows.
376  nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
377  nsCOMPtr<nsIWindowWatcher>
378  windowWatcher = do_GetService("@mozilla.org/embedcomp/window-watcher;1",
379  &rv);
380  NS_ENSURE_SUCCESS(rv, rv);
381  rv = windowWatcher->GetWindowEnumerator(getter_AddRefs(windowEnumerator));
382  NS_ENSURE_SUCCESS(rv, rv);
383 
384  // Search for the DOM window corresponding to the native window.
385  while (1) {
386  // Get the next DOM window. Break from loop if no more windows.
387  nsCOMPtr<nsISupports> domWindow;
388  PRBool hasMoreElements;
389  rv = windowEnumerator->HasMoreElements(&hasMoreElements);
390  NS_ENSURE_SUCCESS(rv, rv);
391  if (!hasMoreElements)
392  break;
393  rv = windowEnumerator->GetNext(getter_AddRefs(domWindow));
394  NS_ENSURE_SUCCESS(rv, rv);
395 
396  // Get the native window corresponding to the DOM window.
397  NATIVEWINDOW nativeWindow = NativeWindowFromNode::get(domWindow);
398 
399  // Return with result if DOM window corresponds to the specified native
400  // window.
401  if (nativeWindow == aNativeWindow) {
402  rv = CallQueryInterface(domWindow, aDOMWindow);
403  NS_ENSURE_SUCCESS(rv, rv);
404  return NS_OK;
405  }
406  }
407 
408  return NS_ERROR_NOT_AVAILABLE;
409 }
410 
411 
421 nsresult
422 GetSBTitlebarColor(NSWindow* aWindow,
423  NSColor** aColor)
424 {
425  // Validate arguments.
426  NS_ENSURE_ARG_POINTER(aWindow);
427  NS_ENSURE_ARG_POINTER(aColor);
428 
429  // Function variables.
430  nsresult rv;
431 
432  // Get the titlebar color.
433  if ([aWindow isKeyWindow]) {
434  rv = GetWindowAttribute(aWindow,
435  NS_LITERAL_STRING("activetitlebarcolor"),
436  aColor);
437  NS_ENSURE_SUCCESS(rv, rv);
438  }
439  else {
440  rv = GetWindowAttribute(aWindow,
441  NS_LITERAL_STRING("inactivetitlebarcolor"),
442  aColor);
443  NS_ENSURE_SUCCESS(rv, rv);
444  }
445 
446  return NS_OK;
447 }
448 
449 
459 nsresult
460 GetSBTitlebarImage(NSWindow* aWindow,
461  NSImage** aImage)
462 {
463  // Validate arguments.
464  NS_ENSURE_ARG_POINTER(aWindow);
465  NS_ENSURE_ARG_POINTER(aImage);
466 
467  // Function variables.
468  nsresult rv;
469 
470  // Get the titlebar image.
471  if ([aWindow isKeyWindow]) {
472  rv = GetWindowAttribute(aWindow,
473  NS_LITERAL_STRING("activetitlebarimage"),
474  aImage);
475  NS_ENSURE_SUCCESS(rv, rv);
476  }
477  else {
478  rv = GetWindowAttribute(aWindow,
479  NS_LITERAL_STRING("inactivetitlebarimage"),
480  aImage);
481  NS_ENSURE_SUCCESS(rv, rv);
482  }
483 
484  return NS_OK;
485 }
486 
487 
497 nsresult
498 GetSBTitlebarTextColor(NSWindow* aWindow,
499  NSColor** aColor)
500 {
501  // Validate arguments.
502  NS_ENSURE_ARG_POINTER(aWindow);
503  NS_ENSURE_ARG_POINTER(aColor);
504 
505  // Function variables.
506  nsresult rv;
507 
508  // Get the titlebar color.
509  if ([aWindow isKeyWindow]) {
510  rv = GetWindowAttribute(aWindow,
511  NS_LITERAL_STRING("activetitlebartextcolor"),
512  aColor);
513  NS_ENSURE_SUCCESS(rv, rv);
514  }
515  else {
516  rv = GetWindowAttribute(aWindow,
517  NS_LITERAL_STRING("inactivetitlebartextcolor"),
518  aColor);
519  NS_ENSURE_SUCCESS(rv, rv);
520  }
521 
522  return NS_OK;
523 }
524 
525 
535 nsresult
536 GetWindowAttribute(NSWindow* aWindow,
537  const nsAString& aAttributeName,
538  nsAString& aAttributeValue)
539 {
540  // Validate arguments.
541  NS_ENSURE_ARG_POINTER(aWindow);
542 
543  // Function variables.
544  nsresult rv;
545 
546  // Default to no attribute value.
547  aAttributeValue.Truncate();
548 
549  // Get the DOM window from the native window. Return no value if no DOM
550  // window.
551  nsCOMPtr<nsIDOMWindow> domWindow;
552  rv = GetDOMWindowFromNativeWindow(aWindow, getter_AddRefs(domWindow));
553  if (rv == NS_ERROR_NOT_AVAILABLE)
554  return NS_OK;
555  NS_ENSURE_SUCCESS(rv, rv);
556 
557  // Get the DOM window document element.
558  nsCOMPtr<nsIDOMElement> documentElement;
559  nsCOMPtr<nsIDOMDocument> document;
560  rv = domWindow->GetDocument(getter_AddRefs(document));
561  NS_ENSURE_SUCCESS(rv, rv);
562  rv = document->GetDocumentElement(getter_AddRefs(documentElement));
563  NS_ENSURE_SUCCESS(rv, rv);
564 
565  // Get the attribute.
566  rv = documentElement->GetAttribute(aAttributeName, aAttributeValue);
567  NS_ENSURE_SUCCESS(rv, rv);
568 
569  return NS_OK;
570 }
571 
572 
582 nsresult
583 GetWindowAttribute(NSWindow* aWindow,
584  const nsAString& aAttributeName,
585  NSColor** aColor)
586 {
587  // Validate arguments.
588  NS_ENSURE_ARG_POINTER(aWindow);
589  NS_ENSURE_ARG_POINTER(aColor);
590 
591  // Function variables.
592  nsresult rv;
593 
594  // Default to no color.
595  *aColor = nil;
596 
597  // Get the color string.
598  nsAutoString colorString;
599  rv = GetWindowAttribute(aWindow, aAttributeName, colorString);
600  NS_ENSURE_SUCCESS(rv, rv);
601  if (colorString.IsEmpty())
602  return NS_OK;
603 
604  // Convert the color string to an nscolor.
605  nscolor color = 0;
606  if (!SBParseColor(colorString, &color))
607  return NS_OK;
608 
609  // Return results.
610  *aColor = [NSColor colorWithDeviceRed:NS_GET_R(color)/255.0
611  green:NS_GET_G(color)/255.0
612  blue:NS_GET_B(color)/255.0
613  alpha:NS_GET_A(color)/255.0];
614 
615  return NS_OK;
616 }
617 
618 
628 nsresult
629 GetWindowAttribute(NSWindow* aWindow,
630  const nsAString& aAttributeName,
631  NSImage** aImage)
632 {
633  // Validate arguments.
634  NS_ENSURE_ARG_POINTER(aWindow);
635  NS_ENSURE_ARG_POINTER(aImage);
636 
637  // Function variables.
638  nsresult rv;
639 
640  // Default to no image.
641  *aImage = nil;
642 
643  // Get the image URL.
644  nsAutoString imageURL;
645  rv = GetWindowAttribute(aWindow, aAttributeName, imageURL);
646  NS_ENSURE_SUCCESS(rv, rv);
647  if (imageURL.IsEmpty())
648  return NS_OK;
649 
650  // Return results.
651  *aImage = GetImageFromURL(imageURL);
652 
653  return NS_OK;
654 }
655 
656 
665 NSImage*
666 GetImageFromURL(const nsAString& aImageURL)
667 {
668  nsresult rv;
669 
670  // Get the image URI.
671  nsCOMPtr<nsIURI> imageURI;
672  rv = NS_NewURI(getter_AddRefs(imageURI), aImageURL);
673  NS_ENSURE_SUCCESS(rv, nil);
674 
675  // Open an image input stream.
676  nsCOMPtr<nsIInputStream> sourceStream;
677  rv = NS_OpenURI(getter_AddRefs(sourceStream), imageURI);
678  NS_ENSURE_SUCCESS(rv, nil);
679  sbAutoInputStream autoSourceStream(sourceStream);
680 
681  // Read the image data.
682  nsCString data;
683  rv = sbConsumeStream(sourceStream, 0xFFFFFFFF, data);
684  NS_ENSURE_SUCCESS(rv, nil);
685 
686  // Create the image object.
687  NSData *dataWrapper = [NSData dataWithBytes:data.BeginReading()
688  length:data.Length()];
689  NSImage *image = [[[NSImage alloc] initWithData:dataWrapper] autorelease];
690 
691  return image;
692 }
693 
694 
705 PRBool
706 SBParseColor(const nsAString& aColorString,
707  nscolor* aColor)
708 {
709  // Validate arguments.
710  NS_ENSURE_ARG_POINTER(aColor);
711 
712  // Function variables.
713  nsresult rv;
714 
715  // Get the color string and remove the leading "#".
716  nsAutoString colorString(aColorString);
717  colorString.Trim("#", PR_TRUE, PR_FALSE);
718 
719  // Convert color string to an integer.
720  PRUint32 color32 = colorString.ToInteger(&rv, 16);
721  if (NS_FAILED(rv))
722  return PR_FALSE;
723 
724  // Return results.
725  *aColor = NS_RGBA((color32 >> 16) & 0xFF,
726  (color32 >> 8) & 0xFF,
727  color32 & 0xFF,
728  255);
729 
730  return PR_TRUE;
731 }
732 
static nsresult GetWindowAttribute(NSWindow *aWindow, const nsAString &aAttributeName, nsAString &aAttributeValue)
NS_IMPL_THREADSAFE_ISUPPORTS0(sbMetadataCrashTracker)
void _sbOrigDrawRect:(NSRect aDirtyRect)
return NS_OK
_updateCookies aPath
static nsresult GetSBTitlebarImage(NSWindow *aWindow, NSImage **aImage)
static PRBool SBParseColor(const nsAString &aColorString, nscolor *aColor)
static NS_METHOD UnregisterSelf(nsIComponentManager *aCompMgr, nsIFile *aPath, const char *aLoaderStr, const nsModuleComponentInfo *aInfo)
static nsresult GetSBTitlebarColor(NSWindow *aWindow, NSColor **aColor)
static NS_METHOD RegisterSelf(nsIComponentManager *aCompMgr, nsIFile *aPath, const char *aLoaderStr, const char *aType, const nsModuleComponentInfo *aInfo)
static NSImage * GetImageFromURL(const nsAString &aImageURL)
let window
const nsIDOMWindow
nsresult sbConsumeStream(nsIInputStream *stream, PRUint32 maxCount, nsACString &result)
#define SB_MAC_WINDOW_TITLEBAR_SERVICE_CLASSNAME
static void * get(nsISupports *window)
NSRect titlebarRect()
#define SB_MAC_WINDOW_TITLEBAR_SERVICE_CONTRACTID
SimpleArrayEnumerator prototype hasMoreElements
#define NATIVEWINDOW
static nsresult GetDOMWindowFromNativeWindow(void *aNativeWindow, nsIDOMWindow **aDOMWindow)
static nsresult GetSBTitlebarTextColor(NSWindow *aWindow, NSColor **aColor)
Songbird Mac Window Titlebar Service Definitions.
NSRect _titlebarTitleRect()
observe data
Definition: FeedWriter.js:1329