void OS_X11::probe_joystick(int p_id) { #ifndef __FreeBSD__ if (p_id == -1) { for (int i=0; i<JOYSTICKS_MAX; i++) { probe_joystick(i); }; return; }; if (joysticks[p_id].fd != -1) close_joystick(p_id); const char *joy_names[] = { "/dev/input/js%d", "/dev/js%d", NULL }; int i=0; while(joy_names[i]) { char fname[64]; sprintf(fname, joy_names[i], p_id); int fd = open(fname, O_RDONLY|O_NONBLOCK); if (fd != -1) { //fcntl( fd, F_SETFL, O_NONBLOCK ); joysticks[p_id] = Joystick(); // this will reset the axis array joysticks[p_id].fd = fd; String name; char namebuf[255] = {0}; if (ioctl(fd, JSIOCGNAME(sizeof(namebuf)), namebuf) >= 0) { name = namebuf; } else { name = "error"; }; input->joy_connection_changed(p_id, true, name); break; // don't try the next name }; ++i; }; #endif };
void OS_X11::probe_joystick(int p_id) { #ifndef __FreeBSD__ if (p_id == -1) { for (int i=0; i<JOYSTICKS_MAX; i++) { probe_joystick(i); }; return; }; close_joystick(p_id); const char *joy_names[] = { "/dev/input/js%d", "/dev/js%d", NULL }; int i=0; while(joy_names[i]) { char fname[64]; sprintf(fname, joy_names[i], p_id); int fd = open(fname, O_RDONLY); if (fd != -1) { fcntl( fd, F_SETFL, O_NONBLOCK ); joysticks[p_id] = Joystick(); // this will reset the axis array joysticks[p_id].fd = fd; break; // don't try the next name }; ++i; }; #endif };
void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) { last_button_state=0; dpad_last[0]=0; dpad_last[1]=0; xmbstring=NULL; event_id=0; x11_window=0; last_click_ms=0; args=OS::get_singleton()->get_cmdline_args(); current_videomode=p_desired; main_loop=NULL; last_timestamp=0; last_mouse_pos_valid=false; last_keyrelease_time=0; if (get_render_thread_mode()==RENDER_SEPARATE_THREAD) { XInitThreads(); } /** XLIB INITIALIZATION **/ x11_display = XOpenDisplay(NULL); char * modifiers = XSetLocaleModifiers ("@im=none"); ERR_FAIL_COND( modifiers == NULL ); xim = XOpenIM (x11_display, NULL, NULL, NULL); if (xim == NULL) { WARN_PRINT("XOpenIM failed"); xim_style=NULL; } else { ::XIMStyles *xim_styles=NULL; xim_style=0; char *imvalret=NULL; imvalret = XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL); if (imvalret != NULL || xim_styles == NULL) { fprintf (stderr, "Input method doesn't support any styles\n"); } if (xim_styles) { xim_style = 0; for (int i=0;i<xim_styles->count_styles;i++) { if (xim_styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) { xim_style = xim_styles->supported_styles[i]; break; } } XFree (xim_styles); } } /* char* windowid = getenv("GODOT_WINDOWID"); if (windowid) { //freopen("/home/punto/stdout", "w", stdout); //reopen("/home/punto/stderr", "w", stderr); x11_window = atol(windowid); XWindowAttributes xwa; XGetWindowAttributes(x11_display,x11_window,&xwa); current_videomode.width = xwa.width; current_videomode.height = xwa.height; }; */ // maybe contextgl wants to be in charge of creating the window //print_line("def videomode "+itos(current_videomode.width)+","+itos(current_videomode.height)); #if defined(OPENGL_ENABLED) || defined(LEGACYGL_ENABLED) context_gl = memnew( ContextGL_X11( x11_display, x11_window,current_videomode, false ) ); context_gl->initialize(); if (true) { rasterizer = memnew( RasterizerGLES2 ); } else { //rasterizer = memnew( RasterizerGLES1 ); }; #endif visual_server = memnew( VisualServerRaster(rasterizer) ); if (get_render_thread_mode()!=RENDER_THREAD_UNSAFE) { visual_server =memnew(VisualServerWrapMT(visual_server,get_render_thread_mode()==RENDER_SEPARATE_THREAD)); } // borderless fullscreen window mode if (current_videomode.fullscreen) { // needed for lxde/openbox, possibly others Hints hints; Atom property; hints.flags = 2; hints.decorations = 0; property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); XMapRaised(x11_display, x11_window); XWindowAttributes xwa; XGetWindowAttributes(x11_display, DefaultRootWindow(x11_display), &xwa); XMoveResizeWindow(x11_display, x11_window, 0, 0, xwa.width, xwa.height); // code for netwm-compliants XEvent xev; Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False); Atom fullscreen = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", False); memset(&xev, 0, sizeof(xev)); xev.type = ClientMessage; xev.xclient.window = x11_window; xev.xclient.message_type = wm_state; xev.xclient.format = 32; xev.xclient.data.l[0] = 1; xev.xclient.data.l[1] = fullscreen; xev.xclient.data.l[2] = 0; XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureNotifyMask, &xev); } // disable resizeable window if (!current_videomode.resizable) { XSizeHints *xsh; xsh = XAllocSizeHints(); xsh->flags = PMinSize | PMaxSize; XWindowAttributes xwa; if (current_videomode.fullscreen) { XGetWindowAttributes(x11_display,DefaultRootWindow(x11_display),&xwa); } else { XGetWindowAttributes(x11_display,x11_window,&xwa); } xsh->min_width = xwa.width; xsh->max_width = xwa.width; xsh->min_height = xwa.height; xsh->max_height = xwa.height; XSetWMNormalHints(x11_display, x11_window, xsh); } AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton(); if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) { ERR_PRINT("Initializing audio failed."); } sample_manager = memnew( SampleManagerMallocSW ); audio_server = memnew( AudioServerSW(sample_manager) ); audio_server->init(); spatial_sound_server = memnew( SpatialSoundServerSW ); spatial_sound_server->init(); spatial_sound_2d_server = memnew( SpatialSound2DServerSW ); spatial_sound_2d_server->init(); ERR_FAIL_COND(!visual_server); ERR_FAIL_COND(x11_window==0); XSetWindowAttributes new_attr; new_attr.event_mask=KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask | ButtonMotionMask | KeymapStateMask | ExposureMask | VisibilityChangeMask | StructureNotifyMask | SubstructureNotifyMask | SubstructureRedirectMask | FocusChangeMask | PropertyChangeMask | ColormapChangeMask | OwnerGrabButtonMask; XChangeWindowAttributes(x11_display, x11_window,CWEventMask,&new_attr); XClassHint* classHint; /* set the titlebar name */ XStoreName(x11_display, x11_window, "Godot"); /* set the name and class hints for the window manager to use */ classHint = XAllocClassHint(); if (classHint) { classHint->res_name = "Godot"; classHint->res_class = "Godot"; } XSetClassHint(x11_display, x11_window, classHint); XFree(classHint); wm_delete = XInternAtom(x11_display, "WM_DELETE_WINDOW", true); XSetWMProtocols(x11_display, x11_window, &wm_delete, 1); if (xim && xim_style) { xic = XCreateIC (xim,XNInputStyle, xim_style,XNClientWindow,x11_window,XNFocusWindow, x11_window, (char*)NULL); } else { xic=NULL; WARN_PRINT("XCreateIC couldn't create xic"); } XcursorSetTheme(x11_display,"default"); cursor_size = XcursorGetDefaultSize(x11_display); cursor_theme = XcursorGetTheme(x11_display); if (!cursor_theme) { print_line("not found theme"); cursor_theme="default"; } for(int i=0;i<CURSOR_MAX;i++) { cursors[i]=None; } current_cursor=CURSOR_ARROW; if (cursor_theme) { //print_line("cursor theme: "+String(cursor_theme)); for(int i=0;i<CURSOR_MAX;i++) { static const char *cursor_file[]={ "left_ptr", "xterm", "hand2", "cross", "watch", "left_ptr_watch", "fleur", "hand1", "X_cursor", "sb_v_double_arrow", "sb_h_double_arrow", "size_bdiag", "size_fdiag", "hand1", "sb_v_double_arrow", "sb_h_double_arrow", "question_arrow" }; XcursorImage *img = XcursorLibraryLoadImage(cursor_file[i],cursor_theme,cursor_size); if (img) { cursors[i]=XcursorImageLoadCursor(x11_display,img); //print_line("found cursor: "+String(cursor_file[i])+" id "+itos(cursors[i])); } else { if (OS::is_stdout_verbose()) print_line("failed cursor: "+String(cursor_file[i])); } } } { Pixmap cursormask; XGCValues xgc; GC gc; XColor col; Cursor cursor; cursormask = XCreatePixmap(x11_display, RootWindow(x11_display,DefaultScreen(x11_display)), 1, 1, 1); xgc.function = GXclear; gc = XCreateGC(x11_display, cursormask, GCFunction, &xgc); XFillRectangle(x11_display, cursormask, gc, 0, 0, 1, 1); col.pixel = 0; col.red = 0; col.flags = 4; cursor = XCreatePixmapCursor(x11_display, cursormask, cursormask, &col, &col, 0, 0); XFreePixmap(x11_display, cursormask); XFreeGC(x11_display, gc); if (cursor == None) { ERR_PRINT("FAILED CREATING CURSOR"); } null_cursor=cursor; } set_cursor_shape(CURSOR_BUSY); visual_server->init(); // physics_server = memnew( PhysicsServerSW ); physics_server->init(); physics_2d_server = memnew( Physics2DServerSW ); physics_2d_server->init(); input = memnew( InputDefault ); probe_joystick(); _ensure_data_dir(); net_wm_icon = XInternAtom(x11_display, "_NET_WM_ICON", False); //printf("got map notify\n"); }
void OS_X11::process_joysticks() { #ifndef __FreeBSD__ int bytes; js_event events[32]; InputEvent ievent; for (int i=0; i<JOYSTICKS_MAX; i++) { if (joysticks[i].fd == -1) { probe_joystick(i); if (joysticks[i].fd == -1) continue; }; ievent.device = i; while ( (bytes = read(joysticks[i].fd, &events, sizeof(events))) > 0) { int ev_count = bytes / sizeof(js_event); for (int j=0; j<ev_count; j++) { js_event& event = events[j]; //printf("got event on joystick %i, %i, %i, %i, %i\n", i, joysticks[i].fd, event.type, event.number, event.value); if (event.type & JS_EVENT_INIT) continue; switch (event.type & ~JS_EVENT_INIT) { case JS_EVENT_AXIS: //if (joysticks[i].last_axis[event.number] != event.value) { /* if (event.number==5 || event.number==6) { int axis=event.number-5; int val = event.value; if (val<0) val=-1; if (val>0) val=+1; InputEvent ev; ev.type = InputEvent::JOYSTICK_BUTTON; ev.ID = ++event_id; if (val!=dpad_last[axis]) { int prev_val = dpad_last[axis]; if (prev_val!=0) { ev.joy_button.pressed=false; ev.joy_button.pressure=0.0; if (event.number==5) ev.joy_button.button_index=JOY_DPAD_LEFT+(prev_val+1)/2; if (event.number==6) ev.joy_button.button_index=JOY_DPAD_UP+(prev_val+1)/2; input->parse_input_event( ev ); } } if (val!=0) { ev.joy_button.pressed=true; ev.joy_button.pressure=1.0; if (event.number==5) ev.joy_button.button_index=JOY_DPAD_LEFT+(val+1)/2; if (event.number==6) ev.joy_button.button_index=JOY_DPAD_UP+(val+1)/2; input->parse_input_event( ev ); } dpad_last[axis]=val; } */ //print_line("ev: "+itos(event.number)+" val: "+ rtos((float)event.value / (float)MAX_JOY_AXIS)); //if (event.number >= JOY_AXIS_MAX) // break; //ERR_FAIL_COND(event.number >= JOY_AXIS_MAX); ievent.type = InputEvent::JOYSTICK_MOTION; ievent.ID = ++event_id; ievent.joy_motion.axis = event.number; //_pc_joystick_get_native_axis(event.number); ievent.joy_motion.axis_value = (float)event.value / (float)MAX_JOY_AXIS; if (event.number < JOY_AXIS_MAX) joysticks[i].last_axis[event.number] = event.value; input->parse_input_event( ievent ); //}; break; case JS_EVENT_BUTTON: ievent.type = InputEvent::JOYSTICK_BUTTON; ievent.ID = ++event_id; ievent.joy_button.button_index = event.number; // _pc_joystick_get_native_button(event.number); ievent.joy_button.pressed = event.value; input->parse_input_event( ievent ); break; }; }; }; if (bytes == 0 || (bytes < 0 && errno != EAGAIN)) { close_joystick(i); }; }; #endif };