meta-backend-x11.c 24.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */

/*
 * Copyright (C) 2014 Red Hat
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 *
 * Written by:
 *     Jasper St. Pierre <jstpierre@mecheye.net>
 */

Niels De Graef's avatar
Niels De Graef committed
25 26 27 28 29 30 31 32 33
/**
 * SECTION:meta-backend-x11
 * @title: MetaBackendX11
 * @short_description: A X11 MetaBackend
 *
 * MetaBackendX11 is an implementation of #MetaBackend using X and X
 * extensions, like XInput and XKB.
 */

34 35
#include "config.h"

Jonas Ådahl's avatar
Jonas Ådahl committed
36
#include "backends/x11/meta-backend-x11.h"
37

38 39
#include <X11/XKBlib.h>
#include <X11/Xlib-xcb.h>
Jonas Ådahl's avatar
Jonas Ådahl committed
40 41 42
#include <X11/extensions/sync.h>
#include <stdlib.h>
#include <string.h>
43
#include <xkbcommon/xkbcommon-x11.h>
44

Jonas Ådahl's avatar
Jonas Ådahl committed
45 46
#include "backends/meta-dnd-private.h"
#include "backends/meta-idle-monitor-private.h"
47
#include "backends/meta-stage-private.h"
48
#include "backends/x11/meta-clutter-backend-x11.h"
Jonas Ådahl's avatar
Jonas Ådahl committed
49
#include "backends/x11/meta-renderer-x11.h"
Jonas Ådahl's avatar
Jonas Ådahl committed
50 51
#include "clutter/clutter.h"
#include "clutter/x11/clutter-x11.h"
52
#include "compositor/compositor-private.h"
Jonas Ådahl's avatar
Jonas Ådahl committed
53 54 55
#include "core/display-private.h"
#include "meta/meta-cursor-tracker.h"
#include "meta/util.h"
56

57 58 59 60
struct _MetaBackendX11Private
{
  /* The host X11 display */
  Display *xdisplay;
61
  xcb_connection_t *xcb;
62 63 64 65
  GSource *source;

  int xsync_event_base;
  int xsync_error_base;
66 67
  XSyncAlarm user_active_alarm;
  XSyncCounter counter;
68 69 70 71

  int xinput_opcode;
  int xinput_event_base;
  int xinput_error_base;
72
  Time latest_evtime;
73 74 75

  uint8_t xkb_event_base;
  uint8_t xkb_error_base;
76 77

  struct xkb_keymap *keymap;
78
  xkb_layout_index_t keymap_layout_group;
79 80

  MetaLogicalMonitor *cached_current_logical_monitor;
81 82 83
};
typedef struct _MetaBackendX11Private MetaBackendX11Private;

84 85 86 87 88 89 90 91 92
static GInitableIface *initable_parent_iface;

static void
initable_iface_init (GInitableIface *initable_iface);

G_DEFINE_TYPE_WITH_CODE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND,
                         G_ADD_PRIVATE (MetaBackendX11)
                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
                                                initable_iface_init));
93

94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166

static void
uint64_to_xsync_value (uint64_t    value,
                       XSyncValue *xsync_value)
{
  XSyncIntsToValue (xsync_value, value & 0xffffffff, value >> 32);
}

static XSyncAlarm
xsync_user_active_alarm_set (MetaBackendX11Private *priv)
{
  XSyncAlarmAttributes attr;
  XSyncValue delta;
  unsigned long flags;

  flags = (XSyncCACounter | XSyncCAValueType | XSyncCATestType |
           XSyncCAValue | XSyncCADelta | XSyncCAEvents);

  XSyncIntToValue (&delta, 0);
  attr.trigger.counter = priv->counter;
  attr.trigger.value_type = XSyncAbsolute;
  attr.delta = delta;
  attr.events = TRUE;

  uint64_to_xsync_value (1, &attr.trigger.wait_value);

  attr.trigger.test_type = XSyncNegativeTransition;
  return XSyncCreateAlarm (priv->xdisplay, flags, &attr);
}

