~ubuntu-branches/ubuntu/precise/clutter-1.0/precise

« back to all changes in this revision

Viewing changes to clutter/x11/clutter-backend-x11.c

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2010-03-21 13:27:56 UTC
  • mto: (2.1.3 experimental) (1.3.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 8.
  • Revision ID: james.westby@ubuntu.com-20100321132756-nf8yd30yxo3zzwcm
Tags: upstream-1.2.2
ImportĀ upstreamĀ versionĀ 1.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
 * Lesser General Public License for more details.
15
15
 *
16
16
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, write to the
18
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
 
 * Boston, MA 02111-1307, USA.
 
17
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 
18
 *
 
19
 *
20
20
 */
21
21
 
22
22
#ifdef HAVE_CONFIG_H
26
26
#include <glib/gi18n-lib.h>
27
27
 
28
28
#include <string.h>
29
 
#include <sys/types.h>
30
 
#ifdef HAVE_UNISTD_H
 
29
 
31
30
#include <unistd.h>
32
 
#endif
33
31
 
 
32
#include <sys/ioctl.h>
34
33
#include <sys/stat.h>
35
 
#include <sys/ioctl.h>
 
34
#include <sys/types.h>
 
35
 
36
36
#include <fcntl.h>
 
37
 
37
38
#include <errno.h>
38
39
 
39
40
#include "clutter-backend-x11.h"
 
41
#include "clutter-device-manager-x11.h"
 
42
#include "clutter-input-device-x11.h"
40
43
#include "clutter-stage-x11.h"
41
44
#include "clutter-x11.h"
42
45
 
46
49
#include <X11/extensions/XInput.h>
47
50
#endif
48
51
 
 
52
#include "cogl/cogl.h"
 
53
 
 
54
#include "../clutter-debug.h"
 
55
#include "../clutter-device-manager.h"
49
56
#include "../clutter-event.h"
50
57
#include "../clutter-main.h"
51
 
#include "../clutter-debug.h"
52
58
#include "../clutter-private.h"
53
59
 
54
 
#include "cogl/cogl.h"
55
 
 
56
60
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND);
57
61
 
58
 
struct _ClutterX11XInputDevice
59
 
{
60
 
  ClutterInputDevice device;
61
 
 
62
 
#ifdef HAVE_XINPUT
63
 
  XDevice           *xdevice;
64
 
  XEventClass        xevent_list[5];   /* MAX 5 event types */
65
 
  int                num_events;
66
 
#endif
67
 
};
68
 
 
69
 
#ifdef HAVE_XINPUT
70
 
void  _clutter_x11_register_xinput ();
71
 
#endif
72
 
 
73
 
 
74
62
/* atoms; remember to add the code that assigns the atom value to
75
63
 * the member of the ClutterBackendX11 structure if you add an
76
64
 * atom name here. do not change the order!
97
85
/* various flags corresponding to pre init setup calls */
98
86
static gboolean _no_xevent_retrieval = FALSE;
99
87
static gboolean clutter_enable_xinput = FALSE;
 
88
static gboolean clutter_enable_argb = FALSE;
100
89
static Display  *_foreign_dpy = NULL;
101
90
 
102
91
/* options */
124
113
      env_string = NULL;
125
114
    }
126
115
 
 
116
  env_string = g_getenv ("CLUTTER_DISABLE_ARGB_VISUAL");
 
117
  if (env_string)
 
118
    {
 
119
      clutter_enable_argb = FALSE;
 
120
      env_string = NULL;
 
121
    }
 
122
 
127
123
  return TRUE;
128
124
}
129
125
 
191
187
 
192
188
      clutter_backend_set_resolution (backend, dpi);
193
189
 
194
 
#ifdef HAVE_XINPUT
195
 
      _clutter_x11_register_xinput ();
196
 
#endif
 
190
      /* register input devices */
 
191
      backend_x11->device_manager =
 
192
        g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_X11,
 
193
                      "use-xinput-1", clutter_enable_xinput,
 
