2 Copyright (C) 2008 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "pbd/failed_constructor.h"
23 #include "pbd/file_utils.h"
25 #include "ardour/ardour.h"
26 #include "ardour/filesystem_paths.h"
28 #include "gtkmm2ext/utils.h"
34 #include "gui_thread.h"
43 using namespace ARDOUR;
45 Splash* Splash::the_splash = 0;
49 assert (the_splash == 0);
51 std::string splash_file;
53 Searchpath rc (ARDOUR::ardour_data_search_path());
54 rc.add_subdirectory_to_paths ("resources");
56 if (!find_file (rc, PROGRAM_NAME "-splash.png", splash_file)) {
57 cerr << "Cannot find splash screen image file\n";
58 throw failed_constructor();
62 pixbuf = Gdk::Pixbuf::create_from_file (splash_file);
66 cerr << "Cannot construct splash screen image\n";
67 throw failed_constructor();
70 darea.set_size_request (pixbuf->get_width(), pixbuf->get_height());
72 set_position (WIN_POS_CENTER);
73 darea.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
74 darea.set_double_buffered (false);
76 layout = create_pango_layout ("");
78 string i18n = string_compose (_("%1 loading ..."), PROGRAM_NAME);
82 layout->set_markup (str);
85 darea.signal_expose_event().connect (sigc::mem_fun (*this, &Splash::expose));
89 set_default_size (pixbuf->get_width(), pixbuf->get_height());
90 set_resizable (false);
91 set_type_hint(Gdk::WINDOW_TYPE_HINT_SPLASHSCREEN);
95 expose_is_the_one = false;
97 ARDOUR::BootMessage.connect (msg_connection, invalidator (*this), boost::bind (&Splash::boot_message, this, _1), gui_context());
106 Splash::pop_back_for (Gtk::Window& win)
108 #if defined __APPLE__ || defined PLATFORM_WINDOWS
109 /* April 2013: window layering on OS X is a bit different to X Window. at present,
110 the "restack()" functionality in GDK will only operate on windows in the same
111 "level" (e.g. two normal top level windows, or two utility windows) and will not
112 work across them. The splashscreen is on its own "StatusWindowLevel" so restacking
113 is not going to work.
115 So for OS X, we just hide ourselves.
117 Oct 2014: The Windows situation is similar, although it should be possible
118 to play tricks with gdk's set_type_hint() or directly hack things using
119 SetWindowLong() and UpdateLayeredWindow()
124 set_keep_above (false);
125 get_window()->restack (win.get_window(), false);
133 #if defined __APPLE__ || defined PLATFORM_WINDOWS
141 Splash::on_realize ()
143 Window::on_realize ();
144 get_window()->set_decorations (Gdk::WMDecoration(0));
145 layout->set_font_description (get_style()->get_font());
149 Splash::on_button_release_event (GdkEventButton* ev)
151 RefPtr<Gdk::Window> window = get_window();
153 if (!window || ev->window != window->gobj()) {
162 Splash::expose (GdkEventExpose* ev)
164 RefPtr<Gdk::Window> window = darea.get_window();
166 /* note: height & width need to be constrained to the pixbuf size
167 in case a WM provides us with a screwy allocation
170 window->draw_pixbuf (get_style()->get_bg_gc (STATE_NORMAL), pixbuf,
171 ev->area.x, ev->area.y,
172 ev->area.x, ev->area.y,
173 min ((pixbuf->get_width() - ev->area.x), ev->area.width),
174 min ((pixbuf->get_height() - ev->area.y), ev->area.height),
175 Gdk::RGB_DITHER_NONE, 0, 0);
177 Glib::RefPtr<Gtk::Style> style = darea.get_style();
178 Glib::RefPtr<Gdk::GC> white = style->get_white_gc();
180 window->draw_layout (white, 10, pixbuf->get_height() - 30, layout);
182 /* this must execute AFTER the GDK idle update mechanism
185 if (expose_is_the_one) {
186 Glib::signal_idle().connect (sigc::mem_fun (this, &Splash::idle_after_expose),
187 GDK_PRIORITY_REDRAW+2);
194 Splash::boot_message (std::string msg)
200 Splash::idle_after_expose ()
209 bool was_mapped = is_mapped ();
213 expose_is_the_one = false;
220 while (!expose_done) {
221 gtk_main_iteration ();
223 gdk_display_flush (gdk_display_get_default());
228 Splash::message (const string& msg)
231 str += Gtkmm2ext::markup_escape_text (msg);
236 layout->set_markup (str);
237 Glib::RefPtr<Gdk::Window> win = darea.get_window();
242 if (win->is_visible ()) {
243 win->invalidate_rect (Gdk::Rectangle (0, darea.get_height() - 30, darea.get_width(), 30), true);
251 Splash::on_map_event (GdkEventAny* ev)
253 expose_is_the_one = true;
254 return Window::on_map_event (ev);