early-access version 1780

This commit is contained in:
pineappleEA
2021-06-11 20:56:03 +02:00
parent e46a402c25
commit 388881fdbb
93 changed files with 2410 additions and 851 deletions

View File

@@ -601,7 +601,7 @@ inputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer
}
/* ignore unless we're active. */
if (!SDL_AtomicGet(&this->paused) && SDL_AtomicGet(&this->enabled) && !SDL_AtomicGet(&this->paused)) {
if (!SDL_AtomicGet(&this->paused) && SDL_AtomicGet(&this->enabled)) {
const Uint8 *ptr = (const Uint8 *) inBuffer->mAudioData;
UInt32 remaining = inBuffer->mAudioDataByteSize;
while (remaining > 0) {

View File

@@ -137,7 +137,7 @@ WASAPI_AddDevice(const SDL_bool iscapture, const char *devname, WAVEFORMATEXTENS
deviceid_list = devidlist;
SDL_zero(spec);
spec.channels = fmt->Format.nChannels;
spec.channels = (Uint8)fmt->Format.nChannels;
spec.freq = fmt->Format.nSamplesPerSec;
spec.format = WaveFormatToSDLFormat((WAVEFORMATEX *) fmt);
SDL_AddAudioDevice(iscapture, devname, &spec, (void *) devid);

View File

@@ -86,7 +86,7 @@ static void DetectWave##typ##Devs(void) { \
* is not provided by the caps struct! At best, we get possible \
* sample formats, but not an _active_ format. \
*/ \
spec.channels = caps.wChannels; \
spec.channels = (Uint8)caps.wChannels; \
SDL_AddAudioDevice((int) iscapture, name, &spec, (void *) ((size_t) i+1)); \
SDL_free(name); \
} \

View File

@@ -451,9 +451,6 @@ SDL_UDEV_Poll(void)
if (action) {
if (SDL_strcmp(action, "add") == 0) {
/* Wait for the device to finish initialization */
SDL_Delay(100);
device_event(SDL_UDEV_DEVICEADDED, dev);
} else if (SDL_strcmp(action, "remove") == 0) {
device_event(SDL_UDEV_DEVICEREMOVED, dev);

View File

@@ -255,6 +255,7 @@ static struct wscons_keycode_to_SDL {
{KS_Num_Lock, SDL_SCANCODE_NUMLOCKCLEAR},
{KS_Caps_Lock, SDL_SCANCODE_CAPSLOCK},
{KS_BackSpace, SDL_SCANCODE_BACKSPACE},
{KS_space, SDL_SCANCODE_SPACE},
{KS_Delete, SDL_SCANCODE_BACKSPACE},
{KS_Home, SDL_SCANCODE_HOME},
{KS_End, SDL_SCANCODE_END},

View File

@@ -103,12 +103,12 @@ void updateMouse(SDL_WSCONS_mouse_input_data* inputData)
break;
case WSCONS_EVENT_MOUSE_DELTA_X:
{
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, events[i].value * 2, 0);
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, events[i].value, 0);
break;
}
case WSCONS_EVENT_MOUSE_DELTA_Y:
{
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, 0, -events[i].value * 2);
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, 0, -events[i].value);
break;
}
case WSCONS_EVENT_MOUSE_DELTA_W:

View File

@@ -729,15 +729,18 @@ void SDL_WinRTApp::OnExiting(Platform::Object^ sender, Platform::Object^ args)
static void
WINRT_LogPointerEvent(const char * header, Windows::UI::Core::PointerEventArgs ^ args, Windows::Foundation::Point transformedPoint)
{
Uint8 button, pressed;
Windows::UI::Input::PointerPoint ^ pt = args->CurrentPoint;
SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, SDL button=%d\n",
WINRT_GetSDLButtonForPointerPoint(pt, &button, &pressed);
SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, SDL button=%d pressed=%d\n",
header,
pt->Position.X, pt->Position.Y,
transformedPoint.X, transformedPoint.Y,
pt->Properties->MouseWheelDelta,
pt->FrameId,
pt->PointerId,
WINRT_GetSDLButtonForPointerPoint(pt));
button,
pressed);
}
void SDL_WinRTApp::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)

View File

@@ -811,3 +811,4 @@
#define SDL_GetAudioDeviceSpec SDL_GetAudioDeviceSpec_REAL
#define SDL_TLSCleanup SDL_TLSCleanup_REAL
#define SDL_SetWindowAlwaysOnTop SDL_SetWindowAlwaysOnTop_REAL
#define SDL_FlashWindow SDL_FlashWindow_REAL

View File

@@ -876,3 +876,4 @@ SDL_DYNAPI_PROC(int,SDL_AndroidShowToast,(const char *a, int b, int c, int d, in
SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceSpec,(int a, int b, SDL_AudioSpec *c),(a,b,c),return)
SDL_DYNAPI_PROC(void,SDL_TLSCleanup,(void),(),)
SDL_DYNAPI_PROC(void,SDL_SetWindowAlwaysOnTop,(SDL_Window *a, SDL_bool b),(a,b),)
SDL_DYNAPI_PROC(int,SDL_FlashWindow,(SDL_Window *a, Uint32 b),(a, b),return)

View File

@@ -586,6 +586,24 @@ SDL_CutEvent(SDL_EventEntry *entry)
SDL_AtomicAdd(&SDL_EventQ.count, -1);
}
static int
SDL_SendWakeupEvent()
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (!_this || !_this->SendWakeupEvent) {
return 0;
}
if (!_this->wakeup_lock || SDL_LockMutex(_this->wakeup_lock) == 0) {
if (_this->wakeup_window) {
_this->SendWakeupEvent(_this, _this->wakeup_window);
}
if (_this->wakeup_lock) {
SDL_UnlockMutex(_this->wakeup_lock);
}
}
return 0;
}
/* Lock the event queue, take a peep at it, and unlock it */
int
SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action,
@@ -662,6 +680,11 @@ SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action,
} else {
return SDL_SetError("Couldn't lock event queue");
}
if (used > 0 && action == SDL_ADDEVENT) {
SDL_SendWakeupEvent();
}
return (used);
}
@@ -759,6 +782,78 @@ SDL_PollEvent(SDL_Event * event)
return SDL_WaitEventTimeout(event, 0);
}
static int
SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Event * event, int timeout)
{
/* Release any keys held down from last frame */
SDL_ReleaseAutoReleaseKeys();
for (;;) {
if (!_this->wakeup_lock || SDL_LockMutex(_this->wakeup_lock) == 0) {
int status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
/* If status == 0 we are going to block so wakeup will be needed. */
if (status == 0) {
_this->wakeup_window = wakeup_window;
} else {
_this->wakeup_window = NULL;
}
if (_this->wakeup_lock) {
SDL_UnlockMutex(_this->wakeup_lock);
}
if (status < 0) {
/* Got an error: return */
break;
}
if (status > 0) {
/* There is an event, we can return. */
SDL_SendPendingSignalEvents(); /* in case we had a signal handler fire, etc. */
return 1;
}
/* No events found in the queue, call WaitEventTimeout to wait for an event. */
status = _this->WaitEventTimeout(_this, timeout);
/* Set wakeup_window to NULL without holding the lock. */
_this->wakeup_window = NULL;
if (status <= 0) {
/* There is either an error or the timeout is elapsed: return */
return status;
}
/* An event was found and pumped into the SDL events queue. Continue the loop
to let SDL_PeepEvents pick it up .*/
}
}
return 0;
}
static int
SDL_events_need_polling() {
SDL_bool need_polling = SDL_FALSE;
#if !SDL_JOYSTICK_DISABLED
need_polling = \
(!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] || SDL_JoystickEventState(SDL_QUERY)) \
&& (SDL_NumJoysticks() > 0);
#endif
#if !SDL_SENSOR_DISABLED
need_polling = need_polling || (!SDL_disabled_events[SDL_SENSORUPDATE >> 8] && \
(SDL_NumSensors() > 0));
#endif
return need_polling;
}
static SDL_Window *
SDL_find_active_window(SDL_VideoDevice * _this)
{
SDL_Window *window;
for (window = _this->windows; window; window = window->next) {
if (!window->is_destroying) {
return window;
}
}
return NULL;
}
int
SDL_WaitEvent(SDL_Event * event)
{
@@ -768,11 +863,27 @@ SDL_WaitEvent(SDL_Event * event)
int
SDL_WaitEventTimeout(SDL_Event * event, int timeout)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
SDL_Window *wakeup_window;
Uint32 expiration = 0;
if (timeout > 0)
expiration = SDL_GetTicks() + timeout;
if (timeout != 0 && _this && _this->WaitEventTimeout && _this->SendWakeupEvent && !SDL_events_need_polling()) {
/* Look if a shown window is available to send the wakeup event. */
wakeup_window = SDL_find_active_window(_this);
if (wakeup_window) {
int status = SDL_WaitEventTimeout_Device(_this, wakeup_window, event, timeout);
/* There may be implementation-defined conditions where the backend cannot
reliably wait for the next event. If that happens, fall back to polling. */
if (status >= 0) {
return status;
}
}
}
for (;;) {
SDL_PumpEvents();
switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {

View File

@@ -61,7 +61,7 @@ static BOOL CALLBACK
EnumHapticsCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
{
(void) pContext;
SDL_DINPUT_MaybeAddDevice(pdidInstance);
SDL_DINPUT_HapticMaybeAddDevice(pdidInstance);
return DIENUM_CONTINUE; /* continue enumerating */
}
@@ -117,7 +117,7 @@ SDL_DINPUT_HapticInit(void)
}
int
SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
SDL_DINPUT_HapticMaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
{
HRESULT ret;
LPDIRECTINPUTDEVICE8 device;
@@ -176,7 +176,7 @@ SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
}
int
SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
SDL_DINPUT_HapticMaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
{
SDL_hapticlist_item *item;
SDL_hapticlist_item *prev = NULL;
@@ -419,7 +419,6 @@ SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
{
HRESULT ret;
LPDIRECTINPUTDEVICE8 device;
LPDIRECTINPUTDEVICE8 device8;
/* Open the device */
ret = IDirectInput8_CreateDevice(dinput, &item->instance.guidInstance,
@@ -429,19 +428,8 @@ SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
return -1;
}
/* Now get the IDirectInputDevice8 interface, instead. */
ret = IDirectInputDevice8_QueryInterface(device,
&IID_IDirectInputDevice8,
(LPVOID *)&device8);
/* Done with the temporary one now. */
IDirectInputDevice8_Release(device);
if (FAILED(ret)) {
DI_SetError("Querying DirectInput interface", ret);
return -1;
}
if (SDL_DINPUT_HapticOpenFromDevice(haptic, device8, SDL_FALSE) < 0) {
IDirectInputDevice8_Release(device8);
if (SDL_DINPUT_HapticOpenFromDevice(haptic, device, SDL_FALSE) < 0) {
IDirectInputDevice8_Release(device);
return -1;
}
return 0;
@@ -713,7 +701,7 @@ SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
/* Specifics */
periodic->dwMagnitude = CONVERT(SDL_abs(hap_periodic->magnitude));
periodic->lOffset = CONVERT(hap_periodic->offset);
periodic->dwPhase =
periodic->dwPhase =
(hap_periodic->phase + (hap_periodic->magnitude < 0 ? 18000 : 0)) % 36000;
periodic->dwPeriod = hap_periodic->period * 1000;
dest->cbTypeSpecificParams = sizeof(DIPERIODIC);
@@ -1200,13 +1188,13 @@ SDL_DINPUT_HapticInit(void)
}
int
SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
SDL_DINPUT_HapticMaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
{
return SDL_Unsupported();
}
int
SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
SDL_DINPUT_HapticMaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
{
return SDL_Unsupported();
}

View File

@@ -25,8 +25,8 @@
extern int SDL_DINPUT_HapticInit(void);
extern int SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance);
extern int SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance);
extern int SDL_DINPUT_HapticMaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance);
extern int SDL_DINPUT_HapticMaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance);
extern int SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item);
extern int SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick);
extern int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick);

View File

@@ -50,14 +50,14 @@ SDL_XINPUT_HapticInit(void)
if (loaded_xinput) {
DWORD i;
for (i = 0; i < XUSER_MAX_COUNT; i++) {
SDL_XINPUT_MaybeAddDevice(i);
SDL_XINPUT_HapticMaybeAddDevice(i);
}
}
return 0;
}
int
SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid)
SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid)
{
const Uint8 userid = (Uint8)dwUserid;
SDL_hapticlist_item *item;
@@ -106,7 +106,7 @@ SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid)
}
int
SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid)
SDL_XINPUT_HapticMaybeRemoveDevice(const DWORD dwUserid)
{
const Uint8 userid = (Uint8)dwUserid;
SDL_hapticlist_item *item;
@@ -377,13 +377,13 @@ SDL_XINPUT_HapticInit(void)
}
int
SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid)
SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid)
{
return SDL_Unsupported();
}
int
SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid)
SDL_XINPUT_HapticMaybeRemoveDevice(const DWORD dwUserid)
{
return SDL_Unsupported();
}

View File

@@ -25,8 +25,8 @@
extern int SDL_XINPUT_HapticInit(void);
extern int SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid);
extern int SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid);
extern int SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid);
extern int SDL_XINPUT_HapticMaybeRemoveDevice(const DWORD dwUserid);
extern int SDL_XINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item);
extern int SDL_XINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick);
extern int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick);

View File

@@ -480,6 +480,7 @@ static void usb_string_cache_destroy()
usb_string_cache = NULL;
usb_string_cache_size = 0;
usb_string_cache_insert_pos = 0;
}
static struct usb_string_cache_entry *usb_string_cache_insert()
@@ -732,8 +733,12 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
if (dev_vid && dev_pid) {
string_cache = usb_string_cache_find(&desc, handle);
if (string_cache) {
cur_dev->manufacturer_string = wcsdup(string_cache->vendor);
cur_dev->product_string = wcsdup(string_cache->product);
if (string_cache->vendor) {
cur_dev->manufacturer_string = wcsdup(string_cache->vendor);
}
if (string_cache->product) {
cur_dev->product_string = wcsdup(string_cache->product);
}
}
} else {
if (desc.iManufacturer > 0)

View File

@@ -488,6 +488,15 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
continue;
}
#if defined(SDL_JOYSTICK_MFI)
// We want to prefer Game Controller support where available,
// as Apple will likely be requiring that for supported devices.
extern SDL_bool IOS_SupportedHIDDevice(IOHIDDeviceRef device);
if (IOS_SupportedHIDDevice(dev)) {
continue;
}
#endif
dev_vid = get_vendor_id(dev);
dev_pid = get_product_id(dev);

View File

@@ -526,6 +526,7 @@ static const char *s_ControllerMappings [] =
"05000000a00500003232000001000000,8BitDo Zero Gamepad,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000a00500003232000008010000,8BitDo Zero Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000a00500003232000008010000,8BitDo Zero Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000031000011010000,8Bitdo Receiver,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,",
"03000000c82d00001290000011010000,8Bitdo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00001290000011010000,8Bitdo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"05000000c82d00006228000000010000,8Bitdo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
@@ -536,6 +537,10 @@ static const char *s_ControllerMappings [] =
"030000006f0e00003901000000430000,Afterglow Prismatic Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000006f0e00001302000000010000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"03000000503200000110000000000000,Atari Classic Controller,a:b0,x:b1,back:b2,guide:b4,start:b3,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2",
"05000000503200000110000000000000,Atari Classic Controller,a:b0,x:b1,back:b2,guide:b4,start:b3,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2",
"03000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,x:b3,y:b2,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5",
"05000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,x:b3,y:b2,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5",
"05000000491900000204000021000000,Amazon Fire Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
"05000000710100001904000000010000,Amazon Luna Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
"03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
@@ -673,6 +678,7 @@ static const char *s_ControllerMappings [] =
"030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"030000004c050000da0c000011010000,Playstation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,",
"03000000c62400003a54000001010000,PowerA XBox One Controller,a:b0,b:b1,back:b6,dpdown:h0.7,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,",
"030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
@@ -767,6 +773,7 @@ static const char *s_ControllerMappings [] =
"050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,",
"030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,",
"03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,righttrigger:b7,",
#endif
#if defined(__ANDROID__)
"05000000c82d000006500000ffff3f00,8BitDo M30 Gamepad,a:b0,b:b1,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",

View File

@@ -2062,6 +2062,8 @@ static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid)
MAKE_VIDPID(0x044f, 0xb65d), /* Thrustmaster Wheel FFB */
MAKE_VIDPID(0x044f, 0xb66d), /* Thrustmaster Wheel FFB */
MAKE_VIDPID(0x044f, 0xb677), /* Thrustmaster T150 */
MAKE_VIDPID(0x044f, 0xb66e), /* Thrustmaster T300RS */
MAKE_VIDPID(0x044f, 0xb65e), /* Thrustmaster T500RS */
MAKE_VIDPID(0x044f, 0xb664), /* Thrustmaster TX (initial mode) */
MAKE_VIDPID(0x044f, 0xb669), /* Thrustmaster TX (active mode) */
};

View File

