Merge lp:~brandontschaefer/libsdl/add-mir-support-v2 into lp:libsdl

Proposed by Brandon Schaefer
Status: Superseded
Proposed branch: lp:~brandontschaefer/libsdl/add-mir-support-v2
Merge into: lp:libsdl
Diff against target: 458056 lines
To merge this branch: bzr merge lp:~brandontschaefer/libsdl/add-mir-support-v2
Reviewer Review Type Date Requested Status
VCS imports Pending
Review via email: mp+260771@code.launchpad.net

This proposal has been superseded by a proposal from 2015-06-01.

Commit message

Add support for Mir under libsdl1.2 for only i386/amd64 (no gles1/2 support in libsdl1.2).

Description of the change

Add support for Mir under libsdl1.2 for only i386/amd64 (no gles1/2 support in libsdl1.2).

This patch adds support for Software rendering and Opengl on the desktop for mir in sdl1.2.

*Note* This is written for the new libmir 0.13.1. This uses new event 2.0 and buffering system.

To post a comment you must log in.
53. By Brandon Schaefer

* I should not ignore key_repeat rather, if we are not a KEY_UP action
  assume its a KEY_DOWN event.

Unmerged revisions

53. By Brandon Schaefer

* I should not ignore key_repeat rather, if we are not a KEY_UP action
  assume its a KEY_DOWN event.

52. By Brandon Schaefer

* Make sure we depend on the version of mir this is written for

51. By Brandon Schaefer

* Add video driver backend support for Mir (i386/amd64)

50. By Steve Langasek

* Merge from Debian unstable, remaining changes:
  - Drop directfb support. This is the only package which still pulls the
    rather sizable directfb into a standard installation, and we never
    actually used/supported it anyway.
* Dropped changes, included in Debian:
  - Drop tslib support which is in universe.
  - debian/patches/sdl-check-for-SDL_VIDEO_X11_BACKINGSTORE.patch:
    Restore old backingstore behavior to prevent tearing.

49. By Steve Langasek

* Restore accidentally-clobbered changes from 1.2.15-8ubuntu2.

