panda3d/direct/src/plugin/p3dX11SplashWindow.cxx

302 lines
9.1 KiB
C++
Executable File

// Filename: p3dX11SplashWindow.cxx
// Created by: pro-rsoft (08Jul09)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "p3dX11SplashWindow.h"
#ifdef HAVE_X11
////////////////////////////////////////////////////////////////////
// Function: P3DX11SplashWindow::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
P3DX11SplashWindow::
P3DX11SplashWindow(P3DInstance *inst) :
P3DSplashWindow(inst)
{
INIT_THREAD(_thread);
_display = None;
_window = None;
_screen = 0;
_graphics_context = None;
_thread_running = false;
_got_install = false;
_image_filename_changed = false;
_image_filename_temp = false;
_install_label_changed = false;
_install_progress = 0.0;
INIT_LOCK(_install_lock);
start_thread();
}
////////////////////////////////////////////////////////////////////
// Function: P3DX11SplashWindow::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
P3DX11SplashWindow::
~P3DX11SplashWindow() {
stop_thread();
DESTROY_LOCK(_install_lock);
}
////////////////////////////////////////////////////////////////////
// Function: P3DX11SplashWindow::set_image_filename
// Access: Public, Virtual
// displayed in the center of the splash window. If
// image_filename_temp is true, the file is immediately
// deleted after it has been read.
////////////////////////////////////////////////////////////////////
void P3DX11SplashWindow::
set_image_filename(const string &image_filename,
bool image_filename_temp) {
ACQUIRE_LOCK(_install_lock);
if (_image_filename != image_filename) {
_image_filename = image_filename;
_image_filename_temp = image_filename_temp;
_image_filename_changed = true;
}
RELEASE_LOCK(_install_lock);
// Post a silly message to spin the message loop.
//PostThreadMessage(_thread_id, WM_USER, 0, 0);
if (!_thread_running && _thread_continue) {
// The user must have closed the window. Let's shut down the
// instance, too.
_inst->request_stop();
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DX11SplashWindow::set_install_label
// Access: Public, Virtual
// Description: Specifies the text that is displayed above the
// install progress bar.
////////////////////////////////////////////////////////////////////
void P3DX11SplashWindow::
set_install_label(const string &install_label) {
ACQUIRE_LOCK(_install_lock);
if (_install_label != install_label) {
_install_label = install_label;
_install_label_changed = true;
}
RELEASE_LOCK(_install_lock);
// Post a silly message to spin the message loop.
//PostThreadMessage(_thread_id, WM_USER, 0, 0);
if (!_thread_running && _thread_continue) {
// The user must have closed the window. Let's shut down the
// instance, too.
_inst->request_stop();
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DX11SplashWindow::set_install_progress
// Access: Public, Virtual
// Description: Moves the install progress bar from 0.0 to 1.0.
////////////////////////////////////////////////////////////////////
void P3DX11SplashWindow::
set_install_progress(double install_progress) {
_got_install = true;
ACQUIRE_LOCK(_install_lock);
_install_progress = install_progress;
RELEASE_LOCK(_install_lock);
// Post a silly message to spin the message loop.
//PostThreadMessage(_thread_id, WM_USER, 0, 0);
if (!_thread_running && _thread_continue) {
// The user must have closed the window. Let's shut down the
// instance, too.
_inst->request_stop();
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DX11SplashWindow::start_thread
// Access: Private
// Description: Spawns the sub-thread.
////////////////////////////////////////////////////////////////////
void P3DX11SplashWindow::
start_thread() {
_thread_continue = true;
INIT_THREAD(_thread);
SPAWN_THREAD(_thread, thread_run, this);
if (_thread != 0) {
_thread_running = true;
}
}
////////////////////////////////////////////////////////////////////
// Function: P3DX11SplashWindow::stop_thread
// Access: Private
// Description: Terminates and joins the sub-thread.
////////////////////////////////////////////////////////////////////
void P3DX11SplashWindow::
stop_thread() {
_thread_continue = false;
// Post a silly message to spin the message loop.
//PostThreadMessage(_thread_id, WM_USER, 0, 0);
JOIN_THREAD(_thread);
}
////////////////////////////////////////////////////////////////////
// Function: P3DX11SplashWindow::thread_run
// Access: Private
// Description: The sub-thread's main run method.
////////////////////////////////////////////////////////////////////
void P3DX11SplashWindow::
thread_run() {
make_window();
setup_gc();
XEvent event;
XSelectInput(_display, _window, ExposureMask);
bool override = true, have_event = false;
string prev_label;
while (_thread_continue) {
have_event = XCheckTypedWindowEvent(_display, _window, Expose, &event);
ACQUIRE_LOCK(_install_lock);
double install_progress = _install_progress;
if (have_event || _install_label != prev_label) {
redraw(_install_label, install_progress);
override = false;
}
prev_label = _install_label;
RELEASE_LOCK(_install_lock);
}
close_window();
_thread_running = false;
}
////////////////////////////////////////////////////////////////////
// Function: P3DX11SplashWindow::redraw
// Access: Private
// Description: Redraws the window.
////////////////////////////////////////////////////////////////////
void P3DX11SplashWindow::
redraw(string label, double progress) {
if (_graphics_context == NULL) return;
XClearWindow(_display, _window);
XDrawString(_display, _window, _graphics_context, 10, 20, label.c_str(), label.size());
}
////////////////////////////////////////////////////////////////////
// Function: P3DX11SplashWindow::make_window
// Access: Private
// Description: Creates the window for displaying progress. Runs
// within the sub-thread.
////////////////////////////////////////////////////////////////////
void P3DX11SplashWindow::
make_window() {
int x = 0;
int y = 0;
if (_wparams.get_win_x() != 0 && _wparams.get_win_y() != 0) {
x = _wparams.get_win_x();
y = _wparams.get_win_y();
}
int width = 320;
int height = 240;
if (_wparams.get_win_width() != 0 && _wparams.get_win_height() != 0) {
width = _wparams.get_win_width();
height = _wparams.get_win_height();
}
Window parent = 0;
_display = (Display*) _wparams.get_parent_window()._xdisplay;
if (_display == 0) {
_display = XOpenDisplay(NULL);
}
_screen = DefaultScreen(_display);
if (_wparams.get_window_type() == P3D_WT_embedded) {
// Create an embedded window.
parent = _wparams.get_parent_window()._xwindow;
} else {
// Create a toplevel window.
parent = XRootWindow(_display, _screen);
}
assert(_display != NULL);
assert(parent != None);
_window = XCreateSimpleWindow(_display, parent, x, y, width, height, 0, 0, -1);
XMapWindow(_display, _window);
}
////////////////////////////////////////////////////////////////////
// Function: P3DX11SplashWindow::setup_gc
// Access: Private
// Description: Sets up the graphics context for drawing the text.
////////////////////////////////////////////////////////////////////
void P3DX11SplashWindow::
setup_gc() {
if (_graphics_context != NULL) {
return;
}
ACQUIRE_LOCK(_install_lock);
string install_label = _install_label;
double install_progress = _install_progress;
_install_label_changed = false;
RELEASE_LOCK(_install_lock);
XFontStruct* fs = XLoadQueryFont(_display, "6x13");
XGCValues gcval;
gcval.font = fs->fid;
gcval.function = GXcopy;
gcval.plane_mask = AllPlanes;
gcval.foreground = BlackPixel(_display, _screen);
gcval.background = WhitePixel(_display, _screen);
_graphics_context = XCreateGC(_display, _window,
GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval);
}
////////////////////////////////////////////////////////////////////
// Function: P3DX11SplashWindow::close_window
// Access: Private
// Description: Closes the window created above.
////////////////////////////////////////////////////////////////////
void P3DX11SplashWindow::
close_window() {
if (_window != None) {
XDestroyWindow(_display, _window);
_window = None;
}
if (_display != None) {
XCloseDisplay(_display);
_display = None;
}
}
#endif // HAVE_X11