@@ -187,7 +187,7 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x045e, 0x028f ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft X-Box 360 pad v2
{ MAKE_CONTROLLER_ID( 0x045e, 0x0291 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver (XBOX)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a0 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft X-Box 360 Big Button IR
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a1 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft X-Box 360 pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a1 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft X-Box 360 Wireless Controller with XUSB driver on Windows
{ MAKE_CONTROLLER_ID( 0x045e, 0x02a9 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver (third party knockoff)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0719 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver
{ MAKE_CONTROLLER_ID( 0x046d, 0xc21d ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F310
@@ -322,11 +322,11 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x045e, 0x02e3 ), k_eControllerType_XBoxOneController, "Xbox One Elite Controller" }, // Microsoft X-Box One Elite pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x02ea ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x02fd ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x02ff ), k_eControllerType_XBoxOneController, NULL }, // Microsoft X-Box One controller with the RAWINPUT driver on Windows
{ MAKE_CONTROLLER_ID( 0x045e, 0x02ff ), k_eControllerType_XBoxOneController, NULL }, // Microsoft X-Box One controller with XBOXGIP driver on Windows
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b00 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b05 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b12 ), k_eControllerType_XBoxOneController, "Xbox One Series X Controller" }, // Microsoft X-Box One Elite Series X pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b13 ), k_eControllerType_XBoxOneController, "Xbox One Series X Controller" }, // Microsoft X-Box One Elite Series X pad (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b12 ), k_eControllerType_XBoxOneController, "Xbox One Series X Controller" }, // Microsoft X-Box One Series X pad
{ MAKE_CONTROLLER_ID( 0x045e, 0x0b13 ), k_eControllerType_XBoxOneController, "Xbox One Series X Controller" }, // Microsoft X-Box One Series X pad (Bluetooth)
{ MAKE_CONTROLLER_ID( 0x0738, 0x4a01 ), k_eControllerType_XBoxOneController, NULL }, // Mad Catz FightStick TE 2
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0139 ), k_eControllerType_XBoxOneController, "PDP Xbox One Afterglow" }, // PDP Afterglow Wired Controller for Xbox One
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x013B ), k_eControllerType_XBoxOneController, "PDP Xbox One Face-Off Controller" }, // PDP Face-Off Gamepad for Xbox One

View File

@@ -709,7 +709,7 @@ HIDAPI_DriverPS5_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick
static SDL_bool
HIDAPI_DriverPS5_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return SDL_FALSE;
return SDL_TRUE;
}
static int

View File

@@ -717,11 +717,7 @@ static Sint16 ApplyStickCalibrationCentered(SDL_DriverSwitch_Context *ctx, int n
ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue;
}
if (sRawValue > 0) {
return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_StickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16);
} else {
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0);
}
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, ctx->m_StickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16);
}
static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue)

View File

