Example #1
0
/**
 * meta_compositor_process_event: (skip)
 * @compositor:
 * @event:
 * @window:
 *
 */
gboolean
meta_compositor_process_event (MetaCompositor *compositor,
                               XEvent         *event,
                               MetaWindow     *window)
{
  if (!meta_is_wayland_compositor () &&
      event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
    {
      /* Core code doesn't handle damage events, so we need to extract the MetaWindow
       * ourselves
       */
      if (window == NULL)
        {
          Window xwin = ((XDamageNotifyEvent *) event)->drawable;
          window = meta_display_lookup_x_window (compositor->display, xwin);
        }

      if (window)
        process_damage (compositor, (XDamageNotifyEvent *) event, window);
    }

  if (compositor->have_x11_sync_object)
    meta_sync_ring_handle_event (event);

  /* Clutter needs to know about MapNotify events otherwise it will
     think the stage is invisible */
  if (!meta_is_wayland_compositor () && event->type == MapNotify)
    clutter_x11_handle_event (event);

  /* The above handling is basically just "observing" the events, so we return
   * FALSE to indicate that the event should not be filtered out; if we have
   * GTK+ windows in the same process, GTK+ needs the ConfigureNotify event, for example.
   */
  return FALSE;
}
Example #2
0
/**
 * meta_cursor_tracker_get_hot:
 * @tracker:
 * @x: (out):
 * @y: (out):
 *
 */
void
meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
                             int               *x,
                             int               *y)
{
  MetaCursorSprite *cursor_sprite;

  g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));

  if (meta_is_wayland_compositor ())
    {
      cursor_sprite = tracker->displayed_cursor;
    }
  else
    {
      ensure_xfixes_cursor (tracker);
      cursor_sprite = tracker->xfixes_cursor;
    }

  if (cursor_sprite)
    meta_cursor_sprite_get_hotspot (cursor_sprite, x, y);
  else
    {
      if (x)
        *x = 0;
      if (y)
        *y = 0;
    }
}
Example #3
0
void
meta_set_stage_input_region (MetaScreen   *screen,
                             XserverRegion region)
{
  /* As a wayland compositor we can simply ignore all this trickery
   * for setting an input region on the stage for capturing events in
   * clutter since all input comes to us first and we get to choose
   * who else sees them.
   */
  if (!meta_is_wayland_compositor ())
    {
      MetaDisplay *display = screen->display;
      MetaCompositor *compositor = display->compositor;
      Display *xdpy = meta_display_get_xdisplay (display);
      Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));

      XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);

      /* It's generally a good heuristic that when a crossing event is generated because
       * we reshape the overlay, we don't want it to affect focus-follows-mouse focus -
       * it's not the user doing something, it's the environment changing under the user.
       */
      meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy));
      XFixesSetWindowShapeRegion (xdpy, compositor->output, ShapeInput, 0, 0, region);
    }
}
Example #4
0
void
meta_end_modal_for_plugin (MetaCompositor *compositor,
                           MetaPlugin     *plugin,
                           guint32         timestamp)
{
  MetaDisplay *display = compositor->display;
  MetaBackend *backend = meta_get_backend ();

  g_return_if_fail (is_modal (display));

  g_signal_emit_by_name (display, "grab-op-end",
                         meta_plugin_get_screen (plugin),
                         display->grab_window, display->grab_op);

  display->grab_op = META_GRAB_OP_NONE;
  display->event_route = META_EVENT_ROUTE_NORMAL;
  display->grab_window = NULL;
  display->grab_have_pointer = FALSE;
  display->grab_have_keyboard = FALSE;

  meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
  meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);

  if (meta_is_wayland_compositor ())
    meta_display_sync_wayland_input_focus (display);
}
Example #5
0
static void
meta_barrier_constructed (GObject *object)
{
  MetaBarrier *barrier = META_BARRIER (object);
  MetaBarrierPrivate *priv = barrier->priv;

  g_return_if_fail (priv->border.line.a.x == priv->border.line.b.x ||
                    priv->border.line.a.y == priv->border.line.b.y);

#if defined(HAVE_NATIVE_BACKEND)
  if (META_IS_BACKEND_NATIVE (meta_get_backend ()))
    priv->impl = meta_barrier_impl_native_new (barrier);
#endif
  if (META_IS_BACKEND_X11 (meta_get_backend ()) &&
      !meta_is_wayland_compositor ())
    priv->impl = meta_barrier_impl_x11_new (barrier);

  if (priv->impl == NULL)
    g_warning ("Created a non-working barrier");

  /* Take a ref that we'll release in destroy() so that the object stays
   * alive while active. */
  g_object_ref (barrier);

  G_OBJECT_CLASS (meta_barrier_parent_class)->constructed (object);
}
Example #6
0
/**
 * meta_cursor_tracker_get_hot:
 * @tracker:
 * @x: (out):
 * @y: (out):
 *
 */
