1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/generic/splash.cpp
3 // Purpose:     wxSplashScreen class
4 // Author:      Julian Smart
5 // Modified by:
6 // Created:     28/6/2000
7 // Copyright:   (c) Julian Smart
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // For compilers that support precompilation, includes "wx/wx.h".
12 #include "wx/wxprec.h"
13 
14 #ifdef __BORLANDC__
15     #pragma hdrstop
16 #endif
17 
18 #if wxUSE_SPLASH
19 
20 #ifdef __WXGTK20__
21     #include <gtk/gtk.h>
22 #endif
23 
24 #include "wx/splash.h"
25 
26 #ifndef WX_PRECOMP
27     #include "wx/dcmemory.h"
28     #include "wx/dcclient.h"
29 #endif
30 
31 
32 // ----------------------------------------------------------------------------
33 // wxSplashScreen
34 // ----------------------------------------------------------------------------
35 
36 #define wxSPLASH_TIMER_ID       9999
37 
IMPLEMENT_DYNAMIC_CLASS(wxSplashScreen,wxFrame)38 IMPLEMENT_DYNAMIC_CLASS(wxSplashScreen, wxFrame)
39 BEGIN_EVENT_TABLE(wxSplashScreen, wxFrame)
40     EVT_TIMER(wxSPLASH_TIMER_ID, wxSplashScreen::OnNotify)
41     EVT_CLOSE(wxSplashScreen::OnCloseWindow)
42 END_EVENT_TABLE()
43 
44 void wxSplashScreen::Init()
45 {
46     m_window = NULL;
47 
48     wxEvtHandler::AddFilter(this);
49 }
50 
51 /* Note that unless we pass a non-default size to the frame, SetClientSize
52  * won't work properly under Windows, and the splash screen frame is sized
53  * slightly too small.
54  */
55 
wxSplashScreen(const wxBitmap & bitmap,long splashStyle,int milliseconds,wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style)56 wxSplashScreen::wxSplashScreen(const wxBitmap& bitmap, long splashStyle, int milliseconds,
57                                wxWindow* parent, wxWindowID id, const wxPoint& pos,
58                                const wxSize& size, long style)
59     : wxFrame(parent, id, wxEmptyString, wxPoint(0,0), wxSize(100, 100),
60               style | wxFRAME_TOOL_WINDOW | wxFRAME_NO_TASKBAR)
61 {
62     Init();
63 
64     // splash screen must not be used as parent by the other windows because it
65     // is going to disappear soon, indicate it by giving it this special style
66     SetExtraStyle(GetExtraStyle() | wxWS_EX_TRANSIENT);
67 
68 #if defined(__WXGTK20__)
69     gtk_window_set_type_hint(GTK_WINDOW(m_widget),
70                              GDK_WINDOW_TYPE_HINT_SPLASHSCREEN);
71 #endif
72 
73     m_splashStyle = splashStyle;
74     m_milliseconds = milliseconds;
75 
76     m_window = new wxSplashScreenWindow(bitmap, this, wxID_ANY, pos, size, wxNO_BORDER);
77 
78     SetClientSize(bitmap.GetWidth(), bitmap.GetHeight());
79 
80     if (m_splashStyle & wxSPLASH_CENTRE_ON_PARENT)
81         CentreOnParent();
82     else if (m_splashStyle & wxSPLASH_CENTRE_ON_SCREEN)
83         CentreOnScreen();
84 
85     if (m_splashStyle & wxSPLASH_TIMEOUT)
86     {
87         m_timer.SetOwner(this, wxSPLASH_TIMER_ID);
88         m_timer.Start(milliseconds, true);
89     }
90 
91     Show(true);
92     m_window->SetFocus();
93 #if defined( __WXMSW__ ) || defined(__WXMAC__)
94     Update(); // Without this, you see a blank screen for an instant
95 #elif defined(__WXGTK20__)
96     // we don't need to do anything at least on wxGTK with GTK+ 2.12.9
97 #else
98     wxYieldIfNeeded(); // Should eliminate this
99 #endif
100 }
101 
~wxSplashScreen()102 wxSplashScreen::~wxSplashScreen()
103 {
104     m_timer.Stop();
105 
106     wxEvtHandler::RemoveFilter(this);
107 }
108 
FilterEvent(wxEvent & event)109 int wxSplashScreen::FilterEvent(wxEvent& event)
110 {
111     const wxEventType t = event.GetEventType();
112     if ( t == wxEVT_KEY_DOWN ||
113             t == wxEVT_LEFT_DOWN ||
114                 t == wxEVT_RIGHT_DOWN ||
115                     t == wxEVT_MIDDLE_DOWN )
116         Close(true);
117 
118     return -1;
119 }
120 
OnNotify(wxTimerEvent & WXUNUSED (event))121 void wxSplashScreen::OnNotify(wxTimerEvent& WXUNUSED(event))
122 {
123     Close(true);
124 }
125 
OnCloseWindow(wxCloseEvent & WXUNUSED (event))126 void wxSplashScreen::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
127 {
128     m_timer.Stop();
129     this->Destroy();
130 }
131 
132 // ----------------------------------------------------------------------------
133 // wxSplashScreenWindow
134 // ----------------------------------------------------------------------------
135 
BEGIN_EVENT_TABLE(wxSplashScreenWindow,wxWindow)136 BEGIN_EVENT_TABLE(wxSplashScreenWindow, wxWindow)
137 #ifdef __WXGTK__
138     EVT_PAINT(wxSplashScreenWindow::OnPaint)
139 #endif
140     EVT_ERASE_BACKGROUND(wxSplashScreenWindow::OnEraseBackground)
141 END_EVENT_TABLE()
142 
143 wxSplashScreenWindow::wxSplashScreenWindow(const wxBitmap& bitmap, wxWindow* parent,
144                                            wxWindowID id, const wxPoint& pos,
145                                            const wxSize& size, long style)
146     : wxWindow(parent, id, pos, size, style)
147 {
148     m_bitmap = bitmap;
149 
150 #if !defined(__WXGTK__) && wxUSE_PALETTE
151     bool hiColour = (wxDisplayDepth() >= 16) ;
152 
153     if (bitmap.GetPalette() && !hiColour)
154     {
155         SetPalette(* bitmap.GetPalette());
156     }
157 #endif
158 }
159 
160 // VZ: why don't we do it under wxGTK?
161 #if !defined(__WXGTK__) && wxUSE_PALETTE
162     #define USE_PALETTE_IN_SPLASH
163 #endif
164 
wxDrawSplashBitmap(wxDC & dc,const wxBitmap & bitmap,int WXUNUSED (x),int WXUNUSED (y))165 static void wxDrawSplashBitmap(wxDC& dc, const wxBitmap& bitmap, int WXUNUSED(x), int WXUNUSED(y))
166 {
167     wxMemoryDC dcMem;
168 
169 #ifdef USE_PALETTE_IN_SPLASH
170     bool hiColour = (wxDisplayDepth() >= 16) ;
171 
172     if (bitmap.GetPalette() && !hiColour)
173     {
174         dcMem.SetPalette(* bitmap.GetPalette());
175     }
176 #endif // USE_PALETTE_IN_SPLASH
177 
178     dcMem.SelectObjectAsSource(bitmap);
179     dc.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), &dcMem, 0, 0, wxCOPY,
180             true /* use mask */);
181     dcMem.SelectObject(wxNullBitmap);
182 
183 #ifdef USE_PALETTE_IN_SPLASH
184     if (bitmap.GetPalette() && !hiColour)
185     {
186         dcMem.SetPalette(wxNullPalette);
187     }
188 #endif // USE_PALETTE_IN_SPLASH
189 }
190 
OnPaint(wxPaintEvent & WXUNUSED (event))191 void wxSplashScreenWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
192 {
193     wxPaintDC dc(this);
194     if (m_bitmap.IsOk())
195         wxDrawSplashBitmap(dc, m_bitmap, 0, 0);
196 }
197 
OnEraseBackground(wxEraseEvent & event)198 void wxSplashScreenWindow::OnEraseBackground(wxEraseEvent& event)
199 {
200     if (event.GetDC() && m_bitmap.IsOk())
201     {
202         wxDrawSplashBitmap(* event.GetDC(), m_bitmap, 0, 0);
203     }
204     else
205     {
206         wxClientDC dc(this);
207         if (m_bitmap.IsOk())
208             wxDrawSplashBitmap(dc, m_bitmap, 0, 0);
209     }
210 }
211 
212 #endif // wxUSE_SPLASH
213