static XSyncCounter
find_idletime_counter (MetaBackendX11Private *priv)
{
  int i;
  int n_counters;
  XSyncSystemCounter *counters;
  XSyncCounter counter = None;

  counters = XSyncListSystemCounters (priv->xdisplay, &n_counters);
  for (i = 0; i < n_counters; i++)
    {
      if (g_strcmp0 (counters[i].name, "IDLETIME") == 0)
        {
          counter = counters[i].counter;
          break;
        }
    }
  XSyncFreeSystemCounterList (counters);

  return counter;
}

static void
handle_alarm_notify (MetaBackend           *backend,
                     XSyncAlarmNotifyEvent *alarm_event)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
  MetaIdleMonitor *idle_monitor;
  XSyncAlarmAttributes attr;

  if (alarm_event->state != XSyncAlarmActive ||
      alarm_event->alarm != priv->user_active_alarm)
    return;

  attr.events = TRUE;
  XSyncChangeAlarm (priv->xdisplay, priv->user_active_alarm,
                    XSyncCAEvents, &attr);

  idle_monitor = meta_backend_get_idle_monitor (backend, 0);
  meta_idle_monitor_reset_idletime (idle_monitor);
}

167 168 169 170 171 172 173 174 175 176
static void
meta_backend_x11_translate_device_event (MetaBackendX11 *x11,
                                         XIDeviceEvent  *device_event)
{
  MetaBackendX11Class *backend_x11_class =
    META_BACKEND_X11_GET_CLASS (x11);

  backend_x11_class->translate_device_event (x11, device_event);
}

177 178 179 180
static void
translate_device_event (MetaBackendX11 *x11,
                        XIDeviceEvent  *device_event)
{
181
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
182

183
  meta_backend_x11_translate_device_event (x11, device_event);
184

185
  if (!device_event->send_event && device_event->time != META_CURRENT_TIME)
186
    {
187
      if (XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime))
188 189 190 191 192 193 194 195 196 197 198
        {
          /* Emulated pointer events received after XIRejectTouch is received
           * on a passive touch grab will contain older timestamps, update those
           * so we dont get InvalidTime at grabs.
           */
          device_event->time = priv->latest_evtime;
        }

      /* Update the internal latest evtime, for any possible later use */
      priv->latest_evtime = device_event->time;
    }
199 200
}

201 202 203 204 205 206 207 208 209 210 211
static void
meta_backend_x11_translate_crossing_event (MetaBackendX11 *x11,
                                           XIEnterEvent   *enter_event)
{
  MetaBackendX11Class *backend_x11_class =
    META_BACKEND_X11_GET_CLASS (x11);

  if (backend_x11_class->translate_crossing_event)
    backend_x11_class->translate_crossing_event (x11, enter_event);
}

212 213 214 215 216 217 218 219 220 221 222 223
static void
translate_crossing_event (MetaBackendX11 *x11,
                          XIEnterEvent   *enter_event)
{
  /* Throw out weird events generated by grabs. */
  if (enter_event->mode == XINotifyGrab ||
      enter_event->mode == XINotifyUngrab)
    {
      enter_event->event = None;
      return;
    }

224
  meta_backend_x11_translate_crossing_event (x11, enter_event);
225 226
}

227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
static void
handle_device_change (MetaBackendX11 *x11,
                      XIEvent        *event)
{
  XIDeviceChangedEvent *device_changed;

  if (event->evtype != XI_DeviceChanged)
    return;

  device_changed = (XIDeviceChangedEvent *) event;

  if (device_changed->reason != XISlaveSwitch)
    return;

  meta_backend_update_last_device (META_BACKEND (x11),
                                   device_changed->sourceid);
}

245 246 247 248 249 250 251 252 253 254 255
/* Clutter makes the assumption that there is only one X window
 * per stage, which is a valid assumption to make for a generic
 * application toolkit. As such, it will ignore any events sent
 * to the a stage that isn't its X window.
 *
 * When running as an X window manager, we need to respond to
 * events from lots of windows. Trick Clutter into translating
 * these events by pretending we got an event on the stage window.
 */
