mirror of https://github.com/BOINC/boinc.git
223 lines
5.8 KiB
C
223 lines
5.8 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <setjmp.h>
|
|
#include <unistd.h>
|
|
#include <pthread.h>
|
|
#include "x_opengl.h"
|
|
|
|
#include "app_ipc.h"
|
|
#include "util.h"
|
|
|
|
#include "boinc_gl.h"
|
|
#include "graphics_api.h"
|
|
#include "graphics_impl.h"
|
|
|
|
#define BOINC_WINDOW_CLASS_NAME "BOINC_app"
|
|
|
|
#define TIMER_INTERVAL_MSEC 30
|
|
|
|
static bool visible = true;
|
|
static int current_graphics_mode = MODE_HIDE_GRAPHICS;
|
|
static int acked_graphics_mode;
|
|
static int xpos = 100, ypos = 100;
|
|
static int clicked_button;
|
|
static int win=0;
|
|
static void set_mode(int mode);
|
|
static APP_INIT_DATA aid;
|
|
|
|
// This callback is invoked when a user presses a key.
|
|
//
|
|
void keyboardD(unsigned char key, int x, int y) {
|
|
if (current_graphics_mode == MODE_FULLSCREEN) {
|
|
set_mode(MODE_HIDE_GRAPHICS);
|
|
}
|
|
}
|
|
|
|
void keyboardU(unsigned char key, int x, int y) {
|
|
if (current_graphics_mode == MODE_FULLSCREEN) {
|
|
set_mode(MODE_HIDE_GRAPHICS);
|
|
}
|
|
}
|
|
|
|
void mouse_click(int button, int state, int x, int y){
|
|
clicked_button = button;
|
|
if (current_graphics_mode == MODE_FULLSCREEN) {
|
|
set_mode(MODE_HIDE_GRAPHICS);
|
|
} else {
|
|
if (state) {
|
|
boinc_app_mouse_button(x, y, button, false);
|
|
} else {
|
|
boinc_app_mouse_button(x, y, button, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void mouse_click_move(int x, int y){
|
|
if (current_graphics_mode == MODE_FULLSCREEN){
|
|
set_mode(MODE_HIDE_GRAPHICS);
|
|
} else if (clicked_button == 2){
|
|
boinc_app_mouse_move(x, y, false, false, true);
|
|
} else if (clicked_button == 1){
|
|
boinc_app_mouse_move(x, y, false, true, false);
|
|
} else if (clicked_button == 0){
|
|
boinc_app_mouse_move(x, y, true, false, false);
|
|
} else{
|
|
boinc_app_mouse_move(x, y, false, false, false);
|
|
}
|
|
}
|
|
|
|
static void maybe_render() {
|
|
int width, height;
|
|
if (visible && (current_graphics_mode != MODE_HIDE_GRAPHICS)) {
|
|
width = glutGet(GLUT_WINDOW_WIDTH);
|
|
height = glutGet(GLUT_WINDOW_HEIGHT);
|
|
if (throttled_app_render(width, height, dtime())) {
|
|
glutSwapBuffers();
|
|
}
|
|
}
|
|
}
|
|
|
|
static void close_func() {
|
|
if (bmsp->boinc_is_standalone_hook()) {
|
|
exit(0);
|
|
} else {
|
|
set_mode(MODE_HIDE_GRAPHICS);
|
|
}
|
|
}
|
|
|
|
static void make_new_window(int mode){
|
|
char* args[] = {"foobar", 0};
|
|
int one=1;
|
|
static bool first=true;
|
|
|
|
if (mode == MODE_WINDOW || mode == MODE_FULLSCREEN){
|
|
if (first) {
|
|
glutInit(&one, args);
|
|
first = false;
|
|
}
|
|
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
|
|
glutInitWindowPosition(xpos, ypos);
|
|
glutInitWindowSize(600, 400);
|
|
bmsp->boinc_get_init_data_hook(aid);
|
|
if (!strlen(aid.app_name)) {
|
|
strcpy(aid.app_name, "BOINC Application");
|
|
}
|
|
win = glutCreateWindow(aid.app_name);
|
|
|
|
glutReshapeFunc(app_graphics_resize);
|
|
glutKeyboardFunc(keyboardD);
|
|
glutKeyboardUpFunc(keyboardU);
|
|
glutMouseFunc(mouse_click);
|
|
glutMotionFunc(mouse_click_move);
|
|
glutDisplayFunc(maybe_render);
|
|
|
|
app_graphics_init();
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
if (mode == MODE_FULLSCREEN) {
|
|
glutFullScreen();
|
|
}
|
|
}
|
|
}
|
|
|
|
void KillWindow() {
|
|
if (win) {
|
|
glutDestroyWindow(win);
|
|
win = 0;
|
|
}
|
|
}
|
|
|
|
void set_mode(int mode) {
|
|
if (mode == current_graphics_mode) return;
|
|
KillWindow();
|
|
current_graphics_mode = mode;
|
|
if (mode != MODE_HIDE_GRAPHICS) {
|
|
make_new_window(mode);
|
|
}
|
|
}
|
|
|
|
static void wait_for_initial_message() {
|
|
bmsp->app_client_shm->shm->graphics_reply.send_msg(
|
|
xml_graphics_modes[MODE_HIDE_GRAPHICS]
|
|
);
|
|
acked_graphics_mode = MODE_HIDE_GRAPHICS;
|
|
while (1) {
|
|
if (bmsp->app_client_shm->shm->graphics_request.has_msg()) {
|
|
break;
|
|
}
|
|
sleep(1);
|
|
}
|
|
}
|
|
|
|
static void timer_handler(int) {
|
|
char buf[MSG_CHANNEL_SIZE];
|
|
GRAPHICS_MSG m;
|
|
|
|
int new_mode;
|
|
if (bmsp->app_client_shm) {
|
|
if (bmsp->app_client_shm->shm->graphics_request.get_msg(buf)) {
|
|
bmsp->app_client_shm->decode_graphics_msg(buf, m);
|
|
switch (m.mode) {
|
|
case MODE_REREAD_PREFS:
|
|
//only reread graphics prefs if we have a window open
|
|
//
|
|
switch (current_graphics_mode){
|
|
case MODE_WINDOW:
|
|
case MODE_FULLSCREEN:
|
|
app_graphics_reread_prefs();
|
|
break;
|
|
}
|
|
break;
|
|
case MODE_HIDE_GRAPHICS:
|
|
case MODE_WINDOW:
|
|
case MODE_FULLSCREEN:
|
|
case MODE_BLANKSCREEN:
|
|
set_mode(m.mode);
|
|
break;
|
|
}
|
|
}
|
|
if (acked_graphics_mode != current_graphics_mode) {
|
|
bool sent = bmsp->app_client_shm->shm->graphics_reply.send_msg(
|
|
xml_graphics_modes[current_graphics_mode]
|
|
);
|
|
if (sent) acked_graphics_mode = current_graphics_mode;
|
|
}
|
|
}
|
|
maybe_render();
|
|
glutTimerFunc(TIMER_INTERVAL_MSEC, timer_handler, 0);
|
|
}
|
|
|
|
static jmp_buf jbuf;
|
|
static pthread_t graphics_thread;
|
|
|
|
void restart() {
|
|
if (pthread_equal(pthread_self(), graphics_thread)) {
|
|
atexit(restart);
|
|
longjmp(jbuf, 1);
|
|
}
|
|
}
|
|
|
|
void xwin_graphics_event_loop() {
|
|
graphics_thread = pthread_self();
|
|
if (bmsp->boinc_is_standalone_hook()) {
|
|
set_mode(MODE_WINDOW);
|
|
} else {
|
|
wait_for_initial_message();
|
|
timer_handler(0);
|
|
atexit(restart);
|
|
}
|
|
int retval = setjmp(jbuf);
|
|
if (retval) {
|
|
//fprintf(stderr, "graphics thread restarted\n"); fflush(stderr);
|
|
set_mode(MODE_HIDE_GRAPHICS);
|
|
}
|
|
glutTimerFunc(TIMER_INTERVAL_MSEC, timer_handler, 0);
|
|
glutMainLoop();
|
|
}
|
|
|
|
#ifdef __GNUC__
|
|
static volatile const char __attribute__((unused)) *BOINCrcsid="$Id$";
|
|
#else
|
|
static volatile const char *BOINCrcsid="$Id$";
|
|
#endif
|