/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ /* Splash.cpp -- class for dealing with the unix splash screen. Created: Chris Toshok , 21-Dec-1996. */ #include "Splash.h" #include "DisplayFactory.h" #include "xpassert.h" #include "prefapi.h" #include #include #include #include "private/prpriv.h" /* For PR_NewNamedMonitor */ #ifdef DEBUG_username #define D(x) x #else #define D(x) #endif struct XFE_SplashEvent { PREvent event; /* the PREvent structure */ char *text; /* the new text to be displayed. */ XFE_Splash *splash; /* the splash screen object we're going to muck with. */ }; static XFE_Splash *xfe_splash = NULL; extern fe_icon_data Splash; extern "C" Colormap fe_getColormap(fe_colormap *colormap); fe_icon XFE_Splash::splash_icon = { 0 }; XFE_Splash::XFE_Splash(Widget toplevel) { Arg av[10]; int ac; fe_colormap *cmap = XFE_DisplayFactory::theFactory()->getSharedColormap(); m_exposemonitor = PR_NewNamedMonitor("expose-monitor"); m_eventmonitor = PR_NewNamedMonitor("event-monitor"); m_stopmonitor = PR_NewNamedMonitor("stop-monitor"); m_done = 0; m_context = XP_NewContext(); m_context->fe.data = XP_NEW_ZAP(fe_ContextData); m_thread = PR_CreateThread(PR_USER_THREAD, splashThreadProc, this, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); /* default stack size */ m_eventqueue = PR_CreateEventQueue("splash-events", m_thread); ac = 0; XtSetArg(av[ac], XmNwidth, 1); ac++; XtSetArg(av[ac], XmNheight, 1); ac++; XtSetArg(av[ac], XmNcolormap, fe_getColormap(cmap)); ac++; XtSetArg(av[ac], XmNvisual, XFE_DisplayFactory::theFactory()->getVisual()); ac++; XtSetArg(av[ac], XmNdepth, XFE_DisplayFactory::theFactory()->getVisualDepth()); ac++; m_shell = XtCreatePopupShell("splashShell", xmMenuShellWidgetClass, toplevel, av, ac); m_rc = XtVaCreateManagedWidget("splashRC", xmRowColumnWidgetClass, m_shell, XmNspacing, 0, NULL); CONTEXT_WIDGET(m_context) = m_shell; CONTEXT_DATA (m_context)->colormap = cmap; setBaseWidget(m_shell); XtGetApplicationResources (m_widget, (XtPointer) CONTEXT_DATA (m_context), fe_Resources, fe_ResourcesSize, 0, 0); fe_InitIconColors(m_context); fe_init_image_callbacks(m_context); fe_InitColormap (m_context); //PREF_AlterSplashIcon(&Splash); fe_NewMakeIcon(m_shell, BlackPixelOfScreen(XtScreen(m_shell)), //XXX hack... doesn't really matter though. BlackPixelOfScreen(XtScreen(m_shell)), //XXX hack... doesn't really matter though. &splash_icon, NULL, Splash.width, Splash.height, Splash.mono_bits, Splash.color_bits, Splash.mask_bits, FALSE); XP_ASSERT(splash_icon.pixmap); m_splashlabel = XtVaCreateManagedWidget("splashPixmap", xmLabelWidgetClass, m_rc, XmNlabelType, XmPIXMAP, XmNlabelPixmap, splash_icon.pixmap, NULL); m_statuslabel = XtVaCreateManagedWidget("splashStatus", xmLabelWidgetClass, m_rc, NULL); XtAddEventHandler(m_splashlabel, ExposureMask, False, splashExpose_eh, this); } XFE_Splash::~XFE_Splash() { if(m_eventqueue) PR_DestroyEventQueue(m_eventqueue); if (m_eventmonitor) PR_DestroyMonitor(m_eventmonitor); fe_DisposeColormap(m_context); XP_FREE(CONTEXT_DATA(m_context)); XP_FREE(m_context); } void XFE_Splash::splashExpose() { PR_EnterMonitor(m_exposemonitor); PR_Notify(m_exposemonitor); PR_ExitMonitor(m_exposemonitor); XtRemoveEventHandler(m_splashlabel, ExposureMask, False, splashExpose_eh, this); } void XFE_Splash::splashExpose_eh(Widget, XtPointer closure, XEvent *, Boolean *) { XFE_Splash *splash = (XFE_Splash*)closure; splash->splashExpose(); } /* Caller must wrap calls to show() in PR_XLock and PR_XUnlock. */ void XFE_Splash::show() { Dimension height_of_splash, width_of_splash; Dimension height_of_screen = HeightOfScreen(XtScreen(m_shell)), width_of_screen = WidthOfScreen(XtScreen(m_shell)); XtRealizeWidget(m_shell); XtVaGetValues(m_shell, XmNwidth, &width_of_splash, XmNheight, &height_of_splash, NULL); XtVaSetValues(m_shell, XmNx, width_of_screen / 2 - width_of_splash / 2, XmNy, height_of_screen / 2 - height_of_splash / 2, NULL); XtPopup(m_shell, XtGrabNone); XSync(XtDisplay(m_shell), False); } /* Caller must wrap calls to hide() in PR_XLock and PR_XUnlock. */ void XFE_Splash::hide() { XtPopdown(m_shell); XSync(XtDisplay(m_shell), False); } void XFE_Splash::waitForExpose() { PR_EnterMonitor(m_exposemonitor); PR_Wait(m_exposemonitor, PR_INTERVAL_NO_TIMEOUT); PR_ExitMonitor(m_exposemonitor); PR_DestroyMonitor(m_exposemonitor); } void XFE_Splash::setStatus(char *text) { XmString xmstr = XmStringCreate(text, XmFONTLIST_DEFAULT_TAG); XtVaSetValues(m_statuslabel, XmNlabelString, xmstr, NULL); XmStringFree(xmstr); XSync(XtDisplay(m_statuslabel), False); PR_EnterMonitor(m_eventmonitor); PR_Notify(m_eventmonitor); PR_ExitMonitor(m_eventmonitor); } void XFE_Splash::update_text_handler(XFE_SplashEvent *event) { XP_ASSERT(event->text); event->splash->setStatus(event->text); } void XFE_Splash::update_text_destructor(XFE_SplashEvent *event) { XP_FREE(event); } PRThread * XFE_Splash::getThread() { return m_thread; } PREventQueue * XFE_Splash::getEventQueue() { return m_eventqueue; } PRMonitor * XFE_Splash::getEventMonitor() { return m_eventmonitor; } PRMonitor * XFE_Splash::getStopMonitor() { return m_stopmonitor; } void XFE_Splash::splashThreadProc() { PREvent * event; for (;;) { PR_EnterMonitor(m_stopmonitor); if (m_done) { PR_ExitMonitor(m_stopmonitor); return; } else { PR_ExitMonitor(m_stopmonitor); } PR_XLock(); XtInputMask pending = XtAppPending(fe_XtAppContext); /* if there was a pending X event, handle it now */ if (pending) XtAppProcessEvent(fe_XtAppContext, pending); PR_EnterMonitor(m_eventmonitor); event = PR_GetEvent(m_eventqueue); PR_ExitMonitor(m_eventmonitor); /* if we got an nspr event (telling us to update our status) do it */ if (event) { PR_HandleEvent(event); PR_DestroyEvent(event); } PR_XUnlock(); } } void XFE_Splash::splashThreadProc(void *a) { XFE_Splash *splash = (XFE_Splash*)a; PRMonitor *monitor = splash->getStopMonitor(); splash->splashThreadProc(); delete splash; PR_EnterMonitor(monitor); PR_Notify(monitor); PR_ExitMonitor(monitor); D(printf ("exiting the splash thread\n");) } void fe_splashStart(Widget toplevel) { XP_ASSERT(!xfe_splash); xfe_splash = new XFE_Splash(toplevel); PR_XLock(); xfe_splash->show(); PR_XUnlock(); xfe_splash->waitForExpose(); } void fe_splashUpdateText(char *text) { XP_ASSERT(xfe_splash); D(printf ("fe_splashUpdateText('%s')\n", text);) PRMonitor *monitor = xfe_splash->getEventMonitor(); XFE_SplashEvent *event = XP_NEW_ZAP(XFE_SplashEvent); PR_InitEvent(&event->event, NULL, (PRHandleEventProc)XFE_Splash::update_text_handler, (PRDestroyEventProc)XFE_Splash::update_text_destructor); event->text = text; event->splash = xfe_splash; PR_PostEvent(xfe_splash->getEventQueue(), &event->event); if (monitor) { /* wake up the processing routine */ PR_EnterMonitor(monitor); PR_Notify(monitor); PR_ExitMonitor(monitor); /* now we wait until it actually happens. */ PR_EnterMonitor(monitor); PR_Wait(monitor, PR_INTERVAL_NO_TIMEOUT); PR_ExitMonitor(monitor); } } void fe_splashStop(void) { XP_ASSERT(xfe_splash); D(printf ("fe_splashStop()\n");) PRMonitor *monitor = xfe_splash->getStopMonitor(); XP_ASSERT(monitor); /* first we tell the splash screen to stop */ PR_EnterMonitor(monitor); xfe_splash->m_done = 1; PR_ExitMonitor(monitor); /* now we wait until it actually happens. */ PR_EnterMonitor(monitor); PR_Wait(monitor, PR_INTERVAL_NO_TIMEOUT); PR_ExitMonitor(monitor); PR_DestroyMonitor(monitor); }