static void
maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
                                  XIEvent        *input_event)
{
  switch (input_event->evtype)
    {
    case XI_Motion:
    case XI_ButtonPress:
    case XI_ButtonRelease:
    case XI_KeyPress:
    case XI_KeyRelease:
    case XI_TouchBegin:
    case XI_TouchUpdate:
    case XI_TouchEnd:
      translate_device_event (x11, (XIDeviceEvent *) input_event);
      break;
    case XI_Enter:
    case XI_Leave:
      translate_crossing_event (x11, (XIEnterEvent *) input_event);
      break;
    default:
      break;
    }
}

static void
handle_input_event (MetaBackendX11 *x11,
                    XEvent         *event)
282 283 284 285 286 287 288 289
{
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

  if (event->type == GenericEvent &&
      event->xcookie.extension == priv->xinput_opcode)
    {
      XIEvent *input_event = (XIEvent *) event->xcookie.data;

290 291 292 293
      if (input_event->evtype == XI_DeviceChanged)
        handle_device_change (x11, input_event);
      else
        maybe_spoof_event_as_stage_event (x11, input_event);
294 295 296
    }
}

297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
static void
keymap_changed (MetaBackend *backend)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

  if (priv->keymap)
    {
      xkb_keymap_unref (priv->keymap);
      priv->keymap = NULL;
    }

  g_signal_emit_by_name (backend, "keymap-changed", 0);
}

312 313 314 315 316 317 318 319 320 321
static gboolean
meta_backend_x11_handle_host_xevent (MetaBackendX11 *backend_x11,
                                     XEvent         *event)
{
  MetaBackendX11Class *backend_x11_class =
    META_BACKEND_X11_GET_CLASS (backend_x11);

  return backend_x11_class->handle_host_xevent (backend_x11, event);
}

322 323
static void
handle_host_xevent (MetaBackend *backend,
324
                    XEvent      *event)
325 326 327
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
328
  gboolean bypass_clutter = FALSE;
329

330 331
  XGetEventData (priv->xdisplay, &event->xcookie);

332 333 334 335 336 337 338 339
  {
    MetaDisplay *display = meta_get_display ();

    if (display)
      {
        MetaCompositor *compositor = display->compositor;
        if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
          bypass_clutter = TRUE;
Hyungwon Hwang's avatar
Hyungwon Hwang committed
340

341
        if (meta_dnd_handle_xdnd_event (backend, compositor, priv->xdisplay, event))
Hyungwon Hwang's avatar
Hyungwon Hwang committed
342
          bypass_clutter = TRUE;
343 344
      }
  }
345

346 347
  bypass_clutter = (meta_backend_x11_handle_host_xevent (x11, event) ||
                    bypass_clutter);
348

349 350 351
  if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
    handle_alarm_notify (backend, (XSyncAlarmNotifyEvent *) event);

352 353
  if (event->type == priv->xkb_event_base)
    {
354
      XkbEvent *xkb_ev = (XkbEvent *) event;
355

356
      if (xkb_ev->any.device == META_VIRTUAL_CORE_KEYBOARD_ID)
357
        {
358
          switch (xkb_ev->any.xkb_type)
359 360 361
            {
            case XkbMapNotify:
              keymap_changed (backend);
362
              break;
363
            case XkbStateNotify:
364 365 366 367 368 369 370 371 372 373 374 375 376 377
              if (xkb_ev->state.changed & XkbGroupLockMask)
                {
                  int layout_group;
                  gboolean layout_group_changed;

                  layout_group = xkb_ev->state.locked_group;
                  layout_group_changed =
                    (int) priv->keymap_layout_group != layout_group;
                  priv->keymap_layout_group = layout_group;

                  if (layout_group_changed)
                    meta_backend_notify_keymap_layout_group_changed (backend,
                                                                     layout_group);
                }
378
              break;
379 380 381 382 383 384
            default:
              break;
            }
        }
    }

385
  if (!bypass_clutter)
386
    {
387
      handle_input_event (x11, event);
388 389
      clutter_x11_handle_event (event);
    }
390 391

  XFreeEventData (priv->xdisplay, &event->xcookie);
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
}

typedef struct {
  GSource base;
  GPollFD event_poll_fd;
  MetaBackend *backend;
} XEventSource;

static gboolean
x_event_source_prepare (GSource *source,
                        int     *timeout)
{
  XEventSource *x_source = (XEventSource *) source;
  MetaBackend *backend = x_source->backend;
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

  *timeout = -1;

  return XPending (priv->xdisplay);
}