@@ -1086,12 +1086,12 @@ HIDAPI_IsEquivalentToDevice(Uint16 vendor_id, Uint16 product_id, SDL_HIDAPI_Devi
if (vendor_id == USB_VENDOR_MICROSOFT) {
/* If we're looking for the wireless XBox 360 controller, also look for the dongle */
if (product_id == 0x02a1 && device->product_id == 0x0719) {
if (product_id == USB_PRODUCT_XBOX360_XUSB_CONTROLLER && device->product_id == USB_PRODUCT_XBOX360_WIRELESS_RECEIVER) {
return SDL_TRUE;
}
/* If we're looking for the raw input Xbox One controller, match it against any other Xbox One controller */
if (product_id == USB_PRODUCT_XBOX_ONE_RAW_INPUT_CONTROLLER &&
if (product_id == USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER &&
SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == SDL_CONTROLLER_TYPE_XBOXONE) {
return SDL_TRUE;
}

View File

@@ -127,6 +127,14 @@ FixupDeviceInfoForMapping(int fd, struct input_id *inpid)
inpid->version = 0x0902;
}
}
/* For Atari vcs modern and classic controllers have the version reflecting
* firmware version, but the mapping stays stable so ignore
* version information */
if (inpid->vendor == 0x3250
&& (inpid->product == 0x1001 || inpid->product == 0x1002)) {
inpid->version = 0;
}
}
#ifdef SDL_JOYSTICK_HIDAPI

View File

@@ -51,6 +51,8 @@
#define USB_PRODUCT_SONY_DS4_DONGLE 0x0ba0
#define USB_PRODUCT_SONY_DS4_SLIM 0x09cc
#define USB_PRODUCT_SONY_DS5 0x0ce6
#define USB_PRODUCT_XBOX360_XUSB_CONTROLLER 0x02a1 /* XUSB driver software PID */
#define USB_PRODUCT_XBOX360_WIRELESS_RECEIVER 0x0719
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 0x02e3
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2 0x0b00
#define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH 0x0b05
@@ -60,7 +62,7 @@
#define USB_PRODUCT_XBOX_ONE_SERIES_X 0x0b12
#define USB_PRODUCT_XBOX_ONE_SERIES_X_BLUETOOTH 0x0b13
#define USB_PRODUCT_XBOX_ONE_SERIES_X_POWERA 0x2001
#define USB_PRODUCT_XBOX_ONE_RAW_INPUT_CONTROLLER 0x02ff
#define USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER 0x02ff /* XBOXGIP driver software PID */
#define USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER 0x02fe /* Made up product ID for XInput */
/* USB usage pages */

View File

@@ -45,8 +45,6 @@ extern HWND SDL_HelperWindow;
/* local variables */
static SDL_bool coinitialized = SDL_FALSE;
static LPDIRECTINPUT8 dinput = NULL;
static PRAWINPUTDEVICELIST SDL_RawDevList = NULL;
static UINT SDL_RawDevListCount = 0;
/* Taken from Wine - Thanks! */
static DIOBJECTDATAFORMAT dfDIJoystick2[] = {
@@ -235,210 +233,104 @@ SetDIerror(const char *function, HRESULT code)
return SDL_SetError("%s() DirectX error 0x%8.8lx", function, code);
}
#if 0 /* Microsoft recommended implementation, but slower than checking raw devices */
#define COBJMACROS
#include <wbemidl.h>
#include <oleauto.h>
static const IID CLSID_WbemLocator = { 0x4590f811, 0x1d3a, 0x11d0,{ 0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 } };
static const IID IID_IWbemLocator = { 0xdc12a687, 0x737f, 0x11cf,{ 0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 } };
static SDL_bool
WIN_IsXInputDevice(const TCHAR *name, const GUID* pGuidProductFromDirectInput)
SDL_IsXInputDevice(Uint16 vendor_id, Uint16 product_id, const char* hidPath)
{
IWbemLocator* pIWbemLocator = NULL;
IEnumWbemClassObject* pEnumDevices = NULL;
IWbemClassObject* pDevices[20];
IWbemServices* pIWbemServices = NULL;
BSTR bstrNamespace = NULL;
BSTR bstrDeviceID = NULL;
BSTR bstrClassName = NULL;
DWORD uReturned = 0;
SDL_bool bIsXinputDevice = SDL_FALSE;
UINT iDevice = 0;
VARIANT var;
HRESULT hr;
SDL_GameControllerType type;
if (!SDL_XINPUT_Enabled()) {
return SDL_FALSE;
}
if (SDL_tcsstr(name, TEXT(" XINPUT ")) != NULL) {
/* This is a duplicate interface for a controller that will show up with XInput,
e.g. Xbox One Elite Series 2 in Bluetooth mode.
*/
type = SDL_GetJoystickGameControllerType("", vendor_id, product_id, -1, 0, 0, 0);
if (type == SDL_CONTROLLER_TYPE_XBOX360 ||
type == SDL_CONTROLLER_TYPE_XBOXONE ||
(vendor_id == 0x28DE && product_id == 0x11FF)) {
return SDL_TRUE;
}
SDL_zeroa(pDevices);
// Create WMI
hr = CoCreateInstance(&CLSID_WbemLocator,
NULL,
CLSCTX_INPROC_SERVER,
&IID_IWbemLocator,
(LPVOID*)&pIWbemLocator);
if (FAILED(hr) || pIWbemLocator == NULL)
goto LCleanup;
bstrNamespace = SysAllocString(L"\\\\.\\root\\cimv2"); if (bstrNamespace == NULL) goto LCleanup;
bstrClassName = SysAllocString(L"Win32_PNPEntity"); if (bstrClassName == NULL) goto LCleanup;
bstrDeviceID = SysAllocString(L"DeviceID"); if (bstrDeviceID == NULL) goto LCleanup;
// Connect to WMI
hr = IWbemLocator_ConnectServer(pIWbemLocator, bstrNamespace, NULL, NULL, 0L,
0L, NULL, NULL, &pIWbemServices);
if (FAILED(hr) || pIWbemServices == NULL) {
goto LCleanup;
}
// Switch security level to IMPERSONATE.
CoSetProxyBlanket((IUnknown *)pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
hr = IWbemServices_CreateInstanceEnum(pIWbemServices, bstrClassName, 0, NULL, &pEnumDevices);
if (FAILED(hr) || pEnumDevices == NULL)
goto LCleanup;
// Loop over all devices
for (;;) {
// Get 20 at a time
hr = IEnumWbemClassObject_Next(pEnumDevices, 10000, SDL_arraysize(pDevices), pDevices, &uReturned);
if (FAILED(hr)) {
goto LCleanup;
}
if (uReturned == 0) {
break;
}
for (iDevice = 0; iDevice < uReturned; iDevice++) {
// For each device, get its device ID
hr = IWbemClassObject_Get(pDevices[iDevice], bstrDeviceID, 0L, &var, NULL, NULL);
if (SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL) {
// Check if the device ID contains "IG_". If it does, then it's an XInput device
// This information can not be found from DirectInput
if (SDL_wcsstr(var.bstrVal, L"IG_")) {
char *bstrVal = WIN_StringToUTF8W(var.bstrVal);
// If it does, then get the VID/PID from var.bstrVal
DWORD dwPid = 0, dwVid = 0, dwVidPid;
const char *strVid, *strPid;
strVid = SDL_strstr(bstrVal, "VID_");
if (strVid && SDL_sscanf(strVid, "VID_%4X", &dwVid) != 1)
dwVid = 0;
strPid = SDL_strstr(bstrVal, "PID_");
if (strPid && SDL_sscanf(strPid, "PID_%4X", &dwPid) != 1)
dwPid = 0;
SDL_free(bstrVal);
// Compare the VID/PID to the DInput device
dwVidPid = MAKELONG(dwVid, dwPid);
if (dwVidPid == pGuidProductFromDirectInput->Data1) {
bIsXinputDevice = SDL_TRUE;
goto LCleanup;
}
}
}
IWbemClassObject_Release(pDevices[iDevice]);
}
}
LCleanup:
if (bstrNamespace) {
SysFreeString(bstrNamespace);
}
if (bstrDeviceID) {
SysFreeString(bstrDeviceID);
}
if (bstrClassName) {
SysFreeString(bstrClassName);
}
for (iDevice = 0; iDevice < SDL_arraysize(pDevices); iDevice++) {
if (pDevices[iDevice]) {
IWbemClassObject_Release(pDevices[iDevice]);
}
}
if (pEnumDevices) {
IEnumWbemClassObject_Release(pEnumDevices);
}
if (pIWbemLocator) {
IWbemLocator_Release(pIWbemLocator);
}
if (pIWbemServices) {
IWbemServices_Release(pIWbemServices);
}
return bIsXinputDevice;
}
#endif /* 0 */
static SDL_bool
SDL_IsXInputDevice(const TCHAR *name, const GUID* pGuidProductFromDirectInput)
{
UINT i;
if (!SDL_XINPUT_Enabled()) {
return SDL_FALSE;
}
if (SDL_tcsstr(name, TEXT(" XINPUT ")) != NULL) {
/* This is a duplicate interface for a controller that will show up with XInput,
e.g. Xbox One Elite Series 2 in Bluetooth mode.
*/
/* If device path contains "IG_" then its an XInput device */
/* See: https://docs.microsoft.com/windows/win32/xinput/xinput-and-directinput */
if (SDL_strstr(hidPath, "IG_") != NULL) {
return SDL_TRUE;
}
if (SDL_memcmp(&pGuidProductFromDirectInput->Data4[2], "PIDVID", 6) == 0) {
Uint16 vendor_id = (Uint16)LOWORD(pGuidProductFromDirectInput->Data1);
Uint16 product_id = (Uint16)HIWORD(pGuidProductFromDirectInput->Data1);
SDL_GameControllerType type = SDL_GetJoystickGameControllerType("", vendor_id, product_id, -1, 0, 0, 0);
if (type == SDL_CONTROLLER_TYPE_XBOX360 ||
type == SDL_CONTROLLER_TYPE_XBOXONE ||
(vendor_id == 0x28DE && product_id == 0x11FF)) {
return SDL_TRUE;
}
}
/* Go through RAWINPUT (WinXP and later) to find HID devices. */
/* Cache this if we end up using it. */
if (SDL_RawDevList == NULL) {
if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) {
return SDL_FALSE; /* oh well. */
}
SDL_RawDevList = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * SDL_RawDevListCount);
if (SDL_RawDevList == NULL) {
SDL_OutOfMemory();
return SDL_FALSE;
}
if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) {
SDL_free(SDL_RawDevList);
SDL_RawDevList = NULL;
return SDL_FALSE; /* oh well. */
}
}
for (i = 0; i < SDL_RawDevListCount; i++) {
RID_DEVICE_INFO rdi;
char devName[MAX_PATH];
UINT rdiSize = sizeof(rdi);
UINT nameSize = SDL_arraysize(devName);
rdi.cbSize = sizeof(rdi);
if ((SDL_RawDevList[i].dwType == RIM_TYPEHID) &&
(GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
(MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) &&
(GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
(SDL_strstr(devName, "IG_") != NULL)) {
return SDL_TRUE;
}
}
return SDL_FALSE;
}
static SDL_bool
QueryDeviceName(LPDIRECTINPUTDEVICE8 device, char** device_name)
{
DIPROPSTRING dipstr;
if (!device || !device_name) {
return SDL_FALSE;
}
dipstr.diph.dwSize = sizeof(dipstr);
dipstr.diph.dwHeaderSize = sizeof(dipstr.diph);
dipstr.diph.dwObj = 0;
dipstr.diph.dwHow = DIPH_DEVICE;
if (FAILED(IDirectInputDevice8_GetProperty(device, DIPROP_PRODUCTNAME, &dipstr.diph))) {
return SDL_FALSE;
}
*device_name = WIN_StringToUTF8(dipstr.wsz);
return SDL_TRUE;
}
static SDL_bool
QueryDevicePath(LPDIRECTINPUTDEVICE8 device, char** device_path)
{
DIPROPGUIDANDPATH dippath;
if (!device || !device_path) {
return SDL_FALSE;
}
dippath.diph.dwSize = sizeof(dippath);
dippath.diph.dwHeaderSize = sizeof(dippath.diph);
dippath.diph.dwObj = 0;
dippath.diph.dwHow = DIPH_DEVICE;
if (FAILED(IDirectInputDevice8_GetProperty(device, DIPROP_GUIDANDPATH, &dippath.diph))) {
return SDL_FALSE;
}
*device_path = WIN_StringToUTF8W(dippath.wszPath);
/* Normalize path to upper case. */
SDL_strupr(*device_path);
return SDL_TRUE;
}
static SDL_bool
QueryDeviceInfo(LPDIRECTINPUTDEVICE8 device, Uint16* vendor_id, Uint16* product_id)
{
DIPROPDWORD dipdw;
if (!device || !vendor_id || !product_id) {
return SDL_FALSE;
}
dipdw.diph.dwSize = sizeof(dipdw);
dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
if (FAILED(IDirectInputDevice8_GetProperty(device, DIPROP_VIDPID, &dipdw.diph))) {
return SDL_FALSE;
}
*vendor_id = LOWORD(dipdw.dwData);
*product_id = HIWORD(dipdw.dwData);
return SDL_TRUE;
}
void FreeRumbleEffectData(DIEFFECT *effect)
{
if (!effect) {
@@ -533,88 +425,49 @@ SDL_DINPUT_JoystickInit(void)
/* helper function for direct input, gets called for each connected joystick */
static BOOL CALLBACK
EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
EnumJoysticksCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext)
{
JoyStick_DeviceData *pNewJoystick;
#define CHECK(exp) { if(!(exp)) goto err; }
JoyStick_DeviceData *pNewJoystick = NULL;
JoyStick_DeviceData *pPrevJoystick = NULL;
const DWORD devtype = (pdidInstance->dwDevType & 0xFF);
Uint16 *guid16;
Uint16 vendor = 0;
Uint16 product = 0;
Uint16 version = 0;
WCHAR hidPath[MAX_PATH];
char *name;
char *hidPath = NULL;
char *name = NULL;
LPDIRECTINPUTDEVICE8 device = NULL;
if (devtype == DI8DEVTYPE_SUPPLEMENTAL) {
/* Add any supplemental devices that should be ignored here */
#define MAKE_TABLE_ENTRY(VID, PID) ((((DWORD)PID)<<16)|VID)
static DWORD ignored_devices[] = {
MAKE_TABLE_ENTRY(0, 0)
};
#undef MAKE_TABLE_ENTRY
unsigned int i;
/* We are only supporting HID devices. */
CHECK((pDeviceInstance->dwDevType & DIDEVTYPE_HID) != 0);
for (i = 0; i < SDL_arraysize(ignored_devices); ++i) {
if (pdidInstance->guidProduct.Data1 == ignored_devices[i]) {
return DIENUM_CONTINUE;
}
}
}
CHECK(SUCCEEDED(IDirectInput8_CreateDevice(dinput, &pDeviceInstance->guidInstance, &device, NULL)));
CHECK(QueryDeviceName(device, &name));
CHECK(QueryDevicePath(device, &hidPath));
CHECK(QueryDeviceInfo(device, &vendor, &product));
if (SDL_IsXInputDevice(pdidInstance->tszProductName, &pdidInstance->guidProduct)) {
return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */
}
CHECK(!SDL_IsXInputDevice(vendor, product, hidPath));
{
HRESULT result;
LPDIRECTINPUTDEVICE8 device;
LPDIRECTINPUTDEVICE8 InputDevice;
DIPROPGUIDANDPATH dipdw2;
result = IDirectInput8_CreateDevice(dinput, &(pdidInstance->guidInstance), &device, NULL);
if (FAILED(result)) {
return DIENUM_CONTINUE; /* better luck next time? */
}
/* Now get the IDirectInputDevice8 interface, instead. */
result = IDirectInputDevice8_QueryInterface(device, &IID_IDirectInputDevice8, (LPVOID *)&InputDevice);
/* We are done with this object. Use the stored one from now on. */
IDirectInputDevice8_Release(device);
if (FAILED(result)) {
return DIENUM_CONTINUE; /* better luck next time? */
}
dipdw2.diph.dwSize = sizeof(dipdw2);
dipdw2.diph.dwHeaderSize = sizeof(dipdw2.diph);
dipdw2.diph.dwObj = 0; // device property
dipdw2.diph.dwHow = DIPH_DEVICE;
result = IDirectInputDevice8_GetProperty(InputDevice, DIPROP_GUIDANDPATH, &dipdw2.diph);
IDirectInputDevice8_Release(InputDevice);
if (FAILED(result)) {
return DIENUM_CONTINUE; /* better luck next time? */
}
/* Get device path, compare that instead of GUID, additionally update GUIDs of joysticks with matching paths, in case they're not open yet. */
SDL_wcslcpy(hidPath, dipdw2.wszPath, SDL_arraysize(hidPath));
}
pNewJoystick = *(JoyStick_DeviceData **)pContext;
pNewJoystick = *(JoyStick_DeviceData**)pContext;
while (pNewJoystick) {
if (SDL_wcscmp(pNewJoystick->hidPath, hidPath) == 0) {
/* update GUIDs of joysticks with matching paths, in case they're not open yet */
if (SDL_strcmp(pNewJoystick->hidPath, hidPath) == 0) {
/* if we are replacing the front of the list then update it */
if (pNewJoystick == *(JoyStick_DeviceData **)pContext) {
*(JoyStick_DeviceData **)pContext = pNewJoystick->pNext;
} else if (pPrevJoystick) {
if (pNewJoystick == *(JoyStick_DeviceData**)pContext) {
*(JoyStick_DeviceData**)pContext = pNewJoystick->pNext;
}
else if (pPrevJoystick) {
pPrevJoystick->pNext = pNewJoystick->pNext;
}
/* Update with new guid/etc, if it has changed */
SDL_memcpy(&pNewJoystick->dxdevice, pdidInstance, sizeof(DIDEVICEINSTANCE));
SDL_memcpy(&pNewJoystick->dxdevice, pDeviceInstance, sizeof(DIDEVICEINSTANCE));
pNewJoystick->pNext = SYS_Joystick;
SYS_Joystick = pNewJoystick;
return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */
pNewJoystick = NULL;
CHECK(FALSE);
}
pPrevJoystick = pNewJoystick;
@@ -622,31 +475,18 @@ EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
}
pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
if (!pNewJoystick) {
return DIENUM_CONTINUE; /* better luck next time? */
}
CHECK(pNewJoystick);
SDL_zerop(pNewJoystick);
SDL_wcslcpy(pNewJoystick->hidPath, hidPath, SDL_arraysize(pNewJoystick->hidPath));
SDL_memcpy(&pNewJoystick->dxdevice, pdidInstance, sizeof(DIDEVICEINSTANCE));
SDL_strlcpy(pNewJoystick->hidPath, hidPath, SDL_arraysize(pNewJoystick->hidPath));
SDL_memcpy(&pNewJoystick->dxdevice, pDeviceInstance, sizeof(DIDEVICEINSTANCE));
SDL_memset(pNewJoystick->guid.data, 0, sizeof(pNewJoystick->guid.data));
if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) {
vendor = (Uint16)LOWORD(pdidInstance->guidProduct.Data1);
product = (Uint16)HIWORD(pdidInstance->guidProduct.Data1);
}
name = WIN_StringToUTF8(pdidInstance->tszProductName);
pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, name);
SDL_free(name);
if (!pNewJoystick->joystickname) {
SDL_free(pNewJoystick);
return DIENUM_CONTINUE; /* better luck next time? */
}
CHECK(pNewJoystick->joystickname);
guid16 = (Uint16 *)pNewJoystick->guid.data;
if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) {
if (vendor && product) {
*guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB);
*guid16++ = 0;
*guid16++ = SDL_SwapLE16(vendor);
@@ -661,127 +501,102 @@ EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
SDL_strlcpy((char*)guid16, pNewJoystick->joystickname, sizeof(pNewJoystick->guid.data) - 4);
}
if (SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)) {
SDL_free(pNewJoystick->joystickname);
SDL_free(pNewJoystick);
return DIENUM_CONTINUE;
}
CHECK(!SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid));
#ifdef SDL_JOYSTICK_HIDAPI
if (HIDAPI_IsDevicePresent(vendor, product, 0, pNewJoystick->joystickname)) {
/* The HIDAPI driver is taking care of this device */
SDL_free(pNewJoystick->joystickname);
SDL_free(pNewJoystick);
return DIENUM_CONTINUE;
}
CHECK(!HIDAPI_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname));
#endif
#ifdef SDL_JOYSTICK_RAWINPUT
if (RAWINPUT_IsDevicePresent(vendor, product, 0, pNewJoystick->joystickname)) {
/* The RAWINPUT driver is taking care of this device */
SDL_free(pNewJoystick);
return DIENUM_CONTINUE;
}
CHECK(!RAWINPUT_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname));
#endif
WINDOWS_AddJoystickDevice(pNewJoystick);
pNewJoystick = NULL;
err:
if (pNewJoystick) {
SDL_free(pNewJoystick->joystickname);
SDL_free(pNewJoystick);
}
SDL_free(hidPath);
SDL_free(name);
if (device) {
IDirectInputDevice8_Release(device);
}
return DIENUM_CONTINUE; /* get next device, please */
#undef CHECK
}
void
SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
{
IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, pContext, DIEDFL_ATTACHEDONLY);
if (SDL_RawDevList) {
SDL_free(SDL_RawDevList); /* in case we used this in DirectInput detection */
SDL_RawDevList = NULL;
}
SDL_RawDevListCount = 0;
}
typedef struct
SDL_bool
SDL_DINPUT_JoystickPresent(Uint16 vendor_id, Uint16 product_id, Uint16 version_number)
{
Uint16 vendor;
Uint16 product;
Uint16 version;
SDL_bool present;
} EnumJoystickPresentData;
static BOOL CALLBACK
EnumJoystickPresentCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
{
EnumJoystickPresentData *data = (EnumJoystickPresentData *)pContext;
JoyStick_DeviceData* joystick = SYS_Joystick;
Uint16 vendor = 0;
Uint16 product = 0;
Uint16 version = 0;
if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) {
vendor = (Uint16)LOWORD(pdidInstance->guidProduct.Data1);
product = (Uint16)HIWORD(pdidInstance->guidProduct.Data1);
if (data->vendor == vendor && data->product == product && data->version == version) {
data->present = SDL_TRUE;
return DIENUM_STOP;
while (joystick) {
SDL_GetJoystickGUIDInfo(joystick->guid, &vendor, &product, &version);
if (!joystick->bXInputDevice &&
vendor == vendor_id &&
product == product_id &&
version == version_number) {
return SDL_TRUE;
}
}
return DIENUM_CONTINUE;
}
SDL_bool
SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version)
{
EnumJoystickPresentData data;
if (dinput == NULL) {
return SDL_FALSE;
joystick = joystick->pNext;
}
data.vendor = vendor;
data.product = product;
data.version = version;
data.present = SDL_FALSE;
IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoystickPresentCallback, &data, DIEDFL_ATTACHEDONLY);
return data.present;
return SDL_FALSE;
}
static BOOL CALLBACK
EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE pDeviceObject, LPVOID pContext)
{
SDL_Joystick *joystick = (SDL_Joystick *)pvRef;
SDL_Joystick *joystick = (SDL_Joystick *)pContext;
HRESULT result;
input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
if (dev->dwType & DIDFT_BUTTON) {
if (pDeviceObject->dwType & DIDFT_BUTTON) {
in->type = BUTTON;
in->num = joystick->nbuttons;
in->ofs = DIJOFS_BUTTON(in->num);
joystick->nbuttons++;
} else if (dev->dwType & DIDFT_POV) {
} else if (pDeviceObject->dwType & DIDFT_POV) {
in->type = HAT;
in->num = joystick->nhats;
in->ofs = DIJOFS_POV(in->num);
joystick->nhats++;
} else if (dev->dwType & DIDFT_AXIS) {
} else if (pDeviceObject->dwType & DIDFT_AXIS) {
DIPROPRANGE diprg;
DIPROPDWORD dilong;
in->type = AXIS;
in->num = joystick->naxes;
if (!SDL_memcmp(&dev->guidType, &GUID_XAxis, sizeof(dev->guidType)))
if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_XAxis, sizeof(pDeviceObject->guidType)))
in->ofs = DIJOFS_X;
else if (!SDL_memcmp(&dev->guidType, &GUID_YAxis, sizeof(dev->guidType)))
else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_YAxis, sizeof(pDeviceObject->guidType)))
in->ofs = DIJOFS_Y;
else if (!SDL_memcmp(&dev->guidType, &GUID_ZAxis, sizeof(dev->guidType)))
else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_ZAxis, sizeof(pDeviceObject->guidType)))
in->ofs = DIJOFS_Z;
else if (!SDL_memcmp(&dev->guidType, &GUID_RxAxis, sizeof(dev->guidType)))
else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_RxAxis, sizeof(pDeviceObject->guidType)))
in->ofs = DIJOFS_RX;
else if (!SDL_memcmp(&dev->guidType, &GUID_RyAxis, sizeof(dev->guidType)))
else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_RyAxis, sizeof(pDeviceObject->guidType)))
in->ofs = DIJOFS_RY;
else if (!SDL_memcmp(&dev->guidType, &GUID_RzAxis, sizeof(dev->guidType)))
else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_RzAxis, sizeof(pDeviceObject->guidType)))
in->ofs = DIJOFS_RZ;
else if (!SDL_memcmp(&dev->guidType, &GUID_Slider, sizeof(dev->guidType))) {
else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_Slider, sizeof(pDeviceObject->guidType))) {
in->ofs = DIJOFS_SLIDER(joystick->hwdata->NumSliders);
++joystick->hwdata->NumSliders;
} else {
@@ -790,7 +605,7 @@ EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
diprg.diph.dwSize = sizeof(diprg);
diprg.diph.dwHeaderSize = sizeof(diprg.diph);
diprg.diph.dwObj = dev->dwType;
diprg.diph.dwObj = pDeviceObject->dwType;
diprg.diph.dwHow = DIPH_BYID;
diprg.lMin = SDL_JOYSTICK_AXIS_MIN;
diprg.lMax = SDL_JOYSTICK_AXIS_MAX;
@@ -805,7 +620,7 @@ EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
/* Set dead zone to 0. */
dilong.diph.dwSize = sizeof(dilong);
dilong.diph.dwHeaderSize = sizeof(dilong.diph);
dilong.diph.dwObj = dev->dwType;
dilong.diph.dwObj = pDeviceObject->dwType;
dilong.diph.dwHow = DIPH_BYID;
dilong.dwData = 0;
result =
@@ -882,7 +697,6 @@ int
SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
{
HRESULT result;
LPDIRECTINPUTDEVICE8 device;
DIPROPDWORD dipdw;
joystick->hwdata->buffered = SDL_TRUE;
@@ -894,23 +708,13 @@ SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickde
result =
IDirectInput8_CreateDevice(dinput,
&(joystickdevice->dxdevice.guidInstance), &device, NULL);
&joystickdevice->dxdevice.guidInstance,
&joystick->hwdata->InputDevice,
NULL);
if (FAILED(result)) {
return SetDIerror("IDirectInput::CreateDevice", result);
}
/* Now get the IDirectInputDevice8 interface, instead. */
result = IDirectInputDevice8_QueryInterface(device,
&IID_IDirectInputDevice8,
(LPVOID *)& joystick->
hwdata->InputDevice);
/* We are done with this object. Use the stored one from now on. */
IDirectInputDevice8_Release(device);
if (FAILED(result)) {
return SetDIerror("IDirectInputDevice8::QueryInterface", result);
}
/* Acquire shared access. Exclusive access is required for forces,
* though. */
result =

View File

@@ -891,7 +891,7 @@ RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, co
/* The Xbox One controller shows up as a hardcoded raw input VID/PID */
if (name && SDL_strcmp(name, "Xbox One Game Controller") == 0 &&
device->vendor_id == USB_VENDOR_MICROSOFT &&
device->product_id == USB_PRODUCT_XBOX_ONE_RAW_INPUT_CONTROLLER) {
device->product_id == USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER) {
return SDL_TRUE;
}

View File

@@ -429,11 +429,11 @@ WINDOWS_JoystickDetect(void)
if (pCurList->bXInputDevice) {
#if SDL_HAPTIC_XINPUT
SDL_XINPUT_MaybeRemoveDevice(pCurList->XInputUserId);
SDL_XINPUT_HapticMaybeRemoveDevice(pCurList->XInputUserId);
#endif
} else {
#if SDL_HAPTIC_DINPUT
SDL_DINPUT_MaybeRemoveDevice(&pCurList->dxdevice);
SDL_DINPUT_HapticMaybeRemoveDevice(&pCurList->dxdevice);
#endif
}
@@ -449,11 +449,11 @@ WINDOWS_JoystickDetect(void)
if (pCurList->send_add_event) {
if (pCurList->bXInputDevice) {
#if SDL_HAPTIC_XINPUT
SDL_XINPUT_MaybeAddDevice(pCurList->XInputUserId);
SDL_XINPUT_HapticMaybeAddDevice(pCurList->XInputUserId);
#endif
} else {
#if SDL_HAPTIC_DINPUT
SDL_DINPUT_MaybeAddDevice(&pCurList->dxdevice);
SDL_DINPUT_HapticMaybeAddDevice(&pCurList->dxdevice);
#endif
}

View File

@@ -37,7 +37,7 @@ typedef struct JoyStick_DeviceData
BYTE SubType;
Uint8 XInputUserId;
DIDEVICEINSTANCE dxdevice;
WCHAR hidPath[MAX_PATH];
char hidPath[MAX_PATH];
struct JoyStick_DeviceData *pNext;
} JoyStick_DeviceData;

View File

@@ -629,6 +629,170 @@ SDLTest_CommonDefaultArgs(SDLTest_CommonState *state, const int argc, char **arg
return SDL_TRUE;
}
static void
SDLTest_PrintDisplayOrientation(char* text, size_t maxlen, SDL_DisplayOrientation orientation)
{
switch (orientation) {
case SDL_ORIENTATION_UNKNOWN:
SDL_snprintfcat(text, maxlen, "UNKNOWN");
break;
case SDL_ORIENTATION_LANDSCAPE:
SDL_snprintfcat(text, maxlen, "LANDSCAPE");
break;
case SDL_ORIENTATION_LANDSCAPE_FLIPPED:
SDL_snprintfcat(text, maxlen, "LANDSCAPE_FLIPPED");
break;
case SDL_ORIENTATION_PORTRAIT:
SDL_snprintfcat(text, maxlen, "PORTRAIT");
break;
case SDL_ORIENTATION_PORTRAIT_FLIPPED:
SDL_snprintfcat(text, maxlen, "PORTRAIT_FLIPPED");
break;
default:
SDL_snprintfcat(text, maxlen, "0x%8.8x", orientation);
break;
}
}
static void
SDLTest_PrintWindowFlag(char* text, size_t maxlen, Uint32 flag)
{
switch (flag) {
case SDL_WINDOW_FULLSCREEN:
SDL_snprintfcat(text, maxlen, "FULLSCREEN");
break;
case SDL_WINDOW_OPENGL:
SDL_snprintfcat(text, maxlen, "OPENGL");
break;
case SDL_WINDOW_SHOWN:
SDL_snprintfcat(text, maxlen, "SHOWN");
break;
case SDL_WINDOW_HIDDEN:
SDL_snprintfcat(text, maxlen, "HIDDEN");
break;
case SDL_WINDOW_BORDERLESS:
SDL_snprintfcat(text, maxlen, "BORDERLESS");
break;
case SDL_WINDOW_RESIZABLE:
SDL_snprintfcat(text, maxlen, "RESIZABLE");
break;
case SDL_WINDOW_MINIMIZED:
SDL_snprintfcat(text, maxlen, "MINIMIZED");
break;
case SDL_WINDOW_MAXIMIZED:
SDL_snprintfcat(text, maxlen, "MAXIMIZED");
break;
case SDL_WINDOW_MOUSE_GRABBED:
SDL_snprintfcat(text, maxlen, "MOUSE_GRABBED");
break;
case SDL_WINDOW_INPUT_FOCUS:
SDL_snprintfcat(text, maxlen, "INPUT_FOCUS");
break;
case SDL_WINDOW_MOUSE_FOCUS:
SDL_snprintfcat(text, maxlen, "MOUSE_FOCUS");
break;
case SDL_WINDOW_FULLSCREEN_DESKTOP:
SDL_snprintfcat(text, maxlen, "FULLSCREEN_DESKTOP");
break;
case SDL_WINDOW_FOREIGN:
SDL_snprintfcat(text, maxlen, "FOREIGN");
break;
case SDL_WINDOW_ALLOW_HIGHDPI:
SDL_snprintfcat(text, maxlen, "ALLOW_HIGHDPI");
break;
case SDL_WINDOW_MOUSE_CAPTURE:
SDL_snprintfcat(text, maxlen, "MOUSE_CAPTURE");
break;
case SDL_WINDOW_ALWAYS_ON_TOP:
SDL_snprintfcat(text, maxlen, "ALWAYS_ON_TOP");
break;
case SDL_WINDOW_SKIP_TASKBAR:
SDL_snprintfcat(text, maxlen, "SKIP_TASKBAR");
break;
case SDL_WINDOW_UTILITY:
SDL_snprintfcat(text, maxlen, "UTILITY");
break;
case SDL_WINDOW_TOOLTIP:
SDL_snprintfcat(text, maxlen, "TOOLTIP");
break;
case SDL_WINDOW_POPUP_MENU:
SDL_snprintfcat(text, maxlen, "POPUP_MENU");
break;
case SDL_WINDOW_KEYBOARD_GRABBED:
SDL_snprintfcat(text, maxlen, "KEYBOARD_GRABBED");
break;
case SDL_WINDOW_VULKAN:
SDL_snprintfcat(text, maxlen, "VULKAN");
break;
case SDL_WINDOW_METAL:
SDL_snprintfcat(text, maxlen, "METAL");
break;
default:
SDL_snprintfcat(text, maxlen, "0x%8.8x", flag);
break;
}
}
static void
SDLTest_PrintWindowFlags(char* text, size_t maxlen, Uint32 flags)
{
const Uint32 window_flags[] = {
SDL_WINDOW_FULLSCREEN,
SDL_WINDOW_OPENGL,
SDL_WINDOW_SHOWN,
SDL_WINDOW_HIDDEN,
SDL_WINDOW_BORDERLESS,
SDL_WINDOW_RESIZABLE,
SDL_WINDOW_MINIMIZED,
SDL_WINDOW_MAXIMIZED,
SDL_WINDOW_MOUSE_GRABBED,
SDL_WINDOW_INPUT_FOCUS,
SDL_WINDOW_MOUSE_FOCUS,
SDL_WINDOW_FULLSCREEN_DESKTOP,
SDL_WINDOW_FOREIGN,
SDL_WINDOW_ALLOW_HIGHDPI,
SDL_WINDOW_MOUSE_CAPTURE,
SDL_WINDOW_ALWAYS_ON_TOP,
SDL_WINDOW_SKIP_TASKBAR,
SDL_WINDOW_UTILITY,
SDL_WINDOW_TOOLTIP,
SDL_WINDOW_POPUP_MENU,
SDL_WINDOW_KEYBOARD_GRABBED,
SDL_WINDOW_VULKAN,
SDL_WINDOW_METAL
};
int i;
int count = 0;
for (i = 0; i < (sizeof(window_flags) / sizeof(window_flags[0])); ++i) {
const Uint32 flag = window_flags[i];
if ((flags & flag) == flag) {
if (count > 0) {
SDL_snprintfcat(text, maxlen, " | ");
}
SDLTest_PrintWindowFlag(text, maxlen, flag);
++count;
}
}
}
static void
SDLTest_PrintButtonMask(char* text, size_t maxlen, Uint32 flags)
{
int i;
int count = 0;
for (i = 1; i <= 32; ++i) {
const Uint32 flag = SDL_BUTTON(i);
if ((flags & flag) == flag) {
if (count > 0) {
SDL_snprintfcat(text, maxlen, " | ");
}
SDL_snprintfcat(text, maxlen, "SDL_BUTTON(%d)", i);
++count;
}
}
}
static void
SDLTest_PrintRendererFlag(char *text, size_t maxlen, Uint32 flag)
{
@@ -1990,4 +2154,115 @@ SDLTest_CommonQuit(SDLTest_CommonState * state)
SDLTest_LogAllocations();
}
void
SDLTest_CommonDrawWindowInfo(SDL_Renderer * renderer, SDL_Window * window)
{
char text[1024];
int textY = 0;
const int lineHeight = 10;
int x, y, w, h;
SDL_Rect rect;
SDL_DisplayMode mode;
float ddpi, hdpi, vdpi;
Uint32 flags;
const int windowDisplayIndex = SDL_GetWindowDisplayIndex(window);
/* Renderer */
if (0 == SDL_GetRendererOutputSize(renderer, &w, &h)) {
SDL_snprintf(text, sizeof(text), "SDL_GetRendererOutputSize: %dx%d", w, h);
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
}
SDL_RenderGetViewport(renderer, &rect);
SDL_snprintf(text, sizeof(text), "SDL_RenderGetViewport: %d,%d, %dx%d",
rect.x, rect.y, rect.w, rect.h);
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
/* Window */
SDLTest_DrawString(renderer, 0, textY, "----");
textY += lineHeight;
SDL_GetWindowPosition(window, &x, &y);
SDL_snprintf(text, sizeof(text), "SDL_GetWindowPosition: %d,%d", x, y);
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
SDL_GetWindowSize(window, &w, &h);
SDL_snprintf(text, sizeof(text), "SDL_GetWindowSize: %dx%d", w, h);
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
SDL_snprintf(text, sizeof(text), "SDL_GetWindowFlags: ");
SDLTest_PrintWindowFlags(text, sizeof(text), SDL_GetWindowFlags(window));
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
/* Display */
SDLTest_DrawString(renderer, 0, textY, "----");
textY += lineHeight;
SDL_snprintf(text, sizeof(text), "SDL_GetWindowDisplayIndex: %d", windowDisplayIndex);
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
SDL_snprintf(text, sizeof(text), "SDL_GetDisplayName: %s", SDL_GetDisplayName(windowDisplayIndex));
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
if (0 == SDL_GetDisplayBounds(windowDisplayIndex, &rect)) {
SDL_snprintf(text, sizeof(text), "SDL_GetDisplayBounds: %d,%d, %dx%d",
rect.x, rect.y, rect.w, rect.h);
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
}
if (0 == SDL_GetCurrentDisplayMode(windowDisplayIndex, &mode)) {
SDL_snprintf(text, sizeof(text), "SDL_GetCurrentDisplayMode: %dx%d@%d",
mode.w, mode.h, mode.refresh_rate);
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
}
if (0 == SDL_GetDesktopDisplayMode(windowDisplayIndex, &mode)) {
SDL_snprintf(text, sizeof(text), "SDL_GetDesktopDisplayMode: %dx%d@%d",
mode.w, mode.h, mode.refresh_rate);
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
}
if (0 == SDL_GetDisplayDPI(windowDisplayIndex, &ddpi, &hdpi, &vdpi)) {
SDL_snprintf(text, sizeof(text), "SDL_GetDisplayDPI: ddpi: %f, hdpi: %f, vdpi: %f",
ddpi, hdpi, vdpi);
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
}
SDL_snprintf(text, sizeof(text), "SDL_GetDisplayOrientation: ");
SDLTest_PrintDisplayOrientation(text, sizeof(text), SDL_GetDisplayOrientation(windowDisplayIndex));
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
/* Mouse */
SDLTest_DrawString(renderer, 0, textY, "----");
textY += lineHeight;
flags = SDL_GetMouseState(&x, &y);
SDL_snprintf(text, sizeof(text), "SDL_GetMouseState: %d,%d ", x, y);
SDLTest_PrintButtonMask(text, sizeof(text), flags);
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
flags = SDL_GetGlobalMouseState(&x, &y);
SDL_snprintf(text, sizeof(text), "SDL_GetGlobalMouseState: %d,%d ", x, y);
SDLTest_PrintButtonMask(text, sizeof(text), flags);
SDLTest_DrawString(renderer, 0, textY, text);
textY += lineHeight;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -407,14 +407,20 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
goto done;
}
/*
| guich: always use 1<<bpp b/c some bitmaps can bring wrong information
| for colorsUsed
*/
/* if (biClrUsed == 0) { */
biClrUsed = 1 << biBitCount;
/* } */
if (biSize == 12) {
if (biClrUsed == 0) {
biClrUsed = 1 << biBitCount;
}
if (biClrUsed > palette->ncolors) {
biClrUsed = 1 << biBitCount; /* try forcing it? */
if (biClrUsed > palette->ncolors) {
SDL_SetError("Unsupported or incorrect biClrUsed field");
was_error = SDL_TRUE;
goto done;
}
}
if (biSize == 12) {
for (i = 0; i < (int) biClrUsed; ++i) {
SDL_RWread(src, &palette->colors[i].b, 1, 1);
SDL_RWread(src, &palette->colors[i].g, 1, 1);

View File

@@ -1089,7 +1089,16 @@ SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context)
if (!_this->egl_data) {
return SDL_SetError("OpenGL not initialized");
}
if (!_this->egl_data->eglMakeCurrent) {
if (!egl_surface && !context) {
/* Can't do the nothing there is to do? Probably trying to cleanup a failed startup, just return. */
return 0;
} else {
return SDL_SetError("OpenGL not initialized"); /* something clearly went wrong somewhere. */
}
}
/* The android emulator crashes badly if you try to eglMakeCurrent
* with a valid context and invalid surface, so we have to check for both here.
*/
@@ -1101,7 +1110,7 @@ SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context)
return SDL_EGL_SetError("Unable to make EGL context current", "eglMakeCurrent");
}
}
return 0;
}

