diff options
Diffstat (limited to 'indra/llplugin/slplugin/slplugin.cpp')
-rw-r--r-- | indra/llplugin/slplugin/slplugin.cpp | 163 |
1 files changed, 136 insertions, 27 deletions
diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp index 77240ce546..7d69e1c5cd 100644 --- a/indra/llplugin/slplugin/slplugin.cpp +++ b/indra/llplugin/slplugin/slplugin.cpp @@ -4,30 +4,25 @@ * * @cond * - * $LicenseInfo:firstyear=2008&license=viewergpl$ - * - * Copyright (c) 2008, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ * * @endcond @@ -44,6 +39,7 @@ #if LL_DARWIN #include <Carbon/Carbon.h> + #include "slplugin-objc.h" #endif #if LL_DARWIN || LL_LINUX @@ -51,7 +47,7 @@ #endif /* - On Mac OS, since we call WaitNextEvent, this process will show up in the dock unless we set the LSBackgroundOnly flag in the Info.plist. + On Mac OS, since we call WaitNextEvent, this process will show up in the dock unless we set the LSBackgroundOnly or LSUIElement flag in the Info.plist. Normally non-bundled binaries don't have an info.plist file, but it's possible to embed one in the binary by adding this to the linker flags: @@ -60,7 +56,8 @@ which means adding this to the gcc flags: -Wl,-sectcreate,__TEXT,__info_plist,/path/to/slplugin_info.plist - + + Now that SLPlugin is a bundled app on the Mac, this is no longer necessary (it can just use a regular Info.plist file), but I'm leaving this comment in for posterity. */ #if LL_DARWIN || LL_LINUX @@ -228,10 +225,19 @@ int main(int argc, char **argv) signal(SIGSYS, &crash_handler); // non-existent system call invoked #endif +#if LL_DARWIN + setupCocoa(); + createAutoReleasePool(); +#endif + LLPluginProcessChild *plugin = new LLPluginProcessChild(); plugin->init(port); +#if LL_DARWIN + deleteAutoReleasePool(); +#endif + LLTimer timer; timer.start(); @@ -239,15 +245,114 @@ int main(int argc, char **argv) checkExceptionHandler(); #endif +#if LL_DARWIN + // If the plugin opens a new window (such as the Flash plugin's fullscreen player), we may need to bring this plugin process to the foreground. + // Use this to track the current frontmost window and bring this process to the front if it changes. + WindowRef front_window = NULL; + WindowGroupRef layer_group = NULL; + int window_hack_state = 0; + CreateWindowGroup(kWindowGroupAttrFixedLevel, &layer_group); + if(layer_group) + { + // Start out with a window layer that's way out in front (fixes the problem with the menubar not getting hidden on first switch to fullscreen youtube) + SetWindowGroupName(layer_group, CFSTR("SLPlugin Layer")); + SetWindowGroupLevel(layer_group, kCGOverlayWindowLevel); + } +#endif + +#if LL_DARWIN + EventTargetRef event_target = GetEventDispatcherTarget(); +#endif while(!plugin->isDone()) { +#if LL_DARWIN + createAutoReleasePool(); +#endif timer.reset(); plugin->idle(); #if LL_DARWIN { // Some plugins (webkit at least) will want an event loop. This qualifies. - EventRecord evt; - WaitNextEvent(0, &evt, 0, NULL); + EventRef event; + if(ReceiveNextEvent(0, 0, kEventDurationNoWait, true, &event) == noErr) + { + SendEventToEventTarget (event, event_target); + ReleaseEvent(event); + } + + // Check for a change in this process's frontmost window. + if(FrontWindow() != front_window) + { + ProcessSerialNumber self = { 0, kCurrentProcess }; + ProcessSerialNumber parent = { 0, kNoProcess }; + ProcessSerialNumber front = { 0, kNoProcess }; + Boolean this_is_front_process = false; + Boolean parent_is_front_process = false; + { + // Get this process's parent + ProcessInfoRec info; + info.processInfoLength = sizeof(ProcessInfoRec); + info.processName = NULL; + info.processAppSpec = NULL; + if(GetProcessInformation( &self, &info ) == noErr) + { + parent = info.processLauncher; + } + + // and figure out whether this process or its parent are currently frontmost + if(GetFrontProcess(&front) == noErr) + { + (void) SameProcess(&self, &front, &this_is_front_process); + (void) SameProcess(&parent, &front, &parent_is_front_process); + } + } + + if((FrontWindow() != NULL) && (front_window == NULL)) + { + // Opening the first window + + if(window_hack_state == 0) + { + // Next time through the event loop, lower the window group layer + window_hack_state = 1; + } + + if(layer_group) + { + SetWindowGroup(FrontWindow(), layer_group); + } + + if(parent_is_front_process) + { + // Bring this process's windows to the front. + (void) SetFrontProcess( &self ); + } + + ActivateWindow(FrontWindow(), true); + } + else if((FrontWindow() == NULL) && (front_window != NULL)) + { + // Closing the last window + + if(this_is_front_process) + { + // Try to bring this process's parent to the front + (void) SetFrontProcess(&parent); + } + } + else if(window_hack_state == 1) + { + if(layer_group) + { + // Set the window group level back to something less extreme + SetWindowGroupLevel(layer_group, kCGNormalWindowLevel); + } + window_hack_state = 2; + } + + front_window = FrontWindow(); + + } } #endif F64 elapsed = timer.getElapsedTimeF64(); @@ -280,6 +385,10 @@ int main(int argc, char **argv) // exception handler such as QuickTime. //checkExceptionHandler(); #endif + +#if LL_DARWIN + deleteAutoReleasePool(); +#endif } delete plugin; |