| @@ -2573,6 +2573,13 @@ private: | |||||
| Array <Atom> srcMimeTypeAtomList; | 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*/) | ComponentPeer* Component::createNewPeer (int styleFlags, void* /*nativeWindowToAttachTo*/) | ||||
| { | { | ||||
| @@ -95,7 +95,7 @@ public: | |||||
| } | } | ||||
| void addSubMenu (NSMenu* parent, const PopupMenu& child, | 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) | NSMenuItem* item = [parent addItemWithTitle: juceStringToNS (name) | ||||
| action: nil | action: nil | ||||
| @@ -181,98 +181,102 @@ public: | |||||
| MenuBarModel* currentModel; | 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]; | [m update]; | ||||
| return m; | return m; | ||||
| @@ -315,49 +319,22 @@ END_JUCE_NAMESPACE | |||||
| BEGIN_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; | 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... | // Services... | ||||
| item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Services", nil) | item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Services", nil) | ||||
| action: nil keyEquivalent: @""]; | 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... | // 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; | const ScopedAutoReleasePool pool; | ||||
| @@ -418,12 +398,50 @@ void initialiseMainMenu() | |||||
| [mainMenu setSubmenu: appMenu forItem: item]; | [mainMenu setSubmenu: appMenu forItem: item]; | ||||
| [NSApp setMainMenu: mainMenu]; | [NSApp setMainMenu: mainMenu]; | ||||
| createStandardAppMenu (appMenu, JUCEApplication::getInstance()->getApplicationName()); | |||||
| createStandardAppMenu (appMenu, JUCEApplication::getInstance()->getApplicationName(), extraItems); | |||||
| [appMenu release]; | [appMenu release]; | ||||
| [mainMenu 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 | #endif | ||||
| @@ -110,8 +110,6 @@ public: | |||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| using namespace JUCE_NAMESPACE; | using namespace JUCE_NAMESPACE; | ||||
| typedef void (*juce_HandleProcessFocusChangeFunction)(); | |||||
| #define JuceAppDelegate MakeObjCClassName(JuceAppDelegate) | #define JuceAppDelegate MakeObjCClassName(JuceAppDelegate) | ||||
| @interface JuceAppDelegate : NSObject | @interface JuceAppDelegate : NSObject | ||||
| @@ -1062,9 +1062,16 @@ void juce_HandleProcessFocusChange() | |||||
| if (NSViewComponentPeer::isValidPeer (currentlyFocusedPeer)) | if (NSViewComponentPeer::isValidPeer (currentlyFocusedPeer)) | ||||
| { | { | ||||
| if (Process::isForegroundProcess()) | if (Process::isForegroundProcess()) | ||||
| { | |||||
| currentlyFocusedPeer->handleFocusGain(); | currentlyFocusedPeer->handleFocusGain(); | ||||
| } | |||||
| else | else | ||||
| { | |||||
| currentlyFocusedPeer->handleFocusLoss(); | currentlyFocusedPeer->handleFocusLoss(); | ||||
| // turn kiosk mode off if we lose focus.. | |||||
| Desktop::getInstance().setKioskModeComponent (0); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1337,6 +1344,23 @@ void NSViewComponentPeer::redirectMovedOrResized() | |||||
| handleMovedOrResized(); | 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) | 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 | // so this forces an update when the app is brought to the front | ||||
| if (wParam != FALSE) | if (wParam != FALSE) | ||||
| juce_repeatLastProcessPriority(); | juce_repeatLastProcessPriority(); | ||||
| else | |||||
| Desktop::getInstance().setKioskModeComponent (0); // turn kiosk mode off if we lose focus | |||||
| juce_CheckCurrentlyFocusedTopLevelWindow(); | juce_CheckCurrentlyFocusedTopLevelWindow(); | ||||
| modifiersAtLastCallback = -1; | modifiersAtLastCallback = -1; | ||||
| @@ -2299,6 +2301,13 @@ bool Desktop::isScreenSaverEnabled() throw() | |||||
| return screenSaverAllowed; | 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) | static BOOL CALLBACK enumMonitorsProc (HMONITOR, HDC, LPRECT r, LPARAM userInfo) | ||||
| { | { | ||||
| @@ -121,7 +121,8 @@ class ContentComp : public Component, | |||||
| setDefaultLookAndFeel = 0x200b, | setDefaultLookAndFeel = 0x200b, | ||||
| setOldSchoolLookAndFeel = 0x200c, | setOldSchoolLookAndFeel = 0x200c, | ||||
| useNativeTitleBar = 0x200d, | useNativeTitleBar = 0x200d, | ||||
| useNativeMenus = 0x200e | |||||
| useNativeMenus = 0x200e, | |||||
| goToKioskMode = 0x200f | |||||
| }; | }; | ||||
| public: | public: | ||||
| @@ -223,6 +224,10 @@ public: | |||||
| #if JUCE_MAC | #if JUCE_MAC | ||||
| menu.addCommandItem (commandManager, useNativeMenus); | menu.addCommandItem (commandManager, useNativeMenus); | ||||
| #endif | #endif | ||||
| #if ! JUCE_LINUX | |||||
| menu.addCommandItem (commandManager, goToKioskMode); | |||||
| #endif | |||||
| } | } | ||||
| return menu; | return menu; | ||||
| @@ -268,6 +273,10 @@ public: | |||||
| #if JUCE_MAC | #if JUCE_MAC | ||||
| , useNativeMenus | , useNativeMenus | ||||
| #endif | #endif | ||||
| #if ! JUCE_LINUX | |||||
| , goToKioskMode | |||||
| #endif | |||||
| }; | }; | ||||
| commands.addArray (ids, numElementsInArray (ids)); | commands.addArray (ids, numElementsInArray (ids)); | ||||
| @@ -381,6 +390,13 @@ public: | |||||
| break; | break; | ||||
| #endif | #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: | default: | ||||
| break; | break; | ||||
| }; | }; | ||||
| @@ -482,6 +498,20 @@ public: | |||||
| break; | break; | ||||
| #endif | #endif | ||||
| #if ! JUCE_LINUX | |||||
| case goToKioskMode: | |||||
| if (Desktop::getInstance().getKioskModeComponent() == 0) | |||||
| { | |||||
| Desktop::getInstance().setKioskModeComponent (getTopLevelComponent()); | |||||
| } | |||||
| else | |||||
| { | |||||
| Desktop::getInstance().setKioskModeComponent (0); | |||||
| } | |||||
| break; | |||||
| #endif | |||||
| default: | default: | ||||
| return false; | return false; | ||||
| }; | }; | ||||
| @@ -40219,7 +40219,8 @@ Desktop::Desktop() throw() | |||||
| monitorCoordsClipped (2), | monitorCoordsClipped (2), | ||||
| monitorCoordsUnclipped (2), | monitorCoordsUnclipped (2), | ||||
| lastMouseX (0), | lastMouseX (0), | ||||
| lastMouseY (0) | |||||
| lastMouseY (0), | |||||
| kioskModeComponent (0) | |||||
| { | { | ||||
| refreshMonitorSizes(); | refreshMonitorSizes(); | ||||
| } | } | ||||
| @@ -40487,6 +40488,40 @@ void Desktop::resetTimer() throw() | |||||
| getMousePosition (lastMouseX, lastMouseY); | 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_JUCE_NAMESPACE | ||||
| /********* End of inlined file: juce_Desktop.cpp *********/ | /********* End of inlined file: juce_Desktop.cpp *********/ | ||||
| @@ -42660,13 +42695,13 @@ void Label::setText (const String& newText, | |||||
| text = newText; | text = newText; | ||||
| repaint(); | repaint(); | ||||
| textWasChanged(); | |||||
| if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) | if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) | ||||
| { | |||||
| componentMovedOrResized (*ownerComponent, true, true); | componentMovedOrResized (*ownerComponent, true, true); | ||||
| if (broadcastChangeMessage) | |||||
| callChangeListeners(); | |||||
| } | |||||
| if (broadcastChangeMessage) | |||||
| callChangeListeners(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -42770,6 +42805,10 @@ void Label::textWasEdited() | |||||
| { | { | ||||
| } | } | ||||
| void Label::textWasChanged() | |||||
| { | |||||
| } | |||||
| void Label::showEditor() | void Label::showEditor() | ||||
| { | { | ||||
| if (editor == 0) | if (editor == 0) | ||||
| @@ -42799,6 +42838,8 @@ bool Label::updateFromTextEditorContents() | |||||
| text = newText; | text = newText; | ||||
| repaint(); | repaint(); | ||||
| textWasChanged(); | |||||
| if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) | if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) | ||||
| componentMovedOrResized (*ownerComponent, true, true); | componentMovedOrResized (*ownerComponent, true, true); | ||||
| @@ -242642,6 +242683,8 @@ private: | |||||
| // so this forces an update when the app is brought to the front | // so this forces an update when the app is brought to the front | ||||
| if (wParam != FALSE) | if (wParam != FALSE) | ||||
| juce_repeatLastProcessPriority(); | juce_repeatLastProcessPriority(); | ||||
| else | |||||
| Desktop::getInstance().setKioskModeComponent (0); // turn kiosk mode off if we lose focus | |||||
| juce_CheckCurrentlyFocusedTopLevelWindow(); | juce_CheckCurrentlyFocusedTopLevelWindow(); | ||||
| modifiersAtLastCallback = -1; | modifiersAtLastCallback = -1; | ||||
| @@ -242969,6 +243012,12 @@ bool Desktop::isScreenSaverEnabled() throw() | |||||
| return screenSaverAllowed; | 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) | static BOOL CALLBACK enumMonitorsProc (HMONITOR, HDC, LPRECT r, LPARAM userInfo) | ||||
| { | { | ||||
| Array <Rectangle>* const monitorCoords = (Array <Rectangle>*) userInfo; | Array <Rectangle>* const monitorCoords = (Array <Rectangle>*) userInfo; | ||||
| @@ -261216,6 +261265,12 @@ private: | |||||
| Array <Atom> srcMimeTypeAtomList; | 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*/) | ComponentPeer* Component::createNewPeer (int styleFlags, void* /*nativeWindowToAttachTo*/) | ||||
| { | { | ||||
| return new LinuxComponentPeer (this, styleFlags); | return new LinuxComponentPeer (this, styleFlags); | ||||
| @@ -265133,9 +265188,16 @@ void juce_HandleProcessFocusChange() | |||||
| if (NSViewComponentPeer::isValidPeer (currentlyFocusedPeer)) | if (NSViewComponentPeer::isValidPeer (currentlyFocusedPeer)) | ||||
| { | { | ||||
| if (Process::isForegroundProcess()) | if (Process::isForegroundProcess()) | ||||
| { | |||||
| currentlyFocusedPeer->handleFocusGain(); | currentlyFocusedPeer->handleFocusGain(); | ||||
| } | |||||
| else | else | ||||
| { | |||||
| currentlyFocusedPeer->handleFocusLoss(); | currentlyFocusedPeer->handleFocusLoss(); | ||||
| // turn kiosk mode off if we lose focus.. | |||||
| Desktop::getInstance().setKioskModeComponent (0); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -265406,6 +265468,22 @@ void NSViewComponentPeer::redirectMovedOrResized() | |||||
| handleMovedOrResized(); | 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) | void NSViewComponentPeer::repaint (int x, int y, int w, int h) | ||||
| { | { | ||||
| [view setNeedsDisplayInRect: | [view setNeedsDisplayInRect: | ||||
| @@ -266306,7 +266384,7 @@ public: | |||||
| } | } | ||||
| void addSubMenu (NSMenu* parent, const PopupMenu& child, | 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) | NSMenuItem* item = [parent addItemWithTitle: juceStringToNS (name) | ||||
| action: nil | action: nil | ||||
| @@ -266392,98 +266470,102 @@ public: | |||||
| MenuBarModel* currentModel; | 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]; | [m update]; | ||||
| return m; | return m; | ||||
| @@ -266526,47 +266608,21 @@ END_JUCE_NAMESPACE | |||||
| BEGIN_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; | 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... | // Services... | ||||
| item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Services", nil) | item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString (@"Services", nil) | ||||
| action: nil keyEquivalent: @""]; | 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... | // 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; | const ScopedAutoReleasePool pool; | ||||
| @@ -266627,13 +266686,50 @@ void initialiseMainMenu() | |||||
| [mainMenu setSubmenu: appMenu forItem: item]; | [mainMenu setSubmenu: appMenu forItem: item]; | ||||
| [NSApp setMainMenu: mainMenu]; | [NSApp setMainMenu: mainMenu]; | ||||
| createStandardAppMenu (appMenu, JUCEApplication::getInstance()->getApplicationName()); | |||||
| createStandardAppMenu (appMenu, JUCEApplication::getInstance()->getApplicationName(), extraItems); | |||||
| [appMenu release]; | [appMenu release]; | ||||
| [mainMenu 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 | #endif | ||||
| /********* End of inlined file: juce_mac_MainMenu.mm *********/ | /********* End of inlined file: juce_mac_MainMenu.mm *********/ | ||||
| @@ -268007,8 +268103,6 @@ public: | |||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| using namespace JUCE_NAMESPACE; | using namespace JUCE_NAMESPACE; | ||||
| typedef void (*juce_HandleProcessFocusChangeFunction)(); | |||||
| #define JuceAppDelegate MakeObjCClassName(JuceAppDelegate) | #define JuceAppDelegate MakeObjCClassName(JuceAppDelegate) | ||||
| @interface JuceAppDelegate : NSObject | @interface JuceAppDelegate : NSObject | ||||
| @@ -23677,6 +23677,25 @@ public: | |||||
| /** Unregisters a listener that was added with addFocusChangeListener(). */ | /** Unregisters a listener that was added with addFocusChangeListener(). */ | ||||
| void removeFocusChangeListener (FocusChangeListener* const listener) throw(); | 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 | /** Returns the number of components that are currently active as top-level | ||||
| desktop windows. | desktop windows. | ||||
| @@ -23729,6 +23748,9 @@ private: | |||||
| Array <Rectangle> monitorCoordsClipped, monitorCoordsUnclipped; | Array <Rectangle> monitorCoordsClipped, monitorCoordsUnclipped; | ||||
| int lastMouseX, lastMouseY; | int lastMouseX, lastMouseY; | ||||
| Component* kioskModeComponent; | |||||
| Rectangle kioskComponentOriginalBounds; | |||||
| void timerCallback(); | void timerCallback(); | ||||
| void sendMouseMove(); | void sendMouseMove(); | ||||
| void resetTimer() throw(); | void resetTimer() throw(); | ||||
| @@ -33290,6 +33312,10 @@ protected: | |||||
| */ | */ | ||||
| virtual void textWasEdited(); | virtual void textWasEdited(); | ||||
| /** Called when the text has been altered. | |||||
| */ | |||||
| virtual void textWasChanged(); | |||||
| private: | private: | ||||
| String text; | String text; | ||||
| Font font; | Font font; | ||||
| @@ -43159,13 +43185,23 @@ public: | |||||
| You can pass 0 to stop the current model being displayed. Be careful | You can pass 0 to stop the current model being displayed. Be careful | ||||
| not to delete a model while it is being used. | 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 | /** MAC ONLY - Returns the menu model that is currently being shown as | ||||
| the main menu bar. | the main menu bar. | ||||
| */ | */ | ||||
| static MenuBarModel* getMacMainMenu() throw(); | static MenuBarModel* getMacMainMenu() throw(); | ||||
| #endif | #endif | ||||
| /** @internal */ | /** @internal */ | ||||
| @@ -82,13 +82,13 @@ void Label::setText (const String& newText, | |||||
| text = newText; | text = newText; | ||||
| repaint(); | repaint(); | ||||
| textWasChanged(); | |||||
| if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) | if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) | ||||
| { | |||||
| componentMovedOrResized (*ownerComponent, true, true); | componentMovedOrResized (*ownerComponent, true, true); | ||||
| if (broadcastChangeMessage) | |||||
| callChangeListeners(); | |||||
| } | |||||
| if (broadcastChangeMessage) | |||||
| callChangeListeners(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -194,6 +194,10 @@ void Label::textWasEdited() | |||||
| { | { | ||||
| } | } | ||||
| void Label::textWasChanged() | |||||
| { | |||||
| } | |||||
| void Label::showEditor() | void Label::showEditor() | ||||
| { | { | ||||
| if (editor == 0) | if (editor == 0) | ||||
| @@ -223,6 +227,8 @@ bool Label::updateFromTextEditorContents() | |||||
| text = newText; | text = newText; | ||||
| repaint(); | repaint(); | ||||
| textWasChanged(); | |||||
| if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) | if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted()) | ||||
| componentMovedOrResized (*ownerComponent, true, true); | componentMovedOrResized (*ownerComponent, true, true); | ||||
| @@ -305,6 +305,10 @@ protected: | |||||
| */ | */ | ||||
| virtual void textWasEdited(); | virtual void textWasEdited(); | ||||
| /** Called when the text has been altered. | |||||
| */ | |||||
| virtual void textWasChanged(); | |||||
| private: | private: | ||||
| String text; | String text; | ||||
| Font font; | Font font; | ||||
| @@ -51,7 +51,8 @@ Desktop::Desktop() throw() | |||||
| monitorCoordsClipped (2), | monitorCoordsClipped (2), | ||||
| monitorCoordsUnclipped (2), | monitorCoordsUnclipped (2), | ||||
| lastMouseX (0), | lastMouseX (0), | ||||
| lastMouseY (0) | |||||
| lastMouseY (0), | |||||
| kioskModeComponent (0) | |||||
| { | { | ||||
| refreshMonitorSizes(); | refreshMonitorSizes(); | ||||
| } | } | ||||
| @@ -326,4 +327,40 @@ void Desktop::resetTimer() throw() | |||||
| getMousePosition (lastMouseX, lastMouseY); | 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_JUCE_NAMESPACE | ||||
| @@ -175,6 +175,26 @@ public: | |||||
| /** Unregisters a listener that was added with addFocusChangeListener(). */ | /** Unregisters a listener that was added with addFocusChangeListener(). */ | ||||
| void removeFocusChangeListener (FocusChangeListener* const listener) throw(); | 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 | /** Returns the number of components that are currently active as top-level | ||||
| desktop windows. | desktop windows. | ||||
| @@ -231,6 +251,9 @@ private: | |||||
| Array <Rectangle> monitorCoordsClipped, monitorCoordsUnclipped; | Array <Rectangle> monitorCoordsClipped, monitorCoordsUnclipped; | ||||
| int lastMouseX, lastMouseY; | int lastMouseX, lastMouseY; | ||||
| Component* kioskModeComponent; | |||||
| Rectangle kioskComponentOriginalBounds; | |||||
| void timerCallback(); | void timerCallback(); | ||||
| void sendMouseMove(); | void sendMouseMove(); | ||||
| void resetTimer() throw(); | void resetTimer() throw(); | ||||
| @@ -147,13 +147,23 @@ public: | |||||
| You can pass 0 to stop the current model being displayed. Be careful | You can pass 0 to stop the current model being displayed. Be careful | ||||
| not to delete a model while it is being used. | 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 | /** MAC ONLY - Returns the menu model that is currently being shown as | ||||
| the main menu bar. | the main menu bar. | ||||
| */ | */ | ||||
| static MenuBarModel* getMacMainMenu() throw(); | static MenuBarModel* getMacMainMenu() throw(); | ||||
| #endif | #endif | ||||
| //============================================================================== | //============================================================================== | ||||