View File

@@ -240,6 +240,7 @@ struct SDL_VideoDevice
int (*UpdateWindowFramebuffer) (_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects);
void (*DestroyWindowFramebuffer) (_THIS, SDL_Window * window);
void (*OnWindowEnter) (_THIS, SDL_Window * window);
int (*FlashWindow) (_THIS, SDL_Window * window, Uint32 flash_count);
/* * * */
/*
@@ -290,6 +291,8 @@ struct SDL_VideoDevice
/*
* Event manager functions
*/
int (*WaitEventTimeout) (_THIS, int timeout);
void (*SendWakeupEvent) (_THIS, SDL_Window *window);
void (*PumpEvents) (_THIS);
/* Suspend the screensaver */
@@ -324,6 +327,8 @@ struct SDL_VideoDevice
/* Data common to all drivers */
SDL_bool is_dummy;
SDL_bool suspend_screensaver;
SDL_Window *wakeup_window;
SDL_mutex *wakeup_lock; /* Initialized only if WaitEventTimeout/SendWakeupEvent are supported */
int num_displays;
SDL_VideoDisplay *displays;
SDL_Window *windows;

View File

@@ -2792,6 +2792,18 @@ SDL_GetGrabbedWindow(void)
return _this->grabbed_window;
}
int
SDL_FlashWindow(SDL_Window * window, Uint32 flash_count)
{
CHECK_WINDOW_MAGIC(window, -1);
if (_this->FlashWindow) {
return _this->FlashWindow(_this, window, flash_count);
}
return SDL_Unsupported();
}
void
SDL_OnWindowShown(SDL_Window * window)
{

View File

@@ -32,10 +32,14 @@ Cocoa_SetClipboardText(_THIS, const char *text)
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
NSPasteboard *pasteboard;
NSString *format = NSPasteboardTypeString;
NSString *nsstr = [NSString stringWithUTF8String:text];
if (nsstr == nil) {
return SDL_SetError("Couldn't create NSString; is your string data in UTF-8 format?");
}
pasteboard = [NSPasteboard generalPasteboard];
data->clipboard_count = [pasteboard declareTypes:[NSArray arrayWithObject:format] owner:nil];
[pasteboard setString:[NSString stringWithUTF8String:text] forType:format];
[pasteboard setString:nsstr forType:format];
return 0;
}}
@@ -61,7 +65,7 @@ Cocoa_GetClipboardText(_THIS)
} else {
utf8 = [string UTF8String];
}
text = SDL_strdup(utf8);
text = SDL_strdup(utf8 ? utf8 : "");
} else {
text = SDL_strdup("");
}

View File

@@ -25,6 +25,8 @@
extern void Cocoa_RegisterApp(void);
extern void Cocoa_PumpEvents(_THIS);
extern int Cocoa_WaitEventTimeout(_THIS, int timeout);
extern void Cocoa_SendWakeupEvent(_THIS, SDL_Window *window);
extern void Cocoa_SuspendScreenSaver(_THIS);
#endif /* SDL_cocoaevents_h_ */

View File

@@ -35,6 +35,9 @@
#ifndef NSAppKitVersionNumber10_8
#define NSAppKitVersionNumber10_8 1187
#endif
#ifndef MAC_OS_X_VERSION_10_12
#define NSEventTypeApplicationDefined NSApplicationDefined
#endif
static SDL_Window *FindSDLWindowForNSWindow(NSWindow *win)
{
@@ -512,9 +515,8 @@ Cocoa_RegisterApp(void)
}
}}
void
Cocoa_PumpEvents(_THIS)
{ @autoreleasepool
int
Cocoa_PumpEventsUntilDate(_THIS, NSDate *expiration, bool accumulate)
{
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
/* Update activity every 30 seconds to prevent screensaver */
@@ -530,9 +532,9 @@ Cocoa_PumpEvents(_THIS)
#endif
for ( ; ; ) {
NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES ];
NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:expiration inMode:NSDefaultRunLoopMode dequeue:YES ];
if ( event == nil ) {
break;
return 0;
}
if (!s_bShouldHandleEventsInSDLApplication) {
@@ -541,7 +543,52 @@ Cocoa_PumpEvents(_THIS)
// Pass events down to SDLApplication to be handled in sendEvent:
[NSApp sendEvent:event];
if ( !accumulate) {
break;
}
}
return 1;
}
int
Cocoa_WaitEventTimeout(_THIS, int timeout)
{ @autoreleasepool
{
if (timeout > 0) {
NSDate *limitDate = [NSDate dateWithTimeIntervalSinceNow: (double) timeout / 1000.0];
return Cocoa_PumpEventsUntilDate(_this, limitDate, false);
} else if (timeout == 0) {
return Cocoa_PumpEventsUntilDate(_this, [NSDate distantPast], false);
} else {
while (Cocoa_PumpEventsUntilDate(_this, [NSDate distantFuture], false) == 0) {
}
}
return 1;
}}
void
Cocoa_PumpEvents(_THIS)
{ @autoreleasepool
{
Cocoa_PumpEventsUntilDate(_this, [NSDate distantPast], true);
}}
void Cocoa_SendWakeupEvent(_THIS, SDL_Window *window)
{ @autoreleasepool
{
NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow;
NSEvent* event = [NSEvent otherEventWithType: NSEventTypeApplicationDefined
location: NSMakePoint(0,0)
modifierFlags: 0
timestamp: 0.0
windowNumber: nswindow.windowNumber
context: nil
subtype: 0
data1: 0
data2: 0];
[NSApp postEvent: event atStart: YES];
}}
void

View File

@@ -38,6 +38,9 @@ static void Cocoa_VideoQuit(_THIS);
static void
Cocoa_DeleteDevice(SDL_VideoDevice * device)
{
if (device->wakeup_lock) {
SDL_DestroyMutex(device->wakeup_lock);
}
SDL_free(device->driverdata);
SDL_free(device);
}
@@ -63,6 +66,7 @@ Cocoa_CreateDevice(int devindex)
return NULL;
}
device->driverdata = data;
device->wakeup_lock = SDL_CreateMutex();
/* Set the function pointers */
device->VideoInit = Cocoa_VideoInit;
@@ -73,6 +77,8 @@ Cocoa_CreateDevice(int devindex)
device->GetDisplayModes = Cocoa_GetDisplayModes;
device->SetDisplayMode = Cocoa_SetDisplayMode;
device->PumpEvents = Cocoa_PumpEvents;
device->WaitEventTimeout = Cocoa_WaitEventTimeout;
device->SendWakeupEvent = Cocoa_SendWakeupEvent;
device->SuspendScreenSaver = Cocoa_SuspendScreenSaver;
device->CreateSDLWindow = Cocoa_CreateWindow;

View File