void
meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
                             int               *x,
                             int               *y)
{
  MetaCursorReference *cursor;

  g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));

  if (meta_is_wayland_compositor ())
    {
      cursor = tracker->displayed_cursor;
    }
  else
    {
      ensure_xfixes_cursor (tracker);
      cursor = tracker->xfixes_cursor;
    }

  if (cursor)
    meta_cursor_reference_get_cogl_texture (cursor, x, y);
  else
    {
      if (x)
        *x = 0;
      if (y)
        *y = 0;
    }
}
Example #7
0
void
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
                                     int                new_x,
                                     int                new_y)
{
  g_assert (meta_is_wayland_compositor ());

  meta_cursor_renderer_set_position (tracker->renderer, new_x, new_y);
}
Example #8
0
static MetaMonitorManager *
meta_backend_x11_create_monitor_manager (MetaBackend *backend)
{
  /* If we're a Wayland compositor using the X11 backend,
   * we're a nested configuration, so return the dummy
   * monitor setup. */
  if (meta_is_wayland_compositor ())
    return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);

  return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
}
Example #9
0
static void
meta_finalize (void)
{
  MetaDisplay *display = meta_get_display ();

  if (display)
    meta_display_close (display,
                        CurrentTime); /* I doubt correct timestamps matter here */

  if (meta_is_wayland_compositor ())
    meta_wayland_finalize ();
}
Example #10
0
void
meta_stage_set_cursor (MetaStage     *stage,
                       CoglTexture   *texture,
                       MetaRectangle *rect)
{
  MetaStagePrivate *priv = meta_stage_get_instance_private (stage);

  g_assert (meta_is_wayland_compositor () || texture == NULL);

  meta_overlay_set (&priv->cursor_overlay, texture, rect);
  queue_redraw_for_overlay (stage, &priv->cursor_overlay);
}
Example #11
0
void
meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
                                   int x, int y)
{
  MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);

  g_assert (meta_is_wayland_compositor ());

  priv->current_x = x;
  priv->current_y = y;

  update_cursor (renderer);
}
Example #12
0
static void
after_stage_paint (ClutterStage *stage,
                   gpointer      data)
{
  MetaCompositor *compositor = data;
  GList *l;

  for (l = compositor->windows; l; l = l->next)
    meta_window_actor_post_paint (l->data);

  if (meta_is_wayland_compositor ())
    meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ());
}
Example #13
0
static void
meta_backend_x11_init (MetaBackendX11 *x11)
{
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);

  clutter_x11_request_reset_on_video_memory_purge ();

  /* We do X11 event retrieval ourselves */
  clutter_x11_disable_event_retrieval ();

  if (meta_is_wayland_compositor ())
    priv->mode = META_BACKEND_X11_MODE_NESTED;
  else
    priv->mode = META_BACKEND_X11_MODE_COMPOSITOR;
}
Example #14
0
void
meta_compositor_unmanage (MetaCompositor *compositor)
{
  if (!meta_is_wayland_compositor ())
    {
      MetaDisplay *display = compositor->display;
      Display *xdisplay = meta_display_get_xdisplay (display);
      Window xroot = display->screen->xroot;

      /* This is the most important part of cleanup - we have to do this
       * before giving up the window manager selection or the next
       * window manager won't be able to redirect subwindows */
      XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
    }
}
Example #15
0
void
meta_cursor_tracker_get_pointer (MetaCursorTracker   *tracker,
                                 int                 *x,
                                 int                 *y,
                                 ClutterModifierType *mods)
{
  /* We can't use the clutter interface when not running as a wayland compositor,
     because we need to query the server, rather than using the last cached value.
     OTOH, on wayland we can't use GDK, because that only sees the events
     we forward to xwayland.
  */
  if (meta_is_wayland_compositor ())
    get_pointer_position_clutter (x, y, (int*)mods);
  else
    get_pointer_position_gdk (x, y, (int*)mods);
}
Example #16
0
static TestClient *
test_client_new (const char          *id,
                 MetaWindowClientType type,
                 GError             **error)
{
  TestClient *client = g_new0 (TestClient, 1);
  GSubprocessLauncher *launcher;
  GSubprocess *subprocess;

  launcher =  g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE);

  g_assert (meta_is_wayland_compositor ());
  MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();

  g_subprocess_launcher_setenv (launcher,
                                "WAYLAND_DISPLAY", meta_wayland_get_wayland_display_name (compositor),
                                TRUE);
  g_subprocess_launcher_setenv (launcher,
                                "DISPLAY", meta_wayland_get_xwayland_display_name (compositor),
                                TRUE);

  subprocess = g_subprocess_launcher_spawn (launcher,
                                            error,
                                            test_client_path,
                                            "--client-id",
                                            id,
                                            type == META_WINDOW_CLIENT_TYPE_WAYLAND ? "--wayland" : NULL,
                                            NULL);
  g_object_unref (launcher);

  if (!subprocess)
    return NULL;

  client->type = type;
  client->id = g_strdup (id);
  client->cancellable = g_cancellable_new ();
  client->subprocess = subprocess;
  client->in = g_data_output_stream_new (g_subprocess_get_stdin_pipe (subprocess));
  client->out = g_data_input_stream_new (g_subprocess_get_stdout_pipe (subprocess));
  client->loop = g_main_loop_new (NULL, FALSE);

  if (client->type == META_WINDOW_CLIENT_TYPE_X11)
    client->waiter = async_waiter_new ();

  return client;
}
Example #17
0
static void
meta_backend_x11_update_screen_size (MetaBackend *backend,
                                     int width, int height)
{
  if (meta_is_wayland_compositor ())
    {
      /* For a nested wayland session, we want to go through Clutter to update the
       * toplevel window size, rather than doing it directly.
       */
      META_BACKEND_CLASS (meta_backend_x11_parent_class)->update_screen_size (backend, width, height);
    }
  else
    {
      MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
      MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
      Window xwin = meta_backend_x11_get_xwindow (x11);
      XResizeWindow (priv->xdisplay, xwin, width, height);
    }
}
Example #18
0
gboolean
meta_begin_modal_for_plugin (MetaCompositor   *compositor,
                             MetaPlugin       *plugin,
                             MetaModalOptions  options,
                             guint32           timestamp)
{
  /* To some extent this duplicates code in meta_display_begin_grab_op(), but there
   * are significant differences in how we handle grabs that make it difficult to
   * merge the two.
   */
  MetaDisplay *display = compositor->display;

  if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE)
    return FALSE;

  /* XXX: why is this needed? */
  XIUngrabDevice (display->xdisplay,
                  META_VIRTUAL_CORE_POINTER_ID,
                  timestamp);
  XSync (display->xdisplay, False);

  if (!grab_devices (options, timestamp))
    return FALSE;

  display->grab_op = META_GRAB_OP_COMPOSITOR;
  display->event_route = META_EVENT_ROUTE_COMPOSITOR_GRAB;
  display->grab_window = NULL;
  display->grab_have_pointer = TRUE;
  display->grab_have_keyboard = TRUE;

  g_signal_emit_by_name (display, "grab-op-begin",
                         meta_plugin_get_screen (plugin),
                         display->grab_window, display->grab_op);

  if (meta_is_wayland_compositor ())
    {
      meta_display_sync_wayland_input_focus (display);
      meta_display_cancel_touch (display);
    }

  return TRUE;
}
Example #19
0
static void
meta_overlay_paint (MetaOverlay *overlay)
{
  if (!overlay->enabled)
    return;

  g_assert (meta_is_wayland_compositor ());

  cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
                                   overlay->pipeline,
                                   overlay->current_rect.x,
                                   overlay->current_rect.y,
                                   overlay->current_rect.x +
                                   overlay->current_rect.width,
                                   overlay->current_rect.y +
                                   overlay->current_rect.height);

  overlay->previous_rect = overlay->current_rect;
  overlay->previous_is_valid = TRUE;
}
Example #20
0
gboolean
meta_stage_is_focused (MetaScreen *screen)
{
  ClutterStage *stage;
  Window window;

  if (meta_is_wayland_compositor ())
    return TRUE;

  stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
  if (!stage)
    return FALSE;

  window = clutter_x11_get_stage_window (stage);

  if (window == None)
    return FALSE;

  return (screen->display->focus_xwindow == window);
}
Example #21
0
gboolean
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
                                   XEvent            *xevent)
{
  MetaDisplay *display = meta_get_display ();
  XFixesCursorNotifyEvent *notify_event;

  if (meta_is_wayland_compositor ())
    return FALSE;

  if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify)
    return FALSE;

  notify_event = (XFixesCursorNotifyEvent *)xevent;
  if (notify_event->subtype != XFixesDisplayCursorNotify)
    return FALSE;

  g_clear_pointer (&tracker->xfixes_cursor, meta_cursor_reference_unref);

  return TRUE;
}
Example #22
0
/**
 * meta_cursor_tracker_get_sprite:
 *
 * Returns: (transfer none):
 */
CoglTexture *
meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
{
  MetaCursorSprite *cursor_sprite;

  g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);

  if (meta_is_wayland_compositor ())
    {
      cursor_sprite = tracker->displayed_cursor;
    }
  else
    {
      ensure_xfixes_cursor (tracker);
      cursor_sprite = tracker->xfixes_cursor;
    }

  if (cursor_sprite)
    return meta_cursor_sprite_get_cogl_texture (cursor_sprite);
  else
    return NULL;
}
Example #23
0
gboolean
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
                                   XEvent            *xevent)
{
  MetaDisplay *display = meta_get_display ();
  XFixesCursorNotifyEvent *notify_event;

  if (meta_is_wayland_compositor ())
    return FALSE;

  if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify)
    return FALSE;

  notify_event = (XFixesCursorNotifyEvent *)xevent;
  if (notify_event->subtype != XFixesDisplayCursorNotify)
    return FALSE;

  g_clear_object (&tracker->xfixes_cursor);
  g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);

  return TRUE;
}
MetaSurfaceActor *
meta_surface_actor_x11_new (MetaWindow *window)
{
  MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL);
  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
  MetaDisplay *display = meta_window_get_display (window);

  g_assert (!meta_is_wayland_compositor ());

  priv->window = window;
  priv->display = display;

  create_damage (self);
  g_signal_connect_object (priv->window, "notify::decorated",
                           G_CALLBACK (window_decorated_notify), self, 0);

  priv->unredirected = FALSE;
  sync_unredirected (self);

  clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
  return META_SURFACE_ACTOR (self);
}
Example #25
0
static void
translate_device_event (MetaBackendX11 *x11,
                        XIDeviceEvent  *device_event)
{
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
  Window stage_window = meta_backend_x11_get_xwindow (x11);

  if (device_event->event != stage_window)
    {
      /* This codepath should only ever trigger as an X11 compositor,
       * and never under nested, as under nested all backend events
       * should be reported with respect to the stage window. */
      g_assert (!meta_is_wayland_compositor ());

      device_event->event = stage_window;

      /* As an X11 compositor, the stage window is always at 0,0, so
       * using root coordinates will give us correct stage coordinates
       * as well... */
      device_event->event_x = device_event->root_x;
      device_event->event_y = device_event->root_y;
    }

  if (!device_event->send_event && device_event->time != CurrentTime)
    {
      if (device_event->time < priv->latest_evtime)
        {
          /* 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;
    }
}
Example #26
0
void
meta_compositor_sync_screen_size (MetaCompositor  *compositor,
				  guint		   width,
				  guint		   height)
{
  MetaDisplay *display = compositor->display;

  if (meta_is_wayland_compositor ())
    {
      /* FIXME: when we support a sliced stage, this is the place to do it
         But! This is not the place to apply KMS config, here we only
         notify Clutter/Cogl/GL that the framebuffer sizes changed.

         And because for now clutter does not do sliced, we use one
         framebuffer the size of the whole screen, and when running on
         bare metal MetaMonitorManager will do the necessary tricks to
         show the right portions on the right screens.
      */

      clutter_actor_set_size (compositor->stage, width, height);
    }
  else
    {
      Display        *xdisplay;
      Window          xwin;

      xdisplay = meta_display_get_xdisplay (display);
      xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));

      XResizeWindow (xdisplay, xwin, width, height);
    }

  meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
                meta_screen_get_screen_number (display->screen),
                width, height);
}
Example #27
0
/**
 * meta_init: (skip)
 *
 * Initialize mutter. Call this after meta_get_option_context() and
 * meta_plugin_manager_set_plugin_type(), and before meta_run().
 */