static gboolean
x_event_source_check (GSource *source)
{
  XEventSource *x_source = (XEventSource *) source;
  MetaBackend *backend = x_source->backend;
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

  return XPending (priv->xdisplay);
}

static gboolean
x_event_source_dispatch (GSource     *source,
                         GSourceFunc  callback,
                         gpointer     user_data)
{
  XEventSource *x_source = (XEventSource *) source;
  MetaBackend *backend = x_source->backend;
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

  while (XPending (priv->xdisplay))
    {
437
      XEvent event;
438

439
      XNextEvent (priv->xdisplay, &event);
440

441
      handle_host_xevent (backend, &event);
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
    }

  return TRUE;
}

static GSourceFuncs x_event_funcs = {
  x_event_source_prepare,
  x_event_source_check,
  x_event_source_dispatch,
};

static GSource *
x_event_source_new (MetaBackend *backend)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
  GSource *source;
  XEventSource *x_source;

  source = g_source_new (&x_event_funcs, sizeof (XEventSource));
  x_source = (XEventSource *) source;
  x_source->backend = backend;
  x_source->event_poll_fd.fd = ConnectionNumber (priv->xdisplay);
  x_source->event_poll_fd.events = G_IO_IN;
  g_source_add_poll (source, &x_source->event_poll_fd);

  g_source_attach (source, NULL);
  return source;
}

472 473 474 475 476 477 478 479 480 481
static void
on_monitors_changed (MetaMonitorManager *manager,
                     MetaBackend        *backend)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

  priv->cached_current_logical_monitor = NULL;
}

482 483 484 485 486
static void
meta_backend_x11_post_init (MetaBackend *backend)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
487
  MetaMonitorManager *monitor_manager;
488
  int major, minor;
489
  gboolean has_xi = FALSE;
490 491 492

  priv->source = x_event_source_new (backend);

493 494
  if (!XSyncQueryExtension (priv->xdisplay, &priv->xsync_event_base, &priv->xsync_error_base) ||
      !XSyncInitialize (priv->xdisplay, &major, &minor))
495 496
    meta_fatal ("Could not initialize XSync");

497 498 499 500 501 502
  priv->counter = find_idletime_counter (priv);
  if (priv->counter == None)
    meta_fatal ("Could not initialize XSync counter");

  priv->user_active_alarm = xsync_user_active_alarm_set (priv);

503 504 505 506 507 508 509 510 511 512 513 514 515 516
  if (XQueryExtension (priv->xdisplay,
                       "XInputExtension",
                       &priv->xinput_opcode,
                       &priv->xinput_error_base,
                       &priv->xinput_event_base))
    {
      major = 2; minor = 3;
      if (XIQueryVersion (priv->xdisplay, &major, &minor) == Success)
        {
          int version = (major * 10) + minor;
          if (version >= 22)
            has_xi = TRUE;
        }
    }
517

518 519
  if (!has_xi)
    meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
520

521 522 523 524 525 526 527 528 529 530
  if (!xkb_x11_setup_xkb_extension (priv->xcb,
                                    XKB_X11_MIN_MAJOR_XKB_VERSION,
                                    XKB_X11_MIN_MINOR_XKB_VERSION,
                                    XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS,
                                    NULL, NULL,
                                    &priv->xkb_event_base,
                                    &priv->xkb_error_base))
    meta_fatal ("X server doesn't have the XKB extension, version %d.%d or newer\n",
                XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION);

531
  META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
532 533

  monitor_manager = meta_backend_get_monitor_manager (backend);
534
  g_signal_connect (monitor_manager, "monitors-changed-internal",
535
                    G_CALLBACK (on_monitors_changed), backend);
536 537
}

538 539 540 541 542 543
static ClutterBackend *
meta_backend_x11_create_clutter_backend (MetaBackend *backend)
{
  return g_object_new (META_TYPE_CLUTTER_BACKEND_X11, NULL);
}

544 545 546 547 548 549 550 551 552 553 554
static gboolean
meta_backend_x11_grab_device (MetaBackend *backend,
                              int          device_id,
                              uint32_t     timestamp)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
  unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
  XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
  int ret;