194
                      "backend", backend_x11,
 
195
                      NULL);
197
196
 
198
197
      if (clutter_synchronise)
199
198
        XSynchronize (backend_x11->xdpy, True);
341
340
  return CLUTTER_FEATURE_STAGE_USER_RESIZE | CLUTTER_FEATURE_STAGE_CURSOR;
342
341
}
343
342
 
 
343
gboolean
 
344
clutter_backend_x11_handle_event (ClutterBackendX11 *backend_x11,
 
345
                                  XEvent *xevent)
 
346
{
 
347
  return FALSE;
 
348
}
 
349
 
 
350
static ClutterDeviceManager *
 
351
clutter_backend_x11_get_device_manager (ClutterBackend *backend)
 
352
{
 
353
  ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
 
354
 
 
355
  if (G_UNLIKELY (backend_x11->device_manager == NULL))
 
356
    {
 
357
      backend_x11->device_manager =
 
358
        g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_X11,
 
359
                      "use-xinput-1", clutter_enable_xinput,
 
360
                      "backend", backend_x11,
 
361
                      NULL);
 
362
    }
 
363
 
 
364
  return backend_x11->device_manager;
 
365
}
 
366
 
344
367
static void
345
368
clutter_backend_x11_class_init (ClutterBackendX11Class *klass)
346
369
{
347
370
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
348
371
  ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
 
372
  ClutterBackendX11Class *backendx11_class = CLUTTER_BACKEND_X11_CLASS (klass);
349
373
 
350
374
  gobject_class->constructor = clutter_backend_x11_constructor;
351
375
  gobject_class->dispose = clutter_backend_x11_dispose;
352
376
  gobject_class->finalize = clutter_backend_x11_finalize;
353
377
 
354
 
  backend_class->pre_parse        = clutter_backend_x11_pre_parse;
355
 
  backend_class->post_parse       = clutter_backend_x11_post_parse;
356
 
  backend_class->init_events      = clutter_backend_x11_init_events;
357
 
  backend_class->add_options      = clutter_backend_x11_add_options;
358
 
  backend_class->get_features     = clutter_backend_x11_get_features;
 
378
  backend_class->pre_parse = clutter_backend_x11_pre_parse;
 
379
  backend_class->post_parse = clutter_backend_x11_post_parse;
 
380
  backend_class->init_events = clutter_backend_x11_init_events;
 
381
  backend_class->add_options = clutter_backend_x11_add_options;
 
382
  backend_class->get_features = clutter_backend_x11_get_features;
 
383
  backend_class->get_device_manager = clutter_backend_x11_get_device_manager;
 
384
 
 
385
  backendx11_class->handle_event = clutter_backend_x11_handle_event;
359
386
}
360
387
 
361
388
static void
463
490
 * clutter_x11_enable_xinput:
464
491
 *
465
492
 * Enables the use of the XInput extension if present on connected
466
 
 * XServer and support built into Clutter.  XInput allows for multiple
467
 
 * pointing devices to be used. This must be called before
468
 
 * clutter_init().
469
 
 *
470
 
 * You should use #clutter_x11_has_xinput to see if support was enabled.
 
493
 * XServer and support built into Clutter. XInput allows for multiple
 
494
 * pointing devices to be used.
 
495
 *
 
496
 * This function must be called before clutter_init().
 
497
 *
 
498
 * Since XInput might not be supported by the X server, you might
 
499
 * want to use clutter_x11_has_xinput() to see if support was enabled.
471
500
 *
472
501
 * Since: 0.8
473
502
 */
637
666
}
638
667
 
639
668
void
640
 
_clutter_x11_register_xinput ()
641
 
