Browse Source

SystemTrayIconComponent support for OSX

tags/2021-05-28
jules 12 years ago
parent
commit
51df5143bf
7 changed files with 188 additions and 23 deletions
  1. +2
    -2
      extras/JuceDemo/Source/MainDemoWindow.cpp
  2. +1
    -1
      modules/juce_gui_basics/native/juce_mac_MouseCursor.mm
  3. +1
    -0
      modules/juce_gui_extra/juce_gui_extra.cpp
  4. +1
    -1
      modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.cpp
  5. +1
    -1
      modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.h
  6. +173
    -0
      modules/juce_gui_extra/native/juce_mac_SystemTrayIcon.cpp
  7. +9
    -18
      modules/juce_gui_extra/native/juce_win32_SystemTrayIcon.cpp

+ 2
- 2
extras/JuceDemo/Source/MainDemoWindow.cpp View File

@@ -565,7 +565,7 @@ private:
}; };
//============================================================================== //==============================================================================
#if JUCE_WINDOWS || JUCE_LINUX
#if JUCE_WINDOWS || JUCE_LINUX || JUCE_MAC
// Just add a simple icon to the Window system tray area.. // Just add a simple icon to the Window system tray area..
class DemoTaskbarComponent : public SystemTrayIconComponent class DemoTaskbarComponent : public SystemTrayIconComponent
@@ -633,7 +633,7 @@ MainDemoWindow::MainDemoWindow()
setVisible (true); setVisible (true);
#if JUCE_WINDOWS || JUCE_LINUX
#if JUCE_WINDOWS || JUCE_LINUX || JUCE_MAC
taskbarIcon = new DemoTaskbarComponent(); taskbarIcon = new DemoTaskbarComponent();
#endif #endif
} }


+ 1
- 1
modules/juce_gui_basics/native/juce_mac_MouseCursor.mm View File