555 556 557
  if (timestamp != META_CURRENT_TIME &&
      XSERVER_TIME_IS_BEFORE (timestamp, priv->latest_evtime))
    timestamp = priv->latest_evtime;
558

559 560 561 562 563
  XISetMask (mask.mask, XI_ButtonPress);
  XISetMask (mask.mask, XI_ButtonRelease);
  XISetMask (mask.mask, XI_Enter);
  XISetMask (mask.mask, XI_Leave);
  XISetMask (mask.mask, XI_Motion);
564 565
  XISetMask (mask.mask, XI_KeyPress);
  XISetMask (mask.mask, XI_KeyRelease);
566 567

  ret = XIGrabDevice (priv->xdisplay, device_id,
568
                      meta_backend_x11_get_xwindow (x11),
569
                      timestamp,
570
                      None,
571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
                      XIGrabModeAsync, XIGrabModeAsync,
                      False, /* owner_events */
                      &mask);

  return (ret == Success);
}

static gboolean
meta_backend_x11_ungrab_device (MetaBackend *backend,
                                int          device_id,
                                uint32_t     timestamp)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
  int ret;

  ret = XIUngrabDevice (priv->xdisplay, device_id, timestamp);
588
  XFlush (priv->xdisplay);
589 590 591 592

  return (ret == Success);
}

593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
static void
meta_backend_x11_warp_pointer (MetaBackend *backend,
                               int          x,
                               int          y)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

  XIWarpPointer (priv->xdisplay,
                 META_VIRTUAL_CORE_POINTER_ID,
                 None,
                 meta_backend_x11_get_xwindow (x11),
                 0, 0, 0, 0,
                 x, y);
}

609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
static MetaLogicalMonitor *
meta_backend_x11_get_current_logical_monitor (MetaBackend *backend)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
  MetaCursorTracker *cursor_tracker;
  int x, y;
  MetaMonitorManager *monitor_manager;
  MetaLogicalMonitor *logical_monitor;

  if (priv->cached_current_logical_monitor)
    return priv->cached_current_logical_monitor;

  cursor_tracker = meta_backend_get_cursor_tracker (backend);
  meta_cursor_tracker_get_pointer (cursor_tracker, &x, &y, NULL);
  monitor_manager = meta_backend_get_monitor_manager (backend);
  logical_monitor =
    meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y);

628 629 630
  if (!logical_monitor && monitor_manager->logical_monitors)
    logical_monitor = monitor_manager->logical_monitors->data;

631 632 633 634
  priv->cached_current_logical_monitor = logical_monitor;
  return priv->cached_current_logical_monitor;
}

635 636 637 638 639 640
static struct xkb_keymap *
meta_backend_x11_get_keymap (MetaBackend *backend)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

641 642 643 644 645 646 647
  if (priv->keymap == NULL)
    {
      struct xkb_context *context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
      priv->keymap = xkb_x11_keymap_new_from_device (context,
                                                     priv->xcb,
                                                     xkb_x11_get_core_keyboard_device_id (priv->xcb),
                                                     XKB_KEYMAP_COMPILE_NO_FLAGS);
648 649 650
      if (priv->keymap == NULL)
        priv->keymap = xkb_keymap_new_from_names (context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS);

651 652
      xkb_context_unref (context);
    }
653

654
  return priv->keymap;
655 656
}

657 658 659 660 661 662 663 664 665
static xkb_layout_index_t
meta_backend_x11_get_keymap_layout_group (MetaBackend *backend)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

  return priv->keymap_layout_group;
}

666 667 668 669 670 671 672
static void
meta_backend_x11_set_numlock (MetaBackend *backend,
                              gboolean     numlock_state)
{
  /* TODO: Currently handled by gnome-settings-deamon */
}

673 674 675 676 677 678 679 680
void
meta_backend_x11_handle_event (MetaBackendX11 *x11,
                               XEvent      *xevent)
{
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

  priv->cached_current_logical_monitor = NULL;
}
681

682 683 684 685 686 687 688 689
uint8_t
meta_backend_x11_get_xkb_event_base (MetaBackendX11 *x11)
{
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

  return priv->xkb_event_base;
}