@@ -97,6 +97,11 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
even if you do async flips. */
uint32_t flip_flags = DRM_MODE_PAGE_FLIP_EVENT;
/* Recreate the GBM / EGL surfaces if the display mode has changed */
if (windata->egl_surface_dirty) {
KMSDRM_CreateSurfaces(_this, window);
}
/* Wait for confirmation that the next front buffer has been flipped, at which
point the previous front buffer can be released */
if (!KMSDRM_WaitPageflip(_this, windata)) {
@@ -136,64 +141,58 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
return 0;
}
/* Do we have a modeset pending? If so, configure the new mode on the CRTC.
Has to be done before next pageflip issues, so the buffer with the
new size is big enough for preventing CRTC from reading out of bounds. */
if (dispdata->modeset_pending) {
if (!windata->bo) {
/* On the first swap, immediately present the new front buffer. Before
drmModePageFlip can be used the CRTC has to be configured to use
the current connector and mode with drmModeSetCrtc */
ret = KMSDRM_drmModeSetCrtc(viddata->drm_fd,
dispdata->crtc->crtc_id, fb_info->fb_id, 0, 0,
&dispdata->connector->connector_id, 1, &dispdata->mode);
dispdata->modeset_pending = SDL_FALSE;
if (ret) {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not set videomode on CRTC.");
return 0;
}
/* It's OK to return now if we have done a drmModeSetCrtc(),
it has done the pageflip and blocked until it was done. */
return 1;
}
/* Issue pageflip on the next front buffer.
Remember: drmModePageFlip() never blocks, it just issues the flip,
which will be done during the next vblank, or immediately if
we pass the DRM_MODE_PAGE_FLIP_ASYNC flag.
Since calling drmModePageFlip() will return EBUSY if we call it
without having completed the last issued flip, we must pass the
DRM_MODE_PAGE_FLIP_ASYNC if we don't block on EGL (egl_swapinterval = 0).
That makes it flip immediately, without waiting for the next vblank
to do so, so even if we don't block on EGL, the flip will have completed
when we get here again. */
if (_this->egl_data->egl_swapinterval == 0 && viddata->async_pageflip_support) {
flip_flags |= DRM_MODE_PAGE_FLIP_ASYNC;
}
ret = KMSDRM_drmModePageFlip(viddata->drm_fd, dispdata->crtc->crtc_id,
fb_info->fb_id, flip_flags, &windata->waiting_for_flip);
if (ret == 0) {
windata->waiting_for_flip = SDL_TRUE;
} else {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
}
/* On subsequent swaps, queue the new front buffer to be flipped during
the next vertical blank
/* Wait immediately for vsync (as if we only had two buffers).
Even if we are already doing a WaitPageflip at the begining of this
function, this is NOT redundant because here we wait immediately
after submitting the image to the screen, reducing lag, and if
we have waited here, there won't be a pending pageflip so the
WaitPageflip at the beggining of this function will be a no-op.
Just leave it here and don't worry.
Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 <program_name>"
to enable this. */
if (windata->double_buffer) {
if (!KMSDRM_WaitPageflip(_this, windata)) {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Immediate wait for previous pageflip failed");
return 0;
Remember: drmModePageFlip() never blocks, it just issues the flip,
which will be done during the next vblank, or immediately if
we pass the DRM_MODE_PAGE_FLIP_ASYNC flag.
Since calling drmModePageFlip() will return EBUSY if we call it
without having completed the last issued flip, we must pass the
DRM_MODE_PAGE_FLIP_ASYNC if we don't block on EGL (egl_swapinterval = 0).
That makes it flip immediately, without waiting for the next vblank
to do so, so even if we don't block on EGL, the flip will have completed
when we get here again. */
if (_this->egl_data->egl_swapinterval == 0 && viddata->async_pageflip_support) {
flip_flags |= DRM_MODE_PAGE_FLIP_ASYNC;
}
ret = KMSDRM_drmModePageFlip(viddata->drm_fd, dispdata->crtc->crtc_id,
fb_info->fb_id, flip_flags, &windata->waiting_for_flip);
if (ret == 0) {
windata->waiting_for_flip = SDL_TRUE;
} else {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
}
/* Wait immediately for vsync (as if we only had two buffers).
Even if we are already doing a WaitPageflip at the begining of this
function, this is NOT redundant because here we wait immediately
after submitting the image to the screen, reducing lag, and if
we have waited here, there won't be a pending pageflip so the
WaitPageflip at the beggining of this function will be a no-op.
Just leave it here and don't worry.
Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 <program_name>"
to enable this. */
if (windata->double_buffer) {
if (!KMSDRM_WaitPageflip(_this, windata)) {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Immediate wait for previous pageflip failed");
return 0;
}
}
}

View File

@@ -551,7 +551,6 @@ void KMSDRM_AddDisplay (_THIS, drmModeConnector *connector, drmModeRes *resource
/* Initialize some of the members of the new display's driverdata
to sane values. */
dispdata->modeset_pending = SDL_FALSE;
dispdata->cursor_bo = NULL;
/* Since we create and show the default cursor on KMSDRM_InitMouse(),
@@ -907,6 +906,7 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
{
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
SDL_WindowData *windata = (SDL_WindowData *)window->driverdata;
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayForWindow(window)->driverdata;
uint32_t surface_fmt = GBM_FORMAT_ARGB8888;
uint32_t surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
@@ -929,7 +929,8 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
}
windata->gs = KMSDRM_gbm_surface_create(viddata->gbm_dev,
windata->surface_w, windata->surface_h, surface_fmt, surface_flags);
dispdata->mode.hdisplay, dispdata->mode.vdisplay,
surface_fmt, surface_flags);
if (!windata->gs) {
return SDL_SetError("Could not create GBM surface");
@@ -951,6 +952,8 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window)
egl_context = (EGLContext)SDL_GL_GetCurrentContext();
ret = SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context);
windata->egl_surface_dirty = SDL_FALSE;
cleanup:
if (ret) {
@@ -1069,14 +1072,14 @@ KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
/* Take note of the new mode to be set, and leave the CRTC modeset pending
so it's done in SwapWindow. */
dispdata->mode = conn->modes[modedata->mode_index];
dispdata->modeset_pending = SDL_TRUE;
for (i = 0; i < viddata->num_windows; i++) {
SDL_Window *window = viddata->windows[i];
SDL_WindowData *windata = (SDL_WindowData *)window->driverdata;
if (KMSDRM_CreateSurfaces(_this, window)) {
return -1;
}
/* Can't recreate EGL surfaces right now, need to wait until SwapWindow
so the correct thread-local surface and context state are available */
windata->egl_surface_dirty = SDL_TRUE;
/* Tell app about the window resize */
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode->w, mode->h);
@@ -1246,18 +1249,11 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
window->windowed.w, window->windowed.h, 0 );
if (mode) {
windata->surface_w = mode->hdisplay;
windata->surface_h = mode->vdisplay;
dispdata->mode = *mode;
} else {
windata->surface_w = dispdata->original_mode.hdisplay;
windata->surface_h = dispdata->original_mode.vdisplay;
dispdata->mode = dispdata->original_mode;
}
/* Take note to do the modesettng on the CRTC in SwapWindow. */
dispdata->modeset_pending = SDL_TRUE;
/* Create the window surfaces with the size we have just chosen.
Needs the window diverdata in place. */
if ((ret = KMSDRM_CreateSurfaces(_this, window))) {
@@ -1267,7 +1263,7 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
/* Tell app about the size we have determined for the window,
so SDL pre-scales to that size for us. */
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED,
windata->surface_w, windata->surface_h);
dispdata->mode.hdisplay, dispdata->mode.vdisplay);
} /* NON-Vulkan block ends. */
@@ -1310,67 +1306,48 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
/* To be used by SetWindowSize() and SetWindowFullscreen(). */
/*****************************************************************************/
void
KMSDRM_ReconfigureWindow( _THIS, SDL_Window * window) {
SDL_WindowData *windata = (SDL_WindowData *) window->driverdata;
KMSDRM_ReconfigureWindow( _THIS, SDL_Window * window)
{
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
SDL_DisplayData *dispdata = display->driverdata;
uint32_t refresh_rate = 0;
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) ==
SDL_WINDOW_FULLSCREEN_DESKTOP)
if ((window->flags & SDL_WINDOW_FULLSCREEN) ==
SDL_WINDOW_FULLSCREEN)
{
/* Nothing to do, honor the most recent mode requested by the user */
}
else if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) ==
SDL_WINDOW_FULLSCREEN_DESKTOP)
{
/* Update the current mode to the desktop mode. */
windata->surface_w = dispdata->original_mode.hdisplay;
windata->surface_h = dispdata->original_mode.vdisplay;
dispdata->mode = dispdata->original_mode;
} else {
drmModeModeInfo *mode;
/* Refresh rate is only important for fullscreen windows. */
if ((window->flags & SDL_WINDOW_FULLSCREEN) ==
SDL_WINDOW_FULLSCREEN)
{
refresh_rate = (uint32_t)window->fullscreen_mode.refresh_rate;
}
/* Try to find a valid video mode matching the size of the window. */
mode = KMSDRM_GetClosestDisplayMode(display,
window->windowed.w, window->windowed.h, refresh_rate );
window->windowed.w, window->windowed.h, 0);
if (mode) {
/* If matching mode found, recreate the GBM surface with the size
of that mode and configure it on the CRTC. */
windata->surface_w = mode->hdisplay;
windata->surface_h = mode->vdisplay;
dispdata->mode = *mode;
} else {
/* If not matching mode found, recreate the GBM surfaces with the
size of the mode that was originally configured on the CRTC,
and setup that mode on the CRTC. */
windata->surface_w = dispdata->original_mode.hdisplay;
windata->surface_h = dispdata->original_mode.vdisplay;
dispdata->mode = dispdata->original_mode;
}
/* Tell app about the size we have determined for the window,
so SDL pre-scales to that size for us. */
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED,
windata->surface_w, windata->surface_h);
}
/* Recreate the GBM (and EGL) surfaces, and mark the CRTC mode/fb setting
as pending so it's done on SwapWindow. */
KMSDRM_CreateSurfaces(_this, window);
dispdata->modeset_pending = SDL_TRUE;
/* Tell app about the size we have determined for the window,
so SDL pre-scales to that size for us. */
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED,
windata->surface_w, windata->surface_h);
dispdata->mode.hdisplay, dispdata->mode.vdisplay);
}
int

View File

@@ -80,8 +80,6 @@ typedef struct SDL_DisplayData
uint64_t cursor_w, cursor_h;
SDL_bool default_cursor_init;
SDL_bool modeset_pending;
} SDL_DisplayData;
typedef struct SDL_WindowData
@@ -99,13 +97,7 @@ typedef struct SDL_WindowData
SDL_bool double_buffer;
EGLSurface egl_surface;
/* The size we chose for the GBM surface. REMEMBER that the CRTC must always have
a mode with the same size configured before trying to flip to a buffer of that
surface or drmModePageFlip() will return -28. */
uint32_t surface_w;
uint32_t surface_h;
SDL_bool egl_surface_dirty;
} SDL_WindowData;
typedef struct KMSDRM_FBInfo

View File

@@ -51,6 +51,7 @@
#include "xdg-decoration-unstable-v1-client-protocol.h"
#include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h"
#include "idle-inhibit-unstable-v1-client-protocol.h"
#include "xdg-activation-v1-client-protocol.h"
#define WAYLANDVID_DRIVER_NAME "wayland"
@@ -199,6 +200,7 @@ Wayland_CreateDevice(int devindex)
device->CreateSDLWindow = Wayland_CreateWindow;
device->ShowWindow = Wayland_ShowWindow;
device->HideWindow = Wayland_HideWindow;
device->RaiseWindow = Wayland_RaiseWindow;
device->SetWindowFullscreen = Wayland_SetWindowFullscreen;
device->MaximizeWindow = Wayland_MaximizeWindow;
device->MinimizeWindow = Wayland_MinimizeWindow;
@@ -214,6 +216,7 @@ Wayland_CreateDevice(int devindex)
device->SetWindowTitle = Wayland_SetWindowTitle;
device->DestroyWindow = Wayland_DestroyWindow;
device->SetWindowHitTest = Wayland_SetWindowHitTest;
device->FlashWindow = Wayland_FlashWindow;
device->SetClipboardText = Wayland_SetClipboardText;
device->GetClipboardText = Wayland_GetClipboardText;
@@ -463,6 +466,8 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
d->key_inhibitor_manager = wl_registry_bind(d->registry, id, &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1);
} else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0) {
d->idle_inhibit_manager = wl_registry_bind(d->registry, id, &zwp_idle_inhibit_manager_v1_interface, 1);
} else if (strcmp(interface, "xdg_activation_v1") == 0) {
d->activation_manager = wl_registry_bind(d->registry, id, &xdg_activation_v1_interface, 1);
} else if (strcmp(interface, "wl_data_device_manager") == 0) {
Wayland_add_data_device_manager(d, id, version);
} else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
@@ -583,6 +588,9 @@ Wayland_VideoQuit(_THIS)
Wayland_display_destroy_pointer_constraints(data);
Wayland_display_destroy_relative_pointer_manager(data);
if (data->activation_manager)
xdg_activation_v1_destroy(data->activation_manager);
if (data->idle_inhibit_manager)
zwp_idle_inhibit_manager_v1_destroy(data->idle_inhibit_manager);

View File