[ Timo Jyrinki ]
* debian/patches/sdl-check-for-SDL_VIDEO_X11_BACKINGSTORE.patch:
  - Restore old backingstore behavior to prevent tearing
    (LP: #1280665)

48. By Steve Langasek

* Merge from Debian unstable, remaining changes:
  - Drop directfb support. This is the only package which still pulls the
    rather sizable directfb into a standard installation, and we never
    actually used/supported it anyway.
  - Drop tslib support which is in universe.
* Dropped changes, included in Debian:
  - fix dh_autoreconf handling.

47. By Timo Jyrinki

* debian/patches/sdl-check-for-SDL_VIDEO_X11_BACKINGSTORE.patch:
  - Restore old backingstore behavior to prevent tearing
    (LP: #1280665)

46. By Steve Langasek

* Merge from Debian unstable, remaining changes:
  - Drop directfb support. This is the only package which still pulls the
    rather sizable directfb into a standard installation, and we never
    actually used/supported it anyway.
    --enable-video-directfb from confflags.
  - Drop tslib support which is in universe.
  - debian/rules, debian/patches/proper-autotools.patch: Fix wrong
    handling of dh_autoreconf that fails to ever re-libtoolize the
    package. Bypass calling autoheader, since configure.in isn't
    compatible with current version of autoheader.
* Dropped changes, merged in Debian:
  - drop the unused libsdl1.2debian-udeb package
  - Use dh_autotools-dev to update config.{sub,guess} for new ports.

45. By Steve Langasek

debian/rules, debian/patches/proper-autotools.patch: Fix wrong handling
of dh_autoreconf that fails to ever re-libtoolize the package. Bypass
calling autoheader, since configure.in isn't compatible with current
version of autoheader.

44. By Steve Langasek

releasing package libsdl1.2 version 1.2.15-5ubuntu3

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory '.pc'
2=== added file '.pc/.quilt_patches'
3--- .pc/.quilt_patches 1970-01-01 00:00:00 +0000
4+++ .pc/.quilt_patches 2015-06-01 21:40:05 +0000
5@@ -0,0 +1,1 @@
6+debian/patches
7
8=== added file '.pc/.quilt_series'
9--- .pc/.quilt_series 1970-01-01 00:00:00 +0000
10+++ .pc/.quilt_series 2015-06-01 21:40:05 +0000
11@@ -0,0 +1,1 @@
12+series
13
14=== added file '.pc/.version'
15--- .pc/.version 1970-01-01 00:00:00 +0000
16+++ .pc/.version 2015-06-01 21:40:05 +0000
17@@ -0,0 +1,1 @@
18+2
19
20=== added file '.pc/applied-patches'
21--- .pc/applied-patches 1970-01-01 00:00:00 +0000
22+++ .pc/applied-patches 2015-06-01 21:40:05 +0000
23@@ -0,0 +1,7 @@
24+x11_keytounicode.diff
25+dont_propagate_lpthread.diff
26+fix_build_joystick_freebsd.diff
27+fix_window_resizing.diff
28+fix_joystick_misc_axes.diff
29+sdl-check-for-SDL_VIDEO_X11_BACKINGSTORE.patch
30+mir-support.diff
31
32=== added directory '.pc/dont_propagate_lpthread.diff'
33=== added file '.pc/dont_propagate_lpthread.diff/sdl-config.in'
34--- .pc/dont_propagate_lpthread.diff/sdl-config.in 1970-01-01 00:00:00 +0000
35+++ .pc/dont_propagate_lpthread.diff/sdl-config.in 2015-06-01 21:40:05 +0000
36@@ -0,0 +1,60 @@
37+#!/bin/sh
38+
39+prefix=@prefix@
40+exec_prefix=@exec_prefix@
41+exec_prefix_set=no
42+libdir=@libdir@
43+
44+@ENABLE_STATIC_FALSE@usage="\
45+@ENABLE_STATIC_FALSE@Usage: sdl-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--cflags] [--libs]"
46+@ENABLE_STATIC_TRUE@usage="\
47+@ENABLE_STATIC_TRUE@Usage: sdl-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--cflags] [--libs] [--static-libs]"
48+
49+if test $# -eq 0; then
50+ echo "${usage}" 1>&2
51+ exit 1
52+fi
53+
54+while test $# -gt 0; do
55+ case "$1" in
56+ -*=*) optarg=`echo "$1" | LC_ALL="C" sed 's/[-_a-zA-Z0-9]*=//'` ;;
57+ *) optarg= ;;
58+ esac
59+
60+ case $1 in
61+ --prefix=*)
62+ prefix=$optarg
63+ if test $exec_prefix_set = no ; then
64+ exec_prefix=$optarg
65+ fi
66+ ;;
67+ --prefix)
68+ echo $prefix
69+ ;;
70+ --exec-prefix=*)
71+ exec_prefix=$optarg
72+ exec_prefix_set=yes
73+ ;;
74+ --exec-prefix)
75+ echo $exec_prefix
76+ ;;
77+ --version)
78+ echo @SDL_VERSION@
79+ ;;
80+ --cflags)
81+ echo -I@includedir@/SDL @SDL_CFLAGS@
82+ ;;
83+@ENABLE_SHARED_TRUE@ --libs)
84+@ENABLE_SHARED_TRUE@ echo -L@libdir@ @SDL_RLD_FLAGS@ @SDL_LIBS@
85+@ENABLE_SHARED_TRUE@ ;;
86+@ENABLE_STATIC_TRUE@@ENABLE_SHARED_TRUE@ --static-libs)
87+@ENABLE_STATIC_TRUE@@ENABLE_SHARED_FALSE@ --libs|--static-libs)
88+@ENABLE_STATIC_TRUE@ echo -L@libdir@ @SDL_RLD_FLAGS@ @SDL_STATIC_LIBS@
89+@ENABLE_STATIC_TRUE@ ;;
90+ *)
91+ echo "${usage}" 1>&2
92+ exit 1
93+ ;;
94+ esac
95+ shift
96+done
97
98=== added file '.pc/dont_propagate_lpthread.diff/sdl.pc.in'
99--- .pc/dont_propagate_lpthread.diff/sdl.pc.in 1970-01-01 00:00:00 +0000
100+++ .pc/dont_propagate_lpthread.diff/sdl.pc.in 2015-06-01 21:40:05 +0000
101@@ -0,0 +1,15 @@
102+# sdl pkg-config source file
103+
104+prefix=@prefix@
105+exec_prefix=@exec_prefix@
106+libdir=@libdir@
107+includedir=@includedir@
108+
109+Name: sdl
110+Description: Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer.
111+Version: @SDL_VERSION@
112+Requires:
113+Conflicts:
114+Libs: -L${libdir} @SDL_RLD_FLAGS@ @SDL_LIBS@
115+Libs.private: @SDL_STATIC_LIBS@
116+Cflags: -I${includedir}/SDL @SDL_CFLAGS@
117
118=== added directory '.pc/fix_build_joystick_freebsd.diff'
119=== added directory '.pc/fix_build_joystick_freebsd.diff/src'
120=== added directory '.pc/fix_build_joystick_freebsd.diff/src/joystick'
121=== added directory '.pc/fix_build_joystick_freebsd.diff/src/joystick/bsd'
122=== added file '.pc/fix_build_joystick_freebsd.diff/src/joystick/bsd/SDL_sysjoystick.c'
123--- .pc/fix_build_joystick_freebsd.diff/src/joystick/bsd/SDL_sysjoystick.c 1970-01-01 00:00:00 +0000
124+++ .pc/fix_build_joystick_freebsd.diff/src/joystick/bsd/SDL_sysjoystick.c 2015-06-01 21:40:05 +0000
125@@ -0,0 +1,608 @@
126+/*
127+ SDL - Simple DirectMedia Layer
128+ Copyright (C) 1997-2012 Sam Lantinga
129+
130+ This library is free software; you can redistribute it and/or
131+ modify it under the terms of the GNU Lesser General Public
132+ License as published by the Free Software Foundation; either
133+ version 2.1 of the License, or (at your option) any later version.
134+
135+ This library is distributed in the hope that it will be useful,
136+ but WITHOUT ANY WARRANTY; without even the implied warranty of
137+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
138+ Lesser General Public License for more details.
139+
140+ You should have received a copy of the GNU Lesser General Public
141+ License along with this library; if not, write to the Free Software
142+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
143+
144+ Sam Lantinga
145+ slouken@libsdl.org
146+*/
147+#include "SDL_config.h"
148+
149+#ifdef SDL_JOYSTICK_USBHID
150+
151+/*
152+ * Joystick driver for the uhid(4) interface found in OpenBSD,
153+ * NetBSD and FreeBSD.
154+ *
155+ * Maintainer: <vedge at csoft.org>
156+ */
157+
158+#include <sys/param.h>
159+
160+#include <unistd.h>
161+#include <fcntl.h>
162+#include <errno.h>
163+
164+#ifndef __FreeBSD_kernel_version
165+#define __FreeBSD_kernel_version __FreeBSD_version
166+#endif
167+
168+#if defined(HAVE_USB_H)
169+#include <usb.h>
170+#endif
171+#ifdef __DragonFly__
172+#include <bus/usb/usb.h>
173+#include <bus/usb/usbhid.h>
174+#else
175+#include <dev/usb/usb.h>
176+#include <dev/usb/usbhid.h>
177+#endif
178+
179+#if defined(HAVE_USBHID_H)
180+#include <usbhid.h>
181+#elif defined(HAVE_LIBUSB_H)
182+#include <libusb.h>
183+#elif defined(HAVE_LIBUSBHID_H)
184+#include <libusbhid.h>
185+#endif
186+
187+#if defined(__FREEBSD__) || defined(__FreeBSD_kernel__)
188+#ifndef __DragonFly__
189+#include <osreldate.h>
190+#endif
191+#if __FreeBSD_kernel_version > 800063
192+#include <dev/usb/usb_ioctl.h>
193+#endif
194+#include <sys/joystick.h>
195+#endif
196+
197+#if SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
198+#include <machine/joystick.h>
199+#endif
200+
201+#include "SDL_joystick.h"
202+#include "../SDL_sysjoystick.h"
203+#include "../SDL_joystick_c.h"
204+
205+#define MAX_UHID_JOYS 4
206+#define MAX_JOY_JOYS 2
207+#define MAX_JOYS (MAX_UHID_JOYS + MAX_JOY_JOYS)
208+
209+struct report {
210+#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)
211+ struct usb_gen_descriptor *buf; /* Buffer */
212+#else
213+ struct usb_ctl_report *buf; /* Buffer */
214+#endif
215+ size_t size; /* Buffer size */
216+ int rid; /* Report ID */
217+ enum {
218+ SREPORT_UNINIT,
219+ SREPORT_CLEAN,
220+ SREPORT_DIRTY
221+ } status;
222+};
223+
224+static struct {
225+ int uhid_report;
226+ hid_kind_t kind;
227+ const char *name;
228+} const repinfo[] = {
229+ { UHID_INPUT_REPORT, hid_input, "input" },
230+ { UHID_OUTPUT_REPORT, hid_output, "output" },
231+ { UHID_FEATURE_REPORT, hid_feature, "feature" }
232+};
233+
234+enum {
235+ REPORT_INPUT = 0,
236+ REPORT_OUTPUT = 1,
237+ REPORT_FEATURE = 2
238+};
239+
240+enum {
241+ JOYAXE_X,
242+ JOYAXE_Y,
243+ JOYAXE_Z,
244+ JOYAXE_SLIDER,
245+ JOYAXE_WHEEL,
246+ JOYAXE_RX,
247+ JOYAXE_RY,
248+ JOYAXE_RZ,
249+ JOYAXE_count
250+};
251+
252+struct joystick_hwdata {
253+ int fd;
254+ char *path;
255+ enum {
256+ BSDJOY_UHID, /* uhid(4) */
257+ BSDJOY_JOY /* joy(4) */
258+ } type;
259+ struct report_desc *repdesc;
260+ struct report inreport;
261+ int axis_map[JOYAXE_count]; /* map present JOYAXE_* to 0,1,..*/
262+ int x;
263+ int y;
264+ int xmin;
265+ int ymin;
266+ int xmax;
267+ int ymax;
268+};
269+
270+static char *joynames[MAX_JOYS];
271+static char *joydevnames[MAX_JOYS];
272+
273+static int report_alloc(struct report *, struct report_desc *, int);
274+static void report_free(struct report *);
275+
276+#if defined(USBHID_UCR_DATA) || defined(__FreeBSD_kernel__)
277+#define REP_BUF_DATA(rep) ((rep)->buf->ucr_data)
278+#elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063))
279+#define REP_BUF_DATA(rep) ((rep)->buf->ugd_data)
280+#else
281+#define REP_BUF_DATA(rep) ((rep)->buf->data)
282+#endif
283+
284+int
285+SDL_SYS_JoystickInit(void)
286+{
287+ char s[16];
288+ int i, fd;
289+
290+ SDL_numjoysticks = 0;
291+
292+ SDL_memset(joynames, 0, sizeof(joynames));
293+ SDL_memset(joydevnames, 0, sizeof(joydevnames));
294+
295+ for (i = 0; i < MAX_UHID_JOYS; i++) {
296+ SDL_Joystick nj;
297+
298+ SDL_snprintf(s, SDL_arraysize(s), "/dev/uhid%d", i);
299+
300+ nj.index = SDL_numjoysticks;
301+ joynames[nj.index] = strdup(s);
302+
303+ if (SDL_SYS_JoystickOpen(&nj) == 0) {
304+ SDL_SYS_JoystickClose(&nj);
305+ SDL_numjoysticks++;
306+ } else {
307+ SDL_free(joynames[nj.index]);
308+ joynames[nj.index] = NULL;
309+ }
310+ }
311+ for (i = 0; i < MAX_JOY_JOYS; i++) {
312+ SDL_snprintf(s, SDL_arraysize(s), "/dev/joy%d", i);
313+ fd = open(s, O_RDONLY);
314+ if (fd != -1) {
315+ joynames[SDL_numjoysticks++] = strdup(s);
316+ close(fd);
317+ }
318+ }
319+
320+ /* Read the default USB HID usage table. */
321+ hid_init(NULL);
322+
323+ return (SDL_numjoysticks);
324+}
325+
326+const char *
327+SDL_SYS_JoystickName(int index)
328+{
329+ if (joydevnames[index] != NULL) {
330+ return (joydevnames[index]);
331+ }
332+ return (joynames[index]);
333+}
334+
335+static int
336+usage_to_joyaxe(unsigned usage)
337+{
338+ int joyaxe;
339+ switch (usage) {
340+ case HUG_X:
341+ joyaxe = JOYAXE_X; break;
342+ case HUG_Y:
343+ joyaxe = JOYAXE_Y; break;
344+ case HUG_Z:
345+ joyaxe = JOYAXE_Z; break;
346+ case HUG_SLIDER:
347+ joyaxe = JOYAXE_SLIDER; break;
348+ case HUG_WHEEL:
349+ joyaxe = JOYAXE_WHEEL; break;
350+ case HUG_RX:
351+ joyaxe = JOYAXE_RX; break;
352+ case HUG_RY:
353+ joyaxe = JOYAXE_RY; break;
354+ case HUG_RZ:
355+ joyaxe = JOYAXE_RZ; break;
356+ default:
357+ joyaxe = -1;
358+ }
359+ return joyaxe;
360+}
361+
362+static unsigned
363+hatval_to_sdl(Sint32 hatval)
364+{
365+ static const unsigned hat_dir_map[8] = {
366+ SDL_HAT_UP, SDL_HAT_RIGHTUP, SDL_HAT_RIGHT, SDL_HAT_RIGHTDOWN,
367+ SDL_HAT_DOWN, SDL_HAT_LEFTDOWN, SDL_HAT_LEFT, SDL_HAT_LEFTUP
368+ };
369+ unsigned result;
370+ if ((hatval & 7) == hatval)
371+ result = hat_dir_map[hatval];
372+ else
373+ result = SDL_HAT_CENTERED;
374+ return result;
375+}
376+
377+
378+int
379+SDL_SYS_JoystickOpen(SDL_Joystick *joy)
380+{
381+ char *path = joynames[joy->index];
382+ struct joystick_hwdata *hw;
383+ struct hid_item hitem;
384+ struct hid_data *hdata;
385+ struct report *rep;
386+ int fd;
387+ int i;
388+
389+ fd = open(path, O_RDONLY);
390+ if (fd == -1) {
391+ SDL_SetError("%s: %s", path, strerror(errno));
392+ return (-1);
393+ }
394+
395+ hw = (struct joystick_hwdata *)SDL_malloc(sizeof(struct joystick_hwdata));
396+ if (hw == NULL) {
397+ SDL_OutOfMemory();
398+ close(fd);
399+ return (-1);
400+ }
401+ joy->hwdata = hw;
402+ hw->fd = fd;
403+ hw->path = strdup(path);
404+ hw->x = 0;
405+ hw->y = 0;
406+ hw->xmin = 0xffff;
407+ hw->ymin = 0xffff;
408+ hw->xmax = 0;
409+ hw->ymax = 0;
410+ if (! SDL_strncmp(path, "/dev/joy", 8)) {
411+ hw->type = BSDJOY_JOY;
412+ joy->naxes = 2;
413+ joy->nbuttons = 2;
414+ joy->nhats = 0;
415+ joy->nballs = 0;
416+ joydevnames[joy->index] = strdup("Gameport joystick");
417+ goto usbend;
418+ } else {
419+ hw->type = BSDJOY_UHID;
420+ }
421+
422+ {
423+ int ax;
424+ for (ax = 0; ax < JOYAXE_count; ax++)
425+ hw->axis_map[ax] = -1;
426+ }
427+ hw->repdesc = hid_get_report_desc(fd);
428+ if (hw->repdesc == NULL) {
429+ SDL_SetError("%s: USB_GET_REPORT_DESC: %s", hw->path,
430+ strerror(errno));
431+ goto usberr;
432+ }
433+ rep = &hw->inreport;
434+#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__)
435+ rep->rid = hid_get_report_id(fd);
436+ if (rep->rid < 0) {
437+#else
438+ if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
439+#endif
440+ rep->rid = -1; /* XXX */
441+ }
442+ if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
443+ goto usberr;
444+ }
445+ if (rep->size <= 0) {
446+ SDL_SetError("%s: Input report descriptor has invalid length",
447+ hw->path);
448+ goto usberr;
449+ }
450+
451+#if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
452+ hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
453+#else
454+ hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
455+#endif
456+ if (hdata == NULL) {
457+ SDL_SetError("%s: Cannot start HID parser", hw->path);
458+ goto usberr;
459+ }
460+ joy->naxes = 0;
461+ joy->nbuttons = 0;
462+ joy->nhats = 0;
463+ joy->nballs = 0;
464+ for (i=0; i<JOYAXE_count; i++)
465+ hw->axis_map[i] = -1;
466+
467+ while (hid_get_item(hdata, &hitem) > 0) {
468+ char *sp;
469+ const char *s;
470+
471+ switch (hitem.kind) {
472+ case hid_collection:
473+ switch (HID_PAGE(hitem.usage)) {
474+ case HUP_GENERIC_DESKTOP:
475+ switch (HID_USAGE(hitem.usage)) {
476+ case HUG_JOYSTICK:
477+ case HUG_GAME_PAD:
478+ s = hid_usage_in_page(hitem.usage);
479+ sp = SDL_malloc(SDL_strlen(s) + 5);
480+ SDL_snprintf(sp, SDL_strlen(s) + 5, "%s (%d)", s,
481+ joy->index);
482+ joydevnames[joy->index] = sp;
483+ }
484+ }
485+ break;
486+ case hid_input:
487+ switch (HID_PAGE(hitem.usage)) {
488+ case HUP_GENERIC_DESKTOP: {
489+ unsigned usage = HID_USAGE(hitem.usage);
490+ int joyaxe = usage_to_joyaxe(usage);
491+ if (joyaxe >= 0) {
492+ hw->axis_map[joyaxe] = 1;
493+ } else if (usage == HUG_HAT_SWITCH) {
494+ joy->nhats++;
495+ }
496+ break;
497+ }
498+ case HUP_BUTTON:
499+ joy->nbuttons++;
500+ break;
501+ default:
502+ break;
503+ }
504+ break;
505+ default:
506+ break;
507+ }
508+ }
509+ hid_end_parse(hdata);
510+ for (i=0; i<JOYAXE_count; i++)
511+ if (hw->axis_map[i] > 0)
512+ hw->axis_map[i] = joy->naxes++;
513+
514+usbend:
515+ /* The poll blocks the event thread. */
516+ fcntl(fd, F_SETFL, O_NONBLOCK);
517+
518+ return (0);
519+usberr:
520+ close(hw->fd);
521+ SDL_free(hw->path);
522+ SDL_free(hw);
523+ return (-1);
524+}
525+
526+void
527+SDL_SYS_JoystickUpdate(SDL_Joystick *joy)
528+{
529+ struct hid_item hitem;
530+ struct hid_data *hdata;
531+ struct report *rep;
532+ int nbutton, naxe = -1;
533+ Sint32 v;
534+
535+#if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__)
536+ struct joystick gameport;
537+
538+ if (joy->hwdata->type == BSDJOY_JOY) {
539+ if (read(joy->hwdata->fd, &gameport, sizeof gameport) != sizeof gameport)
540+ return;
541+ if (abs(joy->hwdata->x - gameport.x) > 8) {
542+ joy->hwdata->x = gameport.x;
543+ if (joy->hwdata->x < joy->hwdata->xmin) {
544+ joy->hwdata->xmin = joy->hwdata->x;
545+ }
546+ if (joy->hwdata->x > joy->hwdata->xmax) {
547+ joy->hwdata->xmax = joy->hwdata->x;
548+ }
549+ if (joy->hwdata->xmin == joy->hwdata->xmax) {
550+ joy->hwdata->xmin--;
551+ joy->hwdata->xmax++;
552+ }
553+ v = (Sint32)joy->hwdata->x;
554+ v -= (joy->hwdata->xmax + joy->hwdata->xmin + 1)/2;
555+ v *= 32768/((joy->hwdata->xmax - joy->hwdata->xmin + 1)/2);
556+ SDL_PrivateJoystickAxis(joy, 0, v);
557+ }
558+ if (abs(joy->hwdata->y - gameport.y) > 8) {
559+ joy->hwdata->y = gameport.y;
560+ if (joy->hwdata->y < joy->hwdata->ymin) {
561+ joy->hwdata->ymin = joy->hwdata->y;
562+ }
563+ if (joy->hwdata->y > joy->hwdata->ymax) {
564+ joy->hwdata->ymax = joy->hwdata->y;
565+ }
566+ if (joy->hwdata->ymin == joy->hwdata->ymax) {
567+ joy->hwdata->ymin--;
568+ joy->hwdata->ymax++;
569+ }
570+ v = (Sint32)joy->hwdata->y;
571+ v -= (joy->hwdata->ymax + joy->hwdata->ymin + 1)/2;
572+ v *= 32768/((joy->hwdata->ymax - joy->hwdata->ymin + 1)/2);
573+ SDL_PrivateJoystickAxis(joy, 1, v);
574+ }
575+ if (gameport.b1 != joy->buttons[0]) {
576+ SDL_PrivateJoystickButton(joy, 0, gameport.b1);
577+ }
578+ if (gameport.b2 != joy->buttons[1]) {
579+ SDL_PrivateJoystickButton(joy, 1, gameport.b2);
580+ }
581+ return;
582+ }
583+#endif /* defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H */
584+
585+ rep = &joy->hwdata->inreport;
586+
587+ if (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) != rep->size) {
588+ return;
589+ }
590+#if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
591+ hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
592+#else
593+ hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
594+#endif
595+ if (hdata == NULL) {
596+ fprintf(stderr, "%s: Cannot start HID parser\n",
597+ joy->hwdata->path);
598+ return;
599+ }
600+
601+ for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
602+ switch (hitem.kind) {
603+ case hid_input:
604+ switch (HID_PAGE(hitem.usage)) {
605+ case HUP_GENERIC_DESKTOP: {
606+ unsigned usage = HID_USAGE(hitem.usage);
607+ int joyaxe = usage_to_joyaxe(usage);
608+ if (joyaxe >= 0) {
609+ naxe = joy->hwdata->axis_map[joyaxe];
610+ /* scaleaxe */
611+ v = (Sint32)hid_get_data(REP_BUF_DATA(rep),
612+ &hitem);
613+ v -= (hitem.logical_maximum + hitem.logical_minimum + 1)/2;
614+ v *= 32768/((hitem.logical_maximum - hitem.logical_minimum + 1)/2);
615+ if (v != joy->axes[naxe]) {
616+ SDL_PrivateJoystickAxis(joy, naxe, v);
617+ }
618+ } else if (usage == HUG_HAT_SWITCH) {
619+ v = (Sint32)hid_get_data(REP_BUF_DATA(rep),
620+ &hitem);
621+ SDL_PrivateJoystickHat(joy, 0,
622+ hatval_to_sdl(v)-hitem.logical_minimum);
623+ }
624+ break;
625+ }
626+ case HUP_BUTTON:
627+ v = (Sint32)hid_get_data(REP_BUF_DATA(rep),
628+ &hitem);
629+ if (joy->buttons[nbutton] != v) {
630+ SDL_PrivateJoystickButton(joy,
631+ nbutton, v);
632+ }
633+ nbutton++;
634+ break;
635+ default:
636+ continue;
637+ }
638+ break;
639+ default:
640+ break;
641+ }
642+ }
643+ hid_end_parse(hdata);
644+
645+ return;
646+}
647+
648+/* Function to close a joystick after use */
649+void
650+SDL_SYS_JoystickClose(SDL_Joystick *joy)
651+{
652+ if (SDL_strncmp(joy->hwdata->path, "/dev/joy", 8)) {
653+ report_free(&joy->hwdata->inreport);
654+ hid_dispose_report_desc(joy->hwdata->repdesc);
655+ }
656+ close(joy->hwdata->fd);
657+ SDL_free(joy->hwdata->path);
658+ SDL_free(joy->hwdata);
659+
660+ return;
661+}
662+
663+void
664+SDL_SYS_JoystickQuit(void)
665+{
666+ int i;
667+
668+ for (i = 0; i < MAX_JOYS; i++) {
669+ if (joynames[i] != NULL)
670+ SDL_free(joynames[i]);
671+ if (joydevnames[i] != NULL)
672+ SDL_free(joydevnames[i]);
673+ }
674+
675+ return;
676+}
677+
678+static int
679+report_alloc(struct report *r, struct report_desc *rd, int repind)
680+{
681+ int len;
682+
683+#ifdef __DragonFly__
684+ len = hid_report_size(rd, r->rid, repinfo[repind].kind);
685+#elif __FREEBSD__
686+# if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__)
687+# if (__FreeBSD_kernel_version <= 500111)
688+ len = hid_report_size(rd, r->rid, repinfo[repind].kind);
689+# else
690+ len = hid_report_size(rd, repinfo[repind].kind, r->rid);
691+# endif
692+# else
693+ len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
694+# endif
695+#else
696+# ifdef USBHID_NEW
697+ len = hid_report_size(rd, repinfo[repind].kind, r->rid);
698+# else
699+ len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
700+# endif
701+#endif
702+
703+ if (len < 0) {
704+ SDL_SetError("Negative HID report size");
705+ return (-1);
706+ }
707+ r->size = len;
708+
709+ if (r->size > 0) {
710+ r->buf = SDL_malloc(sizeof(*r->buf) - sizeof(REP_BUF_DATA(r)) +
711+ r->size);
712+ if (r->buf == NULL) {
713+ SDL_OutOfMemory();
714+ return (-1);
715+ }
716+ } else {
717+ r->buf = NULL;
718+ }
719+
720+ r->status = SREPORT_CLEAN;
721+ return (0);
722+}
723+
724+static void
725+report_free(struct report *r)
726+{
727+ if (r->buf != NULL) {
728+ SDL_free(r->buf);
729+ }
730+ r->status = SREPORT_UNINIT;
731+}
732+
733+#endif /* SDL_JOYSTICK_USBHID */
734
735=== added directory '.pc/fix_joystick_misc_axes.diff'
736=== added directory '.pc/fix_joystick_misc_axes.diff/src'
737=== added directory '.pc/fix_joystick_misc_axes.diff/src/joystick'
738=== added directory '.pc/fix_joystick_misc_axes.diff/src/joystick/linux'
739=== added file '.pc/fix_joystick_misc_axes.diff/src/joystick/linux/SDL_sysjoystick.c'
740--- .pc/fix_joystick_misc_axes.diff/src/joystick/linux/SDL_sysjoystick.c 1970-01-01 00:00:00 +0000
741+++ .pc/fix_joystick_misc_axes.diff/src/joystick/linux/SDL_sysjoystick.c 2015-06-01 21:40:05 +0000
742@@ -0,0 +1,1218 @@
743+/*
744+ SDL - Simple DirectMedia Layer
745+ Copyright (C) 1997-2012 Sam Lantinga
746+
747+ This library is free software; you can redistribute it and/or
748+ modify it under the terms of the GNU Lesser General Public
749+ License as published by the Free Software Foundation; either
750+ version 2.1 of the License, or (at your option) any later version.
751+
752+ This library is distributed in the hope that it will be useful,
753+ but WITHOUT ANY WARRANTY; without even the implied warranty of
754+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
755+ Lesser General Public License for more details.
756+
757+ You should have received a copy of the GNU Lesser General Public
758+ License along with this library; if not, write to the Free Software
759+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
760+
761+ Sam Lantinga
762+ slouken@libsdl.org
763+*/
764+#include "SDL_config.h"
765+
766+#ifdef SDL_JOYSTICK_LINUX
767+
768+/* This is the system specific header for the SDL joystick API */
769+
770+#include <sys/stat.h>
771+#include <unistd.h>
772+#include <fcntl.h>
773+#include <sys/ioctl.h>
774+#include <limits.h> /* For the definition of PATH_MAX */
775+#include <linux/joystick.h>
776+#if SDL_INPUT_LINUXEV
777+#include <linux/input.h>
778+#endif
779+
780+#include "SDL_joystick.h"
781+#include "../SDL_sysjoystick.h"
782+#include "../SDL_joystick_c.h"
783+
784+/* Special joystick configurations */
785+static struct {
786+ const char *name;
787+ int naxes;
788+ int nhats;
789+ int nballs;
790+} special_joysticks[] = {
791+ { "MadCatz Panther XL", 3, 2, 1 }, /* We don't handle rudder (axis 8) */
792+ { "SideWinder Precision Pro", 4, 1, 0 },
793+ { "SideWinder 3D Pro", 4, 1, 0 },
794+ { "Microsoft SideWinder 3D Pro", 4, 1, 0 },
795+ { "Microsoft SideWinder Precision Pro", 4, 1, 0 },
796+ { "Microsoft SideWinder Dual Strike USB version 1.0", 2, 1, 0 },
797+ { "WingMan Interceptor", 3, 3, 0 },
798+ { "WingMan Extreme Digital 3D", 4, 1, 0 },
799+ { "Microsoft SideWinder Precision 2 Joystick", 4, 1, 0 },
800+ { "Logitech Inc. WingMan Extreme Digital 3D", 4, 1, 0 },
801+ { "Saitek Saitek X45", 6, 1, 0 }
802+};
803+
804+/* It looks like newer kernels have the logical mapping at the driver level */
805+#define NO_LOGICAL_JOYSTICKS
806+
807+#ifndef NO_LOGICAL_JOYSTICKS
808+
809+/*
810+ Some USB HIDs show up as a single joystick even though they actually
811+ control 2 or more joysticks.
812+*/
813+/*
814+ This code handles the MP-8800 (Quad) and MP-8866 (Dual), which can
815+ be identified by their transparent blue design. It's quite trivial
816+ to add other joysticks with similar quirky behavior.
817+ -id
818+*/
819+
820+struct joystick_logical_mapping {
821+ int njoy;
822+ int nthing;
823+};
824+
825+/*
826+ {logical joy, logical axis},
827+ {logical joy, logical hat},
828+ {logical joy, logical ball},
829+ {logical joy, logical button}
830+*/
831+
832+static struct joystick_logical_mapping mp88xx_1_logical_axismap[] = {
833+ {0,0},{0,1},{0,2},{0,3},{0,4},{0,5}
834+};
835+static struct joystick_logical_mapping mp88xx_1_logical_buttonmap[] = {
836+ {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}
837+};
838+
839+static struct joystick_logical_mapping mp88xx_2_logical_axismap[] = {
840+ {0,0},{0,1},{0,2},{1,0},{1,1},{0,3},
841+ {1,2},{1,3},{0,4},{0,5},{1,4},{1,5}
842+};
843+static struct joystick_logical_mapping mp88xx_2_logical_buttonmap[] = {
844+ {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11},
845+ {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}
846+};
847+
848+static struct joystick_logical_mapping mp88xx_3_logical_axismap[] = {
849+ {0,0},{0,1},{0,2},{1,0},{1,1},{0,3},
850+ {1,2},{1,3},{2,0},{2,1},{2,2},{2,3},
851+ {0,4},{0,5},{1,4},{1,5},{2,4},{2,5}
852+};
853+static struct joystick_logical_mapping mp88xx_3_logical_buttonmap[] = {
854+ {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11},
855+ {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11},
856+ {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11}
857+};
858+
859+static struct joystick_logical_mapping mp88xx_4_logical_axismap[] = {
860+ {0,0},{0,1},{0,2},{1,0},{1,1},{0,3},
861+ {1,2},{1,3},{2,0},{2,1},{2,2},{2,3},
862+ {3,0},{3,1},{3,2},{3,3},{0,4},{0,5},
863+ {1,4},{1,5},{2,4},{2,5},{3,4},{3,5}
864+};
865+static struct joystick_logical_mapping mp88xx_4_logical_buttonmap[] = {
866+ {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11},
867+ {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11},
868+ {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11},
869+ {3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{3,8},{3,9},{3,10},{3,11}
870+};
871+
872+struct joystick_logical_layout {
873+ int naxes;
874+ int nhats;
875+ int nballs;
876+ int nbuttons;
877+};
878+
879+static struct joystick_logical_layout mp88xx_1_logical_layout[] = {
880+ {6, 0, 0, 12}
881+};
882+static struct joystick_logical_layout mp88xx_2_logical_layout[] = {
883+ {6, 0, 0, 12},
884+ {6, 0, 0, 12}
885+};
886+static struct joystick_logical_layout mp88xx_3_logical_layout[] = {
887+ {6, 0, 0, 12},
888+ {6, 0, 0, 12},
889+ {6, 0, 0, 12}
890+};
891+static struct joystick_logical_layout mp88xx_4_logical_layout[] = {
892+ {6, 0, 0, 12},
893+ {6, 0, 0, 12},
894+ {6, 0, 0, 12},
895+ {6, 0, 0, 12}
896+};
897+
898+/*
899+ This array sets up a means of mapping a single physical joystick to
900+ multiple logical joysticks. (djm)
901+
902+ njoys
903+ the number of logical joysticks
904+
905+ layouts
906+ an array of layout structures, one to describe each logical joystick
907+
908+ axes, hats, balls, buttons
909+ arrays that map a physical thingy to a logical thingy
910+ */
911+struct joystick_logicalmap {
912+ const char *name;
913+ int nbuttons;
914+ int njoys;
915+ struct joystick_logical_layout *layout;
916+ struct joystick_logical_mapping *axismap;
917+ struct joystick_logical_mapping *hatmap;
918+ struct joystick_logical_mapping *ballmap;
919+ struct joystick_logical_mapping *buttonmap;
920+};
921+
922+static struct joystick_logicalmap joystick_logicalmap[] = {
923+ {
924+ "WiseGroup.,Ltd MP-8866 Dual USB Joypad",
925+ 12,
926+ 1,
927+ mp88xx_1_logical_layout,
928+ mp88xx_1_logical_axismap,
929+ NULL,
930+ NULL,
931+ mp88xx_1_logical_buttonmap
932+ },
933+ {
934+ "WiseGroup.,Ltd MP-8866 Dual USB Joypad",
935+ 24,
936+ 2,
937+ mp88xx_2_logical_layout,
938+ mp88xx_2_logical_axismap,
939+ NULL,
940+ NULL,
941+ mp88xx_2_logical_buttonmap
942+ },
943+ {
944+ "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
945+ 12,
946+ 1,
947+ mp88xx_1_logical_layout,
948+ mp88xx_1_logical_axismap,
949+ NULL,
950+ NULL,
951+ mp88xx_1_logical_buttonmap
952+ },
953+ {
954+ "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
955+ 24,
956+ 2,
957+ mp88xx_2_logical_layout,
958+ mp88xx_2_logical_axismap,
959+ NULL,
960+ NULL,
961+ mp88xx_2_logical_buttonmap
962+ },
963+ {
964+ "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
965+ 36,
966+ 3,
967+ mp88xx_3_logical_layout,
968+ mp88xx_3_logical_axismap,
969+ NULL,
970+ NULL,
971+ mp88xx_3_logical_buttonmap
972+ },
973+ {
974+ "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
975+ 48,
976+ 4,
977+ mp88xx_4_logical_layout,
978+ mp88xx_4_logical_axismap,
979+ NULL,
980+ NULL,
981+ mp88xx_4_logical_buttonmap
982+ }
983+};
984+
985+/* find the head of a linked list, given a point in it
986+ */
987+#define SDL_joylist_head(i, start)\
988+ for(i = start; SDL_joylist[i].fname == NULL;) i = SDL_joylist[i].prev;
989+
990+#define SDL_logical_joydecl(d) d
991+
992+
993+#else
994+
995+#define SDL_logical_joydecl(d)
996+
997+#endif /* USE_LOGICAL_JOYSTICKS */
998+
999+/* The maximum number of joysticks we'll detect */
1000+#define MAX_JOYSTICKS 32
1001+
1002+/* A list of available joysticks */
1003+static struct
1004+{
1005+ char* fname;
1006+#ifndef NO_LOGICAL_JOYSTICKS
1007+ SDL_Joystick* joy;
1008+ struct joystick_logicalmap* map;
1009+ int prev;
1010+ int next;
1011+ int logicalno;
1012+#endif /* USE_LOGICAL_JOYSTICKS */
1013+} SDL_joylist[MAX_JOYSTICKS];
1014+
1015+
1016+/* The private structure used to keep track of a joystick */
1017+struct joystick_hwdata {
1018+ int fd;
1019+ /* The current linux joystick driver maps hats to two axes */
1020+ struct hwdata_hat {
1021+ int axis[2];
1022+ } *hats;
1023+ /* The current linux joystick driver maps balls to two axes */
1024+ struct hwdata_ball {
1025+ int axis[2];
1026+ } *balls;
1027+
1028+ /* Support for the Linux 2.4 unified input interface */
1029+#if SDL_INPUT_LINUXEV
1030+ SDL_bool is_hid;
1031+ Uint8 key_map[KEY_MAX-BTN_MISC];
1032+ Uint8 abs_map[ABS_MAX];
1033+ struct axis_correct {
1034+ int used;
1035+ int coef[3];
1036+ } abs_correct[ABS_MAX];
1037+#endif
1038+};
1039+
1040+
1041+#ifndef NO_LOGICAL_JOYSTICKS
1042+
1043+static int CountLogicalJoysticks(int max)
1044+{
1045+ register int i, j, k, ret, prev;
1046+ const char* name;
1047+ int nbuttons, fd;
1048+ unsigned char n;
1049+
1050+ ret = 0;
1051+
1052+ for(i = 0; i < max; i++) {
1053+ name = SDL_SYS_JoystickName(i);
1054+
1055+ fd = open(SDL_joylist[i].fname, O_RDONLY, 0);
1056+ if ( fd >= 0 ) {
1057+ if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) {
1058+ nbuttons = -1;
1059+ } else {
1060+ nbuttons = n;
1061+ }
1062+ close(fd);
1063+ }
1064+ else {
1065+ nbuttons=-1;
1066+ }
1067+
1068+ if (name) {
1069+ for(j = 0; j < SDL_arraysize(joystick_logicalmap); j++) {
1070+ if (!SDL_strcmp(name, joystick_logicalmap[j].name) && (nbuttons==-1 || nbuttons==joystick_logicalmap[j].nbuttons)) {
1071+ prev = i;
1072+ SDL_joylist[prev].map = &(joystick_logicalmap[j]);
1073+
1074+ for(k = 1; k < joystick_logicalmap[j].njoys; k++) {
1075+ SDL_joylist[prev].next = max + ret;
1076+ SDL_joylist[max+ret].prev = prev;
1077+
1078+ prev = max + ret;
1079+ SDL_joylist[prev].logicalno = k;
1080+ SDL_joylist[prev].map = &(joystick_logicalmap[j]);
1081+ ret++;
1082+ }
1083+
1084+ break;
1085+ }
1086+ }
1087+ }
1088+ }
1089+
1090+ return ret;
1091+}
1092+
1093+static void LogicalSuffix(int logicalno, char* namebuf, int len)
1094+{
1095+ register int slen;
1096+ const static char suffixs[] =
1097+ "01020304050607080910111213141516171819"
1098+ "20212223242526272829303132";
1099+ const char* suffix;
1100+ slen = SDL_strlen(namebuf);
1101+ suffix = NULL;
1102+
1103+ if (logicalno*2<sizeof(suffixs))
1104+ suffix = suffixs + (logicalno*2);
1105+
1106+ if (slen + 4 < len && suffix) {
1107+ namebuf[slen++] = ' ';
1108+ namebuf[slen++] = '#';
1109+ namebuf[slen++] = suffix[0];
1110+ namebuf[slen++] = suffix[1];
1111+ namebuf[slen++] = 0;
1112+ }
1113+}
1114+
1115+#endif /* USE_LOGICAL_JOYSTICKS */
1116+
1117+#if SDL_INPUT_LINUXEV
1118+#define test_bit(nr, addr) \
1119+ (((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
1120+#define NBITS(x) ((((x)-1)/(sizeof(long) * 8))+1)
1121+
1122+static int EV_IsJoystick(int fd)
1123+{
1124+ unsigned long evbit[NBITS(EV_MAX)] = { 0 };
1125+ unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
1126+ unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
1127+
1128+ if ( (ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
1129+ (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
1130+ (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0) ) {
1131+ return(0);
1132+ }
1133+ if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) &&
1134+ test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit) &&
1135+ (test_bit(BTN_TRIGGER, keybit) || test_bit(BTN_A, keybit) || test_bit(BTN_1, keybit)))) return 0;
1136+ return(1);
1137+}
1138+
1139+#endif /* SDL_INPUT_LINUXEV */
1140+
1141+/* Function to scan the system for joysticks */
1142+int SDL_SYS_JoystickInit(void)
1143+{
1144+ /* The base path of the joystick devices */
1145+ const char *joydev_pattern[] = {
1146+#if SDL_INPUT_LINUXEV
1147+ "/dev/input/event%d",
1148+#endif
1149+ "/dev/input/js%d",
1150+ "/dev/js%d"
1151+ };
1152+ int numjoysticks;
1153+ int i, j;
1154+ int fd;
1155+ char path[PATH_MAX];
1156+ dev_t dev_nums[MAX_JOYSTICKS]; /* major/minor device numbers */
1157+ struct stat sb;
1158+ int n, duplicate;
1159+
1160+ numjoysticks = 0;
1161+
1162+ /* First see if the user specified one or more joysticks to use */
1163+ if ( SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL ) {
1164+ char *envcopy, *envpath, *delim;
1165+ envcopy = SDL_strdup(SDL_getenv("SDL_JOYSTICK_DEVICE"));
1166+ envpath = envcopy;
1167+ while ( envpath != NULL ) {
1168+ delim = SDL_strchr(envpath, ':');
1169+ if ( delim != NULL ) {
1170+ *delim++ = '\0';
1171+ }
1172+ if ( stat(envpath, &sb) == 0 ) {
1173+ fd = open(envpath, O_RDONLY, 0);
1174+ if ( fd >= 0 ) {
1175+ /* Assume the user knows what they're doing. */
1176+ SDL_joylist[numjoysticks].fname = SDL_strdup(envpath);
1177+ if ( SDL_joylist[numjoysticks].fname ) {
1178+ dev_nums[numjoysticks] = sb.st_rdev;
1179+ ++numjoysticks;
1180+ }
1181+ close(fd);
1182+ }
1183+ }
1184+ envpath = delim;
1185+ }
1186+ SDL_free(envcopy);
1187+ }
1188+
1189+ for ( i=0; i<SDL_arraysize(joydev_pattern); ++i ) {
1190+ for ( j=0; j < MAX_JOYSTICKS; ++j ) {
1191+ SDL_snprintf(path, SDL_arraysize(path), joydev_pattern[i], j);
1192+
1193+ /* rcg06302000 replaced access(F_OK) call with stat().
1194+ * stat() will fail if the file doesn't exist, so it's
1195+ * equivalent behaviour.
1196+ */
1197+ if ( stat(path, &sb) == 0 ) {
1198+ /* Check to make sure it's not already in list.
1199+ * This happens when we see a stick via symlink.
1200+ */
1201+ duplicate = 0;
1202+ for (n=0; (n<numjoysticks) && !duplicate; ++n) {
1203+ if ( sb.st_rdev == dev_nums[n] ) {
1204+ duplicate = 1;
1205+ }
1206+ }
1207+ if (duplicate) {
1208+ continue;
1209+ }
1210+
1211+ fd = open(path, O_RDONLY, 0);
1212+ if ( fd < 0 ) {
1213+ continue;
1214+ }
1215+#if SDL_INPUT_LINUXEV
1216+#ifdef DEBUG_INPUT_EVENTS
1217+ printf("Checking %s\n", path);
1218+#endif
1219+ if ( (i == 0) && ! EV_IsJoystick(fd) ) {
1220+ close(fd);
1221+ continue;
1222+ }
1223+#endif
1224+ close(fd);
1225+
1226+ /* We're fine, add this joystick */
1227+ SDL_joylist[numjoysticks].fname = SDL_strdup(path);
1228+ if ( SDL_joylist[numjoysticks].fname ) {
1229+ dev_nums[numjoysticks] = sb.st_rdev;
1230+ ++numjoysticks;
1231+ }
1232+ }
1233+ }
1234+
1235+#if SDL_INPUT_LINUXEV
1236+ /* This is a special case...
1237+ If the event devices are valid then the joystick devices
1238+ will be duplicates but without extra information about their
1239+ hats or balls. Unfortunately, the event devices can't
1240+ currently be calibrated, so it's a win-lose situation.
1241+ So : /dev/input/eventX = /dev/input/jsY = /dev/jsY
1242+ */
1243+ if ( (i == 0) && (numjoysticks > 0) )
1244+ break;
1245+#endif
1246+ }
1247+#ifndef NO_LOGICAL_JOYSTICKS
1248+ numjoysticks += CountLogicalJoysticks(numjoysticks);
1249+#endif
1250+
1251+ return(numjoysticks);
1252+}
1253+
1254+/* Function to get the device-dependent name of a joystick */
1255+const char *SDL_SYS_JoystickName(int index)
1256+{
1257+ int fd;
1258+ static char namebuf[128];
1259+ char *name;
1260+ SDL_logical_joydecl(int oindex = index);
1261+
1262+#ifndef NO_LOGICAL_JOYSTICKS
1263+ SDL_joylist_head(index, index);
1264+#endif
1265+ name = NULL;
1266+ fd = open(SDL_joylist[index].fname, O_RDONLY, 0);
1267+ if ( fd >= 0 ) {
1268+ if (
1269+#if SDL_INPUT_LINUXEV
1270+ (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) <= 0) &&
1271+#endif
1272+ (ioctl(fd, JSIOCGNAME(sizeof(namebuf)), namebuf) <= 0) ) {
1273+ name = SDL_joylist[index].fname;
1274+ } else {
1275+ name = namebuf;
1276+ }
1277+ close(fd);
1278+
1279+
1280+#ifndef NO_LOGICAL_JOYSTICKS
1281+ if (SDL_joylist[oindex].prev || SDL_joylist[oindex].next || index!=oindex)
1282+ {
1283+ LogicalSuffix(SDL_joylist[oindex].logicalno, namebuf, 128);
1284+ }
1285+#endif
1286+ }
1287+ return name;
1288+}
1289+
1290+static int allocate_hatdata(SDL_Joystick *joystick)
1291+{
1292+ int i;
1293+
1294+ joystick->hwdata->hats = (struct hwdata_hat *)SDL_malloc(
1295+ joystick->nhats * sizeof(struct hwdata_hat));
1296+ if ( joystick->hwdata->hats == NULL ) {
1297+ return(-1);
1298+ }
1299+ for ( i=0; i<joystick->nhats; ++i ) {
1300+ joystick->hwdata->hats[i].axis[0] = 1;
1301+ joystick->hwdata->hats[i].axis[1] = 1;
1302+ }
1303+ return(0);
1304+}
1305+
1306+static int allocate_balldata(SDL_Joystick *joystick)
1307+{
1308+ int i;
1309+
1310+ joystick->hwdata->balls = (struct hwdata_ball *)SDL_malloc(
1311+ joystick->nballs * sizeof(struct hwdata_ball));
1312+ if ( joystick->hwdata->balls == NULL ) {
1313+ return(-1);
1314+ }
1315+ for ( i=0; i<joystick->nballs; ++i ) {
1316+ joystick->hwdata->balls[i].axis[0] = 0;
1317+ joystick->hwdata->balls[i].axis[1] = 0;
1318+ }
1319+ return(0);
1320+}
1321+
1322+static SDL_bool JS_ConfigJoystick(SDL_Joystick *joystick, int fd)
1323+{
1324+ SDL_bool handled;
1325+ unsigned char n;
1326+ int tmp_naxes, tmp_nhats, tmp_nballs;
1327+ const char *name;
1328+ char *env, env_name[128];
1329+ int i;
1330+
1331+ handled = SDL_FALSE;
1332+
1333+ /* Default joystick device settings */
1334+ if ( ioctl(fd, JSIOCGAXES, &n) < 0 ) {
1335+ joystick->naxes = 2;
1336+ } else {
1337+ joystick->naxes = n;
1338+ }
1339+ if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) {
1340+ joystick->nbuttons = 2;
1341+ } else {
1342+ joystick->nbuttons = n;
1343+ }
1344+
1345+ name = SDL_SYS_JoystickName(joystick->index);
1346+
1347+ /* Generic analog joystick support */
1348+ if ( SDL_strstr(name, "Analog") == name && SDL_strstr(name, "-hat") ) {
1349+ if ( SDL_sscanf(name,"Analog %d-axis %*d-button %d-hat",
1350+ &tmp_naxes, &tmp_nhats) == 2 ) {
1351+
1352+ joystick->naxes = tmp_naxes;
1353+ joystick->nhats = tmp_nhats;
1354+
1355+ handled = SDL_TRUE;
1356+ }
1357+ }
1358+
1359+ /* Special joystick support */
1360+ for ( i=0; i < SDL_arraysize(special_joysticks); ++i ) {
1361+ if ( SDL_strcmp(name, special_joysticks[i].name) == 0 ) {
1362+
1363+ joystick->naxes = special_joysticks[i].naxes;
1364+ joystick->nhats = special_joysticks[i].nhats;
1365+ joystick->nballs = special_joysticks[i].nballs;
1366+
1367+ handled = SDL_TRUE;
1368+ break;
1369+ }
1370+ }
1371+
1372+ /* User environment joystick support */
1373+ if ( (env = SDL_getenv("SDL_LINUX_JOYSTICK")) ) {
1374+ *env_name = '\0';
1375+ if ( *env == '\'' && SDL_sscanf(env, "'%[^']s'", env_name) == 1 )
1376+ env += SDL_strlen(env_name)+2;
1377+ else if ( SDL_sscanf(env, "%s", env_name) == 1 )
1378+ env += SDL_strlen(env_name);
1379+
1380+ if ( SDL_strcmp(name, env_name) == 0 ) {
1381+
1382+ if ( SDL_sscanf(env, "%d %d %d", &tmp_naxes, &tmp_nhats,
1383+ &tmp_nballs) == 3 ) {
1384+
1385+ joystick->naxes = tmp_naxes;
1386+ joystick->nhats = tmp_nhats;
1387+ joystick->nballs = tmp_nballs;
1388+
1389+ handled = SDL_TRUE;
1390+ }
1391+ }
1392+ }
1393+
1394+ /* Remap hats and balls */
1395+ if (handled) {
1396+ if ( joystick->nhats > 0 ) {
1397+ if ( allocate_hatdata(joystick) < 0 ) {
1398+ joystick->nhats = 0;
1399+ }
1400+ }
1401+ if ( joystick->nballs > 0 ) {
1402+ if ( allocate_balldata(joystick) < 0 ) {
1403+ joystick->nballs = 0;
1404+ }
1405+ }
1406+ }
1407+
1408+ return(handled);
1409+}
1410+
1411+#if SDL_INPUT_LINUXEV
1412+
1413+static SDL_bool EV_ConfigJoystick(SDL_Joystick *joystick, int fd)
1414+{
1415+ int i, t;
1416+ unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
1417+ unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
1418+ unsigned long relbit[NBITS(REL_MAX)] = { 0 };
1419+
1420+ /* See if this device uses the new unified event API */
1421+ if ( (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
1422+ (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) &&
1423+ (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) ) {
1424+ joystick->hwdata->is_hid = SDL_TRUE;
1425+
1426+ /* Get the number of buttons, axes, and other thingamajigs */
1427+ for ( i=BTN_JOYSTICK; i < KEY_MAX; ++i ) {
1428+ if ( test_bit(i, keybit) ) {
1429+#ifdef DEBUG_INPUT_EVENTS
1430+ printf("Joystick has button: 0x%x\n", i);
1431+#endif
1432+ joystick->hwdata->key_map[i-BTN_MISC] =
1433+ joystick->nbuttons;
1434+ ++joystick->nbuttons;
1435+ }
1436+ }
1437+ for ( i=BTN_MISC; i < BTN_JOYSTICK; ++i ) {
1438+ if ( test_bit(i, keybit) ) {
1439+#ifdef DEBUG_INPUT_EVENTS
1440+ printf("Joystick has button: 0x%x\n", i);
1441+#endif
1442+ joystick->hwdata->key_map[i-BTN_MISC] =
1443+ joystick->nbuttons;
1444+ ++joystick->nbuttons;
1445+ }
1446+ }
1447+ for ( i=0; i<ABS_MISC; ++i ) {
1448+ /* Skip hats */
1449+ if ( i == ABS_HAT0X ) {
1450+ i = ABS_HAT3Y;
1451+ continue;
1452+ }
1453+ if ( test_bit(i, absbit) ) {
1454+ struct input_absinfo absinfo;
1455+
1456+ if ( ioctl(fd, EVIOCGABS(i), &absinfo) < 0 )
1457+ continue;
1458+#ifdef DEBUG_INPUT_EVENTS
1459+ printf("Joystick has absolute axis: %x\n", i);
1460+ printf("Values = { %d, %d, %d, %d, %d }\n",
1461+ absinfo.value, absinfo.minimum,
1462+ absinfo.maximum, absinfo.fuzz, absinfo.flat);
1463+#endif /* DEBUG_INPUT_EVENTS */
1464+ joystick->hwdata->abs_map[i] = joystick->naxes;
1465+ if ( absinfo.minimum == absinfo.maximum ) {
1466+ joystick->hwdata->abs_correct[i].used = 0;
1467+ } else {
1468+ joystick->hwdata->abs_correct[i].used = 1;
1469+ joystick->hwdata->abs_correct[i].coef[0] =
1470+ (absinfo.maximum + absinfo.minimum) / 2 - absinfo.flat;
1471+ joystick->hwdata->abs_correct[i].coef[1] =
1472+ (absinfo.maximum + absinfo.minimum) / 2 + absinfo.flat;
1473+ t = ((absinfo.maximum - absinfo.minimum) / 2 - 2 * absinfo.flat);
1474+ if ( t != 0 ) {
1475+ joystick->hwdata->abs_correct[i].coef[2] = (1 << 29) / t;
1476+ } else {
1477+ joystick->hwdata->abs_correct[i].coef[2] = 0;
1478+ }
1479+ }
1480+ ++joystick->naxes;
1481+ }
1482+ }
1483+ for ( i=ABS_HAT0X; i <= ABS_HAT3Y; i += 2 ) {
1484+ if ( test_bit(i, absbit) || test_bit(i+1, absbit) ) {
1485+#ifdef DEBUG_INPUT_EVENTS
1486+ printf("Joystick has hat %d\n",(i-ABS_HAT0X)/2);
1487+#endif
1488+ ++joystick->nhats;
1489+ }
1490+ }
1491+ if ( test_bit(REL_X, relbit) || test_bit(REL_Y, relbit) ) {
1492+ ++joystick->nballs;
1493+ }
1494+
1495+ /* Allocate data to keep track of these thingamajigs */
1496+ if ( joystick->nhats > 0 ) {
1497+ if ( allocate_hatdata(joystick) < 0 ) {
1498+ joystick->nhats = 0;
1499+ }
1500+ }
1501+ if ( joystick->nballs > 0 ) {
1502+ if ( allocate_balldata(joystick) < 0 ) {
1503+ joystick->nballs = 0;
1504+ }
1505+ }
1506+ }
1507+ return(joystick->hwdata->is_hid);
1508+}
1509+
1510+#endif /* SDL_INPUT_LINUXEV */
1511+
1512+#ifndef NO_LOGICAL_JOYSTICKS
1513+static void ConfigLogicalJoystick(SDL_Joystick *joystick)
1514+{
1515+ struct joystick_logical_layout* layout;
1516+
1517+ layout = SDL_joylist[joystick->index].map->layout +
1518+ SDL_joylist[joystick->index].logicalno;
1519+
1520+ joystick->nbuttons = layout->nbuttons;
1521+ joystick->nhats = layout->nhats;
1522+ joystick->naxes = layout->naxes;
1523+ joystick->nballs = layout->nballs;
1524+}
1525+#endif
1526+
1527+
1528+/* Function to open a joystick for use.
1529+ The joystick to open is specified by the index field of the joystick.
1530+ This should fill the nbuttons and naxes fields of the joystick structure.
1531+ It returns 0, or -1 if there is an error.
1532+ */
1533+int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
1534+{
1535+ int fd;
1536+ SDL_logical_joydecl(int realindex);
1537+ SDL_logical_joydecl(SDL_Joystick *realjoy = NULL);
1538+
1539+ /* Open the joystick and set the joystick file descriptor */
1540+#ifndef NO_LOGICAL_JOYSTICKS
1541+ if (SDL_joylist[joystick->index].fname == NULL) {
1542+ SDL_joylist_head(realindex, joystick->index);
1543+ realjoy = SDL_JoystickOpen(realindex);
1544+
1545+ if (realjoy == NULL)
1546+ return(-1);
1547+
1548+ fd = realjoy->hwdata->fd;
1549+
1550+ } else {
1551+ fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0);
1552+ }
1553+ SDL_joylist[joystick->index].joy = joystick;
1554+#else
1555+ fd = open(SDL_joylist[joystick->index].fname, O_RDONLY, 0);
1556+#endif
1557+
1558+ if ( fd < 0 ) {
1559+ SDL_SetError("Unable to open %s\n",
1560+ SDL_joylist[joystick->index]);
1561+ return(-1);
1562+ }
1563+ joystick->hwdata = (struct joystick_hwdata *)
1564+ SDL_malloc(sizeof(*joystick->hwdata));
1565+ if ( joystick->hwdata == NULL ) {
1566+ SDL_OutOfMemory();
1567+ close(fd);
1568+ return(-1);
1569+ }
1570+ SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
1571+ joystick->hwdata->fd = fd;
1572+
1573+ /* Set the joystick to non-blocking read mode */
1574+ fcntl(fd, F_SETFL, O_NONBLOCK);
1575+
1576+ /* Get the number of buttons and axes on the joystick */
1577+#ifndef NO_LOGICAL_JOYSTICKS
1578+ if (realjoy)
1579+ ConfigLogicalJoystick(joystick);
1580+ else
1581+#endif
1582+#if SDL_INPUT_LINUXEV
1583+ if ( ! EV_ConfigJoystick(joystick, fd) )
1584+#endif
1585+ JS_ConfigJoystick(joystick, fd);
1586+
1587+ return(0);
1588+}
1589+
1590+#ifndef NO_LOGICAL_JOYSTICKS
1591+
1592+static SDL_Joystick* FindLogicalJoystick(
1593+ SDL_Joystick *joystick, struct joystick_logical_mapping* v)
1594+{
1595+ SDL_Joystick *logicaljoy;
1596+ register int i;
1597+
1598+ i = joystick->index;
1599+ logicaljoy = NULL;
1600+
1601+ /* get the fake joystick that will receive the event
1602+ */
1603+ for(;;) {
1604+
1605+ if (SDL_joylist[i].logicalno == v->njoy) {
1606+ logicaljoy = SDL_joylist[i].joy;
1607+ break;
1608+ }
1609+
1610+ if (SDL_joylist[i].next == 0)
1611+ break;
1612+
1613+ i = SDL_joylist[i].next;
1614+
1615+ }
1616+
1617+ return logicaljoy;
1618+}
1619+
1620+static int LogicalJoystickButton(
1621+ SDL_Joystick *joystick, Uint8 button, Uint8 state){
1622+ struct joystick_logical_mapping* buttons;
1623+ SDL_Joystick *logicaljoy = NULL;
1624+
1625+ /* if there's no map then this is just a regular joystick
1626+ */
1627+ if (SDL_joylist[joystick->index].map == NULL)
1628+ return 0;
1629+
1630+ /* get the logical joystick that will receive the event
1631+ */
1632+ buttons = SDL_joylist[joystick->index].map->buttonmap+button;
1633+ logicaljoy = FindLogicalJoystick(joystick, buttons);
1634+
1635+ if (logicaljoy == NULL)
1636+ return 1;
1637+
1638+ SDL_PrivateJoystickButton(logicaljoy, buttons->nthing, state);
1639+
1640+ return 1;
1641+}
1642+
1643+static int LogicalJoystickAxis(
1644+ SDL_Joystick *joystick, Uint8 axis, Sint16 value)
1645+{
1646+ struct joystick_logical_mapping* axes;
1647+ SDL_Joystick *logicaljoy = NULL;
1648+
1649+ /* if there's no map then this is just a regular joystick
1650+ */
1651+ if (SDL_joylist[joystick->index].map == NULL)
1652+ return 0;
1653+
1654+ /* get the logical joystick that will receive the event
1655+ */
1656+ axes = SDL_joylist[joystick->index].map->axismap+axis;
1657+ logicaljoy = FindLogicalJoystick(joystick, axes);
1658+
1659+ if (logicaljoy == NULL)
1660+ return 1;
1661+
1662+ SDL_PrivateJoystickAxis(logicaljoy, axes->nthing, value);
1663+
1664+ return 1;
1665+}
1666+#endif /* USE_LOGICAL_JOYSTICKS */
1667+
1668+static __inline__
1669+void HandleHat(SDL_Joystick *stick, Uint8 hat, int axis, int value)
1670+{
1671+ struct hwdata_hat *the_hat;
1672+ const Uint8 position_map[3][3] = {
1673+ { SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP },
1674+ { SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT },
1675+ { SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN }
1676+ };
1677+ SDL_logical_joydecl(SDL_Joystick *logicaljoy = NULL);
1678+ SDL_logical_joydecl(struct joystick_logical_mapping* hats = NULL);
1679+
1680+ if (stick->nhats <= hat) {
1681+ return; /* whoops, that shouldn't happen! */
1682+ }
1683+
1684+ the_hat = &stick->hwdata->hats[hat];
1685+ if ( value < 0 ) {
1686+ value = 0;
1687+ } else
1688+ if ( value == 0 ) {
1689+ value = 1;
1690+ } else
1691+ if ( value > 0 ) {
1692+ value = 2;
1693+ }
1694+ if ( value != the_hat->axis[axis] ) {
1695+ the_hat->axis[axis] = value;
1696+
1697+#ifndef NO_LOGICAL_JOYSTICKS
1698+ /* if there's no map then this is just a regular joystick
1699+ */
1700+ if (SDL_joylist[stick->index].map != NULL) {
1701+
1702+ /* get the fake joystick that will receive the event
1703+ */
1704+ hats = SDL_joylist[stick->index].map->hatmap+hat;
1705+ logicaljoy = FindLogicalJoystick(stick, hats);
1706+ }
1707+
1708+ if (logicaljoy) {
1709+ stick = logicaljoy;
1710+ hat = hats->nthing;
1711+ }
1712+#endif /* USE_LOGICAL_JOYSTICKS */
1713+
1714+ SDL_PrivateJoystickHat(stick, hat,
1715+ position_map[the_hat->axis[1]][the_hat->axis[0]]);
1716+ }
1717+}
1718+
1719+static __inline__
1720+void HandleBall(SDL_Joystick *stick, Uint8 ball, int axis, int value)
1721+{
1722+ if ((stick->nballs <= ball) || (axis >= 2)) {
1723+ return; /* whoops, that shouldn't happen! */
1724+ }
1725+ stick->hwdata->balls[ball].axis[axis] += value;
1726+}
1727+
1728+/* Function to update the state of a joystick - called as a device poll.
1729+ * This function shouldn't update the joystick structure directly,
1730+ * but instead should call SDL_PrivateJoystick*() to deliver events
1731+ * and update joystick device state.
1732+ */
1733+static __inline__ void JS_HandleEvents(SDL_Joystick *joystick)
1734+{
1735+ struct js_event events[32];
1736+ int i, len;
1737+ Uint8 other_axis;
1738+
1739+#ifndef NO_LOGICAL_JOYSTICKS
1740+ if (SDL_joylist[joystick->index].fname == NULL) {
1741+ SDL_joylist_head(i, joystick->index);
1742+ JS_HandleEvents(SDL_joylist[i].joy);
1743+ return;
1744+ }
1745+#endif
1746+
1747+ while ((len=read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
1748+ len /= sizeof(events[0]);
1749+ for ( i=0; i<len; ++i ) {
1750+ switch (events[i].type & ~JS_EVENT_INIT) {
1751+ case JS_EVENT_AXIS:
1752+ if ( events[i].number < joystick->naxes ) {
1753+#ifndef NO_LOGICAL_JOYSTICKS
1754+ if (!LogicalJoystickAxis(joystick,
1755+ events[i].number, events[i].value))
1756+#endif
1757+ SDL_PrivateJoystickAxis(joystick,
1758+ events[i].number, events[i].value);
1759+ break;
1760+ }
1761+ events[i].number -= joystick->naxes;
1762+ other_axis = (events[i].number / 2);
1763+ if ( other_axis < joystick->nhats ) {
1764+ HandleHat(joystick, other_axis,
1765+ events[i].number%2,
1766+ events[i].value);
1767+ break;
1768+ }
1769+ events[i].number -= joystick->nhats*2;
1770+ other_axis = (events[i].number / 2);
1771+ if ( other_axis < joystick->nballs ) {
1772+ HandleBall(joystick, other_axis,
1773+ events[i].number%2,
1774+ events[i].value);
1775+ break;
1776+ }
1777+ break;
1778+ case JS_EVENT_BUTTON:
1779+#ifndef NO_LOGICAL_JOYSTICKS
1780+ if (!LogicalJoystickButton(joystick,
1781+ events[i].number, events[i].value))
1782+#endif
1783+ SDL_PrivateJoystickButton(joystick,
1784+ events[i].number, events[i].value);
1785+ break;
1786+ default:
1787+ /* ?? */
1788+ break;
1789+ }
1790+ }
1791+ }
1792+}
1793+#if SDL_INPUT_LINUXEV
1794+static __inline__ int EV_AxisCorrect(SDL_Joystick *joystick, int which, int value)
1795+{
1796+ struct axis_correct *correct;
1797+
1798+ correct = &joystick->hwdata->abs_correct[which];
1799+ if ( correct->used ) {
1800+ if ( value > correct->coef[0] ) {
1801+ if ( value < correct->coef[1] ) {
1802+ return 0;
1803+ }
1804+ value -= correct->coef[1];
1805+ } else {
1806+ value -= correct->coef[0];
1807+ }
1808+ value *= correct->coef[2];
1809+ value >>= 14;
1810+ }
1811+
1812+ /* Clamp and return */
1813+ if ( value < -32768 ) return -32768;
1814+ if ( value > 32767 ) return 32767;
1815+
1816+ return value;
1817+}
1818+
1819+static __inline__ void EV_HandleEvents(SDL_Joystick *joystick)
1820+{
1821+ struct input_event events[32];
1822+ int i, len;
1823+ int code;
1824+
1825+#ifndef NO_LOGICAL_JOYSTICKS
1826+ if (SDL_joylist[joystick->index].fname == NULL) {
1827+ SDL_joylist_head(i, joystick->index);
1828+ return EV_HandleEvents(SDL_joylist[i].joy);
1829+ }
1830+#endif
1831+
1832+ while ((len=read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
1833+ len /= sizeof(events[0]);
1834+ for ( i=0; i<len; ++i ) {
1835+ code = events[i].code;
1836+ switch (events[i].type) {
1837+ case EV_KEY:
1838+ if ( code >= BTN_MISC ) {
1839+ code -= BTN_MISC;
1840+#ifndef NO_LOGICAL_JOYSTICKS
1841+ if (!LogicalJoystickButton(joystick,
1842+ joystick->hwdata->key_map[code],
1843+ events[i].value))
1844+#endif
1845+ SDL_PrivateJoystickButton(joystick,
1846+ joystick->hwdata->key_map[code],
1847+ events[i].value);
1848+ }
1849+ break;
1850+ case EV_ABS:
1851+ switch (code) {
1852+ case ABS_HAT0X:
1853+ case ABS_HAT0Y:
1854+ case ABS_HAT1X:
1855+ case ABS_HAT1Y:
1856+ case ABS_HAT2X:
1857+ case ABS_HAT2Y:
1858+ case ABS_HAT3X:
1859+ case ABS_HAT3Y:
1860+ code -= ABS_HAT0X;
1861+ HandleHat(joystick, code/2, code%2,
1862+ events[i].value);
1863+ break;
1864+ default:
1865+ events[i].value = EV_AxisCorrect(joystick, code, events[i].value);
1866+#ifndef NO_LOGICAL_JOYSTICKS
1867+ if (!LogicalJoystickAxis(joystick,
1868+ joystick->hwdata->abs_map[code],
1869+ events[i].value))
1870+#endif
1871+ SDL_PrivateJoystickAxis(joystick,
1872+ joystick->hwdata->abs_map[code],
1873+ events[i].value);
1874+ break;
1875+ }
1876+ break;
1877+ case EV_REL:
1878+ switch (code) {
1879+ case REL_X:
1880+ case REL_Y:
1881+ code -= REL_X;
1882+ HandleBall(joystick, code/2, code%2,
1883+ events[i].value);
1884+ break;
1885+ default:
1886+ break;
1887+ }
1888+ break;
1889+ default:
1890+ break;
1891+ }
1892+ }
1893+ }
1894+}
1895+#endif /* SDL_INPUT_LINUXEV */
1896+
1897+void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
1898+{
1899+ int i;
1900+
1901+#if SDL_INPUT_LINUXEV
1902+ if ( joystick->hwdata->is_hid )
1903+ EV_HandleEvents(joystick);
1904+ else
1905+#endif
1906+ JS_HandleEvents(joystick);
1907+
1908+ /* Deliver ball motion updates */
1909+ for ( i=0; i<joystick->nballs; ++i ) {
1910+ int xrel, yrel;
1911+
1912+ xrel = joystick->hwdata->balls[i].axis[0];
1913+ yrel = joystick->hwdata->balls[i].axis[1];
1914+ if ( xrel || yrel ) {
1915+ joystick->hwdata->balls[i].axis[0] = 0;
1916+ joystick->hwdata->balls[i].axis[1] = 0;
1917+ SDL_PrivateJoystickBall(joystick, (Uint8)i, xrel, yrel);
1918+ }
1919+ }
1920+}
1921+
1922+/* Function to close a joystick after use */
1923+void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
1924+{
1925+#ifndef NO_LOGICAL_JOYSTICKS
1926+ register int i;
1927+ if (SDL_joylist[joystick->index].fname == NULL) {
1928+ SDL_joylist_head(i, joystick->index);
1929+ SDL_JoystickClose(SDL_joylist[i].joy);
1930+ }
1931+#endif
1932+
1933+ if ( joystick->hwdata ) {
1934+#ifndef NO_LOGICAL_JOYSTICKS
1935+ if (SDL_joylist[joystick->index].fname != NULL)
1936+#endif
1937+ close(joystick->hwdata->fd);
1938+ if ( joystick->hwdata->hats ) {
1939+ SDL_free(joystick->hwdata->hats);
1940+ }
1941+ if ( joystick->hwdata->balls ) {
1942+ SDL_free(joystick->hwdata->balls);
1943+ }
1944+ SDL_free(joystick->hwdata);
1945+ joystick->hwdata = NULL;
1946+ }
1947+}
1948+
1949+/* Function to perform any system-specific joystick related cleanup */
1950+void SDL_SYS_JoystickQuit(void)
1951+{
1952+ int i;
1953+
1954+ for ( i=0; SDL_joylist[i].fname; ++i ) {
1955+ SDL_free(SDL_joylist[i].fname);
1956+ SDL_joylist[i].fname = NULL;
1957+ }
1958+}
1959+
1960+#endif /* SDL_JOYSTICK_LINUX */
1961
1962=== added directory '.pc/fix_window_resizing.diff'
1963=== added directory '.pc/fix_window_resizing.diff/src'
1964=== added directory '.pc/fix_window_resizing.diff/src/video'
1965=== added directory '.pc/fix_window_resizing.diff/src/video/x11'
1966=== added file '.pc/fix_window_resizing.diff/src/video/x11/SDL_x11events.c'
1967--- .pc/fix_window_resizing.diff/src/video/x11/SDL_x11events.c 1970-01-01 00:00:00 +0000
1968+++ .pc/fix_window_resizing.diff/src/video/x11/SDL_x11events.c 2015-06-01 21:40:05 +0000
1969@@ -0,0 +1,1423 @@
1970+/*
1971+ SDL - Simple DirectMedia Layer
1972+ Copyright (C) 1997-2012 Sam Lantinga
1973+
1974+ This library is free software; you can redistribute it and/or
1975+ modify it under the terms of the GNU Lesser General Public
1976+ License as published by the Free Software Foundation; either
1977+ version 2.1 of the License, or (at your option) any later version.
1978+
1979+ This library is distributed in the hope that it will be useful,
1980+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1981+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1982+ Lesser General Public License for more details.
1983+
1984+ You should have received a copy of the GNU Lesser General Public
1985+ License along with this library; if not, write to the Free Software
1986+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1987+
1988+ Sam Lantinga
1989+ slouken@libsdl.org
1990+*/
1991+#include "SDL_config.h"
1992+
1993+/* Handle the event stream, converting X11 events into SDL events */
1994+
1995+#include <setjmp.h>
1996+#include <X11/Xlib.h>
1997+#include <X11/Xutil.h>
1998+#include <X11/keysym.h>
1999+#ifdef __SVR4
2000+#include <X11/Sunkeysym.h>
2001+#endif
2002+#include <sys/types.h>
2003+#include <sys/time.h>
2004+#include <unistd.h>
2005+
2006+#include "SDL_timer.h"
2007+#include "SDL_syswm.h"
2008+#include "../SDL_sysvideo.h"
2009+#include "../../events/SDL_sysevents.h"
2010+#include "../../events/SDL_events_c.h"
2011+#include "SDL_x11video.h"
2012+#include "SDL_x11dga_c.h"
2013+#include "SDL_x11modes_c.h"
2014+#include "SDL_x11image_c.h"
2015+#include "SDL_x11gamma_c.h"
2016+#include "SDL_x11wm_c.h"
2017+#include "SDL_x11mouse_c.h"
2018+#include "SDL_x11events_c.h"
2019+
2020+
2021+/* Define this if you want to debug X11 events */
2022+/*#define DEBUG_XEVENTS*/
2023+
2024+/* The translation tables from an X11 keysym to a SDL keysym */
2025+static SDLKey ODD_keymap[256];
2026+static SDLKey MISC_keymap[256];
2027+SDLKey X11_TranslateKeycode(Display *display, KeyCode kc);
2028+
2029+/*
2030+ Pending resize target for ConfigureNotify (so outdated events don't
2031+ cause inappropriate resize events)
2032+*/
2033+int X11_PendingConfigureNotifyWidth = -1;
2034+int X11_PendingConfigureNotifyHeight = -1;
2035+
2036+#ifdef X_HAVE_UTF8_STRING
2037+Uint32 Utf8ToUcs4(const Uint8 *utf8)
2038+{
2039+ Uint32 c;
2040+ int i = 1;
2041+ int noOctets = 0;
2042+ int firstOctetMask = 0;
2043+ unsigned char firstOctet = utf8[0];
2044+ if (firstOctet < 0x80) {
2045+ /*
2046+ Characters in the range:
2047+ 00000000 to 01111111 (ASCII Range)
2048+ are stored in one octet:
2049+ 0xxxxxxx (The same as its ASCII representation)
2050+ The least 6 significant bits of the first octet is the most 6 significant nonzero bits
2051+ of the UCS4 representation.
2052+ */
2053+ noOctets = 1;
2054+ firstOctetMask = 0x7F; /* 0(1111111) - The most significant bit is ignored */
2055+ } else if ((firstOctet & 0xE0) /* get the most 3 significant bits by AND'ing with 11100000 */
2056+ == 0xC0 ) { /* see if those 3 bits are 110. If so, the char is in this range */
2057+ /*
2058+ Characters in the range:
2059+ 00000000 10000000 to 00000111 11111111
2060+ are stored in two octets:
2061+ 110xxxxx 10xxxxxx
2062+ The least 5 significant bits of the first octet is the most 5 significant nonzero bits
2063+ of the UCS4 representation.
2064+ */
2065+ noOctets = 2;
2066+ firstOctetMask = 0x1F; /* 000(11111) - The most 3 significant bits are ignored */
2067+ } else if ((firstOctet & 0xF0) /* get the most 4 significant bits by AND'ing with 11110000 */
2068+ == 0xE0) { /* see if those 4 bits are 1110. If so, the char is in this range */
2069+ /*
2070+ Characters in the range:
2071+ 00001000 00000000 to 11111111 11111111
2072+ are stored in three octets:
2073+ 1110xxxx 10xxxxxx 10xxxxxx
2074+ The least 4 significant bits of the first octet is the most 4 significant nonzero bits
2075+ of the UCS4 representation.
2076+ */
2077+ noOctets = 3;
2078+ firstOctetMask = 0x0F; /* 0000(1111) - The most 4 significant bits are ignored */
2079+ } else if ((firstOctet & 0xF8) /* get the most 5 significant bits by AND'ing with 11111000 */
2080+ == 0xF0) { /* see if those 5 bits are 11110. If so, the char is in this range */
2081+ /*
2082+ Characters in the range:
2083+ 00000001 00000000 00000000 to 00011111 11111111 11111111
2084+ are stored in four octets:
2085+ 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
2086+ The least 3 significant bits of the first octet is the most 3 significant nonzero bits
2087+ of the UCS4 representation.
2088+ */
2089+ noOctets = 4;
2090+ firstOctetMask = 0x07; /* 11110(111) - The most 5 significant bits are ignored */
2091+ } else if ((firstOctet & 0xFC) /* get the most 6 significant bits by AND'ing with 11111100 */
2092+ == 0xF8) { /* see if those 6 bits are 111110. If so, the char is in this range */
2093+ /*
2094+ Characters in the range:
2095+ 00000000 00100000 00000000 00000000 to
2096+ 00000011 11111111 11111111 11111111
2097+ are stored in five octets:
2098+ 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
2099+ The least 2 significant bits of the first octet is the most 2 significant nonzero bits
2100+ of the UCS4 representation.
2101+ */
2102+ noOctets = 5;
2103+ firstOctetMask = 0x03; /* 111110(11) - The most 6 significant bits are ignored */
2104+ } else if ((firstOctet & 0xFE) /* get the most 7 significant bits by AND'ing with 11111110 */
2105+ == 0xFC) { /* see if those 7 bits are 1111110. If so, the char is in this range */
2106+ /*
2107+ Characters in the range:
2108+ 00000100 00000000 00000000 00000000 to
2109+ 01111111 11111111 11111111 11111111
2110+ are stored in six octets:
2111+ 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
2112+ The least significant bit of the first octet is the most significant nonzero bit
2113+ of the UCS4 representation.
2114+ */
2115+ noOctets = 6;
2116+ firstOctetMask = 0x01; /* 1111110(1) - The most 7 significant bits are ignored */
2117+ } else
2118+ return 0; /* The given chunk is not a valid UTF-8 encoded Unicode character */
2119+
2120+ /*
2121+ The least noOctets significant bits of the first octet is the most 2 significant nonzero bits
2122+ of the UCS4 representation.
2123+ The first 6 bits of the UCS4 representation is the least 8-noOctets-1 significant bits of
2124+ firstOctet if the character is not ASCII. If so, it's the least 7 significant bits of firstOctet.
2125+ This done by AND'ing firstOctet with its mask to trim the bits used for identifying the
2126+ number of continuing octets (if any) and leave only the free bits (the x's)
2127+ Sample:
2128+ 1-octet: 0xxxxxxx & 01111111 = 0xxxxxxx
2129+ 2-octets: 110xxxxx & 00011111 = 000xxxxx
2130+ */
2131+ c = firstOctet & firstOctetMask;
2132+
2133+ /* Now, start filling c.ucs4 with the bits from the continuing octets from utf8. */
2134+ for (i = 1; i < noOctets; i++) {
2135+ /* A valid continuing octet is of the form 10xxxxxx */
2136+ if ((utf8[i] & 0xC0) /* get the most 2 significant bits by AND'ing with 11000000 */
2137+ != 0x80) /* see if those 2 bits are 10. If not, the is a malformed sequence. */
2138+ /*The given chunk is a partial sequence at the end of a string that could
2139+ begin a valid character */
2140+ return 0;
2141+
2142+ /* Make room for the next 6-bits */
2143+ c <<= 6;
2144+
2145+ /*
2146+ Take only the least 6 significance bits of the current octet (utf8[i]) and fill the created room
2147+ of c.ucs4 with them.
2148+ This done by AND'ing utf8[i] with 00111111 and the OR'ing the result with c.ucs4.
2149+ */
2150+ c |= utf8[i] & 0x3F;
2151+ }
2152+ return c;
2153+}
2154+
2155+/* Given a UTF-8 encoded string pointed to by utf8 of length length in
2156+ bytes, returns the corresponding UTF-16 encoded string in the
2157+ buffer pointed to by utf16. The maximum number of UTF-16 encoding
2158+ units (i.e., Unit16s) allowed in the buffer is specified in
2159+ utf16_max_length. The return value is the number of UTF-16
2160+ encoding units placed in the output buffer pointed to by utf16.
2161+
2162+ In case of an error, -1 is returned, leaving some unusable partial
2163+ results in the output buffer.
2164+
2165+ The caller must estimate the size of utf16 buffer by itself before
2166+ calling this function. Insufficient output buffer is considered as
2167+ an error, and once an error occured, this function doesn't give any
2168+ clue how large the result will be.
2169+
2170+ The error cases include following:
2171+
2172+ - Invalid byte sequences were in the input UTF-8 bytes. The caller
2173+ has no way to know what point in the input buffer was the
2174+ errornous byte.
2175+
2176+ - The input contained a character (a valid UTF-8 byte sequence)
2177+ whose scalar value exceeded the range that UTF-16 can represent
2178+ (i.e., characters whose Unicode scalar value above 0x110000).
2179+
2180+ - The output buffer has no enough space to hold entire utf16 data.
2181+
2182+ Please note:
2183+
2184+ - '\0'-termination is not assumed both on the input UTF-8 string
2185+ and on the output UTF-16 string; any legal zero byte in the input
2186+ UTF-8 string will be converted to a 16-bit zero in output. As a
2187+ side effect, the last UTF-16 encoding unit stored in the output
2188+ buffer will have a non-zero value if the input UTF-8 was not
2189+ '\0'-terminated.
2190+
2191+ - UTF-8 aliases are *not* considered as an error. They are
2192+ converted to UTF-16. For example, 0xC0 0xA0, 0xE0 0x80 0xA0,
2193+ and 0xF0 0x80 0x80 0xA0 are all mapped to a single UTF-16
2194+ encoding unit 0x0020.
2195+
2196+ - Three byte UTF-8 sequences whose value corresponds to a surrogate
2197+ code or other reserved scalar value are not considered as an
2198+ error either. They may cause an invalid UTF-16 data (e.g., those
2199+ containing unpaired surrogates).
2200+
2201+*/
2202+
2203+static int Utf8ToUtf16(const Uint8 *utf8, const int utf8_length, Uint16 *utf16, const int utf16_max_length) {
2204+
2205+ /* p moves over the output buffer. max_ptr points to the next to the last slot of the buffer. */
2206+ Uint16 *p = utf16;
2207+ Uint16 const *const max_ptr = utf16 + utf16_max_length;
2208+
2209+ /* end_of_input points to the last byte of input as opposed to the next to the last byte. */
2210+ Uint8 const *const end_of_input = utf8 + utf8_length - 1;
2211+
2212+ while (utf8 <= end_of_input) {
2213+ Uint8 const c = *utf8;
2214+ if (p >= max_ptr) {
2215+ /* No more output space. */
2216+ return -1;
2217+ }
2218+ if (c < 0x80) {
2219+ /* One byte ASCII. */
2220+ *p++ = c;
2221+ utf8 += 1;
2222+ } else if (c < 0xC0) {
2223+ /* Follower byte without preceeding leader bytes. */
2224+ return -1;
2225+ } else if (c < 0xE0) {
2226+ /* Two byte sequence. We need one follower byte. */
2227+ if (end_of_input - utf8 < 1 || (((utf8[1] ^ 0x80)) & 0xC0)) {
2228+ return -1;
2229+ }
2230+ *p++ = (Uint16)(0xCF80 + (c << 6) + utf8[1]);
2231+ utf8 += 2;
2232+ } else if (c < 0xF0) {
2233+ /* Three byte sequence. We need two follower byte. */
2234+ if (end_of_input - utf8 < 2 || (((utf8[1] ^ 0x80) | (utf8[2] ^ 0x80)) & 0xC0)) {
2235+ return -1;
2236+ }
2237+ *p++ = (Uint16)(0xDF80 + (c << 12) + (utf8[1] << 6) + utf8[2]);
2238+ utf8 += 3;
2239+ } else if (c < 0xF8) {
2240+ int plane;
2241+ /* Four byte sequence. We need three follower bytes. */
2242+ if (end_of_input - utf8 < 3 || (((utf8[1] ^ 0x80) | (utf8[2] ^0x80) | (utf8[3] ^ 0x80)) & 0xC0)) {
2243+ return -1;
2244+ }
2245+ plane = (-0xC8 + (c << 2) + (utf8[1] >> 4));
2246+ if (plane == 0) {
2247+ /* This four byte sequence is an alias that
2248+ corresponds to a Unicode scalar value in BMP.
2249+ It fits in an UTF-16 encoding unit. */
2250+ *p++ = (Uint16)(0xDF80 + (utf8[1] << 12) + (utf8[2] << 6) + utf8[3]);
2251+ } else if (plane <= 16) {
2252+ /* This is a legal four byte sequence that corresponds to a surrogate pair. */
2253+ if (p + 1 >= max_ptr) {
2254+ /* No enough space on the output buffer for the pair. */
2255+ return -1;
2256+ }
2257+ *p++ = (Uint16)(0xE5B8 + (c << 8) + (utf8[1] << 2) + (utf8[2] >> 4));
2258+ *p++ = (Uint16)(0xDB80 + ((utf8[2] & 0x0F) << 6) + utf8[3]);
2259+ } else {
2260+ /* This four byte sequence is out of UTF-16 code space. */
2261+ return -1;
2262+ }
2263+ utf8 += 4;
2264+ } else {
2265+ /* Longer sequence or unused byte. */
2266+ return -1;
2267+ }
2268+ }
2269+ return p - utf16;
2270+}
2271+
2272+#endif
2273+
2274+/* Check to see if this is a repeated key.
2275+ (idea shamelessly lifted from GII -- thanks guys! :)
2276+ */
2277+static int X11_KeyRepeat(Display *display, XEvent *event)
2278+{
2279+ XEvent peekevent;
2280+ int repeated;
2281+
2282+ repeated = 0;
2283+ if ( XPending(display) ) {
2284+ XPeekEvent(display, &peekevent);
2285+ if ( (peekevent.type == KeyPress) &&
2286+ (peekevent.xkey.keycode == event->xkey.keycode) &&
2287+ ((peekevent.xkey.time-event->xkey.time) < 2) ) {
2288+ repeated = 1;
2289+ XNextEvent(display, &peekevent);
2290+ }
2291+ }
2292+ return(repeated);
2293+}
2294+
2295+/* Note: The X server buffers and accumulates mouse motion events, so
2296+ the motion event generated by the warp may not appear exactly as we
2297+ expect it to. We work around this (and improve performance) by only
2298+ warping the pointer when it reaches the edge, and then wait for it.
2299+*/
2300+#define MOUSE_FUDGE_FACTOR 8
2301+
2302+static __inline__ int X11_WarpedMotion(_THIS, XEvent *xevent)
2303+{
2304+ int w, h, i;
2305+ int deltax, deltay;
2306+ int posted;
2307+
2308+ w = SDL_VideoSurface->w;
2309+ h = SDL_VideoSurface->h;
2310+ deltax = xevent->xmotion.x - mouse_last.x;
2311+ deltay = xevent->xmotion.y - mouse_last.y;
2312+#ifdef DEBUG_MOTION
2313+ printf("Warped mouse motion: %d,%d\n", deltax, deltay);
2314+#endif
2315+ mouse_last.x = xevent->xmotion.x;
2316+ mouse_last.y = xevent->xmotion.y;
2317+ posted = SDL_PrivateMouseMotion(0, 1, deltax, deltay);
2318+
2319+ if ( (xevent->xmotion.x < MOUSE_FUDGE_FACTOR) ||
2320+ (xevent->xmotion.x > (w-MOUSE_FUDGE_FACTOR)) ||
2321+ (xevent->xmotion.y < MOUSE_FUDGE_FACTOR) ||
2322+ (xevent->xmotion.y > (h-MOUSE_FUDGE_FACTOR)) ) {
2323+ /* Get the events that have accumulated */
2324+ while ( XCheckTypedEvent(SDL_Display, MotionNotify, xevent) ) {
2325+ deltax = xevent->xmotion.x - mouse_last.x;
2326+ deltay = xevent->xmotion.y - mouse_last.y;
2327+#ifdef DEBUG_MOTION
2328+ printf("Extra mouse motion: %d,%d\n", deltax, deltay);
2329+#endif
2330+ mouse_last.x = xevent->xmotion.x;
2331+ mouse_last.y = xevent->xmotion.y;
2332+ posted += SDL_PrivateMouseMotion(0, 1, deltax, deltay);
2333+ }
2334+ mouse_last.x = w/2;
2335+ mouse_last.y = h/2;
2336+ XWarpPointer(SDL_Display, None, SDL_Window, 0, 0, 0, 0,
2337+ mouse_last.x, mouse_last.y);
2338+ for ( i=0; i<10; ++i ) {
2339+ XMaskEvent(SDL_Display, PointerMotionMask, xevent);
2340+ if ( (xevent->xmotion.x >
2341+ (mouse_last.x-MOUSE_FUDGE_FACTOR)) &&
2342+ (xevent->xmotion.x <
2343+ (mouse_last.x+MOUSE_FUDGE_FACTOR)) &&
2344+ (xevent->xmotion.y >
2345+ (mouse_last.y-MOUSE_FUDGE_FACTOR)) &&
2346+ (xevent->xmotion.y <
2347+ (mouse_last.y+MOUSE_FUDGE_FACTOR)) ) {
2348+ break;
2349+ }
2350+#ifdef DEBUG_XEVENTS
2351+ printf("Lost mouse motion: %d,%d\n", xevent->xmotion.x, xevent->xmotion.y);
2352+#endif
2353+ }
2354+#ifdef DEBUG_XEVENTS
2355+ if ( i == 10 ) {
2356+ printf("Warning: didn't detect mouse warp motion\n");
2357+ }
2358+#endif
2359+ }
2360+ return(posted);
2361+}
2362+
2363+static int X11_DispatchEvent(_THIS)
2364+{
2365+ int posted;
2366+ XEvent xevent;
2367+
2368+ SDL_memset(&xevent, '\0', sizeof (XEvent)); /* valgrind fix. --ryan. */
2369+ XNextEvent(SDL_Display, &xevent);
2370+
2371+ /* Discard KeyRelease and KeyPress events generated by auto-repeat.
2372+ We need to do it before passing event to XFilterEvent. Otherwise,
2373+ KeyRelease aware IMs are confused... */
2374+ if ( xevent.type == KeyRelease
2375+ && X11_KeyRepeat(SDL_Display, &xevent) ) {
2376+ return 0;
2377+ }
2378+
2379+#ifdef X_HAVE_UTF8_STRING
2380+ /* If we are translating with IM, we need to pass all events
2381+ to XFilterEvent, and discard those filtered events immediately. */
2382+ if ( SDL_TranslateUNICODE
2383+ && SDL_IM != NULL
2384+ && XFilterEvent(&xevent, None) ) {
2385+ return 0;
2386+ }
2387+#endif
2388+
2389+ posted = 0;
2390+ switch (xevent.type) {
2391+
2392+ /* Gaining mouse coverage? */
2393+ case EnterNotify: {
2394+#ifdef DEBUG_XEVENTS
2395+printf("EnterNotify! (%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y);
2396+if ( xevent.xcrossing.mode == NotifyGrab )
2397+printf("Mode: NotifyGrab\n");
2398+if ( xevent.xcrossing.mode == NotifyUngrab )
2399+printf("Mode: NotifyUngrab\n");
2400+#endif
2401+ if ( this->input_grab == SDL_GRAB_OFF ) {
2402+ posted = SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
2403+ }
2404+ posted = SDL_PrivateMouseMotion(0, 0,
2405+ xevent.xcrossing.x,
2406+ xevent.xcrossing.y);
2407+ }
2408+ break;
2409+
2410+ /* Losing mouse coverage? */
2411+ case LeaveNotify: {
2412+#ifdef DEBUG_XEVENTS
2413+printf("LeaveNotify! (%d,%d)\n", xevent.xcrossing.x, xevent.xcrossing.y);
2414+if ( xevent.xcrossing.mode == NotifyGrab )
2415+printf("Mode: NotifyGrab\n");
2416+if ( xevent.xcrossing.mode == NotifyUngrab )
2417+printf("Mode: NotifyUngrab\n");
2418+#endif
2419+ if ( (xevent.xcrossing.mode != NotifyGrab) &&
2420+ (xevent.xcrossing.mode != NotifyUngrab) &&
2421+ (xevent.xcrossing.detail != NotifyInferior) ) {
2422+ if ( this->input_grab == SDL_GRAB_OFF ) {
2423+ posted = SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
2424+ } else {
2425+ posted = SDL_PrivateMouseMotion(0, 0,
2426+ xevent.xcrossing.x,
2427+ xevent.xcrossing.y);
2428+ }
2429+ }
2430+ }
2431+ break;
2432+
2433+ /* Gaining input focus? */
2434+ case FocusIn: {
2435+#ifdef DEBUG_XEVENTS
2436+printf("FocusIn!\n");
2437+#endif
2438+ posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS);
2439+
2440+#ifdef X_HAVE_UTF8_STRING
2441+ if ( SDL_IC != NULL ) {
2442+ XSetICFocus(SDL_IC);
2443+ }
2444+#endif
2445+ /* Queue entry into fullscreen mode */
2446+ switch_waiting = 0x01 | SDL_FULLSCREEN;
2447+ switch_time = SDL_GetTicks() + 1500;
2448+ }
2449+ break;
2450+
2451+ /* Losing input focus? */
2452+ case FocusOut: {
2453+#ifdef DEBUG_XEVENTS
2454+printf("FocusOut!\n");
2455+#endif
2456+ posted = SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS);
2457+
2458+#ifdef X_HAVE_UTF8_STRING
2459+ if ( SDL_IC != NULL ) {
2460+ XUnsetICFocus(SDL_IC);
2461+ }
2462+#endif
2463+ /* Queue leaving fullscreen mode */
2464+ switch_waiting = 0x01;
2465+ switch_time = SDL_GetTicks() + 200;
2466+ }
2467+ break;
2468+
2469+#ifdef X_HAVE_UTF8_STRING
2470+ /* Some IM requires MappingNotify to be passed to
2471+ XRefreshKeyboardMapping by the app. */
2472+ case MappingNotify: {
2473+ XRefreshKeyboardMapping(&xevent.xmapping);
2474+ }
2475+ break;
2476+#endif /* X_HAVE_UTF8_STRING */
2477+
2478+ /* Generated upon EnterWindow and FocusIn */
2479+ case KeymapNotify: {
2480+#ifdef DEBUG_XEVENTS
2481+printf("KeymapNotify!\n");
2482+#endif
2483+ X11_SetKeyboardState(SDL_Display, xevent.xkeymap.key_vector);
2484+ }
2485+ break;
2486+
2487+ /* Mouse motion? */
2488+ case MotionNotify: {
2489+ if ( SDL_VideoSurface ) {
2490+ if ( mouse_relative ) {
2491+ if ( using_dga & DGA_MOUSE ) {
2492+#ifdef DEBUG_MOTION
2493+ printf("DGA motion: %d,%d\n", xevent.xmotion.x_root, xevent.xmotion.y_root);
2494+#endif
2495+ posted = SDL_PrivateMouseMotion(0, 1,
2496+ xevent.xmotion.x_root,
2497+ xevent.xmotion.y_root);
2498+ } else {
2499+ posted = X11_WarpedMotion(this,&xevent);
2500+ }
2501+ } else {
2502+#ifdef DEBUG_MOTION
2503+ printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
2504+#endif
2505+ posted = SDL_PrivateMouseMotion(0, 0,
2506+ xevent.xmotion.x,
2507+ xevent.xmotion.y);
2508+ }
2509+ }
2510+ }
2511+ break;
2512+
2513+ /* Mouse button press? */
2514+ case ButtonPress: {
2515+ posted = SDL_PrivateMouseButton(SDL_PRESSED,
2516+ xevent.xbutton.button, 0, 0);
2517+ }
2518+ break;
2519+
2520+ /* Mouse button release? */
2521+ case ButtonRelease: {
2522+ posted = SDL_PrivateMouseButton(SDL_RELEASED,
2523+ xevent.xbutton.button, 0, 0);
2524+ }
2525+ break;
2526+
2527+ /* Key press? */
2528+ case KeyPress: {
2529+ SDL_keysym keysym;
2530+ KeyCode keycode = xevent.xkey.keycode;
2531+
2532+#ifdef DEBUG_XEVENTS
2533+printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
2534+#endif
2535+ /* If we're not doing translation, we're done! */
2536+ if ( !SDL_TranslateUNICODE ) {
2537+ /* Get the translated SDL virtual keysym and put it on the queue.*/
2538+ keysym.scancode = keycode;
2539+ keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
2540+ keysym.mod = KMOD_NONE;
2541+ keysym.unicode = 0;
2542+ posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
2543+ break;
2544+ }
2545+
2546+ /* Look up the translated value for the key event */
2547+#ifdef X_HAVE_UTF8_STRING
2548+ if ( SDL_IC != NULL ) {
2549+ Status status;
2550+ KeySym xkeysym;
2551+ int i;
2552+ /* A UTF-8 character can be at most 6 bytes */
2553+ /* ... It's true, but Xutf8LookupString can
2554+ return more than one characters. Moreover,
2555+ the spec. put no upper bound, so we should
2556+ be ready for longer strings. */
2557+ char keybuf[32];
2558+ char *keydata = keybuf;
2559+ int count;
2560+ Uint16 utf16buf[32];
2561+ Uint16 *utf16data = utf16buf;
2562+ int utf16size;
2563+ int utf16length;
2564+
2565+ count = Xutf8LookupString(SDL_IC, &xevent.xkey, keydata, sizeof(keybuf), &xkeysym, &status);
2566+ if (XBufferOverflow == status) {
2567+ /* The IM has just generated somewhat long
2568+ string. We need a longer buffer in this
2569+ case. */
2570+ keydata = SDL_malloc(count);
2571+ if ( keydata == NULL ) {
2572+ SDL_OutOfMemory();
2573+ break;
2574+ }
2575+ count = Xutf8LookupString(SDL_IC, &xevent.xkey, keydata, count, &xkeysym, &status);
2576+ }
2577+
2578+ switch (status) {
2579+
2580+ case XBufferOverflow: {
2581+ /* Oops! We have allocated the bytes as
2582+ requested by Xutf8LookupString, so the
2583+ length of the buffer must be
2584+ sufficient. This case should never
2585+ happen! */
2586+ SDL_SetError("Xutf8LookupString indicated a double buffer overflow!");
2587+ break;
2588+ }
2589+
2590+ case XLookupChars:
2591+ case XLookupBoth: {
2592+ if (0 == count) {
2593+ break;
2594+ }
2595+
2596+ /* We got a converted string from IM. Make
2597+ sure to deliver all characters to the
2598+ application as SDL events. Note that
2599+ an SDL event can only carry one UTF-16
2600+ encoding unit, and a surrogate pair is
2601+ delivered as two SDL events. I guess
2602+ this behaviour is probably _imported_
2603+ from Windows or MacOS. To do so, we need
2604+ to convert the UTF-8 data into UTF-16
2605+ data (not UCS4/UTF-32!). We need an
2606+ estimate of the number of UTF-16 encoding
2607+ units here. The worst case is pure ASCII
2608+ string. Assume so. */
2609+ /* In 1.3 SDL may have a text event instead, that
2610+ carries the whole UTF-8 string with it. */
2611+ utf16size = count * sizeof(Uint16);
2612+ if (utf16size > sizeof(utf16buf)) {
2613+ utf16data = (Uint16 *) SDL_malloc(utf16size);
2614+ if (utf16data == NULL) {
2615+ SDL_OutOfMemory();
2616+ break;
2617+ }
2618+ }
2619+ utf16length = Utf8ToUtf16((Uint8 *)keydata, count, utf16data, utf16size);
2620+ if (utf16length < 0) {
2621+ /* The keydata contained an invalid byte
2622+ sequence. It should be a bug of the IM
2623+ or Xlib... */
2624+ SDL_SetError("Oops! Xutf8LookupString returned an invalid UTF-8 sequence!");
2625+ break;
2626+ }
2627+
2628+ /* Deliver all UTF-16 encoding units. At
2629+ this moment, SDL event queue has a
2630+ fixed size (128 events), and an SDL
2631+ event can hold just one UTF-16 encoding
2632+ unit. So, if we receive more than 128
2633+ UTF-16 encoding units from a commit,
2634+ exceeded characters will be lost. */
2635+ for (i = 0; i < utf16length - 1; i++) {
2636+ keysym.scancode = 0;
2637+ keysym.sym = SDLK_UNKNOWN;
2638+ keysym.mod = KMOD_NONE;
2639+ keysym.unicode = utf16data[i];
2640+ posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
2641+ }
2642+ /* The keysym for the last character carries the
2643+ scancode and symbol that corresponds to the X11
2644+ keycode. */
2645+ if (utf16length > 0) {
2646+ keysym.scancode = keycode;
2647+ keysym.sym = (keycode ? X11_TranslateKeycode(SDL_Display, keycode) : 0);
2648+ keysym.mod = KMOD_NONE;
2649+ keysym.unicode = utf16data[utf16length - 1];
2650+ posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
2651+ }
2652+ break;
2653+ }
2654+
2655+ case XLookupKeySym: {
2656+ /* I'm not sure whether it is possible that
2657+ a zero keycode makes XLookupKeySym
2658+ status. What I'm sure is that a
2659+ combination of a zero scan code and a non
2660+ zero sym makes SDL_PrivateKeyboard
2661+ strange state... So, just discard it.
2662+ If this doesn't work, I'm receiving bug
2663+ reports, and I can know under what
2664+ condition this case happens. */
2665+ if (keycode) {
2666+ keysym.scancode = keycode;
2667+ keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
2668+ keysym.mod = KMOD_NONE;
2669+ keysym.unicode = 0;
2670+ posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
2671+ }
2672+ break;
2673+ }
2674+
2675+ case XLookupNone: {
2676+ /* IM has eaten the event. */
2677+ break;
2678+ }
2679+
2680+ default:
2681+ /* An unknown status from Xutf8LookupString. */
2682+ SDL_SetError("Oops! Xutf8LookupStringreturned an unknown status");
2683+ }
2684+
2685+ /* Release dynamic buffers if allocated. */
2686+ if (keydata != NULL && keybuf != keydata) {
2687+ SDL_free(keydata);
2688+ }
2689+ if (utf16data != NULL && utf16buf != utf16data) {
2690+ SDL_free(utf16data);
2691+ }
2692+ }
2693+ else
2694+#endif
2695+ {
2696+ static XComposeStatus state;
2697+ char keybuf[32];
2698+
2699+ keysym.scancode = keycode;
2700+ keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
2701+ keysym.mod = KMOD_NONE;
2702+ keysym.unicode = 0;
2703+ if ( XLookupString(&xevent.xkey,
2704+ keybuf, sizeof(keybuf),
2705+ NULL, &state) ) {
2706+ /*
2707+ * FIXME: XLookupString() may yield more than one
2708+ * character, so we need a mechanism to allow for
2709+ * this (perhaps null keypress events with a
2710+ * unicode value)
2711+ */
2712+ keysym.unicode = (Uint8)keybuf[0];
2713+ }
2714+
2715+ posted = SDL_PrivateKeyboard(SDL_PRESSED, &keysym);
2716+ }
2717+ }
2718+ break;
2719+
2720+ /* Key release? */
2721+ case KeyRelease: {
2722+ SDL_keysym keysym;
2723+ KeyCode keycode = xevent.xkey.keycode;
2724+
2725+ if (keycode == 0) {
2726+ /* There should be no KeyRelease for keycode == 0,
2727+ since it is a notification from IM but a real
2728+ keystroke. */
2729+ /* We need to emit some diagnostic message here. */
2730+ break;
2731+ }
2732+
2733+#ifdef DEBUG_XEVENTS
2734+printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
2735+#endif
2736+
2737+ /* Get the translated SDL virtual keysym */
2738+ keysym.scancode = keycode;
2739+ keysym.sym = X11_TranslateKeycode(SDL_Display, keycode);
2740+ keysym.mod = KMOD_NONE;
2741+ keysym.unicode = 0;
2742+
2743+ posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym);
2744+ }
2745+ break;
2746+
2747+ /* Have we been iconified? */
2748+ case UnmapNotify: {
2749+#ifdef DEBUG_XEVENTS
2750+printf("UnmapNotify!\n");
2751+#endif
2752+ /* If we're active, make ourselves inactive */
2753+ if ( SDL_GetAppState() & SDL_APPACTIVE ) {
2754+ /* Swap out the gamma before we go inactive */
2755+ X11_SwapVidModeGamma(this);
2756+
2757+ /* Send an internal deactivate event */
2758+ posted = SDL_PrivateAppActive(0,
2759+ SDL_APPACTIVE|SDL_APPINPUTFOCUS);
2760+ }
2761+ }
2762+ break;
2763+
2764+ /* Have we been restored? */
2765+ case MapNotify: {
2766+#ifdef DEBUG_XEVENTS
2767+printf("MapNotify!\n");
2768+#endif
2769+ /* If we're not active, make ourselves active */
2770+ if ( !(SDL_GetAppState() & SDL_APPACTIVE) ) {
2771+ /* Send an internal activate event */
2772+ posted = SDL_PrivateAppActive(1, SDL_APPACTIVE);
2773+
2774+ /* Now that we're active, swap the gamma back */
2775+ X11_SwapVidModeGamma(this);
2776+ }
2777+
2778+ if ( SDL_VideoSurface &&
2779+ (SDL_VideoSurface->flags & SDL_FULLSCREEN) ) {
2780+ X11_EnterFullScreen(this);
2781+ } else {
2782+ X11_GrabInputNoLock(this, this->input_grab);
2783+ }
2784+ X11_CheckMouseModeNoLock(this);
2785+
2786+ if ( SDL_VideoSurface ) {
2787+ X11_RefreshDisplay(this);
2788+ }
2789+ }
2790+ break;
2791+
2792+ /* Have we been resized or moved? */
2793+ case ConfigureNotify: {
2794+#ifdef DEBUG_XEVENTS
2795+printf("ConfigureNotify! (resize: %dx%d)\n", xevent.xconfigure.width, xevent.xconfigure.height);
2796+#endif
2797+ if ((X11_PendingConfigureNotifyWidth != -1) &&
2798+ (X11_PendingConfigureNotifyHeight != -1)) {
2799+ if ((xevent.xconfigure.width != X11_PendingConfigureNotifyWidth) &&
2800+ (xevent.xconfigure.height != X11_PendingConfigureNotifyHeight)) {
2801+ /* Event is from before the resize, so ignore. */
2802+ break;
2803+ }
2804+ X11_PendingConfigureNotifyWidth = -1;
2805+ X11_PendingConfigureNotifyHeight = -1;
2806+ }
2807+ if ( SDL_VideoSurface ) {
2808+ if ((xevent.xconfigure.width != SDL_VideoSurface->w) ||
2809+ (xevent.xconfigure.height != SDL_VideoSurface->h)) {
2810+ /* FIXME: Find a better fix for the bug with KDE 1.2 */
2811+ if ( ! ((xevent.xconfigure.width == 32) &&
2812+ (xevent.xconfigure.height == 32)) ) {
2813+ SDL_PrivateResize(xevent.xconfigure.width,
2814+ xevent.xconfigure.height);
2815+ }
2816+ } else {
2817+ /* OpenGL windows need to know about the change */
2818+ if ( SDL_VideoSurface->flags & SDL_OPENGL ) {
2819+ SDL_PrivateExpose();
2820+ }
2821+ }
2822+ }
2823+ }
2824+ break;
2825+
2826+ /* Have we been requested to quit (or another client message?) */
2827+ case ClientMessage: {
2828+ if ( (xevent.xclient.format == 32) &&
2829+ (xevent.xclient.data.l[0] == WM_DELETE_WINDOW) )
2830+ {
2831+ posted = SDL_PrivateQuit();
2832+ } else
2833+ if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
2834+ SDL_SysWMmsg wmmsg;
2835+
2836+ SDL_VERSION(&wmmsg.version);
2837+ wmmsg.subsystem = SDL_SYSWM_X11;
2838+ wmmsg.event.xevent = xevent;
2839+ posted = SDL_PrivateSysWMEvent(&wmmsg);
2840+ }
2841+ }
2842+ break;
2843+
2844+ /* Do we need to refresh ourselves? */
2845+ case Expose: {
2846+#ifdef DEBUG_XEVENTS
2847+printf("Expose (count = %d)\n", xevent.xexpose.count);
2848+#endif
2849+ if ( SDL_VideoSurface && (xevent.xexpose.count == 0) ) {
2850+ X11_RefreshDisplay(this);
2851+ }
2852+ }
2853+ break;
2854+
2855+ default: {
2856+#ifdef DEBUG_XEVENTS
2857+printf("Unhandled event %d\n", xevent.type);
2858+#endif
2859+ /* Only post the event if we're watching for it */
2860+ if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
2861+ SDL_SysWMmsg wmmsg;
2862+
2863+ SDL_VERSION(&wmmsg.version);
2864+ wmmsg.subsystem = SDL_SYSWM_X11;
2865+ wmmsg.event.xevent = xevent;
2866+ posted = SDL_PrivateSysWMEvent(&wmmsg);
2867+ }
2868+ }
2869+ break;
2870+ }
2871+ return(posted);
2872+}
2873+
2874+/* Ack! XPending() actually performs a blocking read if no events available */
2875+int X11_Pending(Display *display)
2876+{
2877+ /* Flush the display connection and look to see if events are queued */
2878+ XFlush(display);
2879+ if ( XEventsQueued(display, QueuedAlready) ) {
2880+ return(1);
2881+ }
2882+
2883+ /* More drastic measures are required -- see if X is ready to talk */
2884+ {
2885+ static struct timeval zero_time; /* static == 0 */
2886+ int x11_fd;
2887+ fd_set fdset;
2888+
2889+ x11_fd = ConnectionNumber(display);
2890+ FD_ZERO(&fdset);
2891+ FD_SET(x11_fd, &fdset);
2892+ if ( select(x11_fd+1, &fdset, NULL, NULL, &zero_time) == 1 ) {
2893+ return(XPending(display));
2894+ }
2895+ }
2896+
2897+ /* Oh well, nothing is ready .. */
2898+ return(0);
2899+}
2900+
2901+void X11_PumpEvents(_THIS)
2902+{
2903+ int pending;
2904+
2905+ /* Update activity every five seconds to prevent screensaver. --ryan. */
2906+ if (!allow_screensaver) {
2907+ static Uint32 screensaverTicks;
2908+ Uint32 nowTicks = SDL_GetTicks();
2909+ if ((nowTicks - screensaverTicks) > 5000) {
2910+ XResetScreenSaver(SDL_Display);
2911+ screensaverTicks = nowTicks;
2912+ }
2913+ }
2914+
2915+ /* Keep processing pending events */
2916+ pending = 0;
2917+ while ( X11_Pending(SDL_Display) ) {
2918+ X11_DispatchEvent(this);
2919+ ++pending;
2920+ }
2921+ if ( switch_waiting ) {
2922+ Uint32 now;
2923+
2924+ now = SDL_GetTicks();
2925+ if ( pending || !SDL_VideoSurface ) {
2926+ /* Try again later... */
2927+ if ( switch_waiting & SDL_FULLSCREEN ) {
2928+ switch_time = now + 1500;
2929+ } else {
2930+ switch_time = now + 200;
2931+ }
2932+ } else if ( (int)(switch_time-now) <= 0 ) {
2933+ Uint32 go_fullscreen;
2934+
2935+ go_fullscreen = switch_waiting & SDL_FULLSCREEN;
2936+ switch_waiting = 0;
2937+ if ( SDL_VideoSurface->flags & SDL_FULLSCREEN ) {
2938+ if ( go_fullscreen ) {
2939+ X11_EnterFullScreen(this);
2940+ } else {
2941+ X11_LeaveFullScreen(this);
2942+ }
2943+ }
2944+ /* Handle focus in/out when grabbed */
2945+ if ( go_fullscreen ) {
2946+ X11_GrabInputNoLock(this, this->input_grab);
2947+ } else {
2948+ X11_GrabInputNoLock(this, SDL_GRAB_OFF);
2949+ }
2950+ X11_CheckMouseModeNoLock(this);
2951+ }
2952+ }
2953+}
2954+
2955+void X11_InitKeymap(void)
2956+{
2957+ int i;
2958+
2959+ /* Odd keys used in international keyboards */
2960+ for ( i=0; i<SDL_arraysize(ODD_keymap); ++i )
2961+ ODD_keymap[i] = SDLK_UNKNOWN;
2962+
2963+ /* Some of these might be mappable to an existing SDLK_ code */
2964+ ODD_keymap[XK_dead_grave&0xFF] = SDLK_COMPOSE;
2965+ ODD_keymap[XK_dead_acute&0xFF] = SDLK_COMPOSE;
2966+ ODD_keymap[XK_dead_tilde&0xFF] = SDLK_COMPOSE;
2967+ ODD_keymap[XK_dead_macron&0xFF] = SDLK_COMPOSE;
2968+ ODD_keymap[XK_dead_breve&0xFF] = SDLK_COMPOSE;
2969+ ODD_keymap[XK_dead_abovedot&0xFF] = SDLK_COMPOSE;
2970+ ODD_keymap[XK_dead_diaeresis&0xFF] = SDLK_COMPOSE;
2971+ ODD_keymap[XK_dead_abovering&0xFF] = SDLK_COMPOSE;
2972+ ODD_keymap[XK_dead_doubleacute&0xFF] = SDLK_COMPOSE;
2973+ ODD_keymap[XK_dead_caron&0xFF] = SDLK_COMPOSE;
2974+ ODD_keymap[XK_dead_cedilla&0xFF] = SDLK_COMPOSE;
2975+ ODD_keymap[XK_dead_ogonek&0xFF] = SDLK_COMPOSE;
2976+ ODD_keymap[XK_dead_iota&0xFF] = SDLK_COMPOSE;
2977+ ODD_keymap[XK_dead_voiced_sound&0xFF] = SDLK_COMPOSE;
2978+ ODD_keymap[XK_dead_semivoiced_sound&0xFF] = SDLK_COMPOSE;
2979+ ODD_keymap[XK_dead_belowdot&0xFF] = SDLK_COMPOSE;
2980+#ifdef XK_dead_hook
2981+ ODD_keymap[XK_dead_hook&0xFF] = SDLK_COMPOSE;
2982+#endif
2983+#ifdef XK_dead_horn
2984+ ODD_keymap[XK_dead_horn&0xFF] = SDLK_COMPOSE;
2985+#endif
2986+
2987+#ifdef XK_dead_circumflex
2988+ /* These X keysyms have 0xFE as the high byte */
2989+ ODD_keymap[XK_dead_circumflex&0xFF] = SDLK_CARET;
2990+#endif
2991+#ifdef XK_ISO_Level3_Shift
2992+ ODD_keymap[XK_ISO_Level3_Shift&0xFF] = SDLK_MODE; /* "Alt Gr" key */
2993+#endif
2994+
2995+ /* Map the miscellaneous keys */
2996+ for ( i=0; i<SDL_arraysize(MISC_keymap); ++i )
2997+ MISC_keymap[i] = SDLK_UNKNOWN;
2998+
2999+ /* These X keysyms have 0xFF as the high byte */
3000+ MISC_keymap[XK_BackSpace&0xFF] = SDLK_BACKSPACE;
3001+ MISC_keymap[XK_Tab&0xFF] = SDLK_TAB;
3002+ MISC_keymap[XK_Clear&0xFF] = SDLK_CLEAR;
3003+ MISC_keymap[XK_Return&0xFF] = SDLK_RETURN;
3004+ MISC_keymap[XK_Pause&0xFF] = SDLK_PAUSE;
3005+ MISC_keymap[XK_Escape&0xFF] = SDLK_ESCAPE;
3006+ MISC_keymap[XK_Delete&0xFF] = SDLK_DELETE;
3007+
3008+ MISC_keymap[XK_KP_0&0xFF] = SDLK_KP0; /* Keypad 0-9 */
3009+ MISC_keymap[XK_KP_1&0xFF] = SDLK_KP1;
3010+ MISC_keymap[XK_KP_2&0xFF] = SDLK_KP2;
3011+ MISC_keymap[XK_KP_3&0xFF] = SDLK_KP3;
3012+ MISC_keymap[XK_KP_4&0xFF] = SDLK_KP4;
3013+ MISC_keymap[XK_KP_5&0xFF] = SDLK_KP5;
3014+ MISC_keymap[XK_KP_6&0xFF] = SDLK_KP6;
3015+ MISC_keymap[XK_KP_7&0xFF] = SDLK_KP7;
3016+ MISC_keymap[XK_KP_8&0xFF] = SDLK_KP8;
3017+ MISC_keymap[XK_KP_9&0xFF] = SDLK_KP9;
3018+ MISC_keymap[XK_KP_Insert&0xFF] = SDLK_KP0;
3019+ MISC_keymap[XK_KP_End&0xFF] = SDLK_KP1;
3020+ MISC_keymap[XK_KP_Down&0xFF] = SDLK_KP2;
3021+ MISC_keymap[XK_KP_Page_Down&0xFF] = SDLK_KP3;
3022+ MISC_keymap[XK_KP_Left&0xFF] = SDLK_KP4;
3023+ MISC_keymap[XK_KP_Begin&0xFF] = SDLK_KP5;
3024+ MISC_keymap[XK_KP_Right&0xFF] = SDLK_KP6;
3025+ MISC_keymap[XK_KP_Home&0xFF] = SDLK_KP7;
3026+ MISC_keymap[XK_KP_Up&0xFF] = SDLK_KP8;
3027+ MISC_keymap[XK_KP_Page_Up&0xFF] = SDLK_KP9;
3028+ MISC_keymap[XK_KP_Delete&0xFF] = SDLK_KP_PERIOD;
3029+ MISC_keymap[XK_KP_Decimal&0xFF] = SDLK_KP_PERIOD;
3030+ MISC_keymap[XK_KP_Divide&0xFF] = SDLK_KP_DIVIDE;
3031+ MISC_keymap[XK_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY;
3032+ MISC_keymap[XK_KP_Subtract&0xFF] = SDLK_KP_MINUS;
3033+ MISC_keymap[XK_KP_Add&0xFF] = SDLK_KP_PLUS;
3034+ MISC_keymap[XK_KP_Enter&0xFF] = SDLK_KP_ENTER;
3035+ MISC_keymap[XK_KP_Equal&0xFF] = SDLK_KP_EQUALS;
3036+
3037+ MISC_keymap[XK_Up&0xFF] = SDLK_UP;
3038+ MISC_keymap[XK_Down&0xFF] = SDLK_DOWN;
3039+ MISC_keymap[XK_Right&0xFF] = SDLK_RIGHT;
3040+ MISC_keymap[XK_Left&0xFF] = SDLK_LEFT;
3041+ MISC_keymap[XK_Insert&0xFF] = SDLK_INSERT;
3042+ MISC_keymap[XK_Home&0xFF] = SDLK_HOME;
3043+ MISC_keymap[XK_End&0xFF] = SDLK_END;
3044+ MISC_keymap[XK_Page_Up&0xFF] = SDLK_PAGEUP;
3045+ MISC_keymap[XK_Page_Down&0xFF] = SDLK_PAGEDOWN;
3046+
3047+ MISC_keymap[XK_F1&0xFF] = SDLK_F1;
3048+ MISC_keymap[XK_F2&0xFF] = SDLK_F2;
3049+ MISC_keymap[XK_F3&0xFF] = SDLK_F3;
3050+ MISC_keymap[XK_F4&0xFF] = SDLK_F4;
3051+ MISC_keymap[XK_F5&0xFF] = SDLK_F5;
3052+ MISC_keymap[XK_F6&0xFF] = SDLK_F6;
3053+ MISC_keymap[XK_F7&0xFF] = SDLK_F7;
3054+ MISC_keymap[XK_F8&0xFF] = SDLK_F8;
3055+ MISC_keymap[XK_F9&0xFF] = SDLK_F9;
3056+ MISC_keymap[XK_F10&0xFF] = SDLK_F10;
3057+ MISC_keymap[XK_F11&0xFF] = SDLK_F11;
3058+ MISC_keymap[XK_F12&0xFF] = SDLK_F12;
3059+ MISC_keymap[XK_F13&0xFF] = SDLK_F13;
3060+ MISC_keymap[XK_F14&0xFF] = SDLK_F14;
3061+ MISC_keymap[XK_F15&0xFF] = SDLK_F15;
3062+
3063+ MISC_keymap[XK_Num_Lock&0xFF] = SDLK_NUMLOCK;
3064+ MISC_keymap[XK_Caps_Lock&0xFF] = SDLK_CAPSLOCK;
3065+ MISC_keymap[XK_Scroll_Lock&0xFF] = SDLK_SCROLLOCK;
3066+ MISC_keymap[XK_Shift_R&0xFF] = SDLK_RSHIFT;
3067+ MISC_keymap[XK_Shift_L&0xFF] = SDLK_LSHIFT;
3068+ MISC_keymap[XK_Control_R&0xFF] = SDLK_RCTRL;
3069+ MISC_keymap[XK_Control_L&0xFF] = SDLK_LCTRL;
3070+ MISC_keymap[XK_Alt_R&0xFF] = SDLK_RALT;
3071+ MISC_keymap[XK_Alt_L&0xFF] = SDLK_LALT;
3072+ MISC_keymap[XK_Meta_R&0xFF] = SDLK_RMETA;
3073+ MISC_keymap[XK_Meta_L&0xFF] = SDLK_LMETA;
3074+ MISC_keymap[XK_Super_L&0xFF] = SDLK_LSUPER; /* Left "Windows" */
3075+ MISC_keymap[XK_Super_R&0xFF] = SDLK_RSUPER; /* Right "Windows */
3076+ MISC_keymap[XK_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */
3077+ MISC_keymap[XK_Multi_key&0xFF] = SDLK_COMPOSE; /* Multi-key compose */
3078+
3079+ MISC_keymap[XK_Help&0xFF] = SDLK_HELP;
3080+ MISC_keymap[XK_Print&0xFF] = SDLK_PRINT;
3081+ MISC_keymap[XK_Sys_Req&0xFF] = SDLK_SYSREQ;
3082+ MISC_keymap[XK_Break&0xFF] = SDLK_BREAK;
3083+ MISC_keymap[XK_Menu&0xFF] = SDLK_MENU;
3084+ MISC_keymap[XK_Hyper_R&0xFF] = SDLK_MENU; /* Windows "Menu" key */
3085+}
3086+
3087+/* Get the translated SDL virtual keysym */
3088+SDLKey X11_TranslateKeycode(Display *display, KeyCode kc)
3089+{
3090+ KeySym xsym;
3091+ SDLKey key;
3092+
3093+ xsym = XKeycodeToKeysym(display, kc, 0);
3094+#ifdef DEBUG_KEYS
3095+ fprintf(stderr, "Translating key code %d -> 0x%.4x\n", kc, xsym);
3096+#endif
3097+ key = SDLK_UNKNOWN;
3098+ if ( xsym ) {
3099+ switch (xsym>>8) {
3100+ case 0x1005FF:
3101+#ifdef SunXK_F36
3102+ if ( xsym == SunXK_F36 )
3103+ key = SDLK_F11;
3104+#endif
3105+#ifdef SunXK_F37
3106+ if ( xsym == SunXK_F37 )
3107+ key = SDLK_F12;
3108+#endif
3109+ break;
3110+ case 0x00: /* Latin 1 */
3111+ key = (SDLKey)(xsym & 0xFF);
3112+ break;
3113+ case 0x01: /* Latin 2 */
3114+ case 0x02: /* Latin 3 */
3115+ case 0x03: /* Latin 4 */
3116+ case 0x04: /* Katakana */
3117+ case 0x05: /* Arabic */
3118+ case 0x06: /* Cyrillic */
3119+ case 0x07: /* Greek */
3120+ case 0x08: /* Technical */
3121+ case 0x0A: /* Publishing */
3122+ case 0x0C: /* Hebrew */
3123+ case 0x0D: /* Thai */
3124+ /* These are wrong, but it's better than nothing */
3125+ key = (SDLKey)(xsym & 0xFF);
3126+ break;
3127+ case 0xFE:
3128+ key = ODD_keymap[xsym&0xFF];
3129+ break;
3130+ case 0xFF:
3131+ key = MISC_keymap[xsym&0xFF];
3132+ break;
3133+ default:
3134+ /*
3135+ fprintf(stderr, "X11: Unhandled xsym, sym = 0x%04x\n",
3136+ (unsigned int)xsym);
3137+ */
3138+ break;
3139+ }
3140+ } else {
3141+ /* X11 doesn't know how to translate the key! */
3142+ switch (kc) {
3143+ /* Caution:
3144+ These keycodes are from the Microsoft Keyboard
3145+ */
3146+ case 115:
3147+ key = SDLK_LSUPER;
3148+ break;
3149+ case 116:
3150+ key = SDLK_RSUPER;
3151+ break;
3152+ case 117:
3153+ key = SDLK_MENU;
3154+ break;
3155+ default:
3156+ /*
3157+ * no point in an error message; happens for
3158+ * several keys when we get a keymap notify
3159+ */
3160+ break;
3161+ }
3162+ }
3163+ return key;
3164+}
3165+
3166+/* X11 modifier masks for various keys */
3167+static unsigned meta_l_mask, meta_r_mask, alt_l_mask, alt_r_mask;
3168+static unsigned num_mask, mode_switch_mask;
3169+
3170+static void get_modifier_masks(Display *display)
3171+{
3172+ static unsigned got_masks;
3173+ int i, j;
3174+ XModifierKeymap *xmods;
3175+ unsigned n;
3176+
3177+ if(got_masks)
3178+ return;
3179+
3180+ xmods = XGetModifierMapping(display);
3181+ n = xmods->max_keypermod;
3182+ for(i = 3; i < 8; i++) {
3183+ for(j = 0; j < n; j++) {
3184+ KeyCode kc = xmods->modifiermap[i * n + j];
3185+ KeySym ks = XKeycodeToKeysym(display, kc, 0);
3186+ unsigned mask = 1 << i;
3187+ switch(ks) {
3188+ case XK_Num_Lock:
3189+ num_mask = mask; break;
3190+ case XK_Alt_L:
3191+ alt_l_mask = mask; break;
3192+ case XK_Alt_R:
3193+ alt_r_mask = mask; break;
3194+ case XK_Meta_L:
3195+ meta_l_mask = mask; break;
3196+ case XK_Meta_R:
3197+ meta_r_mask = mask; break;
3198+ case XK_Mode_switch:
3199+ mode_switch_mask = mask; break;
3200+ }
3201+ }
3202+ }
3203+ XFreeModifiermap(xmods);
3204+ got_masks = 1;
3205+}
3206+
3207+
3208+/*
3209+ * This function is semi-official; it is not officially exported and should
3210+ * not be considered part of the SDL API, but may be used by client code
3211+ * that *really* needs it (including legacy code).
3212+ * It is slow, though, and should be avoided if possible.
3213+ *
3214+ * Note that it isn't completely accurate either; in particular, multi-key
3215+ * sequences (dead accents, compose key sequences) will not work since the
3216+ * state has been irrevocably lost.
3217+ */
3218+extern DECLSPEC Uint16 SDLCALL X11_KeyToUnicode(SDLKey, SDLMod);
3219+
3220+Uint16 X11_KeyToUnicode(SDLKey keysym, SDLMod modifiers)
3221+{
3222+ static int warning = 1;
3223+ struct SDL_VideoDevice *this = current_video;
3224+ char keybuf[32];
3225+ int i;
3226+ KeySym xsym = 0;
3227+ XKeyEvent xkey;
3228+ Uint16 unicode;
3229+
3230+ if ( warning ) {
3231+ warning = 0;
3232+ fprintf(stderr, "WARNING: Application is using X11_KeyToUnicode().\n");
3233+ fprintf(stderr, "This is not an official SDL function, please report this as a bug.\n");
3234+ }
3235+
3236+ if ( !this || !SDL_Display ) {
3237+ return 0;
3238+ }
3239+
3240+ SDL_memset(&xkey, 0, sizeof(xkey));
3241+ xkey.display = SDL_Display;
3242+
3243+ xsym = keysym; /* last resort if not found */
3244+ for (i = 0; i < 256; ++i) {
3245+ if ( MISC_keymap[i] == keysym ) {
3246+ xsym = 0xFF00 | i;
3247+ break;
3248+ } else if ( ODD_keymap[i] == keysym ) {
3249+ xsym = 0xFE00 | i;
3250+ break;
3251+ }
3252+ }
3253+
3254+ xkey.keycode = XKeysymToKeycode(xkey.display, xsym);
3255+
3256+ get_modifier_masks(SDL_Display);
3257+ if(modifiers & KMOD_SHIFT)
3258+ xkey.state |= ShiftMask;
3259+ if(modifiers & KMOD_CAPS)
3260+ xkey.state |= LockMask;
3261+ if(modifiers & KMOD_CTRL)
3262+ xkey.state |= ControlMask;
3263+ if(modifiers & KMOD_MODE)
3264+ xkey.state |= mode_switch_mask;
3265+ if(modifiers & KMOD_LALT)
3266+ xkey.state |= alt_l_mask;
3267+ if(modifiers & KMOD_RALT)
3268+ xkey.state |= alt_r_mask;
3269+ if(modifiers & KMOD_LMETA)
3270+ xkey.state |= meta_l_mask;
3271+ if(modifiers & KMOD_RMETA)
3272+ xkey.state |= meta_r_mask;
3273+ if(modifiers & KMOD_NUM)
3274+ xkey.state |= num_mask;
3275+
3276+ unicode = 0;
3277+ if ( XLookupString(&xkey, keybuf, sizeof(keybuf), NULL, NULL) )
3278+ unicode = (unsigned char)keybuf[0];
3279+ return(unicode);
3280+}
3281+
3282+
3283+/*
3284+ * Called when focus is regained, to read the keyboard state and generate
3285+ * synthetic keypress/release events.
3286+ * key_vec is a bit vector of keycodes (256 bits)
3287+ */
3288+void X11_SetKeyboardState(Display *display, const char *key_vec)
3289+{
3290+ char keys_return[32];
3291+ int i;
3292+ Uint8 *kstate = SDL_GetKeyState(NULL);
3293+ SDLMod modstate;
3294+ Window junk_window;
3295+ int x, y;
3296+ unsigned int mask;
3297+
3298+ /* The first time the window is mapped, we initialize key state */
3299+ if ( ! key_vec ) {
3300+ XQueryKeymap(display, keys_return);
3301+ key_vec = keys_return;
3302+ }
3303+
3304+ /* Get the keyboard modifier state */
3305+ modstate = 0;
3306+ get_modifier_masks(display);
3307+ if ( XQueryPointer(display, DefaultRootWindow(display),
3308+ &junk_window, &junk_window, &x, &y, &x, &y, &mask) ) {
3309+ if ( mask & LockMask ) {
3310+ modstate |= KMOD_CAPS;
3311+ }
3312+ if ( mask & mode_switch_mask ) {
3313+ modstate |= KMOD_MODE;
3314+ }
3315+ if ( mask & num_mask ) {
3316+ modstate |= KMOD_NUM;
3317+ }
3318+ }
3319+
3320+ /* Zero the new keyboard state and generate it */
3321+ SDL_memset(kstate, 0, SDLK_LAST);
3322+ /*
3323+ * An obvious optimisation is to check entire longwords at a time in
3324+ * both loops, but we can't be sure the arrays are aligned so it's not
3325+ * worth the extra complexity
3326+ */
3327+ for ( i = 0; i < 32; i++ ) {
3328+ int j;
3329+ if ( !key_vec[i] )
3330+ continue;
3331+ for ( j = 0; j < 8; j++ ) {
3332+ if ( key_vec[i] & (1 << j) ) {
3333+ SDLKey key;
3334+ KeyCode kc = (i << 3 | j);
3335+ key = X11_TranslateKeycode(display, kc);
3336+ if ( key == SDLK_UNKNOWN ) {
3337+ continue;
3338+ }
3339+ kstate[key] = SDL_PRESSED;
3340+ switch (key) {
3341+ case SDLK_LSHIFT:
3342+ modstate |= KMOD_LSHIFT;
3343+ break;
3344+ case SDLK_RSHIFT:
3345+ modstate |= KMOD_RSHIFT;
3346+ break;
3347+ case SDLK_LCTRL:
3348+ modstate |= KMOD_LCTRL;
3349+ break;
3350+ case SDLK_RCTRL:
3351+ modstate |= KMOD_RCTRL;
3352+ break;
3353+ case SDLK_LALT:
3354+ modstate |= KMOD_LALT;
3355+ break;
3356+ case SDLK_RALT:
3357+ modstate |= KMOD_RALT;
3358+ break;
3359+ case SDLK_LMETA:
3360+ modstate |= KMOD_LMETA;
3361+ break;
3362+ case SDLK_RMETA:
3363+ modstate |= KMOD_RMETA;
3364+ break;
3365+ default:
3366+ break;
3367+ }
3368+ }
3369+ }
3370+ }
3371+
3372+ /* Hack - set toggle key state */
3373+ if ( modstate & KMOD_CAPS ) {
3374+ kstate[SDLK_CAPSLOCK] = SDL_PRESSED;
3375+ } else {
3376+ kstate[SDLK_CAPSLOCK] = SDL_RELEASED;
3377+ }
3378+ if ( modstate & KMOD_NUM ) {
3379+ kstate[SDLK_NUMLOCK] = SDL_PRESSED;
3380+ } else {
3381+ kstate[SDLK_NUMLOCK] = SDL_RELEASED;
3382+ }
3383+
3384+ /* Set the final modifier state */
3385+ SDL_SetModState(modstate);
3386+}
3387+
3388+void X11_InitOSKeymap(_THIS)
3389+{
3390+ X11_InitKeymap();
3391+}
3392+
3393
3394=== added file '.pc/fix_window_resizing.diff/src/video/x11/SDL_x11events_c.h'
3395--- .pc/fix_window_resizing.diff/src/video/x11/SDL_x11events_c.h 1970-01-01 00:00:00 +0000
3396+++ .pc/fix_window_resizing.diff/src/video/x11/SDL_x11events_c.h 2015-06-01 21:40:05 +0000
3397@@ -0,0 +1,34 @@
3398+/*
3399+ SDL - Simple DirectMedia Layer
3400+ Copyright (C) 1997-2012 Sam Lantinga
3401+
3402+ This library is free software; you can redistribute it and/or
3403+ modify it under the terms of the GNU Lesser General Public
3404+ License as published by the Free Software Foundation; either
3405+ version 2.1 of the License, or (at your option) any later version.
3406+
3407+ This library is distributed in the hope that it will be useful,
3408+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3409+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3410+ Lesser General Public License for more details.
3411+
3412+ You should have received a copy of the GNU Lesser General Public
3413+ License along with this library; if not, write to the Free Software
3414+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3415+
3416+ Sam Lantinga
3417+ slouken@libsdl.org
3418+*/
3419+#include "SDL_config.h"
3420+
3421+#include "SDL_x11video.h"
3422+
3423+/* Functions to be exported */
3424+extern void X11_InitOSKeymap(_THIS);
3425+extern void X11_PumpEvents(_THIS);
3426+extern void X11_SetKeyboardState(Display *display, const char *key_vec);
3427+
3428+/* Variables to be exported */
3429+extern int X11_PendingConfigureNotifyWidth;
3430+extern int X11_PendingConfigureNotifyHeight;
3431+
3432
3433=== added file '.pc/fix_window_resizing.diff/src/video/x11/SDL_x11video.c'
3434--- .pc/fix_window_resizing.diff/src/video/x11/SDL_x11video.c 1970-01-01 00:00:00 +0000
3435+++ .pc/fix_window_resizing.diff/src/video/x11/SDL_x11video.c 2015-06-01 21:40:05 +0000
3436@@ -0,0 +1,1571 @@
3437+/*
3438+ SDL - Simple DirectMedia Layer
3439+ Copyright (C) 1997-2012 Sam Lantinga
3440+
3441+ This library is free software; you can redistribute it and/or
3442+ modify it under the terms of the GNU Lesser General Public
3443+ License as published by the Free Software Foundation; either
3444+ version 2.1 of the License, or (at your option) any later version.
3445+
3446+ This library is distributed in the hope that it will be useful,
3447+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3448+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3449+ Lesser General Public License for more details.
3450+
3451+ You should have received a copy of the GNU Lesser General Public
3452+ License along with this library; if not, write to the Free Software
3453+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3454+
3455+ Sam Lantinga
3456+ slouken@libsdl.org
3457+*/
3458+#include "SDL_config.h"
3459+
3460+/* X11 based SDL video driver implementation.
3461+ Note: This implementation does not currently need X11 thread locking,
3462+ since the event thread uses a separate X connection and any
3463+ additional locking necessary is handled internally. However,
3464+ if full locking is neccessary, take a look at XInitThreads().
3465+*/
3466+
3467+#include <unistd.h>
3468+#include <sys/ioctl.h>
3469+#ifdef MTRR_SUPPORT
3470+#include <asm/mtrr.h>
3471+#include <sys/fcntl.h>
3472+#endif
3473+
3474+#include "SDL_endian.h"
3475+#include "SDL_timer.h"
3476+#include "SDL_thread.h"
3477+#include "SDL_video.h"
3478+#include "SDL_mouse.h"
3479+#include "../SDL_sysvideo.h"
3480+#include "../SDL_pixels_c.h"
3481+#include "../../events/SDL_events_c.h"
3482+#include "SDL_x11video.h"
3483+#include "SDL_x11wm_c.h"
3484+#include "SDL_x11mouse_c.h"
3485+#include "SDL_x11events_c.h"
3486+#include "SDL_x11modes_c.h"
3487+#include "SDL_x11image_c.h"
3488+#include "SDL_x11yuv_c.h"
3489+#include "SDL_x11gl_c.h"
3490+#include "SDL_x11gamma_c.h"
3491+#include "../blank_cursor.h"
3492+
3493+#ifdef X_HAVE_UTF8_STRING
3494+#include <locale.h>
3495+#endif
3496+
3497+/* Initialization/Query functions */
3498+static int X11_VideoInit(_THIS, SDL_PixelFormat *vformat);
3499+static SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
3500+static int X11_ToggleFullScreen(_THIS, int on);
3501+static void X11_UpdateMouse(_THIS);
3502+static int X11_SetColors(_THIS, int firstcolor, int ncolors,
3503+ SDL_Color *colors);
3504+static int X11_SetGammaRamp(_THIS, Uint16 *ramp);
3505+static void X11_VideoQuit(_THIS);
3506+
3507+
3508+/* X11 driver bootstrap functions */
3509+
3510+static int X11_Available(void)
3511+{
3512+ Display *display = NULL;
3513+ if ( SDL_X11_LoadSymbols() ) {
3514+ display = XOpenDisplay(NULL);
3515+ if ( display != NULL ) {
3516+ XCloseDisplay(display);
3517+ }
3518+ SDL_X11_UnloadSymbols();
3519+ }
3520+ return(display != NULL);
3521+}
3522+
3523+static void X11_DeleteDevice(SDL_VideoDevice *device)
3524+{
3525+ if ( device ) {
3526+ if ( device->hidden ) {
3527+ SDL_free(device->hidden);
3528+ }
3529+ if ( device->gl_data ) {
3530+ SDL_free(device->gl_data);
3531+ }
3532+ SDL_free(device);
3533+ SDL_X11_UnloadSymbols();
3534+ }
3535+}
3536+
3537+static SDL_VideoDevice *X11_CreateDevice(int devindex)
3538+{
3539+ SDL_VideoDevice *device = NULL;
3540+
3541+ if ( SDL_X11_LoadSymbols() ) {
3542+ /* Initialize all variables that we clean on shutdown */
3543+ device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
3544+ if ( device ) {
3545+ SDL_memset(device, 0, (sizeof *device));
3546+ device->hidden = (struct SDL_PrivateVideoData *)
3547+ SDL_malloc((sizeof *device->hidden));
3548+ device->gl_data = (struct SDL_PrivateGLData *)
3549+ SDL_malloc((sizeof *device->gl_data));
3550+ }
3551+ if ( (device == NULL) || (device->hidden == NULL) ||
3552+ (device->gl_data == NULL) ) {
3553+ SDL_OutOfMemory();
3554+ X11_DeleteDevice(device); /* calls SDL_X11_UnloadSymbols(). */
3555+ return(0);
3556+ }
3557+ SDL_memset(device->hidden, 0, (sizeof *device->hidden));
3558+ SDL_memset(device->gl_data, 0, (sizeof *device->gl_data));
3559+
3560+#if SDL_VIDEO_OPENGL_GLX
3561+ device->gl_data->swap_interval = -1;
3562+#endif
3563+
3564+ /* Set the driver flags */
3565+ device->handles_any_size = 1;
3566+
3567+ /* Set the function pointers */
3568+ device->VideoInit = X11_VideoInit;
3569+ device->ListModes = X11_ListModes;
3570+ device->SetVideoMode = X11_SetVideoMode;
3571+ device->ToggleFullScreen = X11_ToggleFullScreen;
3572+ device->UpdateMouse = X11_UpdateMouse;
3573+#if SDL_VIDEO_DRIVER_X11_XV
3574+ device->CreateYUVOverlay = X11_CreateYUVOverlay;
3575+#endif
3576+ device->SetColors = X11_SetColors;
3577+ device->UpdateRects = NULL;
3578+ device->VideoQuit = X11_VideoQuit;
3579+ device->AllocHWSurface = X11_AllocHWSurface;
3580+ device->CheckHWBlit = NULL;
3581+ device->FillHWRect = NULL;
3582+ device->SetHWColorKey = NULL;
3583+ device->SetHWAlpha = NULL;
3584+ device->LockHWSurface = X11_LockHWSurface;
3585+ device->UnlockHWSurface = X11_UnlockHWSurface;
3586+ device->FlipHWSurface = X11_FlipHWSurface;
3587+ device->FreeHWSurface = X11_FreeHWSurface;
3588+ device->SetGamma = X11_SetVidModeGamma;
3589+ device->GetGamma = X11_GetVidModeGamma;
3590+ device->SetGammaRamp = X11_SetGammaRamp;
3591+ device->GetGammaRamp = NULL;
3592+#if SDL_VIDEO_OPENGL_GLX
3593+ device->GL_LoadLibrary = X11_GL_LoadLibrary;
3594+ device->GL_GetProcAddress = X11_GL_GetProcAddress;
3595+ device->GL_GetAttribute = X11_GL_GetAttribute;
3596+ device->GL_MakeCurrent = X11_GL_MakeCurrent;
3597+ device->GL_SwapBuffers = X11_GL_SwapBuffers;
3598+#endif
3599+ device->SetCaption = X11_SetCaption;
3600+ device->SetIcon = X11_SetIcon;
3601+ device->IconifyWindow = X11_IconifyWindow;
3602+ device->GrabInput = X11_GrabInput;
3603+ device->GetWMInfo = X11_GetWMInfo;
3604+ device->FreeWMCursor = X11_FreeWMCursor;
3605+ device->CreateWMCursor = X11_CreateWMCursor;
3606+ device->ShowWMCursor = X11_ShowWMCursor;
3607+ device->WarpWMCursor = X11_WarpWMCursor;
3608+ device->CheckMouseMode = X11_CheckMouseMode;
3609+ device->InitOSKeymap = X11_InitOSKeymap;
3610+ device->PumpEvents = X11_PumpEvents;
3611+
3612+ device->free = X11_DeleteDevice;
3613+ }
3614+
3615+ return device;
3616+}
3617+
3618+VideoBootStrap X11_bootstrap = {
3619+ "x11", "X Window System",
3620+ X11_Available, X11_CreateDevice
3621+};
3622+
3623+/* Normal X11 error handler routine */
3624+static int (*X_handler)(Display *, XErrorEvent *) = NULL;
3625+static int x_errhandler(Display *d, XErrorEvent *e)
3626+{
3627+#if SDL_VIDEO_DRIVER_X11_VIDMODE
3628+ extern int vm_error;
3629+#endif
3630+#if SDL_VIDEO_DRIVER_X11_DGAMOUSE
3631+ extern int dga_error;
3632+#endif
3633+
3634+#if SDL_VIDEO_DRIVER_X11_VIDMODE
3635+ /* VidMode errors are non-fatal. :) */
3636+ /* Are the errors offset by one from the error base?
3637+ e.g. the error base is 143, the code is 148, and the
3638+ actual error is XF86VidModeExtensionDisabled (4) ?
3639+ */
3640+ if ( (vm_error >= 0) &&
3641+ (((e->error_code == BadRequest)&&(e->request_code == vm_error)) ||
3642+ ((e->error_code > vm_error) &&
3643+ (e->error_code <= (vm_error+XF86VidModeNumberErrors)))) ) {
3644+#ifdef X11_DEBUG
3645+{ char errmsg[1024];
3646+ XGetErrorText(d, e->error_code, errmsg, sizeof(errmsg));
3647+printf("VidMode error: %s\n", errmsg);
3648+}
3649+#endif
3650+ return(0);
3651+ }
3652+#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
3653+
3654+#if SDL_VIDEO_DRIVER_X11_DGAMOUSE
3655+ /* DGA errors can be non-fatal. :) */
3656+ if ( (dga_error >= 0) &&
3657+ ((e->error_code > dga_error) &&
3658+ (e->error_code <= (dga_error+XF86DGANumberErrors))) ) {
3659+#ifdef X11_DEBUG
3660+{ char errmsg[1024];
3661+ XGetErrorText(d, e->error_code, errmsg, sizeof(errmsg));
3662+printf("DGA error: %s\n", errmsg);
3663+}
3664+#endif
3665+ return(0);
3666+ }
3667+#endif /* SDL_VIDEO_DRIVER_X11_DGAMOUSE */
3668+
3669+ return(X_handler(d,e));
3670+}
3671+
3672+/* X11 I/O error handler routine */
3673+static int (*XIO_handler)(Display *) = NULL;
3674+static int xio_errhandler(Display *d)
3675+{
3676+ /* Ack! Lost X11 connection! */
3677+
3678+ /* We will crash if we try to clean up our display */
3679+ if ( SDL_VideoSurface && current_video->hidden->Ximage ) {
3680+ SDL_VideoSurface->pixels = NULL;
3681+ }
3682+ current_video->hidden->X11_Display = NULL;
3683+
3684+ /* Continue with the standard X11 error handler */
3685+ return(XIO_handler(d));
3686+}
3687+
3688+static int (*Xext_handler)(Display *, _Xconst char *, _Xconst char *) = NULL;
3689+static int xext_errhandler(Display *d, _Xconst char *ext, _Xconst char *reason)
3690+{
3691+#ifdef X11_DEBUG
3692+ printf("Xext error inside SDL (may be harmless):\n");
3693+ printf(" Extension \"%s\" %s on display \"%s\".\n",
3694+ ext, reason, XDisplayString(d));
3695+#endif
3696+
3697+ if (SDL_strcmp(reason, "missing") == 0) {
3698+ /*
3699+ * Since the query itself, elsewhere, can handle a missing extension
3700+ * and the default behaviour in Xlib is to write to stderr, which
3701+ * generates unnecessary bug reports, we just ignore these.
3702+ */
3703+ return 0;
3704+ }
3705+
3706+ /* Everything else goes to the default handler... */
3707+ return Xext_handler(d, ext, reason);
3708+}
3709+
3710+/* Find out what class name we should use */
3711+static char *get_classname(char *classname, int maxlen)
3712+{
3713+ char *spot;
3714+#if defined(__LINUX__) || defined(__FREEBSD__)
3715+ char procfile[1024];
3716+ char linkfile[1024];
3717+ int linksize;
3718+#endif
3719+
3720+ /* First allow environment variable override */
3721+ spot = SDL_getenv("SDL_VIDEO_X11_WMCLASS");
3722+ if ( spot ) {
3723+ SDL_strlcpy(classname, spot, maxlen);
3724+ return classname;
3725+ }
3726+
3727+ /* Next look at the application's executable name */
3728+#if defined(__LINUX__) || defined(__FREEBSD__)
3729+#if defined(__LINUX__)
3730+ SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/exe", getpid());
3731+#elif defined(__FREEBSD__)
3732+ SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/file", getpid());
3733+#else
3734+#error Where can we find the executable name?
3735+#endif
3736+ linksize = readlink(procfile, linkfile, sizeof(linkfile)-1);
3737+ if ( linksize > 0 ) {
3738+ linkfile[linksize] = '\0';
3739+ spot = SDL_strrchr(linkfile, '/');
3740+ if ( spot ) {
3741+ SDL_strlcpy(classname, spot+1, maxlen);
3742+ } else {
3743+ SDL_strlcpy(classname, linkfile, maxlen);
3744+ }
3745+ return classname;
3746+ }
3747+#endif /* __LINUX__ */
3748+
3749+ /* Finally use the default we've used forever */
3750+ SDL_strlcpy(classname, "SDL_App", maxlen);
3751+ return classname;
3752+}
3753+
3754+/* Create auxiliary (toplevel) windows with the current visual */
3755+static void create_aux_windows(_THIS)
3756+{
3757+ int x = 0, y = 0;
3758+ char classname[1024];
3759+ XSetWindowAttributes xattr;
3760+ XWMHints *hints;
3761+ unsigned long app_event_mask;
3762+ int def_vis = (SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen));
3763+
3764+ /* Look up some useful Atoms */
3765+ WM_DELETE_WINDOW = XInternAtom(SDL_Display, "WM_DELETE_WINDOW", False);
3766+
3767+ /* Don't create any extra windows if we are being managed */
3768+ if ( SDL_windowid ) {
3769+ FSwindow = 0;
3770+ WMwindow = SDL_strtol(SDL_windowid, NULL, 0);
3771+ return;
3772+ }
3773+
3774+ if(FSwindow)
3775+ XDestroyWindow(SDL_Display, FSwindow);
3776+
3777+#if SDL_VIDEO_DRIVER_X11_XINERAMA
3778+ if ( use_xinerama ) {
3779+ x = xinerama_info.x_org;
3780+ y = xinerama_info.y_org;
3781+ }
3782+#endif
3783+ xattr.override_redirect = True;
3784+ xattr.background_pixel = def_vis ? BlackPixel(SDL_Display, SDL_Screen) : 0;
3785+ xattr.border_pixel = 0;
3786+ xattr.colormap = SDL_XColorMap;
3787+
3788+ FSwindow = XCreateWindow(SDL_Display, SDL_Root,
3789+ x, y, 32, 32, 0,
3790+ this->hidden->depth, InputOutput, SDL_Visual,
3791+ CWOverrideRedirect | CWBackPixel | CWBorderPixel
3792+ | CWColormap,
3793+ &xattr);
3794+
3795+ XSelectInput(SDL_Display, FSwindow, StructureNotifyMask);
3796+
3797+ /* Tell KDE to keep the fullscreen window on top */
3798+ {
3799+ XEvent ev;
3800+ long mask;
3801+
3802+ SDL_memset(&ev, 0, sizeof(ev));
3803+ ev.xclient.type = ClientMessage;
3804+ ev.xclient.window = SDL_Root;
3805+ ev.xclient.message_type = XInternAtom(SDL_Display,
3806+ "KWM_KEEP_ON_TOP", False);
3807+ ev.xclient.format = 32;
3808+ ev.xclient.data.l[0] = FSwindow;
3809+ ev.xclient.data.l[1] = CurrentTime;
3810+ mask = SubstructureRedirectMask;
3811+ XSendEvent(SDL_Display, SDL_Root, False, mask, &ev);
3812+ }
3813+
3814+ hints = NULL;
3815+ if(WMwindow) {
3816+ /* All window attributes must survive the recreation */
3817+ hints = XGetWMHints(SDL_Display, WMwindow);
3818+ XDestroyWindow(SDL_Display, WMwindow);
3819+ }
3820+
3821+ /* Create the window for windowed management */
3822+ /* (reusing the xattr structure above) */
3823+ WMwindow = XCreateWindow(SDL_Display, SDL_Root,
3824+ x, y, 32, 32, 0,
3825+ this->hidden->depth, InputOutput, SDL_Visual,
3826+ CWBackPixel | CWBorderPixel | CWColormap,
3827+ &xattr);
3828+
3829+ /* Set the input hints so we get keyboard input */
3830+ if(!hints) {
3831+ hints = XAllocWMHints();
3832+ hints->input = True;
3833+ hints->flags = InputHint;
3834+ }
3835+ XSetWMHints(SDL_Display, WMwindow, hints);
3836+ XFree(hints);
3837+ X11_SetCaptionNoLock(this, this->wm_title, this->wm_icon);
3838+
3839+ app_event_mask = FocusChangeMask | KeyPressMask | KeyReleaseMask
3840+ | PropertyChangeMask | StructureNotifyMask | KeymapStateMask;
3841+ XSelectInput(SDL_Display, WMwindow, app_event_mask);
3842+
3843+ /* Set the class hints so we can get an icon (AfterStep) */
3844+ get_classname(classname, sizeof(classname));
3845+ {
3846+ XClassHint *classhints;
3847+ classhints = XAllocClassHint();
3848+ if(classhints != NULL) {
3849+ classhints->res_name = classname;
3850+ classhints->res_class = classname;
3851+ XSetClassHint(SDL_Display, WMwindow, classhints);
3852+ XFree(classhints);
3853+ }
3854+ }
3855+
3856+ {
3857+ pid_t pid = getpid();
3858+ char hostname[256];
3859+
3860+ if (pid > 0 && gethostname(hostname, sizeof(hostname)) > -1) {
3861+ Atom _NET_WM_PID = XInternAtom(SDL_Display, "_NET_WM_PID", False);
3862+ Atom WM_CLIENT_MACHINE = XInternAtom(SDL_Display, "WM_CLIENT_MACHINE", False);
3863+
3864+ hostname[sizeof(hostname)-1] = '\0';
3865+ XChangeProperty(SDL_Display, WMwindow, _NET_WM_PID, XA_CARDINAL, 32,
3866+ PropModeReplace, (unsigned char *)&pid, 1);
3867+ XChangeProperty(SDL_Display, WMwindow, WM_CLIENT_MACHINE, XA_STRING, 8,
3868+ PropModeReplace, (unsigned char *)hostname, SDL_strlen(hostname));
3869+ }
3870+ }
3871+
3872+ /* Setup the communication with the IM server */
3873+ /* create_aux_windows may be called several times against the same
3874+ Display. We should reuse the SDL_IM if one has been opened for
3875+ the Display, so we should not simply reset SDL_IM here. */
3876+
3877+ #ifdef X_HAVE_UTF8_STRING
3878+ if (SDL_X11_HAVE_UTF8) {
3879+ /* Discard obsolete resources if any. */
3880+ if (SDL_IM != NULL && SDL_Display != XDisplayOfIM(SDL_IM)) {
3881+ /* Just a double check. I don't think this
3882+ code is ever executed. */
3883+ SDL_SetError("display has changed while an IM is kept");
3884+ if (SDL_IC) {
3885+ XUnsetICFocus(SDL_IC);
3886+ XDestroyIC(SDL_IC);
3887+ SDL_IC = NULL;
3888+ }
3889+ XCloseIM(SDL_IM);
3890+ SDL_IM = NULL;
3891+ }
3892+
3893+ /* Open an input method. */
3894+ if (SDL_IM == NULL) {
3895+ char *old_locale = NULL, *old_modifiers = NULL;
3896+ const char *p;
3897+ size_t n;
3898+ /* I'm not comfortable to do locale setup
3899+ here. However, we need C library locale
3900+ (and xlib modifiers) to be set based on the
3901+ user's preference to use XIM, and many
3902+ existing game programs doesn't take care of
3903+ users' locale preferences, so someone other
3904+ than the game program should do it.
3905+ Moreover, ones say that some game programs
3906+ heavily rely on the C locale behaviour,
3907+ e.g., strcol()'s, and we can't change the C
3908+ library locale. Given the situation, I
3909+ couldn't find better place to do the
3910+ job... */
3911+
3912+ /* Save the current (application program's)
3913+ locale settings. */
3914+ p = setlocale(LC_ALL, NULL);
3915+ if ( p ) {
3916+ n = SDL_strlen(p)+1;
3917+ old_locale = SDL_stack_alloc(char, n);
3918+ if ( old_locale ) {
3919+ SDL_strlcpy(old_locale, p, n);
3920+ }
3921+ }
3922+ p = XSetLocaleModifiers(NULL);
3923+ if ( p ) {
3924+ n = SDL_strlen(p)+1;
3925+ old_modifiers = SDL_stack_alloc(char, n);
3926+ if ( old_modifiers ) {
3927+ SDL_strlcpy(old_modifiers, p, n);
3928+ }
3929+ }
3930+
3931+ /* Fetch the user's preferences and open the
3932+ input method with them. */
3933+ setlocale(LC_ALL, "");
3934+ XSetLocaleModifiers("");
3935+ SDL_IM = XOpenIM(SDL_Display, NULL, classname, classname);
3936+
3937+ /* Restore the application's locale settings
3938+ so that we don't break the application's
3939+ expected behaviour. */
3940+ if ( old_locale ) {
3941+ /* We need to restore the C library
3942+ locale first, since the
3943+ interpretation of the X modifier
3944+ may depend on it. */
3945+ setlocale(LC_ALL, old_locale);
3946+ SDL_stack_free(old_locale);
3947+ }
3948+ if ( old_modifiers ) {
3949+ XSetLocaleModifiers(old_modifiers);
3950+ SDL_stack_free(old_modifiers);
3951+ }
3952+ }
3953+
3954+ /* Create a new input context for the new window just created. */
3955+ if (SDL_IM == NULL) {
3956+ SDL_SetError("no input method could be opened");
3957+ } else {
3958+ if (SDL_IC != NULL) {
3959+ /* Discard the old IC before creating new one. */
3960+ XUnsetICFocus(SDL_IC);
3961+ XDestroyIC(SDL_IC);
3962+ }
3963+ /* Theoretically we should check the current IM supports
3964+ PreeditNothing+StatusNothing style (i.e., root window method)
3965+ before creating the IC. However, it is the bottom line method,
3966+ and we supports any other options. If the IM didn't support
3967+ root window method, the following call fails, and SDL falls
3968+ back to pre-XIM keyboard handling. */
3969+ SDL_IC = pXCreateIC(SDL_IM,
3970+ XNClientWindow, WMwindow,
3971+ XNFocusWindow, WMwindow,
3972+ XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
3973+ XNResourceName, classname,
3974+ XNResourceClass, classname,
3975+ NULL);
3976+
3977+ if (SDL_IC == NULL) {
3978+ SDL_SetError("no input context could be created");
3979+ XCloseIM(SDL_IM);
3980+ SDL_IM = NULL;
3981+ } else {
3982+ /* We need to receive X events that an IM wants and to pass
3983+ them to the IM through XFilterEvent. The set of events may
3984+ vary depending on the IM implementation and the options
3985+ specified through various routes. Although unlikely, the
3986+ xlib specification allows IM to change the event requirement
3987+ with its own circumstances, it is safe to call SelectInput
3988+ whenever we re-create an IC. */
3989+ unsigned long mask = 0;
3990+ char *ret = pXGetICValues(SDL_IC, XNFilterEvents, &mask, NULL);
3991+ if (ret != NULL) {
3992+ XUnsetICFocus(SDL_IC);
3993+ XDestroyIC(SDL_IC);
3994+ SDL_IC = NULL;
3995+ SDL_SetError("no input context could be created");
3996+ XCloseIM(SDL_IM);
3997+ SDL_IM = NULL;
3998+ } else {
3999+ XSelectInput(SDL_Display, WMwindow, app_event_mask | mask);
4000+ XSetICFocus(SDL_IC);
4001+ }
4002+ }
4003+ }
4004+ }
4005+ #endif
4006+
4007+ /* Allow the window to be deleted by the window manager */
4008+ XSetWMProtocols(SDL_Display, WMwindow, &WM_DELETE_WINDOW, 1);
4009+}
4010+
4011+static int X11_VideoInit(_THIS, SDL_PixelFormat *vformat)
4012+{
4013+ const char *env;
4014+ char *display;
4015+ int i;
4016+
4017+ /* Open the X11 display */
4018+ display = NULL; /* Get it from DISPLAY environment variable */
4019+
4020+ if ( (SDL_strncmp(XDisplayName(display), ":", 1) == 0) ||
4021+ (SDL_strncmp(XDisplayName(display), "unix:", 5) == 0) ) {
4022+ local_X11 = 1;
4023+ } else {
4024+ local_X11 = 0;
4025+ }
4026+ SDL_Display = XOpenDisplay(display);
4027+#if defined(__osf__) && defined(SDL_VIDEO_DRIVER_X11_DYNAMIC)
4028+ /* On Tru64 if linking without -lX11, it fails and you get following message.
4029+ * Xlib: connection to ":0.0" refused by server
4030+ * Xlib: XDM authorization key matches an existing client!
4031+ *
4032+ * It succeeds if retrying 1 second later
4033+ * or if running xhost +localhost on shell.
4034+ *
4035+ */
4036+ if ( SDL_Display == NULL ) {
4037+ SDL_Delay(1000);
4038+ SDL_Display = XOpenDisplay(display);
4039+ }
4040+#endif
4041+ if ( SDL_Display == NULL ) {
4042+ SDL_SetError("Couldn't open X11 display");
4043+ return(-1);
4044+ }
4045+#ifdef X11_DEBUG
4046+ XSynchronize(SDL_Display, True);
4047+#endif
4048+
4049+ /* Create an alternate X display for graphics updates -- allows us
4050+ to do graphics updates in a separate thread from event handling.
4051+ Thread-safe X11 doesn't seem to exist.
4052+ */
4053+ GFX_Display = XOpenDisplay(display);
4054+ if ( GFX_Display == NULL ) {
4055+ XCloseDisplay(SDL_Display);
4056+ SDL_Display = NULL;
4057+ SDL_SetError("Couldn't open X11 display");
4058+ return(-1);
4059+ }
4060+
4061+ /* Set the normal X error handler */
4062+ X_handler = XSetErrorHandler(x_errhandler);
4063+
4064+ /* Set the error handler if we lose the X display */
4065+ XIO_handler = XSetIOErrorHandler(xio_errhandler);
4066+
4067+ /* Set the X extension error handler */
4068+ Xext_handler = XSetExtensionErrorHandler(xext_errhandler);
4069+
4070+ /* use default screen (from $DISPLAY) */
4071+ SDL_Screen = DefaultScreen(SDL_Display);
4072+
4073+#ifndef NO_SHARED_MEMORY
4074+ /* Check for MIT shared memory extension */
4075+ use_mitshm = 0;
4076+ if ( local_X11 ) {
4077+ use_mitshm = XShmQueryExtension(SDL_Display);
4078+ }
4079+#endif /* NO_SHARED_MEMORY */
4080+
4081+ /* Get the available video modes */
4082+ if(X11_GetVideoModes(this) < 0) {
4083+ XCloseDisplay(GFX_Display);
4084+ GFX_Display = NULL;
4085+ XCloseDisplay(SDL_Display);
4086+ SDL_Display = NULL;
4087+ return -1;
4088+ }
4089+
4090+ /* Determine the current screen size */
4091+ this->info.current_w = DisplayWidth(SDL_Display, SDL_Screen);
4092+ this->info.current_h = DisplayHeight(SDL_Display, SDL_Screen);
4093+
4094+ /* Determine the default screen depth:
4095+ Use the default visual (or at least one with the same depth) */
4096+ SDL_DisplayColormap = DefaultColormap(SDL_Display, SDL_Screen);
4097+ for(i = 0; i < this->hidden->nvisuals; i++)
4098+ if(this->hidden->visuals[i].depth == DefaultDepth(SDL_Display,
4099+ SDL_Screen))
4100+ break;
4101+ if(i == this->hidden->nvisuals) {
4102+ /* default visual was useless, take the deepest one instead */
4103+ i = 0;
4104+ }
4105+ SDL_Visual = this->hidden->visuals[i].visual;
4106+ if ( SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen) ) {
4107+ SDL_XColorMap = SDL_DisplayColormap;
4108+ } else {
4109+ SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
4110+ SDL_Visual, AllocNone);
4111+ }
4112+ this->hidden->depth = this->hidden->visuals[i].depth;
4113+ vformat->BitsPerPixel = this->hidden->visuals[i].bpp;
4114+ if ( vformat->BitsPerPixel > 8 ) {
4115+ vformat->Rmask = SDL_Visual->red_mask;
4116+ vformat->Gmask = SDL_Visual->green_mask;
4117+ vformat->Bmask = SDL_Visual->blue_mask;
4118+ }
4119+ if ( this->hidden->depth == 32 ) {
4120+ vformat->Amask = (0xFFFFFFFF & ~(vformat->Rmask|vformat->Gmask|vformat->Bmask));
4121+ }
4122+ X11_SaveVidModeGamma(this);
4123+
4124+ /* Allow environment override of screensaver disable. */
4125+ env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
4126+ if ( env ) {
4127+ allow_screensaver = SDL_atoi(env);
4128+ } else {
4129+#ifdef SDL_VIDEO_DISABLE_SCREENSAVER
4130+ allow_screensaver = 0;
4131+#else
4132+ allow_screensaver = 1;
4133+#endif
4134+ }
4135+
4136+ /* See if we have been passed a window to use */
4137+ SDL_windowid = SDL_getenv("SDL_WINDOWID");
4138+
4139+ /* Create the fullscreen and managed windows */
4140+ create_aux_windows(this);
4141+
4142+ /* Create the blank cursor */
4143+ SDL_BlankCursor = this->CreateWMCursor(this, blank_cdata, blank_cmask,
4144+ BLANK_CWIDTH, BLANK_CHEIGHT,
4145+ BLANK_CHOTX, BLANK_CHOTY);
4146+
4147+ /* Fill in some window manager capabilities */
4148+ this->info.wm_available = 1;
4149+
4150+ /* We're done! */
4151+ XFlush(SDL_Display);
4152+ return(0);
4153+}
4154+
4155+static void X11_DestroyWindow(_THIS, SDL_Surface *screen)
4156+{
4157+ /* Clean up OpenGL */
4158+ if ( screen ) {
4159+ screen->flags &= ~(SDL_OPENGL|SDL_OPENGLBLIT);
4160+ }
4161+ X11_GL_Shutdown(this);
4162+
4163+ if ( ! SDL_windowid ) {
4164+ /* Hide the managed window */
4165+ if ( WMwindow ) {
4166+ XUnmapWindow(SDL_Display, WMwindow);
4167+ }
4168+ if ( screen && (screen->flags & SDL_FULLSCREEN) ) {
4169+ screen->flags &= ~SDL_FULLSCREEN;
4170+ X11_LeaveFullScreen(this);
4171+ }
4172+
4173+ /* Destroy the output window */
4174+ if ( SDL_Window ) {
4175+ XDestroyWindow(SDL_Display, SDL_Window);
4176+ }
4177+
4178+ /* Free the colormap entries */
4179+ if ( SDL_XPixels ) {
4180+ int numcolors;
4181+ unsigned long pixel;
4182+ numcolors = SDL_Visual->map_entries;
4183+ for ( pixel=0; pixel<numcolors; ++pixel ) {
4184+ while ( SDL_XPixels[pixel] > 0 ) {
4185+ XFreeColors(GFX_Display,
4186+ SDL_DisplayColormap,&pixel,1,0);
4187+ --SDL_XPixels[pixel];
4188+ }
4189+ }
4190+ SDL_free(SDL_XPixels);
4191+ SDL_XPixels = NULL;
4192+ }
4193+
4194+ /* Free the graphics context */
4195+ if ( SDL_GC ) {
4196+ XFreeGC(SDL_Display, SDL_GC);
4197+ SDL_GC = 0;
4198+ }
4199+ }
4200+}
4201+
4202+static SDL_bool X11_WindowPosition(_THIS, int *x, int *y, int w, int h)
4203+{
4204+ const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
4205+ const char *center = SDL_getenv("SDL_VIDEO_CENTERED");
4206+ if ( window ) {
4207+ if ( SDL_sscanf(window, "%d,%d", x, y) == 2 ) {
4208+ return SDL_TRUE;
4209+ }
4210+ if ( SDL_strcmp(window, "center") == 0 ) {
4211+ center = window;
4212+ }
4213+ }
4214+ if ( center ) {
4215+ *x = (DisplayWidth(SDL_Display, SDL_Screen) - w)/2;
4216+ *y = (DisplayHeight(SDL_Display, SDL_Screen) - h)/2;
4217+ return SDL_TRUE;
4218+ }
4219+ return SDL_FALSE;
4220+}
4221+
4222+static void X11_SetSizeHints(_THIS, int w, int h, Uint32 flags)
4223+{
4224+ XSizeHints *hints;
4225+
4226+ hints = XAllocSizeHints();
4227+ if ( hints ) {
4228+ if (!(flags & SDL_RESIZABLE)) {
4229+ hints->min_width = hints->max_width = w;
4230+ hints->min_height = hints->max_height = h;
4231+ hints->flags = PMaxSize | PMinSize;
4232+ }
4233+ if ( flags & SDL_FULLSCREEN ) {
4234+ hints->x = 0;
4235+ hints->y = 0;
4236+ hints->flags |= USPosition;
4237+ } else
4238+ /* Center it, if desired */
4239+ if ( X11_WindowPosition(this, &hints->x, &hints->y, w, h) ) {
4240+ hints->flags |= USPosition;
4241+
4242+ /* Hints must be set before moving the window, otherwise an
4243+ unwanted ConfigureNotify event will be issued */
4244+ XSetWMNormalHints(SDL_Display, WMwindow, hints);
4245+
4246+ XMoveWindow(SDL_Display, WMwindow, hints->x, hints->y);
4247+
4248+ /* Flush the resize event so we don't catch it later */
4249+ XSync(SDL_Display, True);
4250+ }
4251+ XSetWMNormalHints(SDL_Display, WMwindow, hints);
4252+ XFree(hints);
4253+ }
4254+
4255+ /* Respect the window caption style */
4256+ if ( flags & SDL_NOFRAME ) {
4257+ SDL_bool set;
4258+ Atom WM_HINTS;
4259+
4260+ /* We haven't modified the window manager hints yet */
4261+ set = SDL_FALSE;
4262+
4263+ /* First try to set MWM hints */
4264+ WM_HINTS = XInternAtom(SDL_Display, "_MOTIF_WM_HINTS", True);
4265+ if ( WM_HINTS != None ) {
4266+ /* Hints used by Motif compliant window managers */
4267+ struct {
4268+ unsigned long flags;
4269+ unsigned long functions;
4270+ unsigned long decorations;
4271+ long input_mode;
4272+ unsigned long status;
4273+ } MWMHints = { (1L << 1), 0, 0, 0, 0 };
4274+
4275+ XChangeProperty(SDL_Display, WMwindow,
4276+ WM_HINTS, WM_HINTS, 32,
4277+ PropModeReplace,
4278+ (unsigned char *)&MWMHints,
4279+ sizeof(MWMHints)/sizeof(long));
4280+ set = SDL_TRUE;
4281+ }
4282+ /* Now try to set KWM hints */
4283+ WM_HINTS = XInternAtom(SDL_Display, "KWM_WIN_DECORATION", True);
4284+ if ( WM_HINTS != None ) {
4285+ long KWMHints = 0;
4286+
4287+ XChangeProperty(SDL_Display, WMwindow,
4288+ WM_HINTS, WM_HINTS, 32,
4289+ PropModeReplace,
4290+ (unsigned char *)&KWMHints,
4291+ sizeof(KWMHints)/sizeof(long));
4292+ set = SDL_TRUE;
4293+ }
4294+ /* Now try to set GNOME hints */
4295+ WM_HINTS = XInternAtom(SDL_Display, "_WIN_HINTS", True);
4296+ if ( WM_HINTS != None ) {
4297+ long GNOMEHints = 0;
4298+
4299+ XChangeProperty(SDL_Display, WMwindow,
4300+ WM_HINTS, WM_HINTS, 32,
4301+ PropModeReplace,
4302+ (unsigned char *)&GNOMEHints,
4303+ sizeof(GNOMEHints)/sizeof(long));
4304+ set = SDL_TRUE;
4305+ }
4306+ /* Finally set the transient hints if necessary */
4307+ if ( ! set ) {
4308+ XSetTransientForHint(SDL_Display, WMwindow, SDL_Root);
4309+ }
4310+ } else {
4311+ SDL_bool set;
4312+ Atom WM_HINTS;
4313+
4314+ /* We haven't modified the window manager hints yet */
4315+ set = SDL_FALSE;
4316+
4317+ /* First try to unset MWM hints */
4318+ WM_HINTS = XInternAtom(SDL_Display, "_MOTIF_WM_HINTS", True);
4319+ if ( WM_HINTS != None ) {
4320+ XDeleteProperty(SDL_Display, WMwindow, WM_HINTS);
4321+ set = SDL_TRUE;
4322+ }
4323+ /* Now try to unset KWM hints */
4324+ WM_HINTS = XInternAtom(SDL_Display, "KWM_WIN_DECORATION", True);
4325+ if ( WM_HINTS != None ) {
4326+ XDeleteProperty(SDL_Display, WMwindow, WM_HINTS);
4327+ set = SDL_TRUE;
4328+ }
4329+ /* Now try to unset GNOME hints */
4330+ WM_HINTS = XInternAtom(SDL_Display, "_WIN_HINTS", True);
4331+ if ( WM_HINTS != None ) {
4332+ XDeleteProperty(SDL_Display, WMwindow, WM_HINTS);
4333+ set = SDL_TRUE;
4334+ }
4335+ /* Finally unset the transient hints if necessary */
4336+ if ( ! set ) {
4337+ XDeleteProperty(SDL_Display, WMwindow, XA_WM_TRANSIENT_FOR);
4338+ }
4339+ }
4340+}
4341+
4342+static int X11_CreateWindow(_THIS, SDL_Surface *screen,
4343+ int w, int h, int bpp, Uint32 flags)
4344+{
4345+ int i, depth;
4346+ Visual *vis;
4347+ int vis_change;
4348+ Uint32 Amask;
4349+
4350+ /* If a window is already present, destroy it and start fresh */
4351+ if ( SDL_Window ) {
4352+ X11_DestroyWindow(this, screen);
4353+ switch_waiting = 0; /* Prevent jump back to now-meaningless state. */
4354+ }
4355+
4356+ /* See if we have been given a window id */
4357+ if ( SDL_windowid ) {
4358+ SDL_Window = SDL_strtol(SDL_windowid, NULL, 0);
4359+ } else {
4360+ SDL_Window = 0;
4361+ }
4362+
4363+ /* find out which visual we are going to use */
4364+ if ( flags & SDL_OPENGL ) {
4365+ XVisualInfo *vi;
4366+
4367+ vi = X11_GL_GetVisual(this);
4368+ if( !vi ) {
4369+ return -1;
4370+ }
4371+ vis = vi->visual;
4372+ depth = vi->depth;
4373+ } else if ( SDL_windowid ) {
4374+ XWindowAttributes a;
4375+
4376+ XGetWindowAttributes(SDL_Display, SDL_Window, &a);
4377+ vis = a.visual;
4378+ depth = a.depth;
4379+ } else {
4380+ for ( i = 0; i < this->hidden->nvisuals; i++ ) {
4381+ if ( this->hidden->visuals[i].bpp == bpp )
4382+ break;
4383+ }
4384+ if ( i == this->hidden->nvisuals ) {
4385+ SDL_SetError("No matching visual for requested depth");
4386+ return -1; /* should never happen */
4387+ }
4388+ vis = this->hidden->visuals[i].visual;
4389+ depth = this->hidden->visuals[i].depth;
4390+ }
4391+#ifdef X11_DEBUG
4392+ printf("Choosing %s visual at %d bpp - %d colormap entries\n", vis->class == PseudoColor ? "PseudoColor" : (vis->class == TrueColor ? "TrueColor" : (vis->class == DirectColor ? "DirectColor" : "Unknown")), depth, vis->map_entries);
4393+#endif
4394+ vis_change = (vis != SDL_Visual);
4395+ SDL_Visual = vis;
4396+ this->hidden->depth = depth;
4397+
4398+ /* Allocate the new pixel format for this video mode */
4399+ if ( this->hidden->depth == 32 ) {
4400+ Amask = (0xFFFFFFFF & ~(vis->red_mask|vis->green_mask|vis->blue_mask));
4401+ } else {
4402+ Amask = 0;
4403+ }
4404+ if ( ! SDL_ReallocFormat(screen, bpp,
4405+ vis->red_mask, vis->green_mask, vis->blue_mask, Amask) ) {
4406+ return -1;
4407+ }
4408+
4409+ /* Create the appropriate colormap */
4410+ if ( SDL_XColorMap != SDL_DisplayColormap ) {
4411+ XFreeColormap(SDL_Display, SDL_XColorMap);
4412+ }
4413+ if ( SDL_Visual->class == PseudoColor ) {
4414+ int ncolors;
4415+
4416+ /* Allocate the pixel flags */
4417+ ncolors = SDL_Visual->map_entries;
4418+ SDL_XPixels = SDL_malloc(ncolors * sizeof(int));
4419+ if(SDL_XPixels == NULL) {
4420+ SDL_OutOfMemory();
4421+ return -1;
4422+ }
4423+ SDL_memset(SDL_XPixels, 0, ncolors * sizeof(*SDL_XPixels));
4424+
4425+ /* always allocate a private colormap on non-default visuals */
4426+ if ( SDL_Visual != DefaultVisual(SDL_Display, SDL_Screen) ) {
4427+ flags |= SDL_HWPALETTE;
4428+ }
4429+ if ( flags & SDL_HWPALETTE ) {
4430+ screen->flags |= SDL_HWPALETTE;
4431+ SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
4432+ SDL_Visual, AllocAll);
4433+ } else {
4434+ SDL_XColorMap = SDL_DisplayColormap;
4435+ }
4436+ } else if ( SDL_Visual->class == DirectColor ) {
4437+
4438+ /* Create a colormap which we can manipulate for gamma */
4439+ SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
4440+ SDL_Visual, AllocAll);
4441+ XSync(SDL_Display, False);
4442+
4443+ /* Initialize the colormap to the identity mapping */
4444+ SDL_GetGammaRamp(0, 0, 0);
4445+ this->screen = screen;
4446+ X11_SetGammaRamp(this, this->gamma);
4447+ this->screen = NULL;
4448+ } else {
4449+ /* Create a read-only colormap for our window */
4450+ SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root,
4451+ SDL_Visual, AllocNone);
4452+ }
4453+
4454+ /* Recreate the auxiliary windows, if needed (required for GL) */
4455+ if ( vis_change )
4456+ create_aux_windows(this);
4457+
4458+ if(screen->flags & SDL_HWPALETTE) {
4459+ /* Since the full-screen window might have got a nonzero background
4460+ colour (0 is white on some displays), we should reset the
4461+ background to 0 here since that is what the user expects
4462+ with a private colormap */
4463+ XSetWindowBackground(SDL_Display, FSwindow, 0);
4464+ XClearWindow(SDL_Display, FSwindow);
4465+ }
4466+
4467+ /* resize the (possibly new) window manager window */
4468+ if( !SDL_windowid ) {
4469+ X11_SetSizeHints(this, w, h, flags);
4470+ window_w = w;
4471+ window_h = h;
4472+ XResizeWindow(SDL_Display, WMwindow, w, h);
4473+ }
4474+
4475+ /* Create (or use) the X11 display window */
4476+ if ( !SDL_windowid ) {
4477+ if ( flags & SDL_OPENGL ) {
4478+ if ( X11_GL_CreateWindow(this, w, h) < 0 ) {
4479+ return(-1);
4480+ }
4481+ } else {
4482+ XSetWindowAttributes swa;
4483+
4484+ swa.background_pixel = 0;
4485+ swa.border_pixel = 0;
4486+ swa.colormap = SDL_XColorMap;
4487+ SDL_Window = XCreateWindow(SDL_Display, WMwindow,
4488+ 0, 0, w, h, 0, depth,
4489+ InputOutput, SDL_Visual,
4490+ CWBackPixel | CWBorderPixel
4491+ | CWColormap, &swa);
4492+ }
4493+ /* Only manage our input if we own the window */
4494+ XSelectInput(SDL_Display, SDL_Window,
4495+ ( EnterWindowMask | LeaveWindowMask
4496+ | ButtonPressMask | ButtonReleaseMask
4497+ | PointerMotionMask | ExposureMask ));
4498+ }
4499+ /* Create the graphics context here, once we have a window */
4500+ if ( flags & SDL_OPENGL ) {
4501+ if ( X11_GL_CreateContext(this) < 0 ) {
4502+ return(-1);
4503+ } else {
4504+ screen->flags |= SDL_OPENGL;
4505+ }
4506+ } else {
4507+ XGCValues gcv;
4508+
4509+ gcv.graphics_exposures = False;
4510+ SDL_GC = XCreateGC(SDL_Display, SDL_Window,
4511+ GCGraphicsExposures, &gcv);
4512+ if ( ! SDL_GC ) {
4513+ SDL_SetError("Couldn't create graphics context");
4514+ return(-1);
4515+ }
4516+ }
4517+
4518+ /* Set our colormaps when not setting a GL mode */
4519+ if ( ! (flags & SDL_OPENGL) ) {
4520+ XSetWindowColormap(SDL_Display, SDL_Window, SDL_XColorMap);
4521+ if( !SDL_windowid ) {
4522+ XSetWindowColormap(SDL_Display, FSwindow, SDL_XColorMap);
4523+ XSetWindowColormap(SDL_Display, WMwindow, SDL_XColorMap);
4524+ }
4525+ }
4526+
4527+#if 0 /* This is an experiment - are the graphics faster now? - nope. */
4528+ if ( SDL_getenv("SDL_VIDEO_X11_BACKINGSTORE") )
4529+#endif
4530+ /* Cache the window in the server, when possible */
4531+ {
4532+ Screen *xscreen;
4533+ XSetWindowAttributes a;
4534+
4535+ xscreen = ScreenOfDisplay(SDL_Display, SDL_Screen);
4536+ a.backing_store = DoesBackingStore(xscreen);
4537+ if ( a.backing_store != NotUseful ) {
4538+ XChangeWindowAttributes(SDL_Display, SDL_Window,
4539+ CWBackingStore, &a);
4540+ }
4541+ }
4542+
4543+ /* Map them both and go fullscreen, if requested */
4544+ if ( ! SDL_windowid ) {
4545+ XMapWindow(SDL_Display, SDL_Window);
4546+ XMapWindow(SDL_Display, WMwindow);
4547+ X11_WaitMapped(this, WMwindow);
4548+ if ( flags & SDL_FULLSCREEN ) {
4549+ screen->flags |= SDL_FULLSCREEN;
4550+ X11_EnterFullScreen(this);
4551+ } else {
4552+ screen->flags &= ~SDL_FULLSCREEN;
4553+ }
4554+ }
4555+
4556+ return(0);
4557+}
4558+
4559+static int X11_ResizeWindow(_THIS,
4560+ SDL_Surface *screen, int w, int h, Uint32 flags)
4561+{
4562+ if ( ! SDL_windowid ) {
4563+ /* Resize the window manager window */
4564+ X11_SetSizeHints(this, w, h, flags);
4565+ window_w = w;
4566+ window_h = h;
4567+ XResizeWindow(SDL_Display, WMwindow, w, h);
4568+
4569+ /* Resize the fullscreen and display windows */
4570+ if ( flags & SDL_FULLSCREEN ) {
4571+ if ( screen->flags & SDL_FULLSCREEN ) {
4572+ X11_ResizeFullScreen(this);
4573+ } else {
4574+ screen->flags |= SDL_FULLSCREEN;
4575+ X11_EnterFullScreen(this);
4576+ }
4577+ } else {
4578+ if ( screen->flags & SDL_FULLSCREEN ) {
4579+ screen->flags &= ~SDL_FULLSCREEN;
4580+ X11_LeaveFullScreen(this);
4581+ }
4582+ }
4583+ XResizeWindow(SDL_Display, SDL_Window, w, h);
4584+ }
4585+ return(0);
4586+}
4587+
4588+SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current,
4589+ int width, int height, int bpp, Uint32 flags)
4590+{
4591+ Uint32 saved_flags;
4592+
4593+ /* Lock the event thread, in multi-threading environments */
4594+ SDL_Lock_EventThread();
4595+
4596+ /* Check the combination of flags we were passed */
4597+ if ( flags & SDL_FULLSCREEN ) {
4598+ /* Clear fullscreen flag if not supported */
4599+ if ( SDL_windowid ) {
4600+ flags &= ~SDL_FULLSCREEN;
4601+ }
4602+ }
4603+
4604+ /* Flush any delayed updates */
4605+ XSync(GFX_Display, False);
4606+
4607+ /* Set up the X11 window */
4608+ saved_flags = current->flags;
4609+ if ( (SDL_Window) && ((saved_flags&SDL_OPENGL) == (flags&SDL_OPENGL))
4610+ && (bpp == current->format->BitsPerPixel)
4611+ && ((saved_flags&SDL_NOFRAME) == (flags&SDL_NOFRAME)) ) {
4612+ if (X11_ResizeWindow(this, current, width, height, flags) < 0) {
4613+ current = NULL;
4614+ goto done;
4615+ }
4616+ X11_PendingConfigureNotifyWidth = width;
4617+ X11_PendingConfigureNotifyHeight = height;
4618+ } else {
4619+ if (X11_CreateWindow(this,current,width,height,bpp,flags) < 0) {
4620+ current = NULL;
4621+ goto done;
4622+ }
4623+ }
4624+
4625+ /* Update the internal keyboard state */
4626+ X11_SetKeyboardState(SDL_Display, NULL);
4627+
4628+ /* When the window is first mapped, ignore non-modifier keys */
4629+ if ( !current->w && !current->h ) {
4630+ Uint8 *keys = SDL_GetKeyState(NULL);
4631+ int i;
4632+ for ( i = 0; i < SDLK_LAST; ++i ) {
4633+ switch (i) {
4634+ case SDLK_NUMLOCK:
4635+ case SDLK_CAPSLOCK:
4636+ case SDLK_LCTRL:
4637+ case SDLK_RCTRL:
4638+ case SDLK_LSHIFT:
4639+ case SDLK_RSHIFT:
4640+ case SDLK_LALT:
4641+ case SDLK_RALT:
4642+ case SDLK_LMETA:
4643+ case SDLK_RMETA:
4644+ case SDLK_MODE:
4645+ break;
4646+ default:
4647+ keys[i] = SDL_RELEASED;
4648+ break;
4649+ }
4650+ }
4651+ }
4652+
4653+ /* Set up the new mode framebuffer */
4654+ if ( ((current->w != width) || (current->h != height)) ||
4655+ ((saved_flags&SDL_OPENGL) != (flags&SDL_OPENGL)) ) {
4656+ current->w = width;
4657+ current->h = height;
4658+ current->pitch = SDL_CalculatePitch(current);
4659+ if (X11_ResizeImage(this, current, flags) < 0) {
4660+ current = NULL;
4661+ goto done;
4662+ }
4663+ }
4664+
4665+ /* Clear these flags and set them only if they are in the new set. */
4666+ current->flags &= ~(SDL_RESIZABLE|SDL_NOFRAME);
4667+ current->flags |= (flags&(SDL_RESIZABLE|SDL_NOFRAME));
4668+
4669+ done:
4670+ /* Release the event thread */
4671+ XSync(SDL_Display, False);
4672+ SDL_Unlock_EventThread();
4673+
4674+ /* We're done! */
4675+ return(current);
4676+}
4677+
4678+static int X11_ToggleFullScreen(_THIS, int on)
4679+{
4680+ Uint32 event_thread;
4681+
4682+ /* Don't switch if we don't own the window */
4683+ if ( SDL_windowid ) {
4684+ return(0);
4685+ }
4686+
4687+ /* Don't lock if we are the event thread */
4688+ event_thread = SDL_EventThreadID();
4689+ if ( event_thread && (SDL_ThreadID() == event_thread) ) {
4690+ event_thread = 0;
4691+ }
4692+ if ( event_thread ) {
4693+ SDL_Lock_EventThread();
4694+ }
4695+ if ( on ) {
4696+ this->screen->flags |= SDL_FULLSCREEN;
4697+ X11_EnterFullScreen(this);
4698+ } else {
4699+ this->screen->flags &= ~SDL_FULLSCREEN;
4700+ X11_LeaveFullScreen(this);
4701+ }
4702+ X11_RefreshDisplay(this);
4703+ if ( event_thread ) {
4704+ SDL_Unlock_EventThread();
4705+ }
4706+ SDL_ResetKeyboard();
4707+ return(1);
4708+}
4709+
4710+/* Update the current mouse state and position */
4711+static void X11_UpdateMouse(_THIS)
4712+{
4713+ Window u1; int u2;
4714+ Window current_win;
4715+ int x, y;
4716+ unsigned int mask;
4717+
4718+ /* Lock the event thread, in multi-threading environments */
4719+ SDL_Lock_EventThread();
4720+ if ( XQueryPointer(SDL_Display, SDL_Window, &u1, &current_win,
4721+ &u2, &u2, &x, &y, &mask) ) {
4722+ if ( (x >= 0) && (x < SDL_VideoSurface->w) &&
4723+ (y >= 0) && (y < SDL_VideoSurface->h) ) {
4724+ SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS);
4725+ SDL_PrivateMouseMotion(0, 0, x, y);
4726+ } else {
4727+ SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS);
4728+ }
4729+ }
4730+ SDL_Unlock_EventThread();
4731+}
4732+
4733+/* simple colour distance metric. Supposed to be better than a plain
4734+ Euclidian distance anyway. */
4735+#define COLOUR_FACTOR 3
4736+#define LIGHT_FACTOR 1
4737+#define COLOUR_DIST(r1, g1, b1, r2, g2, b2) \
4738+ (COLOUR_FACTOR * (abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2)) \
4739+ + LIGHT_FACTOR * abs(r1 + g1 + b1 - (r2 + g2 + b2)))
4740+
4741+static void allocate_nearest(_THIS, SDL_Color *colors,
4742+ SDL_Color *want, int nwant)
4743+{
4744+ /*
4745+ * There is no way to know which ones to choose from, so we retrieve
4746+ * the entire colormap and try the nearest possible, until we find one
4747+ * that is shared.
4748+ */
4749+ XColor all[256];
4750+ int i;
4751+ for(i = 0; i < 256; i++)
4752+ all[i].pixel = i;
4753+ /*
4754+ * XQueryColors sets the flags in the XColor struct, so we use
4755+ * that to keep track of which colours are available
4756+ */
4757+ XQueryColors(GFX_Display, SDL_XColorMap, all, 256);
4758+
4759+ for(i = 0; i < nwant; i++) {
4760+ XColor *c;
4761+ int j;
4762+ int best = 0;
4763+ int mindist = 0x7fffffff;
4764+ int ri = want[i].r;
4765+ int gi = want[i].g;
4766+ int bi = want[i].b;
4767+ for(j = 0; j < 256; j++) {
4768+ int rj, gj, bj, d2;
4769+ if(!all[j].flags)
4770+ continue; /* unavailable colour cell */
4771+ rj = all[j].red >> 8;
4772+ gj = all[j].green >> 8;
4773+ bj = all[j].blue >> 8;
4774+ d2 = COLOUR_DIST(ri, gi, bi, rj, gj, bj);
4775+ if(d2 < mindist) {
4776+ mindist = d2;
4777+ best = j;
4778+ }
4779+ }
4780+ if(SDL_XPixels[best])
4781+ continue; /* already allocated, waste no more time */
4782+ c = all + best;
4783+ if(XAllocColor(GFX_Display, SDL_XColorMap, c)) {
4784+ /* got it */
4785+ colors[c->pixel].r = c->red >> 8;
4786+ colors[c->pixel].g = c->green >> 8;
4787+ colors[c->pixel].b = c->blue >> 8;
4788+ ++SDL_XPixels[c->pixel];
4789+ } else {
4790+ /*
4791+ * The colour couldn't be allocated, probably being
4792+ * owned as a r/w cell by another client. Flag it as
4793+ * unavailable and try again. The termination of the
4794+ * loop is guaranteed since at least black and white
4795+ * are always there.
4796+ */
4797+ c->flags = 0;
4798+ i--;
4799+ }
4800+ }
4801+}
4802+
4803+int X11_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
4804+{
4805+ int nrej = 0;
4806+
4807+ /* Check to make sure we have a colormap allocated */
4808+ if ( SDL_XPixels == NULL ) {
4809+ return(0);
4810+ }
4811+ if ( (this->screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) {
4812+ /* private writable colormap: just set the colours we need */
4813+ XColor *xcmap;
4814+ int i;
4815+ xcmap = SDL_stack_alloc(XColor, ncolors);
4816+ if(xcmap == NULL)
4817+ return 0;
4818+ for ( i=0; i<ncolors; ++i ) {
4819+ xcmap[i].pixel = i + firstcolor;
4820+ xcmap[i].red = (colors[i].r<<8)|colors[i].r;
4821+ xcmap[i].green = (colors[i].g<<8)|colors[i].g;
4822+ xcmap[i].blue = (colors[i].b<<8)|colors[i].b;
4823+ xcmap[i].flags = (DoRed|DoGreen|DoBlue);
4824+ }
4825+ XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors);
4826+ XSync(GFX_Display, False);
4827+ SDL_stack_free(xcmap);
4828+ } else {
4829+ /*
4830+ * Shared colormap: We only allocate read-only cells, which
4831+ * increases the likelyhood of colour sharing with other
4832+ * clients. The pixel values will almost certainly be
4833+ * different from the requested ones, so the user has to
4834+ * walk the colormap and see which index got what colour.
4835+ *
4836+ * We can work directly with the logical palette since it
4837+ * has already been set when we get here.
4838+ */
4839+ SDL_Color *want, *reject;
4840+ unsigned long *freelist;
4841+ int i;
4842+ int nfree = 0;
4843+ int nc = this->screen->format->palette->ncolors;
4844+ colors = this->screen->format->palette->colors;
4845+ freelist = SDL_stack_alloc(unsigned long, nc);
4846+ /* make sure multiple allocations of the same cell are freed */
4847+ for(i = 0; i < ncolors; i++) {
4848+ int pixel = firstcolor + i;
4849+ while(SDL_XPixels[pixel]) {
4850+ freelist[nfree++] = pixel;
4851+ --SDL_XPixels[pixel];
4852+ }
4853+ }
4854+ XFreeColors(GFX_Display, SDL_XColorMap, freelist, nfree, 0);
4855+ SDL_stack_free(freelist);
4856+
4857+ want = SDL_stack_alloc(SDL_Color, ncolors);
4858+ reject = SDL_stack_alloc(SDL_Color, ncolors);
4859+ SDL_memcpy(want, colors + firstcolor, ncolors * sizeof(SDL_Color));
4860+ /* make sure the user isn't fooled by her own wishes
4861+ (black is safe, always available in the default colormap) */
4862+ SDL_memset(colors + firstcolor, 0, ncolors * sizeof(SDL_Color));
4863+
4864+ /* now try to allocate the colours */
4865+ for(i = 0; i < ncolors; i++) {
4866+ XColor col;
4867+ col.red = want[i].r << 8;
4868+ col.green = want[i].g << 8;
4869+ col.blue = want[i].b << 8;
4870+ col.flags = DoRed | DoGreen | DoBlue;
4871+ if(XAllocColor(GFX_Display, SDL_XColorMap, &col)) {
4872+ /* We got the colour, or at least the nearest
4873+ the hardware could get. */
4874+ colors[col.pixel].r = col.red >> 8;
4875+ colors[col.pixel].g = col.green >> 8;
4876+ colors[col.pixel].b = col.blue >> 8;
4877+ ++SDL_XPixels[col.pixel];
4878+ } else {
4879+ /*
4880+ * no more free cells, add it to the list
4881+ * of rejected colours
4882+ */
4883+ reject[nrej++] = want[i];
4884+ }
4885+ }
4886+ if(nrej)
4887+ allocate_nearest(this, colors, reject, nrej);
4888+ SDL_stack_free(reject);
4889+ SDL_stack_free(want);
4890+ }
4891+ return nrej == 0;
4892+}
4893+
4894+int X11_SetGammaRamp(_THIS, Uint16 *ramp)
4895+{
4896+ int i, ncolors;
4897+ XColor xcmap[256];
4898+
4899+ /* See if actually setting the gamma is supported */
4900+ if ( SDL_Visual->class != DirectColor ) {
4901+ SDL_SetError("Gamma correction not supported on this visual");
4902+ return(-1);
4903+ }
4904+
4905+ /* Calculate the appropriate palette for the given gamma ramp */
4906+ ncolors = SDL_Visual->map_entries;
4907+ for ( i=0; i<ncolors; ++i ) {
4908+ Uint8 c = (256 * i / ncolors);
4909+ xcmap[i].pixel = SDL_MapRGB(this->screen->format, c, c, c);
4910+ xcmap[i].red = ramp[0*256+c];
4911+ xcmap[i].green = ramp[1*256+c];
4912+ xcmap[i].blue = ramp[2*256+c];
4913+ xcmap[i].flags = (DoRed|DoGreen|DoBlue);
4914+ }
4915+ XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors);
4916+ XSync(GFX_Display, False);
4917+ return(0);
4918+}
4919+
4920+/* Note: If we are terminated, this could be called in the middle of
4921+ another SDL video routine -- notably UpdateRects.
4922+*/
4923+void X11_VideoQuit(_THIS)
4924+{
4925+ /* Shutdown everything that's still up */
4926+ /* The event thread should be done, so we can touch SDL_Display */
4927+ if ( SDL_Display != NULL ) {
4928+ /* Flush any delayed updates */
4929+ XSync(GFX_Display, False);
4930+
4931+ /* Close the connection with the IM server */
4932+ #ifdef X_HAVE_UTF8_STRING
4933+ if (SDL_IC != NULL) {
4934+ XUnsetICFocus(SDL_IC);
4935+ XDestroyIC(SDL_IC);
4936+ SDL_IC = NULL;
4937+ }
4938+ if (SDL_IM != NULL) {
4939+ XCloseIM(SDL_IM);
4940+ SDL_IM = NULL;
4941+ }
4942+ #endif
4943+
4944+ /* Start shutting down the windows */
4945+ X11_DestroyImage(this, this->screen);
4946+ X11_DestroyWindow(this, this->screen);
4947+ X11_FreeVideoModes(this);
4948+ if ( SDL_XColorMap != SDL_DisplayColormap ) {
4949+ XFreeColormap(SDL_Display, SDL_XColorMap);
4950+ }
4951+ if ( SDL_iconcolors ) {
4952+ unsigned long pixel;
4953+ Colormap dcmap = DefaultColormap(SDL_Display,
4954+ SDL_Screen);
4955+ for(pixel = 0; pixel < 256; ++pixel) {
4956+ while(SDL_iconcolors[pixel] > 0) {
4957+ XFreeColors(GFX_Display,
4958+ dcmap, &pixel, 1, 0);
4959+ --SDL_iconcolors[pixel];
4960+ }
4961+ }
4962+ SDL_free(SDL_iconcolors);
4963+ SDL_iconcolors = NULL;
4964+ }
4965+
4966+ /* Restore gamma settings if they've changed */
4967+ if ( SDL_GetAppState() & SDL_APPACTIVE ) {
4968+ X11_SwapVidModeGamma(this);
4969+ }
4970+
4971+ /* Free that blank cursor */
4972+ if ( SDL_BlankCursor != NULL ) {
4973+ this->FreeWMCursor(this, SDL_BlankCursor);
4974+ SDL_BlankCursor = NULL;
4975+ }
4976+
4977+ /* Close the X11 graphics connection */
4978+ if ( GFX_Display != NULL ) {
4979+ XCloseDisplay(GFX_Display);
4980+ GFX_Display = NULL;
4981+ }
4982+
4983+ /* Close the X11 display connection */
4984+ XCloseDisplay(SDL_Display);
4985+ SDL_Display = NULL;
4986+
4987+ /* Reset the X11 error handlers */
4988+ if ( XIO_handler ) {
4989+ XSetIOErrorHandler(XIO_handler);
4990+ }
4991+ if ( X_handler ) {
4992+ XSetErrorHandler(X_handler);
4993+ }
4994+
4995+ /* Unload GL library after X11 shuts down */
4996+ X11_GL_UnloadLibrary(this);
4997+ }
4998+ if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) {
4999+ /* Direct screen access, no memory buffer */
5000+ this->screen->pixels = NULL;
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches