Compare commits
	
		
			17 Commits
		
	
	
		
			wip/garnac
			...
			wip/waylan
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					ef00e3fc0b | ||
| 
						 | 
					e0df9eee28 | ||
| 
						 | 
					4492845528 | ||
| 
						 | 
					c334fd5288 | ||
| 
						 | 
					83f61daf95 | ||
| 
						 | 
					a474608954 | ||
| 
						 | 
					67457dc25c | ||
| 
						 | 
					9cff36bf30 | ||
| 
						 | 
					8708d038be | ||
| 
						 | 
					f59d92a246 | ||
| 
						 | 
					b7983201d7 | ||
| 
						 | 
					99a6a1f881 | ||
| 
						 | 
					3b3c6d08b6 | ||
| 
						 | 
					26f452d522 | ||
| 
						 | 
					76fccc069d | ||
| 
						 | 
					156365b609 | ||
| 
						 | 
					bd6536dec3 | 
@@ -2,7 +2,7 @@ AC_PREREQ(2.50)
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_major_version], [3])
 | 
			
		||||
m4_define([mutter_minor_version], [9])
 | 
			
		||||
m4_define([mutter_micro_version], [90])
 | 
			
		||||
m4_define([mutter_micro_version], [91])
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_version],
 | 
			
		||||
          [mutter_major_version.mutter_minor_version.mutter_micro_version])
 | 
			
		||||
 
 | 
			
		||||
@@ -134,6 +134,7 @@ libmutter_wayland_la_SOURCES =			\
 | 
			
		||||
	core/meta-xrandr-shared.h		\
 | 
			
		||||
	core/monitor.c				\
 | 
			
		||||
	core/monitor-config.c			\
 | 
			
		||||
	core/monitor-kms.c			\
 | 
			
		||||
	core/monitor-private.h			\
 | 
			
		||||
	core/monitor-xrandr.c			\
 | 
			
		||||
	core/mutter-Xatomtype.h			\
 | 
			
		||||
 
 | 
			
		||||
@@ -236,7 +236,7 @@ set_cogl_texture (MetaShapedTexture *stex,
 | 
			
		||||
  if (priv->texture)
 | 
			
		||||
    cogl_object_unref (priv->texture);
 | 
			
		||||
 | 
			
		||||
  priv->texture = cogl_tex;
 | 
			
		||||
  priv->texture = cogl_object_ref (cogl_tex);
 | 
			
		||||
 | 
			
		||||
  if (cogl_tex != NULL)
 | 
			
		||||
    {
 | 
			
		||||
@@ -870,26 +870,7 @@ meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture  *stex,
 | 
			
		||||
  g_return_if_fail (priv->wayland.surface->buffer_ref.buffer == buffer);
 | 
			
		||||
 | 
			
		||||
  if (buffer)
 | 
			
		||||
    {
 | 
			
		||||
      CoglContext *ctx =
 | 
			
		||||
        clutter_backend_get_cogl_context (clutter_get_default_backend ());
 | 
			
		||||
      CoglError *catch_error = NULL;
 | 
			
		||||
      CoglTexture *texture =
 | 
			
		||||
        COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx,
 | 
			
		||||
                                                               buffer->resource,
 | 
			
		||||
                                                               &catch_error));
 | 
			
		||||
      if (!texture)
 | 
			
		||||
        {
 | 
			
		||||
          cogl_error_free (catch_error);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          buffer->width = cogl_texture_get_width (texture);
 | 
			
		||||
          buffer->height = cogl_texture_get_height (texture);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      set_cogl_texture (stex, texture);
 | 
			
		||||
    }
 | 
			
		||||
    set_cogl_texture (stex, buffer->texture);
 | 
			
		||||
  else
 | 
			
		||||
    set_cogl_texture (stex, NULL);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,8 @@ typedef enum
 | 
			
		||||
  META_DO_GRAVITY_ADJUST    = 1 << 1,
 | 
			
		||||
  META_IS_USER_ACTION       = 1 << 2,
 | 
			
		||||
  META_IS_MOVE_ACTION       = 1 << 3,
 | 
			
		||||
  META_IS_RESIZE_ACTION     = 1 << 4
 | 
			
		||||
  META_IS_RESIZE_ACTION     = 1 << 4,
 | 
			
		||||
  META_IS_WAYLAND_RESIZE    = 1 << 5
 | 
			
		||||
} MetaMoveResizeFlags;
 | 
			
		||||
 | 
			
		||||
void meta_window_constrain (MetaWindow          *window,
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,7 @@
 | 
			
		||||
#include "keybindings-private.h"
 | 
			
		||||
#include <meta/prefs.h>
 | 
			
		||||
#include <meta/barrier.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_STARTUP_NOTIFICATION
 | 
			
		||||
#include <libsn/sn.h>
 | 
			
		||||
@@ -188,7 +189,7 @@ struct _MetaDisplay
 | 
			
		||||
  MetaWindow* autoraise_window;
 | 
			
		||||
 | 
			
		||||
  /* Alt+click button grabs */
 | 
			
		||||
  unsigned int window_grab_modifiers;
 | 
			
		||||
  ClutterModifierType window_grab_modifiers;
 | 
			
		||||
  
 | 
			
		||||
  /* current window operation */
 | 
			
		||||
  MetaGrabOp  grab_op;
 | 
			
		||||
@@ -476,8 +477,11 @@ gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
 | 
			
		||||
/* In above-tab-keycode.c */
 | 
			
		||||
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
 | 
			
		||||
 | 
			
		||||
gboolean meta_display_handle_event (MetaDisplay *display,
 | 
			
		||||
                                    XEvent      *event);
 | 
			
		||||
gboolean meta_display_handle_xevent (MetaDisplay *display,
 | 
			
		||||
                                     XEvent      *event);
 | 
			
		||||
 | 
			
		||||
gboolean meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
                                    const ClutterEvent *event);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_XI23
 | 
			
		||||
