- graphics API: redo the code for backwards compatibility with V5 so that

at most one regular and one full-screen graphics window can be open,
    and a "hide" message kills the full-screen window if one exists,
    else a regular window.
    Keep track of the PIDs separately for regular and full-screen.
    Also, don't send a "hide" ack if we don't do graphics.

svn path=/trunk/boinc/; revision=13697
This commit is contained in:
David Anderson 2007-09-28 04:23:34 +00:00
parent e680c9a9a1
commit ab09ba8834
4 changed files with 72 additions and 31 deletions

View File

@ -154,8 +154,7 @@ struct UPLOAD_FILE_STATUS {
static bool have_new_upload_file;
static std::vector<UPLOAD_FILE_STATUS> upload_file_status;
static char graphics_app_path[1024];
static void control_graphics_app(char* path, bool start, bool fullscreen);
void graphics_cleanup();
static int setup_shared_mem() {
if (standalone) {
@ -431,9 +430,8 @@ int boinc_finish(int status) {
// This is called from the worker, timer, and graphics threads.
//
void boinc_exit(int status) {
// kill the (separate) graphics app if running
if (options.backwards_compatible_graphics && graphics_app_path[0]) {
control_graphics_app(graphics_app_path, false, false);
if (options.backwards_compatible_graphics) {
graphics_cleanup();
}
// Unlock the lock file
@ -714,16 +712,15 @@ static void handle_process_control_msg() {
}
}
// helper function for handle_graphics_messages()
//
static void control_graphics_app(char* path, bool start, bool fullscreen) {
static bool running = false;
struct GRAPHICS_APP {
bool fullscreen;
#ifdef _WIN32
static HANDLE pid=0;
HANDLE pid;
#else
static int pid=0;
int pid;
#endif
if (start) {
GRAPHICS_APP(bool f) {fullscreen=f;}
void run(char* path) {
int argc;
char* argv[4];
char abspath[1024];
@ -743,29 +740,34 @@ static void control_graphics_app(char* path, bool start, bool fullscreen) {
}
int retval = run_program(0, abspath, argc, argv, 0, pid);
if (retval) {
running = false;
pid = 0;
} else {
running = true;
}
} else {
if (running) {
kill_program(pid);
running = false;
pid = 0;
}
}
}
bool is_running() {
if (pid && process_exists(pid)) return true;
pid = 0;
return false;
}
void kill() {
if (pid) {
kill_program(pid);
pid = 0;
}
}
};
static GRAPHICS_APP ga_win(false), ga_full(true);
static bool have_graphics_app;
// The following is used by V6 apps so that graphics
// will work with pre-V6 clients.
// If we get a graphics message, run/kill the (separate) graphics app
//
static inline void handle_graphics_messages() {
static char graphics_app_path[1024];
char buf[MSG_CHANNEL_SIZE];
GRAPHICS_MSG m;
static bool first=true;
static bool have_graphics_app;
if (first) {
first = false;
boinc_resolve_filename(
@ -774,13 +776,12 @@ static inline void handle_graphics_messages() {
);
if (!strcmp(graphics_app_path, GRAPHICS_APP_FILENAME)) {
have_graphics_app = false;
graphics_app_path[0] = 0;
} else {
have_graphics_app = true;
app_client_shm->shm->graphics_reply.send_msg(
xml_graphics_modes[MODE_HIDE_GRAPHICS]
);
}
app_client_shm->shm->graphics_reply.send_msg(
xml_graphics_modes[MODE_HIDE_GRAPHICS]
);
}
if (!have_graphics_app) return;
@ -789,18 +790,24 @@ static inline void handle_graphics_messages() {
app_client_shm->decode_graphics_msg(buf, m);
switch (m.mode) {
case MODE_HIDE_GRAPHICS:
control_graphics_app(graphics_app_path, false, false);
if (ga_full.is_running()) {
ga_full.kill();
} else if (ga_win.is_running()) {
ga_win.kill();
}
break;
case MODE_WINDOW:
control_graphics_app(graphics_app_path, true, false);
if (!ga_win.is_running()) ga_win.run(graphics_app_path);
break;
case MODE_FULLSCREEN:
control_graphics_app(graphics_app_path, true, true);
if (!ga_full.is_running()) ga_full.run(graphics_app_path);
break;
case MODE_BLANKSCREEN:
// we can't actually blank the screen; just kill the app
//
control_graphics_app(graphics_app_path, false, false);
if (ga_full.is_running()) {
ga_full.kill();
}
break;
}
app_client_shm->shm->graphics_reply.send_msg(
@ -809,6 +816,12 @@ static inline void handle_graphics_messages() {
}
}
void graphics_cleanup() {
if (!have_graphics_app) return;
if (ga_full.is_running()) ga_full.kill();
if (ga_win.is_running()) ga_win.kill();
}
// once-a-second timer.
// Runs in a separate thread (not the worker thread)
//

View File

@ -8906,3 +8906,15 @@ Charlie 27 Sep 2007
boinc.xcodeproj/
project.pbxproj
David 27 Sept 2007
- graphics API: redo the code for backwards compatibility with V5 so that
at most one regular and one full-screen graphics window can be open,
and a "hide" message kills the full-screen window if one exists,
else a regular window.
Keep track of the PIDs separately for regular and full-screen.
Also, don't send a "hide" ack if we don't do graphics.
api/
boinc_api.C
lib/
util.C,h

View File

@ -398,12 +398,26 @@ int get_exit_status(HANDLE pid_handle) {
}
return (int) status;
}
bool process_exists(HANDLE h) {
unsigned long status=1;
if (GetExitCodeProcess(h, &status)) {
if (status == STILL_ACTIVE) return true;
}
return false;
}
#else
int get_exit_status(int pid) {
int status;
waitpid(pid, &status, 0);
return status;
}
bool process_exists(int pid) {
int p = waitpid(pid, 0, WNOHANG);
if (p == pid) return false; // process has exited
if (p == -1) return false; // PID doesn't exist
return true;
}
#endif
#ifdef _WIN32

View File

@ -89,12 +89,14 @@ extern int run_program(
);
extern void kill_program(HANDLE);
extern int get_exit_status(HANDLE);
extern bool process_exists(HANDLE);
#else
extern int run_program(
const char* path, const char* cdir, int argc, char *const argv[], double, int&
);
extern void kill_program(int);
extern int get_exit_status(int);
extern bool process_exists(int);
#endif
extern int wait_client_mutex(const char* dir, double timeout);