{
642
 
#ifdef HAVE_XINPUT
643
 
  XDeviceInfo *xdevices = NULL;
644
 
  XDeviceInfo *info = NULL;
645
 
 
646
 
  XDevice *xdevice = NULL;
647
 
 
648
 
  XInputClassInfo *xclass_info = NULL;
649
 
 
650
 
  gint opcode, event, error;
651
 
  gint res;
652
 
  gint num_devices = 0;
653
 
  gint num_events = 0;
654
 
  gint i = 0, j = 0;
655
 
  gboolean have_an_xpointer = FALSE;
656
 
 
657
 
  ClutterBackendX11      *x11b;
658
 
  ClutterX11XInputDevice *device = NULL;
659
 
 
660
 
  ClutterMainContext  *context;
661
 
 
662
 
  GSList *input_devices = NULL;
663
 
 
664
 
  if (!backend_singleton)
665
 
    {
666
 
      g_critical ("X11 backend has not been initialised");
667
 
      return;
668
 
    }
669
 
 
670
 
  if (!clutter_enable_xinput)
671
 
    {
672
 
      CLUTTER_NOTE (BACKEND, "Not enabling XInput");
673
 
      return;
674
 
    }
675
 
 
676
 
  context = _clutter_context_get_default ();
677
 
 
678
 
  backend_singleton->have_xinput = FALSE;
679
 
 
680
 
  /* is the XInput extension available? */
681
 
  res = XQueryExtension (backend_singleton->xdpy, "XInputExtension",
682
 
                         &opcode, &event,
683
 
                         &error);
684
 
  if (!res)
685
 
    {
686
 
      CLUTTER_NOTE (BACKEND, "X Input extension not available");
687
 
      return;
688
 
    }
689
 
 
690
 
  x11b = backend_singleton;
691
 
 
692
 
  xdevices = XListInputDevices (x11b->xdpy, &num_devices);
693
 
 
694
 
  CLUTTER_NOTE (BACKEND, "%d XINPUT devices found", num_devices);
695
 
 
696
 
  if (num_devices == 0)
697
 
    return;
698
 
 
699
 
  for (i = 0; i < num_devices; i++)
700
 
    {
701
 
      info = xdevices + i;
702
 
      num_events = 0;
703
 
 
704
 
      CLUTTER_NOTE (BACKEND, "Considering %li with type %d",
705
 
                    info->id,
706
 
                    info->use);
707
 
 
708
 
      /* Only want 'raw' devices themselves not virtual ones */
709
 
      if (info->use == IsXExtensionPointer ||
710
 
        /*info->use == IsXExtensionKeyboard || XInput 1.x is broken */
711
 
          info->use == IsXExtensionDevice)
712
 
        {
713
 
          clutter_x11_trap_x_errors ();
714
 
          xdevice = XOpenDevice (backend_singleton->xdpy, info->id);
715
 
          if (clutter_x11_untrap_x_errors () || xdevice == NULL)
716
 
            continue;
717
 
 
718
 
          /* Create the appropriate Clutter device */
719
 
          device = g_slice_new0 (ClutterX11XInputDevice);
720
 
 
721
 
          device->device.id = info->id;
722
 
 
723
 
          switch (info->use)
724
 
            {
725
 
            case IsXExtensionPointer:
726
 
              device->device.device_type = CLUTTER_POINTER_DEVICE;
727
 
              have_an_xpointer = TRUE;
728
 
              break;
729
 
 
730
 
#if 0
731
 
            /* XInput 1.x is broken for keyboards: */
732
 
            case IsXExtensionKeyboard:
733
 
              device->device.type = CLUTTER_KEYBOARD_DEVICE;
734
 
              break;
735
 
#endif
736
 
 
737
 
            case IsXExtensionDevice:
738
 
              device->device.device_type = CLUTTER_EXTENSION_DEVICE;
739
 
              break;
740
 
            }
741
 
 
742
 
          /* FIXME: some kind of general device_init() call should do below */
743
 
          device->device.click_count = 0;
744
 
          device->device.previous_time = 0;
745
 
          device->device.previous_x = -1;
746
 
          device->device.previous_y = -1;
747
 
          device->device.previous_button_number = -1;
748
 
 
749
 
          device->num_events = 0;
750
 
          device->xdevice = xdevice;
751
 
 
752
 
          CLUTTER_NOTE (BACKEND, "Registering XINPUT device with XID: %li",
753
 
                        xdevice->device_id);
754
 
 
755
 
          /* We must go through all the classes supported by this device and
756
 
           * register the appropriate events we want. Each class only appears
757
 
           * once. We need to store the types with the stage since they are
758
 
           * created dynamically by the server. They are not device specific.
759
 
           */
760
 
          for (j = 0; j < xdevice->num_classes; j++)
761
 
            {
762
 
              xclass_info = xdevice->classes + j;
763
 
 
764
 
              switch (xclass_info->input_class)
765
 
                {
766
 
#if 0
767
 
                /* XInput 1.x is broken for keyboards: */
768
 
                case KeyClass:
769
 
                  DeviceKeyPress (xdevice,
770
 
                                  x11b->event_types[CLUTTER_X11_XINPUT_KEY_PRESS_EVENT],
771
 
                                  device->xevent_list [num_events]);
772
 
                  num_events++;
773
 
 
774
 
                  DeviceKeyRelease (xdevice,
775
 
                                    x11b->event_types[CLUTTER_X11_XINPUT_KEY_RELEASE_EVENT],
776
 
                                    device->xevent_list [num_events]);
777
 
                  num_events++;
778
 
                  break;
779
 
#endif
780
 
 
781
 
                case ButtonClass:
782
 
                  DeviceButtonPress (xdevice,
783
 
                                     x11b->event_types[CLUTTER_X11_XINPUT_BUTTON_PRESS_EVENT],
784
 
                                     device->xevent_list [num_events]);
785
 
                  num_events++;
786
 
 
787
 
                  DeviceButtonRelease (xdevice,
788
 
                                       x11b->event_types[CLUTTER_X11_XINPUT_BUTTON_RELEASE_EVENT],
789
 
                                       device->xevent_list [num_events]);
790
 
                  num_events++;
791
 
                  break;
792
 
 
793
 
                case ValuatorClass:
794
 
                  DeviceMotionNotify (xdevice,
795
 
                                      x11b->event_types[CLUTTER_X11_XINPUT_MOTION_NOTIFY_EVENT],
796
 
                                      device->xevent_list [num_events]);
797
 
                  num_events++;
798
 
                  break;
799
 
                }
800
 
            }
801
 
 
802
 
          if (info->use == IsXExtensionPointer && num_events > 0)
803
 
            have_an_xpointer = TRUE;
804
 
 
805
 
          device->num_events  = num_events;
806
 
 
807
 
          input_devices = g_slist_prepend (input_devices, device);
808
 
        }
809
 
    }
810
 
 
811
 
  XFree (xdevices);
812
 
 
813
 
  if (!have_an_xpointer)
814
 
    {
815
 
      GSList *l;
816
 
 
817
 
      /* Something is likely wrong with Xinput setup so we basically
818
 
       * abort here and fall back to lofi regular xinput.
819
 
      */
820
 
      g_warning ("No usuable XInput pointing devices found");
821
 
 
822
 
      for (l = input_devices; l != NULL; l = l->next)
823
 
        g_slice_free (ClutterX11XInputDevice, l->data);
824
 
 
825
 
      g_slist_free (input_devices);
826
 
      context->input_devices = NULL;
827
 
 
828
 
      return;
829
 
    }
830
 
 
831
 
  /* store the list of input devices */
832
 
  context->input_devices = g_slist_reverse (input_devices);
833
 
 
834
 
  /* why yes, we are awesome */
835
 
  backend_singleton->have_xinput = TRUE;
836
 
#endif /* HAVE_XINPUT */
837
 
}
838
 
 
839
 
