| @@ -2573,6 +2573,13 @@ private: | |||
| Array <Atom> srcMimeTypeAtomList; | |||
| }; | |||
| //============================================================================== | |||
| void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable) | |||
| { | |||
| if (enableOrDisable) | |||
| kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); | |||
| } | |||
| //============================================================================== | |||
| ComponentPeer* Component::createNewPeer (int styleFlags, void* /*nativeWindowToAttachTo*/) | |||
| { | |||
| @@ -95,7 +95,7 @@ public: | |||
| } | |||
| void addSubMenu (NSMenu* parent, const PopupMenu& child, | |||
| const String& name, int& menuId, int& tag) | |||
| const String& name, const int menuId, int& tag) | |||
| { | |||
| NSMenuItem* item = [parent addItemWithTitle: juceStringToNS (name) | |||
| action: nil | |||
| @@ -181,98 +181,102 @@ public: | |||
| MenuBarModel* currentModel; | |||
| private: | |||
| JuceMenuCallback* callback; | |||
| NSMenu* createMenu (const PopupMenu menu, | |||
| const String& menuName, | |||
| int& id, | |||
| const int topLevelIndex) | |||
| void addMenuItem (PopupMenu::MenuItemIterator& iter, NSMenu* menuToAddTo, | |||
| const int topLevelMenuId, const int topLevelIndex) | |||
| { | |||
| NSMenu* m = [[NSMenu alloc] initWithTitle: juceStringToNS (menuName)]; | |||
| NSString* text = juceStringToNS (iter.itemName.upToFirstOccurrenceOf (T("<end>"), false, true)); | |||
| [m setAutoenablesItems: false]; | |||
| PopupMenu::MenuItemIterator iter (menu); | |||
| while (iter.next()) | |||
| if (iter.isSeparator) | |||
| { | |||
| [menuToAddTo addItem: [NSMenuItem separatorItem]]; | |||
| } | |||
| else if (iter.isSectionHeader) | |||
| { | |||
| NSString* text = juceStringToNS (iter.itemName.upToFirstOccurrenceOf (T("<end>"), false, true)); | |||
| NSMenuItem* item = [menuToAddTo addItemWithTitle: text | |||
| action: nil | |||
| keyEquivalent: @""]; | |||
| if (iter.isSeparator) | |||
| { | |||
| [m addItem: [NSMenuItem separatorItem]]; | |||
| } | |||
| else if (iter.isSectionHeader) | |||
| { | |||
| NSMenuItem* item = [m addItemWithTitle: text | |||
| action: nil | |||
| keyEquivalent: @""]; | |||
| [item setEnabled: iter.isEnabled]; | |||
| } | |||
| else if (iter.subMenu != 0) | |||
| { | |||
| NSMenuItem* item = [menuToAddTo addItemWithTitle: text | |||
| action: nil | |||
| keyEquivalent: @""]; | |||
| [item setEnabled: iter.isEnabled]; | |||
| } | |||
| else if (iter.subMenu != 0) | |||
| { | |||
| NSMenuItem* item = [m addItemWithTitle: text | |||
| action: nil | |||
| keyEquivalent: @""]; | |||
| [item setTag: iter.itemId]; | |||
| [item setEnabled: iter.isEnabled]; | |||
| [item setTag: iter.itemId]; | |||
| [item setEnabled: iter.isEnabled]; | |||
| NSMenu* sub = createMenu (*iter.subMenu, iter.itemName, topLevelMenuId, topLevelIndex); | |||
| [menuToAddTo setSubmenu: sub forItem: item]; | |||
| [sub release]; | |||
| } | |||
| else | |||
| { | |||
| NSMenuItem* item = [menuToAddTo addItemWithTitle: text | |||
| action: @selector (menuItemInvoked:) | |||
| keyEquivalent: @""]; | |||
| NSMenu* sub = createMenu (*iter.subMenu, iter.itemName, id, topLevelIndex); | |||
| [m setSubmenu: sub forItem: item]; | |||
| [sub release]; | |||
| } | |||
| else | |||
| { | |||
| NSMenuItem* item = [m addItemWithTitle: text | |||
| action: @selector (menuItemInvoked:) | |||
| keyEquivalent: @""]; | |||
| [item setTag: iter.itemId]; | |||
| [item setEnabled: iter.isEnabled]; | |||
| [item setState: iter.isTicked ? NSOnState : NSOffState]; | |||
| [item setTarget: (id) callback]; | |||
| [item setTag: iter.itemId]; | |||
| [item setEnabled: iter.isEnabled]; | |||
| [item setState: iter.isTicked ? NSOnState : NSOffState]; | |||
| [item setTarget: (id) callback]; | |||
| NSMutableArray* info = [NSMutableArray arrayWithObject: [NSNumber numberWithUnsignedLongLong: (pointer_sized_int) (void*) iter.commandManager]]; | |||
| [info addObject: [NSNumber numberWithInt: topLevelIndex]]; | |||
| [item setRepresentedObject: info]; | |||
| NSMutableArray* info = [NSMutableArray arrayWithObject: [NSNumber numberWithUnsignedLongLong: (pointer_sized_int) (void*) iter.commandManager]]; | |||
| [info addObject: [NSNumber numberWithInt: topLevelIndex]]; | |||
| [item setRepresentedObject: info]; | |||
| if (iter.commandManager != 0) | |||
| { | |||
| const Array <KeyPress> keyPresses (iter.commandManager->getKeyMappings() | |||
| ->getKeyPressesAssignedToCommand (iter.itemId)); | |||
| if (iter.commandManager != 0) | |||
| if (keyPresses.size() > 0) | |||
| { | |||
| const Array <KeyPress> keyPresses (iter.commandManager->getKeyMappings() | |||
| ->getKeyPressesAssignedToCommand (iter.itemId)); | |||
| if (keyPresses.size() > 0) | |||
| { | |||
| const KeyPress& kp = keyPresses.getReference(0); | |||
| juce_wchar key = kp.getTextCharacter(); | |||
| if (kp.getKeyCode() == KeyPress::backspaceKey) | |||
| key = NSBackspaceCharacter; | |||
| else if (kp.getKeyCode() == KeyPress::deleteKey) | |||
| key = NSDeleteCharacter; | |||
| else if (key == 0) | |||
| key = (juce_wchar) kp.getKeyCode(); | |||
| unsigned int mods = 0; | |||
| if (kp.getModifiers().isShiftDown()) | |||
| mods |= NSShiftKeyMask; | |||
| if (kp.getModifiers().isCtrlDown()) | |||
| mods |= NSControlKeyMask; | |||
| if (kp.getModifiers().isAltDown()) | |||
| mods |= NSAlternateKeyMask; | |||
| if (kp.getModifiers().isCommandDown()) | |||
| mods |= NSCommandKeyMask; | |||
| [item setKeyEquivalent: juceStringToNS (String::charToString (key))]; | |||
| [item setKeyEquivalentModifierMask: mods]; | |||
| } | |||
| const KeyPress& kp = keyPresses.getReference(0); | |||
| juce_wchar key = kp.getTextCharacter(); | |||
| if (kp.getKeyCode() == KeyPress::backspaceKey) | |||
| key = NSBackspaceCharacter; | |||
| else if (kp.getKeyCode() == KeyPress::deleteKey) | |||
| key = NSDeleteCharacter; | |||
| else if (key == 0) | |||
| key = (juce_wchar) kp.getKeyCode(); | |||
| unsigned int mods = 0; | |||
| if (kp.getModifiers().isShiftDown()) | |||
| mods |= NSShiftKeyMask; | |||
| if (kp.getModifiers().isCtrlDown()) | |||
| mods |= NSControlKeyMask; | |||
| if (kp.getModifiers().isAltDown()) | |||
| mods |= NSAlternateKeyMask; | |||
| if (kp.getModifiers().isCommandDown()) | |||
| mods |= NSCommandKeyMask; | |||
| [item setKeyEquivalent: juceStringToNS (String::charToString (key))]; | |||
| [item setKeyEquivalentModifierMask: mods]; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| private: | |||
| JuceMenuCallback* callback; | |||
| NSMenu* createMenu (const PopupMenu menu, | |||
| const String& menuName, | |||
| const int topLevelMenuId, | |||
| const int topLevelIndex) | |||
| { | |||
| NSMenu* m = [[NSMenu alloc] initWithTitle: juceStringToNS (menuName)]; | |||
| [m setAutoenablesItems: false]; | |||
| PopupMenu::MenuItemIterator iter (menu); | |||
| while (iter.next()) | |||
| addMenuItem (iter, m, topLevelMenuId, topLevelIndex); | |||
| [m update]; | |||
| return m; | |||
| @@ -315,49 +319,22 @@ END_JUCE_NAMESPACE | |||
| BEGIN_JUCE_NAMESPACE | |||
| void MenuBarModel::setMacMainMenu (MenuBarModel* newMenuBarModel) throw() | |||
| //============================================================================== | |||
| static NSMenu* createStandardAppMenu (NSMenu* menu, const String& appName, | |||
| const PopupMenu* extraItems) | |||
| { | |||
| if (getMacMainMenu() != newMenuBarModel) | |||
| if (extraItems != 0 && JuceMainMenuHandler::instance != 0 && extraItems->getNumItems() > 0) | |||
| { | |||
| if (newMenuBarModel == 0) | |||
| { | |||
| delete JuceMainMenuHandler::instance; | |||
| jassert (JuceMainMenuHandler::instance == 0); // should be zeroed in the destructor | |||
| } | |||
| else | |||
| { | |||
| if (JuceMainMenuHandler::instance == 0) | |||
| JuceMainMenuHandler::instance = new JuceMainMenuHandler(); | |||
| PopupMenu::MenuItemIterator iter (*extraItems); | |||
| JuceMainMenuHandler::instance->setMenu (newMenuBarModel); | |||
| } | |||
| while (iter.next()) | |||
| JuceMainMenuHandler::instance->addMenuItem (iter, menu, 0, -1); | |||
| [menu addItem: [NSMenuItem separatorItem]]; | |||
| } | |||
| } | |||
| MenuBarModel* MenuBarModel::getMacMainMenu() throw() | |||
| { | |||
| return JuceMainMenuHandler::instance != 0 | |||
| ? JuceMainMenuHandler::instance->currentModel : 0; | |||
| } | |||
| //============================================================================== | |||
| static NSMenu* createStandardAppMenu (NSMenu* menu, const String& appName) | |||
| { | |||
| NSMenuItem* item; | |||
| // xxx should allow the 'about' and 'preferences' items to be turned on programatically... | |||
| /* item = [menu addItemWithTitle: juceStringToNS ("About " + appName)] | |||
| action: @selector(orderFrontStandardAboutPanel:) keyEquivalent: @""]; | |||
| [item setTarget: NSApp]; | |||
| [menu addItem: [NSMenuItem separatorItem]]; | |||
| */ | |||
| /* item = [menu addItemWithTitle: NSLocalizedString (@"Preferences...", nil) | |||
| action: nil keyEquivalent: @","]; | |||
| [menu addItem: [NSMenuItem separatorItem]]; | |||
| */ | |||
| // Services... | |||
| item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Services", nil) | |||
| action: nil keyEquivalent: @""]; | |||
| @@ -403,9 +380,12 @@ static NSMenu* createStandardAppMenu (NSMenu* menu, const String& appName) | |||
| } | |||
| // Since our app has no NIB, this initialises a standard app menu... | |||
| void initialiseMainMenu() | |||
| static void rebuildMainMenu (const PopupMenu* extraItems) | |||
| { | |||
| if (JUCEApplication::getInstance() != 0) // only needed in an app | |||
| // this can't be used in a plugin! | |||
| jassert (JUCEApplication::getInstance() != 0); | |||
| if (JUCEApplication::getInstance() != 0) | |||
| { | |||
| const ScopedAutoReleasePool pool; | |||
| @@ -418,12 +398,50 @@ void initialiseMainMenu() | |||
| [mainMenu setSubmenu: appMenu forItem: item]; | |||
| [NSApp setMainMenu: mainMenu]; | |||
| createStandardAppMenu (appMenu, JUCEApplication::getInstance()->getApplicationName()); | |||
| createStandardAppMenu (appMenu, JUCEApplication::getInstance()->getApplicationName(), extraItems); | |||
| [appMenu release]; | |||
| [mainMenu release]; | |||
| } | |||
| } | |||
| void MenuBarModel::setMacMainMenu (MenuBarModel* newMenuBarModel, | |||
| const PopupMenu* extraAppleMenuItems) throw() | |||
| { | |||
| if (getMacMainMenu() != newMenuBarModel) | |||
| { | |||
| if (newMenuBarModel == 0) | |||
| { | |||
| delete JuceMainMenuHandler::instance; | |||
| jassert (JuceMainMenuHandler::instance == 0); // should be zeroed in the destructor | |||
| jassert (extraAppleMenuItems == 0); // you can't specify some extra items without also supplying a model | |||
| extraAppleMenuItems = 0; | |||
| } | |||
| else | |||
| { | |||
| if (JuceMainMenuHandler::instance == 0) | |||
| JuceMainMenuHandler::instance = new JuceMainMenuHandler(); | |||
| JuceMainMenuHandler::instance->setMenu (newMenuBarModel); | |||
| } | |||
| } | |||
| rebuildMainMenu (extraAppleMenuItems); | |||
| } | |||
| MenuBarModel* MenuBarModel::getMacMainMenu() throw() | |||
| { | |||
| return JuceMainMenuHandler::instance != 0 | |||
| ? JuceMainMenuHandler::instance->currentModel : 0; | |||
| } | |||
| void initialiseMainMenu() | |||
| { | |||
| if (JUCEApplication::getInstance() != 0) // only needed in an app | |||
| rebuildMainMenu (0); | |||
| } | |||
| #endif | |||
| @@ -110,8 +110,6 @@ public: | |||
| END_JUCE_NAMESPACE | |||
| using namespace JUCE_NAMESPACE; | |||
| typedef void (*juce_HandleProcessFocusChangeFunction)(); | |||
| #define JuceAppDelegate MakeObjCClassName(JuceAppDelegate) | |||
| @interface JuceAppDelegate : NSObject | |||
| @@ -1062,9 +1062,16 @@ void juce_HandleProcessFocusChange() | |||
| if (NSViewComponentPeer::isValidPeer (currentlyFocusedPeer)) | |||
| { | |||
| if (Process::isForegroundProcess()) | |||
| { | |||
| currentlyFocusedPeer->handleFocusGain(); | |||
| } | |||
| else | |||
| { | |||
| currentlyFocusedPeer->handleFocusLoss(); | |||
| // turn kiosk mode off if we lose focus.. | |||
| Desktop::getInstance().setKioskModeComponent (0); | |||
| } | |||
| } | |||
| } | |||
| @@ -1337,6 +1344,23 @@ void NSViewComponentPeer::redirectMovedOrResized() | |||
| handleMovedOrResized(); | |||
| } | |||
| //============================================================================== | |||
| void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable) | |||
| { | |||
| // Very annoyingly, this function has to use the old SetSystemUIMode function, | |||
| // which is in Carbon.framework. But, because there's no Cocoa equivalent, it | |||
| // is apparently still available in 64-bit apps.. | |||
| if (enableOrDisable) | |||
| { | |||
| SetSystemUIMode (kUIModeAllSuppressed, kUIOptionAutoShowMenuBar); | |||
| kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); | |||
| } | |||
| else | |||
| { | |||
| SetSystemUIMode (kUIModeNormal, 0); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| void NSViewComponentPeer::repaint (int x, int y, int w, int h) | |||
| { | |||
| @@ -1962,6 +1962,8 @@ private: | |||
| // so this forces an update when the app is brought to the front | |||
| if (wParam != FALSE) | |||
| juce_repeatLastProcessPriority(); | |||
| else | |||
| Desktop::getInstance().setKioskModeComponent (0); // turn kiosk mode off if we lose focus | |||
| juce_CheckCurrentlyFocusedTopLevelWindow(); | |||
| modifiersAtLastCallback = -1; | |||
| @@ -2299,6 +2301,13 @@ bool Desktop::isScreenSaverEnabled() throw() | |||
| return screenSaverAllowed; | |||
| } | |||
| //============================================================================== | |||
| void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable) | |||
| { | |||
| if (enableOrDisable) | |||
| kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); | |||
| } | |||
| //============================================================================== | |||
| static BOOL CALLBACK enumMonitorsProc (HMONITOR, HDC, LPRECT r, LPARAM userInfo) | |||
| { | |||
| @@ -121,7 +121,8 @@ class ContentComp : public Component, | |||
| setDefaultLookAndFeel = 0x200b, | |||
| setOldSchoolLookAndFeel = 0x200c, | |||
| useNativeTitleBar = 0x200d, | |||
| useNativeMenus = 0x200e | |||
| useNativeMenus = 0x200e, | |||
| goToKioskMode = 0x200f | |||
| }; | |||
| public: | |||
| @@ -223,6 +224,10 @@ public: | |||
| #if JUCE_MAC | |||
| menu.addCommandItem (commandManager, useNativeMenus); | |||
| #endif | |||
| #if ! JUCE_LINUX | |||
| menu.addCommandItem (commandManager, goToKioskMode); | |||
| #endif | |||
| } | |||
| return menu; | |||
| @@ -268,6 +273,10 @@ public: | |||
| #if JUCE_MAC | |||
| , useNativeMenus | |||
| #endif | |||
| #if ! JUCE_LINUX | |||
| , goToKioskMode | |||
| #endif | |||
| }; | |||
| commands.addArray (ids, numElementsInArray (ids)); | |||
| @@ -381,6 +390,13 @@ public: | |||
| break; | |||
| #endif | |||
| #if ! JUCE_LINUX | |||
| case goToKioskMode: | |||
| result.setInfo (T("Show full-screen kiosk mode"), String::empty, generalCategory, 0); | |||
| result.setTicked (Desktop::getInstance().getKioskModeComponent() != 0); | |||
| break; | |||
| #endif | |||
| default: | |||
| break; | |||
| }; | |||
| @@ -482,6 +498,20 @@ public: | |||
| break; | |||
| #endif | |||
| #if ! JUCE_LINUX | |||
| case goToKioskMode: | |||
| if (Desktop::getInstance().getKioskModeComponent() == 0) | |||
| { | |||
| Desktop::getInstance().setKioskModeComponent (getTopLevelComponent()); | |||
| } | |||
| else | |||
| { | |||
| Desktop::getInstance().setKioskModeComponent (0); | |||
| } | |||
| break; | |||
| #endif | |||
| default: | |||
| return false; | |||
| }; | |||
| @@ -40219,7 +40219,8 @@ Desktop::Desktop() throw() | |||
| monitorCoordsClipped (2), | |||
| monitorCoordsUnclipped (2), | |||
| lastMouseX (0), | |||
| lastMouseY (0) | |||
| lastMouseY (0), | |||
| kioskModeComponent (0) | |||
| { | |||
| refreshMonitorSizes(); | |||
| } | |||
| @@ -40487,6 +40488,40 @@ void Desktop::resetTimer() throw() | |||
| getMousePosition (lastMouseX, lastMouseY); | |||
| } | |||
| extern void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable); | |||
| void Desktop::setKioskModeComponent (Component* componentToUse) | |||
| { | |||
| if (kioskModeComponent != componentToUse) | |||
| { | |||
| // agh! Don't delete a component without first stopping it being the kiosk comp | |||
| jassert (kioskModeComponent == 0 || kioskModeComponent->isValidComponent()); | |||
| // agh! Don't remove a component from the desktop if it's the kiosk comp! | |||
| jassert (kioskModeComponent == 0 || kioskModeComponent->isOnDesktop()); | |||
| if (kioskModeComponent->isValidComponent()) | |||
| { | |||
| juce_setKioskComponent (kioskModeComponent, false); | |||
| kioskModeComponent->setBounds (kioskComponentOriginalBounds); | |||
| } | |||
| kioskModeComponent = componentToUse; | |||
| if (kioskModeComponent != 0) | |||
| { | |||
| jassert (kioskModeComponent->isValidComponent()); | |||
| // Only components that are already on the desktop can be put into kiosk mode! | |||
| jassert (kioskModeComponent->isOnDesktop()); | |||
| kioskComponentOriginalBounds = kioskModeComponent->getBounds(); | |||
| juce_setKioskComponent (kioskModeComponent, true); | |||
| } | |||
| } | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| /********* End of inlined file: juce_Desktop.cpp *********/ | |||
| @@ -42660,13 +42695,13 @@ void Label::setText (const String& newText, | |||
| text = newText; | |||
| repaint(); | |||
| textWasChanged(); | |||
| if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) | |||
| { | |||
| componentMovedOrResized (*ownerComponent, true, true); | |||
| if (broadcastChangeMessage) | |||
| callChangeListeners(); | |||
| } | |||
| if (broadcastChangeMessage) | |||
| callChangeListeners(); | |||
| } | |||
| } | |||
| @@ -42770,6 +42805,10 @@ void Label::textWasEdited() | |||
| { | |||
| } | |||
| void Label::textWasChanged() | |||
| { | |||
| } | |||
| void Label::showEditor() | |||
| { | |||
| if (editor == 0) | |||
| @@ -42799,6 +42838,8 @@ bool Label::updateFromTextEditorContents() | |||
| text = newText; | |||
| repaint(); | |||
| textWasChanged(); | |||
| if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) | |||
| componentMovedOrResized (*ownerComponent, true, true); | |||
| @@ -242642,6 +242683,8 @@ private: | |||
| // so this forces an update when the app is brought to the front | |||
| if (wParam != FALSE) | |||
| juce_repeatLastProcessPriority(); | |||
| else | |||
| Desktop::getInstance().setKioskModeComponent (0); // turn kiosk mode off if we lose focus | |||
| juce_CheckCurrentlyFocusedTopLevelWindow(); | |||
| modifiersAtLastCallback = -1; | |||
| @@ -242969,6 +243012,12 @@ bool Desktop::isScreenSaverEnabled() throw() | |||
| return screenSaverAllowed; | |||
| } | |||
| void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable) | |||
| { | |||
| if (enableOrDisable) | |||
| kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); | |||
| } | |||
| static BOOL CALLBACK enumMonitorsProc (HMONITOR, HDC, LPRECT r, LPARAM userInfo) | |||
| { | |||
| Array <Rectangle>* const monitorCoords = (Array <Rectangle>*) userInfo; | |||
| @@ -261216,6 +261265,12 @@ private: | |||
| Array <Atom> srcMimeTypeAtomList; | |||
| }; | |||
| void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable) | |||
| { | |||
| if (enableOrDisable) | |||
| kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); | |||
| } | |||
| ComponentPeer* Component::createNewPeer (int styleFlags, void* /*nativeWindowToAttachTo*/) | |||
| { | |||
| return new LinuxComponentPeer (this, styleFlags); | |||
| @@ -265133,9 +265188,16 @@ void juce_HandleProcessFocusChange() | |||
| if (NSViewComponentPeer::isValidPeer (currentlyFocusedPeer)) | |||
| { | |||
| if (Process::isForegroundProcess()) | |||
| { | |||
| currentlyFocusedPeer->handleFocusGain(); | |||
| } | |||
| else | |||
| { | |||
| currentlyFocusedPeer->handleFocusLoss(); | |||
| // turn kiosk mode off if we lose focus.. | |||
| Desktop::getInstance().setKioskModeComponent (0); | |||
| } | |||
| } | |||
| } | |||
| @@ -265406,6 +265468,22 @@ void NSViewComponentPeer::redirectMovedOrResized() | |||
| handleMovedOrResized(); | |||
| } | |||
| void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable) | |||
| { | |||
| // Very annoyingly, this function has to use the old SetSystemUIMode function, | |||
| // which is in Carbon.framework. But, because there's no Cocoa equivalent, it | |||
| // is apparently still available in 64-bit apps.. | |||
| if (enableOrDisable) | |||
| { | |||
| SetSystemUIMode (kUIModeAllSuppressed, kUIOptionAutoShowMenuBar); | |||
| kioskModeComponent->setBounds (Desktop::getInstance().getMainMonitorArea (false)); | |||
| } | |||
| else | |||
| { | |||
| SetSystemUIMode (kUIModeNormal, 0); | |||
| } | |||
| } | |||
| void NSViewComponentPeer::repaint (int x, int y, int w, int h) | |||
| { | |||
| [view setNeedsDisplayInRect: | |||
| @@ -266306,7 +266384,7 @@ public: | |||
| } | |||
| void addSubMenu (NSMenu* parent, const PopupMenu& child, | |||
| const String& name, int& menuId, int& tag) | |||
| const String& name, const int menuId, int& tag) | |||
| { | |||
| NSMenuItem* item = [parent addItemWithTitle: juceStringToNS (name) | |||
| action: nil | |||
| @@ -266392,98 +266470,102 @@ public: | |||
| MenuBarModel* currentModel; | |||
| private: | |||
| JuceMenuCallback* callback; | |||
| NSMenu* createMenu (const PopupMenu menu, | |||
| const String& menuName, | |||
| int& id, | |||
| const int topLevelIndex) | |||
| void addMenuItem (PopupMenu::MenuItemIterator& iter, NSMenu* menuToAddTo, | |||
| const int topLevelMenuId, const int topLevelIndex) | |||
| { | |||
| NSMenu* m = [[NSMenu alloc] initWithTitle: juceStringToNS (menuName)]; | |||
| [m setAutoenablesItems: false]; | |||
| NSString* text = juceStringToNS (iter.itemName.upToFirstOccurrenceOf (T("<end>"), false, true)); | |||
| PopupMenu::MenuItemIterator iter (menu); | |||
| while (iter.next()) | |||
| if (iter.isSeparator) | |||
| { | |||
| [menuToAddTo addItem: [NSMenuItem separatorItem]]; | |||
| } | |||
| else if (iter.isSectionHeader) | |||
| { | |||
| NSString* text = juceStringToNS (iter.itemName.upToFirstOccurrenceOf (T("<end>"), false, true)); | |||
| NSMenuItem* item = [menuToAddTo addItemWithTitle: text | |||
| action: nil | |||
| keyEquivalent: @""]; | |||
| if (iter.isSeparator) | |||
| { | |||
| [m addItem: [NSMenuItem separatorItem]]; | |||
| } | |||
| else if (iter.isSectionHeader) | |||
| { | |||
| NSMenuItem* item = [m addItemWithTitle: text | |||
| action: nil | |||
| keyEquivalent: @""]; | |||
| [item setEnabled: iter.isEnabled]; | |||
| } | |||
| else if (iter.subMenu != 0) | |||
| { | |||
| NSMenuItem* item = [menuToAddTo addItemWithTitle: text | |||
| action: nil | |||
| keyEquivalent: @""]; | |||
| [item setEnabled: iter.isEnabled]; | |||
| } | |||
| else if (iter.subMenu != 0) | |||
| { | |||
| NSMenuItem* item = [m addItemWithTitle: text | |||
| action: nil | |||
| keyEquivalent: @""]; | |||
| [item setTag: iter.itemId]; | |||
| [item setEnabled: iter.isEnabled]; | |||
| [item setTag: iter.itemId]; | |||
| [item setEnabled: iter.isEnabled]; | |||
| NSMenu* sub = createMenu (*iter.subMenu, iter.itemName, topLevelMenuId, topLevelIndex); | |||
| [menuToAddTo setSubmenu: sub forItem: item]; | |||
| [sub release]; | |||
| } | |||
| else | |||
| { | |||
| NSMenuItem* item = [menuToAddTo addItemWithTitle: text | |||
| action: @selector (menuItemInvoked:) | |||
| keyEquivalent: @""]; | |||
| NSMenu* sub = createMenu (*iter.subMenu, iter.itemName, id, topLevelIndex); | |||
| [m setSubmenu: sub forItem: item]; | |||
| [sub release]; | |||
| } | |||
| else | |||
| { | |||
| NSMenuItem* item = [m addItemWithTitle: text | |||
| action: @selector (menuItemInvoked:) | |||
| keyEquivalent: @""]; | |||
| [item setTag: iter.itemId]; | |||
| [item setEnabled: iter.isEnabled]; | |||
| [item setState: iter.isTicked ? NSOnState : NSOffState]; | |||
| [item setTarget: (id) callback]; | |||
| [item setTag: iter.itemId]; | |||
| [item setEnabled: iter.isEnabled]; | |||
| [item setState: iter.isTicked ? NSOnState : NSOffState]; | |||
| [item setTarget: (id) callback]; | |||
| NSMutableArray* info = [NSMutableArray arrayWithObject: [NSNumber numberWithUnsignedLongLong: (pointer_sized_int) (void*) iter.commandManager]]; | |||
| [info addObject: [NSNumber numberWithInt: topLevelIndex]]; | |||
| [item setRepresentedObject: info]; | |||
| NSMutableArray* info = [NSMutableArray arrayWithObject: [NSNumber numberWithUnsignedLongLong: (pointer_sized_int) (void*) iter.commandManager]]; | |||
| [info addObject: [NSNumber numberWithInt: topLevelIndex]]; | |||
| [item setRepresentedObject: info]; | |||
| if (iter.commandManager != 0) | |||
| { | |||
| const Array <KeyPress> keyPresses (iter.commandManager->getKeyMappings() | |||
| ->getKeyPressesAssignedToCommand (iter.itemId)); | |||
| if (iter.commandManager != 0) | |||
| if (keyPresses.size() > 0) | |||
| { | |||
| const Array <KeyPress> keyPresses (iter.commandManager->getKeyMappings() | |||
| ->getKeyPressesAssignedToCommand (iter.itemId)); | |||
| if (keyPresses.size() > 0) | |||
| { | |||
| const KeyPress& kp = keyPresses.getReference(0); | |||
| juce_wchar key = kp.getTextCharacter(); | |||
| if (kp.getKeyCode() == KeyPress::backspaceKey) | |||
| key = NSBackspaceCharacter; | |||
| else if (kp.getKeyCode() == KeyPress::deleteKey) | |||
| key = NSDeleteCharacter; | |||
| else if (key == 0) | |||
| key = (juce_wchar) kp.getKeyCode(); | |||
| unsigned int mods = 0; | |||
| if (kp.getModifiers().isShiftDown()) | |||
| mods |= NSShiftKeyMask; | |||
| if (kp.getModifiers().isCtrlDown()) | |||
| mods |= NSControlKeyMask; | |||
| if (kp.getModifiers().isAltDown()) | |||
| mods |= NSAlternateKeyMask; | |||
| if (kp.getModifiers().isCommandDown()) | |||
| mods |= NSCommandKeyMask; | |||
| [item setKeyEquivalent: juceStringToNS (String::charToString (key))]; | |||
| [item setKeyEquivalentModifierMask: mods]; | |||
| } | |||
| const KeyPress& kp = keyPresses.getReference(0); | |||
| juce_wchar key = kp.getTextCharacter(); | |||
| if (kp.getKeyCode() == KeyPress::backspaceKey) | |||
| key = NSBackspaceCharacter; | |||
| else if (kp.getKeyCode() == KeyPress::deleteKey) | |||
| key = NSDeleteCharacter; | |||
| else if (key == 0) | |||
| key = (juce_wchar) kp.getKeyCode(); | |||
| unsigned int mods = 0; | |||
| if (kp.getModifiers().isShiftDown()) | |||
| mods |= NSShiftKeyMask; | |||
| if (kp.getModifiers().isCtrlDown()) | |||
| mods |= NSControlKeyMask; | |||
| if (kp.getModifiers().isAltDown()) | |||
| mods |= NSAlternateKeyMask; | |||
| if (kp.getModifiers().isCommandDown()) | |||
| mods |= NSCommandKeyMask; | |||
| [item setKeyEquivalent: juceStringToNS (String::charToString (key))]; | |||
| [item setKeyEquivalentModifierMask: mods]; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| private: | |||
| JuceMenuCallback* callback; | |||
| NSMenu* createMenu (const PopupMenu menu, | |||
| const String& menuName, | |||
| const int topLevelMenuId, | |||
| const int topLevelIndex) | |||
| { | |||
| NSMenu* m = [[NSMenu alloc] initWithTitle: juceStringToNS (menuName)]; | |||
| [m setAutoenablesItems: false]; | |||
| PopupMenu::MenuItemIterator iter (menu); | |||
| while (iter.next()) | |||
| addMenuItem (iter, m, topLevelMenuId, topLevelIndex); | |||
| [m update]; | |||
| return m; | |||
| @@ -266526,47 +266608,21 @@ END_JUCE_NAMESPACE | |||
| BEGIN_JUCE_NAMESPACE | |||
| void MenuBarModel::setMacMainMenu (MenuBarModel* newMenuBarModel) throw() | |||
| static NSMenu* createStandardAppMenu (NSMenu* menu, const String& appName, | |||
| const PopupMenu* extraItems) | |||
| { | |||
| if (getMacMainMenu() != newMenuBarModel) | |||
| if (extraItems != 0 && JuceMainMenuHandler::instance != 0 && extraItems->getNumItems() > 0) | |||
| { | |||
| if (newMenuBarModel == 0) | |||
| { | |||
| delete JuceMainMenuHandler::instance; | |||
| jassert (JuceMainMenuHandler::instance == 0); // should be zeroed in the destructor | |||
| } | |||
| else | |||
| { | |||
| if (JuceMainMenuHandler::instance == 0) | |||
| JuceMainMenuHandler::instance = new JuceMainMenuHandler(); | |||
| PopupMenu::MenuItemIterator iter (*extraItems); | |||
| JuceMainMenuHandler::instance->setMenu (newMenuBarModel); | |||
| } | |||
| } | |||
| } | |||
| while (iter.next()) | |||
| JuceMainMenuHandler::instance->addMenuItem (iter, menu, 0, -1); | |||
| MenuBarModel* MenuBarModel::getMacMainMenu() throw() | |||
| { | |||
| return JuceMainMenuHandler::instance != 0 | |||
| ? JuceMainMenuHandler::instance->currentModel : 0; | |||
| } | |||
| [menu addItem: [NSMenuItem separatorItem]]; | |||
| } | |||
| static NSMenu* createStandardAppMenu (NSMenu* menu, const String& appName) | |||
| { | |||
| NSMenuItem* item; | |||
| // xxx should allow the 'about' and 'preferences' items to be turned on programatically... | |||
| /* item = [menu addItemWithTitle: juceStringToNS ("About " + appName)] | |||
| action: @selector(orderFrontStandardAboutPanel:) keyEquivalent: @""]; | |||
| [item setTarget: NSApp]; | |||
| [menu addItem: [NSMenuItem separatorItem]]; | |||
| */ | |||
| /* item = [menu addItemWithTitle: NSLocalizedString (@"Preferences...", nil) | |||
| action: nil keyEquivalent: @","]; | |||
| [menu addItem: [NSMenuItem separatorItem]]; | |||
| */ | |||
| // Services... | |||
| item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Services", nil) | |||
| action: nil keyEquivalent: @""]; | |||
| @@ -266612,9 +266668,12 @@ static NSMenu* createStandardAppMenu (NSMenu* menu, const String& appName) | |||
| } | |||
| // Since our app has no NIB, this initialises a standard app menu... | |||
| void initialiseMainMenu() | |||
| static void rebuildMainMenu (const PopupMenu* extraItems) | |||
| { | |||
| if (JUCEApplication::getInstance() != 0) // only needed in an app | |||
| // this can't be used in a plugin! | |||
| jassert (JUCEApplication::getInstance() != 0); | |||
| if (JUCEApplication::getInstance() != 0) | |||
| { | |||
| const ScopedAutoReleasePool pool; | |||
| @@ -266627,13 +266686,50 @@ void initialiseMainMenu() | |||
| [mainMenu setSubmenu: appMenu forItem: item]; | |||
| [NSApp setMainMenu: mainMenu]; | |||
| createStandardAppMenu (appMenu, JUCEApplication::getInstance()->getApplicationName()); | |||
| createStandardAppMenu (appMenu, JUCEApplication::getInstance()->getApplicationName(), extraItems); | |||
| [appMenu release]; | |||
| [mainMenu release]; | |||
| } | |||
| } | |||
| void MenuBarModel::setMacMainMenu (MenuBarModel* newMenuBarModel, | |||
| const PopupMenu* extraAppleMenuItems) throw() | |||
| { | |||
| if (getMacMainMenu() != newMenuBarModel) | |||
| { | |||
| if (newMenuBarModel == 0) | |||
| { | |||
| delete JuceMainMenuHandler::instance; | |||
| jassert (JuceMainMenuHandler::instance == 0); // should be zeroed in the destructor | |||
| jassert (extraAppleMenuItems == 0); // you can't specify some extra items without also supplying a model | |||
| extraAppleMenuItems = 0; | |||
| } | |||
| else | |||
| { | |||
| if (JuceMainMenuHandler::instance == 0) | |||
| JuceMainMenuHandler::instance = new JuceMainMenuHandler(); | |||
| JuceMainMenuHandler::instance->setMenu (newMenuBarModel); | |||
| } | |||
| } | |||
| rebuildMainMenu (extraAppleMenuItems); | |||
| } | |||
| MenuBarModel* MenuBarModel::getMacMainMenu() throw() | |||
| { | |||
| return JuceMainMenuHandler::instance != 0 | |||
| ? JuceMainMenuHandler::instance->currentModel : 0; | |||
| } | |||
| void initialiseMainMenu() | |||
| { | |||
| if (JUCEApplication::getInstance() != 0) // only needed in an app | |||
| rebuildMainMenu (0); | |||
| } | |||
| #endif | |||
| /********* End of inlined file: juce_mac_MainMenu.mm *********/ | |||
| @@ -268007,8 +268103,6 @@ public: | |||
| END_JUCE_NAMESPACE | |||
| using namespace JUCE_NAMESPACE; | |||
| typedef void (*juce_HandleProcessFocusChangeFunction)(); | |||
| #define JuceAppDelegate MakeObjCClassName(JuceAppDelegate) | |||
| @interface JuceAppDelegate : NSObject | |||
| @@ -23677,6 +23677,25 @@ public: | |||
| /** Unregisters a listener that was added with addFocusChangeListener(). */ | |||
| void removeFocusChangeListener (FocusChangeListener* const listener) throw(); | |||
| /** Takes a component and makes it full-screen, removing the taskbar, dock, etc. | |||
| The component must already be on the desktop for this method to work. It will | |||
| be resized to completely fill the screen and any extraneous taskbars, menu bars, | |||
| etc will be hidden. | |||
| To exit kiosk mode, just call setKioskModeComponent (0). When this is called, | |||
| the component that's currently being used will be resized back to the size | |||
| and position it was in before being put into this mode. | |||
| */ | |||
| void setKioskModeComponent (Component* componentToUse); | |||
| /** Returns the component that is currently being used in kiosk-mode. | |||
| This is the component that was last set by setKioskModeComponent(). If none | |||
| has been set, this returns 0. | |||
| */ | |||
| Component* getKioskModeComponent() const { return kioskModeComponent; } | |||
| /** Returns the number of components that are currently active as top-level | |||
| desktop windows. | |||
| @@ -23729,6 +23748,9 @@ private: | |||
| Array <Rectangle> monitorCoordsClipped, monitorCoordsUnclipped; | |||
| int lastMouseX, lastMouseY; | |||
| Component* kioskModeComponent; | |||
| Rectangle kioskComponentOriginalBounds; | |||
| void timerCallback(); | |||
| void sendMouseMove(); | |||
| void resetTimer() throw(); | |||
| @@ -33290,6 +33312,10 @@ protected: | |||
| */ | |||
| virtual void textWasEdited(); | |||
| /** Called when the text has been altered. | |||
| */ | |||
| virtual void textWasChanged(); | |||
| private: | |||
| String text; | |||
| Font font; | |||
| @@ -43159,13 +43185,23 @@ public: | |||
| You can pass 0 to stop the current model being displayed. Be careful | |||
| not to delete a model while it is being used. | |||
| An optional extra menu can be specified, containing items to add to the top of | |||
| the apple menu. (Confusingly, the 'apple' menu isn't the one with a picture of | |||
| an apple, it's the one next to it, with your application's name at the top | |||
| and the services menu etc on it). When one of these items is selected, the | |||
| menu bar model will be used to invoke it, and in the menuItemSelected() callback | |||
| the topLevelMenuIndex parameter will be -1. If you pass in an extraAppleMenuItems | |||
| object then newMenuBarModel must be non-null. | |||
| */ | |||
| static void setMacMainMenu (MenuBarModel* newMenuBarModel) throw(); | |||
| static void setMacMainMenu (MenuBarModel* newMenuBarModel, | |||
| const PopupMenu* extraAppleMenuItems = 0) throw(); | |||
| /** MAC ONLY - Returns the menu model that is currently being shown as | |||
| the main menu bar. | |||
| */ | |||
| static MenuBarModel* getMacMainMenu() throw(); | |||
| #endif | |||
| /** @internal */ | |||
| @@ -82,13 +82,13 @@ void Label::setText (const String& newText, | |||
| text = newText; | |||
| repaint(); | |||
| textWasChanged(); | |||
| if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) | |||
| { | |||
| componentMovedOrResized (*ownerComponent, true, true); | |||
| if (broadcastChangeMessage) | |||
| callChangeListeners(); | |||
| } | |||
| if (broadcastChangeMessage) | |||
| callChangeListeners(); | |||
| } | |||
| } | |||
| @@ -194,6 +194,10 @@ void Label::textWasEdited() | |||
| { | |||
| } | |||
| void Label::textWasChanged() | |||
| { | |||
| } | |||
| void Label::showEditor() | |||
| { | |||
| if (editor == 0) | |||
| @@ -223,6 +227,8 @@ bool Label::updateFromTextEditorContents() | |||
| text = newText; | |||
| repaint(); | |||
| textWasChanged(); | |||
| if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) | |||
| componentMovedOrResized (*ownerComponent, true, true); | |||
| @@ -305,6 +305,10 @@ protected: | |||
| */ | |||
| virtual void textWasEdited(); | |||
| /** Called when the text has been altered. | |||
| */ | |||
| virtual void textWasChanged(); | |||
| private: | |||
| String text; | |||
| Font font; | |||
| @@ -51,7 +51,8 @@ Desktop::Desktop() throw() | |||
| monitorCoordsClipped (2), | |||
| monitorCoordsUnclipped (2), | |||
| lastMouseX (0), | |||
| lastMouseY (0) | |||
| lastMouseY (0), | |||
| kioskModeComponent (0) | |||
| { | |||
| refreshMonitorSizes(); | |||
| } | |||
| @@ -326,4 +327,40 @@ void Desktop::resetTimer() throw() | |||
| getMousePosition (lastMouseX, lastMouseY); | |||
| } | |||
| //============================================================================== | |||
| extern void juce_setKioskComponent (Component* kioskModeComponent, bool enableOrDisable); | |||
| void Desktop::setKioskModeComponent (Component* componentToUse) | |||
| { | |||
| if (kioskModeComponent != componentToUse) | |||
| { | |||
| // agh! Don't delete a component without first stopping it being the kiosk comp | |||
| jassert (kioskModeComponent == 0 || kioskModeComponent->isValidComponent()); | |||
| // agh! Don't remove a component from the desktop if it's the kiosk comp! | |||
| jassert (kioskModeComponent == 0 || kioskModeComponent->isOnDesktop()); | |||
| if (kioskModeComponent->isValidComponent()) | |||
| { | |||
| juce_setKioskComponent (kioskModeComponent, false); | |||
| kioskModeComponent->setBounds (kioskComponentOriginalBounds); | |||
| } | |||
| kioskModeComponent = componentToUse; | |||
| if (kioskModeComponent != 0) | |||
| { | |||
| jassert (kioskModeComponent->isValidComponent()); | |||
| // Only components that are already on the desktop can be put into kiosk mode! | |||
| jassert (kioskModeComponent->isOnDesktop()); | |||
| kioskComponentOriginalBounds = kioskModeComponent->getBounds(); | |||
| juce_setKioskComponent (kioskModeComponent, true); | |||
| } | |||
| } | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -175,6 +175,26 @@ public: | |||
| /** Unregisters a listener that was added with addFocusChangeListener(). */ | |||
| void removeFocusChangeListener (FocusChangeListener* const listener) throw(); | |||
| //============================================================================== | |||
| /** Takes a component and makes it full-screen, removing the taskbar, dock, etc. | |||
| The component must already be on the desktop for this method to work. It will | |||
| be resized to completely fill the screen and any extraneous taskbars, menu bars, | |||
| etc will be hidden. | |||
| To exit kiosk mode, just call setKioskModeComponent (0). When this is called, | |||
| the component that's currently being used will be resized back to the size | |||
| and position it was in before being put into this mode. | |||
| */ | |||
| void setKioskModeComponent (Component* componentToUse); | |||
| /** Returns the component that is currently being used in kiosk-mode. | |||
| This is the component that was last set by setKioskModeComponent(). If none | |||
| has been set, this returns 0. | |||
| */ | |||
| Component* getKioskModeComponent() const { return kioskModeComponent; } | |||
| //============================================================================== | |||
| /** Returns the number of components that are currently active as top-level | |||
| desktop windows. | |||
| @@ -231,6 +251,9 @@ private: | |||
| Array <Rectangle> monitorCoordsClipped, monitorCoordsUnclipped; | |||
| int lastMouseX, lastMouseY; | |||
| Component* kioskModeComponent; | |||
| Rectangle kioskComponentOriginalBounds; | |||
| void timerCallback(); | |||
| void sendMouseMove(); | |||
| void resetTimer() throw(); | |||
| @@ -147,13 +147,23 @@ public: | |||
| You can pass 0 to stop the current model being displayed. Be careful | |||
| not to delete a model while it is being used. | |||
| An optional extra menu can be specified, containing items to add to the top of | |||
| the apple menu. (Confusingly, the 'apple' menu isn't the one with a picture of | |||
| an apple, it's the one next to it, with your application's name at the top | |||
| and the services menu etc on it). When one of these items is selected, the | |||
| menu bar model will be used to invoke it, and in the menuItemSelected() callback | |||
| the topLevelMenuIndex parameter will be -1. If you pass in an extraAppleMenuItems | |||
| object then newMenuBarModel must be non-null. | |||
| */ | |||
| static void setMacMainMenu (MenuBarModel* newMenuBarModel) throw(); | |||
| static void setMacMainMenu (MenuBarModel* newMenuBarModel, | |||
| const PopupMenu* extraAppleMenuItems = 0) throw(); | |||
| /** MAC ONLY - Returns the menu model that is currently being shown as | |||
| the main menu bar. | |||
| */ | |||
| static MenuBarModel* getMacMainMenu() throw(); | |||
| #endif | |||
| //============================================================================== | |||