void
meta_init (void)
{
  struct sigaction act;
  sigset_t empty_mask;
  ClutterSettings *clutter_settings;

  sigemptyset (&empty_mask);
  act.sa_handler = SIG_IGN;
  act.sa_mask    = empty_mask;
  act.sa_flags   = 0;
  if (sigaction (SIGPIPE,  &act, NULL) < 0)
    g_printerr ("Failed to register SIGPIPE handler: %s\n",
                g_strerror (errno));
#ifdef SIGXFSZ
  if (sigaction (SIGXFSZ,  &act, NULL) < 0)
    g_printerr ("Failed to register SIGXFSZ handler: %s\n",
                g_strerror (errno));
#endif

  g_unix_signal_add (SIGTERM, on_sigterm, NULL);

  if (g_getenv ("MUTTER_VERBOSE"))
    meta_set_verbose (TRUE);
  if (g_getenv ("MUTTER_DEBUG"))
    meta_set_debugging (TRUE);

#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
  if (opt_display_server)
    clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
#endif

  meta_set_is_wayland_compositor (opt_wayland);

  if (g_get_home_dir ())
    if (chdir (g_get_home_dir ()) < 0)
      meta_warning ("Could not change to home directory %s.\n",
                    g_get_home_dir ());

  meta_print_self_identity ();

#ifdef HAVE_INTROSPECTION
  g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
#endif

  if (meta_is_wayland_compositor ())
    {
      /* NB: When running as a hybrid wayland compositor we run our own headless X
       * server so the user can't control the X display to connect too. */
      meta_wayland_init ();
    }
  else
    meta_select_display (opt_display_name);

  meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL));

  if (opt_replace_wm)
    meta_set_replace_current_wm (TRUE);

  if (opt_save_file && opt_client_id)
    meta_fatal ("Can't specify both SM save file and SM client id\n");

  meta_main_loop = g_main_loop_new (NULL, FALSE);

  meta_ui_init ();

  /* If we are running with wayland then we don't wait until we have
   * an X connection before initializing clutter we instead initialize
   * it earlier since we need to initialize the GL driver so the driver
   * can register any needed wayland extensions. */
  if (!meta_is_wayland_compositor ())
    {
      /*
       * Clutter can only be initialized after the UI.
       */
      meta_clutter_init ();
    }

  meta_restart_init ();

  /*
   * XXX: We cannot handle high dpi scaling yet, so fix the scale to 1
   * for now.
   */
  clutter_settings = clutter_settings_get_default ();
  g_object_set (clutter_settings, "window-scaling-factor", 1, NULL);
}
Example #28
0
static gboolean
meta_display_handle_event (MetaDisplay        *display,
                           const ClutterEvent *event)
{
  MetaWindow *window;
  gboolean bypass_clutter = FALSE;
  G_GNUC_UNUSED gboolean bypass_wayland = FALSE;
  MetaGestureTracker *tracker;
  ClutterEventSequence *sequence;
  ClutterInputDevice *source;

  sequence = clutter_event_get_event_sequence (event);

  /* Set the pointer emulating sequence on touch begin, if eligible */
  if (event->type == CLUTTER_TOUCH_BEGIN)
    {
      if (sequence_is_pointer_emulated (display, event))
        {
          /* This is the new pointer emulating sequence */
          display->pointer_emulating_sequence = sequence;
        }
      else if (display->pointer_emulating_sequence == sequence)
        {
          /* This sequence was "pointer emulating" in a prior incarnation,
           * but now it isn't. We unset the pointer emulating sequence at
           * this point so the current sequence is not mistaken as pointer
           * emulating, while we've ensured that it's been deemed
           * "pointer emulating" throughout all of the event processing
           * of the previous incarnation.
           */
          display->pointer_emulating_sequence = NULL;
        }
    }

#ifdef HAVE_WAYLAND
  MetaWaylandCompositor *compositor = NULL;
  if (meta_is_wayland_compositor ())
    {
      compositor = meta_wayland_compositor_get_default ();
      meta_wayland_compositor_update (compositor, event);
    }
#endif

  if (!display->current_pad_osd &&
      (event->type == CLUTTER_PAD_BUTTON_PRESS ||
       event->type == CLUTTER_PAD_BUTTON_RELEASE))
    {
      MetaBackend *backend = meta_get_backend ();

      if (meta_input_settings_handle_pad_button (meta_backend_get_input_settings (backend),
                                                 clutter_event_get_source_device (event),
                                                 event->type == CLUTTER_PAD_BUTTON_PRESS,
                                                 event->pad_button.button))
        {
          bypass_wayland = bypass_clutter = TRUE;
          goto out;
        }
    }

  source = clutter_event_get_source_device (event);

  if (source)
    {
      meta_backend_update_last_device (meta_get_backend (),
                                       clutter_input_device_get_device_id (source));
    }

#ifdef HAVE_WAYLAND
  if (meta_is_wayland_compositor () && event->type == CLUTTER_MOTION)
    {
      MetaWaylandCompositor *compositor;

      compositor = meta_wayland_compositor_get_default ();

      if (meta_wayland_tablet_manager_consumes_event (compositor->tablet_manager, event))
        {
          meta_wayland_tablet_manager_update_cursor_position (compositor->tablet_manager, event);
        }
      else
        {
          MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
          meta_cursor_tracker_update_position (tracker, event->motion.x, event->motion.y);
        }

      display->monitor_cache_invalidated = TRUE;
    }
#endif

  handle_idletime_for_event (event);

  window = get_window_for_event (display, event);

  display->current_time = event->any.time;

  if (window && !window->override_redirect &&
      (event->type == CLUTTER_KEY_PRESS ||
       event->type == CLUTTER_BUTTON_PRESS ||
       event->type == CLUTTER_TOUCH_BEGIN))
    {
      if (CurrentTime == display->current_time)
        {
          /* We can't use missing (i.e. invalid) timestamps to set user time,
           * nor do we want to use them to sanity check other timestamps.
           * See bug 313490 for more details.
           */
          meta_warning ("Event has no timestamp! You may be using a broken "
                        "program such as xse.  Please ask the authors of that "
                        "program to fix it.\n");
        }
      else
        {
          meta_window_set_user_time (window, display->current_time);
          meta_display_sanity_check_timestamps (display, display->current_time);
        }
    }

  tracker = meta_display_get_gesture_tracker (display);

  if (meta_gesture_tracker_handle_event (tracker, event))
    {
      bypass_wayland = bypass_clutter = TRUE;
      goto out;
    }

  if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
    {
      if (meta_window_handle_mouse_grab_op_event (window, event))
        {
          bypass_clutter = TRUE;
          bypass_wayland = TRUE;
          goto out;
        }
    }

  /* For key events, it's important to enforce single-handling, or
   * we can get into a confused state. So if a keybinding is
   * handled (because it's one of our hot-keys, or because we are
   * in a keyboard-grabbed mode like moving a window, we don't
   * want to pass the key event to the compositor or Wayland at all.
   */
  if (meta_keybindings_process_event (display, window, event))
    {
      bypass_clutter = TRUE;
      bypass_wayland = TRUE;
      goto out;
    }

  /* Do not pass keyboard events to Wayland if key focus is not on the
   * stage in normal mode (e.g. during keynav in the panel)
   */
  if (display->event_route == META_EVENT_ROUTE_NORMAL)
    {
      if (IS_KEY_EVENT (event) && !stage_has_key_focus ())
        {
          bypass_wayland = TRUE;
          goto out;
        }
    }

  if (display->current_pad_osd)
    {
      bypass_wayland = TRUE;
      goto out;
    }

  if (window)
    {
      /* Events that are likely to trigger compositor gestures should
       * be known to clutter so they can propagate along the hierarchy.
       * Gesture-wise, there's two groups of events we should be getting
       * here:
       * - CLUTTER_TOUCH_* with a touch sequence that's not yet accepted
       *   by the gesture tracker, these might trigger gesture actions
       *   into recognition. Already accepted touch sequences are handled
       *   directly by meta_gesture_tracker_handle_event().
       * - CLUTTER_TOUCHPAD_* events over windows. These can likewise
       *   trigger ::captured-event handlers along the way.
       */
      bypass_clutter = !IS_GESTURE_EVENT (event);

      meta_window_handle_ungrabbed_event (window, event);

      /* This might start a grab op. If it does, then filter out the
       * event, and if it doesn't, replay the event to release our
       * own sync grab. */

      if (display->event_route == META_EVENT_ROUTE_WINDOW_OP ||
          display->event_route == META_EVENT_ROUTE_FRAME_BUTTON)
        {
          bypass_clutter = TRUE;
          bypass_wayland = TRUE;
        }
      else
        {
          /* Only replay button press events, since that's where we
           * have the synchronous grab. */
          if (event->type == CLUTTER_BUTTON_PRESS)
            {
              MetaBackend *backend = meta_get_backend ();
              if (META_IS_BACKEND_X11 (backend))
                {
                  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
                  meta_verbose ("Allowing events time %u\n",
                                (unsigned int)event->button.time);
                  XIAllowEvents (xdisplay, clutter_event_get_device_id (event),
                                 XIReplayDevice, event->button.time);
                }
            }
        }

      goto out;
    }

 out:
  /* If the compositor has a grab, don't pass that through to Wayland */
  if (display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB)
    bypass_wayland = TRUE;

  /* If a Wayland client has a grab, don't pass that through to Clutter */
  if (display->event_route == META_EVENT_ROUTE_WAYLAND_POPUP)
    bypass_clutter = TRUE;

#ifdef HAVE_WAYLAND
  if (compositor && !bypass_wayland)
    {
      if (meta_wayland_compositor_handle_event (compositor, event))
        bypass_clutter = TRUE;
    }
#endif

  display->current_time = CurrentTime;
  return bypass_clutter;
}
Example #29
0
static gboolean
meta_display_handle_event (MetaDisplay        *display,
                           const ClutterEvent *event)
{
  MetaWindow *window;
  gboolean bypass_clutter = FALSE;
  G_GNUC_UNUSED gboolean bypass_wayland = FALSE;
  MetaGestureTracker *tracker;
  ClutterEventSequence *sequence;

  sequence = clutter_event_get_event_sequence (event);

  /* Set the pointer emulating sequence on touch begin, if eligible */
  if (event->type == CLUTTER_TOUCH_BEGIN &&
      !display->pointer_emulating_sequence &&
      sequence_is_pointer_emulated (display, event))
    display->pointer_emulating_sequence = sequence;

#ifdef HAVE_WAYLAND
  MetaWaylandCompositor *compositor = NULL;
  if (meta_is_wayland_compositor ())
    {
      compositor = meta_wayland_compositor_get_default ();
      meta_wayland_compositor_update (compositor, event);
    }
#endif

  if (meta_is_wayland_compositor () && event->type == CLUTTER_MOTION)
    {
      MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
      meta_cursor_tracker_update_position (tracker, event->motion.x, event->motion.y);
    }

  handle_idletime_for_event (event);

  window = get_window_for_event (display, event);

  display->current_time = event->any.time;

  if (window && !window->override_redirect &&
      (event->type == CLUTTER_KEY_PRESS ||
       event->type == CLUTTER_BUTTON_PRESS ||
       event->type == CLUTTER_TOUCH_BEGIN))
    {
      if (CurrentTime == display->current_time)
        {
          /* We can't use missing (i.e. invalid) timestamps to set user time,
           * nor do we want to use them to sanity check other timestamps.
           * See bug 313490 for more details.
           */
          meta_warning ("Event has no timestamp! You may be using a broken "
                        "program such as xse.  Please ask the authors of that "
                        "program to fix it.\n");
        }
      else
        {
          meta_window_set_user_time (window, display->current_time);
          meta_display_sanity_check_timestamps (display, display->current_time);
        }
    }

  tracker = meta_display_get_gesture_tracker (display);

  if (meta_gesture_tracker_handle_event (tracker, event))
    {
      bypass_wayland = bypass_clutter = TRUE;
      goto out;
    }

  if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
    {
      if (meta_window_handle_mouse_grab_op_event (window, event))
        {
          bypass_clutter = TRUE;
          bypass_wayland = TRUE;
          goto out;
        }
    }

  /* For key events, it's important to enforce single-handling, or
   * we can get into a confused state. So if a keybinding is
   * handled (because it's one of our hot-keys, or because we are
   * in a keyboard-grabbed mode like moving a window, we don't
   * want to pass the key event to the compositor or Wayland at all.
   */
  if (meta_keybindings_process_event (display, window, event))
    {
      bypass_clutter = TRUE;
      bypass_wayland = TRUE;
      goto out;
    }

  if (window)
    {
      if (!clutter_event_get_event_sequence (event))
        {
          /* Swallow all non-touch events on windows that come our way.
           * Touch events that reach here aren't yet in an accepted state,
           * so Clutter must see them to maybe trigger gestures into
           * recognition.
           */
          bypass_clutter = TRUE;
        }

      meta_window_handle_ungrabbed_event (window, event);

      /* This might start a grab op. If it does, then filter out the
       * event, and if it doesn't, replay the event to release our
       * own sync grab. */

      if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
        {
          bypass_clutter = TRUE;
          bypass_wayland = TRUE;
        }
      else
        {
          /* Only replay button press events, since that's where we
           * have the synchronous grab. */
          if (event->type == CLUTTER_BUTTON_PRESS)
            {
              MetaBackend *backend = meta_get_backend ();
              if (META_IS_BACKEND_X11 (backend))
                {
                  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
                  meta_verbose ("Allowing events time %u\n",
                                (unsigned int)event->button.time);
                  XIAllowEvents (xdisplay, clutter_event_get_device_id (event),
                                 XIReplayDevice, event->button.time);
                }
            }
        }

      goto out;
    }

 out:
  /* If the compositor has a grab, don't pass that through to Wayland */
  if (display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB)
    bypass_wayland = TRUE;

  /* If a Wayland client has a grab, don't pass that through to Clutter */
  if (display->event_route == META_EVENT_ROUTE_WAYLAND_POPUP)
    bypass_clutter = TRUE;

#ifdef HAVE_WAYLAND
  if (compositor && !bypass_wayland)
    {
      if (meta_wayland_compositor_handle_event (compositor, event))
        bypass_clutter = TRUE;
    }
#endif

  /* Unset the pointer emulating sequence after its end event is processed */
  if (event->type == CLUTTER_TOUCH_END &&
      display->pointer_emulating_sequence == sequence)
    display->pointer_emulating_sequence = NULL;

  display->current_time = CurrentTime;
  return bypass_clutter;
}
Example #30
0
/**
 * meta_init: (skip)
 *
 * Initialize mutter. Call this after meta_get_option_context() and
 * meta_plugin_manager_set_plugin_type(), and before meta_run().
 */