void
840
 
_clutter_x11_unregister_xinput ()
841
 
{
842
 
 
843
 
}
844
 
 
845
 
void
846
669
_clutter_x11_select_events (Window xwin)
847
670
{
848
671
#ifdef HAVE_XINPUT
849
 
  GSList *list_it;
850
 
  ClutterX11XInputDevice *device = NULL;
851
 
 
852
 
  ClutterMainContext  *context;
853
 
 
854
 
  context = _clutter_context_get_default ();
855
 
 
856
 
  if (!backend_singleton)
 
672
  ClutterDeviceManager *manager;
 
673
  const GSList *l;
 
674
 
 
675
  if (G_UNLIKELY (backend_singleton == NULL))
857
676
    {
858
677
      g_critical ("X11 backend has not been initialised");
 
678
 
859
679
      return;
860
680
    }
861
681
 
862
 
  for (list_it = context->input_devices;
863
 
       list_it != NULL;
864
 
       list_it = list_it->next)
 
682
  manager = clutter_device_manager_get_default ();
 
683
 
 
684
  for (l = clutter_device_manager_peek_devices (manager);
 
685
       l != NULL;
 
686
       l = l->next)
865
687
  {
866
 
    device = (ClutterX11XInputDevice *)list_it->data;
 
688
    ClutterInputDevice *device = l->data;
867
689
 
868
 
    XSelectExtensionEvent (backend_singleton->xdpy,
869
 
                           xwin,
870
 
                           device->xevent_list,
871
 
                           device->num_events);
 
690
    _clutter_input_device_x11_select_events (device, backend_singleton, xwin);
872
691
  }
873
692
#endif /* HAVE_XINPUT */
874
693
}
876
695
ClutterInputDevice *
877
696
_clutter_x11_get_device_for_xid (XID id)
878
697
{
879
 
#ifdef HAVE_XINPUT
880
 
  ClutterMainContext *context;
881
 
  GSList *l;
882
 
 
883
 
  context = _clutter_context_get_default ();
884
 
 
885
 
  if (!backend_singleton)
886
 
    {
887
 
      g_critical ("X11 backend has not been initialised");
888
 
      return NULL;
889
 
    }
890
 
 
891
 
  for (l = context->input_devices; l != NULL; l = l->next)
892
 
    {
893
 
      ClutterX11XInputDevice *device = l->data;
894
 
 
895
 
      if (device->xdevice->device_id == id)
896
 
        return (ClutterInputDevice *) device;
897
 
    }
898
 
#endif /* HAVE_XINPUT */
899
 
 
900
 
  return NULL;
 
698
  ClutterDeviceManager *manager;
 
699
 
 
700
  manager = clutter_device_manager_get_default ();
 
701
 
 
702
  return clutter_device_manager_get_device (manager, (gint) id);
901
703
}
902
704
 
