diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 3f84bb441e..87db3f1edc 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -2769,6 +2769,7 @@ make_splash_window() { int r, g, b; if (parse_color(r, g, b, _fparams.lookup_token("bgcolor"))) { _splash_window->set_bgcolor(r, g, b); + _splash_window->set_bar_bgcolor(r, g, b); } else { nout << "parse failure on bgcolor " << _fparams.lookup_token("bgcolor") << "\n"; } @@ -2781,11 +2782,58 @@ make_splash_window() { nout << "parse failure on barcolor " << _fparams.lookup_token("barcolor") << "\n"; } } + if (_fparams.has_token("bar_bgcolor")) { + int r, g, b; + if (parse_color(r, g, b, _fparams.lookup_token("bar_bgcolor"))) { + _splash_window->set_bar_bgcolor(r, g, b); + } else { + nout << "parse failure on bar_bgcolor " << _fparams.lookup_token("bar_bgcolor") << "\n"; + } + } + if (_fparams.has_token("bar_border")) { + int border = _fparams.lookup_token_int("bar_border"); + _splash_window->set_bar_border(border); + } + if (_fparams.has_token("bar_bottom")) { + int bottom = _fparams.lookup_token_int("bar_bottom"); + _splash_window->set_bar_bottom(bottom); + } + if (_fparams.has_token("bar_width")) { + string bar_width = _fparams.lookup_token("bar_width"); + char *endptr; + long width = strtol(bar_width.c_str(), &endptr, 10); + bool percent = false; + + if (*endptr == '%') { + percent = true; + ++endptr; + } + if (*endptr == '\0' && width >= 0 && width < 65536) { + _splash_window->set_bar_width((int)width, percent); + } else { + nout << "parse failure on bar_width " << bar_width << "\n"; + } + } + if (_fparams.has_token("bar_height")) { + string bar_height = _fparams.lookup_token("bar_height"); + char *endptr; + long height = strtol(bar_height.c_str(), &endptr, 10); + bool percent = false; + + if (*endptr == '%') { + percent = true; + ++endptr; + } + if (*endptr == '\0' && height >= 0 && height < 65536) { + _splash_window->set_bar_height((int)height, percent); + } else { + nout << "parse failure on bar_height " << bar_height << "\n"; + } + } _splash_window->set_wparams(_wparams); _splash_window->set_install_label(_install_label); - - + P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); // Go get the required images. diff --git a/direct/src/plugin/p3dSplashWindow.cxx b/direct/src/plugin/p3dSplashWindow.cxx index cbe58a50e2..d9dcd802dd 100644 --- a/direct/src/plugin/p3dSplashWindow.cxx +++ b/direct/src/plugin/p3dSplashWindow.cxx @@ -48,6 +48,15 @@ P3DSplashWindow(P3DInstance *inst, bool make_visible) : _barcolor_r = 0x6c; _barcolor_g = 0xa5; _barcolor_b = 0xe0; + _bar_bgcolor_r = _bgcolor_r; + _bar_bgcolor_g = _bgcolor_g; + _bar_bgcolor_b = _bgcolor_b; + _bar_border = 1; + _bar_bottom = 24; + _bar_width = 398; + _bar_height = 22; + _bar_width_ratio = 0.6; + _bar_height_ratio = 0.1; _button_width = 0; _button_height = 0; _button_x = 0; @@ -113,7 +122,7 @@ set_image_filename(const string &image_filename, ImagePlacement image_placement) //////////////////////////////////////////////////////////////////// // Function: P3DSplashWindow::set_fgcolor -// Access: Public, Virtual +// Access: Public // Description: Specifies the color that is used to display the text // above the loading bar. // @@ -129,7 +138,7 @@ set_fgcolor(int r, int g, int b) { //////////////////////////////////////////////////////////////////// // Function: P3DSplashWindow::set_bgcolor -// Access: Public, Virtual +// Access: Public // Description: Specifies the solid color that is displayed behind // the splash image, if any, or before the splash image // is loaded. @@ -146,7 +155,7 @@ set_bgcolor(int r, int g, int b) { //////////////////////////////////////////////////////////////////// // Function: P3DSplashWindow::set_barcolor -// Access: Public, Virtual +// Access: Public // Description: Specifies the color that is used to fill the // loading bar. // @@ -160,6 +169,105 @@ set_barcolor(int r, int g, int b) { _barcolor_b = b; } +//////////////////////////////////////////////////////////////////// +// Function: P3DSplashWindow::set_bar_bgcolor +// Access: Public +// Description: Specifies the solid color that is displayed behind +// the loading bar. +// +// This may only be set before wparams is set. +//////////////////////////////////////////////////////////////////// +void P3DSplashWindow:: +set_bar_bgcolor(int r, int g, int b) { + nout << "bar_bgcolor " << r << ", " << g << ", " << b << "\n"; + _bar_bgcolor_r = r; + _bar_bgcolor_g = g; + _bar_bgcolor_b = b; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DSplashWindow::set_bar_border +// Access: Public +// Description: Sets the width in pixels of the border around the +// loading bar, or 0 not to draw a bar at all. +// +// This may only be set before wparams is set. +//////////////////////////////////////////////////////////////////// +void P3DSplashWindow:: +set_bar_border(int border) { + nout << "bar_border " << border << "\n"; + _bar_border = border; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DSplashWindow::set_bar_bottom +// Access: Public +// Description: Sets the amount of background pixels between the +// bottom edge of the window and the bottom edge of +// the loading bar border. +// +// This may only be set before wparams is set. +//////////////////////////////////////////////////////////////////// +void P3DSplashWindow:: +set_bar_bottom(int bottom) { + nout << "bar_bottom " << bottom << "\n"; + _bar_bottom = bottom; +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DSplashWindow::set_bar_width +// Access: Public +// Description: Sets the width of the loading bar. If percent is +// true, it is interpreted as a percentage of the +// window width. If false, it is interpreted as an +// absolute width in pixels. +// +// This may only be set before wparams is set. +//////////////////////////////////////////////////////////////////// +void P3DSplashWindow:: +set_bar_width(int width, bool percent) { + nout << "bar_width " << width; + if (percent) { + nout << '%'; + } + nout << '\n'; + + if (percent) { + _bar_width = -1; + _bar_width_ratio = abs(width) / 100.0; + } else { + _bar_width = abs(width); + _bar_width_ratio = 1.0; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: P3DSplashWindow::set_bar_height +// Access: Public +// Description: Sets the height of the loading bar. If percent is +// true, it is interpreted as a percentage of the +// window height. If false, it is interpreted as an +// absolute height in pixels. +// +// This may only be set before wparams is set. +//////////////////////////////////////////////////////////////////// +void P3DSplashWindow:: +set_bar_height(int height, bool percent) { + nout << "bar_height " << height; + if (percent) { + nout << '%'; + } + nout << '\n'; + + if (percent) { + _bar_height = -1; + _bar_height_ratio = abs(height) / 100.0; + } else { + _bar_height = abs(height); + _bar_height_ratio = 1.0; + } +} + //////////////////////////////////////////////////////////////////// // Function: P3DSplashWindow::set_install_label // Access: Public, Virtual @@ -271,10 +379,21 @@ read_image_data(ImageData &image, string &data, void P3DSplashWindow:: get_bar_placement(int &bar_x, int &bar_y, int &bar_width, int &bar_height) { - bar_width = min((int)(_win_width * 0.6), 400); - bar_height = min((int)(_win_height * 0.1), 24); + + bar_width = (int)(_win_width * _bar_width_ratio); + bar_height = (int)(_win_height * _bar_height_ratio); + + if (_bar_width >= 0) { + bar_width = min(bar_width, _bar_width); + } + if (_bar_height >= 0) { + bar_height = min(bar_height, _bar_height); + } + + // Horizontally center the bar, and set it at a fixed distance + // from the bottom edge of the splash window. bar_x = (_win_width - bar_width) / 2; - bar_y = (_win_height - bar_height * 2); + bar_y = _win_height - _bar_bottom - _bar_border - bar_height; } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dSplashWindow.h b/direct/src/plugin/p3dSplashWindow.h index 33feccead5..edbc02c448 100644 --- a/direct/src/plugin/p3dSplashWindow.h +++ b/direct/src/plugin/p3dSplashWindow.h @@ -54,9 +54,14 @@ public: virtual void set_image_filename(const string &image_filename, ImagePlacement image_placement); - virtual void set_fgcolor(int r, int g, int b); - virtual void set_bgcolor(int r, int g, int b); - virtual void set_barcolor(int r, int g, int b); + void set_fgcolor(int r, int g, int b); + void set_bgcolor(int r, int g, int b); + void set_barcolor(int r, int g, int b); + void set_bar_bgcolor(int r, int g, int b); + void set_bar_border(int border); + void set_bar_bottom(int bottom); + void set_bar_width(int width, bool percent=false); + void set_bar_height(int height, bool percent=false); virtual void set_install_label(const string &install_label); virtual void set_install_progress(double install_progress, bool is_progress_known, size_t received_data); @@ -105,7 +110,15 @@ protected: int _fgcolor_r, _fgcolor_g, _fgcolor_b; int _bgcolor_r, _bgcolor_g, _bgcolor_b; int _barcolor_r, _barcolor_g, _barcolor_b; + int _bar_bgcolor_r, _bar_bgcolor_g, _bar_bgcolor_b; + int _bar_border; +private: + int _bar_bottom; + int _bar_width, _bar_height; + double _bar_width_ratio, _bar_height_ratio; + +protected: // The region of the window for accepting button clicks. int _button_width, _button_height; int _button_x, _button_y; diff --git a/direct/src/plugin/p3dX11SplashWindow.cxx b/direct/src/plugin/p3dX11SplashWindow.cxx index 76c0175a18..6d3d2919a7 100644 --- a/direct/src/plugin/p3dX11SplashWindow.cxx +++ b/direct/src/plugin/p3dX11SplashWindow.cxx @@ -25,6 +25,8 @@ #include #include +static const char *xfont_name = "-*-helvetica-medium-r-normal--12-120-*-*-p-*-iso8859-1"; + //////////////////////////////////////////////////////////////////// // Function: P3DX11SplashWindow::Constructor // Access: Public @@ -47,11 +49,14 @@ P3DX11SplashWindow(P3DInstance *inst, bool make_visible) : _display = None; _window = None; _screen = 0; + _font = NULL; _graphics_context = None; _bar_context = None; + _bar_bg_context = None; _fg_pixel = -1; _bg_pixel = -1; _bar_pixel = -1; + _bar_bg_pixel = -1; _own_display = false; _install_progress = 0.0; _progress_known = true; @@ -609,10 +614,15 @@ subprocess_run() { get_bar_placement(bar_x, bar_y, bar_width, bar_height); if (needs_draw_label) { - int text_width = _install_label.size() * 6; - int text_height = 10; + int direction, ascent, descent; + XCharStruct extents; + XTextExtents(_font, _install_label.c_str(), _install_label.size(), + &direction, &ascent, &descent, &extents); + + int text_width = extents.width; + int text_height = extents.ascent + extents.descent; int text_x = (_win_width - text_width) / 2; - int text_y = bar_y - 4; + int text_y = bar_y - descent - _bar_border - 4; XClearArea(_display, _window, text_x - 2, text_y - text_height - 2, @@ -624,25 +634,44 @@ subprocess_run() { } if (needs_redraw_progress) { - XClearArea(_display, _window, - bar_x, bar_y, bar_width, bar_height, false); - XDrawRectangle(_display, _window, _graphics_context, - bar_x, bar_y, bar_width, bar_height); + // Draw the bar background. + if (_bar_bg_context != None) { + XFillRectangle(_display, _window, _bar_bg_context, + bar_x, bar_y, bar_width, bar_height); + } else { + XClearArea(_display, _window, + bar_x, bar_y, bar_width, bar_height, false); + } + + // Draw the border around the bar. + int border_x = bar_x - 1; + int border_y = bar_y - 1; + int border_width = bar_width + 1; + int border_height = bar_height + 1; + + for (int i = 0; i < _bar_border; ++i) { + XDrawRectangle(_display, _window, _graphics_context, + border_x, border_y, border_width, border_height); + border_x -= 1; + border_y -= 1; + border_width += 2; + border_height += 2; + } needs_update_progress = true; needs_redraw_progress = false; } if (needs_update_progress) { if (_progress_known) { - int progress_width = (int)((bar_width - 2) * _install_progress + 0.5); + int progress_width = (int)((bar_width - 1) * _install_progress + 0.5); XFillRectangle(_display, _window, _bar_context, - bar_x + 1, bar_y + 1, - progress_width + 1, bar_height - 1); + bar_x, bar_y, + progress_width + 1, bar_height); } else { // Progress is unknown. Draw a moving block, not a progress bar // filling up. int block_width = (int)(bar_width * 0.1 + 0.5); - int block_travel = (bar_width - 2) - block_width; + int block_travel = (bar_width - 1) - block_width; int progress = (int)(_received_data * _unknown_progress_rate); progress = progress % (block_travel * 2); if (progress > block_travel) { @@ -650,8 +679,8 @@ subprocess_run() { } XFillRectangle(_display, _window, _bar_context, - bar_x + 1 + progress, bar_y + 1, - block_width + 1, bar_height - 1); + bar_x + progress, bar_y, + block_width + 1, bar_height); } needs_update_progress = false; } @@ -958,10 +987,17 @@ setup_gc() { return; } - XFontStruct* fs = XLoadQueryFont(_display, "6x13"); + _font = XLoadQueryFont(_display, xfont_name); + + if (_font != NULL) { + nout << "Loaded font " << xfont_name << "\n"; + } else { + nout << "Font " << xfont_name << " unavailable.\n"; + _font = XLoadQueryFont(_display, "6x13"); + } XGCValues gcval; - gcval.font = fs->fid; + gcval.font = _font->fid; gcval.function = GXcopy; gcval.plane_mask = AllPlanes; gcval.foreground = BlackPixel(_display, _screen); @@ -991,6 +1027,24 @@ setup_gc() { _bar_context = XCreateGC(_display, _window, GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval); + + // And another for the background color of the bar. + if (_bar_bgcolor_r != _bgcolor_r || _bar_bgcolor_g != _bgcolor_g || + _bar_bgcolor_b != _bgcolor_b) { + XColor bar_bg; + bar_bg.red = _bar_bgcolor_r * 0x101; + bar_bg.green = _bar_bgcolor_g * 0x101; + bar_bg.blue = _bar_bgcolor_b * 0x101; + bar_bg.flags = DoRed | DoGreen | DoBlue; + + if (XAllocColor(_display, colormap, &bar_bg)) { + _bar_bg_pixel = bar_bg.pixel; + gcval.foreground = bar_bg.pixel; + } + + _bar_bg_context = XCreateGC(_display, _window, + GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval); + } } //////////////////////////////////////////////////////////////////// @@ -1016,6 +1070,17 @@ close_window() { XFreeColors(_display, colormap, &_bar_pixel, 1, 0); } + if (_bar_bg_context != None) { + if (_bar_bg_context != _graphics_context) { + XFreeGC(_display, _bar_bg_context); + } + _bar_bg_context = None; + + // Also free the color we allocated. + Colormap colormap = DefaultColormap(_display, _screen); + XFreeColors(_display, colormap, &_bar_bg_pixel, 1, 0); + } + if (_fg_pixel != -1) { Colormap colormap = DefaultColormap(_display, _screen); XFreeColors(_display, colormap, &_fg_pixel, 1, 0); diff --git a/direct/src/plugin/p3dX11SplashWindow.h b/direct/src/plugin/p3dX11SplashWindow.h index b26e4dbc81..2622a31fa3 100644 --- a/direct/src/plugin/p3dX11SplashWindow.h +++ b/direct/src/plugin/p3dX11SplashWindow.h @@ -86,7 +86,7 @@ private: void setup_gc(); void close_window(); - void update_image(X11ImageData &image); + void update_image(X11ImageData &image); void compose_image(); bool scale_image(vector &image0, int &image0_width, int &image0_height, X11ImageData &image); @@ -123,17 +123,20 @@ private: double _install_progress; bool _progress_known; size_t _received_data; - + string _label_text; X11_Display *_display; int _screen; + XFontStruct *_font; GC _graphics_context; GC _bar_context; + GC _bar_bg_context; unsigned long _fg_pixel; unsigned long _bg_pixel; unsigned long _bar_pixel; - + unsigned long _bar_bg_pixel; + X11_Window _window; };