Listing the "Blender Foundation" as copyright holder implied the Blender Foundation holds copyright to files which may include work from many developers. While keeping copyright on headers makes sense for isolated libraries, Blender's own code may be refactored or moved between files in a way that makes the per file copyright holders less meaningful. Copyright references to the "Blender Foundation" have been replaced with "Blender Authors", with the exception of `./extern/` since these this contains libraries which are more isolated, any changed to license headers there can be handled on a case-by-case basis. Some directories in `./intern/` have also been excluded: - `./intern/cycles/` it's own `AUTHORS` file is planned. - `./intern/opensubdiv/`. An "AUTHORS" file has been added, using the chromium projects authors file as a template. Design task: #110784 Ref !110783.
658 lines
23 KiB
C++
658 lines
23 KiB
C++
/* SPDX-FileCopyrightText: 2011-2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup GHOST
|
|
*/
|
|
|
|
#include "GHOST_WindowSDL.hh"
|
|
#include "SDL_mouse.h"
|
|
|
|
#include "GHOST_ContextSDL.hh"
|
|
|
|
#include <cassert>
|
|
|
|
GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system,
|
|
const char *title,
|
|
int32_t left,
|
|
int32_t top,
|
|
uint32_t width,
|
|
uint32_t height,
|
|
GHOST_TWindowState state,
|
|
GHOST_TDrawingContextType type,
|
|
const bool stereoVisual,
|
|
const bool exclusive,
|
|
const GHOST_IWindow * /*parentWindow*/)
|
|
: GHOST_Window(width, height, state, stereoVisual, exclusive),
|
|
m_system(system),
|
|
m_valid_setup(false),
|
|
m_invalid_window(false),
|
|
m_sdl_custom_cursor(nullptr)
|
|
{
|
|
|
|
/* creating the window _must_ come after setting attributes */
|
|
m_sdl_win = SDL_CreateWindow(title,
|
|
left,
|
|
top,
|
|
width,
|
|
height,
|
|
SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
|
|
|
|
/* now set up the rendering context. */
|
|
if (setDrawingContextType(type) == GHOST_kSuccess) {
|
|
m_valid_setup = true;
|
|
GHOST_PRINT("Created window\n");
|
|
}
|
|
|
|
if (exclusive) {
|
|
SDL_RaiseWindow(m_sdl_win);
|
|
}
|
|
|
|
setTitle(title);
|
|
}
|
|
|
|
GHOST_WindowSDL::~GHOST_WindowSDL()
|
|
{
|
|
if (m_sdl_custom_cursor) {
|
|
SDL_FreeCursor(m_sdl_custom_cursor);
|
|
}
|
|
|
|
releaseNativeHandles();
|
|
|
|
SDL_DestroyWindow(m_sdl_win);
|
|
}
|
|
|
|
GHOST_Context *GHOST_WindowSDL::newDrawingContext(GHOST_TDrawingContextType type)
|
|
{
|
|
switch (type) {
|
|
#ifdef WITH_OPENGL_BACKEND
|
|
case GHOST_kDrawingContextTypeOpenGL: {
|
|
for (int minor = 6; minor >= 3; --minor) {
|
|
GHOST_Context *context = new GHOST_ContextSDL(
|
|
m_wantStereoVisual,
|
|
m_sdl_win,
|
|
0, /* Profile bit. */
|
|
4,
|
|
minor,
|
|
GHOST_OPENGL_SDL_CONTEXT_FLAGS,
|
|
GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY);
|
|
|
|
if (context->initializeDrawingContext()) {
|
|
return context;
|
|
}
|
|
delete context;
|
|
}
|
|
return nullptr;
|
|
}
|
|
#endif
|
|
|
|
default:
|
|
/* Unsupported backend. */
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
GHOST_TSuccess GHOST_WindowSDL::invalidate()
|
|
{
|
|
if (m_invalid_window == false) {
|
|
m_system->addDirtyWindow(this);
|
|
m_invalid_window = true;
|
|
}
|
|
|
|
return GHOST_kSuccess;
|
|
}
|
|
|
|
GHOST_TSuccess GHOST_WindowSDL::setState(GHOST_TWindowState state)
|
|
{
|
|
switch (state) {
|
|
case GHOST_kWindowStateNormal:
|
|
SDL_SetWindowFullscreen(m_sdl_win, SDL_FALSE);
|
|
SDL_RestoreWindow(m_sdl_win);
|
|
break;
|
|
case GHOST_kWindowStateMaximized:
|
|
SDL_SetWindowFullscreen(m_sdl_win, SDL_FALSE);
|
|
SDL_MaximizeWindow(m_sdl_win);
|
|
break;
|
|
case GHOST_kWindowStateMinimized:
|
|
SDL_MinimizeWindow(m_sdl_win);
|
|
break;
|
|
case GHOST_kWindowStateFullScreen:
|
|
SDL_SetWindowFullscreen(m_sdl_win, SDL_TRUE);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return GHOST_kSuccess;
|
|
}
|
|
|
|
GHOST_TWindowState GHOST_WindowSDL::getState() const
|
|
{
|
|
Uint32 flags = SDL_GetWindowFlags(m_sdl_win);
|
|
|
|
if (flags & SDL_WINDOW_FULLSCREEN) {
|
|
return GHOST_kWindowStateFullScreen;
|
|
}
|
|
if (flags & SDL_WINDOW_MAXIMIZED) {
|
|
return GHOST_kWindowStateMaximized;
|
|
}
|
|
if (flags & SDL_WINDOW_MINIMIZED) {
|
|
return GHOST_kWindowStateMinimized;
|
|
}
|
|
return GHOST_kWindowStateNormal;
|
|
}
|
|
|
|
bool GHOST_WindowSDL::getValid() const
|
|
{
|
|
return GHOST_Window::getValid() && m_valid_setup;
|
|
}
|
|
|
|
void GHOST_WindowSDL::setTitle(const char *title)
|
|
{
|
|
SDL_SetWindowTitle(m_sdl_win, title);
|
|
}
|
|
|
|
std::string GHOST_WindowSDL::getTitle() const
|
|
{
|
|
return SDL_GetWindowTitle(m_sdl_win);
|
|
}
|
|
|
|
void GHOST_WindowSDL::getWindowBounds(GHOST_Rect &bounds) const
|
|
{
|
|
getClientBounds(bounds);
|
|
}
|
|
|
|
void GHOST_WindowSDL::getClientBounds(GHOST_Rect &bounds) const
|
|
{
|
|
int x, y, w, h;
|
|
SDL_GetWindowSize(m_sdl_win, &w, &h);
|
|
SDL_GetWindowPosition(m_sdl_win, &x, &y);
|
|
|
|
bounds.m_l = x;
|
|
bounds.m_r = x + w;
|
|
bounds.m_t = y;
|
|
bounds.m_b = y + h;
|
|
}
|
|
|
|
GHOST_TSuccess GHOST_WindowSDL::setClientWidth(uint32_t width)
|
|
{
|
|
int height;
|
|
SDL_GetWindowSize(m_sdl_win, nullptr, &height);
|
|
SDL_SetWindowSize(m_sdl_win, width, height);
|
|
return GHOST_kSuccess;
|
|
}
|
|
|
|
GHOST_TSuccess GHOST_WindowSDL::setClientHeight(uint32_t height)
|
|
{
|
|
int width;
|
|
SDL_GetWindowSize(m_sdl_win, &width, nullptr);
|
|
SDL_SetWindowSize(m_sdl_win, width, height);
|
|
return GHOST_kSuccess;
|
|
}
|
|
|
|
GHOST_TSuccess GHOST_WindowSDL::setClientSize(uint32_t width, uint32_t height)
|
|
{
|
|
SDL_SetWindowSize(m_sdl_win, width, height);
|
|
return GHOST_kSuccess;
|
|
}
|
|
|
|
void GHOST_WindowSDL::screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
|
|
{
|
|
/* XXXSDL_WEAK_ABS_COORDS */
|
|
int x_win, y_win;
|
|
SDL_GetWindowPosition(m_sdl_win, &x_win, &y_win);
|
|
|
|
outX = inX - x_win;
|
|
outY = inY - y_win;
|
|
}
|
|
void GHOST_WindowSDL::clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const
|
|
{
|
|
/* XXXSDL_WEAK_ABS_COORDS */
|
|
int x_win, y_win;
|
|
SDL_GetWindowPosition(m_sdl_win, &x_win, &y_win);
|
|
|
|
outX = inX + x_win;
|
|
outY = inY + y_win;
|
|
}
|
|
|
|
/* mouse cursor */
|
|
static uchar sdl_std_cursor_mask_xterm[] = {
|
|
0xef, 0x01, 0xff, 0x01, 0xff, 0x01, 0x7c, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00,
|
|
0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x7c, 0x00, 0xff, 0x01, 0xff, 0x01, 0xef, 0x01,
|
|
};
|
|
static uchar sdl_std_cursor_xterm[] = {
|
|
0x00, 0x77, 0x00, 0x1c, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08,
|
|
0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x1c, 0x00, 0x77, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_xterm 9
|
|
#define sdl_std_cursor_HEIGHT_xterm 16
|
|
#define sdl_std_cursor_HOT_X_xterm -3
|
|
#define sdl_std_cursor_HOT_Y_xterm -7
|
|
|
|
static uchar sdl_std_cursor_mask_watch[] = {
|
|
0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfe, 0x1f, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfe, 0x1f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
|
|
};
|
|
static uchar sdl_std_cursor_watch[] = {
|
|
0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0xfc, 0x0f, 0x86, 0x18, 0x83, 0x30, 0x81, 0xe0, 0xc1, 0xe1,
|
|
0xc1, 0xe1, 0x21, 0xe0, 0x13, 0x30, 0x06, 0x18, 0xfc, 0x0f, 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_watch 16
|
|
#define sdl_std_cursor_HEIGHT_watch 16
|
|
#define sdl_std_cursor_HOT_X_watch -15
|
|
#define sdl_std_cursor_HOT_Y_watch -7
|
|
|
|
static uchar sdl_std_cursor_mask_umbrella[] = {
|
|
0xe8, 0x76, 0xfb, 0xdf, 0xfd, 0x3f, 0xfe, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xcf, 0x79, 0xc0, 0x01,
|
|
0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0x80, 0x03,
|
|
};
|
|
static uchar sdl_std_cursor_umbrella[] = {
|
|
0x88, 0x04, 0x20, 0x0a, 0xc9, 0x32, 0xf2, 0x09, 0x4c, 0x06, 0x43, 0x18, 0x40, 0x00, 0x40, 0x00,
|
|
0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x01, 0x40, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_umbrella 16
|
|
#define sdl_std_cursor_HEIGHT_umbrella 16
|
|
#define sdl_std_cursor_HOT_X_umbrella -7
|
|
#define sdl_std_cursor_HOT_Y_umbrella -12
|
|
|
|
static uchar sdl_std_cursor_mask_top_side[] = {
|
|
0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f,
|
|
0xdc, 0x1d, 0xcc, 0x19, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01,
|
|
};
|
|
static uchar sdl_std_cursor_top_side[] = {
|
|
0xff, 0x1f, 0xff, 0x1f, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x00, 0x50, 0x01, 0x48, 0x02, 0x44, 0x04,
|
|
0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_top_side 15
|
|
#define sdl_std_cursor_HEIGHT_top_side 16
|
|
#define sdl_std_cursor_HOT_X_top_side -6
|
|
#define sdl_std_cursor_HOT_Y_top_side -14
|
|
|
|
static uchar sdl_std_cursor_mask_top_right_corner[] = {
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xfc, 0xf7, 0xfc, 0xf7, 0xfc, 0xf7,
|
|
0xc0, 0xf7, 0xe0, 0xf7, 0x70, 0xf7, 0x38, 0xf7, 0x1c, 0xf7, 0x0c, 0xf7, 0x00, 0xf0, 0x00, 0xf0,
|
|
};
|
|
static uchar sdl_std_cursor_top_right_corner[] = {
|
|
0xff, 0x3f, 0xff, 0x3f, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0xfc, 0x31, 0x80, 0x31, 0x40, 0x31,
|
|
0x20, 0x31, 0x10, 0x31, 0x08, 0x31, 0x04, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_top_right_corner 16
|
|
#define sdl_std_cursor_HEIGHT_top_right_corner 16
|
|
#define sdl_std_cursor_HOT_X_top_right_corner -13
|
|
#define sdl_std_cursor_HOT_Y_top_right_corner -14
|
|
|
|
static uchar sdl_std_cursor_mask_top_left_corner[] = {
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xef, 0x3f, 0xef, 0x3f, 0xef, 0x3f,
|
|
0xef, 0x03, 0xef, 0x07, 0xef, 0x0e, 0xef, 0x1c, 0xef, 0x38, 0xef, 0x30, 0x0f, 0x00, 0x0f, 0x00,
|
|
};
|
|
static uchar sdl_std_cursor_top_left_corner[] = {
|
|
0xff, 0x3f, 0xff, 0x3f, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xe3, 0x0f, 0x63, 0x00, 0xa3, 0x00,
|
|
0x23, 0x01, 0x23, 0x02, 0x23, 0x04, 0x23, 0x08, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_top_left_corner 16
|
|
#define sdl_std_cursor_HEIGHT_top_left_corner 16
|
|
#define sdl_std_cursor_HOT_X_top_left_corner 0
|
|
#define sdl_std_cursor_HOT_Y_top_left_corner -14
|
|
|
|
static uchar sdl_std_cursor_mask_sb_v_double_arrow[] = {
|
|
0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0xff, 0x01, 0xff, 0x01, 0x7c, 0x00, 0x7c, 0x00, 0x7c,
|
|
0x00, 0x7c, 0x00, 0x7c, 0x00, 0xff, 0x01, 0xff, 0x01, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00,
|
|
};
|
|
static uchar sdl_std_cursor_sb_v_double_arrow[] = {
|
|
0x10, 0x00, 0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28,
|
|
0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_sb_v_double_arrow 9
|
|
#define sdl_std_cursor_HEIGHT_sb_v_double_arrow 15
|
|
#define sdl_std_cursor_HOT_X_sb_v_double_arrow -3
|
|
#define sdl_std_cursor_HOT_Y_sb_v_double_arrow -8
|
|
|
|
static uchar sdl_std_cursor_mask_sb_h_double_arrow[] = {
|
|
0x18,
|
|
0x0c,
|
|
0x1c,
|
|
0x1c,
|
|
0xfe,
|
|
0x3f,
|
|
0xff,
|
|
0x7f,
|
|
0xff,
|
|
0x7f,
|
|
0xff,
|
|
0x7f,
|
|
0xfe,
|
|
0x3f,
|
|
0x1c,
|
|
0x1c,
|
|
0x18,
|
|
0x0c,
|
|
};
|
|
static uchar sdl_std_cursor_sb_h_double_arrow[] = {
|
|
0x00,
|
|
0x00,
|
|
0x08,
|
|
0x08,
|
|
0x0c,
|
|
0x18,
|
|
0xfe,
|
|
0x3f,
|
|
0x0f,
|
|
0x78,
|
|
0xfe,
|
|
0x3f,
|
|
0x0c,
|
|
0x18,
|
|
0x08,
|
|
0x08,
|
|
0x00,
|
|
0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_sb_h_double_arrow 15
|
|
#define sdl_std_cursor_HEIGHT_sb_h_double_arrow 9
|
|
#define sdl_std_cursor_HOT_X_sb_h_double_arrow -7
|
|
#define sdl_std_cursor_HOT_Y_sb_h_double_arrow -4
|
|
|
|
static uchar sdl_std_cursor_mask_right_side[] = {
|
|
0x00, 0xf0, 0x00, 0xf0, 0xc0, 0xf0, 0xc0, 0xf1, 0x80, 0xf3, 0x00, 0xf7, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0x00, 0xf7, 0x80, 0xf3, 0xc0, 0xf1, 0xc0, 0xf0, 0x00, 0xf0, 0x00, 0xf0,
|
|
};
|
|
static uchar sdl_std_cursor_right_side[] = {
|
|
0x00, 0x30, 0x00, 0x30, 0x40, 0x30, 0x80, 0x30, 0x00, 0x31, 0x00, 0x32, 0xff, 0x37, 0x00,
|
|
0x32, 0x00, 0x31, 0x80, 0x30, 0x40, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_right_side 16
|
|
#define sdl_std_cursor_HEIGHT_right_side 15
|
|
#define sdl_std_cursor_HOT_X_right_side -13
|
|
#define sdl_std_cursor_HOT_Y_right_side -7
|
|
|
|
static uchar sdl_std_cursor_mask_right_ptr[] = {
|
|
0x00, 0x03, 0x80, 0x03, 0xc0, 0x03, 0xe0, 0x03, 0xf0, 0x03, 0xf8, 0x03, 0xfc, 0x03, 0xfe, 0x03,
|
|
0xff, 0x03, 0xff, 0x03, 0xf8, 0x03, 0xbc, 0x03, 0x3c, 0x03, 0x1e, 0x00, 0x1e, 0x00, 0x0c, 0x00,
|
|
};
|
|
static uchar sdl_std_cursor_right_ptr[] = {
|
|
0x00, 0x80, 0x00, 0xc0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf8, 0x00, 0xfc, 0x00, 0xfe, 0x00, 0xff,
|
|
0x00, 0xf8, 0x00, 0xd8, 0x00, 0x8c, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_right_ptr 10
|
|
#define sdl_std_cursor_HEIGHT_right_ptr 16
|
|
#define sdl_std_cursor_HOT_X_right_ptr -7
|
|
#define sdl_std_cursor_HOT_Y_right_ptr -14
|
|
|
|
static uchar sdl_std_cursor_mask_question_arrow[] = {
|
|
0xf8, 0x00, 0xfc, 0x01, 0xfe, 0x03, 0xff, 0x07, 0x8f, 0x07, 0x9f, 0x07, 0xde, 0x07, 0xfc, 0x03,
|
|
0xf8, 0x01, 0xf8, 0x00, 0xf8, 0x00, 0xfc, 0x01, 0xfe, 0x03, 0xfc, 0x01, 0xf8, 0x00, 0x70, 0x00,
|
|
};
|
|
static uchar sdl_std_cursor_question_arrow[] = {
|
|
0x7c, 0x00, 0xfe, 0x00, 0xc7, 0x01, 0x83, 0x01, 0x87, 0x01, 0xc6, 0x01, 0xe0, 0x00, 0x78, 0x00,
|
|
0x38, 0x00, 0x28, 0x00, 0x28, 0x00, 0xee, 0x00, 0x6c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_question_arrow 11
|
|
#define sdl_std_cursor_HEIGHT_question_arrow 16
|
|
#define sdl_std_cursor_HOT_X_question_arrow -4
|
|
#define sdl_std_cursor_HOT_Y_question_arrow -8
|
|
|
|
static uchar sdl_std_cursor_mask_pirate[] = {
|
|
0xf0, 0x03, 0xf8, 0x07, 0xfc, 0x0f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfc, 0x0f, 0xf8, 0x07, 0xf1, 0x83,
|
|
0xf1, 0xe3, 0xf3, 0xf3, 0xef, 0x39, 0x1e, 0x1e, 0xe0, 0x01, 0xfe, 0xc7, 0xff, 0xff, 0x0f, 0x7c,
|
|
};
|
|
static uchar sdl_std_cursor_pirate[] = {
|
|
0xe0, 0x01, 0xf0, 0x03, 0xf8, 0x07, 0xcc, 0x0c, 0xcc, 0x0c, 0xf8, 0x07, 0xf0, 0x03, 0xe0, 0x01,
|
|
0xe1, 0x21, 0xe1, 0x61, 0xc2, 0x10, 0x1c, 0x0e, 0xe0, 0x01, 0xf8, 0x47, 0x0f, 0x7c, 0x01, 0x20,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_pirate 16
|
|
#define sdl_std_cursor_HEIGHT_pirate 16
|
|
#define sdl_std_cursor_HOT_X_pirate -7
|
|
#define sdl_std_cursor_HOT_Y_pirate -4
|
|
|
|
static uchar sdl_std_cursor_mask_left_side[] = {
|
|
0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x03, 0x8f, 0x03, 0xcf, 0x01, 0xef, 0x00, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xef, 0x00, 0xcf, 0x01, 0x8f, 0x03, 0x0f, 0x03, 0x0f, 0x00, 0x0f, 0x00,
|
|
};
|
|
static uchar sdl_std_cursor_left_side[] = {
|
|
0x03, 0x00, 0x03, 0x00, 0x83, 0x00, 0x43, 0x00, 0x23, 0x00, 0x13, 0x00, 0xfb, 0x3f, 0x13,
|
|
0x00, 0x23, 0x00, 0x43, 0x00, 0x83, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_left_side 16
|
|
#define sdl_std_cursor_HEIGHT_left_side 15
|
|
#define sdl_std_cursor_HOT_X_left_side 0
|
|
#define sdl_std_cursor_HOT_Y_left_side -7
|
|
|
|
static uchar sdl_std_cursor_mask_left_ptr[] = {
|
|
0x03, 0x00, 0x07, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x3f, 0x00, 0x7f, 0x00, 0xff, 0x00, 0xff, 0x01,
|
|
0xff, 0x03, 0xff, 0x03, 0x7f, 0x00, 0xf7, 0x00, 0xf3, 0x00, 0xe0, 0x01, 0xe0, 0x01, 0xc0, 0x00,
|
|
};
|
|
static uchar sdl_std_cursor_left_ptr[] = {
|
|
0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x1e, 0x00, 0x3e, 0x00, 0x7e, 0x00, 0xfe, 0x00,
|
|
0xfe, 0x00, 0x3e, 0x00, 0x36, 0x00, 0x62, 0x00, 0x60, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_left_ptr 10
|
|
#define sdl_std_cursor_HEIGHT_left_ptr 16
|
|
#define sdl_std_cursor_HOT_X_left_ptr -8
|
|
#define sdl_std_cursor_HOT_Y_left_ptr -14
|
|
|
|
static uchar sdl_std_cursor_mask_crosshair[] = {
|
|
0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01,
|
|
};
|
|
static uchar sdl_std_cursor_crosshair[] = {
|
|
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x7f, 0xff,
|
|
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_crosshair 16
|
|
#define sdl_std_cursor_HEIGHT_crosshair 16
|
|
#define sdl_std_cursor_HOT_X_crosshair -7
|
|
#define sdl_std_cursor_HOT_Y_crosshair -8
|
|
|
|
static uchar sdl_std_cursor_mask_bottom_side[] = {
|
|
0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xcc, 0x19, 0xdc, 0x1d,
|
|
0xf8, 0x0f, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f,
|
|
};
|
|
static uchar sdl_std_cursor_bottom_side[] = {
|
|
0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x44, 0x04, 0x48, 0x02,
|
|
0x50, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_bottom_side 15
|
|
#define sdl_std_cursor_HEIGHT_bottom_side 16
|
|
#define sdl_std_cursor_HOT_X_bottom_side -6
|
|
#define sdl_std_cursor_HOT_Y_bottom_side -1
|
|
|
|
static uchar sdl_std_cursor_mask_bottom_right_corner[] = {
|
|
0x00, 0xf0, 0x00, 0xf0, 0x0c, 0xf7, 0x1c, 0xf7, 0x38, 0xf7, 0x70, 0xf7, 0xe0, 0xf7, 0xc0, 0xf7,
|
|
0xfc, 0xf7, 0xfc, 0xf7, 0xfc, 0xf7, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
};
|
|
static uchar sdl_std_cursor_bottom_right_corner[] = {
|
|
0x00, 0x30, 0x00, 0x30, 0x04, 0x31, 0x08, 0x31, 0x10, 0x31, 0x20, 0x31, 0x40, 0x31, 0x80, 0x31,
|
|
0xfc, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0xff, 0x3f, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_bottom_right_corner 16
|
|
#define sdl_std_cursor_HEIGHT_bottom_right_corner 16
|
|
#define sdl_std_cursor_HOT_X_bottom_right_corner -13
|
|
#define sdl_std_cursor_HOT_Y_bottom_right_corner -1
|
|
|
|
static uchar sdl_std_cursor_mask_bottom_left_corner[] = {
|
|
0x0f, 0x00, 0x0f, 0x00, 0xef, 0x30, 0xef, 0x38, 0xef, 0x1c, 0xef, 0x0e, 0xef, 0x07, 0xef, 0x03,
|
|
0xef, 0x3f, 0xef, 0x3f, 0xef, 0x3f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
};
|
|
static uchar sdl_std_cursor_bottom_left_corner[] = {
|
|
0x03, 0x00, 0x03, 0x00, 0x23, 0x08, 0x23, 0x04, 0x23, 0x02, 0x23, 0x01, 0xa3, 0x00, 0x63, 0x00,
|
|
0xe3, 0x0f, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x3f, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_bottom_left_corner 16
|
|
#define sdl_std_cursor_HEIGHT_bottom_left_corner 16
|
|
#define sdl_std_cursor_HOT_X_bottom_left_corner 0
|
|
#define sdl_std_cursor_HOT_Y_bottom_left_corner -1
|
|
|
|
static uchar sdl_std_cursor_mask_arrow[] = {
|
|
0x00, 0xe0, 0x00, 0xf8, 0x00, 0xfe, 0x80, 0x7f, 0xe0, 0x7f, 0xf8, 0x3f, 0xfc, 0x3f, 0xfc, 0x1f,
|
|
0xe0, 0x1f, 0xf0, 0x0f, 0xf8, 0x0f, 0x7c, 0x07, 0x3e, 0x07, 0x1f, 0x02, 0x0e, 0x00, 0x04, 0x00,
|
|
};
|
|
static uchar sdl_std_cursor_arrow[] = {
|
|
0x00, 0x30, 0x00, 0x3c, 0x00, 0x1f, 0xc0, 0x1f, 0xf0, 0x0f, 0xfc, 0x0f, 0xc0, 0x07, 0xe0, 0x07,
|
|
0x70, 0x03, 0x38, 0x03, 0x1c, 0x01, 0x0e, 0x01, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
};
|
|
#define sdl_std_cursor_WIDTH_arrow 16
|
|
#define sdl_std_cursor_HEIGHT_arrow 16
|
|
#define sdl_std_cursor_HOT_X_arrow -13
|
|
#define sdl_std_cursor_HOT_Y_arrow -14
|
|
/* end cursor data */
|
|
|
|
static SDL_Cursor *sdl_std_cursor_array[int(GHOST_kStandardCursorNumCursors)] = {nullptr};
|
|
|
|
/* utility function mostly a copy of SDL_CreateCursor but allows us to change
|
|
* color and supports blenders flipped bits */
|
|
static SDL_Cursor *sdl_ghost_CreateCursor(
|
|
const Uint8 *data, const Uint8 *mask, int w, int h, int hot_x, int hot_y)
|
|
{
|
|
SDL_Surface *surface;
|
|
SDL_Cursor *cursor;
|
|
int x, y;
|
|
Uint32 *pixel;
|
|
Uint8 datab = 0, maskb = 0;
|
|
const Uint32 black = 0xFF000000;
|
|
const Uint32 white = 0xFFFFFFFF;
|
|
const Uint32 transparent = 0x00000000;
|
|
|
|
/* Make sure the width is a multiple of 8 */
|
|
w = ((w + 7) & ~7);
|
|
|
|
/* Create the surface from a bitmap */
|
|
surface = SDL_CreateRGBSurface(0, w, h, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
|
|
if (!surface) {
|
|
return nullptr;
|
|
}
|
|
for (y = 0; y < h; ++y) {
|
|
pixel = (Uint32 *)((Uint8 *)surface->pixels + y * surface->pitch);
|
|
for (x = 0; x < w; ++x) {
|
|
if ((x % 8) == 0) {
|
|
datab = *data++;
|
|
maskb = *mask++;
|
|
|
|
/* reverse bit order */
|
|
datab = (datab * 0x0202020202ULL & 0x010884422010ULL) % 1023;
|
|
maskb = (maskb * 0x0202020202ULL & 0x010884422010ULL) % 1023;
|
|
}
|
|
if (maskb & 0x80) {
|
|
*pixel++ = (datab & 0x80) ? white : black;
|
|
}
|
|
else {
|
|
*pixel++ = (datab & 0x80) ? white : transparent;
|
|
}
|
|
datab <<= 1;
|
|
maskb <<= 1;
|
|
}
|
|
}
|
|
|
|
cursor = SDL_CreateColorCursor(surface, hot_x, hot_y);
|
|
|
|
SDL_FreeSurface(surface);
|
|
|
|
return cursor;
|
|
}
|
|
|
|
/* TODO: this is currently never freed but it won't leak either. */
|
|
static SDL_Cursor *getStandardCursorShape(GHOST_TStandardCursor shape)
|
|
{
|
|
if (sdl_std_cursor_array[0] == nullptr) {
|
|
#define DEF_CURSOR(name, ind) \
|
|
{ \
|
|
sdl_std_cursor_array[int(ind)] = sdl_ghost_CreateCursor( \
|
|
sdl_std_cursor_##name, \
|
|
sdl_std_cursor_mask_##name, \
|
|
sdl_std_cursor_WIDTH_##name, \
|
|
sdl_std_cursor_HEIGHT_##name, \
|
|
(sdl_std_cursor_WIDTH_##name + (sdl_std_cursor_HOT_X_##name)) - 1, \
|
|
(sdl_std_cursor_HEIGHT_##name + (sdl_std_cursor_HOT_Y_##name)) - 1); \
|
|
assert(sdl_std_cursor_array[int(ind)] != nullptr); \
|
|
} \
|
|
(void)0
|
|
|
|
DEF_CURSOR(left_ptr, GHOST_kStandardCursorDefault);
|
|
DEF_CURSOR(right_ptr, GHOST_kStandardCursorRightArrow);
|
|
DEF_CURSOR(left_ptr, GHOST_kStandardCursorLeftArrow);
|
|
DEF_CURSOR(umbrella, GHOST_kStandardCursorInfo); /* TODO: replace this one. */
|
|
DEF_CURSOR(pirate, GHOST_kStandardCursorDestroy);
|
|
DEF_CURSOR(question_arrow, GHOST_kStandardCursorHelp);
|
|
DEF_CURSOR(watch, GHOST_kStandardCursorWait);
|
|
DEF_CURSOR(xterm, GHOST_kStandardCursorText);
|
|
DEF_CURSOR(crosshair, GHOST_kStandardCursorCrosshair);
|
|
DEF_CURSOR(sb_v_double_arrow, GHOST_kStandardCursorUpDown);
|
|
DEF_CURSOR(sb_h_double_arrow, GHOST_kStandardCursorLeftRight);
|
|
DEF_CURSOR(top_side, GHOST_kStandardCursorTopSide);
|
|
DEF_CURSOR(bottom_side, GHOST_kStandardCursorBottomSide);
|
|
DEF_CURSOR(left_side, GHOST_kStandardCursorLeftSide);
|
|
DEF_CURSOR(right_side, GHOST_kStandardCursorRightSide);
|
|
DEF_CURSOR(top_left_corner, GHOST_kStandardCursorTopLeftCorner);
|
|
DEF_CURSOR(top_right_corner, GHOST_kStandardCursorTopRightCorner);
|
|
DEF_CURSOR(bottom_right_corner, GHOST_kStandardCursorBottomRightCorner);
|
|
DEF_CURSOR(bottom_left_corner, GHOST_kStandardCursorBottomLeftCorner);
|
|
DEF_CURSOR(arrow, GHOST_kStandardCursorCopy);
|
|
// DEF_CURSOR(arrow, GHOST_kStandardCursorCustom);
|
|
DEF_CURSOR(arrow, GHOST_kStandardCursorPencil);
|
|
#undef DEF_CURSOR
|
|
}
|
|
|
|
return sdl_std_cursor_array[int(shape)];
|
|
}
|
|
|
|
GHOST_TSuccess GHOST_WindowSDL::setWindowCursorGrab(GHOST_TGrabCursorMode /*mode*/)
|
|
{
|
|
return GHOST_kSuccess;
|
|
}
|
|
|
|
GHOST_TSuccess GHOST_WindowSDL::setWindowCursorShape(GHOST_TStandardCursor shape)
|
|
{
|
|
SDL_Cursor *cursor = getStandardCursorShape(shape);
|
|
if (cursor == nullptr) {
|
|
cursor = getStandardCursorShape(GHOST_kStandardCursorDefault);
|
|
}
|
|
|
|
SDL_SetCursor(cursor);
|
|
return GHOST_kSuccess;
|
|
}
|
|
|
|
GHOST_TSuccess GHOST_WindowSDL::hasCursorShape(GHOST_TStandardCursor shape)
|
|
{
|
|
return (getStandardCursorShape(shape)) ? GHOST_kSuccess : GHOST_kFailure;
|
|
}
|
|
|
|
GHOST_TSuccess GHOST_WindowSDL::setWindowCustomCursorShape(uint8_t *bitmap,
|
|
uint8_t *mask,
|
|
int sizex,
|
|
int sizey,
|
|
int hotX,
|
|
int hotY,
|
|
bool /*canInvertColor*/)
|
|
{
|
|
if (m_sdl_custom_cursor) {
|
|
SDL_FreeCursor(m_sdl_custom_cursor);
|
|
}
|
|
|
|
m_sdl_custom_cursor = sdl_ghost_CreateCursor(
|
|
(const Uint8 *)bitmap, (const Uint8 *)mask, sizex, sizey, hotX, hotY);
|
|
|
|
SDL_SetCursor(m_sdl_custom_cursor);
|
|
return GHOST_kSuccess;
|
|
}
|
|
|
|
GHOST_TSuccess GHOST_WindowSDL::setWindowCursorVisibility(bool visible)
|
|
{
|
|
SDL_ShowCursor(visible);
|
|
return GHOST_kSuccess;
|
|
}
|
|
|
|
uint16_t GHOST_WindowSDL::getDPIHint()
|
|
{
|
|
int displayIndex = SDL_GetWindowDisplayIndex(m_sdl_win);
|
|
if (displayIndex < 0) {
|
|
return 96;
|
|
}
|
|
|
|
float ddpi;
|
|
if (SDL_GetDisplayDPI(displayIndex, &ddpi, nullptr, nullptr) != 0) {
|
|
return 96;
|
|
}
|
|
|
|
return int(ddpi);
|
|
}
|