static void FocusAllMice(_THIS, SDL_Window *window) { #if USE_MULTI_API SDL_DFB_DEVICEDATA(_this); int index; for (index = 0; index < devdata->num_mice; index++) SDL_SetMouseFocus(devdata->mouse_id[index], id); #else SDL_SetMouseFocus(window); #endif }
static void pointer_handle_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t sx_w, wl_fixed_t sy_w) { struct SDL_WaylandInput *input = data; SDL_WindowData *window; if (!surface) { /* enter event for a window we've just destroyed */ return; } /* This handler will be called twice in Wayland 1.4 * Once for the window surface which has valid user data * and again for the mouse cursor surface which does not have valid user data * We ignore the later */ window = (SDL_WindowData *)wl_surface_get_user_data(surface); if (window) { input->pointer_focus = window; SDL_SetMouseFocus(window->sdlwindow); } }
int SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(); int posted; if (window) { SDL_SetMouseFocus(window); } if (!x && !y) { return 0; } /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(SDL_MOUSEWHEEL) == SDL_ENABLE) { SDL_Event event; event.type = SDL_MOUSEWHEEL; event.wheel.windowID = mouse->focus ? mouse->focus->id : 0; event.wheel.which = mouseID; event.wheel.x = x; event.wheel.y = y; posted = (SDL_PushEvent(&event) > 0); } return posted; }
int Android_CreateWindow(_THIS, SDL_Window * window) { SDL_WindowData *data; if (Android_Window) { return SDL_SetError("Android only supports one window"); } Android_PauseSem = SDL_CreateSemaphore(0); Android_ResumeSem = SDL_CreateSemaphore(0); /* Adjust the window data to match the screen */ window->x = 0; window->y = 0; window->w = Android_ScreenWidth; window->h = Android_ScreenHeight; window->flags &= ~SDL_WINDOW_RESIZABLE; /* window is NEVER resizeable */ window->flags |= SDL_WINDOW_FULLSCREEN; /* window is always fullscreen */ window->flags &= ~SDL_WINDOW_HIDDEN; window->flags |= SDL_WINDOW_SHOWN; /* only one window on Android */ window->flags |= SDL_WINDOW_INPUT_FOCUS; /* always has input focus */ /* One window, it always has focus */ SDL_SetMouseFocus(window); SDL_SetKeyboardFocus(window); data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data)); if (!data) { return SDL_OutOfMemory(); } data->native_window = Android_JNI_GetNativeWindow(); if (!data->native_window) { SDL_free(data); return SDL_SetError("Could not fetch native window"); } /* Do not create EGLSurface for Vulkan window since it will then make the window incompatible with vkCreateAndroidSurfaceKHR */ if ((window->flags & SDL_WINDOW_VULKAN) == 0) { data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window); if (data->egl_surface == EGL_NO_SURFACE) { ANativeWindow_release(data->native_window); SDL_free(data); return SDL_SetError("Could not create GLES window surface"); } } window->driverdata = data; Android_Window = window; return 0; }
static void HandleMouseEvent(MirPointerEvent const* pointer, SDL_Window* sdl_window) { SDL_SetMouseFocus(sdl_window); switch (MIR_mir_pointer_event_action(pointer)) { case mir_pointer_action_button_down: HandleMouseButton(sdl_window, SDL_PRESSED, pointer); break; case mir_pointer_action_button_up: HandleMouseButton(sdl_window, SDL_RELEASED, pointer); break; case mir_pointer_action_motion: { int x, y; int hscroll, vscroll; SDL_Mouse* mouse = SDL_GetMouse(); x = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_x); y = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_y); if (mouse) { if (mouse->relative_mode) { int relative_x = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_relative_x); int relative_y = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_relative_y); HandleMouseMotion(sdl_window, relative_x, relative_y); } else if (mouse->x != x || mouse->y != y) { HandleMouseMotion(sdl_window, x, y); } } hscroll = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_hscroll); vscroll = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_vscroll); if (vscroll != 0 || hscroll != 0) HandleMouseScroll(sdl_window, hscroll, vscroll); } break; case mir_pointer_action_leave: SDL_SetMouseFocus(NULL); break; case mir_pointer_action_enter: default: break; } }
void VIVANTE_ShowWindow(_THIS, SDL_Window * window) { #if SDL_VIDEO_DRIVER_VIVANTE_VDK SDL_WindowData *data = window->driverdata; vdkShowWindow(data->native_window); #endif SDL_SetMouseFocus(window); SDL_SetKeyboardFocus(window); }
static void pointer_handle_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface) { struct SDL_WaylandInput *input = data; if (input->pointer_focus) { SDL_SetMouseFocus(NULL); input->pointer_focus = NULL; } }
void Android_OnTouch(int action, float x, float y, float p, int pc) { if (!Android_Window) { return; } if ((action != ACTION_CANCEL) && (action != ACTION_OUTSIDE)) { SDL_SetMouseFocus(Android_Window); SDL_SendMouseMotion(Android_Window, 0, (int) x, (int) y); switch (action) { case ACTION_DOWN: if (pc == 1) { SDL_SendMouseButton(Android_Window, SDL_PRESSED, SDL_BUTTON_LEFT); } break; case ACTION_UP: if (pc == 1) { SDL_SendMouseButton(Android_Window, SDL_RELEASED, SDL_BUTTON_LEFT); } break; case ACTION_POINTER_2_DOWN: case ACTION_POINTER_DOWN: SDL_SetMouseFocus(NULL); SDL_SetMouseFocus(Android_Window); SDL_SendMouseMotion(Android_Window, 0, (int) x, (int) y); SDL_SendMouseButton(Android_Window, SDL_PRESSED, SDL_BUTTON_MIDDLE); break; case ACTION_POINTER_2_UP: case ACTION_POINTER_UP: SDL_SendMouseButton(Android_Window, SDL_RELEASED, SDL_BUTTON_MIDDLE); SDL_SetMouseFocus(NULL); break; } } else { SDL_SetMouseFocus(NULL); } }
int SDL_SetRelativeMouseMode(SDL_bool enabled) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_Window *focusWindow = SDL_GetKeyboardFocus(); if (enabled == mouse->relative_mode) { return 0; } if (enabled && focusWindow) { /* Center it in the focused window to prevent clicks from going through * to background windows. */ SDL_SetMouseFocus(focusWindow); SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2); } /* Set the relative mode */ if (!enabled && mouse->relative_mode_warp) { mouse->relative_mode_warp = SDL_FALSE; } else if (enabled && ShouldUseRelativeModeWarp(mouse)) { mouse->relative_mode_warp = SDL_TRUE; } else if (mouse->SetRelativeMouseMode(enabled) < 0) { if (enabled) { /* Fall back to warp mode if native relative mode failed */ if (!mouse->WarpMouse) { return SDL_SetError("No relative mode implementation available"); } mouse->relative_mode_warp = SDL_TRUE; } } mouse->relative_mode = enabled; mouse->scale_accum_x = 0.0f; mouse->scale_accum_y = 0.0f; if (mouse->focus) { SDL_UpdateWindowGrab(mouse->focus); /* Put the cursor back to where the application expects it */ if (!enabled) { SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y); } } /* Flush pending mouse motion - ideally we would pump events, but that's not always safe */ SDL_FlushEvent(SDL_MOUSEMOTION); /* Update cursor visibility */ SDL_SetCursor(NULL); return 0; }
int SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction) { SDL_Mouse *mouse = SDL_GetMouse(); int posted; int integral_x, integral_y; if (window) { SDL_SetMouseFocus(window); } if (x == 0.0f && y == 0.0f) { return 0; } mouse->accumulated_wheel_x += x; if (mouse->accumulated_wheel_x > 0) { integral_x = (int)SDL_floor(mouse->accumulated_wheel_x); } else if (mouse->accumulated_wheel_x < 0) { integral_x = (int)SDL_ceil(mouse->accumulated_wheel_x); } else { integral_x = 0; } mouse->accumulated_wheel_x -= integral_x; mouse->accumulated_wheel_y += y; if (mouse->accumulated_wheel_y > 0) { integral_y = (int)SDL_floor(mouse->accumulated_wheel_y); } else if (mouse->accumulated_wheel_y < 0) { integral_y = (int)SDL_ceil(mouse->accumulated_wheel_y); } else { integral_y = 0; } mouse->accumulated_wheel_y -= integral_y; /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(SDL_MOUSEWHEEL) == SDL_ENABLE) { SDL_Event event; event.type = SDL_MOUSEWHEEL; event.wheel.windowID = mouse->focus ? mouse->focus->id : 0; event.wheel.which = mouseID; #if 0 /* Uncomment this when it goes in for SDL 2.1 */ event.wheel.preciseX = x; event.wheel.preciseY = y; #endif event.wheel.x = integral_x; event.wheel.y = integral_y; event.wheel.direction = (Uint32)direction; posted = (SDL_PushEvent(&event) > 0); } return posted; }
static void HandleMouseEvent(MirMotionEvent const motion, int cord_index, SDL_Window* sdl_window) { SDL_SetMouseFocus(sdl_window); switch (motion.action) { case mir_motion_action_down: case mir_motion_action_pointer_down: HandleMouseButton(sdl_window, SDL_PRESSED, motion.button_state); break; case mir_motion_action_up: case mir_motion_action_pointer_up: HandleMouseButton(sdl_window, SDL_RELEASED, motion.button_state); break; case mir_motion_action_hover_move: case mir_motion_action_move: HandleMouseMotion(sdl_window, motion.pointer_coordinates[cord_index].x, motion.pointer_coordinates[cord_index].y); break; case mir_motion_action_outside: SDL_SetMouseFocus(NULL); break; case mir_motion_action_scroll: HandleMouseScroll(sdl_window, motion.pointer_coordinates[cord_index].hscroll, motion.pointer_coordinates[cord_index].vscroll); break; case mir_motion_action_cancel: case mir_motion_action_hover_enter: case mir_motion_action_hover_exit: break; default: break; } }
int SDL_SendMouseButton(SDL_Window * window, Uint8 state, Uint8 button) { SDL_Mouse *mouse = SDL_GetMouse(); int posted; Uint32 type; if (window) { SDL_SetMouseFocus(window); } /* Figure out which event to perform */ switch (state) { case SDL_PRESSED: if (mouse->buttonstate & SDL_BUTTON(button)) { /* Ignore this event, no state change */ return 0; } type = SDL_MOUSEBUTTONDOWN; mouse->buttonstate |= SDL_BUTTON(button); break; case SDL_RELEASED: if (!(mouse->buttonstate & SDL_BUTTON(button))) { /* Ignore this event, no state change */ return 0; } type = SDL_MOUSEBUTTONUP; mouse->buttonstate &= ~SDL_BUTTON(button); break; default: /* Invalid state -- bail */ return 0; } /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(type) == SDL_ENABLE) { SDL_Event event; event.type = type; event.button.state = state; event.button.button = button; event.button.x = mouse->x; event.button.y = mouse->y; event.button.windowID = mouse->focus ? mouse->focus->id : 0; posted = (SDL_PushEvent(&event) > 0); } return posted; }
void SDL_WarpMouseInWindow(SDL_Window * window, int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(SDL_current_mouse); if (!mouse) { return; } if (mouse->WarpMouse) { mouse->WarpMouse(mouse, window, x, y); } else { SDL_SetMouseFocus(SDL_current_mouse, window); SDL_SendMouseMotion(SDL_current_mouse, 0, x, y, 0); } }
int SDL_SetRelativeMouseMode(SDL_bool enabled) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_Window *focusWindow = SDL_GetKeyboardFocus(); int original_x = mouse->x, original_y = mouse->y; if (enabled == mouse->relative_mode) { return 0; } if (!mouse->SetRelativeMouseMode) { return SDL_Unsupported(); } if (enabled && focusWindow) { /* Center it in the focused window to prevent clicks from going through * to background windows. */ SDL_SetMouseFocus(focusWindow); SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2); } if (mouse->SetRelativeMouseMode(enabled) < 0) { return -1; } /* Set the relative mode */ mouse->relative_mode = enabled; if (enabled) { /* Save the expected mouse position */ mouse->original_x = original_x; mouse->original_y = original_y; } else if (mouse->focus) { /* Restore the expected mouse position */ SDL_WarpMouseInWindow(mouse->focus, mouse->original_x, mouse->original_y); } /* Flush pending mouse motion */ SDL_FlushEvent(SDL_MOUSEMOTION); /* Update cursor visibility */ SDL_SetCursor(NULL); return 0; }
int FB_CreateWindow(_THIS, SDL_Window * window) { SDL_WindowData *wdata; SDL_VideoDisplay *display; /* Allocate window internal data */ wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData)); if (wdata == NULL) { return SDL_OutOfMemory(); } display = SDL_GetDisplayForWindow(window); /* Windows have one size for now */ window->w = display->desktop_mode.w; window->h = display->desktop_mode.h; /* OpenGL ES is the law here, buddy */ window->flags |= SDL_WINDOW_OPENGL; if (!_this->egl_data) { if (SDL_GL_LoadLibrary(NULL) < 0) { return -1; } } wdata->egl_surface = SDL_EGL_CreateSurface(_this, 0); if (wdata->egl_surface == EGL_NO_SURFACE) { return SDL_SetError("Could not create GLES window surface"); } /* Setup driver data for this window */ window->driverdata = wdata; /* One window, it always has focus */ SDL_SetMouseFocus(window); SDL_SetKeyboardFocus(window); /* Window has been successfully created */ return 0; }
void Android_OnTouch(int action, float x, float y, float p, int pc, int gestureTriggered) { if (!Android_Window) { return; } if (gestureTriggered == GESTURE_LONGPRESS) { LOGI("Mouse Gesture - LongPress"); SDL_SetMouseFocus(NULL); SDL_SetMouseFocus(Android_Window); SDL_SendMouseMotion(Android_Window, 0, (int) x, (int) y); SDL_SendMouseButton(Android_Window, SDL_PRESSED, SDL_BUTTON_RIGHT); SDL_SendMouseButton(Android_Window, SDL_RELEASED, SDL_BUTTON_RIGHT); ignoreNextUp = 1; doubleClick = 0; ignoreNextDown = 1; return; } if (gestureTriggered == GESTURE_MOVE) { switch (action) { case ACTION_DOWN: LOGI("Mouse down - middle"); SDL_SetMouseFocus(NULL); SDL_SetMouseFocus(Android_Window); SDL_SendMouseMotion(Android_Window, 0, (int) x, (int) y); SDL_SendMouseButton(Android_Window, SDL_PRESSED, SDL_BUTTON_MIDDLE); break; case ACTION_UP: LOGI("Mouse up - middle"); SDL_SendMouseButton(Android_Window, SDL_RELEASED, SDL_BUTTON_MIDDLE); SDL_SetMouseFocus(NULL); break; } return; } if ((action != ACTION_CANCEL) && (action != ACTION_OUTSIDE)) { SDL_SetMouseFocus(Android_Window); SDL_SendMouseMotion(Android_Window, 0, (int) x, (int) y); switch (action) { case ACTION_DOWN: LOGI("Mouse Down - left"); if (pc == 1 && ignoreNextDown == 0) { LOGI("Mouse Down - left SENT"); SDL_SendMouseButton(Android_Window, SDL_PRESSED, SDL_BUTTON_LEFT); } ignoreNextDown = 0; break; case ACTION_UP: LOGI("Mouse Up - left"); if (pc == 1 && ignoreNextUp == 0) { LOGI("Mouse Up - left SENT"); SDL_SendMouseButton(Android_Window, SDL_RELEASED, SDL_BUTTON_LEFT); if (doubleClick == 1) { LOGI("Mouse Up - left SENT"); SDL_SendMouseButton(Android_Window, SDL_RELEASED, SDL_BUTTON_LEFT); doubleClick = 0; } } ignoreNextUp = 0; break; } } else { SDL_SetMouseFocus(NULL); } }
int RPI_CreateWindow(_THIS, SDL_Window * window) { SDL_WindowData *wdata; SDL_VideoDisplay *display; SDL_DisplayData *displaydata; VC_RECT_T dst_rect; VC_RECT_T src_rect; VC_DISPMANX_ALPHA_T dispman_alpha; DISPMANX_UPDATE_HANDLE_T dispman_update; /* Disable alpha, otherwise the app looks composed with whatever dispman is showing (X11, console,etc) */ dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; dispman_alpha.opacity = 0xFF; dispman_alpha.mask = 0; /* Allocate window internal data */ wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData)); if (wdata == NULL) { return SDL_OutOfMemory(); } display = SDL_GetDisplayForWindow(window); displaydata = (SDL_DisplayData *) display->driverdata; /* Windows have one size for now */ window->w = display->desktop_mode.w; window->h = display->desktop_mode.h; /* OpenGL ES is the law here, buddy */ window->flags |= SDL_WINDOW_OPENGL; /* Create a dispman element and associate a window to it */ dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = window->w; dst_rect.height = window->h; src_rect.x = 0; src_rect.y = 0; src_rect.width = window->w << 16; src_rect.height = window->h << 16; dispman_update = vc_dispmanx_update_start( 0 ); wdata->dispman_window.element = vc_dispmanx_element_add ( dispman_update, displaydata->dispman_display, SDL_RPI_VIDEOLAYER /* layer */, &dst_rect, 0/*src*/, &src_rect, DISPMANX_PROTECTION_NONE, &dispman_alpha /*alpha*/, 0/*clamp*/, 0/*transform*/); wdata->dispman_window.width = window->w; wdata->dispman_window.height = window->h; vc_dispmanx_update_submit_sync( dispman_update ); if (!_this->egl_data) { if (SDL_GL_LoadLibrary(NULL) < 0) { return -1; } } wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) &wdata->dispman_window); if (wdata->egl_surface == EGL_NO_SURFACE) { return SDL_SetError("Could not create GLES window surface"); } /* Setup driver data for this window */ window->driverdata = wdata; /* One window, it always has focus */ SDL_SetMouseFocus(window); SDL_SetKeyboardFocus(window); /* Window has been successfully created */ return 0; }
/* Check to see if we need to synthesize focus events */ static SDL_bool SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate) { SDL_Mouse *mouse = SDL_GetMouse(); int w, h; SDL_bool inWindow; SDL_GetWindowSize(window, &w, &h); if (x < 0 || y < 0 || x >= w || y >= h) { inWindow = SDL_FALSE; } else { inWindow = SDL_TRUE; } /* Linux doesn't give you mouse events outside your window unless you grab the pointer. Windows doesn't give you mouse events outside your window unless you call SetCapture(). Both of these are slightly scary changes, so for now we'll punt and if the mouse leaves the window you'll lose mouse focus and reset button state. */ #ifdef SUPPORT_DRAG_OUTSIDE_WINDOW if (!inWindow && !buttonstate) { #else if (!inWindow) { #endif if (window == mouse->focus) { #ifdef DEBUG_MOUSE printf("Mouse left window, synthesizing move & focus lost event\n"); #endif SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y); SDL_SetMouseFocus(NULL); } return SDL_FALSE; } if (window != mouse->focus) { #ifdef DEBUG_MOUSE printf("Mouse entered window, synthesizing focus gain & move event\n"); #endif SDL_SetMouseFocus(window); SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y); } return SDL_TRUE; } int SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) { if (window && !relative) { SDL_Mouse *mouse = SDL_GetMouse(); if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) { return 0; } } return SDL_PrivateSendMouseMotion(window, mouseID, relative, x, y); } static int SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(); int posted; int xrel; int yrel; int x_max = 0, y_max = 0; /* relative motion is calculated regarding the system cursor last position */ if (relative) { xrel = x; yrel = y; x = (mouse->last_x + x); y = (mouse->last_y + y); } else { xrel = x - mouse->last_x; yrel = y - mouse->last_y; } /* Drop events that don't change state */ if (!xrel && !yrel) { #ifdef DEBUG_MOUSE printf("Mouse event didn't change state - dropped!\n"); #endif return 0; } /* Update internal mouse coordinates */ if (mouse->relative_mode == SDL_FALSE) { mouse->x = x; mouse->y = y; } else { mouse->x += xrel; mouse->y += yrel; } SDL_GetWindowSize(mouse->focus, &x_max, &y_max); --x_max; --y_max; /* make sure that the pointers find themselves inside the windows */ if (mouse->x > x_max) { mouse->x = x_max; } if (mouse->x < 0) { mouse->x = 0; } if (mouse->y > y_max) { mouse->y = y_max; } if (mouse->y < 0) { mouse->y = 0; } mouse->xdelta += xrel; mouse->ydelta += yrel; #if 0 /* FIXME */ /* Move the mouse cursor, if needed */ if (mouse->cursor_shown && !mouse->relative_mode && mouse->MoveCursor && mouse->cur_cursor) { mouse->MoveCursor(mouse->cur_cursor); } #endif /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE) { SDL_Event event; event.motion.type = SDL_MOUSEMOTION; event.motion.windowID = mouse->focus ? mouse->focus->id : 0; event.motion.which = mouseID; event.motion.state = mouse->buttonstate; event.motion.x = mouse->x; event.motion.y = mouse->y; event.motion.xrel = xrel; event.motion.yrel = yrel; posted = (SDL_PushEvent(&event) > 0); } /* Use unclamped values if we're getting events outside the window */ mouse->last_x = x; mouse->last_y = y; return posted; }
/* Check to see if we need to synthesize focus events */ static SDL_bool SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_bool inWindow = SDL_TRUE; if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) { int w, h; SDL_GetWindowSize(window, &w, &h); if (x < 0 || y < 0 || x >= w || y >= h) { inWindow = SDL_FALSE; } } /* Linux doesn't give you mouse events outside your window unless you grab the pointer. Windows doesn't give you mouse events outside your window unless you call SetCapture(). Both of these are slightly scary changes, so for now we'll punt and if the mouse leaves the window you'll lose mouse focus and reset button state. */ #ifdef SUPPORT_DRAG_OUTSIDE_WINDOW if (!inWindow && !buttonstate) { #else if (!inWindow) { #endif if (window == mouse->focus) { #ifdef DEBUG_MOUSE printf("Mouse left window, synthesizing move & focus lost event\n"); #endif SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y); SDL_SetMouseFocus(NULL); } return SDL_FALSE; } if (window != mouse->focus) { #ifdef DEBUG_MOUSE printf("Mouse entered window, synthesizing focus gain & move event\n"); #endif SDL_SetMouseFocus(window); SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y); } return SDL_TRUE; } int SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) { if (window && !relative) { SDL_Mouse *mouse = SDL_GetMouse(); if (!SDL_UpdateMouseFocus(window, x, y, mouse->buttonstate)) { return 0; } } return SDL_PrivateSendMouseMotion(window, mouseID, relative, x, y); } static int GetScaledMouseDelta(float scale, int value, float *accum) { if (scale != 1.0f) { *accum += scale * value; if (*accum >= 0.0f) { value = (int)SDL_floor(*accum); } else { value = (int)SDL_ceil(*accum); } *accum -= value; } return value; } static int SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(); int posted; int xrel; int yrel; /* SDL_HINT_MOUSE_TOUCH_EVENTS: controlling whether mouse events should generate synthetic touch events */ if (mouse->mouse_touch_events) { if (mouseID != SDL_TOUCH_MOUSEID && !relative && track_mouse_down) { if (window) { float fx = (float)x / (float)window->w; float fy = (float)y / (float)window->h; SDL_SendTouchMotion(SDL_MOUSE_TOUCHID, 0, fx, fy, 1.0f); } } } if (mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp) { int center_x = 0, center_y = 0; SDL_GetWindowSize(window, ¢er_x, ¢er_y); center_x /= 2; center_y /= 2; if (x == center_x && y == center_y) { mouse->last_x = center_x; mouse->last_y = center_y; return 0; } SDL_WarpMouseInWindow(window, center_x, center_y); } if (relative) { if (mouse->relative_mode) { x = GetScaledMouseDelta(mouse->relative_speed_scale, x, &mouse->scale_accum_x); y = GetScaledMouseDelta(mouse->relative_speed_scale, y, &mouse->scale_accum_y); } else { x = GetScaledMouseDelta(mouse->normal_speed_scale, x, &mouse->scale_accum_x); y = GetScaledMouseDelta(mouse->normal_speed_scale, y, &mouse->scale_accum_y); } xrel = x; yrel = y; x = (mouse->last_x + xrel); y = (mouse->last_y + yrel); } else { xrel = x - mouse->last_x; yrel = y - mouse->last_y; } /* Drop events that don't change state */ if (!xrel && !yrel) { #ifdef DEBUG_MOUSE printf("Mouse event didn't change state - dropped!\n"); #endif return 0; } /* Ignore relative motion when first positioning the mouse */ if (!mouse->has_position) { xrel = 0; yrel = 0; mouse->has_position = SDL_TRUE; } /* Ignore relative motion positioning the first touch */ if (mouseID == SDL_TOUCH_MOUSEID && !mouse->buttonstate) { xrel = 0; yrel = 0; } /* Update internal mouse coordinates */ if (!mouse->relative_mode) { mouse->x = x; mouse->y = y; } else { mouse->x += xrel; mouse->y += yrel; } /* make sure that the pointers find themselves inside the windows, unless we have the mouse captured. */ if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) { int x_max = 0, y_max = 0; /* !!! FIXME: shouldn't this be (window) instead of (mouse->focus)? */ SDL_GetWindowSize(mouse->focus, &x_max, &y_max); --x_max; --y_max; if (mouse->x > x_max) { mouse->x = x_max; } if (mouse->x < 0) { mouse->x = 0; } if (mouse->y > y_max) { mouse->y = y_max; } if (mouse->y < 0) { mouse->y = 0; } } mouse->xdelta += xrel; mouse->ydelta += yrel; /* Move the mouse cursor, if needed */ if (mouse->cursor_shown && !mouse->relative_mode && mouse->MoveCursor && mouse->cur_cursor) { mouse->MoveCursor(mouse->cur_cursor); } /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE) { SDL_Event event; event.motion.type = SDL_MOUSEMOTION; event.motion.windowID = mouse->focus ? mouse->focus->id : 0; event.motion.which = mouseID; event.motion.state = mouse->buttonstate; event.motion.x = mouse->x; event.motion.y = mouse->y; event.motion.xrel = xrel; event.motion.yrel = yrel; posted = (SDL_PushEvent(&event) > 0); } if (relative) { mouse->last_x = mouse->x; mouse->last_y = mouse->y; } else { /* Use unclamped values if we're getting events outside the window */ mouse->last_x = x; mouse->last_y = y; } return posted; }
static void X11_DispatchEvent(_THIS) { SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; Display *display = videodata->display; SDL_WindowData *data; XEvent xevent; int i; SDL_zero(xevent); /* valgrind fix. --ryan. */ XNextEvent(display, &xevent); /* filter events catchs XIM events and sends them to the correct handler */ if (XFilterEvent(&xevent, None) == True) { #if 0 printf("Filtered event type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); #endif return; } /* Send a SDL_SYSWMEVENT if the application wants them */ if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) { SDL_SysWMmsg wmmsg; SDL_VERSION(&wmmsg.version); wmmsg.subsystem = SDL_SYSWM_X11; wmmsg.x11.event = xevent; SDL_SendSysWMEvent(&wmmsg); } data = NULL; if (videodata && videodata->windowlist) { for (i = 0; i < videodata->numwindows; ++i) { if ((videodata->windowlist[i] != NULL) && (videodata->windowlist[i]->xwindow == xevent.xany.window)) { data = videodata->windowlist[i]; break; } } } if (!data) { return; } #if 0 printf("type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); #endif switch (xevent.type) { /* Gaining mouse coverage? */ case EnterNotify:{ #ifdef DEBUG_XEVENTS printf("EnterNotify! (%d,%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); if (xevent.xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); if (xevent.xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif SDL_SetMouseFocus(data->window); } break; /* Losing mouse coverage? */ case LeaveNotify:{ #ifdef DEBUG_XEVENTS printf("LeaveNotify! (%d,%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); if (xevent.xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); if (xevent.xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif if (xevent.xcrossing.mode != NotifyGrab && xevent.xcrossing.mode != NotifyUngrab && xevent.xcrossing.detail != NotifyInferior) { SDL_SetMouseFocus(NULL); } } break; /* Gaining input focus? */ case FocusIn:{ #ifdef DEBUG_XEVENTS printf("FocusIn!\n"); #endif SDL_SetKeyboardFocus(data->window); #ifdef X_HAVE_UTF8_STRING if (data->ic) { XSetICFocus(data->ic); } #endif } break; /* Losing input focus? */ case FocusOut:{ #ifdef DEBUG_XEVENTS printf("FocusOut!\n"); #endif SDL_SetKeyboardFocus(NULL); #ifdef X_HAVE_UTF8_STRING if (data->ic) { XUnsetICFocus(data->ic); } #endif } break; /* Generated upon EnterWindow and FocusIn */ case KeymapNotify:{ #ifdef DEBUG_XEVENTS printf("KeymapNotify!\n"); #endif /* FIXME: X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); */ } break; /* Has the keyboard layout changed? */ case MappingNotify:{ #ifdef DEBUG_XEVENTS printf("MappingNotify!\n"); #endif X11_UpdateKeymap(_this); } break; /* Key press? */ case KeyPress:{ KeyCode keycode = xevent.xkey.keycode; KeySym keysym = NoSymbol; SDL_scancode scancode; char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; Status status = 0; #ifdef DEBUG_XEVENTS printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode); #endif SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]); #if 1 if (videodata->key_layout[keycode] == SDLK_UNKNOWN) { int min_keycode, max_keycode; XDisplayKeycodes(display, &min_keycode, &max_keycode); keysym = XKeycodeToKeysym(display, keycode, 0); fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <*****@*****.**> X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).\n", keycode, keycode - min_keycode, keysym, XKeysymToString(keysym)); } #endif /* */ SDL_zero(text); #ifdef X_HAVE_UTF8_STRING if (data->ic) { Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text), &keysym, &status); } #else XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL); #endif if (*text) { SDL_SendKeyboardText(text); } } break; /* Key release? */ case KeyRelease:{ KeyCode keycode = xevent.xkey.keycode; #ifdef DEBUG_XEVENTS printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode); #endif if (X11_KeyRepeat(display, &xevent)) { /* We're about to get a repeated key down, ignore the key up */ break; } SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]); } break; /* Have we been iconified? */ case UnmapNotify:{ #ifdef DEBUG_XEVENTS printf("UnmapNotify!\n"); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0); SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0); } break; /* Have we been restored? */ case MapNotify:{ #ifdef DEBUG_XEVENTS printf("MapNotify!\n"); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0); SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0); } break; /* Have we been resized or moved? */ case ConfigureNotify:{ #ifdef DEBUG_XEVENTS printf("ConfigureNotify! (resize: %dx%d)\n", xevent.xconfigure.width, xevent.xconfigure.height); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, xevent.xconfigure.x, xevent.xconfigure.y); SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, xevent.xconfigure.width, xevent.xconfigure.height); } break; /* Have we been requested to quit (or another client message?) */ case ClientMessage:{ if ((xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0); } } break; /* Do we need to refresh ourselves? */ case Expose:{ #ifdef DEBUG_XEVENTS printf("Expose (count = %d)\n", xevent.xexpose.count); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0); } break; case MotionNotify:{ #ifdef DEBUG_MOTION printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y); #endif SDL_SendMouseMotion(data->window, 0, xevent.xmotion.x, xevent.xmotion.y); } break; case ButtonPress:{ SDL_SendMouseButton(data->window, SDL_PRESSED, xevent.xbutton.button); } break; case ButtonRelease:{ SDL_SendMouseButton(data->window, SDL_RELEASED, xevent.xbutton.button); } break; case PropertyNotify:{ #ifdef DEBUG_XEVENTS unsigned char *propdata; int status, real_format; Atom real_type; unsigned long items_read, items_left, i; char *name = XGetAtomName(display, xevent.xproperty.atom); if (name) { printf("PropertyNotify: %s %s\n", name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed"); XFree(name); } status = XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata); if (status == Success && items_read > 0) { if (real_type == XA_INTEGER) { int *values = (int *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } else if (real_type == XA_CARDINAL) { if (real_format == 32) { Uint32 *values = (Uint32 *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } else if (real_format == 16) { Uint16 *values = (Uint16 *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } else if (real_format == 8) { Uint8 *values = (Uint8 *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } } else if (real_type == XA_STRING || real_type == videodata->UTF8_STRING) { printf("{ \"%s\" }\n", propdata); } else if (real_type == XA_ATOM) { Atom *atoms = (Atom *)propdata; printf("{"); for (i = 0; i < items_read; i++) { char *name = XGetAtomName(display, atoms[i]); if (name) { printf(" %s", name); XFree(name); } } printf(" }\n"); } else { char *name = XGetAtomName(display, real_type); printf("Unknown type: %ld (%s)\n", real_type, name ? name : "UNKNOWN"); if (name) { XFree(name); } } } #endif } break; /* Copy the selection from XA_CUT_BUFFER0 to the requested property */ case SelectionRequest: { XSelectionRequestEvent *req; XEvent sevent; int seln_format; unsigned long nbytes; unsigned long overflow; unsigned char *seln_data; req = &xevent.xselectionrequest; #ifdef DEBUG_XEVENTS printf("SelectionRequest (requestor = %ld, target = %ld)\n", req->requestor, req->target); #endif SDL_zero(sevent); sevent.xany.type = SelectionNotify; sevent.xselection.selection = req->selection; sevent.xselection.target = None; sevent.xselection.property = None; sevent.xselection.requestor = req->requestor; sevent.xselection.time = req->time; if (XGetWindowProperty(display, DefaultRootWindow(display), XA_CUT_BUFFER0, 0, INT_MAX/4, False, req->target, &sevent.xselection.target, &seln_format, &nbytes, &overflow, &seln_data) == Success) { if (sevent.xselection.target == req->target) { XChangeProperty(display, req->requestor, req->property, sevent.xselection.target, seln_format, PropModeReplace, seln_data, nbytes); sevent.xselection.property = req->property; } XFree(seln_data); } XSendEvent(display, req->requestor, False, 0, &sevent); XSync(display, False); } break; case SelectionNotify: { #ifdef DEBUG_XEVENTS printf("SelectionNotify (requestor = %ld, target = %ld)\n", xevent.xselection.requestor, xevent.xselection.target); #endif videodata->selection_waiting = SDL_FALSE; } break; default:{ #ifdef DEBUG_XEVENTS printf("Unhandled event %d\n", xevent.type); #endif } break; } }
static void X11_DispatchEvent(_THIS) { SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; Display *display = videodata->display; SDL_WindowData *data; XEvent xevent; int i; SDL_zero(xevent); /* valgrind fix. --ryan. */ XNextEvent(display, &xevent); /* filter events catchs XIM events and sends them to the correct handler */ if (XFilterEvent(&xevent, None) == True) { #if 0 printf("Filtered event type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); #endif return; } /* Send a SDL_SYSWMEVENT if the application wants them */ if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) { SDL_SysWMmsg wmmsg; SDL_VERSION(&wmmsg.version); wmmsg.subsystem = SDL_SYSWM_X11; wmmsg.msg.x11.event = xevent; SDL_SendSysWMEvent(&wmmsg); } #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS if(xevent.type == GenericEvent) { X11_HandleGenericEvent(videodata,xevent); return; } #endif #if 0 printf("type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); #endif data = NULL; if (videodata && videodata->windowlist) { for (i = 0; i < videodata->numwindows; ++i) { if ((videodata->windowlist[i] != NULL) && (videodata->windowlist[i]->xwindow == xevent.xany.window)) { data = videodata->windowlist[i]; break; } } } if (!data) { return; } switch (xevent.type) { /* Gaining mouse coverage? */ case EnterNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: EnterNotify! (%d,%d,%d)\n", data, xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); if (xevent.xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); if (xevent.xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif SDL_SetMouseFocus(data->window); } break; /* Losing mouse coverage? */ case LeaveNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: LeaveNotify! (%d,%d,%d)\n", data, xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); if (xevent.xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); if (xevent.xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif if (xevent.xcrossing.mode != NotifyGrab && xevent.xcrossing.mode != NotifyUngrab && xevent.xcrossing.detail != NotifyInferior) { SDL_SetMouseFocus(NULL); } } break; /* Gaining input focus? */ case FocusIn:{ if (xevent.xfocus.detail == NotifyInferior) { #ifdef DEBUG_XEVENTS printf("window %p: FocusIn (NotifierInferior, ignoring)\n", data); #endif break; } #ifdef DEBUG_XEVENTS printf("window %p: FocusIn!\n", data); #endif if (data->pending_focus == PENDING_FOCUS_OUT && data->window == SDL_GetKeyboardFocus()) { /* We want to reset the keyboard here, because we may have missed keyboard messages after our previous FocusOut. */ SDL_ResetKeyboard(); } data->pending_focus = PENDING_FOCUS_IN; data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_IN_TIME; } break; /* Losing input focus? */ case FocusOut:{ if (xevent.xfocus.detail == NotifyInferior) { /* We still have focus if a child gets focus */ #ifdef DEBUG_XEVENTS printf("window %p: FocusOut (NotifierInferior, ignoring)\n", data); #endif break; } #ifdef DEBUG_XEVENTS printf("window %p: FocusOut!\n", data); #endif data->pending_focus = PENDING_FOCUS_OUT; data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_OUT_TIME; } break; /* Generated upon EnterWindow and FocusIn */ case KeymapNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: KeymapNotify!\n", data); #endif /* FIXME: X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); */ } break; /* Has the keyboard layout changed? */ case MappingNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: MappingNotify!\n", data); #endif X11_UpdateKeymap(_this); } break; /* Key press? */ case KeyPress:{ KeyCode keycode = xevent.xkey.keycode; KeySym keysym = NoSymbol; char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; Status status = 0; #ifdef DEBUG_XEVENTS printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode); #endif SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]); #if 1 if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN) { int min_keycode, max_keycode; XDisplayKeycodes(display, &min_keycode, &max_keycode); #if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM keysym = XkbKeycodeToKeysym(display, keycode, 0, 0); #else keysym = XKeycodeToKeysym(display, keycode, 0); #endif fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <*****@*****.**> X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).\n", keycode, keycode - min_keycode, keysym, XKeysymToString(keysym)); } #endif /* */ SDL_zero(text); #ifdef X_HAVE_UTF8_STRING if (data->ic) { Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text), &keysym, &status); } #else XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL); #endif if (*text) { SDL_SendKeyboardText(text); } } break; /* Key release? */ case KeyRelease:{ KeyCode keycode = xevent.xkey.keycode; #ifdef DEBUG_XEVENTS printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode); #endif if (X11_KeyRepeat(display, &xevent)) { /* We're about to get a repeated key down, ignore the key up */ break; } SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]); } break; /* Have we been iconified? */ case UnmapNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: UnmapNotify!\n", data); #endif X11_DispatchUnmapNotify(data); } break; /* Have we been restored? */ case MapNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: MapNotify!\n", data); #endif X11_DispatchMapNotify(data); } break; /* Have we been resized or moved? */ case ConfigureNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: ConfigureNotify! (position: %d,%d, size: %dx%d)\n", data, xevent.xconfigure.x, xevent.xconfigure.y, xevent.xconfigure.width, xevent.xconfigure.height); #endif if (xevent.xconfigure.x != data->last_xconfigure.x || xevent.xconfigure.y != data->last_xconfigure.y) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, xevent.xconfigure.x, xevent.xconfigure.y); } if (xevent.xconfigure.width != data->last_xconfigure.width || xevent.xconfigure.height != data->last_xconfigure.height) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, xevent.xconfigure.width, xevent.xconfigure.height); } data->last_xconfigure = xevent.xconfigure; } break; /* Have we been requested to quit (or another client message?) */ case ClientMessage:{ if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) && (xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == videodata->_NET_WM_PING)) { Window root = DefaultRootWindow(display); #ifdef DEBUG_XEVENTS printf("window %p: _NET_WM_PING\n", data); #endif xevent.xclient.window = root; XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent); break; } else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) && (xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) { #ifdef DEBUG_XEVENTS printf("window %p: WM_DELETE_WINDOW\n", data); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0); break; } } break; /* Do we need to refresh ourselves? */ case Expose:{ #ifdef DEBUG_XEVENTS printf("window %p: Expose (count = %d)\n", data, xevent.xexpose.count); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0); } break; case MotionNotify:{ SDL_Mouse *mouse = SDL_GetMouse(); if(!mouse->relative_mode) { #ifdef DEBUG_MOTION printf("window %p: X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y); #endif SDL_SendMouseMotion(data->window, 0, xevent.xmotion.x, xevent.xmotion.y); } } break; case ButtonPress:{ int ticks = 0; if (X11_IsWheelEvent(display,&xevent,&ticks) == SDL_TRUE) { SDL_SendMouseWheel(data->window, 0, ticks); } else { SDL_SendMouseButton(data->window, SDL_PRESSED, xevent.xbutton.button); } } break; case ButtonRelease:{ SDL_SendMouseButton(data->window, SDL_RELEASED, xevent.xbutton.button); } break; case PropertyNotify:{ #ifdef DEBUG_XEVENTS unsigned char *propdata; int status, real_format; Atom real_type; unsigned long items_read, items_left, i; char *name = XGetAtomName(display, xevent.xproperty.atom); if (name) { printf("window %p: PropertyNotify: %s %s\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed"); XFree(name); } status = XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata); if (status == Success && items_read > 0) { if (real_type == XA_INTEGER) { int *values = (int *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } else if (real_type == XA_CARDINAL) { if (real_format == 32) { Uint32 *values = (Uint32 *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } else if (real_format == 16) { Uint16 *values = (Uint16 *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } else if (real_format == 8) { Uint8 *values = (Uint8 *)propdata; printf("{"); for (i = 0; i < items_read; i++) { printf(" %d", values[i]); } printf(" }\n"); } } else if (real_type == XA_STRING || real_type == videodata->UTF8_STRING) { printf("{ \"%s\" }\n", propdata); } else if (real_type == XA_ATOM) { Atom *atoms = (Atom *)propdata; printf("{"); for (i = 0; i < items_read; i++) { char *name = XGetAtomName(display, atoms[i]); if (name) { printf(" %s", name); XFree(name); } } printf(" }\n"); } else { char *name = XGetAtomName(display, real_type); printf("Unknown type: %ld (%s)\n", real_type, name ? name : "UNKNOWN"); if (name) { XFree(name); } } } if (status == Success) { XFree(propdata); } #endif /* DEBUG_XEVENTS */ if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) { /* Get the new state from the window manager. Compositing window managers can alter visibility of windows without ever mapping / unmapping them, so we handle that here, because they use the NETWM protocol to notify us of changes. */ Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window); if ((flags^data->window->flags) & SDL_WINDOW_HIDDEN) { if (flags & SDL_WINDOW_HIDDEN) { X11_DispatchUnmapNotify(data); } else { X11_DispatchMapNotify(data); } } } } break; /* Copy the selection from XA_CUT_BUFFER0 to the requested property */ case SelectionRequest: { XSelectionRequestEvent *req; XEvent sevent; int seln_format; unsigned long nbytes; unsigned long overflow; unsigned char *seln_data; req = &xevent.xselectionrequest; #ifdef DEBUG_XEVENTS printf("window %p: SelectionRequest (requestor = %ld, target = %ld)\n", data, req->requestor, req->target); #endif SDL_zero(sevent); sevent.xany.type = SelectionNotify; sevent.xselection.selection = req->selection; sevent.xselection.target = None; sevent.xselection.property = None; sevent.xselection.requestor = req->requestor; sevent.xselection.time = req->time; if (XGetWindowProperty(display, DefaultRootWindow(display), XA_CUT_BUFFER0, 0, INT_MAX/4, False, req->target, &sevent.xselection.target, &seln_format, &nbytes, &overflow, &seln_data) == Success) { if (sevent.xselection.target == req->target) { XChangeProperty(display, req->requestor, req->property, sevent.xselection.target, seln_format, PropModeReplace, seln_data, nbytes); sevent.xselection.property = req->property; } XFree(seln_data); } XSendEvent(display, req->requestor, False, 0, &sevent); XSync(display, False); } break; case SelectionNotify: { #ifdef DEBUG_XEVENTS printf("window %p: SelectionNotify (requestor = %ld, target = %ld)\n", data, xevent.xselection.requestor, xevent.xselection.target); #endif videodata->selection_waiting = SDL_FALSE; } break; default:{ #ifdef DEBUG_XEVENTS printf("window %p: Unhandled event %d\n", data, xevent.type); #endif } break; } }
int SDL_SendMouseMotion(SDL_Window * window, int relative, int x, int y) { SDL_Mouse *mouse = SDL_GetMouse(); int posted; int xrel; int yrel; int x_max = 0, y_max = 0; if (window) { SDL_SetMouseFocus(window); } /* the relative motion is calculated regarding the system cursor last position */ if (relative) { xrel = x; yrel = y; x = (mouse->last_x + x); y = (mouse->last_y + y); } else { xrel = x - mouse->last_x; yrel = y - mouse->last_y; } /* Drop events that don't change state */ if (!xrel && !yrel) { #if 0 printf("Mouse event didn't change state - dropped!\n"); #endif return 0; } /* Update internal mouse coordinates */ if (mouse->relative_mode == SDL_FALSE) { mouse->x = x; mouse->y = y; } else { mouse->x += xrel; mouse->y += yrel; } SDL_GetWindowSize(mouse->focus, &x_max, &y_max); --x_max; --y_max; /* make sure that the pointers find themselves inside the windows */ /* only check if mouse->xmax is set ! */ if (mouse->x > x_max) { mouse->x = x_max; } if (mouse->x < 0) { mouse->x = 0; } if (mouse->y > y_max) { mouse->y = y_max; } if (mouse->y < 0) { mouse->y = 0; } mouse->xdelta += xrel; mouse->ydelta += yrel; #if 0 /* FIXME */ /* Move the mouse cursor, if needed */ if (mouse->cursor_shown && !mouse->relative_mode && mouse->MoveCursor && mouse->cur_cursor) { mouse->MoveCursor(mouse->cur_cursor); } #endif /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE) { SDL_Event event; event.motion.type = SDL_MOUSEMOTION; event.motion.windowID = mouse->focus ? mouse->focus->id : 0; event.motion.state = mouse->buttonstate; event.motion.x = mouse->x; event.motion.y = mouse->y; event.motion.xrel = xrel; event.motion.yrel = yrel; posted = (SDL_PushEvent(&event) > 0); } mouse->last_x = mouse->x; mouse->last_y = mouse->y; return posted; }
static void X11_DispatchEvent(_THIS) { SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; SDL_WindowData *data; XEvent xevent; int i; SDL_zero(xevent); /* valgrind fix. --ryan. */ XNextEvent(videodata->display, &xevent); /* filter events catchs XIM events and sends them to the correct handler */ if (XFilterEvent(&xevent, None) == True) { #if 0 printf("Filtered event type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); #endif return; } /* Send a SDL_SYSWMEVENT if the application wants them */ if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) { SDL_SysWMmsg wmmsg; SDL_VERSION(&wmmsg.version); wmmsg.subsystem = SDL_SYSWM_X11; wmmsg.event.xevent = xevent; SDL_SendSysWMEvent(&wmmsg); } data = NULL; if (videodata && videodata->windowlist) { for (i = 0; i < videodata->numwindows; ++i) { if ((videodata->windowlist[i] != NULL) && (videodata->windowlist[i]->window == xevent.xany.window)) { data = videodata->windowlist[i]; break; } } } if (!data) { return; } #if 0 printf("type = %d display = %d window = %d\n", xevent.type, xevent.xany.display, xevent.xany.window); #endif switch (xevent.type) { /* Gaining mouse coverage? */ case EnterNotify:{ #ifdef DEBUG_XEVENTS printf("EnterNotify! (%d,%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); if (xevent.xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); if (xevent.xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif #if 1 /* FIXME: Should we reset data for all mice? */ for (i = 0; i < SDL_GetNumMice(); ++i) { SDL_Mouse *mouse = SDL_GetMouse(i); SDL_SetMouseFocus(mouse->id, data->windowID); } #endif } break; /* Losing mouse coverage? */ case LeaveNotify:{ #ifdef DEBUG_XEVENTS printf("LeaveNotify! (%d,%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y, xevent.xcrossing.mode); if (xevent.xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); if (xevent.xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif if (xevent.xcrossing.detail != NotifyInferior) { #if 1 /* FIXME: Should we reset data for all mice? */ for (i = 0; i < SDL_GetNumMice(); ++i) { SDL_Mouse *mouse = SDL_GetMouse(i); SDL_SetMouseFocus(mouse->id, 0); } #endif } } break; /* Gaining input focus? */ case FocusIn:{ #ifdef DEBUG_XEVENTS printf("FocusIn!\n"); #endif SDL_SetKeyboardFocus(videodata->keyboard, data->windowID); #ifdef X_HAVE_UTF8_STRING if (data->ic) { XSetICFocus(data->ic); } #endif } break; /* Losing input focus? */ case FocusOut:{ #ifdef DEBUG_XEVENTS printf("FocusOut!\n"); #endif SDL_SetKeyboardFocus(videodata->keyboard, 0); #ifdef X_HAVE_UTF8_STRING if (data->ic) { XUnsetICFocus(data->ic); } #endif } break; /* Generated upon EnterWindow and FocusIn */ case KeymapNotify:{ #ifdef DEBUG_XEVENTS printf("KeymapNotify!\n"); #endif /* FIXME: X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector); */ } break; /* Has the keyboard layout changed? */ case MappingNotify:{ #ifdef DEBUG_XEVENTS printf("MappingNotify!\n"); #endif X11_UpdateKeymap(_this); } break; /* Key press? */ case KeyPress:{ KeyCode keycode = xevent.xkey.keycode; KeySym keysym = NoSymbol; char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; Status status = 0; #ifdef DEBUG_XEVENTS printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode); #endif SDL_SendKeyboardKey(videodata->keyboard, SDL_PRESSED, videodata->key_layout[keycode]); #if 0 if (videodata->key_layout[keycode] == SDLK_UNKNOWN) { int min_keycode, max_keycode; XDisplayKeycodes(videodata->display, &min_keycode, &max_keycode); keysym = XKeycodeToKeysym(videodata->display, keycode, 0); fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <*****@*****.**> X11 KeyCode %d (%d), X11 KeySym 0x%X (%s).\n", keycode, keycode - min_keycode, keysym, XKeysymToString(keysym)); } #endif /* */ SDL_zero(text); #ifdef X_HAVE_UTF8_STRING if (data->ic) { Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text), &keysym, &status); } #else XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL); #endif if (*text) { SDL_SendKeyboardText(videodata->keyboard, text); } } break; /* Key release? */ case KeyRelease:{ KeyCode keycode = xevent.xkey.keycode; #ifdef DEBUG_XEVENTS printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode); #endif SDL_SendKeyboardKey(videodata->keyboard, SDL_RELEASED, videodata->key_layout[keycode]); } break; /* Have we been iconified? */ case UnmapNotify:{ #ifdef DEBUG_XEVENTS printf("UnmapNotify!\n"); #endif SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_HIDDEN, 0, 0); SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MINIMIZED, 0, 0); } break; /* Have we been restored? */ case MapNotify:{ #ifdef DEBUG_XEVENTS printf("MapNotify!\n"); #endif SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_SHOWN, 0, 0); SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESTORED, 0, 0); } break; /* Have we been resized or moved? */ case ConfigureNotify:{ #ifdef DEBUG_XEVENTS printf("ConfigureNotify! (resize: %dx%d)\n", xevent.xconfigure.width, xevent.xconfigure.height); #endif SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_MOVED, xevent.xconfigure.x, xevent.xconfigure.y); SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_RESIZED, xevent.xconfigure.width, xevent.xconfigure.height); } break; /* Have we been requested to quit (or another client message?) */ case ClientMessage:{ if ((xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) { SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_CLOSE, 0, 0); } } break; /* Do we need to refresh ourselves? */ case Expose:{ #ifdef DEBUG_XEVENTS printf("Expose (count = %d)\n", xevent.xexpose.count); #endif SDL_SendWindowEvent(data->windowID, SDL_WINDOWEVENT_EXPOSED, 0, 0); } break; default:{ for (i = 0; i < SDL_GetNumMice(); ++i) { SDL_Mouse *mouse; #if SDL_VIDEO_DRIVER_X11_XINPUT X11_MouseData *data; #endif mouse = SDL_GetMouse(i); if (!mouse->driverdata) { switch (xevent.type) { case MotionNotify: #ifdef DEBUG_MOTION printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y); #endif SDL_SendMouseMotion(mouse->id, 0, xevent.xmotion.x, xevent.xmotion.y, 0); break; case ButtonPress: SDL_SendMouseButton(mouse->id, SDL_PRESSED, xevent.xbutton.button); break; case ButtonRelease: SDL_SendMouseButton(mouse->id, SDL_RELEASED, xevent.xbutton.button); break; } continue; } #if SDL_VIDEO_DRIVER_X11_XINPUT data = (X11_MouseData *) mouse->driverdata; if (xevent.type == data->motion) { XDeviceMotionEvent *move = (XDeviceMotionEvent *) & xevent; #ifdef DEBUG_MOTION printf("X11 motion: %d,%d\n", move->x, move->y); #endif SDL_SendMouseMotion(move->deviceid, 0, move->x, move->y, move->axis_data[2]); return; } if (xevent.type == data->button_pressed) { XDeviceButtonPressedEvent *pressed = (XDeviceButtonPressedEvent *) & xevent; SDL_SendMouseButton(pressed->deviceid, SDL_PRESSED, pressed->button); return; } if (xevent.type == data->button_released) { XDeviceButtonReleasedEvent *released = (XDeviceButtonReleasedEvent *) & xevent; SDL_SendMouseButton(released->deviceid, SDL_RELEASED, released->button); return; } if (xevent.type == data->proximity_in) { XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) & xevent; SDL_SendProximity(proximity->deviceid, proximity->x, proximity->y, SDL_PROXIMITYIN); return; } if (xevent.type == data->proximity_out) { XProximityNotifyEvent *proximity = (XProximityNotifyEvent *) & xevent; SDL_SendProximity(proximity->deviceid, proximity->x, proximity->y, SDL_PROXIMITYOUT); return; } #endif } #ifdef DEBUG_XEVENTS printf("Unhandled event %d\n", xevent.type); #endif } break; } }
int KMSDRM_CreateWindow(_THIS, SDL_Window * window) { SDL_WindowData *wdata; SDL_VideoDisplay *display; SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); Uint32 surface_fmt, surface_flags; /* Allocate window internal data */ wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData)); if (wdata == NULL) { SDL_OutOfMemory(); goto error; } wdata->waiting_for_flip = SDL_FALSE; display = SDL_GetDisplayForWindow(window); /* Windows have one size for now */ window->w = display->desktop_mode.w; window->h = display->desktop_mode.h; /* Maybe you didn't ask for a fullscreen OpenGL window, but that's what you get */ window->flags |= (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL); surface_fmt = GBM_FORMAT_XRGB8888; surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; if (!KMSDRM_gbm_device_is_format_supported(vdata->gbm, surface_fmt, surface_flags)) { SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "GBM surface format not supported. Trying anyway."); } wdata->gs = KMSDRM_gbm_surface_create(vdata->gbm, window->w, window->h, surface_fmt, surface_flags); #if SDL_VIDEO_OPENGL_EGL if (!_this->egl_data) { if (SDL_GL_LoadLibrary(NULL) < 0) { goto error; } } wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wdata->gs); if (wdata->egl_surface == EGL_NO_SURFACE) { SDL_SetError("Could not create EGL window surface"); goto error; } #endif /* SDL_VIDEO_OPENGL_EGL */ /* In case we want low-latency, double-buffer video, we take note here */ wdata->double_buffer = SDL_FALSE; if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE)) { wdata->double_buffer = SDL_TRUE; } /* Window is created, but we have yet to set up CRTC to one of the GBM buffers if we want drmModePageFlip to work, and we can't do it until EGL is completely setup, because we need to do eglSwapBuffers so we can get a valid GBM buffer object to call drmModeSetCrtc on it. */ wdata->crtc_ready = SDL_FALSE; /* Setup driver data for this window */ window->driverdata = wdata; /* One window, it always has focus */ SDL_SetMouseFocus(window); SDL_SetKeyboardFocus(window); /* Window has been successfully created */ return 0; error: if (wdata != NULL) { #if SDL_VIDEO_OPENGL_EGL if (wdata->egl_surface != EGL_NO_SURFACE) SDL_EGL_DestroySurface(_this, wdata->egl_surface); #endif /* SDL_VIDEO_OPENGL_EGL */ if (wdata->gs != NULL) KMSDRM_gbm_surface_destroy(wdata->gs); SDL_free(wdata); } return -1; }