903
 
/* FIXME: This nasty little func needs moving elsewhere.. */
 
705
/**
 
706
 * clutter_x11_get_input_devices:
 
707
 *
 
708
 * Retrieves a pointer to the list of input devices
 
709
 *
 
710
 * Deprecated: 1.2: Use clutter_device_manager_peek_devices() instead
 
711
 *
 
712
 * Since: 0.8
 
713
 *
 
714
 * Return value: a pointer to the internal list of input devices; the
 
715
 *   returned list is owned by Clutter and should not be modified or
 
716
 *   freed
 
717
 */
904
718
G_CONST_RETURN GSList *
905
719
clutter_x11_get_input_devices (void)
906
720
{
907
 
#ifdef HAVE_XINPUT
908
 
  ClutterMainContext  *context;
909
 
 
910
 
  if (!backend_singleton)
911
 
    {
912
 
      g_critical ("X11 backend has not been initialised");
913
 
      return NULL;
914
 
    }
915
 
 
916
 
  context = _clutter_context_get_default ();
917
 
 
918
 
  return context->input_devices;
919
 
#else /* !HAVE_XINPUT */
920
 
  return NULL;
921
 
#endif /* HAVE_XINPUT */
 
721
  ClutterDeviceManager *manager;
 
722
 
 
723
  manager = clutter_device_manager_get_default ();
 
724
 
 
725
  return clutter_device_manager_peek_devices (manager);
922
726
}
923
727
 