@@ -69,6 +69,7 @@ typedef struct {
struct zxdg_decoration_manager_v1 *decoration_manager;
struct zwp_keyboard_shortcuts_inhibit_manager_v1 *key_inhibitor_manager;
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
struct xdg_activation_v1 *activation_manager;
EGLDisplay edpy;
EGLContext context;

View File

@@ -37,6 +37,7 @@
#include "xdg-shell-unstable-v6-client-protocol.h"
#include "xdg-decoration-unstable-v1-client-protocol.h"
#include "idle-inhibit-unstable-v1-client-protocol.h"
#include "xdg-activation-v1-client-protocol.h"
static float get_window_scale_factor(SDL_Window *window) {
return ((SDL_WindowData*)window->driverdata)->scale_factor;
@@ -272,9 +273,12 @@ handle_configure_zxdg_toplevel(void *data,
enum zxdg_toplevel_v6_state *state;
SDL_bool fullscreen = SDL_FALSE;
SDL_bool maximized = SDL_FALSE;
wl_array_for_each(state, states) {
if (*state == ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN) {
fullscreen = SDL_TRUE;
} else if (*state == ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED) {
maximized = SDL_TRUE;
}
}
@@ -283,6 +287,7 @@ handle_configure_zxdg_toplevel(void *data,
/* We might need to re-enter fullscreen after being restored from minimized */
SDL_WaylandOutputData *driverdata = (SDL_WaylandOutputData *) SDL_GetDisplayForWindow(window)->driverdata;
SetFullscreen(window, driverdata->output);
fullscreen = SDL_TRUE;
}
if (width == 0 || height == 0) {
@@ -310,6 +315,19 @@ handle_configure_zxdg_toplevel(void *data,
}
}
/* Always send a maximized/restore event; if the event is redundant it will
* automatically be discarded (see src/events/SDL_windowevents.c).
*
* No, we do not get minimize events from zxdg-shell.
*/
if (!fullscreen) {
SDL_SendWindowEvent(window,
maximized ?
SDL_WINDOWEVENT_MAXIMIZED :
SDL_WINDOWEVENT_RESTORED,
0, 0);
}
if (width == 0 || height == 0) {
wind->resize.width = window->w;
wind->resize.height = window->h;
@@ -388,9 +406,12 @@ handle_configure_xdg_toplevel(void *data,
enum xdg_toplevel_state *state;
SDL_bool fullscreen = SDL_FALSE;
SDL_bool maximized = SDL_FALSE;
wl_array_for_each(state, states) {
if (*state == XDG_TOPLEVEL_STATE_FULLSCREEN) {
fullscreen = SDL_TRUE;
} else if (*state == XDG_TOPLEVEL_STATE_MAXIMIZED) {
maximized = SDL_TRUE;
}
}
@@ -399,6 +420,7 @@ handle_configure_xdg_toplevel(void *data,
/* We might need to re-enter fullscreen after being restored from minimized */
SDL_WaylandOutputData *driverdata = (SDL_WaylandOutputData *) SDL_GetDisplayForWindow(window)->driverdata;
SetFullscreen(window, driverdata->output);
fullscreen = SDL_TRUE;
}
if (width == 0 || height == 0) {
@@ -426,6 +448,19 @@ handle_configure_xdg_toplevel(void *data,
}
}
/* Always send a maximized/restore event; if the event is redundant it will
* automatically be discarded (see src/events/SDL_windowevents.c)
*
* No, we do not get minimize events from xdg-shell.
*/
if (!fullscreen) {
SDL_SendWindowEvent(window,
maximized ?
SDL_WINDOWEVENT_MAXIMIZED :
SDL_WINDOWEVENT_RESTORED,
0, 0);
}
if (width == 0 || height == 0) {
wind->resize.width = window->w;
wind->resize.height = window->h;
@@ -682,11 +717,6 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
/* Create the window decorations */
if (c->decoration_manager) {
data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(c->decoration_manager, data->shell_surface.xdg.roleobj.toplevel);
}
} else if (c->shell.zxdg) {
data->shell_surface.zxdg.surface = zxdg_shell_v6_get_xdg_surface(c->shell.zxdg, data->surface);
zxdg_surface_v6_set_user_data(data->shell_surface.zxdg.surface, data);
@@ -705,7 +735,6 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
/* Restore state that was set prior to this call */
Wayland_SetWindowTitle(_this, window);
Wayland_SetWindowBordered(_this, window, (window->flags & SDL_WINDOW_BORDERLESS) == 0);
if (window->flags & SDL_WINDOW_MAXIMIZED) {
Wayland_MaximizeWindow(_this, window);
}
@@ -724,6 +753,11 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
WAYLAND_wl_display_dispatch(c->display);
}
}
/* Create the window decorations */
if (data->shell_surface.xdg.roleobj.toplevel && c->decoration_manager) {
data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(c->decoration_manager, data->shell_surface.xdg.roleobj.toplevel);
}
} else if (c->shell.zxdg) {
if (data->shell_surface.zxdg.surface) {
while (!data->shell_surface.zxdg.initial_configure_seen) {
@@ -732,6 +766,31 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
}
}
}
/* Unlike the rest of window state we have to set this _after_ flushing the
* display, because we need to create the decorations before possibly hiding
* them immediately afterward. But don't call it redundantly, the protocol
* may not interpret a redundant call nicely and cause weird stuff to happen
*/
if (window->flags & SDL_WINDOW_BORDERLESS) {
Wayland_SetWindowBordered(_this, window, SDL_FALSE);
}
/* We're finally done putting the window together, raise if possible */
if (c->activation_manager) {
/* Note that we don't check for empty strings, as that is still
* considered a valid activation token!
*/
const char *activation_token = SDL_getenv("XDG_ACTIVATION_TOKEN");
if (activation_token) {
xdg_activation_v1_activate(c->activation_manager,
activation_token,
data->surface);
/* Clear this variable, per the protocol's request */
unsetenv("XDG_ACTIVATION_TOKEN");
}
}
}
void Wayland_HideWindow(_THIS, SDL_Window *window)
@@ -770,6 +829,107 @@ void Wayland_HideWindow(_THIS, SDL_Window *window)
}
}
static void
handle_xdg_activation_done(void *data,
struct xdg_activation_token_v1 *xdg_activation_token_v1,
const char *token)
{
SDL_WindowData *window = data;
if (xdg_activation_token_v1 == window->activation_token) {
xdg_activation_v1_activate(window->waylandData->activation_manager,
token,
window->surface);
xdg_activation_token_v1_destroy(window->activation_token);
window->activation_token = NULL;
}
}
static const struct xdg_activation_token_v1_listener activation_listener_xdg = {
handle_xdg_activation_done
};
/* The xdg-activation protocol considers "activation" to be one of two things:
*
* 1: Raising a window to the top and flashing the titlebar
* 2: Flashing the titlebar while keeping the window where it is
*
* As you might expect from Wayland, the general policy is to go with #2 unless
* the client can prove to the compositor beyond a reasonable doubt that raising
* the window will not be malicuous behavior.
*
* For SDL this means RaiseWindow and FlashWindow both use the same protocol,
* but in different ways: RaiseWindow will provide as _much_ information as
* possible while FlashWindow will provide as _little_ information as possible,
* to nudge the compositor into doing what we want.
*
* This isn't _strictly_ what the protocol says will happen, but this is what
* current implementations are doing (as of writing, YMMV in the far distant
* future).
*
* -flibit
*/
static void
Wayland_activate_window(SDL_VideoData *data, SDL_WindowData *wind,
struct wl_surface *surface,
uint32_t serial, struct wl_seat *seat)
{
if (data->activation_manager) {
if (wind->activation_token != NULL) {
/* We're about to overwrite this with a new request */
xdg_activation_token_v1_destroy(wind->activation_token);
}
wind->activation_token = xdg_activation_v1_get_activation_token(data->activation_manager);
xdg_activation_token_v1_add_listener(wind->activation_token,
&activation_listener_xdg,
wind);
/* Note that we are not setting the app_id or serial here.
*
* Hypothetically we could set the app_id from data->classname, but
* that part of the API is for _external_ programs, not ourselves.
*
* -flibit
*/
if (surface != NULL) {
xdg_activation_token_v1_set_surface(wind->activation_token, surface);
}
if (seat != NULL) {
xdg_activation_token_v1_set_serial(wind->activation_token, serial, seat);
}
xdg_activation_token_v1_commit(wind->activation_token);
}
}
void
Wayland_RaiseWindow(_THIS, SDL_Window *window)
{
SDL_WindowData *wind = window->driverdata;
/* FIXME: This Raise event is arbitrary and doesn't come from an event, so
* it's actually very likely that this token will be ignored! Maybe add
* support for passing serials (and the associated seat) so this can have
* a better chance of actually raising the window.
* -flibit
*/
Wayland_activate_window(_this->driverdata,
wind,
wind->surface,
0,
NULL);
}
int
Wayland_FlashWindow(_THIS, SDL_Window *window, Uint32 flash_count)
{
Wayland_activate_window(_this->driverdata,
window->driverdata,
NULL,
0,
NULL);
return 0;
}
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
static void SDLCALL
QtExtendedSurface_OnHintChanged(void *userdata, const char *name,
@@ -1235,6 +1395,10 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window)
zwp_idle_inhibitor_v1_destroy(wind->idle_inhibitor);
}
if (wind->activation_token) {
xdg_activation_token_v1_destroy(wind->activation_token);
}
SDL_free(wind->outputs);
if (wind->frame_callback) {

View File

@@ -67,6 +67,7 @@ typedef struct {
struct zxdg_toplevel_decoration_v1 *server_decoration;
struct zwp_keyboard_shortcuts_inhibitor_v1 *key_inhibitor;
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
struct xdg_activation_token_v1 *activation_token;
SDL_atomic_t swap_interval_ready;
@@ -89,6 +90,7 @@ typedef struct {
extern void Wayland_ShowWindow(_THIS, SDL_Window *window);
extern void Wayland_HideWindow(_THIS, SDL_Window *window);
extern void Wayland_RaiseWindow(_THIS, SDL_Window *window);
extern void Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
SDL_VideoDisplay * _display,
SDL_bool fullscreen);
@@ -111,6 +113,7 @@ extern void Wayland_SuspendScreenSaver(_THIS);
extern SDL_bool
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
extern int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
extern int Wayland_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count);
extern void Wayland_HandlePendingResize(SDL_Window *window);

View File

@@ -428,6 +428,23 @@ static SDL_MOUSE_EVENT_SOURCE GetMouseMessageSource()
return SDL_MOUSE_EVENT_SOURCE_MOUSE;
}
static SDL_WindowData *
WIN_GetWindowDataFromHWND(HWND hwnd)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
SDL_Window *window;
if (_this) {
for (window = _this->windows; window; window = window->next) {
SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
if (data && data->hwnd == hwnd) {
return data;
}
}
}
return NULL;
}
LRESULT CALLBACK
WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
@@ -510,7 +527,11 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
}
/* Get the window data for the window */
data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
data = WIN_GetWindowDataFromHWND(hwnd);
if (!data) {
/* Fallback */
data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
}
if (!data) {
return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
}
@@ -693,8 +714,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
/* Mouse data (ignoring synthetic mouse events generated for touchscreens) */
if (inp.header.dwType == RIM_TYPEMOUSE) {
if (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH ||
(GetMessageExtraInfo() & 0x82) == 0x82) {
if (SDL_GetNumTouchDevices() > 0 &&
(GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH || (GetMessageExtraInfo() & 0x82) == 0x82)) {
break;
}
if (isRelative) {
@@ -1255,6 +1276,49 @@ void SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata)
g_WindowsMessageHookData = userdata;
}
int
WIN_WaitEventTimeout(_THIS, int timeout)
{
MSG msg;
if (g_WindowsEnableMessageLoop) {
BOOL message_result;
UINT_PTR timer_id = 0;
if (timeout > 0) {
timer_id = SetTimer(NULL, 0, timeout, NULL);
message_result = GetMessage(&msg, 0, 0, 0);
KillTimer(NULL, timer_id);
} else if (timeout == 0) {
message_result = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
} else {
message_result = GetMessage(&msg, 0, 0, 0);
}
if (message_result) {
if (msg.message == WM_TIMER && msg.hwnd == NULL && msg.wParam == timer_id) {
return 0;
}
if (g_WindowsMessageHook) {
g_WindowsMessageHook(g_WindowsMessageHookData, msg.hwnd, msg.message, msg.wParam, msg.lParam);
}
/* Always translate the message in case it's a non-SDL window (e.g. with Qt integration) */
TranslateMessage(&msg);
DispatchMessage(&msg);
return 1;
} else {
return 0;
}
} else {
/* Fail the wait so the caller falls back to polling */
return -1;
}
}
void
WIN_SendWakeupEvent(_THIS, SDL_Window *window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
PostMessage(data->hwnd, data->videodata->_SDL_WAKEUP, 0, 0);
}
void
WIN_PumpEvents(_THIS)
{

View File

@@ -31,6 +31,8 @@ extern LRESULT CALLBACK WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lP
extern LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam);
extern void WIN_PumpEvents(_THIS);
extern void WIN_SendWakeupEvent(_THIS, SDL_Window *window);
extern int WIN_WaitEventTimeout(_THIS, int timeout);
#endif /* SDL_windowsevents_h_ */

View File

@@ -87,7 +87,9 @@ WIN_DeleteDevice(SDL_VideoDevice * device)
if (data->shcoreDLL) {
SDL_UnloadObject(data->shcoreDLL);
}
if (device->wakeup_lock) {
SDL_DestroyMutex(device->wakeup_lock);
}
SDL_free(device->driverdata);
SDL_free(device);
}
@@ -113,6 +115,7 @@ WIN_CreateDevice(int devindex)
return NULL;
}
device->driverdata = data;
device->wakeup_lock = SDL_CreateMutex();
data->userDLL = SDL_LoadObject("USER32.DLL");
if (data->userDLL) {
@@ -139,6 +142,8 @@ WIN_CreateDevice(int devindex)
device->GetDisplayModes = WIN_GetDisplayModes;
device->SetDisplayMode = WIN_SetDisplayMode;
device->PumpEvents = WIN_PumpEvents;
device->WaitEventTimeout = WIN_WaitEventTimeout;
device->SendWakeupEvent = WIN_SendWakeupEvent;
device->SuspendScreenSaver = WIN_SuspendScreenSaver;
device->CreateSDLWindow = WIN_CreateWindow;
@@ -171,6 +176,7 @@ WIN_CreateDevice(int devindex)
device->OnWindowEnter = WIN_OnWindowEnter;
device->SetWindowHitTest = WIN_SetWindowHitTest;
device->AcceptDragAndDrop = WIN_AcceptDragAndDrop;
device->FlashWindow = WIN_FlashWindow;
device->shape_driver.CreateShaper = Win32_CreateShaper;
device->shape_driver.SetWindowShape = Win32_SetWindowShape;
@@ -226,6 +232,8 @@ VideoBootStrap WINDOWS_bootstrap = {
int
WIN_VideoInit(_THIS)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
if (WIN_InitModes(_this) < 0) {
return -1;
}
@@ -236,6 +244,8 @@ WIN_VideoInit(_THIS)
SDL_AddHintCallback(SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP, UpdateWindowsEnableMessageLoop, NULL);
SDL_AddHintCallback(SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN, UpdateWindowFrameUsableWhileCursorHidden, NULL);
data->_SDL_WAKEUP = RegisterWindowMessageA("_SDL_WAKEUP");
return 0;
}

View File

@@ -190,6 +190,7 @@ typedef struct SDL_VideoData
TSFSink *ime_ippasink;
BYTE pre_hook_key_state[256];
UINT _SDL_WAKEUP;
} SDL_VideoData;
extern SDL_bool g_WindowsEnableMessageLoop;

View File

@@ -1084,6 +1084,24 @@ WIN_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept)
DragAcceptFiles(data->hwnd, accept ? TRUE : FALSE);
}
int
WIN_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count)
{
HWND hwnd;
FLASHWINFO desc;
hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
desc.cbSize = sizeof(desc);
desc.hwnd = hwnd;
desc.dwFlags = FLASHW_TRAY;
desc.uCount = flash_count; /* flash x times */
desc.dwTimeout = 0;
FlashWindowEx(&desc);
return 0;
}
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -86,6 +86,7 @@ extern void WIN_OnWindowEnter(_THIS, SDL_Window * window);
extern void WIN_UpdateClipCursor(SDL_Window *window);
extern int WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
extern void WIN_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept);
extern int WIN_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count);
#endif /* SDL_windowswindow_h_ */

View File

@@ -53,7 +53,7 @@ typedef enum {
extern Windows::Foundation::Point WINRT_TransformCursorPosition(SDL_Window * window,
Windows::Foundation::Point rawPosition,
WINRT_CursorNormalizationType normalization);
extern Uint8 WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt);
extern SDL_bool WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt, Uint8 *button, Uint8 *pressed);
extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);

View File

@@ -116,8 +116,8 @@ WINRT_TransformCursorPosition(SDL_Window * window,
return outputPosition;
}
Uint8
WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt)
SDL_bool
WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt, Uint8 *button, Uint8 *pressed)
{
using namespace Windows::UI::Input;
@@ -128,30 +128,42 @@ WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt)
{
case PointerUpdateKind::LeftButtonPressed:
case PointerUpdateKind::LeftButtonReleased:
return SDL_BUTTON_LEFT;
*button = SDL_BUTTON_LEFT;
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::LeftButtonPressed);
return SDL_TRUE;
case PointerUpdateKind::RightButtonPressed:
case PointerUpdateKind::RightButtonReleased:
return SDL_BUTTON_RIGHT;
*button = SDL_BUTTON_RIGHT;
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::RightButtonPressed);
return SDL_TRUE;
case PointerUpdateKind::MiddleButtonPressed:
case PointerUpdateKind::MiddleButtonReleased:
return SDL_BUTTON_MIDDLE;
*button = SDL_BUTTON_MIDDLE;
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::MiddleButtonPressed);
return SDL_TRUE;
case PointerUpdateKind::XButton1Pressed:
case PointerUpdateKind::XButton1Released:
return SDL_BUTTON_X1;
*button = SDL_BUTTON_X1;
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::XButton1Pressed);
return SDL_TRUE;
case PointerUpdateKind::XButton2Pressed:
case PointerUpdateKind::XButton2Released:
return SDL_BUTTON_X2;
*button = SDL_BUTTON_X2;
*pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::XButton2Pressed);
return SDL_TRUE;
default:
break;
}
#endif
return 0;
*button = 0;
*pressed = 0;
return SDL_FALSE;
}
//const char *
@@ -211,9 +223,10 @@ void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::Po
return;
}
Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
if ( ! WINRT_IsTouchEvent(pointerPoint)) {
Uint8 button, pressed;
WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed);
SDL_assert(pressed == 1);
SDL_SendMouseButton(window, 0, SDL_PRESSED, button);
} else {
Windows::Foundation::Point normalizedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, NormalizeZeroToOne);
@@ -241,6 +254,12 @@ WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPo
Windows::Foundation::Point windowPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, TransformToSDLWindowSize);
if ( ! WINRT_IsTouchEvent(pointerPoint)) {
/* For some odd reason Moved events are used for multiple mouse buttons */
Uint8 button, pressed;
if (WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed)) {
SDL_SendMouseButton(window, 0, pressed, button);
}
SDL_SendMouseMotion(window, 0, 0, (int)windowPoint.X, (int)windowPoint.Y);
} else {
SDL_SendTouchMotion(
@@ -259,9 +278,10 @@ void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::P
return;
}
Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
if (!WINRT_IsTouchEvent(pointerPoint)) {
Uint8 button, pressed;
WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed);
SDL_assert(pressed == 0);
SDL_SendMouseButton(window, 0, SDL_RELEASED, button);
} else {
Windows::Foundation::Point normalizedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, NormalizeZeroToOne);

View File