690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
static void
init_xkb_state (MetaBackendX11 *x11)
{
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
  struct xkb_keymap *keymap;
  int32_t device_id;
  struct xkb_state *state;

  keymap = meta_backend_get_keymap (META_BACKEND (x11));

  device_id = xkb_x11_get_core_keyboard_device_id (priv->xcb);
  state = xkb_x11_state_new_from_device (keymap, priv->xcb, device_id);

  priv->keymap_layout_group =
    xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_LOCKED);

  xkb_state_unref (state);
}

709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735
static gboolean
meta_backend_x11_initable_init (GInitable    *initable,
                                GCancellable *cancellable,
                                GError      **error)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (initable);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
  Display *xdisplay;
  const char *xdisplay_name;

  xdisplay_name = g_getenv ("DISPLAY");
  if (!xdisplay_name)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Unable to open display, DISPLAY not set");
      return FALSE;
    }

  xdisplay = XOpenDisplay (xdisplay_name);
  if (!xdisplay)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Unable to open display '%s'", xdisplay_name);
      return FALSE;
    }

  priv->xdisplay = xdisplay;
736
  priv->xcb = XGetXCBConnection (priv->xdisplay);
737 738
  clutter_x11_set_display (xdisplay);

739 740
  init_xkb_state (x11);

741 742 743 744 745 746 747 748 749 750 751
  return initable_parent_iface->init (initable, cancellable, error);
}

static void
initable_iface_init (GInitableIface *initable_iface)
{
  initable_parent_iface = g_type_interface_peek_parent (initable_iface);

  initable_iface->init = meta_backend_x11_initable_init;
}

752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
static void
meta_backend_x11_finalize (GObject *object)
{
  MetaBackendX11 *x11 = META_BACKEND_X11 (object);
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

  if (priv->user_active_alarm != None)
    {
      XSyncDestroyAlarm (priv->xdisplay, priv->user_active_alarm);
      priv->user_active_alarm = None;
    }

  G_OBJECT_CLASS (meta_backend_x11_parent_class)->finalize (object);
}

767 768 769 770
static void
meta_backend_x11_class_init (MetaBackendX11Class *klass)
{
  MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
771
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
772

773
  object_class->finalize = meta_backend_x11_finalize;
774
  backend_class->create_clutter_backend = meta_backend_x11_create_clutter_backend;
775
  backend_class->post_init = meta_backend_x11_post_init;
776 777
  backend_class->grab_device = meta_backend_x11_grab_device;
  backend_class->ungrab_device = meta_backend_x11_ungrab_device;
778
  backend_class->warp_pointer = meta_backend_x11_warp_pointer;
779
  backend_class->get_current_logical_monitor = meta_backend_x11_get_current_logical_monitor;
780
  backend_class->get_keymap = meta_backend_x11_get_keymap;
781
  backend_class->get_keymap_layout_group = meta_backend_x11_get_keymap_layout_group;
782
  backend_class->set_numlock = meta_backend_x11_set_numlock;
783 784 785 786 787
}

static void
meta_backend_x11_init (MetaBackendX11 *x11)
{
788 789 790 791 792 793
  /* XInitThreads() is needed to use the "threaded swap wait" functionality
   * in Cogl - see meta_renderer_x11_create_cogl_renderer(). We call it here
   * to hopefully call it before any other use of XLib.
   */
  XInitThreads();

794 795
  /* We do X11 event retrieval ourselves */
  clutter_x11_disable_event_retrieval ();
796
}
797 798 799 800 801 802 803 804 805

Display *
meta_backend_x11_get_xdisplay (MetaBackendX11 *x11)
{
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

  return priv->xdisplay;
}

806 807 808
Window
meta_backend_x11_get_xwindow (MetaBackendX11 *x11)
{
809 810
  ClutterActor *stage = meta_backend_get_stage (META_BACKEND (x11));
  return clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
811
}
812 813 814 815 816 817 818 819 820 821

void
meta_backend_x11_reload_cursor (MetaBackendX11 *x11)
{
  MetaBackend *backend = META_BACKEND (x11);
  MetaCursorRenderer *cursor_renderer =
    meta_backend_get_cursor_renderer (backend);

  meta_cursor_renderer_force_update (cursor_renderer);
}