924
728
/**
935
739
clutter_x11_has_xinput (void)
936
740
{
937
741
#ifdef HAVE_XINPUT
938
 
  if (!backend_singleton)
 
742
  if (backend_singleton == NULL)
939
743
    {
940
744
      g_critical ("X11 backend has not been initialised");
941
745
      return FALSE;
947
751
#endif
948
752
}
949
753
 
 
754
/**
 
755
 * clutter_x11_has_composite_extension:
 
756
 *
 
757
 * Retrieves whether Clutter is running on an X11 server with the
 
758
 * XComposite extension
 
759
 *
 
760
 * Return value: %TRUE if the XComposite extension is available
 
761
 */
950
762
gboolean
951
763
clutter_x11_has_composite_extension (void)
952
764
{
980
792
  return have_composite;
981
793
}
982
794
 
 
795
/**
 
796
 * clutter_x11_set_use_argb_visual:
 
797
 * @use_argb: %TRUE if ARGB visuals should be requested by default
 
798
 *
 
799
 * Sets whether the Clutter X11 backend should request ARGB visuals by default
 
800
 * or not.
 
801
 *
 
802
 * By default, Clutter requests RGB visuals.
 
803
 *
 
804
 * <note>If no ARGB visuals are found, the X11 backend will fall back to
 
805
 * requesting a RGB visual instead.</note>
 
806
 *
 
807
 * ARGB visuals are required for the #ClutterStage:use-alpha property to work.
 
808
 *
 
809
 * <note>This function can only be called once, and before clutter_init() is
 
810
 * called.</note>
 
811
 *
 
812
 * Since: 1.2
 
813
 */
 
814
void
 
815
clutter_x11_set_use_argb_visual (gboolean use_argb)
 
816
{
 
817
  if (backend_singleton != NULL)
 
818
    {
 
819
      g_warning ("%s() can only be used before calling clutter_init()",
 
820
                 G_STRFUNC);
 
821
      return;
 
822
    }
 
823
 
 
824
  CLUTTER_NOTE (BACKEND, "ARGB visuals are %s",
 
825
                use_argb ? "enabled" : "disabled");
 
826
 
 
827
  clutter_enable_argb = use_argb;
 
828
}
 
829
 
 
830
/**
 
831
 * clutter_x11_get_use_argb_visual:
 
832
 *
 
833
 * Retrieves whether the Clutter X11 backend is using ARGB visuals by default
 
834
 *
 
835
 * Return value: %TRUE if ARGB visuals are queried by default
 
836
 *
 
837
 * Since: 1.2
 
838
 */
 
839
gboolean
 
840
clutter_x11_get_use_argb_visual (void)
 
841
{
 
842
  return clutter_enable_argb;
 
843
}
 
844
 
983
845
XVisualInfo *
984
 
clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11,
985
 
                                     gboolean           for_offscreen)
 
846
clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11)
986
847
{
987
848
  ClutterBackendX11Class *klass;
988
849
 
990
851
 
991
852
  klass = CLUTTER_BACKEND_X11_GET_CLASS (backend_x11);
992
853
  if (klass->get_visual_info)
993
 
    return klass->get_visual_info (backend_x11, for_offscreen);
 
854
    return klass->get_visual_info (backend_x11);
994
855
 
995
856
  return NULL;
996
857
}
 
858
 
 
859
/**
 
860
 * clutter_x11_get_visual_info:
 
861
 *
 
862
 * Retrieves the <structname>XVisualInfo</structname> used by the Clutter X11
 
863
 * backend.
 
864
 *
 
865
 * Return value: a <structname>XVisualInfo</structname>, or
 
866
 *   <varname>None</varname>. The returned value should be freed using XFree()
 
867
 *   when done
 
868
 *
 
869
 * Since: 1.2
 
870
 */
 
871
XVisualInfo *
 
872
clutter_x11_get_visual_info (void)
 
873
{
 
874
  ClutterBackendX11 *backend_x11;
 
875
 
 
876
  backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ());
 
877
 
 
878
  return clutter_backend_x11_get_visual_info (backend_x11);
 
879
}