@@ -670,42 +670,35 @@ isReparentNotify(Display *display, XEvent *ev, XPointer arg)
}
static void
X11_DispatchEvent(_THIS)
X11_DispatchEvent(_THIS, XEvent *xevent)
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
XkbEvent* xkbEvent = (XkbEvent*) xevent;
Display *display;
SDL_WindowData *data;
XEvent xevent;
XkbEvent* xkbEvent;
int orig_event_type;
KeyCode orig_keycode;
XClientMessageEvent m;
int i;
if (!videodata) {
return;
}
SDL_assert(videodata != NULL);
display = videodata->display;
SDL_zero(xevent); /* valgrind fix. --ryan. */
X11_XNextEvent(display, &xevent);
xkbEvent = (XkbEvent*) &xevent;
/* Save the original keycode for dead keys, which are filtered out by
the XFilterEvent() call below.
*/
orig_event_type = xevent.type;
orig_event_type = xevent->type;
if (orig_event_type == KeyPress || orig_event_type == KeyRelease) {
orig_keycode = xevent.xkey.keycode;
orig_keycode = xevent->xkey.keycode;
} else {
orig_keycode = 0;
}
/* filter events catchs XIM events and sends them to the correct handler */
if (X11_XFilterEvent(&xevent, None) == True) {
if (X11_XFilterEvent(xevent, None) == True) {
#if 0
printf("Filtered event type = %d display = %d window = %d\n",
xevent.type, xevent.xany.display, xevent.xany.window);
xevent->type, xevent->xany.display, xevent->xany.window);
#endif
/* Make sure dead key press/release events are sent */
/* But only if we're using one of the DBus IMEs, otherwise
@@ -714,7 +707,7 @@ X11_DispatchEvent(_THIS)
#if defined(HAVE_IBUS_IBUS_H) || defined(HAVE_FCITX)
SDL_Scancode scancode = videodata->key_layout[orig_keycode];
videodata->filter_code = orig_keycode;
videodata->filter_time = xevent.xkey.time;
videodata->filter_time = xevent->xkey.time;
if (orig_event_type == KeyPress) {
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
@@ -727,8 +720,8 @@ X11_DispatchEvent(_THIS)
}
#if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
if(xevent.type == GenericEvent) {
X11_HandleGenericEvent(videodata, &xevent);
if(xevent->type == GenericEvent) {
X11_HandleGenericEvent(videodata, xevent);
return;
}
#endif
@@ -739,18 +732,18 @@ X11_DispatchEvent(_THIS)
SDL_VERSION(&wmmsg.version);
wmmsg.subsystem = SDL_SYSWM_X11;
wmmsg.msg.x11.event = xevent;
wmmsg.msg.x11.event = *xevent;
SDL_SendSysWMEvent(&wmmsg);
}
#if 0
printf("type = %d display = %d window = %d\n",
xevent.type, xevent.xany.display, xevent.xany.window);
xevent->type, xevent->xany.display, xevent->xany.window);
#endif
if ((videodata->clipboard_window != None) &&
(videodata->clipboard_window == xevent.xany.window)) {
X11_HandleClipboardEvent(_this, &xevent);
(videodata->clipboard_window == xevent->xany.window)) {
X11_HandleClipboardEvent(_this, xevent);
return;
}
@@ -758,7 +751,7 @@ X11_DispatchEvent(_THIS)
if (videodata && videodata->windowlist) {
for (i = 0; i < videodata->numwindows; ++i) {
if ((videodata->windowlist[i] != NULL) &&
(videodata->windowlist[i]->xwindow == xevent.xany.window)) {
(videodata->windowlist[i]->xwindow == xevent->xany.window)) {
data = videodata->windowlist[i];
break;
}
@@ -766,19 +759,19 @@ X11_DispatchEvent(_THIS)
}
if (!data) {
/* The window for KeymapNotify, etc events is 0 */
if (xevent.type == KeymapNotify) {
if (xevent->type == KeymapNotify) {
if (SDL_GetKeyboardFocus() != NULL) {
X11_ReconcileKeyboardState(_this);
}
} else if (xevent.type == MappingNotify || xkbEvent->any.xkb_type == XkbStateNotify) {
} else if (xevent->type == MappingNotify || xkbEvent->any.xkb_type == XkbStateNotify) {
/* Has the keyboard layout changed? */
const int request = xevent.xmapping.request;
const int request = xevent->xmapping.request;
#ifdef DEBUG_XEVENTS
printf("window %p: MappingNotify!\n", data);
#endif
if ((request == MappingKeyboard) || (request == MappingModifier)) {
X11_XRefreshKeyboardMapping(&xevent.xmapping);
X11_XRefreshKeyboardMapping(&xevent->xmapping);
}
X11_UpdateKeymap(_this);
@@ -787,28 +780,28 @@ X11_DispatchEvent(_THIS)
return;
}
switch (xevent.type) {
switch (xevent->type) {
/* Gaining mouse coverage? */
case EnterNotify:{
SDL_Mouse *mouse = SDL_GetMouse();
#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)
xevent->xcrossing.x,
xevent->xcrossing.y,
xevent->xcrossing.mode);
if (xevent->xcrossing.mode == NotifyGrab)
printf("Mode: NotifyGrab\n");
if (xevent.xcrossing.mode == NotifyUngrab)
if (xevent->xcrossing.mode == NotifyUngrab)
printf("Mode: NotifyUngrab\n");
#endif
SDL_SetMouseFocus(data->window);
mouse->last_x = xevent.xcrossing.x;
mouse->last_y = xevent.xcrossing.y;
mouse->last_x = xevent->xcrossing.x;
mouse->last_y = xevent->xcrossing.y;
if (!mouse->relative_mode) {
SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y);
SDL_SendMouseMotion(data->window, 0, 0, xevent->xcrossing.x, xevent->xcrossing.y);
}
/* We ungrab in LeaveNotify, so we may need to grab again here */
@@ -819,21 +812,21 @@ X11_DispatchEvent(_THIS)
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)
xevent->xcrossing.x,
xevent->xcrossing.y,
xevent->xcrossing.mode);
if (xevent->xcrossing.mode == NotifyGrab)
printf("Mode: NotifyGrab\n");
if (xevent.xcrossing.mode == NotifyUngrab)
if (xevent->xcrossing.mode == NotifyUngrab)
printf("Mode: NotifyUngrab\n");
#endif
if (!SDL_GetMouse()->relative_mode) {
SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y);
SDL_SendMouseMotion(data->window, 0, 0, xevent->xcrossing.x, xevent->xcrossing.y);
}
if (xevent.xcrossing.mode != NotifyGrab &&
xevent.xcrossing.mode != NotifyUngrab &&
xevent.xcrossing.detail != NotifyInferior) {
if (xevent->xcrossing.mode != NotifyGrab &&
xevent->xcrossing.mode != NotifyUngrab &&
xevent->xcrossing.detail != NotifyInferior) {
/* In order for interaction with the window decorations and menu to work properly
on Mutter, we need to ungrab the keyboard when the the mouse leaves. */
@@ -848,7 +841,7 @@ X11_DispatchEvent(_THIS)
/* Gaining input focus? */
case FocusIn:{
if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) {
if (xevent->xfocus.mode == NotifyGrab || xevent->xfocus.mode == NotifyUngrab) {
/* Someone is handling a global hotkey, ignore it */
#ifdef DEBUG_XEVENTS
printf("window %p: FocusIn (NotifyGrab/NotifyUngrab, ignoring)\n", data);
@@ -856,7 +849,7 @@ X11_DispatchEvent(_THIS)
break;
}
if (xevent.xfocus.detail == NotifyInferior || xevent.xfocus.detail == NotifyPointer) {
if (xevent->xfocus.detail == NotifyInferior || xevent->xfocus.detail == NotifyPointer) {
#ifdef DEBUG_XEVENTS
printf("window %p: FocusIn (NotifyInferior/NotifyPointer, ignoring)\n", data);
#endif
@@ -882,14 +875,14 @@ X11_DispatchEvent(_THIS)
/* Losing input focus? */
case FocusOut:{
if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) {
if (xevent->xfocus.mode == NotifyGrab || xevent->xfocus.mode == NotifyUngrab) {
/* Someone is handling a global hotkey, ignore it */
#ifdef DEBUG_XEVENTS
printf("window %p: FocusOut (NotifyGrab/NotifyUngrab, ignoring)\n", data);
#endif
break;
}
if (xevent.xfocus.detail == NotifyInferior || xevent.xfocus.detail == NotifyPointer) {
if (xevent->xfocus.detail == NotifyInferior || xevent->xfocus.detail == NotifyPointer) {
/* We still have focus if a child gets focus. We also don't
care about the position of the pointer when the keyboard
focus changed. */
@@ -917,20 +910,20 @@ X11_DispatchEvent(_THIS)
/* Key press? */
case KeyPress:{
KeyCode keycode = xevent.xkey.keycode;
KeyCode keycode = xevent->xkey.keycode;
KeySym keysym = NoSymbol;
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
Status status = 0;
SDL_bool handled_by_ime = SDL_FALSE;
#ifdef DEBUG_XEVENTS
printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent->xkey.keycode);
#endif
#if 1
if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
int min_keycode, max_keycode;
X11_XDisplayKeycodes(display, &min_keycode, &max_keycode);
keysym = X11_KeyCodeToSym(_this, keycode, xevent.xkey.state >> 13);
keysym = X11_KeyCodeToSym(_this, keycode, xevent->xkey.state >> 13);
fprintf(stderr,
"The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL forums/mailing list <https://discourse.libsdl.org/> X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).\n",
keycode, keycode - min_keycode, keysym,
@@ -941,13 +934,13 @@ X11_DispatchEvent(_THIS)
SDL_zeroa(text);
#ifdef X_HAVE_UTF8_STRING
if (data->ic) {
X11_Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text),
X11_Xutf8LookupString(data->ic, &xevent->xkey, text, sizeof(text),
&keysym, &status);
} else {
X11_XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
X11_XLookupString(&xevent->xkey, text, sizeof(text), &keysym, NULL);
}
#else
X11_XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
X11_XLookupString(&xevent->xkey, text, sizeof(text), &keysym, NULL);
#endif
#ifdef SDL_USE_IME
@@ -957,7 +950,7 @@ X11_DispatchEvent(_THIS)
#endif
if (!handled_by_ime) {
/* Don't send the key if it looks like a duplicate of a filtered key sent by an IME */
if (xevent.xkey.keycode != videodata->filter_code || xevent.xkey.time != videodata->filter_time) {
if (xevent->xkey.keycode != videodata->filter_code || xevent->xkey.time != videodata->filter_time) {
SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
}
if(*text) {
@@ -965,18 +958,18 @@ X11_DispatchEvent(_THIS)
}
}
X11_UpdateUserTime(data, xevent.xkey.time);
X11_UpdateUserTime(data, xevent->xkey.time);
}
break;
/* Key release? */
case KeyRelease:{
KeyCode keycode = xevent.xkey.keycode;
KeyCode keycode = xevent->xkey.keycode;
#ifdef DEBUG_XEVENTS
printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent->xkey.keycode);
#endif
if (X11_KeyRepeat(display, &xevent)) {
if (X11_KeyRepeat(display, xevent)) {
/* We're about to get a repeated key down, ignore the key up */
break;
}
@@ -992,8 +985,8 @@ X11_DispatchEvent(_THIS)
printf("window %p: UnmapNotify!\n", data);
#endif
if (X11_XCheckIfEvent(display, &ev, &isReparentNotify, (XPointer)&xevent.xunmap)) {
X11_XCheckIfEvent(display, &ev, &isMapNotify, (XPointer)&xevent.xunmap);
if (X11_XCheckIfEvent(display, &ev, &isReparentNotify, (XPointer)&xevent->xunmap)) {
X11_XCheckIfEvent(display, &ev, &isMapNotify, (XPointer)&xevent->xunmap);
} else {
X11_DispatchUnmapNotify(data);
}
@@ -1013,27 +1006,27 @@ X11_DispatchEvent(_THIS)
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);
xevent->xconfigure.x, xevent->xconfigure.y,
xevent->xconfigure.width, xevent->xconfigure.height);
#endif
/* Real configure notify events are relative to the parent, synthetic events are absolute. */
if (!xevent.xconfigure.send_event) {
if (!xevent->xconfigure.send_event) {
unsigned int NumChildren;
Window ChildReturn, Root, Parent;
Window * Children;
/* Translate these coodinates back to relative to root */
X11_XQueryTree(data->videodata->display, xevent.xconfigure.window, &Root, &Parent, &Children, &NumChildren);
X11_XTranslateCoordinates(xevent.xconfigure.display,
Parent, DefaultRootWindow(xevent.xconfigure.display),
xevent.xconfigure.x, xevent.xconfigure.y,
&xevent.xconfigure.x, &xevent.xconfigure.y,
X11_XQueryTree(data->videodata->display, xevent->xconfigure.window, &Root, &Parent, &Children, &NumChildren);
X11_XTranslateCoordinates(xevent->xconfigure.display,
Parent, DefaultRootWindow(xevent->xconfigure.display),
xevent->xconfigure.x, xevent->xconfigure.y,
&xevent->xconfigure.x, &xevent->xconfigure.y,
&ChildReturn);
}
if (xevent.xconfigure.x != data->last_xconfigure.x ||
xevent.xconfigure.y != data->last_xconfigure.y) {
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);
xevent->xconfigure.x, xevent->xconfigure.y);
#ifdef SDL_USE_IME
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
/* Update IME candidate list position */
@@ -1041,13 +1034,13 @@ X11_DispatchEvent(_THIS)
}
#endif
}
if (xevent.xconfigure.width != data->last_xconfigure.width ||
xevent.xconfigure.height != data->last_xconfigure.height) {
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);
xevent->xconfigure.width,
xevent->xconfigure.height);
}
data->last_xconfigure = xevent.xconfigure;
data->last_xconfigure = xevent->xconfigure;
}
break;
@@ -1056,11 +1049,11 @@ X11_DispatchEvent(_THIS)
static int xdnd_version=0;
if (xevent.xclient.message_type == videodata->XdndEnter) {
if (xevent->xclient.message_type == videodata->XdndEnter) {
SDL_bool use_list = xevent.xclient.data.l[1] & 1;
data->xdnd_source = xevent.xclient.data.l[0];
xdnd_version = (xevent.xclient.data.l[1] >> 24);
SDL_bool use_list = xevent->xclient.data.l[1] & 1;
data->xdnd_source = xevent->xclient.data.l[0];
xdnd_version = (xevent->xclient.data.l[1] >> 24);
#ifdef DEBUG_XEVENTS
printf("XID of source window : %ld\n", data->xdnd_source);
printf("Protocol version to use : %d\n", xdnd_version);
@@ -1076,15 +1069,15 @@ X11_DispatchEvent(_THIS)
X11_XFree(p.data);
} else {
/* pick from list of three */
data->xdnd_req = X11_PickTargetFromAtoms(display, xevent.xclient.data.l[2], xevent.xclient.data.l[3], xevent.xclient.data.l[4]);
data->xdnd_req = X11_PickTargetFromAtoms(display, xevent->xclient.data.l[2], xevent->xclient.data.l[3], xevent->xclient.data.l[4]);
}
}
else if (xevent.xclient.message_type == videodata->XdndPosition) {
else if (xevent->xclient.message_type == videodata->XdndPosition) {
#ifdef DEBUG_XEVENTS
Atom act= videodata->XdndActionCopy;
if(xdnd_version >= 2) {
act = xevent.xclient.data.l[4];
act = xevent->xclient.data.l[4];
}
printf("Action requested by user is : %s\n", X11_XGetAtomName(display , act));
#endif
@@ -1093,8 +1086,8 @@ X11_DispatchEvent(_THIS)
/* reply with status */
memset(&m, 0, sizeof(XClientMessageEvent));
m.type = ClientMessage;
m.display = xevent.xclient.display;
m.window = xevent.xclient.data.l[0];
m.display = xevent->xclient.display;
m.window = xevent->xclient.data.l[0];
m.message_type = videodata->XdndStatus;
m.format=32;
m.data.l[0] = data->xwindow;
@@ -1103,47 +1096,47 @@ X11_DispatchEvent(_THIS)
m.data.l[3] = 0;
m.data.l[4] = videodata->XdndActionCopy; /* we only accept copying anyway */
X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
X11_XSendEvent(display, xevent->xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
X11_XFlush(display);
}
else if(xevent.xclient.message_type == videodata->XdndDrop) {
else if(xevent->xclient.message_type == videodata->XdndDrop) {
if (data->xdnd_req == None) {
/* say again - not interested! */
memset(&m, 0, sizeof(XClientMessageEvent));
m.type = ClientMessage;
m.display = xevent.xclient.display;
m.window = xevent.xclient.data.l[0];
m.display = xevent->xclient.display;
m.window = xevent->xclient.data.l[0];
m.message_type = videodata->XdndFinished;
m.format=32;
m.data.l[0] = data->xwindow;
m.data.l[1] = 0;
m.data.l[2] = None; /* fail! */
X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
X11_XSendEvent(display, xevent->xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
} else {
/* convert */
if(xdnd_version >= 1) {
X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, xevent.xclient.data.l[2]);
X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, xevent->xclient.data.l[2]);
} else {
X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, CurrentTime);
}
}
}
else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
(xevent.xclient.format == 32) &&
(xevent.xclient.data.l[0] == videodata->_NET_WM_PING)) {
else 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;
X11_XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
xevent->xclient.window = root;
X11_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)) {
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);
@@ -1151,9 +1144,9 @@ X11_DispatchEvent(_THIS)
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
break;
}
else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
(xevent.xclient.format == 32) &&
(xevent.xclient.data.l[0] == videodata->WM_TAKE_FOCUS)) {
else if ((xevent->xclient.message_type == videodata->WM_PROTOCOLS) &&
(xevent->xclient.format == 32) &&
(xevent->xclient.data.l[0] == videodata->WM_TAKE_FOCUS)) {
#ifdef DEBUG_XEVENTS
printf("window %p: WM_TAKE_FOCUS\n", data);
@@ -1167,7 +1160,7 @@ X11_DispatchEvent(_THIS)
/* Do we need to refresh ourselves? */
case Expose:{
#ifdef DEBUG_XEVENTS
printf("window %p: Expose (count = %d)\n", data, xevent.xexpose.count);
printf("window %p: Expose (count = %d)\n", data, xevent->xexpose.count);
#endif
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
}
@@ -1177,10 +1170,10 @@ X11_DispatchEvent(_THIS)
SDL_Mouse *mouse = SDL_GetMouse();
if(!mouse->relative_mode || mouse->relative_mode_warp) {
#ifdef DEBUG_MOTION
printf("window %p: X11 motion: %d,%d\n", data, xevent.xmotion.x, xevent.xmotion.y);
printf("window %p: X11 motion: %d,%d\n", data, xevent->xmotion.x, xevent->xmotion.y);
#endif
SDL_SendMouseMotion(data->window, 0, 0, xevent.xmotion.x, xevent.xmotion.y);
SDL_SendMouseMotion(data->window, 0, 0, xevent->xmotion.x, xevent->xmotion.y);
}
}
break;
@@ -1188,15 +1181,15 @@ X11_DispatchEvent(_THIS)
case ButtonPress:{
int xticks = 0, yticks = 0;
#ifdef DEBUG_XEVENTS
printf("window %p: ButtonPress (X11 button = %d)\n", data, xevent.xbutton.button);
printf("window %p: ButtonPress (X11 button = %d)\n", data, xevent->xbutton.button);
#endif
if (X11_IsWheelEvent(display,&xevent,&xticks, &yticks)) {
if (X11_IsWheelEvent(display,xevent,&xticks, &yticks)) {
SDL_SendMouseWheel(data->window, 0, (float) xticks, (float) yticks, SDL_MOUSEWHEEL_NORMAL);
} else {
SDL_bool ignore_click = SDL_FALSE;
int button = xevent.xbutton.button;
int button = xevent->xbutton.button;
if(button == Button1) {
if (ProcessHitTest(_this, data, &xevent)) {
if (ProcessHitTest(_this, data, xevent)) {
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
break; /* don't pass this event on to app. */
}
@@ -1217,18 +1210,18 @@ X11_DispatchEvent(_THIS)
SDL_SendMouseButton(data->window, 0, SDL_PRESSED, button);
}
}
X11_UpdateUserTime(data, xevent.xbutton.time);
X11_UpdateUserTime(data, xevent->xbutton.time);
}
break;
case ButtonRelease:{
int button = xevent.xbutton.button;
int button = xevent->xbutton.button;
/* The X server sends a Release event for each Press for wheels. Ignore them. */
int xticks = 0, yticks = 0;
#ifdef DEBUG_XEVENTS
printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent.xbutton.button);
printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent->xbutton.button);
#endif
if (!X11_IsWheelEvent(display, &xevent, &xticks, &yticks)) {
if (!X11_IsWheelEvent(display, xevent, &xticks, &yticks)) {
if (button > 7) {
/* see explanation at case ButtonPress */
button -= (8-SDL_BUTTON_X1);
@@ -1245,13 +1238,13 @@ X11_DispatchEvent(_THIS)
Atom real_type;
unsigned long items_read, items_left;
char *name = X11_XGetAtomName(display, xevent.xproperty.atom);
char *name = X11_XGetAtomName(display, xevent->xproperty.atom);
if (name) {
printf("window %p: PropertyNotify: %s %s time=%lu\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed", xevent.xproperty.time);
printf("window %p: PropertyNotify: %s %s time=%lu\n", data, name, (xevent->xproperty.state == PropertyDelete) ? "deleted" : "changed", xevent->xproperty.time);
X11_XFree(name);
}
status = X11_XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata);
status = X11_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;
@@ -1323,16 +1316,16 @@ X11_DispatchEvent(_THIS)
set _NET_WM_USER_TIME here, though. That's only for legit
user interaction with the window. */
if (!data->user_time) {
data->user_time = xevent.xproperty.time;
data->user_time = xevent->xproperty.time;
}
if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) {
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.
*/
const Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
const Uint32 flags = X11_GetNetWMState(_this, xevent->xproperty.window);
const Uint32 changed = flags ^ data->window->flags;
if ((changed & SDL_WINDOW_HIDDEN) || (changed & SDL_WINDOW_FULLSCREEN)) {
@@ -1350,7 +1343,7 @@ X11_DispatchEvent(_THIS)
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
}
}
} else if (xevent.xproperty.atom == videodata->XKLAVIER_STATE) {
} else if (xevent->xproperty.atom == videodata->XKLAVIER_STATE) {
/* Hack for Ubuntu 12.04 (etc) that doesn't send MappingNotify
events when the keyboard layout changes (for example,
changing from English to French on the menubar's keyboard
@@ -1359,7 +1352,7 @@ X11_DispatchEvent(_THIS)
right approach, but it seems to work. */
X11_UpdateKeymap(_this);
SDL_SendKeymapChangedEvent();
} else if (xevent.xproperty.atom == videodata->_NET_FRAME_EXTENTS) {
} else if (xevent->xproperty.atom == videodata->_NET_FRAME_EXTENTS) {
Atom type;
int format;
unsigned long nitems, bytes_after;
@@ -1382,10 +1375,10 @@ X11_DispatchEvent(_THIS)
break;
case SelectionNotify: {
Atom target = xevent.xselection.target;
Atom target = xevent->xselection.target;
#ifdef DEBUG_XEVENTS
printf("window %p: SelectionNotify (requestor = %ld, target = %ld)\n", data,
xevent.xselection.requestor, xevent.xselection.target);
xevent->xselection.requestor, xevent->xselection.target);
#endif
if (target == data->xdnd_req) {
/* read data */
@@ -1433,7 +1426,7 @@ X11_DispatchEvent(_THIS)
default:{
#ifdef DEBUG_XEVENTS
printf("window %p: Unhandled event %d\n", data, xevent.type);
printf("window %p: Unhandled event %d\n", data, xevent->type);
#endif
}
break;
@@ -1482,10 +1475,79 @@ X11_Pending(Display * display)
return (0);
}
void
X11_SendWakeupEvent(_THIS, SDL_Window *window)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
Display *req_display = data->request_display;
Window xwindow = ((SDL_WindowData *) window->driverdata)->xwindow;
XClientMessageEvent event;
memset(&event, 0, sizeof(XClientMessageEvent));
event.type = ClientMessage;
event.display = req_display;
event.send_event = True;
event.message_type = data->_SDL_WAKEUP;
event.format = 8;
X11_XSendEvent(req_display, xwindow, False, NoEventMask, (XEvent *) &event);
/* XSendEvent returns a status and it could be BadValue or BadWindow. If an
error happens it is an SDL's internal error and there is nothing we can do here. */
X11_XFlush(req_display);
}
int
X11_WaitEventTimeout(_THIS, int timeout)
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
Display *display;
XEvent xevent;
if (!videodata) {
return 0;
}
display = videodata->display;
SDL_zero(xevent);
if (timeout == 0) {
if (X11_Pending(display)) {
X11_XNextEvent(display, &xevent);
} else {
return 0;
}
} else if (timeout > 0) {
int display_fd = ConnectionNumber(display);
fd_set readset;
struct timeval tv_timeout;
FD_ZERO(&readset);
FD_SET(display_fd, &readset);
tv_timeout.tv_sec = (timeout / 1000);
tv_timeout.tv_usec = (timeout % 1000) * 1000;
if (select(display_fd + 1, &readset, NULL, NULL, &tv_timeout) > 0) {
X11_XNextEvent(display, &xevent);
} else {
return 0;
}
} else {
X11_XNextEvent(display, &xevent);
}
X11_DispatchEvent(_this, &xevent);
#ifdef SDL_USE_IME
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
SDL_IME_PumpEvents();
}
#endif
return 1;
}
void
X11_PumpEvents(_THIS)
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
XEvent xevent;
if (data->last_mode_change_deadline) {
if (SDL_TICKS_PASSED(SDL_GetTicks(), data->last_mode_change_deadline)) {
@@ -1508,9 +1570,12 @@ X11_PumpEvents(_THIS)
}
}
SDL_zero(xevent);
/* Keep processing pending events */
while (X11_Pending(data->display)) {
X11_DispatchEvent(_this);
X11_XNextEvent(data->display, &xevent);
X11_DispatchEvent(_this, &xevent);
}
#ifdef SDL_USE_IME

View File

@@ -24,6 +24,8 @@
#define SDL_x11events_h_
extern void X11_PumpEvents(_THIS);
extern int X11_WaitEventTimeout(_THIS, int timeout);
extern void X11_SendWakeupEvent(_THIS, SDL_Window *window);
extern void X11_SuspendScreenSaver(_THIS);
#endif /* SDL_x11events_h_ */

View File

@@ -345,6 +345,29 @@ SetXRandRDisplayName(Display *dpy, Atom EDID, char *name, const size_t namelen,
#endif
}
static int
GetXftDPI(Display* dpy)
{
char* xdefault_resource;
int xft_dpi, err;
xdefault_resource = X11_XGetDefault(dpy, "Xft", "dpi");
if(!xdefault_resource) {
return 0;
}
/*
* It's possible for SDL_atoi to call strtol, if it fails due to a
* overflow or an underflow, it will return LONG_MAX or LONG_MIN and set
* errno to ERANGE. So we need to check for this so we dont get crazy dpi
* values
*/
xft_dpi = SDL_atoi(xdefault_resource);
err = errno;
return err == ERANGE ? 0 : xft_dpi;
}
static int
X11_InitModes_XRandR(_THIS)
@@ -417,6 +440,7 @@ X11_InitModes_XRandR(_THIS)
RRMode modeID;
RRCrtc output_crtc;
XRRCrtcInfo *crtc;
int xft_dpi = 0;
/* The primary output _should_ always be sorted first, but just in case... */
if ((looking_for_primary && (res->outputs[output] != primary)) ||
@@ -471,6 +495,14 @@ X11_InitModes_XRandR(_THIS)
displaydata->hdpi = display_mm_width ? (((float) mode.w) * 25.4f / display_mm_width) : 0.0f;
displaydata->vdpi = display_mm_height ? (((float) mode.h) * 25.4f / display_mm_height) : 0.0f;
displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
/* if xft dpi is available we will use this over xrandr */
xft_dpi = GetXftDPI(dpy);
if(xft_dpi > 0) {
displaydata->hdpi = (float)xft_dpi;
displaydata->vdpi = (float)xft_dpi;
}
displaydata->scanline_pad = scanline_pad;
displaydata->x = display_x;
displaydata->y = display_y;

View File

@@ -138,6 +138,7 @@ SDL_X11_SYM(int,XWarpPointer,(Display* a,Window b,Window c,int d,int e,unsigned
SDL_X11_SYM(int,XWindowEvent,(Display* a,Window b,long c,XEvent* d),(a,b,c,d),return)
SDL_X11_SYM(Status,XWithdrawWindow,(Display* a,Window b,int c),(a,b,c),return)
SDL_X11_SYM(VisualID,XVisualIDFromVisual,(Visual* a),(a),return)
SDL_X11_SYM(char*,XGetDefault,(Display* a,char* b, char* c),(a,b,c),return)
#if SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY
SDL_X11_SYM(XExtDisplayInfo*,XextAddDisplay,(XExtensionInfo* a,Display* b,_Xconst char* c,XExtensionHooks* d,int e,XPointer f),(a,b,c,d,e,f),return)
#else
@@ -276,6 +277,8 @@ SDL_X11_MODULE(XINPUT2)
SDL_X11_SYM(XIDeviceInfo*,XIQueryDevice,(Display *a,int b,int *c),(a,b,c),return)
SDL_X11_SYM(void,XIFreeDeviceInfo,(XIDeviceInfo *a),(a),)
SDL_X11_SYM(int,XISelectEvents,(Display *a,Window b,XIEventMask *c,int d),(a,b,c,d),return)
SDL_X11_SYM(int,XIGrabTouchBegin,(Display *a,int b,Window c,int d,XIEventMask *e,int f,XIGrabModifiers *g),(a,b,c,d,e,f,g),return)
SDL_X11_SYM(int,XIUngrabTouchBegin, (Display *a,int b,Window c, int d,XIGrabModifiers *e),(a, b, c, d, e),return)
SDL_X11_SYM(Status,XIQueryVersion,(Display *a,int *b,int *c),(a,b,c),return)
SDL_X11_SYM(XIEventMask*,XIGetSelectedEvents,(Display *a,Window b,int *c),(a,b,c),return)
#endif

View File

@@ -105,7 +105,13 @@ X11_DeleteDevice(SDL_VideoDevice * device)
X11_XSetErrorHandler(orig_x11_errhandler);
X11_XCloseDisplay(data->display);
}
if (data->request_display) {
X11_XCloseDisplay(data->request_display);
}
SDL_free(data->windowlist);
if (device->wakeup_lock) {
SDL_DestroyMutex(device->wakeup_lock);
}
SDL_free(device->driverdata);
SDL_free(device);
@@ -178,10 +184,22 @@ X11_CreateDevice(int devindex)
return NULL;
}
device->driverdata = data;
device->wakeup_lock = SDL_CreateMutex();
data->global_mouse_changed = SDL_TRUE;
data->display = x11_display;
data->request_display = X11_XOpenDisplay(display);
if (data->request_display == NULL) {
X11_XCloseDisplay(data->display);
SDL_free(device->driverdata);
SDL_free(device);
SDL_X11_UnloadSymbols();
return NULL;
}
device->wakeup_lock = SDL_CreateMutex();
#ifdef X11_DEBUG
X11_XSynchronize(data->display, True);
#endif
@@ -201,6 +219,8 @@ X11_CreateDevice(int devindex)
device->SetDisplayMode = X11_SetDisplayMode;
device->SuspendScreenSaver = X11_SuspendScreenSaver;
device->PumpEvents = X11_PumpEvents;
device->WaitEventTimeout = X11_WaitEventTimeout;
device->SendWakeupEvent = X11_SendWakeupEvent;
device->CreateSDLWindow = X11_CreateWindow;
device->CreateSDLWindowFrom = X11_CreateWindowFrom;
@@ -234,6 +254,7 @@ X11_CreateDevice(int devindex)
device->GetWindowWMInfo = X11_GetWindowWMInfo;
device->SetWindowHitTest = X11_SetWindowHitTest;
device->AcceptDragAndDrop = X11_AcceptDragAndDrop;
device->FlashWindow = X11_FlashWindow;
device->shape_driver.CreateShaper = X11_CreateShaper;
device->shape_driver.SetWindowShape = X11_SetWindowShape;
@@ -403,6 +424,7 @@ X11_VideoInit(_THIS)
GET_ATOM(_NET_WM_USER_TIME);
GET_ATOM(_NET_ACTIVE_WINDOW);
GET_ATOM(_NET_FRAME_EXTENTS);
GET_ATOM(_SDL_WAKEUP);
GET_ATOM(UTF8_STRING);
GET_ATOM(PRIMARY);
GET_ATOM(XdndEnter);

View File

@@ -75,6 +75,7 @@
typedef struct SDL_VideoData
{
Display *display;
Display *request_display;
char *classname;
pid_t pid;
XIM im;
@@ -111,6 +112,7 @@ typedef struct SDL_VideoData
Atom _NET_WM_USER_TIME;
Atom _NET_ACTIVE_WINDOW;
Atom _NET_FRAME_EXTENTS;
Atom _SDL_WAKEUP;
Atom UTF8_STRING;
Atom PRIMARY;
Atom XdndEnter;

View File

@@ -372,6 +372,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
SDL_DisplayData *displaydata =
(SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
const SDL_bool force_override_redirect = SDL_GetHintBoolean(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, SDL_FALSE);
SDL_WindowData *windowdata;
Display *display = data->display;
int screen = displaydata->screen;
@@ -444,7 +445,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
depth = displaydata->depth;
}
xattr.override_redirect = ((window->flags & SDL_WINDOW_TOOLTIP) || (window->flags & SDL_WINDOW_POPUP_MENU)) ? True : False;
xattr.override_redirect = ((window->flags & SDL_WINDOW_TOOLTIP) || (window->flags & SDL_WINDOW_POPUP_MENU) || force_override_redirect) ? True : False;
xattr.backing_store = NotUseful;
xattr.background_pixmap = None;
xattr.border_pixel = 0;
@@ -725,38 +726,24 @@ X11_SetWindowTitle(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
XTextProperty titleprop;
Status status;
const char *title = window->title ? window->title : "";
char *title_locale = NULL;
#ifdef X_HAVE_UTF8_STRING
Atom UTF8_STRING = data->videodata->UTF8_STRING;
Atom _NET_WM_NAME = data->videodata->_NET_WM_NAME;
#endif
title_locale = SDL_iconv_utf8_locale(title);
if (!title_locale) {
SDL_OutOfMemory();
return;
}
status = X11_XChangeProperty(display, data->xwindow, _NET_WM_NAME, UTF8_STRING, 8, 0, (const unsigned char *) title, strlen(title));
status = X11_XStringListToTextProperty(&title_locale, 1, &titleprop);
SDL_free(title_locale);
if (status) {
X11_XSetTextProperty(display, data->xwindow, &titleprop, XA_WM_NAME);
X11_XFree(titleprop.value);
}
#ifdef X_HAVE_UTF8_STRING
if (SDL_X11_HAVE_UTF8) {
status = X11_Xutf8TextListToTextProperty(display, (char **) &title, 1,
XUTF8StringStyle, &titleprop);
if (status == Success) {
X11_XSetTextProperty(display, data->xwindow, &titleprop,
_NET_WM_NAME);
X11_XFree(titleprop.value);
if (status != Success) {
char *x11_error = NULL;
char x11_error_locale[256];
if (X11_XGetErrorText(display, status, x11_error_locale, sizeof(x11_error_locale)) == Success)
{
x11_error = SDL_iconv_string("UTF-8", "", x11_error_locale, SDL_strlen(x11_error_locale)+1);
SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Error when setting X11 window title to %s: %s\n", title, x11_error);
SDL_free(x11_error);
}
}
#endif
X11_XFlush(display);
}
@@ -1637,6 +1624,8 @@ X11_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
}
}
X11_Xinput2GrabTouch(_this, window);
/* Raise the window if we grab the mouse */
X11_XRaiseWindow(display, data->xwindow);
@@ -1646,6 +1635,8 @@ X11_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
}
} else {
X11_XUngrabPointer(display, CurrentTime);
X11_Xinput2UngrabTouch(_this, window);
}
X11_XSync(display, False);
}
@@ -1757,6 +1748,30 @@ X11_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept)
}
}
int
X11_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
Display *display = data->videodata->display;
Atom demands_attention = X11_XInternAtom(display, "_NET_WM_STATE_DEMANDS_ATTENTION", 1);
Atom wm_state = X11_XInternAtom(display, "_NET_WM_STATE", 1);
XEvent snd_ntfy_ev = {ClientMessage};
snd_ntfy_ev.xclient.window = data->xwindow;
snd_ntfy_ev.xclient.message_type = wm_state;
snd_ntfy_ev.xclient.format = 32;
snd_ntfy_ev.xclient.data.l[0] = 1; /* _NET_WM_STATE_ADD */
snd_ntfy_ev.xclient.data.l[1] = demands_attention;
snd_ntfy_ev.xclient.data.l[2] = 0;
snd_ntfy_ev.xclient.data.l[3] = 1; /* normal application */
snd_ntfy_ev.xclient.data.l[4] = 0;
X11_XSendEvent(display, RootWindow(display, displaydata->screen), False, SubstructureNotifyMask | SubstructureRedirectMask, &snd_ntfy_ev);
return 0;
}
#endif /* SDL_VIDEO_DRIVER_X11 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -107,6 +107,7 @@ extern SDL_bool X11_GetWindowWMInfo(_THIS, SDL_Window * window,
struct SDL_SysWMinfo *info);
extern int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
extern void X11_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept);
extern int X11_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count);
#endif /* SDL_x11window_h_ */