gboolean meta_display_process_barrier_event (MetaDisplay    *display,
 | 
			
		||||
 
 | 
			
		||||
@@ -177,8 +177,10 @@ static void   meta_spew_event           (MetaDisplay    *display,
 | 
			
		||||
                                         XEvent         *event);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static gboolean event_callback          (XEvent         *event,
 | 
			
		||||
static gboolean xevent_callback         (XEvent         *event,
 | 
			
		||||
                                         gpointer        data);
 | 
			
		||||
static gboolean event_callback          (const ClutterEvent *event,
 | 
			
		||||
                                         gpointer            data);
 | 
			
		||||
static Window event_get_modified_window (MetaDisplay    *display,
 | 
			
		||||
                                         XEvent         *event);
 | 
			
		||||
static guint32 event_get_time           (MetaDisplay    *display,
 | 
			
		||||
@@ -604,8 +606,9 @@ meta_display_open (void)
 | 
			
		||||
 | 
			
		||||
  /* Get events */
 | 
			
		||||
  meta_ui_add_event_func (the_display->xdisplay,
 | 
			
		||||
                          event_callback,
 | 
			
		||||
                          xevent_callback,
 | 
			
		||||
                          the_display);
 | 
			
		||||
  clutter_event_add_filter (event_callback, the_display);
 | 
			
		||||
  
 | 
			
		||||
  the_display->xids = g_hash_table_new (meta_unsigned_long_hash,
 | 
			
		||||
                                        meta_unsigned_long_equal);
 | 
			
		||||
@@ -1125,8 +1128,9 @@ meta_display_close (MetaDisplay *display,
 | 
			
		||||
  
 | 
			
		||||
  /* Stop caring about events */
 | 
			
		||||
  meta_ui_remove_event_func (display->xdisplay,
 | 
			
		||||
                             event_callback,
 | 
			
		||||
                             xevent_callback,
 | 
			
		||||
                             display);
 | 
			
		||||
  clutter_event_remove_filter (event_callback, display);
 | 
			
		||||
  
 | 
			
		||||
  /* Free all screens */
 | 
			
		||||
  tmp = display->screens;
 | 
			
		||||
@@ -2179,8 +2183,42 @@ handle_window_focus_event (MetaDisplay  *display,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
reload_xkb_rules (MetaScreen  *screen)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandCompositor *compositor;
 | 
			
		||||
  char **names;
 | 
			
		||||
  int n_names;
 | 
			
		||||
  gboolean ok;
 | 
			
		||||
  const char *rules, *model, *layout, *variant, *options;
 | 
			
		||||
 | 
			
		||||
  compositor = meta_wayland_compositor_get_default ();
 | 
			
		||||
 | 
			
		||||
  ok = meta_prop_get_latin1_list (screen->display, screen->xroot,
 | 
			
		||||
                                  screen->display->atom__XKB_RULES_NAMES,
 | 
			
		||||
                                  &names, &n_names);
 | 
			
		||||
  if (!ok)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (n_names != 5)
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  rules = names[0];
 | 
			
		||||
  model = names[1];
 | 
			
		||||
  layout = names[2];
 | 
			
		||||
  variant = names[3];
 | 
			
		||||
  options = names[4];
 | 
			
		||||
 | 
			
		||||
  meta_wayland_keyboard_set_keymap_names (&compositor->seat->keyboard,
 | 
			
		||||
                                          rules, model, layout, variant, options,
 | 
			
		||||
                                          META_WAYLAND_KEYBOARD_SKIP_XCLIENTS);
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  g_strfreev (names);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_display_handle_event:
 | 
			
		||||
 * meta_display_handle_xevent:
 | 
			
		||||
 * @display: The MetaDisplay that events are coming from
 | 
			
		||||
 * @event: The event that just happened
 | 
			
		||||
 *
 | 
			
		||||
@@ -2193,8 +2231,8 @@ handle_window_focus_event (MetaDisplay  *display,
 | 
			
		||||
 * dealing with all the kinds of events that might turn up.
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
meta_display_handle_event (MetaDisplay *display,
 | 
			
		||||
                           XEvent   *event)
 | 
			
		||||
meta_display_handle_xevent (MetaDisplay *display,
 | 
			
		||||
                            XEvent      *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window;
 | 
			
		||||
  MetaWindow *property_for_window;
 | 
			
		||||
@@ -2352,7 +2390,6 @@ meta_display_handle_event (MetaDisplay *display,
 | 
			
		||||
 | 
			
		||||
  if (input_event != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      XIDeviceEvent *device_event = (XIDeviceEvent *) input_event;
 | 
			
		||||
      XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
 | 
			
		||||
 | 
			
		||||
      if (window && !window->override_redirect &&
 | 
			
		||||
@@ -2389,205 +2426,6 @@ meta_display_handle_event (MetaDisplay *display,
 | 
			
		||||
          if (meta_display_process_key_event (display, window, (XIDeviceEvent *) input_event))
 | 
			
		||||
            filter_out_event = bypass_compositor = TRUE;
 | 
			
		||||
          break;
 | 
			
		||||
        case XI_ButtonPress:
 | 
			
		||||
          if (display->grab_op == META_GRAB_OP_COMPOSITOR)
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
          display->overlay_key_only_pressed = FALSE;
 | 
			
		||||
 | 
			
		||||
          if (device_event->detail == 4 || device_event->detail == 5)
 | 
			
		||||
            /* Scrollwheel event, do nothing and deliver event to compositor below */
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
          if ((window &&
 | 
			
		||||
               meta_grab_op_is_mouse (display->grab_op) &&
 | 
			
		||||
               display->grab_button != device_event->detail &&
 | 
			
		||||
               display->grab_window == window) ||
 | 
			
		||||
              grab_op_is_keyboard (display->grab_op))
 | 
			
		||||
            {
 | 
			
		||||
              meta_topic (META_DEBUG_WINDOW_OPS,
 | 
			
		||||
                          "Ending grab op %u on window %s due to button press\n",
 | 
			
		||||
                          display->grab_op,
 | 
			
		||||
                          (display->grab_window ?
 | 
			
		||||
                           display->grab_window->desc : 
 | 
			
		||||
                           "none"));
 | 
			
		||||
              if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
 | 
			
		||||
                {
 | 
			
		||||
                  MetaScreen *screen;
 | 
			
		||||
                  meta_topic (META_DEBUG_WINDOW_OPS, 
 | 
			
		||||
                              "Syncing to old stack positions.\n");
 | 
			
		||||
                  screen = 
 | 
			
		||||
                    meta_display_screen_for_root (display, device_event->event);
 | 
			
		||||
 | 
			
		||||
                  if (screen!=NULL)
 | 
			
		||||
                    meta_stack_set_positions (screen->stack,
 | 
			
		||||
                                              display->grab_old_window_stacking);
 | 
			
		||||
                }
 | 
			
		||||
              meta_display_end_grab_op (display,
 | 
			
		||||
                                        device_event->time);
 | 
			
		||||
            }
 | 
			
		||||
          else if (window && display->grab_op == META_GRAB_OP_NONE)
 | 
			
		||||
            {
 | 
			
		||||
              gboolean begin_move = FALSE;
 | 
			
		||||
              unsigned int grab_mask;
 | 
			
		||||
              gboolean unmodified;
 | 
			
		||||
 | 
			
		||||
              grab_mask = display->window_grab_modifiers;
 | 
			
		||||
              if (g_getenv ("MUTTER_DEBUG_BUTTON_GRABS"))
 | 
			
		||||
                grab_mask |= ControlMask;
 | 
			
		||||
 | 
			
		||||
              /* Two possible sources of an unmodified event; one is a
 | 
			
		||||
               * client that's letting button presses pass through to the
 | 
			
		||||
               * frame, the other is our focus_window_grab on unmodified
 | 
			
		||||
               * button 1.  So for all such events we focus the window.
 | 
			
		||||
               */
 | 
			
		||||
              unmodified = (device_event->mods.effective & grab_mask) == 0;
 | 
			
		||||
          
 | 
			
		||||
              if (unmodified ||
 | 
			
		||||
                  device_event->detail == 1)
 | 
			
		||||
                {
 | 
			
		||||
                  /* don't focus if frame received, will be lowered in
 | 
			
		||||
                   * frames.c or special-cased if the click was on a
 | 
			
		||||
                   * minimize/close button.
 | 
			
		||||
                   */
 | 
			
		||||
                  if (!frame_was_receiver)
 | 
			
		||||
                    {
 | 
			
		||||
                      if (meta_prefs_get_raise_on_click ()) 
 | 
			
		||||
                        meta_window_raise (window);
 | 
			
		||||
                      else
 | 
			
		||||
                        meta_topic (META_DEBUG_FOCUS,
 | 
			
		||||
                                    "Not raising window on click due to don't-raise-on-click option\n");
 | 
			
		||||
 | 
			
		||||
                      /* Don't focus panels--they must explicitly request focus.
 | 
			
		||||
                       * See bug 160470
 | 
			
		||||
                       */
 | 
			
		||||
                      if (window->type != META_WINDOW_DOCK)
 | 
			
		||||
                        {
 | 
			
		||||
                          meta_topic (META_DEBUG_FOCUS,
 | 
			
		||||
                                      "Focusing %s due to unmodified button %u press (display.c)\n",
 | 
			
		||||
                                      window->desc, device_event->detail);
 | 
			
		||||
                          meta_window_focus (window, device_event->time);
 | 
			
		||||
                        }
 | 
			
		||||
                      else
 | 
			
		||||
                        /* However, do allow terminals to lose focus due to new
 | 
			
		||||
                         * window mappings after the user clicks on a panel.
 | 
			
		||||
                         */
 | 
			
		||||
                        display->allow_terminal_deactivation = TRUE;
 | 
			
		||||
                    }
 | 
			
		||||
              
 | 
			
		||||
                  /* you can move on alt-click but not on
 | 
			
		||||
                   * the click-to-focus
 | 
			
		||||
                   */
 | 
			
		||||
                  if (!unmodified)
 | 
			
		||||
                    begin_move = TRUE;
 | 
			
		||||
                }
 | 
			
		||||
              else if (!unmodified && device_event->detail == meta_prefs_get_mouse_button_resize())
 | 
			
		||||
                {
 | 
			
		||||
                  if (window->has_resize_func)
 | 
			
		||||
                    {
 | 
			
		||||
                      gboolean north, south;
 | 
			
		||||
                      gboolean west, east;
 | 
			
		||||
                      int root_x, root_y;
 | 
			
		||||
                      MetaGrabOp op;
 | 
			
		||||
 | 
			
		||||
                      meta_window_get_position (window, &root_x, &root_y);
 | 
			
		||||
 | 
			
		||||
                      west = device_event->root_x <  (root_x + 1 * window->rect.width  / 3);
 | 
			
		||||
                      east = device_event->root_x >  (root_x + 2 * window->rect.width  / 3);
 | 
			
		||||
                      north = device_event->root_y < (root_y + 1 * window->rect.height / 3);
 | 
			
		||||
                      south = device_event->root_y > (root_y + 2 * window->rect.height / 3);
 | 
			
		||||
 | 
			
		||||
                      if (north && west)
 | 
			
		||||
                        op = META_GRAB_OP_RESIZING_NW;
 | 
			
		||||
                      else if (north && east)
 | 
			
		||||
                        op = META_GRAB_OP_RESIZING_NE;
 | 
			
		||||
                      else if (south && west)
 | 
			
		||||
                        op = META_GRAB_OP_RESIZING_SW;
 | 
			
		||||
                      else if (south && east)
 | 
			
		||||
                        op = META_GRAB_OP_RESIZING_SE;
 | 
			
		||||
                      else if (north)
 | 
			
		||||
                        op = META_GRAB_OP_RESIZING_N;
 | 
			
		||||
                      else if (west)
 | 
			
		||||
                        op = META_GRAB_OP_RESIZING_W;
 | 
			
		||||
                      else if (east)
 | 
			
		||||
                        op = META_GRAB_OP_RESIZING_E;
 | 
			
		||||
                      else if (south)
 | 
			
		||||
                        op = META_GRAB_OP_RESIZING_S;
 | 
			
		||||
                      else /* Middle region is no-op to avoid user triggering wrong action */
 | 
			
		||||
                        op = META_GRAB_OP_NONE;
 | 
			
		||||
                  
 | 
			
		||||
                      if (op != META_GRAB_OP_NONE)
 | 
			
		||||
                        meta_display_begin_grab_op (display,
 | 
			
		||||
                                                    window->screen,
 | 
			
		||||
                                                    window,
 | 
			
		||||
                                                    op,
 | 
			
		||||
                                                    TRUE,
 | 
			
		||||
                                                    FALSE,
 | 
			
		||||
                                                    device_event->detail,
 | 
			
		||||
                                                    0,
 | 
			
		||||
                                                    device_event->time,
 | 
			
		||||
                                                    device_event->root_x,
 | 
			
		||||
                                                    device_event->root_y);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
              else if (device_event->detail == meta_prefs_get_mouse_button_menu())
 | 
			
		||||
                {
 | 
			
		||||
                  if (meta_prefs_get_raise_on_click ())
 | 
			
		||||
                    meta_window_raise (window);
 | 
			
		||||
                  meta_window_show_menu (window,
 | 
			
		||||
                                         device_event->root_x,
 | 
			
		||||
                                         device_event->root_y,
 | 
			
		||||
                                         device_event->detail,
 | 
			
		||||
                                         device_event->time);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              if (!frame_was_receiver && unmodified)
 | 
			
		||||
                {
 | 
			
		||||
                  /* This is from our synchronous grab since
 | 
			
		||||
                   * it has no modifiers and was on the client window
 | 
			
		||||
                   */
 | 
			
		||||
 | 
			
		||||
                  meta_verbose ("Allowing events time %u\n",
 | 
			
		||||
                                (unsigned int)device_event->time);
 | 
			
		||||
 | 
			
		||||
                  XIAllowEvents (display->xdisplay, device_event->deviceid,
 | 
			
		||||
                                 XIReplayDevice, device_event->time);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              if (begin_move && window->has_move_func)
 | 
			
		||||
                {
 | 
			
		||||
                  meta_display_begin_grab_op (display,
 | 
			
		||||
                                              window->screen,
 | 
			
		||||
                                              window,
 | 
			
		||||
                                              META_GRAB_OP_MOVING,
 | 
			
		||||
                                              TRUE,
 | 
			
		||||
                                              FALSE,
 | 
			
		||||
                                              device_event->detail,
 | 
			
		||||
                                              0,
 | 
			
		||||
                                              device_event->time,
 | 
			
		||||
                                              device_event->root_x,
 | 
			
		||||
                                              device_event->root_y);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
          break;
 | 
			
		||||
        case XI_ButtonRelease:
 | 
			
		||||
          if (display->grab_op == META_GRAB_OP_COMPOSITOR)
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
          display->overlay_key_only_pressed = FALSE;
 | 
			
		||||
 | 
			
		||||
          if (display->grab_window == window &&
 | 
			
		||||
              meta_grab_op_is_mouse (display->grab_op))
 | 
			
		||||
            meta_window_handle_mouse_grab_op_event (window, device_event);
 | 
			
		||||
          break;
 | 
			
		||||
        case XI_Motion:
 | 
			
		||||
          if (display->grab_op == META_GRAB_OP_COMPOSITOR)
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
          if (display->grab_window == window &&
 | 
			
		||||
              meta_grab_op_is_mouse (display->grab_op))
 | 
			
		||||
            meta_window_handle_mouse_grab_op_event (window, device_event);
 | 
			
		||||
          break;
 | 
			
		||||
        case XI_Enter:
 | 
			
		||||
          if (display->grab_op == META_GRAB_OP_COMPOSITOR)
 | 
			
		||||
            break;
 | 
			
		||||
@@ -2951,6 +2789,10 @@ meta_display_handle_event (MetaDisplay *display,
 | 
			
		||||
                else if (event->xproperty.atom ==
 | 
			
		||||
                         display->atom__NET_DESKTOP_NAMES)
 | 
			
		||||
                  meta_screen_update_workspace_names (screen);
 | 
			
		||||
                else if (meta_is_wayland_compositor () &&
 | 
			
		||||
                         event->xproperty.atom ==
 | 
			
		||||
                         display->atom__XKB_RULES_NAMES)
 | 
			
		||||
                  reload_xkb_rules (screen);
 | 
			
		||||
#if 0
 | 
			
		||||
                else if (event->xproperty.atom ==
 | 
			
		||||
                         display->atom__NET_RESTACK_WINDOW)
 | 
			
		||||
@@ -3169,8 +3011,8 @@ meta_display_handle_event (MetaDisplay *display,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
event_callback (XEvent  *event,
 | 
			
		||||
                gpointer data)
 | 
			
		||||
xevent_callback (XEvent  *event,
 | 
			
		||||
                 gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display = data;
 | 
			
		||||
 | 
			
		||||
@@ -3186,9 +3028,272 @@ event_callback (XEvent  *event,
 | 
			
		||||
     translation altogether by directly using the Clutter events */
 | 
			
		||||
  if (meta_is_wayland_compositor () &&
 | 
			
		||||
      event->type == GenericEvent &&
 | 
			
		||||
      event->xcookie.evtype == XI_Motion)
 | 
			
		||||
      (event->xcookie.evtype == XI_KeyPress ||
 | 
			
		||||
       event->xcookie.evtype == XI_KeyRelease))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  return meta_display_handle_xevent (display, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaWindow *
 | 
			
		||||
get_window_for_actor (ClutterActor *actor,
 | 
			
		||||
                      gboolean     *frame_was_receiver)
 | 
			
		||||
{
 | 
			
		||||
  /* Look for any ancestor that is a MetaWindowActor to determine
 | 
			
		||||
     which window the actor's event belongs to */
 | 
			
		||||
 | 
			
		||||
  *frame_was_receiver = TRUE;
 | 
			
		||||
 | 
			
		||||
  while (actor)
 | 
			
		||||
    {
 | 
			
		||||
      if (META_IS_WINDOW_ACTOR (actor))
 | 
			
		||||
        return meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor));
 | 
			
		||||
 | 
			
		||||
      /* If the frame is the receiver then the source will directly be
 | 
			
		||||
         the MetaWindowActor, otherwise it will be a child of a
 | 
			
		||||
         MetaWindowActor so if we make it here then the event isn't
 | 
			
		||||
         referring to the frame. */
 | 
			
		||||
      *frame_was_receiver = FALSE;
 | 
			
		||||
 | 
			
		||||
      actor = clutter_actor_get_parent (actor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
                           const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window;
 | 
			
		||||
  gboolean frame_was_receiver;
 | 
			
		||||
 | 
			
		||||
  window = get_window_for_actor (event->any.source, &frame_was_receiver);
 | 
			
		||||
 | 
			
		||||
  switch (event->type)
 | 
			
		||||
    {
 | 
			
		||||
    case CLUTTER_BUTTON_PRESS:
 | 
			
		||||
      if (display->grab_op == META_GRAB_OP_COMPOSITOR)
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      display->overlay_key_only_pressed = FALSE;
 | 
			
		||||
 | 
			
		||||
      if ((window &&
 | 
			
		||||
           meta_grab_op_is_mouse (display->grab_op) &&
 | 
			
		||||
           display->grab_button != (int) event->button.button &&
 | 
			
		||||
           display->grab_window == window) ||
 | 
			
		||||
          grab_op_is_keyboard (display->grab_op))
 | 
			
		||||
        {
 | 
			
		||||
          meta_topic (META_DEBUG_WINDOW_OPS,
 | 
			
		||||
                      "Ending grab op %u on window %s due to button press\n",
 | 
			
		||||
                      display->grab_op,
 | 
			
		||||
                      (display->grab_window ?
 | 
			
		||||
                       display->grab_window->desc :
 | 
			
		||||
                       "none"));
 | 
			
		||||
          if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
 | 
			
		||||
            {
 | 
			
		||||
              meta_topic (META_DEBUG_WINDOW_OPS,
 | 
			
		||||
                          "Syncing to old stack positions.\n");
 | 
			
		||||
 | 
			
		||||
              /* XXX: I'm not sure if this is the right thing to do.
 | 
			
		||||
                 The pre-Wayland code was only calling
 | 
			
		||||
                 meta_stack_set_positions if the modified window was a
 | 
			
		||||
                 root window */
 | 
			
		||||
              if (CLUTTER_ACTOR (event->any.stage) == event->any.source &&
 | 
			
		||||
                  window &&
 | 
			
		||||
                  window->screen)
 | 
			
		||||
                meta_stack_set_positions (window->screen->stack,
 | 
			
		||||
                                          display->grab_old_window_stacking);
 | 
			
		||||
            }
 | 
			
		||||
          meta_display_end_grab_op (display,
 | 
			
		||||
                                    event->any.time);
 | 
			
		||||
        }
 | 
			
		||||
      else if (window && display->grab_op == META_GRAB_OP_NONE)
 | 
			
		||||
        {
 | 
			
		||||
          gboolean begin_move = FALSE;
 | 
			
		||||
          ClutterModifierType grab_mask;
 | 
			
		||||
          gboolean unmodified;
 | 
			
		||||
 | 
			
		||||
          grab_mask = display->window_grab_modifiers;
 | 
			
		||||
          if (g_getenv ("MUTTER_DEBUG_BUTTON_GRABS"))
 | 
			
		||||
            grab_mask |= CLUTTER_CONTROL_MASK;
 | 
			
		||||
 | 
			
		||||
          /* Two possible sources of an unmodified event; one is a
 | 
			
		||||
           * client that's letting button presses pass through to the
 | 
			
		||||
           * frame, the other is our focus_window_grab on unmodified
 | 
			
		||||
           * button 1.  So for all such events we focus the window.
 | 
			
		||||
           */
 | 
			
		||||
          unmodified = (clutter_event_get_state (event) & grab_mask) == 0;
 | 
			
		||||
 | 
			
		||||
          if (unmodified ||
 | 
			
		||||
              event->button.button == 1)
 | 
			
		||||
            {
 | 
			
		||||
              /* don't focus if frame received, will be lowered in
 | 
			
		||||
               * frames.c or special-cased if the click was on a
 | 
			
		||||
               * minimize/close button.
 | 
			
		||||
               */
 | 
			
		||||
              if (!frame_was_receiver)
 | 
			
		||||
                {
 | 
			
		||||
                  if (meta_prefs_get_raise_on_click ())
 | 
			
		||||
                    meta_window_raise (window);
 | 
			
		||||
                  else
 | 
			
		||||
                    meta_topic (META_DEBUG_FOCUS,
 | 
			
		||||
                                "Not raising window on click due "
 | 
			
		||||
                                "to don't-raise-on-click option\n");
 | 
			
		||||
 | 
			
		||||
                  /* Don't focus panels--they must explicitly request focus.
 | 
			
		||||
                   * See bug 160470
 | 
			
		||||
                   */
 | 
			
		||||
                  if (window->type != META_WINDOW_DOCK)
 | 
			
		||||
                    {
 | 
			
		||||
                      meta_topic (META_DEBUG_FOCUS,
 | 
			
		||||
                                  "Focusing %s due to unmodified button %u "
 | 
			
		||||
                                  "press (display.c)\n",
 | 
			
		||||
                                  window->desc, event->button.button);
 | 
			
		||||
                      meta_window_focus (window, event->any.time);
 | 
			
		||||
                    }
 | 
			
		||||
                  else
 | 
			
		||||
                    /* However, do allow terminals to lose focus due to new
 | 
			
		||||
                     * window mappings after the user clicks on a panel.
 | 
			
		||||
                     */
 | 
			
		||||
                    display->allow_terminal_deactivation = TRUE;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              /* you can move on alt-click but not on
 | 
			
		||||
               * the click-to-focus
 | 
			
		||||
               */
 | 
			
		||||
              if (!unmodified)
 | 
			
		||||
                begin_move = TRUE;
 | 
			
		||||
            }
 | 
			
		||||
          else if (!unmodified &&
 | 
			
		||||
                   ((int) event->button.button ==
 | 
			
		||||
                    meta_prefs_get_mouse_button_resize ()))
 | 
			
		||||
            {
 | 
			
		||||
              if (window->has_resize_func)
 | 
			
		||||
                {
 | 
			
		||||
                  gboolean north, south;
 | 
			
		||||
                  gboolean west, east;
 | 
			
		||||
                  int root_x, root_y;
 | 
			
		||||
                  MetaGrabOp op;
 | 
			
		||||
 | 
			
		||||
                  meta_window_get_position (window, &root_x, &root_y);
 | 
			
		||||
 | 
			
		||||
                  west = (event->button.x <
 | 
			
		||||
                          (root_x + 1 * window->rect.width / 3));
 | 
			
		||||
                  east = (event->button.x >
 | 
			
		||||
                          (root_x + 2 * window->rect.width / 3));
 | 
			
		||||
                  north = (event->button.y <
 | 
			
		||||
                           (root_y + 1 * window->rect.height / 3));
 | 
			
		||||
                  south = (event->button.y >
 | 
			
		||||
                           (root_y + 2 * window->rect.height / 3));
 | 
			
		||||
 | 
			
		||||
                  if (north && west)
 | 
			
		||||
                    op = META_GRAB_OP_RESIZING_NW;
 | 
			
		||||
                  else if (north && east)
 | 
			
		||||
                    op = META_GRAB_OP_RESIZING_NE;
 | 
			
		||||
                  else if (south && west)
 | 
			
		||||
                    op = META_GRAB_OP_RESIZING_SW;
 | 
			
		||||
                  else if (south && east)
 | 
			
		||||
                    op = META_GRAB_OP_RESIZING_SE;
 | 
			
		||||
                  else if (north)
 | 
			
		||||
                    op = META_GRAB_OP_RESIZING_N;
 | 
			
		||||
                  else if (west)
 | 
			
		||||
                    op = META_GRAB_OP_RESIZING_W;
 | 
			
		||||
                  else if (east)
 | 
			
		||||
                    op = META_GRAB_OP_RESIZING_E;
 | 
			
		||||
                  else if (south)
 | 
			
		||||
                    op = META_GRAB_OP_RESIZING_S;
 | 
			
		||||
                  else
 | 
			
		||||
                    /* Middle region is no-op to avoid user triggering
 | 
			
		||||
                       wrong action */
 | 
			
		||||
                    op = META_GRAB_OP_NONE;
 | 
			
		||||
 | 
			
		||||
                  if (op != META_GRAB_OP_NONE)
 | 
			
		||||
                    meta_display_begin_grab_op (display,
 | 
			
		||||
                                                window->screen,
 | 
			
		||||
                                                window,
 | 
			
		||||
                                                op,
 | 
			
		||||
                                                TRUE,
 | 
			
		||||
                                                FALSE,
 | 
			
		||||
                                                event->button.button,
 | 
			
		||||
                                                0,
 | 
			
		||||
                                                event->any.time,
 | 
			
		||||
                                                event->button.x,
 | 
			
		||||
                                                event->button.y);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
          else if ((int) event->button.button ==
 | 
			
		||||
                   meta_prefs_get_mouse_button_menu ())
 | 
			
		||||
            {
 | 
			
		||||
              if (meta_prefs_get_raise_on_click ())
 | 
			
		||||
                meta_window_raise (window);
 | 
			
		||||
              meta_window_show_menu (window,
 | 
			
		||||
                                     event->button.x,
 | 
			
		||||
                                     event->button.y,
 | 
			
		||||
                                     event->button.button,
 | 
			
		||||
                                     event->any.time);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          if (!frame_was_receiver && unmodified)
 | 
			
		||||
            {
 | 
			
		||||
              /* This is from our synchronous grab since
 | 
			
		||||
               * it has no modifiers and was on the client window
 | 
			
		||||
               */
 | 
			
		||||
 | 
			
		||||
              meta_verbose ("Allowing events time %u\n",
 | 
			
		||||
                            (unsigned int) event->any.time);
 | 
			
		||||
 | 
			
		||||
              clutter_input_device_set_enabled (event->button.device, TRUE);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          if (begin_move && window->has_move_func)
 | 
			
		||||
            {
 | 
			
		||||
              meta_display_begin_grab_op (display,
 | 
			
		||||
                                          window->screen,
 | 
			
		||||
                                          window,
 | 
			
		||||
                                          META_GRAB_OP_MOVING,
 | 
			
		||||
                                          TRUE,
 | 
			
		||||
                                          FALSE,
 | 
			
		||||
                                          event->button.button,
 | 
			
		||||
                                          0,
 | 
			
		||||
                                          event->any.time,
 | 
			
		||||
                                          event->button.x,
 | 
			
		||||
                                          event->button.y);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
      break;
 | 
			
		||||
    case CLUTTER_BUTTON_RELEASE:
 | 
			
		||||
      if (display->grab_op == META_GRAB_OP_COMPOSITOR)
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      display->overlay_key_only_pressed = FALSE;
 | 
			
		||||
 | 
			
		||||
      if (display->grab_window == window &&
 | 
			
		||||
          meta_grab_op_is_mouse (display->grab_op))
 | 
			
		||||
        meta_window_handle_mouse_grab_op_event (window, event);
 | 
			
		||||
      break;
 | 
			
		||||
    case CLUTTER_MOTION:
 | 
			
		||||
      if (display->grab_op == META_GRAB_OP_COMPOSITOR)
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      if (display->grab_window == window &&
 | 
			
		||||
          meta_grab_op_is_mouse (display->grab_op))
 | 
			
		||||
        meta_window_handle_mouse_grab_op_event (window, event);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
event_callback (const ClutterEvent *event,
 | 
			
		||||
                gpointer            data)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display = data;
 | 
			
		||||
 | 
			
		||||
  return meta_display_handle_event (display, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -5984,7 +6089,7 @@ meta_display_get_xinput_opcode (MetaDisplay *display)
 | 
			
		||||
gboolean
 | 
			
		||||
meta_display_supports_extended_barriers (MetaDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  return META_DISPLAY_HAS_XINPUT_23 (display);
 | 
			
		||||
  return META_DISPLAY_HAS_XINPUT_23 (display) && !meta_is_wayland_compositor ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -2065,22 +2065,22 @@ meta_display_process_key_event (MetaDisplay   *display,
 | 
			
		||||
  gboolean handled;
 | 
			
		||||
  const char *str;
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
  gboolean was_current_time;
 | 
			
		||||
 | 
			
		||||
  /* if key event was on root window, we have a shortcut */
 | 
			
		||||
  screen = meta_display_screen_for_root (display, event->event);
 | 
			
		||||
 | 
			
		||||
  /* else round-trip to server */
 | 
			
		||||
  if (screen == NULL)
 | 
			
		||||
    screen = meta_display_screen_for_xwindow (display, event->event);
 | 
			
		||||
 | 
			
		||||
  if (screen == NULL)
 | 
			
		||||
    return FALSE; /* event window is destroyed */
 | 
			
		||||
  /* We only ever have one screen */
 | 
			
		||||
  screen = display->screens->data;
 | 
			
		||||
 | 
			
		||||
  /* ignore key events on popup menus and such. */
 | 
			
		||||
  if (meta_ui_window_is_widget (screen->ui, event->event))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  /* window may be NULL */
 | 
			
		||||
  if (display->current_time == CurrentTime)
 | 
			
		||||
    {
 | 
			
		||||
      display->current_time = event->time;
 | 
			
		||||
      was_current_time = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    was_current_time = FALSE;
 | 
			
		||||
 | 
			
		||||
  keysym = XKeycodeToKeysym (display->xdisplay, event->detail, 0);
 | 
			
		||||
 | 
			
		||||
@@ -2098,11 +2098,11 @@ meta_display_process_key_event (MetaDisplay   *display,
 | 
			
		||||
    {
 | 
			
		||||
      handled = process_overlay_key (display, screen, event, keysym);
 | 
			
		||||
      if (handled)
 | 
			
		||||
        return TRUE;
 | 
			
		||||
        goto out;
 | 
			
		||||
 | 
			
		||||
      handled = process_iso_next_group (display, screen, event, keysym);
 | 
			
		||||
      if (handled)
 | 
			
		||||
        return TRUE;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  XIAllowEvents (display->xdisplay, event->deviceid,
 | 
			
		||||
@@ -2112,7 +2112,11 @@ meta_display_process_key_event (MetaDisplay   *display,
 | 
			
		||||
  if (all_keys_grabbed)
 | 
			
		||||
    {
 | 
			
		||||
      if (display->grab_op == META_GRAB_OP_NONE)
 | 
			
		||||
        return TRUE;
 | 
			
		||||
        {
 | 
			
		||||
          handled = TRUE;
 | 
			
		||||
          goto out;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      /* If we get here we have a global grab, because
 | 
			
		||||
       * we're in some special keyboard mode such as window move
 | 
			
		||||
       * mode.
 | 
			
		||||
@@ -2191,14 +2195,20 @@ meta_display_process_key_event (MetaDisplay   *display,
 | 
			
		||||
          meta_display_end_grab_op (display, event->time);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      return TRUE;
 | 
			
		||||
      handled = TRUE;
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Do the normal keybindings */
 | 
			
		||||
  return process_event (display->key_bindings,
 | 
			
		||||
                        display->n_key_bindings,
 | 
			
		||||
                        display, screen, window, event, keysym,
 | 
			
		||||
                        !all_keys_grabbed && window);
 | 
			
		||||
  handled = process_event (display->key_bindings,
 | 
			
		||||
                           display->n_key_bindings,
 | 
			
		||||
                           display, screen, window, event, keysym,
 | 
			
		||||
                           !all_keys_grabbed && window);
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  if (was_current_time)
 | 
			
		||||
    display->current_time = CurrentTime;
 | 
			
		||||
  return handled;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
 
 | 
			
		||||
@@ -249,6 +249,17 @@ meta_get_option_context (void)
 | 
			
		||||
  bindtextdomain (GETTEXT_PACKAGE, MUTTER_LOCALEDIR);
 | 
			
		||||
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 | 
			
		||||
 | 
			
		||||
  /* We must set the variables here, because Clutter creates the backend
 | 
			
		||||
     when the first call is made.
 | 
			
		||||
 | 
			
		||||
     We consider running from mutter-launch equivalent to running from bare metal.
 | 
			
		||||
  */
 | 
			
		||||
  if (getenv ("WESTON_LAUNCHER_SOCK"))
 | 
			
		||||
    {
 | 
			
		||||
      g_setenv ("CLUTTER_BACKEND", "eglnative", TRUE);
 | 
			
		||||
      g_setenv ("CLUTTER_INPUT_BACKEND", "evdev", TRUE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  ctx = g_option_context_new (NULL);
 | 
			
		||||
  g_option_context_add_main_entries (ctx, meta_options, GETTEXT_PACKAGE);
 | 
			
		||||
  g_option_context_add_group (ctx, clutter_get_option_group_without_init ());
 | 
			
		||||
@@ -386,6 +397,9 @@ meta_init (void)
 | 
			
		||||
                g_strerror (errno));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (getenv ("MUTTER_SLEEP_INIT"))
 | 
			
		||||
    sleep (60);
 | 
			
		||||
 | 
			
		||||
  g_unix_signal_add (SIGTERM, on_sigterm, NULL);
 | 
			
		||||
 | 
			
		||||
  if (g_getenv ("MUTTER_VERBOSE"))
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										858
									
								
								src/core/monitor-kms.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										858
									
								
								src/core/monitor-kms.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,858 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2013 Red Hat Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 * Author: Giovanni Campagna <gcampagn@redhat.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <xf86drm.h>
 | 
			
		||||
#include <xf86drmMode.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "monitor-private.h"
 | 
			
		||||
#include "edid.h"
 | 
			
		||||
 | 
			
		||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  drmModeConnector *connector;
 | 
			
		||||
 | 
			
		||||
  unsigned n_encoders;
 | 
			
		||||
  drmModeEncoderPtr *encoders;
 | 
			
		||||
  drmModeEncoderPtr  current_encoder;
 | 
			
		||||
 | 
			
		||||
  /* bitmasks of encoder position in the resources array */
 | 
			
		||||
  uint32_t encoder_mask;
 | 
			
		||||
  uint32_t enc_clone_mask;
 | 
			
		||||
 | 
			
		||||
  uint32_t dpms_prop_id;
 | 
			
		||||
  uint32_t edid_blob_id;
 | 
			
		||||
  uint32_t has_dpms_prop : 1;
 | 
			
		||||
  uint32_t has_edid_blob : 1;
 | 
			
		||||
} MetaOutputKms;
 | 
			
		||||
 | 
			
		||||
struct _MetaMonitorManagerKms
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager parent_instance;
 | 
			
		||||
 | 
			
		||||
  int fd;
 | 
			
		||||
 | 
			
		||||
  drmModeConnector **connectors;
 | 
			
		||||
  unsigned int       n_connectors;
 | 
			
		||||
 | 
			
		||||
  drmModeEncoder   **encoders;
 | 
			
		||||
  unsigned int       n_encoders;
 | 
			
		||||
 | 
			
		||||
  drmModeEncoder    *current_encoder;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaMonitorManagerKmsClass
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaMonitorManagerKms, meta_monitor_manager_kms, META_TYPE_MONITOR_MANAGER);
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
compare_outputs (const void *one,
 | 
			
		||||
                 const void *two)
 | 
			
		||||
{
 | 
			
		||||
  const MetaOutput *o_one = one, *o_two = two;
 | 
			
		||||
 | 
			
		||||
  return strcmp (o_one->name, o_two->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *
 | 
			
		||||
make_output_name (drmModeConnector *connector)
 | 
			
		||||
{
 | 
			
		||||
  static const char * const connector_type_names[] = {
 | 
			
		||||
    "unknown", "VGA", "DVII", "DVID", "DVID", "Composite",
 | 
			
		||||
    "SVIDEO", "LVDS", "Component", "9PinDIN", "DisplayPort",
 | 
			
		||||
    "HDMIA", "HDMIB", "TV", "eDP"
 | 
			
		||||
  };
 | 
			
		||||
  const char *connector_type_name;
 | 
			
		||||
 | 
			
		||||
  if (connector->connector_type >= 0 &&
 | 
			
		||||
      connector->connector_type < G_N_ELEMENTS (connector_type_names))
 | 
			
		||||
    connector_type_name = connector_type_names[connector->connector_type];
 | 
			
		||||
  else
 | 
			
		||||
    connector_type_name = "unknown";
 | 
			
		||||
 | 
			
		||||
  return g_strdup_printf ("%s%d", connector_type_name, connector->connector_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_output_destroy_notify (MetaOutput *output)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutputKms *output_kms;
 | 
			
		||||
  unsigned i;
 | 
			
		||||
 | 
			
		||||
  output_kms = output->driver_private;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < output_kms->n_encoders; i++)
 | 
			
		||||
    drmModeFreeEncoder (output_kms->encoders[i]);
 | 
			
		||||
 | 
			
		||||
  g_slice_free (MetaOutputKms, output_kms);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_mode_destroy_notify (MetaMonitorMode *output)
 | 
			
		||||
{
 | 
			
		||||
  g_slice_free (drmModeModeInfo, output->driver_private);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
drm_mode_equal (gconstpointer one,
 | 
			
		||||
                gconstpointer two)
 | 
			
		||||
{
 | 
			
		||||
  return memcmp (one, two, sizeof (drmModeModeInfo)) == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint
 | 
			
		||||
drm_mode_hash (gconstpointer ptr)
 | 
			
		||||
{
 | 
			
		||||
  const drmModeModeInfo *mode = ptr;
 | 
			
		||||
  guint hash = 0;
 | 
			
		||||
 | 
			
		||||
  hash ^= mode->clock;
 | 
			
		||||
  hash ^= mode->hdisplay ^ mode->hsync_start ^ mode->hsync_end;
 | 
			
		||||
  hash ^= mode->vdisplay ^ mode->vsync_start ^ mode->vsync_end;
 | 
			
		||||
  hash ^= mode->vrefresh;
 | 
			
		||||
  hash ^= mode->flags ^ mode->type;
 | 
			
		||||
 | 
			
		||||
  return hash;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
find_properties (MetaMonitorManagerKms *manager_kms,
 | 
			
		||||
                 MetaOutputKms         *output_kms)
 | 
			
		||||
{
 | 
			
		||||
  drmModePropertyPtr prop;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < output_kms->connector->count_props; i++)
 | 
			
		||||
    {
 | 
			
		||||
      prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
 | 
			
		||||
      if (!prop)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if ((prop->flags & DRM_MODE_PROP_ENUM) &&
 | 
			
		||||
          strcmp(prop->name, "DPMS") == 0)
 | 
			
		||||
        {
 | 
			
		||||
          output_kms->dpms_prop_id = prop->prop_id;
 | 
			
		||||
          output_kms->has_dpms_prop = TRUE;
 | 
			
		||||
          drmModeFreeProperty(prop);
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if ((prop->flags & DRM_MODE_PROP_BLOB) &&
 | 
			
		||||
          strcmp (prop->name, "EDID") == 0)
 | 
			
		||||
        {
 | 
			
		||||
          output_kms->edid_blob_id = output_kms->connector->prop_values[i];
 | 
			
		||||
          output_kms->has_edid_blob = TRUE;
 | 
			
		||||
          drmModeFreeProperty(prop);
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      drmModeFreeProperty(prop);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GBytes *
 | 
			
		||||
read_output_edid (MetaMonitorManagerKms *manager_kms,
 | 
			
		||||
                  MetaOutput            *output)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutputKms *output_kms = output->driver_private;
 | 
			
		||||
  drmModePropertyBlobPtr edid_blob = NULL;
 | 
			
		||||
 | 
			
		||||
  if (!output_kms->has_edid_blob)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  edid_blob = drmModeGetPropertyBlob (manager_kms->fd, output_kms->edid_blob_id);
 | 
			
		||||
  if (!edid_blob)
 | 
			
		||||
    {
 | 
			
		||||
      meta_warning ("Failed to read EDID of output %s: %s\n", output->name, strerror(errno));
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (edid_blob->length > 0 && edid_blob->length % 128 == 0)
 | 
			
		||||
    return g_bytes_new_with_free_func (edid_blob->data, edid_blob->length,
 | 
			
		||||
                                       (GDestroyNotify)drmModeFreePropertyBlob, edid_blob);
 | 
			
		||||
  else
 | 
			
		||||
    drmModeFreePropertyBlob (edid_blob);
 | 
			
		||||
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
 | 
			
		||||
  drmModeRes *resources;
 | 
			
		||||
  GHashTable *modes;
 | 
			
		||||
  GHashTableIter iter;
 | 
			
		||||
  drmModeModeInfo *mode;
 | 
			
		||||
  unsigned int i, j, k;
 | 
			
		||||
  unsigned int n_actual_outputs;
 | 
			
		||||
  int width, height;
 | 
			
		||||
 | 
			
		||||
  resources = drmModeGetResources(manager_kms->fd);
 | 
			
		||||
  modes = g_hash_table_new (drm_mode_hash, drm_mode_equal);
 | 
			
		||||
 | 
			
		||||
  manager->max_screen_width = resources->max_width;
 | 
			
		||||
  manager->max_screen_height = resources->max_height;
 | 
			
		||||
 | 
			
		||||
  manager->power_save_mode = META_POWER_SAVE_ON;
 | 
			
		||||
 | 
			
		||||
  manager_kms->n_connectors = resources->count_connectors;
 | 
			
		||||
  manager_kms->connectors = g_new (drmModeConnector *, manager_kms->n_connectors);
 | 
			
		||||
  for (i = 0; i < manager_kms->n_connectors; i++)
 | 
			
		||||
    {
 | 
			
		||||
      drmModeConnector *connector;
 | 
			
		||||
 | 
			
		||||
      connector = drmModeGetConnector (manager_kms->fd, resources->connectors[i]);
 | 
			
		||||
      manager_kms->connectors[i] = connector;
 | 
			
		||||
 | 
			
		||||
      if (connector->connection == DRM_MODE_CONNECTED)
 | 
			
		||||
        {
 | 
			
		||||
          /* Collect all modes for this connector */
 | 
			
		||||
          for (j = 0; j < (unsigned)connector->count_modes; j++)
 | 
			
		||||
            g_hash_table_add (modes, &connector->modes[j]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  manager_kms->n_encoders = resources->count_encoders;
 | 
			
		||||
  manager_kms->encoders = g_new (drmModeEncoder *, manager_kms->n_encoders);
 | 
			
		||||
  for (i = 0; i < manager_kms->n_encoders; i++)
 | 
			
		||||
    {
 | 
			
		||||
      manager_kms->encoders[i] = drmModeGetEncoder (manager_kms->fd,
 | 
			
		||||
                                                    resources->encoders[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  manager->n_modes = g_hash_table_size (modes);
 | 
			
		||||
  manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
 | 
			
		||||
  g_hash_table_iter_init (&iter, modes);
 | 
			
		||||
  i = 0;
 | 
			
		||||
  while (g_hash_table_iter_next (&iter, NULL, (gpointer)&mode))
 | 
			
		||||
    {
 | 
			
		||||
      MetaMonitorMode *meta_mode;
 | 
			
		||||
 | 
			
		||||
      meta_mode = &manager->modes[i];
 | 
			
		||||
 | 
			
		||||
      meta_mode->mode_id = i;
 | 
			
		||||
      meta_mode->name = g_strndup (mode->name, DRM_DISPLAY_MODE_LEN);
 | 
			
		||||
      meta_mode->width = mode->hdisplay;
 | 
			
		||||
      meta_mode->height = mode->vdisplay;
 | 
			
		||||
      meta_mode->refresh_rate = (1000 * mode->clock /
 | 
			
		||||
                                 ((float)mode->htotal * mode->vtotal));
 | 
			
		||||
 | 
			
		||||
      meta_mode->driver_private = g_slice_dup (drmModeModeInfo, mode);
 | 
			
		||||
      meta_mode->driver_notify = (GDestroyNotify)meta_monitor_mode_destroy_notify;
 | 
			
		||||
 | 
			
		||||
      i++;
 | 
			
		||||
    }
 | 
			
		||||
  g_hash_table_destroy (modes);
 | 
			
		||||
 | 
			
		||||
  manager->n_crtcs = resources->count_crtcs;
 | 
			
		||||
  manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs);
 | 
			
		||||
  width = 0; height = 0;
 | 
			
		||||
  for (i = 0; i < (unsigned)resources->count_crtcs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      drmModeCrtc *crtc;
 | 
			
		||||
      MetaCRTC *meta_crtc;
 | 
			
		||||
 | 
			
		||||
      crtc = drmModeGetCrtc (manager_kms->fd, resources->crtcs[i]);
 | 
			
		||||
 | 
			
		||||
      meta_crtc = &manager->crtcs[i];
 | 
			
		||||
 | 
			
		||||
      meta_crtc->crtc_id = crtc->crtc_id;
 | 
			
		||||
      meta_crtc->rect.x = crtc->x;
 | 
			
		||||
      meta_crtc->rect.y = crtc->y;
 | 
			
		||||
      meta_crtc->rect.width = crtc->width;
 | 
			
		||||
      meta_crtc->rect.height = crtc->height;
 | 
			
		||||
      meta_crtc->is_dirty = FALSE;
 | 
			
		||||
      meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
 | 
			
		||||
      /* FIXME: implement! */
 | 
			
		||||
      meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
 | 
			
		||||
 | 
			
		||||
      if (crtc->mode_valid)
 | 
			
		||||
        {
 | 
			
		||||
          for (j = 0; j < manager->n_modes; j++)
 | 
			
		||||
            {
 | 
			
		||||
              if (drm_mode_equal (&crtc->mode, manager->modes[j].driver_private))
 | 
			
		||||
                {
 | 
			
		||||
                  meta_crtc->current_mode = &manager->modes[j];
 | 
			
		||||
                  break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          width = MAX (width, meta_crtc->rect.x + meta_crtc->rect.width);
 | 
			
		||||
          height = MAX (height, meta_crtc->rect.y + meta_crtc->rect.height);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      drmModeFreeCrtc (crtc);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  manager->screen_width = width;
 | 
			
		||||
  manager->screen_height = height;
 | 
			
		||||
 | 
			
		||||
  manager->outputs = g_new0 (MetaOutput, manager_kms->n_connectors);
 | 
			
		||||
  n_actual_outputs = 0;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < manager_kms->n_connectors; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *meta_output;
 | 
			
		||||
      MetaOutputKms *output_kms;
 | 
			
		||||
      drmModeConnector *connector;
 | 
			
		||||
      GArray *crtcs;
 | 
			
		||||
      unsigned int crtc_mask;
 | 
			
		||||
      GBytes *edid;
 | 
			
		||||
 | 
			
		||||
      connector = manager_kms->connectors[i];
 | 
			
		||||
      meta_output = &manager->outputs[n_actual_outputs];
 | 
			
		||||
 | 
			
		||||
      if (connector->connection == DRM_MODE_CONNECTED)
 | 
			
		||||
	{
 | 
			
		||||
          meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
 | 
			
		||||
          meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
 | 
			
		||||
 | 
			
		||||
	  meta_output->output_id = connector->connector_id;
 | 
			
		||||
	  meta_output->name = make_output_name (connector);
 | 
			
		||||
	  meta_output->width_mm = connector->mmWidth;
 | 
			
		||||
	  meta_output->height_mm = connector->mmHeight;
 | 
			
		||||
 | 
			
		||||
          if (connector->subpixel == DRM_MODE_SUBPIXEL_UNKNOWN)
 | 
			
		||||
            meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
 | 
			
		||||
          else if (connector->subpixel == DRM_MODE_SUBPIXEL_NONE)
 | 
			
		||||
            meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE;
 | 
			
		||||
          else
 | 
			
		||||
            meta_output->subpixel_order = connector->subpixel;
 | 
			
		||||
 | 
			
		||||
	  meta_output->n_modes = connector->count_modes;
 | 
			
		||||
	  meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
 | 
			
		||||
	  for (j = 0; j < meta_output->n_modes; j++)
 | 
			
		||||
	    {
 | 
			
		||||
	      for (k = 0; k < manager->n_modes; k++)
 | 
			
		||||
		{
 | 
			
		||||
		  if (drm_mode_equal (&connector->modes[j], manager->modes[k].driver_private))
 | 
			
		||||
		    {
 | 
			
		||||
		      meta_output->modes[j] = &manager->modes[k];
 | 
			
		||||
		      break;
 | 
			
		||||
		    }
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	  meta_output->preferred_mode = meta_output->modes[0];
 | 
			
		||||
 | 
			
		||||
          output_kms->connector = connector;
 | 
			
		||||
          output_kms->n_encoders = connector->count_encoders;
 | 
			
		||||
          output_kms->encoders = g_new0 (drmModeEncoderPtr, output_kms->n_encoders);
 | 
			
		||||
 | 
			
		||||
          crtc_mask = 0x7F;
 | 
			
		||||
	  for (j = 0; j < output_kms->n_encoders; j++)
 | 
			
		||||
	    {
 | 
			
		||||
              output_kms->encoders[j] = drmModeGetEncoder (manager_kms->fd, connector->encoders[j]);
 | 
			
		||||
 | 
			
		||||
              crtc_mask &= output_kms->encoders[j]->possible_crtcs;
 | 
			
		||||
 | 
			
		||||
              if (output_kms->encoders[j]->encoder_id == connector->encoder_id)
 | 
			
		||||
                output_kms->current_encoder = output_kms->encoders[j];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCRTC*));
 | 
			
		||||
 | 
			
		||||
          for (j = 0; j < manager->n_crtcs; j++)
 | 
			
		||||
            {
 | 
			
		||||
              if (crtc_mask & (1 << j))
 | 
			
		||||
                {
 | 
			
		||||
                  MetaCRTC *crtc = &manager->crtcs[j];
 | 
			
		||||
                  g_array_append_val (crtcs, crtc);
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
          
 | 
			
		||||
	  meta_output->n_possible_crtcs = crtcs->len;
 | 
			
		||||
	  meta_output->possible_crtcs = (void*)g_array_free (crtcs, FALSE);
 | 
			
		||||
 | 
			
		||||
          if (output_kms->current_encoder && output_kms->current_encoder->crtc_id != 0)
 | 
			
		||||
            {
 | 
			
		||||
              for (j = 0; j < manager->n_crtcs; j++)
 | 
			
		||||
                {
 | 
			
		||||
                  if (manager->crtcs[j].crtc_id == output_kms->current_encoder->crtc_id)
 | 
			
		||||
                    {
 | 
			
		||||
                      meta_output->crtc = &manager->crtcs[j];
 | 
			
		||||
                      break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            meta_output->crtc = NULL;
 | 
			
		||||
 | 
			
		||||
	  meta_output->is_primary = FALSE;
 | 
			
		||||
	  meta_output->is_presentation = FALSE;
 | 
			
		||||
 | 
			
		||||
          find_properties (manager_kms, output_kms);
 | 
			
		||||
 | 
			
		||||
          edid = read_output_edid (manager_kms, meta_output);
 | 
			
		||||
          if (edid)
 | 
			
		||||
            {
 | 
			
		||||
              MonitorInfo *parsed_edid;
 | 
			
		||||
              gsize len;
 | 
			
		||||
 | 
			
		||||
              parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
 | 
			
		||||
              if (parsed_edid)
 | 
			
		||||
                {
 | 
			
		||||
                  meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
 | 
			
		||||
                  meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
 | 
			
		||||
                  meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
 | 
			
		||||
 | 
			
		||||
                  g_free (parsed_edid);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              g_bytes_unref (edid);
 | 
			
		||||
            }
 | 
			
		||||
          if (!meta_output->vendor)
 | 
			
		||||
            {
 | 
			
		||||
              meta_output->vendor = g_strdup ("unknown");
 | 
			
		||||
              meta_output->product = g_strdup ("unknown");
 | 
			
		||||
              meta_output->serial = g_strdup ("unknown");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          /* FIXME: backlight is a very driver specific thing unfortunately,
 | 
			
		||||
             every DDX does its own thing, and the dumb KMS API does not include it.
 | 
			
		||||
 | 
			
		||||
             For example, xf86-video-intel has a list of paths to probe in /sys/class/backlight
 | 
			
		||||
             (one for each major HW maker, and then some).
 | 
			
		||||
             We can't do the same because we're not root.
 | 
			
		||||
             It might be best to leave backlight out of the story and rely on the setuid
 | 
			
		||||
             helper in gnome-settings-daemon.
 | 
			
		||||
          */
 | 
			
		||||
	  meta_output->backlight_min = 0;
 | 
			
		||||
          meta_output->backlight_max = 0;
 | 
			
		||||
          meta_output->backlight = -1;
 | 
			
		||||
 | 
			
		||||
	  n_actual_outputs++;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  manager->n_outputs = n_actual_outputs;
 | 
			
		||||
  manager->outputs = g_renew (MetaOutput, manager->outputs, manager->n_outputs);
 | 
			
		||||
 | 
			
		||||
  /* Sort the outputs for easier handling in MetaMonitorConfig */
 | 
			
		||||
  qsort (manager->outputs, manager->n_outputs, sizeof (MetaOutput), compare_outputs);
 | 
			
		||||
 | 
			
		||||
  /* Now fix the clones.
 | 
			
		||||
     Code mostly inspired by xf86-video-modesetting. */
 | 
			
		||||
 | 
			
		||||
  /* XXX: intel hardware doesn't usually have clones, but we only have intel
 | 
			
		||||
     cards, so this code was never tested! */
 | 
			
		||||
  for (i = 0; i < manager->n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *meta_output;
 | 
			
		||||
      MetaOutputKms *output_kms;
 | 
			
		||||
 | 
			
		||||
      meta_output = &manager->outputs[i];
 | 
			
		||||
      output_kms = meta_output->driver_private;
 | 
			
		||||
 | 
			
		||||
      output_kms->enc_clone_mask = 0xff;
 | 
			
		||||
      output_kms->encoder_mask = 0;
 | 
			
		||||
 | 
			
		||||
      for (j = 0; j < output_kms->n_encoders; j++)
 | 
			
		||||
	{
 | 
			
		||||
	  for (k = 0; k < manager_kms->n_encoders; k++)
 | 
			
		||||
	    {
 | 
			
		||||
	      if (output_kms->encoders[j]->encoder_id == manager_kms->encoders[k]->encoder_id)
 | 
			
		||||
		{
 | 
			
		||||
                  output_kms->encoder_mask |= (1 << k);
 | 
			
		||||
		  break;
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
          output_kms->enc_clone_mask &= output_kms->encoders[j]->possible_clones;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < manager->n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *meta_output;
 | 
			
		||||
      MetaOutputKms *output_kms;
 | 
			
		||||
 | 
			
		||||
      meta_output = &manager->outputs[i];
 | 
			
		||||
      output_kms = meta_output->driver_private;
 | 
			
		||||
 | 
			
		||||
      if (output_kms->enc_clone_mask == 0)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      for (j = 0; j < manager->n_outputs; j++)
 | 
			
		||||
        {
 | 
			
		||||
          MetaOutput *meta_clone;
 | 
			
		||||
          MetaOutputKms *clone_kms;
 | 
			
		||||
 | 
			
		||||
          meta_clone = &manager->outputs[i];
 | 
			
		||||
          clone_kms = meta_clone->driver_private;
 | 
			
		||||
 | 
			
		||||
          if (meta_clone == meta_output)
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
          if (clone_kms->encoder_mask == 0)
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
          if (clone_kms->encoder_mask == output_kms->enc_clone_mask)
 | 
			
		||||
            {
 | 
			
		||||
              meta_output->n_possible_clones++;
 | 
			
		||||
              meta_output->possible_clones = g_renew (MetaOutput *,
 | 
			
		||||
                                                      meta_output->possible_clones,
 | 
			
		||||
                                                      meta_output->n_possible_clones);
 | 
			
		||||
              meta_output->possible_clones[meta_output->n_possible_clones - 1] = meta_clone;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  drmModeFreeResources (resources);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GBytes *
 | 
			
		||||
meta_monitor_manager_kms_read_edid (MetaMonitorManager *manager,
 | 
			
		||||
                                    MetaOutput         *output)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
 | 
			
		||||
 | 
			
		||||
  return read_output_edid (manager_kms, output);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
 | 
			
		||||
                                              MetaPowerSave       mode)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
 | 
			
		||||
  uint64_t state;
 | 
			
		||||
  unsigned i;
 | 
			
		||||
 | 
			
		||||
  switch (mode) {
 | 
			
		||||
  case META_POWER_SAVE_ON:
 | 
			
		||||
    state = DRM_MODE_DPMS_ON;
 | 
			
		||||
    break;
 | 
			
		||||
  case META_POWER_SAVE_STANDBY:
 | 
			
		||||
    state = DRM_MODE_DPMS_STANDBY;
 | 
			
		||||
    break;
 | 
			
		||||
  case META_POWER_SAVE_SUSPEND:
 | 
			
		||||
    state = DRM_MODE_DPMS_SUSPEND;
 | 
			
		||||
    break;
 | 
			
		||||
  case META_POWER_SAVE_OFF:
 | 
			
		||||
    state = DRM_MODE_DPMS_SUSPEND;
 | 
			
		||||
    break;
 | 
			
		||||
  default:
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < manager->n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *meta_output;
 | 
			
		||||
      MetaOutputKms *output_kms;
 | 
			
		||||
 | 
			
		||||
      meta_output = &manager->outputs[i];
 | 
			
		||||
      output_kms = meta_output->driver_private;
 | 
			
		||||
 | 
			
		||||
      if (output_kms->has_dpms_prop)
 | 
			
		||||
        {
 | 
			
		||||
          int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->output_id,
 | 
			
		||||
                                               output_kms->dpms_prop_id, state);
 | 
			
		||||
 | 
			
		||||
          if (ok < 0)
 | 
			
		||||
            meta_warning ("Failed to set power save mode for output %s: %s\n",
 | 
			
		||||
                          meta_output->name, strerror (errno));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
crtc_free (CoglKmsCrtc *crtc)
 | 
			
		||||
{
 | 
			
		||||
  g_free (crtc->connectors);
 | 
			
		||||
  g_slice_free (CoglKmsCrtc, crtc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
                                              MetaCRTCInfo       **crtcs,
 | 
			
		||||
                                              unsigned int         n_crtcs,
 | 
			
		||||
                                              MetaOutputInfo     **outputs,
 | 
			
		||||
                                              unsigned int         n_outputs)
 | 
			
		||||
{
 | 
			
		||||
  ClutterBackend *backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
  CoglDisplay *cogl_display;
 | 
			
		||||
  unsigned i;
 | 
			
		||||
  GPtrArray *cogl_crtcs;
 | 
			
		||||
  int screen_width, screen_height;
 | 
			
		||||
  gboolean ok;
 | 
			
		||||
  GError *error;
 | 
			
		||||
 | 
			
		||||
  cogl_crtcs = g_ptr_array_new_full (manager->n_crtcs, (GDestroyNotify)crtc_free);
 | 
			
		||||
  screen_width = 0; screen_height = 0;
 | 
			
		||||
  for (i = 0; i < n_crtcs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCRTCInfo *crtc_info = crtcs[i];
 | 
			
		||||
      MetaCRTC *crtc = crtc_info->crtc;
 | 
			
		||||
      CoglKmsCrtc *cogl_crtc;
 | 
			
		||||
 | 
			
		||||
      crtc->is_dirty = TRUE;
 | 
			
		||||
 | 
			
		||||
      cogl_crtc = g_slice_new0 (CoglKmsCrtc);
 | 
			
		||||
      g_ptr_array_add (cogl_crtcs, cogl_crtc);
 | 
			
		||||
 | 
			
		||||
      if (crtc_info->mode == NULL)
 | 
			
		||||
        {
 | 
			
		||||
          cogl_crtc->id = crtc->crtc_id;
 | 
			
		||||
          cogl_crtc->x = 0;
 | 
			
		||||
          cogl_crtc->y = 0;
 | 
			
		||||
          cogl_crtc->count = 0;
 | 
			
		||||
          memset (&cogl_crtc->mode, 0, sizeof (drmModeModeInfo));
 | 
			
		||||
          cogl_crtc->connectors = NULL;
 | 
			
		||||
          cogl_crtc->count = 0;
 | 
			
		||||
 | 
			
		||||
          crtc->rect.x = 0;
 | 
			
		||||
          crtc->rect.y = 0;
 | 
			
		||||
          crtc->rect.width = 0;
 | 
			
		||||
          crtc->rect.height = 0;
 | 
			
		||||
          crtc->current_mode = NULL;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          MetaMonitorMode *mode;
 | 
			
		||||
          uint32_t *outputs;
 | 
			
		||||
          unsigned int j, n_outputs;
 | 
			
		||||
          int width, height;
 | 
			
		||||
 | 
			
		||||
          mode = crtc_info->mode;
 | 
			
		||||
 | 
			
		||||
          cogl_crtc->id = crtc->crtc_id;
 | 
			
		||||
          cogl_crtc->x = crtc_info->x;
 | 
			
		||||
          cogl_crtc->y = crtc_info->y;
 | 
			
		||||
          cogl_crtc->count = n_outputs = crtc_info->outputs->len;
 | 
			
		||||
          cogl_crtc->connectors = outputs = g_new (uint32_t, n_outputs);
 | 
			
		||||
 | 
			
		||||
          for (j = 0; j < n_outputs; j++)
 | 
			
		||||
            {
 | 
			
		||||
              MetaOutput *output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
 | 
			
		||||
 | 
			
		||||
              outputs[j] = output->output_id;
 | 
			
		||||
 | 
			
		||||
              output->is_dirty = TRUE;
 | 
			
		||||
              output->crtc = crtc;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          memcpy (&cogl_crtc->mode, crtc_info->mode->driver_private,
 | 
			
		||||
                  sizeof (drmModeModeInfo));
 | 
			
		||||
 | 
			
		||||
          if (meta_monitor_transform_is_rotated (crtc_info->transform))
 | 
			
		||||
            {
 | 
			
		||||
              width = mode->height;
 | 
			
		||||
              height = mode->width;
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              width = mode->width;
 | 
			
		||||
              height = mode->height;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          screen_width = MAX (screen_width, crtc_info->x + width);
 | 
			
		||||
          screen_height = MAX (screen_height, crtc_info->y + height);
 | 
			
		||||
 | 
			
		||||
          crtc->rect.x = crtc_info->x;
 | 
			
		||||
          crtc->rect.y = crtc_info->y;
 | 
			
		||||
          crtc->rect.width = width;
 | 
			
		||||
          crtc->rect.height = height;
 | 
			
		||||
          crtc->current_mode = mode;
 | 
			
		||||
          crtc->transform = crtc_info->transform;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Disable CRTCs not mentioned in the list */
 | 
			
		||||
  for (i = 0; i < manager->n_crtcs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCRTC *crtc = &manager->crtcs[i];
 | 
			
		||||
      CoglKmsCrtc *cogl_crtc;
 | 
			
		||||
 | 
			
		||||
      crtc->logical_monitor = NULL;
 | 
			
		||||
 | 
			
		||||
      if (crtc->is_dirty)
 | 
			
		||||
        {
 | 
			
		||||
          crtc->is_dirty = FALSE;
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      cogl_crtc = g_slice_new0 (CoglKmsCrtc);
 | 
			
		||||
      g_ptr_array_add (cogl_crtcs, cogl_crtc);
 | 
			
		||||
 | 
			
		||||
      cogl_crtc->id = crtc->crtc_id;
 | 
			
		||||
      cogl_crtc->x = 0;
 | 
			
		||||
      cogl_crtc->y = 0;
 | 
			
		||||
      cogl_crtc->count = 0;
 | 
			
		||||
      memset (&cogl_crtc->mode, 0, sizeof (drmModeModeInfo));
 | 
			
		||||
      cogl_crtc->connectors = NULL;
 | 
			
		||||
      cogl_crtc->count = 0;
 | 
			
		||||
 | 
			
		||||
      crtc->rect.x = 0;
 | 
			
		||||
      crtc->rect.y = 0;
 | 
			
		||||
      crtc->rect.width = 0;
 | 
			
		||||
      crtc->rect.height = 0;
 | 
			
		||||
      crtc->current_mode = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  backend = clutter_get_default_backend ();
 | 
			
		||||
  cogl_context = clutter_backend_get_cogl_context (backend);
 | 
			
		||||
  cogl_display = cogl_context_get_display (cogl_context);
 | 
			
		||||
 | 
			
		||||
  error = NULL;
 | 
			
		||||
  ok = cogl_kms_display_set_layout (cogl_display, screen_width, screen_height,
 | 
			
		||||
                                    (CoglKmsCrtc**)cogl_crtcs->pdata, cogl_crtcs->len, &error);
 | 
			
		||||
  g_ptr_array_unref (cogl_crtcs);
 | 
			
		||||
 | 
			
		||||
  if (!ok)
 | 
			
		||||
    {
 | 
			
		||||
      meta_warning ("Applying display configuration failed: %s\n", error->message);
 | 
			
		||||
      g_error_free (error);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutputInfo *output_info = outputs[i];
 | 
			
		||||
      MetaOutput *output = output_info->output;
 | 
			
		||||
 | 
			
		||||
      output->is_primary = output_info->is_primary;
 | 
			
		||||
      output->is_presentation = output_info->is_presentation;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Disable outputs not mentioned in the list */
 | 
			
		||||
  for (i = 0; i < manager->n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *output = &manager->outputs[i];
 | 
			
		||||
 | 
			
		||||
      if (output->is_dirty)
 | 
			
		||||
        {
 | 
			
		||||
          output->is_dirty = FALSE;
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      output->crtc = NULL;
 | 
			
		||||
      output->is_primary = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  manager->screen_width = screen_width;
 | 
			
		||||
  manager->screen_height = screen_height;
 | 
			
		||||
 | 
			
		||||
  meta_monitor_manager_rebuild_derived (manager);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_kms_get_crtc_gamma (MetaMonitorManager  *manager,
 | 
			
		||||
                                         MetaCRTC            *crtc,
 | 
			
		||||
                                         gsize               *size,
 | 
			
		||||
                                         unsigned short     **red,
 | 
			
		||||
                                         unsigned short     **green,
 | 
			
		||||
                                         unsigned short     **blue)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
 | 
			
		||||
  drmModeCrtc *kms_crtc;
 | 
			
		||||
 | 
			
		||||
  kms_crtc = drmModeGetCrtc (manager_kms->fd, crtc->crtc_id);
 | 
			
		||||
 | 
			
		||||
  *size = kms_crtc->gamma_size;
 | 
			
		||||
  *red = g_new (unsigned short, *size);
 | 
			
		||||
  *green = g_new (unsigned short, *size);
 | 
			
		||||
  *blue = g_new (unsigned short, *size);
 | 
			
		||||
 | 
			
		||||
  drmModeCrtcGetGamma (manager_kms->fd, crtc->crtc_id, *size, *red, *green, *blue);
 | 
			
		||||
 | 
			
		||||
  drmModeFreeCrtc (kms_crtc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
 | 
			
		||||
                                         MetaCRTC           *crtc,
 | 
			
		||||
                                         gsize               size,
 | 
			
		||||
                                         unsigned short     *red,
 | 
			
		||||
                                         unsigned short     *green,
 | 
			
		||||
                                         unsigned short     *blue)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
 | 
			
		||||
 | 
			
		||||
  drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
 | 
			
		||||
{
 | 
			
		||||
  ClutterBackend *backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
  CoglDisplay *cogl_display;
 | 
			
		||||
  CoglRenderer *cogl_renderer;
 | 
			
		||||
 | 
			
		||||
  backend = clutter_get_default_backend ();
 | 
			
		||||
  cogl_context = clutter_backend_get_cogl_context (backend);
 | 
			
		||||
  cogl_display = cogl_context_get_display (cogl_context);
 | 
			
		||||
  cogl_renderer = cogl_display_get_renderer (cogl_display);
 | 
			
		||||
 | 
			
		||||
  manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_kms_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object);
 | 
			
		||||
  unsigned i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < manager_kms->n_encoders; i++)
 | 
			
		||||
    drmModeFreeEncoder (manager_kms->encoders[i]);
 | 
			
		||||
  for (i = 0; i < manager_kms->n_connectors; i++)
 | 
			
		||||
    drmModeFreeConnector (manager_kms->connectors[i]);
 | 
			
		||||
 | 
			
		||||
  g_free (manager_kms->encoders);
 | 
			
		||||
  g_free (manager_kms->connectors);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->finalize = meta_monitor_manager_kms_finalize;
 | 
			
		||||
 | 
			
		||||
  manager_class->read_current = meta_monitor_manager_kms_read_current;
 | 
			
		||||
  manager_class->read_edid = meta_monitor_manager_kms_read_edid;
 | 
			
		||||
  manager_class->apply_configuration = meta_monitor_manager_kms_apply_configuration;
 | 
			
		||||
  manager_class->set_power_save_mode = meta_monitor_manager_kms_set_power_save_mode;
 | 
			
		||||
  manager_class->get_crtc_gamma = meta_monitor_manager_kms_get_crtc_gamma;
 | 
			
		||||
  manager_class->set_crtc_gamma = meta_monitor_manager_kms_set_crtc_gamma;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -116,6 +116,9 @@ struct _MetaOutput
 | 
			
		||||
  */
 | 
			
		||||
  gboolean is_primary;
 | 
			
		||||
  gboolean is_presentation;
 | 
			
		||||
 | 
			
		||||
  gpointer driver_private;
 | 
			
		||||
  GDestroyNotify driver_notify;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaCRTC
 | 
			
		||||
@@ -139,10 +142,14 @@ struct _MetaMonitorMode
 | 
			
		||||
{
 | 
			
		||||
  /* The low-level ID of this mode, used to apply back configuration */
 | 
			
		||||
  glong mode_id;
 | 
			
		||||
  char *name;
 | 
			
		||||
 | 
			
		||||
  int width;
 | 
			
		||||
  int height;
 | 
			
		||||
  float refresh_rate;
 | 
			
		||||
 | 
			
		||||
  gpointer driver_private;
 | 
			
		||||
  GDestroyNotify driver_notify;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -351,6 +358,18 @@ typedef struct _MetaMonitorManagerXrandr         MetaMonitorManagerXrandr;
 | 
			
		||||
 | 
			
		||||
GType meta_monitor_manager_xrandr_get_type (void);
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_MONITOR_MANAGER_KMS            (meta_monitor_manager_kms_get_type ())
 | 
			
		||||
#define META_MONITOR_MANAGER_KMS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKms))
 | 
			
		||||
#define META_MONITOR_MANAGER_KMS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
 | 
			
		||||
#define META_IS_MONITOR_MANAGER_KMS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_KMS))
 | 
			
		||||
#define META_IS_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_MONITOR_MANAGER_KMS))
 | 
			
		||||
#define META_MONITOR_MANAGER_KMS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaMonitorManagerKmsClass    MetaMonitorManagerKmsClass;
 | 
			
		||||
typedef struct _MetaMonitorManagerKms         MetaMonitorManagerKms;
 | 
			
		||||
 | 
			
		||||
GType meta_monitor_manager_kms_get_type (void);
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_MONITOR_CONFIG            (meta_monitor_config_get_type ())
 | 
			
		||||
#define META_MONITOR_CONFIG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
 | 
			
		||||
#define META_MONITOR_CONFIG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
 | 
			
		||||
@@ -383,6 +402,8 @@ void               meta_output_info_free (MetaOutputInfo *info);
 | 
			
		||||
 | 
			
		||||
void               meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
 | 
			
		||||
                                                           int         n_old_outputs);
 | 
			
		||||
void               meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
 | 
			
		||||
                                                         int              n_old_modes);
 | 
			
		||||
 | 
			
		||||
/* Returns true if transform causes width and height to be inverted
 | 
			
		||||
   This is true for the odd transforms in the enum */
 | 
			
		||||
 
 | 
			
		||||
@@ -977,7 +977,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
 | 
			
		||||
  MetaOutput *old_outputs;
 | 
			
		||||
  MetaCRTC *old_crtcs;
 | 
			
		||||
  MetaMonitorMode *old_modes;
 | 
			
		||||
  int n_old_outputs;
 | 
			
		||||
  unsigned int n_old_outputs, n_old_modes;
 | 
			
		||||
 | 
			
		||||
  if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
@@ -988,6 +988,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
 | 
			
		||||
  old_outputs = manager->outputs;
 | 
			
		||||
  n_old_outputs = manager->n_outputs;
 | 
			
		||||
  old_modes = manager->modes;
 | 
			
		||||
  n_old_modes = manager->n_modes;
 | 
			
		||||
  old_crtcs = manager->crtcs;
 | 
			
		||||
 | 
			
		||||
  manager->serial++;
 | 
			
		||||
@@ -1022,7 +1023,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
 | 
			
		||||
  g_free (old_modes);
 | 
			
		||||
  meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
 | 
			
		||||
  g_free (old_crtcs);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,7 @@
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "monitor-private.h"
 | 
			
		||||
#include "meta-wayland-private.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-dbus-xrandr.h"
 | 
			
		||||
 | 
			
		||||
@@ -358,7 +359,16 @@ static GType
 | 
			
		||||
get_default_backend (void)
 | 
			
		||||
{
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    return META_TYPE_MONITOR_MANAGER; /* FIXME: KMS */
 | 
			
		||||
    {
 | 
			
		||||
      MetaWaylandCompositor *compositor;
 | 
			
		||||
 | 
			
		||||
      compositor = meta_wayland_compositor_get_default ();
 | 
			
		||||
 | 
			
		||||
      if (meta_wayland_compositor_is_native (compositor))
 | 
			
		||||
        return META_TYPE_MONITOR_MANAGER_KMS;
 | 
			
		||||
      else
 | 
			
		||||
        return META_TYPE_MONITOR_MANAGER;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    return META_TYPE_MONITOR_MANAGER_XRANDR;
 | 
			
		||||
}
 | 
			
		||||
@@ -407,17 +417,18 @@ meta_monitor_manager_constructed (GObject *object)
 | 
			
		||||
      MetaOutput *old_outputs;
 | 
			
		||||
      MetaCRTC *old_crtcs;
 | 
			
		||||
      MetaMonitorMode *old_modes;
 | 
			
		||||
      int n_old_outputs;
 | 
			
		||||
      unsigned int n_old_outputs, n_old_modes;
 | 
			
		||||
 | 
			
		||||
      old_outputs = manager->outputs;
 | 
			
		||||
      n_old_outputs = manager->n_outputs;
 | 
			
		||||
      old_modes = manager->modes;
 | 
			
		||||
      n_old_modes = manager->n_modes;
 | 
			
		||||
      old_crtcs = manager->crtcs;
 | 
			
		||||
 | 
			
		||||
      read_current_config (manager);
 | 
			
		||||
 | 
			
		||||
      meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
 | 
			
		||||
      g_free (old_modes);
 | 
			
		||||
      meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
 | 
			
		||||
      g_free (old_crtcs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -462,19 +473,39 @@ meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
 | 
			
		||||
      g_free (old_outputs[i].modes);
 | 
			
		||||
      g_free (old_outputs[i].possible_crtcs);
 | 
			
		||||
      g_free (old_outputs[i].possible_clones);
 | 
			
		||||
 | 
			
		||||
      if (old_outputs[i].driver_notify)
 | 
			
		||||
        old_outputs[i].driver_notify (&old_outputs[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_free (old_outputs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
 | 
			
		||||
                                      int              n_old_modes)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_old_modes; i++)
 | 
			
		||||
    {
 | 
			
		||||
      g_free (old_modes[i].name);
 | 
			
		||||
 | 
			
		||||
      if (old_modes[i].driver_notify)
 | 
			
		||||
        old_modes[i].driver_notify (&old_modes[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_free (old_modes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
 | 
			
		||||
 | 
			
		||||
  meta_monitor_manager_free_output_array (manager->outputs, manager->n_outputs);
 | 
			
		||||
  meta_monitor_manager_free_mode_array (manager->modes, manager->n_modes);
 | 
			
		||||
  g_free (manager->monitor_infos);
 | 
			
		||||
  g_free (manager->modes);
 | 
			
		||||
  g_free (manager->crtcs);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object);
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,8 @@
 | 
			
		||||
 | 
			
		||||
#include <config.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include "session.h"
 | 
			
		||||
#include <X11/Xatom.h>
 | 
			
		||||
 | 
			
		||||
@@ -531,6 +533,12 @@ die_callback (SmcConn smc_conn, SmPointer client_data)
 | 
			
		||||
   * Anything that wants us to go away outside of session management
 | 
			
		||||
   * can use kill().
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  /* All of that is true - unless we're a wayland compositor. In which
 | 
			
		||||
   * case the X server won't go down until we do, so we must die first.
 | 
			
		||||
   */
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    meta_quit (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,7 @@
 | 
			
		||||
#include <X11/Xutil.h>
 | 
			
		||||
#include <cairo.h>
 | 
			
		||||
#include <gdk-pixbuf/gdk-pixbuf.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include "meta-wayland-types.h"
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaWindowQueue MetaWindowQueue;
 | 
			
		||||
@@ -127,6 +128,7 @@ struct _MetaWindow
 | 
			
		||||
  Window xtransient_for;
 | 
			
		||||
  Window xgroup_leader;
 | 
			
		||||
  Window xclient_leader;
 | 
			
		||||
  MetaWindow *transient_for;
 | 
			
		||||
 | 
			
		||||
  /* Initial workspace property */
 | 
			
		||||
  int initial_workspace;  
 | 
			
		||||
@@ -403,6 +405,12 @@ struct _MetaWindow
 | 
			
		||||
   */
 | 
			
		||||
  MetaRectangle rect;
 | 
			
		||||
 | 
			
		||||
  /* The size we want the window to be (i.e. what we last asked
 | 
			
		||||
   * the client to configure).
 | 
			
		||||
   * This is only used for wayland clients.
 | 
			
		||||
   */
 | 
			
		||||
  MetaRectangle expected_rect;
 | 
			
		||||
 | 
			
		||||
  gboolean has_custom_frame_extents;
 | 
			
		||||
  GtkBorder custom_frame_extents;
 | 
			
		||||
 | 
			
		||||
@@ -600,6 +608,11 @@ void     meta_window_move_resize_request(MetaWindow *window,
 | 
			
		||||
                                         int         y,
 | 
			
		||||
                                         int         width,
 | 
			
		||||
                                         int         height);
 | 
			
		||||
void     meta_window_move_resize_wayland (MetaWindow *window,
 | 
			
		||||
                                          int         width,
 | 
			
		||||
                                          int         height,
 | 
			
		||||
                                          int         dx,
 | 
			
		||||
                                          int         dy);
 | 
			
		||||
gboolean meta_window_configure_request (MetaWindow *window,
 | 
			
		||||
                                        XEvent     *event);
 | 
			
		||||
gboolean meta_window_property_notify   (MetaWindow *window,
 | 
			
		||||
@@ -630,8 +643,8 @@ void meta_window_update_sync_request_counter (MetaWindow *window,
 | 
			
		||||
                                              gint64      new_counter_value);
 | 
			
		||||
#endif /* HAVE_XSYNC */
 | 
			
		||||
 | 
			
		||||
void meta_window_handle_mouse_grab_op_event (MetaWindow *window,
 | 
			
		||||
                                             XIDeviceEvent *xev);
 | 
			
		||||
void meta_window_handle_mouse_grab_op_event (MetaWindow         *window,
 | 
			
		||||
                                             const ClutterEvent *event);
 | 
			
		||||
 | 
			
		||||
GList* meta_window_get_workspaces (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
@@ -716,4 +729,7 @@ void meta_window_set_gtk_dbus_properties  (MetaWindow *window,
 | 
			
		||||
                                           const char *application_object_path,
 | 
			
		||||
                                           const char *window_object_path);
 | 
			
		||||
 | 
			
		||||
void meta_window_set_transient_for        (MetaWindow *window,
 | 
			
		||||
                                           MetaWindow *parent);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1554,9 +1554,6 @@ reload_transient_for (MetaWindow    *window,
 | 
			
		||||
  if (transient_for == window->xtransient_for)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (meta_window_appears_focused (window) && window->xtransient_for != None)
 | 
			
		||||
    meta_window_propagate_focus_appearance (window, FALSE);
 | 
			
		||||
 | 
			
		||||
  old_transient_for = window->xtransient_for;
 | 
			
		||||
  window->xtransient_for = transient_for;
 | 
			
		||||
 | 
			
		||||
@@ -1569,46 +1566,14 @@ reload_transient_for (MetaWindow    *window,
 | 
			
		||||
  else
 | 
			
		||||
    meta_verbose ("Window %s is not transient\n", window->desc);
 | 
			
		||||
 | 
			
		||||
  /* may now be a dialog */
 | 
			
		||||
  meta_window_recalc_window_type (window);
 | 
			
		||||
 | 
			
		||||
  if (!window->constructing)
 | 
			
		||||
  if (window->transient_parent_is_root_window || window->xtransient_for == None)
 | 
			
		||||
    meta_window_set_transient_for (window, NULL);
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      /* If the window attaches, detaches, or changes attached
 | 
			
		||||
       * parents, we need to destroy the MetaWindow and let a new one
 | 
			
		||||
       * be created (which happens as a side effect of
 | 
			
		||||
       * meta_window_unmanage()). The condition below is correct
 | 
			
		||||
       * because we know window->xtransient_for has changed.
 | 
			
		||||
       */
 | 
			
		||||
      if (window->attached || meta_window_should_attach_to_parent (window))
 | 
			
		||||
        {
 | 
			
		||||
          guint32 timestamp;
 | 
			
		||||
 | 
			
		||||
          window->xtransient_for = old_transient_for;
 | 
			
		||||
          timestamp = meta_display_get_current_time_roundtrip (window->display);
 | 
			
		||||
          meta_window_unmanage (window, timestamp);
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
      parent = meta_display_lookup_x_window (window->display,
 | 
			
		||||
                                             window->xtransient_for);
 | 
			
		||||
      meta_window_set_transient_for (window, parent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* update stacking constraints */
 | 
			
		||||
  if (!window->override_redirect)
 | 
			
		||||
    meta_stack_update_transient (window->screen->stack, window);
 | 
			
		||||
 | 
			
		||||
  /* possibly change its group. We treat being a window's transient as
 | 
			
		||||
   * equivalent to making it your group leader, to work around shortcomings
 | 
			
		||||
   * in programs such as xmms-- see #328211.
 | 
			
		||||
   */
 | 
			
		||||
  if (window->xtransient_for != None &&
 | 
			
		||||
      window->xgroup_leader != None &&
 | 
			
		||||
      window->xtransient_for != window->xgroup_leader)
 | 
			
		||||
    meta_window_group_leader_changed (window);
 | 
			
		||||
 | 
			
		||||
  if (!window->constructing && !window->override_redirect)
 | 
			
		||||
    meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
 | 
			
		||||
 | 
			
		||||
  if (meta_window_appears_focused (window) && window->xtransient_for != None)
 | 
			
		||||
    meta_window_propagate_focus_appearance (window, TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -536,6 +536,81 @@ meta_prop_get_utf8_list (MetaDisplay   *display,
 | 
			
		||||
  return utf8_list_from_results (&results, str_p, n_str_p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* this one freakishly returns g_malloc memory */
 | 
			
		||||
static gboolean
 | 
			
		||||
latin1_list_from_results (GetPropertyResults *results,
 | 
			
		||||
                        char             ***str_p,
 | 
			
		||||
                        int                *n_str_p)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
  int n_strings;
 | 
			
		||||
  char **retval;
 | 
			
		||||
  const char *p;
 | 
			
		||||
  
 | 
			
		||||
  *str_p = NULL;
 | 
			
		||||
  *n_str_p = 0;
 | 
			
		||||
 | 
			
		||||
  if (!validate_or_free_results (results, 8, XA_STRING, FALSE))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  
 | 
			
		||||
  /* I'm not sure this is right, but I'm guessing the
 | 
			
		||||
   * property is nul-separated
 | 
			
		||||
   */
 | 
			
		||||
  i = 0;
 | 
			
		||||
  n_strings = 0;
 | 
			
		||||
  while (i < (int) results->n_items)
 | 
			
		||||
    {
 | 
			
		||||
      if (results->prop[i] == '\0')
 | 
			
		||||
        ++n_strings;
 | 
			
		||||
      ++i;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (results->prop[results->n_items - 1] != '\0')
 | 
			
		||||
    ++n_strings;
 | 
			
		||||
 
 | 
			
		||||
  /* we're guaranteed that results->prop has a nul on the end
 | 
			
		||||
   * by XGetWindowProperty
 | 
			
		||||
   */
 | 
			
		||||
  
 | 
			
		||||
  retval = g_new0 (char*, n_strings + 1);
 | 
			
		||||
 | 
			
		||||
  p = (char *)results->prop;
 | 
			
		||||
  i = 0;
 | 
			
		||||
  while (i < n_strings)
 | 
			
		||||
    {
 | 
			
		||||
      retval[i] = g_strdup (p);
 | 
			
		||||
      
 | 
			
		||||
      p = p + strlen (p) + 1;
 | 
			
		||||
      ++i;
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  *str_p = retval;
 | 
			
		||||
  *n_str_p = i;
 | 
			
		||||
 | 
			
		||||
  meta_XFree (results->prop);
 | 
			
		||||
  results->prop = NULL;
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_prop_get_latin1_list (MetaDisplay   *display,
 | 
			
		||||
                           Window         xwindow,
 | 
			
		||||
                           Atom           xatom,
 | 
			
		||||
                           char        ***str_p,
 | 
			
		||||
                           int           *n_str_p)
 | 
			
		||||
{
 | 
			
		||||
  GetPropertyResults results;
 | 
			
		||||
 | 
			
		||||
  *str_p = NULL;
 | 
			
		||||
 | 
			
		||||
  if (!get_property (display, xwindow, xatom,
 | 
			
		||||
                     XA_STRING, &results))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  return latin1_list_from_results (&results, str_p, n_str_p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_prop_set_utf8_string_hint (MetaDisplay *display,
 | 
			
		||||
                                Window xwindow,
 | 
			
		||||
 
 | 
			
		||||
@@ -102,6 +102,11 @@ gboolean meta_prop_get_utf8_list     (MetaDisplay   *display,
 | 
			
		||||
                                      Atom           xatom,
 | 
			
		||||
                                      char        ***str_p,
 | 
			
		||||
                                      int           *n_str_p);
 | 
			
		||||
gboolean meta_prop_get_latin1_list   (MetaDisplay   *display,
 | 
			
		||||
                                      Window         xwindow,
 | 
			
		||||
                                      Atom           xatom,
 | 
			
		||||
                                      char        ***str_p,
 | 
			
		||||
                                      int           *n_str_p);
 | 
			
		||||
void     meta_prop_set_utf8_string_hint
 | 
			
		||||
                                     (MetaDisplay *display,
 | 
			
		||||
                                      Window xwindow,
 | 
			
		||||
 
 | 
			
		||||
@@ -81,6 +81,7 @@ item(TIMESTAMP)
 | 
			
		||||
item(VERSION)
 | 
			
		||||
item(ATOM_PAIR)
 | 
			
		||||
item(BACKLIGHT)
 | 
			
		||||
item(_XKB_RULES_NAMES)
 | 
			
		||||
 | 
			
		||||
/* Oddities: These are used, and we need atoms for them,
 | 
			
		||||
 * but when we need all _NET_WM hints (i.e. when we're making
 | 
			
		||||
 
 | 
			
		||||
@@ -106,11 +106,49 @@ create_anonymous_file (off_t size,
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_wayland_xkb_info_new_keymap (MetaWaylandXkbInfo *xkb_info)
 | 
			
		||||
static void
 | 
			
		||||
inform_clients_of_new_keymap (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
			      int                  flags)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandCompositor *compositor;
 | 
			
		||||
  struct wl_client *xclient;
 | 
			
		||||
  struct wl_resource *keyboard_resource;
 | 
			
		||||
 | 
			
		||||
  compositor = meta_wayland_compositor_get_default ();
 | 
			
		||||
  xclient = compositor->xwayland_client;
 | 
			
		||||
 | 
			
		||||
  wl_resource_for_each (keyboard_resource, &keyboard->resource_list)
 | 
			
		||||
    {
 | 
			
		||||
      if ((flags & META_WAYLAND_KEYBOARD_SKIP_XCLIENTS) &&
 | 
			
		||||
	  wl_resource_get_client (keyboard_resource) == xclient)
 | 
			
		||||
	continue;
 | 
			
		||||
 | 
			
		||||
      wl_keyboard_send_keymap (keyboard_resource,
 | 
			
		||||
			       WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
 | 
			
		||||
			       keyboard->xkb_info.keymap_fd,
 | 
			
		||||
			       keyboard->xkb_info.keymap_size);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
				   struct xkb_keymap   *keymap,
 | 
			
		||||
				   int                  flags)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandXkbInfo  *xkb_info = &keyboard->xkb_info;
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
  char *keymap_str;
 | 
			
		||||
  size_t previous_size;
 | 
			
		||||
 | 
			
		||||
  if (keymap == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Attempting to set null keymap (compilation probably failed)");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (xkb_info->keymap)
 | 
			
		||||
    xkb_keymap_unref (xkb_info->keymap);
 | 
			
		||||
  xkb_info->keymap = keymap;
 | 
			
		||||
 | 
			
		||||
  xkb_info->shift_mod =
 | 
			
		||||
    xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_SHIFT);
 | 
			
		||||
@@ -129,21 +167,28 @@ meta_wayland_xkb_info_new_keymap (MetaWaylandXkbInfo *xkb_info)
 | 
			
		||||
  keymap_str = xkb_map_get_as_string (xkb_info->keymap);
 | 
			
		||||
  if (keymap_str == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("failed to get string version of keymap\n");
 | 
			
		||||
      return FALSE;
 | 
			
		||||
      g_warning ("failed to get string version of keymap");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  previous_size = xkb_info->keymap_size;
 | 
			
		||||
  xkb_info->keymap_size = strlen (keymap_str) + 1;
 | 
			
		||||
 | 
			
		||||
  if (xkb_info->keymap_fd >= 0)
 | 
			
		||||
    close (xkb_info->keymap_fd);
 | 
			
		||||
 | 
			
		||||
  xkb_info->keymap_fd = create_anonymous_file (xkb_info->keymap_size, &error);
 | 
			
		||||
  if (xkb_info->keymap_fd < 0)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("creating a keymap file for %lu bytes failed: %s\n",
 | 
			
		||||
      g_warning ("creating a keymap file for %lu bytes failed: %s",
 | 
			
		||||
                 (unsigned long) xkb_info->keymap_size,
 | 
			
		||||
                 error->message);
 | 
			
		||||
      g_clear_error (&error);
 | 
			
		||||
      goto err_keymap_str;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (xkb_info->keymap_area)
 | 
			
		||||
    munmap (xkb_info->keymap_area, previous_size);
 | 
			
		||||
 | 
			
		||||
  xkb_info->keymap_area = mmap (NULL, xkb_info->keymap_size,
 | 
			
		||||
                                PROT_READ | PROT_WRITE,
 | 
			
		||||
                                MAP_SHARED, xkb_info->keymap_fd, 0);
 | 
			
		||||
@@ -156,41 +201,24 @@ meta_wayland_xkb_info_new_keymap (MetaWaylandXkbInfo *xkb_info)
 | 
			
		||||
  strcpy (xkb_info->keymap_area, keymap_str);
 | 
			
		||||
  free (keymap_str);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
  if (keyboard->is_evdev)
 | 
			
		||||
    {
 | 
			
		||||
      ClutterDeviceManager *manager;
 | 
			
		||||
 | 
			
		||||
      manager = clutter_device_manager_get_default ();
 | 
			
		||||
      clutter_evdev_set_keyboard_map (manager, xkb_info->keymap);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  inform_clients_of_new_keymap (keyboard, flags);
 | 
			
		||||
 | 
			
		||||
  return;
 | 
			
		||||
 | 
			
		||||
err_dev_zero:
 | 
			
		||||
  close (xkb_info->keymap_fd);
 | 
			
		||||
  xkb_info->keymap_fd = -1;
 | 
			
		||||
err_keymap_str:
 | 
			
		||||
  free (keymap_str);
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_wayland_keyboard_build_global_keymap (struct xkb_context *xkb_context,
 | 
			
		||||
                                           struct xkb_rule_names *xkb_names,
 | 
			
		||||
                                           MetaWaylandXkbInfo *xkb_info)
 | 
			
		||||
{
 | 
			
		||||
  xkb_info->keymap = xkb_map_new_from_names (xkb_context,
 | 
			
		||||
                                             xkb_names,
 | 
			
		||||
                                             0 /* flags */);
 | 
			
		||||
  if (xkb_info->keymap == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("failed to compile global XKB keymap\n"
 | 
			
		||||
                 "  tried rules %s, model %s, layout %s, variant %s, "
 | 
			
		||||
                 "options %s\n",
 | 
			
		||||
                 xkb_names->rules,
 | 
			
		||||
                 xkb_names->model,
 | 
			
		||||
                 xkb_names->layout,
 | 
			
		||||
                 xkb_names->variant,
 | 
			
		||||
                 xkb_names->options);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!meta_wayland_xkb_info_new_keymap (xkb_info))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
  return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -202,7 +230,7 @@ lose_keyboard_focus (struct wl_listener *listener, void *data)
 | 
			
		||||
  keyboard->focus_resource = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
static gboolean
 | 
			
		||||
default_grab_key (MetaWaylandKeyboardGrab *grab,
 | 
			
		||||
                  uint32_t time, uint32_t key, uint32_t state)
 | 
			
		||||
{
 | 
			
		||||
@@ -218,6 +246,8 @@ default_grab_key (MetaWaylandKeyboardGrab *grab,
 | 
			
		||||
      serial = wl_display_next_serial (display);
 | 
			
		||||
      wl_keyboard_send_key (resource, serial, time, key, state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return resource != NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct wl_resource *
 | 
			
		||||
@@ -274,12 +304,14 @@ static const MetaWaylandKeyboardGrabInterface
 | 
			
		||||
  default_grab_modifiers,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
static gboolean
 | 
			
		||||
modal_key (MetaWaylandKeyboardGrab *grab,
 | 
			
		||||
	   uint32_t                 time,
 | 
			
		||||
	   uint32_t                 key,
 | 
			
		||||
	   uint32_t                 state)
 | 
			
		||||
{
 | 
			
		||||
  /* FALSE means: let the event through to clutter */
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -302,9 +334,8 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
                            struct wl_display   *display,
 | 
			
		||||
			    gboolean             is_evdev)
 | 
			
		||||
{
 | 
			
		||||
  ClutterDeviceManager *manager;
 | 
			
		||||
 | 
			
		||||
  memset (keyboard, 0, sizeof *keyboard);
 | 
			
		||||
  keyboard->xkb_info.keymap_fd = -1;
 | 
			
		||||
 | 
			
		||||
  wl_list_init (&keyboard->resource_list);
 | 
			
		||||
  wl_array_init (&keyboard->keys);
 | 
			
		||||
@@ -317,24 +348,15 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
  keyboard->display = display;
 | 
			
		||||
 | 
			
		||||
  keyboard->xkb_context = xkb_context_new (0 /* flags */);
 | 
			
		||||
 | 
			
		||||
  meta_wayland_keyboard_build_global_keymap (keyboard->xkb_context,
 | 
			
		||||
					     &keyboard->xkb_names,
 | 
			
		||||
					     &keyboard->xkb_info);
 | 
			
		||||
 | 
			
		||||
  keyboard->is_evdev = is_evdev;
 | 
			
		||||
  if (is_evdev)
 | 
			
		||||
    {
 | 
			
		||||
      manager = clutter_device_manager_get_default ();
 | 
			
		||||
 | 
			
		||||
      clutter_evdev_set_keyboard_map (manager, keyboard->xkb_info.keymap);
 | 
			
		||||
      keyboard->xkb_state = clutter_evdev_get_keyboard_state (manager);
 | 
			
		||||
      xkb_state_ref (keyboard->xkb_state);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      keyboard->xkb_state = xkb_state_new (keyboard->xkb_info.keymap);
 | 
			
		||||
    }
 | 
			
		||||
  /* Compute a default until gnome-settings-daemon starts and sets
 | 
			
		||||
     the appropriate values
 | 
			
		||||
  */
 | 
			
		||||
  meta_wayland_keyboard_set_keymap_names (keyboard,
 | 
			
		||||
					  "evdev",
 | 
			
		||||
					  "pc105",
 | 
			
		||||
					  "us", "", "", 0);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
@@ -351,52 +373,6 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
 | 
			
		||||
    close (xkb_info->keymap_fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_state_from_clutter (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
			   ClutterModifierType  modifier_state)
 | 
			
		||||
{
 | 
			
		||||
  uint32_t depressed_mods = 0;
 | 
			
		||||
  uint32_t locked_mods = 0;
 | 
			
		||||
 | 
			
		||||
  if ((modifier_state & CLUTTER_SHIFT_MASK) &&
 | 
			
		||||
      keyboard->xkb_info.shift_mod != XKB_MOD_INVALID)
 | 
			
		||||
    depressed_mods |= (1 << keyboard->xkb_info.shift_mod);
 | 
			
		||||
 | 
			
		||||
  if ((modifier_state & CLUTTER_LOCK_MASK) &&
 | 
			
		||||
      keyboard->xkb_info.caps_mod != XKB_MOD_INVALID)
 | 
			
		||||
    locked_mods |= (1 << keyboard->xkb_info.caps_mod);
 | 
			
		||||
 | 
			
		||||
  if ((modifier_state & CLUTTER_CONTROL_MASK) &&
 | 
			
		||||
      keyboard->xkb_info.ctrl_mod != XKB_MOD_INVALID)
 | 
			
		||||
    depressed_mods |= (1 << keyboard->xkb_info.ctrl_mod);
 | 
			
		||||
 | 
			
		||||
  if ((modifier_state & CLUTTER_MOD1_MASK) &&
 | 
			
		||||
      keyboard->xkb_info.alt_mod != XKB_MOD_INVALID)
 | 
			
		||||
    depressed_mods |= (1 << keyboard->xkb_info.alt_mod);
 | 
			
		||||
 | 
			
		||||
  if ((modifier_state & CLUTTER_MOD2_MASK) &&
 | 
			
		||||
      keyboard->xkb_info.mod2_mod != XKB_MOD_INVALID)
 | 
			
		||||
    depressed_mods |= (1 << keyboard->xkb_info.mod2_mod);
 | 
			
		||||
 | 
			
		||||
  if ((modifier_state & CLUTTER_MOD3_MASK) &&
 | 
			
		||||
      keyboard->xkb_info.mod3_mod != XKB_MOD_INVALID)
 | 
			
		||||
    depressed_mods |= (1 << keyboard->xkb_info.mod3_mod);
 | 
			
		||||
 | 
			
		||||
  if ((modifier_state & CLUTTER_SUPER_MASK) &&
 | 
			
		||||
      keyboard->xkb_info.super_mod != XKB_MOD_INVALID)
 | 
			
		||||
    depressed_mods |= (1 << keyboard->xkb_info.super_mod);
 | 
			
		||||
 | 
			
		||||
  if ((modifier_state & CLUTTER_MOD5_MASK) &&
 | 
			
		||||
      keyboard->xkb_info.mod5_mod != XKB_MOD_INVALID)
 | 
			
		||||
    depressed_mods |= (1 << keyboard->xkb_info.mod5_mod);
 | 
			
		||||
 | 
			
		||||
  xkb_state_update_mask (keyboard->xkb_state,
 | 
			
		||||
			 depressed_mods,
 | 
			
		||||
			 0,
 | 
			
		||||
			 locked_mods,
 | 
			
		||||
			 0, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
state_equal (MetaWaylandXkbState *one,
 | 
			
		||||
	     MetaWaylandXkbState *two)
 | 
			
		||||
@@ -409,25 +385,20 @@ state_equal (MetaWaylandXkbState *one,
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_modifiers (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
               guint32 serial,
 | 
			
		||||
               ClutterModifierType modifier_state)
 | 
			
		||||
               guint32              serial,
 | 
			
		||||
               ClutterEvent        *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandKeyboardGrab *grab = keyboard->grab;
 | 
			
		||||
  MetaWaylandXkbState new_state;
 | 
			
		||||
  guint effective_state;
 | 
			
		||||
 | 
			
		||||
  /* In the evdev case, the state is shared with the clutter backend, so
 | 
			
		||||
     we don't need to update it */
 | 
			
		||||
  if (!keyboard->is_evdev)
 | 
			
		||||
    update_state_from_clutter (keyboard, modifier_state);
 | 
			
		||||
 | 
			
		||||
  new_state.mods_depressed = xkb_state_serialize_mods (keyboard->xkb_state,
 | 
			
		||||
						       XKB_STATE_MODS_DEPRESSED);
 | 
			
		||||
  new_state.mods_latched = xkb_state_serialize_mods (keyboard->xkb_state,
 | 
			
		||||
						     XKB_STATE_MODS_LATCHED);
 | 
			
		||||
  new_state.mods_locked = xkb_state_serialize_mods (keyboard->xkb_state,
 | 
			
		||||
						    XKB_STATE_MODS_LOCKED);
 | 
			
		||||
  new_state.group = xkb_state_serialize_layout (keyboard->xkb_state,
 | 
			
		||||
						XKB_STATE_LAYOUT_EFFECTIVE);
 | 
			
		||||
  clutter_event_get_state_full (event,
 | 
			
		||||
				NULL,
 | 
			
		||||
				&new_state.mods_depressed,
 | 
			
		||||
				&new_state.mods_latched,
 | 
			
		||||
				&new_state.mods_locked,
 | 
			
		||||
				&effective_state);
 | 
			
		||||
  new_state.group = (effective_state >> 13) & 0x3;
 | 
			
		||||
 | 
			
		||||
  if (state_equal (&keyboard->modifier_state, &new_state))
 | 
			
		||||
    return;
 | 
			
		||||
@@ -442,36 +413,101 @@ set_modifiers (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
                              new_state.group);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
                                    const ClutterKeyEvent *event)
 | 
			
		||||
#define N_BUTTONS 5
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
process_keybinding (MetaWaylandKeyboard   *keyboard,
 | 
			
		||||
		    const ClutterEvent    *event)
 | 
			
		||||
{
 | 
			
		||||
  gboolean state = event->type == CLUTTER_KEY_PRESS;
 | 
			
		||||
  guint evdev_code;
 | 
			
		||||
  uint32_t serial;
 | 
			
		||||
  MetaWaylandSurface *surface;
 | 
			
		||||
  XGenericEventCookie generic_event;
 | 
			
		||||
  XIDeviceEvent device_event;
 | 
			
		||||
  unsigned char button_mask[(N_BUTTONS + 7) / 8] = { 0 };
 | 
			
		||||
  MetaDisplay *display = meta_get_display ();
 | 
			
		||||
  ClutterModifierType button_state;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  /* We can't do anything with the event if we can't get an evdev
 | 
			
		||||
     keycode for it */
 | 
			
		||||
  if (event->device == NULL ||
 | 
			
		||||
      !clutter_input_device_keycode_to_evdev (event->device,
 | 
			
		||||
                                              event->hardware_keycode,
 | 
			
		||||
                                              &evdev_code))
 | 
			
		||||
    return;
 | 
			
		||||
  if (!display) /* not initialized yet */
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  /* We want to ignore events that are sent because of auto-repeat. In
 | 
			
		||||
     the Clutter event stream these appear as a single key press
 | 
			
		||||
     event. We can detect that because the key will already have been
 | 
			
		||||
     pressed */
 | 
			
		||||
  if (state)
 | 
			
		||||
  generic_event.type = GenericEvent;
 | 
			
		||||
  generic_event.serial = 0;
 | 
			
		||||
  generic_event.send_event = False;
 | 
			
		||||
  generic_event.display = display->xdisplay;
 | 
			
		||||
  generic_event.extension = display->xinput_opcode;
 | 
			
		||||
  if (clutter_event_type (event) == CLUTTER_KEY_PRESS)
 | 
			
		||||
    generic_event.evtype = XI_KeyPress;
 | 
			
		||||
  else
 | 
			
		||||
    generic_event.evtype = XI_KeyRelease;
 | 
			
		||||
  /* Mutter assumes the data for the event is already retrieved by GDK
 | 
			
		||||
   * so we don't need the cookie */
 | 
			
		||||
  generic_event.cookie = 0;
 | 
			
		||||
  generic_event.data = &device_event;
 | 
			
		||||
 | 
			
		||||
  memcpy (&device_event, &generic_event, sizeof (XGenericEvent));
 | 
			
		||||
 | 
			
		||||
  /* Can't use clutter_event_get_time() here, because evdev timestamps
 | 
			
		||||
     have nothing to do with X timestamps */
 | 
			
		||||
  device_event.time = meta_display_get_current_time_roundtrip (display);
 | 
			
		||||
  device_event.deviceid = clutter_event_get_device_id (event);
 | 
			
		||||
  device_event.sourceid = 0; /* not used, not sure what this should be */
 | 
			
		||||
  device_event.detail = clutter_event_get_key_code (event);
 | 
			
		||||
  device_event.root = DefaultRootWindow (display->xdisplay);
 | 
			
		||||
  device_event.flags = 0;
 | 
			
		||||
 | 
			
		||||
  surface = keyboard->focus;
 | 
			
		||||
  if (surface)
 | 
			
		||||
    device_event.event = surface->window ? surface->window->xwindow : device_event.root;
 | 
			
		||||
  else
 | 
			
		||||
    device_event.event = device_event.root;
 | 
			
		||||
 | 
			
		||||
  /* Mutter doesn't really know about the sub-windows. This assumes it
 | 
			
		||||
     doesn't care either */
 | 
			
		||||
  device_event.child = device_event.event;
 | 
			
		||||
  device_event.root_x = 0;
 | 
			
		||||
  device_event.root_y = 0;
 | 
			
		||||
 | 
			
		||||
  clutter_event_get_state_full (event,
 | 
			
		||||
				&button_state,
 | 
			
		||||
				(ClutterModifierType*)&device_event.mods.base,
 | 
			
		||||
				(ClutterModifierType*)&device_event.mods.latched,
 | 
			
		||||
				(ClutterModifierType*)&device_event.mods.locked,
 | 
			
		||||
				(ClutterModifierType*)&device_event.mods.effective);
 | 
			
		||||
  device_event.mods.effective &= ~button_state;
 | 
			
		||||
  memset (&device_event.group, 0, sizeof (device_event.group));
 | 
			
		||||
  device_event.group.effective = (device_event.mods.effective >> 13) & 0x3;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < N_BUTTONS; i++)
 | 
			
		||||
    if ((button_state & (CLUTTER_BUTTON1_MASK << i)))
 | 
			
		||||
      XISetMask (button_mask, i + 1);
 | 
			
		||||
  device_event.buttons.mask_len = N_BUTTONS + 1;
 | 
			
		||||
  device_event.buttons.mask = button_mask;
 | 
			
		||||
 | 
			
		||||
  device_event.valuators.mask_len = 0;
 | 
			
		||||
  device_event.valuators.mask = NULL;
 | 
			
		||||
  device_event.valuators.values = NULL;
 | 
			
		||||
 | 
			
		||||
  return meta_display_process_key_event (display, surface ? surface->window : NULL, &device_event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
update_pressed_keys (MetaWaylandKeyboard   *keyboard,
 | 
			
		||||
		     uint32_t               evdev_code,
 | 
			
		||||
		     gboolean               is_press)
 | 
			
		||||
{
 | 
			
		||||
  if (is_press)
 | 
			
		||||
    {
 | 
			
		||||
      uint32_t *end = (void *) ((char *) keyboard->keys.data +
 | 
			
		||||
                                keyboard->keys.size);
 | 
			
		||||
      uint32_t *k;
 | 
			
		||||
 | 
			
		||||
      /* Ignore the event if the key is already down */
 | 
			
		||||
      /* We want to ignore events that are sent because of auto-repeat. In
 | 
			
		||||
	 the Clutter event stream these appear as a single key press
 | 
			
		||||
	 event. We can detect that because the key will already have been
 | 
			
		||||
	 pressed */
 | 
			
		||||
      for (k = keyboard->keys.data; k < end; k++)
 | 
			
		||||
        if (*k == evdev_code)
 | 
			
		||||
          return;
 | 
			
		||||
          return TRUE;
 | 
			
		||||
 | 
			
		||||
      /* Otherwise add the key to the list of pressed keys */
 | 
			
		||||
      k = wl_array_add (&keyboard->keys, sizeof (*k));
 | 
			
		||||
@@ -494,19 +530,61 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
      g_warning ("unexpected key release event for key 0x%x", evdev_code);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
 | 
			
		||||
    found:
 | 
			
		||||
      (void) 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
                                    const ClutterKeyEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  gboolean is_press = event->type == CLUTTER_KEY_PRESS;
 | 
			
		||||
  guint xkb_keycode, evdev_code;
 | 
			
		||||
  uint32_t serial;
 | 
			
		||||
  gboolean autorepeat;
 | 
			
		||||
  gboolean handled;
 | 
			
		||||
 | 
			
		||||
  xkb_keycode = event->hardware_keycode;
 | 
			
		||||
  if (event->device == NULL ||
 | 
			
		||||
      !clutter_input_device_keycode_to_evdev (event->device,
 | 
			
		||||
					      xkb_keycode, &evdev_code))
 | 
			
		||||
    evdev_code = xkb_keycode - 8; /* What everyone is doing in practice... */
 | 
			
		||||
 | 
			
		||||
  autorepeat = update_pressed_keys (keyboard, evdev_code, is_press);
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Handling key %s%s event code %d\n",
 | 
			
		||||
		is_press ? "press" : "release",
 | 
			
		||||
		autorepeat ? " (autorepeat)" : "",
 | 
			
		||||
		xkb_keycode);
 | 
			
		||||
 | 
			
		||||
  /* Give a chance to process keybindings */
 | 
			
		||||
  if (process_keybinding (keyboard, (ClutterEvent*) event))
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Keybindings ignored the previous event\n");
 | 
			
		||||
 | 
			
		||||
  if (autorepeat)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  serial = wl_display_next_serial (keyboard->display);
 | 
			
		||||
 | 
			
		||||
  set_modifiers (keyboard, serial, event->modifier_state);
 | 
			
		||||
  set_modifiers (keyboard, serial, (ClutterEvent*)event);
 | 
			
		||||
 | 
			
		||||
  keyboard->grab->interface->key (keyboard->grab,
 | 
			
		||||
                                  event->time,
 | 
			
		||||
                                  evdev_code,
 | 
			
		||||
                                  state);
 | 
			
		||||
  handled = keyboard->grab->interface->key (keyboard->grab,
 | 
			
		||||
					    event->time,
 | 
			
		||||
					    evdev_code,
 | 
			
		||||
					    is_press);
 | 
			
		||||
 | 
			
		||||
  if (handled)
 | 
			
		||||
    meta_verbose ("Sent event to wayland client\n");
 | 
			
		||||
  else
 | 
			
		||||
    meta_verbose ("No wayland surface is focused, continuing normal operation\n");
 | 
			
		||||
 | 
			
		||||
  return handled;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -589,15 +667,8 @@ meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard)
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
  g_free ((char *) keyboard->xkb_names.rules);
 | 
			
		||||
  g_free ((char *) keyboard->xkb_names.model);
 | 
			
		||||
  g_free ((char *) keyboard->xkb_names.layout);
 | 
			
		||||
  g_free ((char *) keyboard->xkb_names.variant);
 | 
			
		||||
  g_free ((char *) keyboard->xkb_names.options);
 | 
			
		||||
 | 
			
		||||
  meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
 | 
			
		||||
  xkb_context_unref (keyboard->xkb_context);
 | 
			
		||||
  xkb_state_unref (keyboard->xkb_state);
 | 
			
		||||
 | 
			
		||||
  /* XXX: What about keyboard->resource_list? */
 | 
			
		||||
  if (keyboard->focus_resource)
 | 
			
		||||
@@ -615,8 +686,10 @@ meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
  uint32_t *k;
 | 
			
		||||
  uint32_t serial;
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Asked to acquire modal keyboard grab, timestamp %d\n", timestamp);
 | 
			
		||||
 | 
			
		||||
  if (keyboard->grab != &keyboard->default_grab)
 | 
			
		||||
    return FALSE; 
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (keyboard->focus)
 | 
			
		||||
    {
 | 
			
		||||
@@ -627,15 +700,19 @@ meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
					    0, 0, 0, 0);
 | 
			
		||||
 | 
			
		||||
      for (k = keyboard->keys.data; k < end; k++)
 | 
			
		||||
	keyboard->grab->interface->key (keyboard->grab,
 | 
			
		||||
					timestamp,
 | 
			
		||||
					*k, 0);
 | 
			
		||||
	{
 | 
			
		||||
	  keyboard->grab->interface->key (keyboard->grab,
 | 
			
		||||
					  timestamp,
 | 
			
		||||
					  *k, 0);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  grab = g_slice_new0 (MetaWaylandKeyboardGrab);
 | 
			
		||||
  grab->interface = &modal_grab;
 | 
			
		||||
  meta_wayland_keyboard_start_grab (keyboard, grab);
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Acquired modal keyboard grab, timestamp %d\n", timestamp);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -668,8 +745,37 @@ meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
					    keyboard->modifier_state.group);
 | 
			
		||||
 | 
			
		||||
      for (k = keyboard->keys.data; k < end; k++)
 | 
			
		||||
	keyboard->grab->interface->key (keyboard->grab,
 | 
			
		||||
					timestamp,
 | 
			
		||||
					*k, 1);
 | 
			
		||||
	{
 | 
			
		||||
	  keyboard->grab->interface->key (keyboard->grab,
 | 
			
		||||
					  timestamp,
 | 
			
		||||
					  *k, 1);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Released modal keyboard grab, timestamp %d\n", timestamp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_keyboard_set_keymap_names (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
					const char          *rules,
 | 
			
		||||
					const char          *model,
 | 
			
		||||
					const char          *layout,
 | 
			
		||||
					const char          *variant,
 | 
			
		||||
					const char          *options,
 | 
			
		||||
					int                  flags)
 | 
			
		||||
{
 | 
			
		||||
  struct xkb_rule_names xkb_names;
 | 
			
		||||
 | 
			
		||||
  xkb_names.rules = rules;
 | 
			
		||||
  xkb_names.model = model;
 | 
			
		||||
  xkb_names.layout = layout;
 | 
			
		||||
  xkb_names.variant = variant;
 | 
			
		||||
  xkb_names.options = options;
 | 
			
		||||
 | 
			
		||||
  meta_wayland_keyboard_take_keymap (keyboard,
 | 
			
		||||
				     xkb_keymap_new_from_names (keyboard->xkb_context,
 | 
			
		||||
								&xkb_names,
 | 
			
		||||
								0 /* flags */),
 | 
			
		||||
				     flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -50,8 +50,8 @@
 | 
			
		||||
 | 
			
		||||
struct _MetaWaylandKeyboardGrabInterface
 | 
			
		||||
{
 | 
			
		||||
  void (*key) (MetaWaylandKeyboardGrab * grab, uint32_t time,
 | 
			
		||||
               uint32_t key, uint32_t state);
 | 
			
		||||
  gboolean (*key) (MetaWaylandKeyboardGrab * grab, uint32_t time,
 | 
			
		||||
		   uint32_t key, uint32_t state);
 | 
			
		||||
  void (*modifiers) (MetaWaylandKeyboardGrab * grab, uint32_t serial,
 | 
			
		||||
                     uint32_t mods_depressed, uint32_t mods_latched,
 | 
			
		||||
                     uint32_t mods_locked, uint32_t group);
 | 
			
		||||
@@ -111,11 +111,8 @@ struct _MetaWaylandKeyboard
 | 
			
		||||
  struct wl_display *display;
 | 
			
		||||
 | 
			
		||||
  struct xkb_context *xkb_context;
 | 
			
		||||
  struct xkb_state *xkb_state;
 | 
			
		||||
  gboolean is_evdev;
 | 
			
		||||
 | 
			
		||||
  MetaWaylandXkbInfo xkb_info;
 | 
			
		||||
  struct xkb_rule_names xkb_names;
 | 
			
		||||
 | 
			
		||||
  MetaWaylandKeyboardGrab input_method_grab;
 | 
			
		||||
  struct wl_resource *input_method_resource;
 | 
			
		||||
@@ -126,7 +123,19 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
                            struct wl_display   *display,
 | 
			
		||||
			    gboolean             is_evdev);
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  META_WAYLAND_KEYBOARD_SKIP_XCLIENTS = 1,
 | 
			
		||||
} MetaWaylandKeyboardSetKeymapFlags;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_keyboard_set_keymap_names (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
					const char          *rules,
 | 
			
		||||
					const char          *model,
 | 
			
		||||
					const char          *layout,
 | 
			
		||||
					const char          *variant,
 | 
			
		||||
					const char          *options,
 | 
			
		||||
					int                  flags);
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
                                    const ClutterKeyEvent *event);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,9 @@
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <clutter/evdev/clutter-evdev.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-wayland-pointer.h"
 | 
			
		||||
#include "meta-wayland-private.h"
 | 
			
		||||
 | 
			
		||||
@@ -120,9 +123,114 @@ static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = {
 | 
			
		||||
  default_grab_button
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_pointer_init (MetaWaylandPointer *pointer)
 | 
			
		||||
/*
 | 
			
		||||
 * The pointer constrain code is mostly a rip-off of the XRandR code from Xorg.
 | 
			
		||||
 * (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder)
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright © 2006 Keith Packard
 | 
			
		||||
 * Copyright 2010 Red Hat, Inc
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_all_screen_monitors(MetaMonitorInfo *monitors,
 | 
			
		||||
			  unsigned         n_monitors,
 | 
			
		||||
			  float            x,
 | 
			
		||||
			  float            y)
 | 
			
		||||
{
 | 
			
		||||
  unsigned int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_monitors; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaMonitorInfo *monitor = &monitors[i];
 | 
			
		||||
      int left, right, top, bottom;
 | 
			
		||||
 | 
			
		||||
      left = monitor->rect.x;
 | 
			
		||||
      right = left + monitor->rect.width;
 | 
			
		||||
      top = monitor->rect.y;
 | 
			
		||||
      bottom = left + monitor->rect.height;
 | 
			
		||||
 | 
			
		||||
      if ((x >= left) && (x < right) && (y >= top) && (y < bottom))
 | 
			
		||||
	return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
constrain_all_screen_monitors (ClutterInputDevice *device,
 | 
			
		||||
			       MetaMonitorInfo    *monitors,
 | 
			
		||||
			       unsigned            n_monitors,
 | 
			
		||||
			       float              *x,
 | 
			
		||||
			       float              *y)
 | 
			
		||||
{
 | 
			
		||||
  ClutterPoint current;
 | 
			
		||||
  unsigned int i;
 | 
			
		||||
 | 
			
		||||
  clutter_input_device_get_coords (device, NULL, ¤t);
 | 
			
		||||
 | 
			
		||||
  /* if we're trying to escape, clamp to the CRTC we're coming from */
 | 
			
		||||
  for (i = 0; i < n_monitors; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaMonitorInfo *monitor = &monitors[i];
 | 
			
		||||
      int left, right, top, bottom;
 | 
			
		||||
      float nx, ny;
 | 
			
		||||
 | 
			
		||||
      left = monitor->rect.x;
 | 
			
		||||
      right = left + monitor->rect.width;
 | 
			
		||||
      top = monitor->rect.y;
 | 
			
		||||
      bottom = left + monitor->rect.height;
 | 
			
		||||
 | 
			
		||||
      nx = current.x;
 | 
			
		||||
      ny = current.y;
 | 
			
		||||
 | 
			
		||||
      if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom))
 | 
			
		||||
	{
 | 
			
		||||
	  if (*x < left)
 | 
			
		||||
	    *x = left;
 | 
			
		||||
	  if (*x >= right)
 | 
			
		||||
	    *x = right - 1;
 | 
			
		||||
	  if (*y < top)
 | 
			
		||||
	    *y = top;
 | 
			
		||||
	  if (*y >= bottom)
 | 
			
		||||
	    *y = bottom - 1;
 | 
			
		||||
 | 
			
		||||
	  return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
pointer_constrain_callback (ClutterInputDevice *device,
 | 
			
		||||
			    float              *new_x,
 | 
			
		||||
			    float              *new_y,
 | 
			
		||||
			    gpointer            user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager *monitor_manager;
 | 
			
		||||
  MetaMonitorInfo *monitors;
 | 
			
		||||
  unsigned int n_monitors;
 | 
			
		||||
  gboolean ret;
 | 
			
		||||
 | 
			
		||||
  monitor_manager = meta_monitor_manager_get ();
 | 
			
		||||
  monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
 | 
			
		||||
 | 
			
		||||
  /* if we're moving inside a monitor, we're fine */
 | 
			
		||||
  ret = check_all_screen_monitors(monitors, n_monitors, *new_x, *new_y);
 | 
			
		||||
  if (ret == TRUE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* if we're trying to escape, clamp to the CRTC we're coming from */
 | 
			
		||||
  constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_pointer_init (MetaWaylandPointer *pointer,
 | 
			
		||||
			   gboolean            is_native)
 | 
			
		||||
{
 | 
			
		||||
  ClutterDeviceManager *manager;
 | 
			
		||||
  ClutterInputDevice *device;
 | 
			
		||||
  ClutterPoint current;
 | 
			
		||||
 | 
			
		||||
  memset (pointer, 0, sizeof *pointer);
 | 
			
		||||
  wl_list_init (&pointer->resource_list);
 | 
			
		||||
  pointer->focus_listener.notify = lose_pointer_focus;
 | 
			
		||||
@@ -131,9 +239,16 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer)
 | 
			
		||||
  pointer->grab = &pointer->default_grab;
 | 
			
		||||
  wl_signal_init (&pointer->focus_signal);
 | 
			
		||||
 | 
			
		||||
  /* FIXME: Pick better co-ords. */
 | 
			
		||||
  pointer->x = wl_fixed_from_int (100);
 | 
			
		||||
  pointer->y = wl_fixed_from_int (100);
 | 
			
		||||
  manager = clutter_device_manager_get_default ();
 | 
			
		||||
  device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
 | 
			
		||||
 | 
			
		||||
  if (is_native)
 | 
			
		||||
    clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback,
 | 
			
		||||
						  pointer, NULL);
 | 
			
		||||
 | 
			
		||||
  clutter_input_device_get_coords (device, NULL, ¤t);
 | 
			
		||||
  pointer->x = wl_fixed_from_double (current.x);
 | 
			
		||||
  pointer->y = wl_fixed_from_double (current.y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
@@ -60,7 +60,7 @@ struct _MetaWaylandPointer
 | 
			
		||||
  guint32 grab_serial;
 | 
			
		||||
  guint32 grab_time;
 | 
			
		||||
 | 
			
		||||
  wl_fixed_t x, y;
 | 
			
		||||
  wl_fixed_t x, y; /* TODO: remove, use ClutterInputDevice instead */
 | 
			
		||||
  MetaWaylandSurface *current;
 | 
			
		||||
  struct wl_listener current_listener;
 | 
			
		||||
  wl_fixed_t current_x, current_y;
 | 
			
		||||
@@ -69,7 +69,8 @@ struct _MetaWaylandPointer
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_pointer_init (MetaWaylandPointer *pointer);
 | 
			
		||||
meta_wayland_pointer_init (MetaWaylandPointer *pointer,
 | 
			
		||||
			   gboolean            is_native);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_pointer_release (MetaWaylandPointer *pointer);
 | 
			
		||||
 
 | 
			
		||||
@@ -104,6 +104,7 @@ void                    meta_wayland_compositor_set_input_focus (MetaWaylandComp
 | 
			
		||||
                                                                 MetaWindow            *window);
 | 
			
		||||
 | 
			
		||||
MetaLauncher           *meta_wayland_compositor_get_launcher    (MetaWaylandCompositor *compositor);
 | 
			
		||||
gboolean                meta_wayland_compositor_is_native       (MetaWaylandCompositor *compositor);
 | 
			
		||||
 | 
			
		||||
MetaWaylandBuffer *     meta_wayland_buffer_from_resource       (struct wl_resource *resource);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -284,7 +284,7 @@ meta_wayland_seat_new (struct wl_display *display,
 | 
			
		||||
  wl_list_init (&seat->drag_resource_list);
 | 
			
		||||
  wl_signal_init (&seat->drag_icon_signal);
 | 
			
		||||
 | 
			
		||||
  meta_wayland_pointer_init (&seat->pointer);
 | 
			
		||||
  meta_wayland_pointer_init (&seat->pointer, is_native);
 | 
			
		||||
 | 
			
		||||
  meta_wayland_keyboard_init (&seat->keyboard, display, is_native);
 | 
			
		||||
 | 
			
		||||
@@ -357,30 +357,24 @@ handle_button_event (MetaWaylandSeat *seat,
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (state)
 | 
			
		||||
  /* FIXME: Handle in display.c */
 | 
			
		||||
  if (state && pointer->button_count == 1)
 | 
			
		||||
    {
 | 
			
		||||
      if (pointer->button_count == 0)
 | 
			
		||||
        {
 | 
			
		||||
          MetaWaylandSurface *surface = pointer->current;
 | 
			
		||||
      MetaWaylandSurface *surface = pointer->current;
 | 
			
		||||
 | 
			
		||||
          pointer->grab_button = button;
 | 
			
		||||
          pointer->grab_time = event->time;
 | 
			
		||||
          pointer->grab_x = pointer->x;
 | 
			
		||||
          pointer->grab_y = pointer->y;
 | 
			
		||||
      pointer->grab_button = button;
 | 
			
		||||
      pointer->grab_time = event->time;
 | 
			
		||||
      pointer->grab_x = pointer->x;
 | 
			
		||||
      pointer->grab_y = pointer->y;
 | 
			
		||||
 | 
			
		||||
          if (button == BTN_LEFT &&
 | 
			
		||||
              surface &&
 | 
			
		||||
              surface->window &&
 | 
			
		||||
              surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
 | 
			
		||||
            {
 | 
			
		||||
              meta_window_raise (surface->window);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      pointer->button_count++;
 | 
			
		||||
      if (button == BTN_LEFT &&
 | 
			
		||||
	  surface &&
 | 
			
		||||
	  surface->window &&
 | 
			
		||||
	  surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
 | 
			
		||||
	{
 | 
			
		||||
	  meta_window_raise (surface->window);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    pointer->button_count--;
 | 
			
		||||
 | 
			
		||||
  pointer->grab->interface->button (pointer->grab, event->time, button, state);
 | 
			
		||||
 | 
			
		||||
@@ -430,10 +424,34 @@ handle_scroll_event (MetaWaylandSeat *seat,
 | 
			
		||||
                          value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
static int
 | 
			
		||||
count_buttons (const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  static gint maskmap[5] =
 | 
			
		||||
    {
 | 
			
		||||
      CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON2_MASK, CLUTTER_BUTTON3_MASK,
 | 
			
		||||
      CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK
 | 
			
		||||
    };
 | 
			
		||||
  ClutterModifierType mod_mask;
 | 
			
		||||
  int i, count;
 | 
			
		||||
 | 
			
		||||
  mod_mask = clutter_event_get_state (event);
 | 
			
		||||
  count = 0;
 | 
			
		||||
  for (i = 0; i < 5; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (mod_mask & maskmap[i])
 | 
			
		||||
	count++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
 | 
			
		||||
                                const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  seat->pointer.button_count = count_buttons (event);
 | 
			
		||||
 | 
			
		||||
  switch (event->type)
 | 
			
		||||
    {
 | 
			
		||||
    case CLUTTER_MOTION:
 | 
			
		||||
@@ -449,9 +467,8 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
 | 
			
		||||
 | 
			
		||||
    case CLUTTER_KEY_PRESS:
 | 
			
		||||
    case CLUTTER_KEY_RELEASE:
 | 
			
		||||
      meta_wayland_keyboard_handle_event (&seat->keyboard,
 | 
			
		||||
                                          (const ClutterKeyEvent *) event);
 | 
			
		||||
      break;
 | 
			
		||||
      return meta_wayland_keyboard_handle_event (&seat->keyboard,
 | 
			
		||||
						 (const ClutterKeyEvent *) event);
 | 
			
		||||
 | 
			
		||||
    case CLUTTER_SCROLL:
 | 
			
		||||
      handle_scroll_event (seat, (const ClutterScrollEvent *) event);
 | 
			
		||||
@@ -460,6 +477,8 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
@@ -90,7 +90,7 @@ MetaWaylandSeat *
 | 
			
		||||
meta_wayland_seat_new (struct wl_display *display,
 | 
			
		||||
		       gboolean           is_native);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
 | 
			
		||||
                                const ClutterEvent *event);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <clutter/wayland/clutter-wayland-compositor.h>
 | 
			
		||||
#include <clutter/wayland/clutter-wayland-surface.h>
 | 
			
		||||
#include <cogl/cogl-wayland-server.h>
 | 
			
		||||
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
@@ -64,8 +65,9 @@ static void
 | 
			
		||||
surface_process_damage (MetaWaylandSurface *surface,
 | 
			
		||||
                        cairo_region_t *region)
 | 
			
		||||
{
 | 
			
		||||
  if (surface->window &&
 | 
			
		||||
      surface->buffer_ref.buffer)
 | 
			
		||||
  g_assert (surface->window);
 | 
			
		||||
 | 
			
		||||
  if (surface->buffer_ref.buffer)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWindowActor *window_actor =
 | 
			
		||||
        META_WINDOW_ACTOR (meta_window_get_compositor_private (surface->window));
 | 
			
		||||
@@ -111,7 +113,7 @@ static void
 | 
			
		||||
meta_wayland_surface_attach (struct wl_client *wayland_client,
 | 
			
		||||
                             struct wl_resource *wayland_surface_resource,
 | 
			
		||||
                             struct wl_resource *wayland_buffer_resource,
 | 
			
		||||
                             gint32 sx, gint32 sy)
 | 
			
		||||
                             gint32 dx, gint32 dy)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurface *surface =
 | 
			
		||||
    wl_resource_get_user_data (wayland_surface_resource);
 | 
			
		||||
@@ -130,8 +132,8 @@ meta_wayland_surface_attach (struct wl_client *wayland_client,
 | 
			
		||||
  if (surface->pending.buffer)
 | 
			
		||||
    wl_list_remove (&surface->pending.buffer_destroy_listener.link);
 | 
			
		||||
 | 
			
		||||
  surface->pending.sx = sx;
 | 
			
		||||
  surface->pending.sy = sy;
 | 
			
		||||
  surface->pending.dx = dx;
 | 
			
		||||
  surface->pending.dy = dy;
 | 
			
		||||
  surface->pending.buffer = buffer;
 | 
			
		||||
  surface->pending.newly_attached = TRUE;
 | 
			
		||||
 | 
			
		||||
@@ -247,36 +249,86 @@ meta_wayland_surface_commit (struct wl_client *client,
 | 
			
		||||
  if (surface->pending.newly_attached &&
 | 
			
		||||
      surface->buffer_ref.buffer != surface->pending.buffer)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWaylandBuffer *buffer = surface->pending.buffer;
 | 
			
		||||
      CoglContext *ctx =
 | 
			
		||||
        clutter_backend_get_cogl_context (clutter_get_default_backend ());
 | 
			
		||||
      CoglError *catch_error = NULL;
 | 
			
		||||
      CoglTexture *texture =
 | 
			
		||||
        COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx,
 | 
			
		||||
                                                               buffer->resource,
 | 
			
		||||
                                                               &catch_error));
 | 
			
		||||
      if (!texture)
 | 
			
		||||
        {
 | 
			
		||||
          cogl_error_free (catch_error);
 | 
			
		||||
	  meta_warning ("Could not import pending buffer, ignoring commit\n");
 | 
			
		||||
	  return;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
	  buffer->texture = texture;
 | 
			
		||||
          buffer->width = cogl_texture_get_width (texture);
 | 
			
		||||
          buffer->height = cogl_texture_get_height (texture);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      /* Note: we set this before informing any window-actor since the
 | 
			
		||||
       * window actor will expect to find the new buffer within the
 | 
			
		||||
       * surface. */
 | 
			
		||||
      meta_wayland_buffer_reference (&surface->buffer_ref,
 | 
			
		||||
                                     surface->pending.buffer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!surface->buffer_ref.buffer)
 | 
			
		||||
    {
 | 
			
		||||
      meta_warning ("Commit without a buffer? Ignoring\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (surface->initial_state)
 | 
			
		||||
    {
 | 
			
		||||
      MetaDisplay *display = meta_get_display ();
 | 
			
		||||
      int width;
 | 
			
		||||
      int height;
 | 
			
		||||
 | 
			
		||||
      width = surface->buffer_ref.buffer->width;
 | 
			
		||||
      height = surface->buffer_ref.buffer->height;
 | 
			
		||||
 | 
			
		||||
      /* This will free and clear initial_state */
 | 
			
		||||
      surface->window = meta_window_new_for_wayland (display, width, height, surface);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (surface == compositor->seat->sprite)
 | 
			
		||||
    meta_wayland_seat_update_sprite (compositor->seat);
 | 
			
		||||
  else if (surface->window)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWindow *window = surface->window;
 | 
			
		||||
 | 
			
		||||
      if (surface->pending.buffer)
 | 
			
		||||
        {
 | 
			
		||||
          MetaWaylandBuffer *buffer = surface->pending.buffer;
 | 
			
		||||
	{
 | 
			
		||||
	  MetaWaylandBuffer *buffer = surface->pending.buffer;
 | 
			
		||||
	  MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
 | 
			
		||||
          if (surface->window)
 | 
			
		||||
            {
 | 
			
		||||
              MetaWindow *window = surface->window;
 | 
			
		||||
              MetaWindowActor *window_actor =
 | 
			
		||||
                META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
              MetaRectangle rect;
 | 
			
		||||
	  meta_window_actor_attach_wayland_buffer (window_actor, buffer);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
              meta_window_get_input_rect (surface->window, &rect);
 | 
			
		||||
      /* We resize X based surfaces according to X events */
 | 
			
		||||
      if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
 | 
			
		||||
	{
 | 
			
		||||
	  int new_width;
 | 
			
		||||
	  int new_height;
 | 
			
		||||
 | 
			
		||||
              if (window_actor)
 | 
			
		||||
                meta_window_actor_attach_wayland_buffer (window_actor, buffer);
 | 
			
		||||
	  new_width = surface->buffer_ref.buffer->width;
 | 
			
		||||
	  new_height = surface->buffer_ref.buffer->height;
 | 
			
		||||
	  if (new_width != window->rect.width ||
 | 
			
		||||
	      new_height != window->rect.height ||
 | 
			
		||||
	      surface->pending.dx != 0 ||
 | 
			
		||||
	      surface->pending.dy != 0)
 | 
			
		||||
	    meta_window_move_resize_wayland (surface->window, new_width, new_height,
 | 
			
		||||
					     surface->pending.dx, surface->pending.dy);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
              /* XXX: we resize X based surfaces according to X events */
 | 
			
		||||
              if (surface->xid == 0 &&
 | 
			
		||||
                  (buffer->width != rect.width || buffer->height != rect.height))
 | 
			
		||||
                meta_window_resize (surface->window, FALSE, buffer->width, buffer->height);
 | 
			
		||||
            }
 | 
			
		||||
          else if (surface == compositor->seat->sprite)
 | 
			
		||||
            meta_wayland_seat_update_sprite (compositor->seat);
 | 
			
		||||
        }
 | 
			
		||||
      meta_window_set_opaque_region (surface->window, surface->pending.opaque_region);
 | 
			
		||||
      meta_window_set_input_region (surface->window, surface->pending.input_region);
 | 
			
		||||
      surface_process_damage (surface, surface->pending.damage);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (surface->pending.buffer)
 | 
			
		||||
@@ -284,20 +336,11 @@ meta_wayland_surface_commit (struct wl_client *client,
 | 
			
		||||
      wl_list_remove (&surface->pending.buffer_destroy_listener.link);
 | 
			
		||||
      surface->pending.buffer = NULL;
 | 
			
		||||
    }
 | 
			
		||||
  surface->pending.sx = 0;
 | 
			
		||||
  surface->pending.sy = 0;
 | 
			
		||||
  surface->pending.dx = 0;
 | 
			
		||||
  surface->pending.dy = 0;
 | 
			
		||||
  surface->pending.newly_attached = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (surface->window)
 | 
			
		||||
    {
 | 
			
		||||
      meta_window_set_opaque_region (surface->window, surface->pending.opaque_region);
 | 
			
		||||
      g_clear_pointer (&surface->pending.opaque_region, cairo_region_destroy);
 | 
			
		||||
 | 
			
		||||
      meta_window_set_input_region (surface->window, surface->pending.input_region);
 | 
			
		||||
      g_clear_pointer (&surface->pending.input_region, cairo_region_destroy);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  surface_process_damage (surface, surface->pending.damage);
 | 
			
		||||
  g_clear_pointer (&surface->pending.opaque_region, cairo_region_destroy);
 | 
			
		||||
  g_clear_pointer (&surface->pending.input_region, cairo_region_destroy);
 | 
			
		||||
  empty_region (surface->pending.damage);
 | 
			
		||||
 | 
			
		||||
  /* wl_surface.frame */
 | 
			
		||||
@@ -632,34 +675,6 @@ shell_surface_resize (struct wl_client *client,
 | 
			
		||||
  g_warning ("TODO: support shell_surface_resize request");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
ensure_surface_window (MetaWaylandSurface *surface)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display = meta_get_display ();
 | 
			
		||||
 | 
			
		||||
  if (!surface->window)
 | 
			
		||||
    {
 | 
			
		||||
      int width, height;
 | 
			
		||||
 | 
			
		||||
      if (surface->buffer_ref.buffer)
 | 
			
		||||
        {
 | 
			
		||||
          MetaWaylandBuffer *buffer = surface->buffer_ref.buffer;
 | 
			
		||||
          width = buffer->width;
 | 
			
		||||
          height = buffer->width;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          width = 0;
 | 
			
		||||
          height = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      surface->window =
 | 
			
		||||
        meta_window_new_for_wayland (display, width, height, surface);
 | 
			
		||||
 | 
			
		||||
      meta_window_calc_showing (surface->window);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
shell_surface_set_toplevel (struct wl_client *client,
 | 
			
		||||
                            struct wl_resource *resource)
 | 
			
		||||
@@ -672,9 +687,19 @@ shell_surface_set_toplevel (struct wl_client *client,
 | 
			
		||||
  if (client == compositor->xwayland_client)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  ensure_surface_window (surface);
 | 
			
		||||
  if (surface->window)
 | 
			
		||||
    {
 | 
			
		||||
      if (surface->window->fullscreen)
 | 
			
		||||
	meta_window_unmake_fullscreen (surface->window);
 | 
			
		||||
      if (meta_window_get_maximized (surface->window) != 0)
 | 
			
		||||
	meta_window_unmaximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      ensure_initial_state (surface);
 | 
			
		||||
 | 
			
		||||
  meta_window_unmake_fullscreen (surface->window);
 | 
			
		||||
      surface->initial_state->initial_type = META_WAYLAND_SURFACE_TOPLEVEL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -687,13 +712,22 @@ shell_surface_set_transient (struct wl_client *client,
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurfaceExtension *shell_surface = wl_resource_get_user_data (resource);
 | 
			
		||||
  MetaWaylandSurface *surface = shell_surface->surface;
 | 
			
		||||
  MetaWaylandSurface *parent_surface = wl_resource_get_user_data (parent);
 | 
			
		||||
  MetaWaylandCompositor *compositor = surface->compositor;
 | 
			
		||||
 | 
			
		||||
  /* NB: Surfaces from xwayland become managed based on X events. */
 | 
			
		||||
  if (client == compositor->xwayland_client)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  ensure_surface_window (surface);
 | 
			
		||||
  if (surface->window)
 | 
			
		||||
    meta_window_set_transient_for (surface->window, parent_surface->window);
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      ensure_initial_state (surface);
 | 
			
		||||
 | 
			
		||||
      surface->initial_state->initial_type = META_WAYLAND_SURFACE_TOPLEVEL;
 | 
			
		||||
      surface->initial_state->transient_for = parent;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -711,9 +745,14 @@ shell_surface_set_fullscreen (struct wl_client *client,
 | 
			
		||||
  if (client == compositor->xwayland_client)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  ensure_surface_window (surface);
 | 
			
		||||
  if (surface->window)
 | 
			
		||||
    meta_window_make_fullscreen (surface->window);
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      ensure_initial_state (surface);
 | 
			
		||||
 | 
			
		||||
  meta_window_make_fullscreen (surface->window);
 | 
			
		||||
      surface->initial_state->initial_type = META_WAYLAND_SURFACE_FULLSCREEN;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -733,7 +772,22 @@ shell_surface_set_maximized (struct wl_client *client,
 | 
			
		||||
                             struct wl_resource *resource,
 | 
			
		||||
                             struct wl_resource *output)
 | 
			
		||||
{
 | 
			
		||||
  g_warning ("TODO: support shell_surface_set_maximized request");
 | 
			
		||||
  MetaWaylandSurfaceExtension *shell_surface = wl_resource_get_user_data (resource);
 | 
			
		||||
  MetaWaylandSurface *surface = shell_surface->surface;
 | 
			
		||||
  MetaWaylandCompositor *compositor = surface->compositor;
 | 
			
		||||
 | 
			
		||||
  /* NB: Surfaces from xwayland become managed based on X events. */
 | 
			
		||||
  if (client == compositor->xwayland_client)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (surface->window)
 | 
			
		||||
    meta_window_maximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      ensure_initial_state (surface);
 | 
			
		||||
 | 
			
		||||
      surface->initial_state->initial_type = META_WAYLAND_SURFACE_MAXIMIZED;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -813,7 +867,7 @@ destroy_surface_extension (struct wl_resource *resource)
 | 
			
		||||
  g_free (extension);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
static MetaWaylandSurfaceExtension *
 | 
			
		||||
create_surface_extension (struct wl_client          *client,
 | 
			
		||||
			  struct wl_resource        *master_resource,
 | 
			
		||||
			  guint32                    id,
 | 
			
		||||
@@ -834,6 +888,8 @@ create_surface_extension (struct wl_client          *client,
 | 
			
		||||
  extension->surface_destroy_listener.notify = extension_handle_surface_destroy;
 | 
			
		||||
  wl_resource_add_destroy_listener (surface->resource,
 | 
			
		||||
                                    &extension->surface_destroy_listener);
 | 
			
		||||
 | 
			
		||||
  return extension;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -844,7 +900,7 @@ get_shell_surface (struct wl_client *client,
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
 | 
			
		||||
 | 
			
		||||
  if (surface->has_shell_surface)
 | 
			
		||||
  if (surface->shell_surface)
 | 
			
		||||
    {
 | 
			
		||||
      wl_resource_post_error (surface_resource,
 | 
			
		||||
                              WL_DISPLAY_ERROR_INVALID_OBJECT,
 | 
			
		||||
@@ -852,10 +908,9 @@ get_shell_surface (struct wl_client *client,
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  create_surface_extension (client, resource, id, surface,
 | 
			
		||||
			    &wl_shell_surface_interface,
 | 
			
		||||
			    &meta_wayland_shell_surface_interface);
 | 
			
		||||
  surface->has_shell_surface = TRUE;
 | 
			
		||||
  surface->shell_surface = create_surface_extension (client, resource, id, surface,
 | 
			
		||||
						     &wl_shell_surface_interface,
 | 
			
		||||
						     &meta_wayland_shell_surface_interface);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct wl_shell_interface meta_wayland_shell_interface =
 | 
			
		||||
@@ -946,7 +1001,7 @@ get_gtk_surface (struct wl_client *client,
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
 | 
			
		||||
 | 
			
		||||
  if (surface->has_gtk_surface)
 | 
			
		||||
  if (surface->gtk_surface)
 | 
			
		||||
    {
 | 
			
		||||
      wl_resource_post_error (surface_resource,
 | 
			
		||||
                              WL_DISPLAY_ERROR_INVALID_OBJECT,
 | 
			
		||||
@@ -954,10 +1009,9 @@ get_gtk_surface (struct wl_client *client,
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  create_surface_extension (client, resource, id, surface,
 | 
			
		||||
			    >k_surface_interface,
 | 
			
		||||
			    &meta_wayland_gtk_surface_interface);
 | 
			
		||||
  surface->has_gtk_surface = TRUE;
 | 
			
		||||
  surface->gtk_surface = create_surface_extension (client, resource, id, surface,
 | 
			
		||||
						   >k_surface_interface,
 | 
			
		||||
						   &meta_wayland_gtk_surface_interface);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct gtk_shell_interface meta_wayland_gtk_shell_interface =
 | 
			
		||||
@@ -1003,6 +1057,29 @@ meta_wayland_surface_set_initial_state (MetaWaylandSurface *surface,
 | 
			
		||||
  if (initial == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* Note that we poke at the bits directly here, because we're
 | 
			
		||||
     in the middle of meta_window_new_shared() */
 | 
			
		||||
  switch (initial->initial_type)
 | 
			
		||||
    {
 | 
			
		||||
    case META_WAYLAND_SURFACE_TOPLEVEL:
 | 
			
		||||
      break;
 | 
			
		||||
    case META_WAYLAND_SURFACE_FULLSCREEN:
 | 
			
		||||
      window->fullscreen = TRUE;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_WAYLAND_SURFACE_MAXIMIZED:
 | 
			
		||||
      window->maximized_horizontally = window->maximized_vertically = TRUE;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (initial->transient_for)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWaylandSurface *parent = wl_resource_get_user_data (initial->transient_for);
 | 
			
		||||
      if (parent)
 | 
			
		||||
	window->transient_for = g_object_ref (parent->window);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (initial->title)
 | 
			
		||||
    meta_window_set_title (window, initial->title);
 | 
			
		||||
 | 
			
		||||
@@ -1045,3 +1122,14 @@ free_initial_state (MetaWaylandSurfaceInitialState *initial)
 | 
			
		||||
 | 
			
		||||
  g_slice_free (MetaWaylandSurfaceInitialState, initial);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
 | 
			
		||||
				       int                 new_width,
 | 
			
		||||
				       int                 new_height,
 | 
			
		||||
				       int                 edges)
 | 
			
		||||
{
 | 
			
		||||
  if (surface->shell_surface)
 | 
			
		||||
    wl_shell_surface_send_configure (surface->shell_surface->resource,
 | 
			
		||||
				     edges, new_width, new_height);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,7 @@ struct _MetaWaylandBuffer
 | 
			
		||||
  struct wl_signal destroy_signal;
 | 
			
		||||
  struct wl_listener destroy_listener;
 | 
			
		||||
 | 
			
		||||
  CoglTexture *texture;
 | 
			
		||||
  int32_t width, height;
 | 
			
		||||
  uint32_t busy_count;
 | 
			
		||||
};
 | 
			
		||||
@@ -52,8 +53,8 @@ typedef struct
 | 
			
		||||
  gboolean newly_attached;
 | 
			
		||||
  MetaWaylandBuffer *buffer;
 | 
			
		||||
  struct wl_listener buffer_destroy_listener;
 | 
			
		||||
  int32_t sx;
 | 
			
		||||
  int32_t sy;
 | 
			
		||||
  int32_t dx;
 | 
			
		||||
  int32_t dy;
 | 
			
		||||
 | 
			
		||||
  /* wl_surface.damage */
 | 
			
		||||
  cairo_region_t *damage;
 | 
			
		||||
@@ -65,8 +66,17 @@ typedef struct
 | 
			
		||||
  struct wl_list frame_callback_list;
 | 
			
		||||
} MetaWaylandDoubleBufferedState;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  META_WAYLAND_SURFACE_TOPLEVEL = 0,
 | 
			
		||||
  META_WAYLAND_SURFACE_MAXIMIZED,
 | 
			
		||||
  META_WAYLAND_SURFACE_FULLSCREEN
 | 
			
		||||
} MetaWaylandSurfaceType;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurfaceType initial_type;
 | 
			
		||||
  struct wl_resource *transient_for;
 | 
			
		||||
 | 
			
		||||
  char *title;
 | 
			
		||||
  char *wm_class;
 | 
			
		||||
 | 
			
		||||
@@ -78,17 +88,21 @@ typedef struct
 | 
			
		||||
  char *gtk_window_object_path;
 | 
			
		||||
} MetaWaylandSurfaceInitialState;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurface *surface;
 | 
			
		||||
  struct wl_resource *resource;
 | 
			
		||||
  struct wl_listener surface_destroy_listener;
 | 
			
		||||
} MetaWaylandSurfaceExtension;
 | 
			
		||||
 | 
			
		||||
struct _MetaWaylandSurface
 | 
			
		||||
{
 | 
			
		||||
  struct wl_resource *resource;
 | 
			
		||||
  MetaWaylandCompositor *compositor;
 | 
			
		||||
  guint32 xid;
 | 
			
		||||
  int x;
 | 
			
		||||
  int y;
 | 
			
		||||
  MetaWaylandBufferReference buffer_ref;
 | 
			
		||||
  MetaWindow *window;
 | 
			
		||||
  gboolean has_shell_surface;
 | 
			
		||||
  gboolean has_gtk_surface;
 | 
			
		||||
  MetaWaylandSurfaceExtension *shell_surface;
 | 
			
		||||
  MetaWaylandSurfaceExtension *gtk_surface;
 | 
			
		||||
 | 
			
		||||
  /* All the pending state, that wl_surface.commit will apply. */
 | 
			
		||||
  MetaWaylandDoubleBufferedState pending;
 | 
			
		||||
@@ -98,13 +112,6 @@ struct _MetaWaylandSurface
 | 
			
		||||
  MetaWaylandSurfaceInitialState *initial_state;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurface *surface;
 | 
			
		||||
  struct wl_resource *resource;
 | 
			
		||||
  struct wl_listener surface_destroy_listener;
 | 
			
		||||
} MetaWaylandSurfaceExtension;
 | 
			
		||||
 | 
			
		||||
void                meta_wayland_init_shell     (MetaWaylandCompositor *compositor);
 | 
			
		||||
 | 
			
		||||
MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *compositor,
 | 
			
		||||
@@ -116,4 +123,9 @@ void                meta_wayland_surface_free   (MetaWaylandSurface    *surface)
 | 
			
		||||
void                meta_wayland_surface_set_initial_state (MetaWaylandSurface *surface,
 | 
			
		||||
							    MetaWindow         *window);
 | 
			
		||||
 | 
			
		||||
void                meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
 | 
			
		||||
							   int                 width,
 | 
			
		||||
							   int                 height,
 | 
			
		||||
							   int                 edges);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,8 @@
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <wayland-server.h>
 | 
			
		||||
 | 
			
		||||
@@ -185,6 +187,7 @@ meta_wayland_buffer_reference (MetaWaylandBufferReference *ref,
 | 
			
		||||
 | 
			
		||||
      if (ref->buffer->busy_count == 0)
 | 
			
		||||
        {
 | 
			
		||||
	  g_clear_pointer (&ref->buffer->texture, cogl_object_unref);
 | 
			
		||||
          g_assert (wl_resource_get_client (ref->buffer->resource));
 | 
			
		||||
          wl_resource_queue_event (ref->buffer->resource, WL_BUFFER_RELEASE);
 | 
			
		||||
        }
 | 
			
		||||
@@ -530,117 +533,6 @@ stage_destroy_cb (void)
 | 
			
		||||
 | 
			
		||||
#define N_BUTTONS 5
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
synthesize_motion_event (MetaWaylandCompositor *compositor,
 | 
			
		||||
                         const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  /* We want to synthesize X events for mouse motion events so that we
 | 
			
		||||
     don't have to rely on the X server's window position being
 | 
			
		||||
     synched with the surface position. See the comment in
 | 
			
		||||
     event_callback() in display.c */
 | 
			
		||||
  MetaWaylandSeat *seat = compositor->seat;
 | 
			
		||||
  MetaWaylandPointer *pointer = &seat->pointer;
 | 
			
		||||
  MetaWaylandSurface *surface;
 | 
			
		||||
  XGenericEventCookie generic_event;
 | 
			
		||||
  XIDeviceEvent device_event;
 | 
			
		||||
  unsigned char button_mask[(N_BUTTONS + 7) / 8] = { 0 };
 | 
			
		||||
  MetaDisplay *display = meta_get_display ();
 | 
			
		||||
  ClutterModifierType state;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  generic_event.type = GenericEvent;
 | 
			
		||||
  generic_event.serial = 0;
 | 
			
		||||
  generic_event.send_event = False;
 | 
			
		||||
  generic_event.display = display->xdisplay;
 | 
			
		||||
  generic_event.extension = display->xinput_opcode;
 | 
			
		||||
  generic_event.evtype = XI_Motion;
 | 
			
		||||
  /* Mutter assumes the data for the event is already retrieved by GDK
 | 
			
		||||
   * so we don't need the cookie */
 | 
			
		||||
  generic_event.cookie = 0;
 | 
			
		||||
  generic_event.data = &device_event;
 | 
			
		||||
 | 
			
		||||
  memcpy (&device_event, &generic_event, sizeof (XGenericEvent));
 | 
			
		||||
 | 
			
		||||
  device_event.time = clutter_event_get_time (event);
 | 
			
		||||
  device_event.deviceid = clutter_event_get_device_id (event);
 | 
			
		||||
  device_event.sourceid = 0; /* not used, not sure what this should be */
 | 
			
		||||
  device_event.detail = 0;
 | 
			
		||||
  device_event.root = DefaultRootWindow (display->xdisplay);
 | 
			
		||||
  device_event.flags = 0 /* not used for motion events */;
 | 
			
		||||
 | 
			
		||||
  if (compositor->implicit_grab_surface)
 | 
			
		||||
    surface = compositor->implicit_grab_surface;
 | 
			
		||||
  else
 | 
			
		||||
    surface = pointer->current;
 | 
			
		||||
 | 
			
		||||
  if (surface == pointer->current)
 | 
			
		||||
    {
 | 
			
		||||
      device_event.event_x = wl_fixed_to_int (pointer->current_x);
 | 
			
		||||
      device_event.event_y = wl_fixed_to_int (pointer->current_y);
 | 
			
		||||
    }
 | 
			
		||||
  else if (surface && surface->window)
 | 
			
		||||
    {
 | 
			
		||||
      ClutterActor *window_actor =
 | 
			
		||||
        CLUTTER_ACTOR (meta_window_get_compositor_private (surface->window));
 | 
			
		||||
 | 
			
		||||
      if (window_actor)
 | 
			
		||||
        {
 | 
			
		||||
          float ax, ay;
 | 
			
		||||
 | 
			
		||||
          clutter_actor_transform_stage_point (window_actor,
 | 
			
		||||
                                               wl_fixed_to_double (pointer->x),
 | 
			
		||||
                                               wl_fixed_to_double (pointer->y),
 | 
			
		||||
                                               &ax, &ay);
 | 
			
		||||
 | 
			
		||||
          device_event.event_x = ax;
 | 
			
		||||
          device_event.event_y = ay;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          device_event.event_x = wl_fixed_to_double (pointer->x);
 | 
			
		||||
          device_event.event_y = wl_fixed_to_double (pointer->y);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      device_event.event_x = wl_fixed_to_double (pointer->x);
 | 
			
		||||
      device_event.event_y = wl_fixed_to_double (pointer->y);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (surface && surface->xid != None)
 | 
			
		||||
    device_event.event = surface->xid;
 | 
			
		||||
  else
 | 
			
		||||
    device_event.event = device_event.root;
 | 
			
		||||
 | 
			
		||||
  /* Mutter doesn't really know about the sub-windows. This assumes it
 | 
			
		||||
     doesn't care either */
 | 
			
		||||
  device_event.child = device_event.event;
 | 
			
		||||
  device_event.root_x = wl_fixed_to_double (pointer->x);
 | 
			
		||||
  device_event.root_y = wl_fixed_to_double (pointer->y);
 | 
			
		||||
 | 
			
		||||
  state = clutter_event_get_state (event);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < N_BUTTONS; i++)
 | 
			
		||||
    if ((state & (CLUTTER_BUTTON1_MASK << i)))
 | 
			
		||||
      XISetMask (button_mask, i + 1);
 | 
			
		||||
  device_event.buttons.mask_len = N_BUTTONS + 1;
 | 
			
		||||
  device_event.buttons.mask = button_mask;
 | 
			
		||||
 | 
			
		||||
  device_event.valuators.mask_len = 0;
 | 
			
		||||
  device_event.valuators.mask = NULL;
 | 
			
		||||
  device_event.valuators.values = NULL;
 | 
			
		||||
 | 
			
		||||
  memset (&device_event.mods, 0, sizeof (device_event.mods));
 | 
			
		||||
  device_event.mods.effective =
 | 
			
		||||
    state & (CLUTTER_MODIFIER_MASK &
 | 
			
		||||
             ~(((CLUTTER_BUTTON1_MASK << N_BUTTONS) - 1) ^
 | 
			
		||||
               (CLUTTER_BUTTON1_MASK - 1)));
 | 
			
		||||
 | 
			
		||||
  memset (&device_event.group, 0, sizeof (device_event.group));
 | 
			
		||||
 | 
			
		||||
  meta_display_handle_event (display, (XEvent *) &generic_event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
reset_idletimes (const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
@@ -667,10 +559,10 @@ reset_idletimes (const ClutterEvent *event)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
event_cb (ClutterActor *stage,
 | 
			
		||||
          const ClutterEvent *event,
 | 
			
		||||
          MetaWaylandCompositor *compositor)
 | 
			
		||||
event_filter_cb (const ClutterEvent *event,
 | 
			
		||||
                 gpointer            user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandCompositor *compositor = user_data;
 | 
			
		||||
  MetaWaylandSeat *seat = compositor->seat;
 | 
			
		||||
  MetaWaylandPointer *pointer = &seat->pointer;
 | 
			
		||||
  MetaWaylandSurface *surface;
 | 
			
		||||
@@ -678,7 +570,8 @@ event_cb (ClutterActor *stage,
 | 
			
		||||
 | 
			
		||||
  reset_idletimes (event);
 | 
			
		||||
 | 
			
		||||
  meta_wayland_seat_handle_event (compositor->seat, event);
 | 
			
		||||
  if (meta_wayland_seat_handle_event (compositor->seat, event))
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  /* HACK: for now, the surfaces from Wayland clients aren't
 | 
			
		||||
     integrated into Mutter's event handling and Mutter won't give them
 | 
			
		||||
@@ -708,7 +601,8 @@ event_cb (ClutterActor *stage,
 | 
			
		||||
      if (pointer->current == NULL)
 | 
			
		||||
	meta_cursor_tracker_revert_root (seat->cursor_tracker);
 | 
			
		||||
 | 
			
		||||
      meta_cursor_tracker_queue_redraw (seat->cursor_tracker, stage);
 | 
			
		||||
      meta_cursor_tracker_queue_redraw (seat->cursor_tracker,
 | 
			
		||||
                                        CLUTTER_ACTOR (event->any.stage));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  display = meta_get_display ();
 | 
			
		||||
@@ -732,67 +626,11 @@ event_cb (ClutterActor *stage,
 | 
			
		||||
        compositor->implicit_grab_surface = NULL;
 | 
			
		||||
      return FALSE;
 | 
			
		||||
 | 
			
		||||
    case CLUTTER_MOTION:
 | 
			
		||||
      synthesize_motion_event (compositor, event);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
event_emission_hook_cb (GSignalInvocationHint *ihint,
 | 
			
		||||
                        guint n_param_values,
 | 
			
		||||
                        const GValue *param_values,
 | 
			
		||||
                        gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandCompositor *compositor = data;
 | 
			
		||||
  ClutterActor *actor;
 | 
			
		||||
  ClutterEvent *event;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (n_param_values == 2, FALSE);
 | 
			
		||||
 | 
			
		||||
  actor = g_value_get_object (param_values + 0);
 | 
			
		||||
  event = g_value_get_boxed (param_values + 1);
 | 
			
		||||
 | 
			
		||||
  if (actor == NULL)
 | 
			
		||||
    return TRUE /* stay connected */;
 | 
			
		||||
 | 
			
		||||
  /* If this event belongs to the corresponding grab for this event
 | 
			
		||||
   * type then the captured-event signal won't be emitted so we have
 | 
			
		||||
   * to manually forward it on */
 | 
			
		||||
 | 
			
		||||
  switch (event->type)
 | 
			
		||||
    {
 | 
			
		||||
      /* Pointer events */
 | 
			
		||||
    case CLUTTER_MOTION:
 | 
			
		||||
    case CLUTTER_ENTER:
 | 
			
		||||
    case CLUTTER_LEAVE:
 | 
			
		||||
    case CLUTTER_BUTTON_PRESS:
 | 
			
		||||
    case CLUTTER_BUTTON_RELEASE:
 | 
			
		||||
    case CLUTTER_SCROLL:
 | 
			
		||||
      if (actor == clutter_get_pointer_grab ())
 | 
			
		||||
        event_cb (clutter_actor_get_stage (actor),
 | 
			
		||||
                  event,
 | 
			
		||||
                  compositor);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
      /* Keyboard events */
 | 
			
		||||
    case CLUTTER_KEY_PRESS:
 | 
			
		||||
    case CLUTTER_KEY_RELEASE:
 | 
			
		||||
      if (actor == clutter_get_keyboard_grab ())
 | 
			
		||||
        event_cb (clutter_actor_get_stage (actor),
 | 
			
		||||
                  event,
 | 
			
		||||
                  compositor);
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE /* stay connected */;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_monitors_changed (MetaMonitorManager    *monitors,
 | 
			
		||||
                     MetaWaylandCompositor *compositor)
 | 
			
		||||
@@ -800,15 +638,44 @@ on_monitors_changed (MetaMonitorManager    *monitors,
 | 
			
		||||
  compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_gnome_env (const char *name,
 | 
			
		||||
	       const char *value)
 | 
			
		||||
{
 | 
			
		||||
  GDBusConnection *session_bus;
 | 
			
		||||
  GError *error;
 | 
			
		||||
 | 
			
		||||
  setenv (name, value, TRUE);
 | 
			
		||||
 | 
			
		||||
  session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
 | 
			
		||||
  g_assert (session_bus);
 | 
			
		||||
 | 
			
		||||
  error = NULL;
 | 
			
		||||
  g_dbus_connection_call_sync (session_bus,
 | 
			
		||||
			       "org.gnome.SessionManager",
 | 
			
		||||
			       "/org/gnome/SessionManager",
 | 
			
		||||
			       "org.gnome.SessionManager",
 | 
			
		||||
			       "Setenv",
 | 
			
		||||
			       g_variant_new ("(ss)", name, value),
 | 
			
		||||
			       NULL,
 | 
			
		||||
			       G_DBUS_CALL_FLAGS_NONE,
 | 
			
		||||
			       -1, NULL, &error);
 | 
			
		||||
  if (error)
 | 
			
		||||
    {
 | 
			
		||||
      meta_warning ("Failed to set environment variable %s for gnome-session: %s\n", name, error->message);
 | 
			
		||||
      g_clear_error (&error);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_init (void)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
 | 
			
		||||
  guint event_signal;
 | 
			
		||||
  MetaMonitorManager *monitors;
 | 
			
		||||
  ClutterBackend *backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
  CoglRenderer *cogl_renderer;
 | 
			
		||||
  char *display_name;
 | 
			
		||||
 | 
			
		||||
  memset (compositor, 0, sizeof (MetaWaylandCompositor));
 | 
			
		||||
 | 
			
		||||
@@ -851,6 +718,9 @@ meta_wayland_init (void)
 | 
			
		||||
  if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
 | 
			
		||||
    g_error ("Failed to initialize Clutter");
 | 
			
		||||
 | 
			
		||||
  unsetenv ("CLUTTER_BACKEND");
 | 
			
		||||
  unsetenv ("CLUTTER_INPUT_BACKEND");
 | 
			
		||||
 | 
			
		||||
  backend = clutter_get_default_backend ();
 | 
			
		||||
  cogl_context = clutter_backend_get_cogl_context (backend);
 | 
			
		||||
  cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (cogl_context));
 | 
			
		||||
@@ -891,20 +761,7 @@ meta_wayland_init (void)
 | 
			
		||||
  compositor->seat = meta_wayland_seat_new (compositor->wayland_display,
 | 
			
		||||
					    compositor->drm_fd >= 0);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (compositor->stage,
 | 
			
		||||
                    "captured-event",
 | 
			
		||||
                    G_CALLBACK (event_cb),
 | 
			
		||||
                    compositor);
 | 
			
		||||
  /* If something sets a grab on an actor then the captured event
 | 
			
		||||
   * signal won't get emitted but we still want to see these events so
 | 
			
		||||
   * we can update the cursor position. To make sure we see all events
 | 
			
		||||
   * we also install an emission hook on the event signal */
 | 
			
		||||
  event_signal = g_signal_lookup ("event", CLUTTER_TYPE_STAGE);
 | 
			
		||||
  g_signal_add_emission_hook (event_signal,
 | 
			
		||||
                              0 /* detail */,
 | 
			
		||||
                              event_emission_hook_cb,
 | 
			
		||||
                              compositor, /* hook_data */
 | 
			
		||||
                              NULL /* data_destroy */);
 | 
			
		||||
  clutter_event_add_filter (event_filter_cb, compositor);
 | 
			
		||||
 | 
			
		||||
  meta_wayland_init_shell (compositor);
 | 
			
		||||
 | 
			
		||||
@@ -926,7 +783,11 @@ meta_wayland_init (void)
 | 
			
		||||
  if (!meta_xwayland_start (compositor))
 | 
			
		||||
    g_error ("Failed to start X Wayland");
 | 
			
		||||
 | 
			
		||||
  putenv (g_strdup_printf ("DISPLAY=:%d", compositor->xwayland_display_index));
 | 
			
		||||
  display_name = g_strdup_printf (":%d", compositor->xwayland_display_index);
 | 
			
		||||
  set_gnome_env ("DISPLAY", display_name);
 | 
			
		||||
  g_free (display_name);
 | 
			
		||||
 | 
			
		||||
  set_gnome_env ("WAYLAND_DISPLAY", "wayland-0");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -936,6 +797,8 @@ meta_wayland_finalize (void)
 | 
			
		||||
 | 
			
		||||
  compositor = meta_wayland_compositor_get_default ();
 | 
			
		||||
 | 
			
		||||
  clutter_event_remove_filter (event_filter_cb, compositor);
 | 
			
		||||
 | 
			
		||||
  meta_xwayland_stop (compositor);
 | 
			
		||||
  g_clear_object (&compositor->launcher);
 | 
			
		||||
}
 | 
			
		||||
@@ -945,3 +808,9 @@ meta_wayland_compositor_get_launcher (MetaWaylandCompositor *compositor)
 | 
			
		||||
{
 | 
			
		||||
  return compositor->launcher;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_compositor_is_native (MetaWaylandCompositor *compositor)
 | 
			
		||||
{
 | 
			
		||||
  return compositor->drm_fd >= 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -45,10 +45,6 @@ xserver_set_window_id (struct wl_client *client,
 | 
			
		||||
  MetaDisplay *display = meta_get_display ();
 | 
			
		||||
  MetaWindow *window;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (surface->xid == None);
 | 
			
		||||
 | 
			
		||||
  surface->xid = xid;
 | 
			
		||||
 | 
			
		||||
  window  = meta_display_lookup_x_window (display, xid);
 | 
			
		||||
  if (window)
 | 
			
		||||
    {
 | 
			
		||||
@@ -269,7 +265,7 @@ bind_to_unix_socket (int display)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
uncloexec_and_setpgid (gpointer user_data)
 | 
			
		||||
uncloexec (gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  int fd = GPOINTER_TO_INT (user_data);
 | 
			
		||||
 | 
			
		||||
@@ -278,10 +274,6 @@ uncloexec_and_setpgid (gpointer user_data)
 | 
			
		||||
  int flags = fcntl (fd, F_GETFD);
 | 
			
		||||
  if (flags != -1)
 | 
			
		||||
    fcntl (fd, F_SETFD, flags & ~FD_CLOEXEC);
 | 
			
		||||
 | 
			
		||||
  /* Put this process in a background process group, so that Ctrl-C
 | 
			
		||||
     goes to mutter only */
 | 
			
		||||
  setpgid (0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -401,7 +393,7 @@ meta_xwayland_start (MetaWaylandCompositor *compositor)
 | 
			
		||||
                     G_SPAWN_DO_NOT_REAP_CHILD |
 | 
			
		||||
                     G_SPAWN_STDOUT_TO_DEV_NULL |
 | 
			
		||||
                     G_SPAWN_STDERR_TO_DEV_NULL,
 | 
			
		||||
                     uncloexec_and_setpgid,
 | 
			
		||||
                     uncloexec,
 | 
			
		||||
                     GINT_TO_POINTER (sp[1]),
 | 
			
		||||
                     &pid,
 | 
			
		||||
                     &error))
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user