void
meta_init (void)
{
  struct sigaction act;
  sigset_t empty_mask;

  sigemptyset (&empty_mask);
  act.sa_handler = SIG_IGN;
  act.sa_mask    = empty_mask;
  act.sa_flags   = 0;
  if (sigaction (SIGPIPE,  &act, NULL) < 0)
    g_printerr ("Failed to register SIGPIPE handler: %s\n",
                g_strerror (errno));
#ifdef SIGXFSZ
  if (sigaction (SIGXFSZ,  &act, NULL) < 0)
    g_printerr ("Failed to register SIGXFSZ handler: %s\n",
                g_strerror (errno));
#endif

  g_unix_signal_add (SIGTERM, on_sigterm, NULL);

  if (g_getenv ("MUTTER_VERBOSE"))
    meta_set_verbose (TRUE);
  if (g_getenv ("MUTTER_DEBUG"))
    meta_set_debugging (TRUE);

#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
  if (opt_display_server)
    clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
  else
#endif
    clutter_set_windowing_backend (CLUTTER_WINDOWING_X11);

#ifdef HAVE_WAYLAND
  meta_set_is_wayland_compositor (opt_wayland);
#endif

  if (g_get_home_dir ())
    if (chdir (g_get_home_dir ()) < 0)
      meta_warning ("Could not change to home directory %s.\n",
                    g_get_home_dir ());

  meta_print_self_identity ();

#ifdef HAVE_INTROSPECTION
  g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
#endif

#ifdef HAVE_WAYLAND
  if (meta_is_wayland_compositor ())
    meta_wayland_pre_clutter_init ();
#endif

  /* NB: When running as a hybrid wayland compositor we run our own headless X
   * server so the user can't control the X display to connect too. */
  if (!meta_is_wayland_compositor ())
    meta_select_display (opt_display_name);

  meta_clutter_init ();

#ifdef HAVE_WAYLAND
  /* Bring up Wayland. This also launches Xwayland and sets DISPLAY as well... */
  if (meta_is_wayland_compositor ())
    meta_wayland_init ();
#endif

  meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL));

  if (opt_replace_wm)
    meta_set_replace_current_wm (TRUE);

  if (opt_save_file && opt_client_id)
    meta_fatal ("Can't specify both SM save file and SM client id\n");

  meta_main_loop = g_main_loop_new (NULL, FALSE);

  meta_ui_init ();

  meta_restart_init ();
}