View File

@@ -343,6 +343,50 @@ X11_Xinput2IsMultitouchSupported()
#endif
}
void
X11_Xinput2GrabTouch(_THIS, SDL_Window *window)
{
#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
unsigned char mask[4] = { 0, 0, 0, 0 };
XIGrabModifiers mods;
XIEventMask eventmask;
mods.modifiers = XIAnyModifier;
mods.status = 0;
eventmask.deviceid = XIAllDevices;
eventmask.mask_len = sizeof(mask);
eventmask.mask = mask;
XISetMask(eventmask.mask, XI_TouchBegin);
XISetMask(eventmask.mask, XI_TouchUpdate);
XISetMask(eventmask.mask, XI_TouchEnd);
XISetMask(eventmask.mask, XI_Motion);
X11_XIGrabTouchBegin(display, XIAllDevices, data->xwindow, True, &eventmask, 1, &mods);
#endif
}
void
X11_Xinput2UngrabTouch(_THIS, SDL_Window *window)
{
#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
XIGrabModifiers mods;
mods.modifiers = XIAnyModifier;
mods.status = 0;
X11_XIUngrabTouchBegin(display, XIAllDevices, data->xwindow, 1, &mods);
#endif
}
#endif /* SDL_VIDEO_DRIVER_X11 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -36,6 +36,8 @@ extern int X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *
extern int X11_Xinput2IsInitialized(void);
extern int X11_Xinput2IsMultitouchSupported(void);
extern void X11_Xinput2SelectTouch(_THIS, SDL_Window *window);
extern void X11_Xinput2GrabTouch(_THIS, SDL_Window *window);
extern void X11_Xinput2UngrabTouch(_THIS, SDL_Window *window);
#endif /* SDL_x11xinput2_h_ */