@@ -28,7 +28,7 @@
//============================================================================== //==============================================================================
namespace MouseCursorHelpers namespace MouseCursorHelpers
{ {
static NSImage* createNSImage (const Image& image)
NSImage* createNSImage (const Image& image)
{ {
JUCE_AUTORELEASEPOOL JUCE_AUTORELEASEPOOL
{ {


+ 1
- 0
modules/juce_gui_extra/juce_gui_extra.cpp View File

@@ -111,6 +111,7 @@ namespace juce
#if JUCE_MAC #if JUCE_MAC
#include "native/juce_mac_NSViewComponent.mm" #include "native/juce_mac_NSViewComponent.mm"
#include "native/juce_mac_AppleRemote.mm" #include "native/juce_mac_AppleRemote.mm"
#include "native/juce_mac_SystemTrayIcon.cpp"
#endif #endif
#if JUCE_IOS #if JUCE_IOS


+ 1
- 1
modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.cpp View File

@@ -23,7 +23,7 @@
============================================================================== ==============================================================================
*/ */
#if JUCE_WINDOWS || JUCE_LINUX
#if JUCE_WINDOWS || JUCE_LINUX || JUCE_MAC
SystemTrayIconComponent::SystemTrayIconComponent() SystemTrayIconComponent::SystemTrayIconComponent()
{ {


+ 1
- 1
modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.h View File

@@ -26,7 +26,7 @@
#ifndef __JUCE_SYSTEMTRAYICONCOMPONENT_JUCEHEADER__ #ifndef __JUCE_SYSTEMTRAYICONCOMPONENT_JUCEHEADER__
#define __JUCE_SYSTEMTRAYICONCOMPONENT_JUCEHEADER__ #define __JUCE_SYSTEMTRAYICONCOMPONENT_JUCEHEADER__
#if JUCE_WINDOWS || JUCE_LINUX || DOXYGEN
#if JUCE_WINDOWS || JUCE_LINUX || JUCE_MAC || DOXYGEN
//============================================================================== //==============================================================================


+ 173
- 0
modules/juce_gui_extra/native/juce_mac_SystemTrayIcon.cpp View File

@@ -0,0 +1,173 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
namespace MouseCursorHelpers
{
extern NSImage* createNSImage (const Image&);
}
class SystemTrayIconComponent::Pimpl
{
public:
Pimpl (SystemTrayIconComponent& iconComp, const Image& im)
: owner (iconComp), statusItem (nil),
statusIcon (MouseCursorHelpers::createNSImage (im))
{
static SystemTrayCallbackClass cls;
callback = [cls.createInstance() init];
SystemTrayCallbackClass::setOwner (callback, this);
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength: NSSquareStatusItemLength] retain];
[statusItem setHighlightMode: YES];
setIconSize();
[statusItem setImage: statusIcon];
[statusItem setTarget: callback];
[statusItem setAction: @selector (statusItemAction:)];
}
~Pimpl()
{
[statusItem release];
[statusIcon release];
[callback release];
}
void updateIcon (const Image& newImage)
{
[statusIcon release];
statusIcon = MouseCursorHelpers::createNSImage (newImage);
setIconSize();
}
void handleStatusItemAction (NSEvent* e)
{
NSEventType type = [e type];
const bool isLeft = (type == NSLeftMouseDown || type == NSLeftMouseUp);
const bool isRight = (type == NSRightMouseDown || type == NSRightMouseUp);
if (owner.isCurrentlyBlockedByAnotherModalComponent())
{
if (isLeft || isRight)
if (Component* const current = Component::getCurrentlyModalComponent())
current->inputAttemptWhenModal();
}
else
{
ModifierKeys eventMods (ModifierKeys::getCurrentModifiersRealtime());
if (([e modifierFlags] & NSCommandKeyMask) != 0)
eventMods = eventMods.withFlags (ModifierKeys::commandModifier);
NSRect r = [[e window] frame];
r.origin.y = [[[NSScreen screens] objectAtIndex: 0] frame].size.height - r.origin.y - r.size.height;
owner.setBounds (convertToRectInt (r));
const Time now (Time::getCurrentTime());
if (isLeft || isRight) // Only mouse up is sent by the OS, so simulate a down/up
{
owner.mouseDown (MouseEvent (Desktop::getInstance().getMainMouseSource(),
Point<int>(),
eventMods.withFlags (isLeft ? ModifierKeys::leftButtonModifier
: ModifierKeys::rightButtonModifier),
&owner, &owner, now,
Point<int>(), now, 1, false));
owner.mouseUp (MouseEvent (Desktop::getInstance().getMainMouseSource(),
Point<int>(), eventMods.withoutMouseButtons(),
&owner, &owner, now,
Point<int>(), now, 1, false));
}
else if (type == NSMouseMoved)
{
owner.mouseMove (MouseEvent (Desktop::getInstance().getMainMouseSource(),
Point<int>(), eventMods,
&owner, &owner, now,
Point<int>(), now, 1, false));
}
}
}
private:
SystemTrayIconComponent& owner;
NSStatusItem* statusItem;
NSImage* statusIcon;
NSObject* callback;
void setIconSize()
{
[statusIcon setSize: NSMakeSize (20.0f, 20.0f)];
}
struct SystemTrayCallbackClass : public ObjCClass <NSObject>
{
SystemTrayCallbackClass() : ObjCClass <NSObject> ("JUCESystemTray_")
{
addIvar<SystemTrayIconComponent::Pimpl*> ("owner");
addMethod (@selector (statusItemAction:), statusItemAction, "v@:@");
registerClass();
}
static void setOwner (id self, SystemTrayIconComponent::Pimpl* owner)
{
object_setInstanceVariable (self, "owner", owner);
}
private:
static void statusItemAction (id self, SEL, id /*sender*/)
{
if (SystemTrayIconComponent::Pimpl* const owner = getIvar<SystemTrayIconComponent::Pimpl*> (self, "owner"))
owner->handleStatusItemAction ([NSApp currentEvent]);
}
};
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
};
//==============================================================================
void SystemTrayIconComponent::setIconImage (const Image& newImage)
{
if (newImage.isValid())
{
if (pimpl == nullptr)
pimpl = new Pimpl (*this, newImage);
else
pimpl->updateIcon (newImage);
}
else
{
pimpl = nullptr;
}
}
void SystemTrayIconComponent::setIconTooltip (const String& /* tooltip */)
{
// xxx not yet implemented!
}

+ 9
- 18
modules/juce_gui_extra/native/juce_win32_SystemTrayIcon.cpp View File

@@ -55,10 +55,9 @@ public:
// In order to receive the "TaskbarCreated" message, we need to request that it's not filtered out. // In order to receive the "TaskbarCreated" message, we need to request that it's not filtered out.
// (Need to load dynamically, as ChangeWindowMessageFilter is only available in Vista and later) // (Need to load dynamically, as ChangeWindowMessageFilter is only available in Vista and later)
typedef BOOL (WINAPI* ChangeWindowMessageFilterType) (UINT, DWORD); typedef BOOL (WINAPI* ChangeWindowMessageFilterType) (UINT, DWORD);
ChangeWindowMessageFilterType changeWindowMessageFilter
= (ChangeWindowMessageFilterType) getUser32Function ("ChangeWindowMessageFilter");
if (changeWindowMessageFilter != nullptr)
if (ChangeWindowMessageFilterType changeWindowMessageFilter
= (ChangeWindowMessageFilterType) getUser32Function ("ChangeWindowMessageFilter"))
changeWindowMessageFilter (taskbarCreatedMessage, 1 /* MSGFLT_ADD */); changeWindowMessageFilter (taskbarCreatedMessage, 1 /* MSGFLT_ADD */);
} }
@@ -96,9 +95,7 @@ public:
if (lParam == WM_LBUTTONDOWN || lParam == WM_RBUTTONDOWN if (lParam == WM_LBUTTONDOWN || lParam == WM_RBUTTONDOWN
|| lParam == WM_LBUTTONDBLCLK || lParam == WM_LBUTTONDBLCLK) || lParam == WM_LBUTTONDBLCLK || lParam == WM_LBUTTONDBLCLK)
{ {
Component* const current = Component::getCurrentlyModalComponent();
if (current != nullptr)
if (Component* const current = Component::getCurrentlyModalComponent())
current->inputAttemptWhenModal(); current->inputAttemptWhenModal();
} }
} }
@@ -113,9 +110,11 @@ public:
else if (lParam == WM_LBUTTONUP || lParam == WM_RBUTTONUP) else if (lParam == WM_LBUTTONUP || lParam == WM_RBUTTONUP)
eventMods = eventMods.withoutMouseButtons(); eventMods = eventMods.withoutMouseButtons();
const Time eventTime (getMouseEventTime());
const MouseEvent e (Desktop::getInstance().getMainMouseSource(), const MouseEvent e (Desktop::getInstance().getMainMouseSource(),
Point<int>(), eventMods, &owner, &owner, Time (getMouseEventTime()),
Point<int>(), Time (getMouseEventTime()), 1, false);
Point<int>(), eventMods, &owner, &owner, eventTime,
Point<int>(), eventTime, 1, false);
if (lParam == WM_LBUTTONDOWN || lParam == WM_RBUTTONDOWN) if (lParam == WM_LBUTTONDOWN || lParam == WM_RBUTTONDOWN)
{ {
@@ -141,17 +140,9 @@ public:
static Pimpl* getPimpl (HWND hwnd) static Pimpl* getPimpl (HWND hwnd)
{ {
if (JuceWindowIdentifier::isJUCEWindow (hwnd)) if (JuceWindowIdentifier::isJUCEWindow (hwnd))
{
ComponentPeer* peer = (ComponentPeer*) GetWindowLongPtr (hwnd, 8);
if (peer != nullptr)
{
SystemTrayIconComponent* const iconComp = dynamic_cast<SystemTrayIconComponent*> (&(peer->getComponent()));
if (iconComp != nullptr)
if (ComponentPeer* peer = (ComponentPeer*) GetWindowLongPtr (hwnd, 8))
if (SystemTrayIconComponent* const iconComp = dynamic_cast<SystemTrayIconComponent*> (&(peer->getComponent())))
return iconComp->pimpl; return iconComp->pimpl;
}
}
return nullptr; return nullptr;
} }


Loading…
Cancel
Save