25 #include "precompiled.h"
27 #if OS_LINUX || OS_BSD
41 #define Cursor X__Cursor
46 #include <Xcursor/Xcursor.h>
49 #include "SDL_syswm.h"
55 static Display *g_SDL_Display;
56 static Window g_SDL_Window;
57 #if !SDL_VERSION_ATLEAST(1, 3, 0)
58 static void (*g_Lock_Display)(void);
59 static void (*g_Unlock_Display)(void);
61 static wchar_t *selection_data=NULL;
62 static size_t selection_size=0;
68 Display* disp = XOpenDisplay(0);
72 int screen = XDefaultScreen(disp);
86 *xres = XDisplayWidth(disp, screen);
88 *yres = XDisplayHeight(disp, screen);
90 *bpp = XDefaultDepth(disp, screen);
100 Display* disp = XOpenDisplay(0);
104 int screen = XDefaultScreen(disp);
106 width_mm = XDisplayWidthMM(disp, screen);
107 height_mm = XDisplayHeightMM(disp, screen);
116 static bool get_wminfo(SDL_SysWMinfo& wminfo)
118 SDL_VERSION(&wminfo.version);
120 #if SDL_VERSION_ATLEAST(2, 0, 0)
123 const int ret = SDL_GetWMInfo(&wminfo);
135 debug_printf(L
"SDL_GetWMInfo is not implemented on this platform\n");
139 debug_printf(L
"SDL_GetWMInfo returned an unknown value: %d\n", ret);
178 Display *disp=XOpenDisplay(NULL);
184 Atom selSource=XInternAtom(disp,
"CLIPBOARD", False);
186 Window selOwner=XGetSelectionOwner(disp, selSource);
192 selSource=XA_PRIMARY;
193 selOwner=XGetSelectionOwner(disp, selSource);
195 if(selOwner != None) {
196 Atom pty=XInternAtom(disp,
"SelectionPropertyTemp", False);
197 XConvertSelection(disp, selSource, XA_STRING, pty, selOwner, CurrentTime);
201 int format=0, result=0;
202 unsigned long len=0, bytes_left=0, dummy=0;
207 result = XGetWindowProperty (disp, selOwner, pty,
215 if(result != Success)
216 debug_printf(L
"clipboard_get: result: %d type:%lu len:%lu format:%d bytes_left:%lu\n",
217 result, type, len, format, bytes_left);
218 if(result == Success && bytes_left > 0)
220 result = XGetWindowProperty (disp, selOwner,
221 pty, 0, bytes_left, 0,
222 AnyPropertyType, &type, &format,
223 &len, &dummy, &data);
225 if(result == Success)
227 debug_printf(L
"clipboard_get: XGetWindowProperty succeeded, returning data\n");
228 debug_printf(L
"clipboard_get: data was: \"%hs\", type was %lu, XA_STRING atom is %lu\n", data, type, XA_STRING);
230 if(type == XA_STRING)
232 wchar_t *ret=(
wchar_t *)malloc((bytes_left+1)*
sizeof(
wchar_t));
233 std::copy(data, data+bytes_left, ret);
241 debug_printf(L
"clipboard_get: XGetWindowProperty failed!\n");
263 #if SDL_VERSION_ATLEAST(1, 3, 0)
266 int clipboard_filter(
const SDL_Event* event)
271 if(event->
type != SDL_SYSWMEVENT || !selection_data)
277 #if SDL_VERSION_ATLEAST(1, 3, 0)
278 XEvent* xevent = &
event->syswm.msg->msg.x11.event;
280 XEvent* xevent = &
event->syswm.msg->event.xevent;
282 switch(xevent->type) {
285 case SelectionRequest: {
286 XSelectionRequestEvent *req;
289 req = &xevent->xselectionrequest;
290 sevent.xselection.type = SelectionNotify;
291 sevent.xselection.display = req->display;
292 sevent.xselection.selection = req->selection;
293 sevent.xselection.target = req->target;
294 sevent.xselection.property = None;
295 sevent.xselection.requestor = req->requestor;
296 sevent.xselection.time = req->time;
299 if(req->target == XA_STRING)
301 size_t size = wcslen(selection_data);
302 u8* buf = (
u8*)alloca(size);
304 for(
size_t i = 0; i < size; i++)
306 buf[i] = selection_data[i] < 0x100 ? selection_data[i] :
'?';
309 XChangeProperty(g_SDL_Display, req->requestor, req->property,
310 sevent.xselection.target, 8, PropModeReplace,
312 sevent.xselection.property = req->property;
315 XSendEvent(g_SDL_Display, req->requestor, False, 0, &sevent);
316 XSync(g_SDL_Display, False);
328 Status x11_clipboard_init()
335 if(info.subsystem == SDL_SYSWM_X11)
337 g_SDL_Display = info.info.x11.display;
338 g_SDL_Window = info.info.x11.window;
339 #if !SDL_VERSION_ATLEAST(1, 3, 0)
340 g_Lock_Display = info.info.x11.lock_func;
341 g_Unlock_Display = info.info.x11.unlock_func;
346 #if SDL_VERSION_ATLEAST(1, 3, 0)
347 SDL_SetEventFilter(clipboard_filter, NULL);
349 SDL_SetEventFilter(clipboard_filter);
375 ONCE(x11_clipboard_init());
381 free(selection_data);
382 selection_data = NULL;
385 selection_size = (wcslen(str)+1)*
sizeof(
wchar_t);
386 selection_data = (
wchar_t *)malloc(selection_size);
387 wcscpy(selection_data, str);
389 #if !SDL_VERSION_ATLEAST(1, 3, 0)
395 Atom clipboard_atom = XInternAtom(g_SDL_Display,
"CLIPBOARD", False);
396 XSetSelectionOwner(g_SDL_Display, clipboard_atom, g_SDL_Window, CurrentTime);
397 XSetSelectionOwner(g_SDL_Display, XA_PRIMARY, g_SDL_Window, CurrentTime);
399 #if !SDL_VERSION_ATLEAST(1, 3, 0)
404 XSync(g_SDL_Display, False);
410 struct sys_cursor_impl
416 static XcursorPixel cursor_pixel_to_x11_format(
const XcursorPixel& bgra_pixel)
418 BOOST_STATIC_ASSERT(
sizeof(XcursorPixel) == 4 *
sizeof(
u8));
420 u8* dst =
reinterpret_cast<u8*
>(&ret);
421 const u8* b =
reinterpret_cast<const u8*
>(&bgra_pixel);
424 for(
size_t i = 0; i < 3; ++i)
425 *dst++ = (b[i]) * a / 255;
432 debug_printf(L
"sys_cursor_create: using Xcursor to create %d x %d cursor\n", w, h);
433 XcursorImage* image = XcursorImageCreate(w, h);
437 const XcursorPixel* bgra_img_begin =
reinterpret_cast<XcursorPixel*
>(bgra_img);
438 std::transform(bgra_img_begin, bgra_img_begin + (w*h), image->pixels,
439 cursor_pixel_to_x11_format);
443 SDL_SysWMinfo wminfo;
444 if(!get_wminfo(wminfo))
447 sys_cursor_impl* impl =
new sys_cursor_impl;
449 impl->cursor = XcursorImageLoadCursor(wminfo.info.x11.display, image);
450 if(impl->cursor == None)
460 static u8 transparent_bgra[] = { 0x0, 0x0, 0x0, 0x0 };
462 return sys_cursor_create(1, 1, static_cast<void*>(transparent_bgra), 0, 0, cursor);
473 SDL_SysWMinfo wminfo;
474 if(!get_wminfo(wminfo))
477 if(wminfo.subsystem != SDL_SYSWM_X11)
480 #if !SDL_VERSION_ATLEAST(1, 3, 0)
481 wminfo.info.x11.lock_func();
487 if(wminfo.info.x11.window)
488 window = wminfo.info.x11.window;
491 #if !SDL_VERSION_ATLEAST(1, 3, 0)
494 window = wminfo.info.x11.fswindow;
500 XDefineCursor(wminfo.info.x11.display, window,
501 static_cast<sys_cursor_impl*>(cursor)->cursor);
502 #if !SDL_VERSION_ATLEAST(1, 3, 0)
503 wminfo.info.x11.unlock_func();
507 XSync(wminfo.info.x11.display, False);
522 sys_cursor_impl* impl =
static_cast<sys_cursor_impl*
>(cursor);
524 XcursorImageDestroy(impl->image);
526 SDL_SysWMinfo wminfo;
527 if(!get_wminfo(wminfo))
529 XFreeCursor(wminfo.info.x11.display, impl->cursor);
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
int SDL_ShowCursor(int toggle)
Status sys_clipboard_set(const wchar_t *text)
Status sys_cursor_create(int w, int h, void *bgra_img, int hx, int hy, sys_cursor *cursor)
Create a cursor from the given color image.
Status sys_cursor_reset()
reset any cached cursor data.
LIB_API Status GetVideoMode(int *xres, int *yres, int *bpp, int *freq)
(useful for choosing a new video mode)
Status sys_clipboard_free(wchar_t *copy)
Status sys_cursor_create_empty(sys_cursor *cursor)
Create a transparent cursor (used to hide the system cursor).
#define ONCE(ONCE_code__)
execute the code passed as a parameter only the first time this is reached.
i64 Status
Error handling system.
LIB_API Status GetMonitorSize(int &width_mm, int &height_mm)
(useful for determining aspect ratio)
wchar_t * sys_clipboard_get()
#define WARN_RETURN(status)
Status sys_cursor_set(sys_cursor cursor)
override the current system cursor.
Status sys_cursor_free(sys_cursor cursor)
destroy the indicated cursor and frees its resources.
void debug_printf(const wchar_t *fmt,...)
write a formatted string to the debug channel, subject to filtering (see below).