1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 
3 /*
4  * Copyright (C) 2014 Red Hat
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19  * 02111-1307, USA.
20  *
21  * Written by:
22  *     Jasper St. Pierre <jstpierre@mecheye.net>
23  */
24 
25 /**
26  * SECTION:meta-backend-native
27  * @title: MetaBackendNative
28  * @short_description: A native (KMS/evdev) MetaBackend
29  *
30  * MetaBackendNative is an implementation of #MetaBackend that uses "native"
31  * technologies like DRM/KMS and libinput/evdev to perform the necessary
32  * functions.
33  */
34 
35 #include "config.h"
36 
37 #include "backends/native/meta-backend-native.h"
38 #include "backends/native/meta-backend-native-private.h"
39 #include "backends/native/meta-input-thread.h"
40 
41 #include <sched.h>
42 #include <stdlib.h>
43 
44 #include "backends/meta-cursor-tracker-private.h"
45 #include "backends/meta-idle-manager.h"
46 #include "backends/meta-keymap-utils.h"
47 #include "backends/meta-logical-monitor.h"
48 #include "backends/meta-monitor-manager-private.h"
49 #include "backends/meta-pointer-constraint.h"
50 #include "backends/meta-settings-private.h"
51 #include "backends/meta-stage-private.h"
52 #include "backends/native/meta-clutter-backend-native.h"
53 #include "backends/native/meta-device-pool-private.h"
54 #include "backends/native/meta-kms.h"
55 #include "backends/native/meta-kms-device.h"
56 #include "backends/native/meta-launcher.h"
57 #include "backends/native/meta-monitor-manager-native.h"
58 #include "backends/native/meta-renderer-native.h"
59 #include "backends/native/meta-seat-native.h"
60 #include "backends/native/meta-stage-native.h"
61 #include "cogl/cogl.h"
62 #include "core/meta-border.h"
63 #include "meta/main.h"
64 
65 #ifdef HAVE_REMOTE_DESKTOP
66 #include "backends/meta-screen-cast.h"
67 #endif
68 
69 enum
70 {
71   PROP_0,
72 
73   PROP_HEADLESS,
74 
75   N_PROPS
76 };
77 
78 static GParamSpec *obj_props[N_PROPS];
79 
80 struct _MetaBackendNative
81 {
82   MetaBackend parent;
83 
84   MetaLauncher *launcher;
85   MetaDevicePool *device_pool;
86   MetaUdev *udev;
87   MetaKms *kms;
88 
89   gboolean is_headless;
90 };
91 
92 static GInitableIface *initable_parent_iface;
93 
94 static void
95 initable_iface_init (GInitableIface *initable_iface);
96 
G_DEFINE_TYPE_WITH_CODE(MetaBackendNative,meta_backend_native,META_TYPE_BACKEND,G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,initable_iface_init))97 G_DEFINE_TYPE_WITH_CODE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND,
98                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
99                                                 initable_iface_init))
100 
101 static void
102 meta_backend_native_dispose (GObject *object)
103 {
104   MetaBackendNative *native = META_BACKEND_NATIVE (object);
105 
106   if (native->kms)
107     meta_kms_prepare_shutdown (native->kms);
108 
109   G_OBJECT_CLASS (meta_backend_native_parent_class)->dispose (object);
110 
111   g_clear_object (&native->kms);
112   g_clear_object (&native->udev);
113   g_clear_object (&native->device_pool);
114   g_clear_pointer (&native->launcher, meta_launcher_free);
115 }
116 
117 static ClutterBackend *
meta_backend_native_create_clutter_backend(MetaBackend * backend)118 meta_backend_native_create_clutter_backend (MetaBackend *backend)
119 {
120   return g_object_new (META_TYPE_CLUTTER_BACKEND_NATIVE, NULL);
121 }
122 
123 static ClutterSeat *
meta_backend_native_create_default_seat(MetaBackend * backend,GError ** error)124 meta_backend_native_create_default_seat (MetaBackend  *backend,
125                                          GError      **error)
126 {
127   MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
128   const char *seat_id;
129   MetaSeatNativeFlag flags;
130 
131   seat_id = meta_backend_native_get_seat_id (backend_native);
132 
133   if (meta_backend_native_is_headless (backend_native))
134     flags = META_SEAT_NATIVE_FLAG_NO_LIBINPUT;
135   else
136     flags = META_SEAT_NATIVE_FLAG_NONE;
137 
138   return CLUTTER_SEAT (g_object_new (META_TYPE_SEAT_NATIVE,
139                                      "backend", backend,
140                                      "seat-id", seat_id,
141                                      "flags", flags,
142                                      NULL));
143 }
144 
145 #ifdef HAVE_REMOTE_DESKTOP
146 static void
maybe_disable_screen_cast_dma_bufs(MetaBackendNative * native)147 maybe_disable_screen_cast_dma_bufs (MetaBackendNative *native)
148 {
149   MetaBackend *backend = META_BACKEND (native);
150   MetaSettings *settings = meta_backend_get_settings (backend);
151   MetaRenderer *renderer = meta_backend_get_renderer (backend);
152   MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
153   MetaScreenCast *screen_cast = meta_backend_get_screen_cast (backend);
154   MetaGpuKms *primary_gpu;
155   MetaKmsDevice *kms_device;
156   const char *driver_name;
157   static const char *enable_dma_buf_drivers[] = {
158     "i915",
159     NULL,
160   };
161 
162   primary_gpu = meta_renderer_native_get_primary_gpu (renderer_native);
163   if (!primary_gpu)
164     {
165       g_message ("Disabling DMA buffer screen sharing (surfaceless)");
166       goto disable_dma_bufs;
167     }
168 
169   kms_device = meta_gpu_kms_get_kms_device (primary_gpu);
170   driver_name = meta_kms_device_get_driver_name (kms_device);
171 
172   if (g_strv_contains (enable_dma_buf_drivers, driver_name))
173     return;
174 
175   if (meta_settings_is_experimental_feature_enabled (settings,
176         META_EXPERIMENTAL_FEATURE_DMA_BUF_SCREEN_SHARING))
177     return;
178 
179   g_message ("Disabling DMA buffer screen sharing for driver '%s'.",
180              driver_name);
181 
182 disable_dma_bufs:
183   meta_screen_cast_disable_dma_bufs (screen_cast);
184 }
185 #endif /* HAVE_REMOTE_DESKTOP */
186 
187 static void
update_viewports(MetaBackend * backend)188 update_viewports (MetaBackend *backend)
189 {
190   MetaMonitorManager *monitor_manager =
191     meta_backend_get_monitor_manager (backend);
192   ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
193   MetaSeatNative *seat =
194     META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));
195   MetaViewportInfo *viewports;
196 
197   viewports = meta_monitor_manager_get_viewports (monitor_manager);
198   meta_seat_native_set_viewports (seat, viewports);
199   g_object_unref (viewports);
200 }
201 
202 static void
meta_backend_native_post_init(MetaBackend * backend)203 meta_backend_native_post_init (MetaBackend *backend)
204 {
205   MetaSettings *settings = meta_backend_get_settings (backend);
206 
207   META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend);
208 
209   if (meta_settings_is_experimental_feature_enabled (settings,
210                                                      META_EXPERIMENTAL_FEATURE_RT_SCHEDULER))
211     {
212       int retval;
213       struct sched_param sp = {
214         .sched_priority = sched_get_priority_min (SCHED_RR)
215       };
216 
217       retval = sched_setscheduler (0, SCHED_RR | SCHED_RESET_ON_FORK, &sp);
218 
219       if (retval != 0)
220         g_warning ("Failed to set RT scheduler: %m");
221     }
222 
223 #ifdef HAVE_REMOTE_DESKTOP
224   maybe_disable_screen_cast_dma_bufs (META_BACKEND_NATIVE (backend));
225 #endif
226 
227   update_viewports (backend);
228 }
229 
230 static MetaMonitorManager *
meta_backend_native_create_monitor_manager(MetaBackend * backend,GError ** error)231 meta_backend_native_create_monitor_manager (MetaBackend *backend,
232                                             GError     **error)
233 {
234   MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
235   MetaMonitorManager *manager;
236 
237   manager = g_initable_new (META_TYPE_MONITOR_MANAGER_NATIVE, NULL, error,
238                             "backend", backend,
239                             "needs-outputs", !backend_native->is_headless,
240                             NULL);
241   if (!manager)
242     return NULL;
243 
244   g_signal_connect_swapped (manager, "monitors-changed-internal",
245                             G_CALLBACK (update_viewports), backend);
246 
247   return manager;
248 }
249 
250 static MetaCursorRenderer *
meta_backend_native_get_cursor_renderer(MetaBackend * backend,ClutterInputDevice * device)251 meta_backend_native_get_cursor_renderer (MetaBackend        *backend,
252                                          ClutterInputDevice *device)
253 {
254   ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
255   MetaSeatNative *seat_native =
256     META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));
257 
258   return meta_seat_native_maybe_ensure_cursor_renderer (seat_native, device);
259 }
260 
261 static MetaRenderer *
meta_backend_native_create_renderer(MetaBackend * backend,GError ** error)262 meta_backend_native_create_renderer (MetaBackend *backend,
263                                      GError     **error)
264 {
265   MetaBackendNative *native = META_BACKEND_NATIVE (backend);
266   MetaRendererNative *renderer_native;
267 
268   renderer_native = meta_renderer_native_new (native, error);
269   if (!renderer_native)
270     return NULL;
271 
272   return META_RENDERER (renderer_native);
273 }
274 
275 static MetaInputSettings *
meta_backend_native_get_input_settings(MetaBackend * backend)276 meta_backend_native_get_input_settings (MetaBackend *backend)
277 {
278   ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
279   MetaSeatNative *seat_native =
280     META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));
281 
282   return meta_seat_impl_get_input_settings (seat_native->impl);
283 }
284 
285 static MetaLogicalMonitor *
meta_backend_native_get_current_logical_monitor(MetaBackend * backend)286 meta_backend_native_get_current_logical_monitor (MetaBackend *backend)
287 {
288   MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
289   MetaMonitorManager *monitor_manager =
290     meta_backend_get_monitor_manager (backend);
291   graphene_point_t point;
292 
293   meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL);
294   return meta_monitor_manager_get_logical_monitor_at (monitor_manager,
295                                                       point.x, point.y);
296 }
297 
298 static void
meta_backend_native_set_keymap(MetaBackend * backend,const char * layouts,const char * variants,const char * options)299 meta_backend_native_set_keymap (MetaBackend *backend,
300                                 const char  *layouts,
301                                 const char  *variants,
302                                 const char  *options)
303 {
304   ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
305   ClutterSeat *seat;
306 
307   seat = clutter_backend_get_default_seat (clutter_backend);
308   meta_seat_native_set_keyboard_map (META_SEAT_NATIVE (seat),
309                                      layouts, variants, options);
310 
311   meta_backend_notify_keymap_changed (backend);
312 }
313 
314 static struct xkb_keymap *
meta_backend_native_get_keymap(MetaBackend * backend)315 meta_backend_native_get_keymap (MetaBackend *backend)
316 {
317   ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
318   ClutterSeat *seat;
319 
320   seat = clutter_backend_get_default_seat (clutter_backend);
321   return meta_seat_native_get_keyboard_map (META_SEAT_NATIVE (seat));
322 }
323 
324 static xkb_layout_index_t
meta_backend_native_get_keymap_layout_group(MetaBackend * backend)325 meta_backend_native_get_keymap_layout_group (MetaBackend *backend)
326 {
327   ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
328   ClutterSeat *seat;
329 
330   seat = clutter_backend_get_default_seat (clutter_backend);
331   return meta_seat_native_get_keyboard_layout_index (META_SEAT_NATIVE (seat));
332 }
333 
334 static void
meta_backend_native_lock_layout_group(MetaBackend * backend,guint idx)335 meta_backend_native_lock_layout_group (MetaBackend *backend,
336                                        guint        idx)
337 {
338   ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
339   xkb_layout_index_t old_idx;
340   ClutterSeat *seat;
341 
342   old_idx = meta_backend_native_get_keymap_layout_group (backend);
343   if (old_idx == idx)
344     return;
345 
346   seat = clutter_backend_get_default_seat (clutter_backend);
347   meta_seat_native_set_keyboard_layout_index (META_SEAT_NATIVE (seat), idx);
348   meta_backend_notify_keymap_layout_group_changed (backend, idx);
349 }
350 
351 const char *
meta_backend_native_get_seat_id(MetaBackendNative * backend_native)352 meta_backend_native_get_seat_id (MetaBackendNative *backend_native)
353 {
354   if (backend_native->is_headless)
355     return "seat0";
356   else
357     return meta_launcher_get_seat_id (backend_native->launcher);
358 }
359 
360 gboolean
meta_backend_native_is_headless(MetaBackendNative * backend_native)361 meta_backend_native_is_headless (MetaBackendNative *backend_native)
362 {
363   return backend_native->is_headless;
364 }
365 
366 static void
meta_backend_native_set_pointer_constraint(MetaBackend * backend,MetaPointerConstraint * constraint)367 meta_backend_native_set_pointer_constraint (MetaBackend           *backend,
368                                             MetaPointerConstraint *constraint)
369 {
370   ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
371   ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend);
372   MetaPointerConstraintImpl *constraint_impl = NULL;
373   cairo_region_t *region;
374 
375   if (constraint)
376     {
377       region = meta_pointer_constraint_get_region (constraint);
378       constraint_impl = meta_pointer_constraint_impl_native_new (constraint,
379                                                                  region);
380     }
381 
382   meta_seat_native_set_pointer_constraint (META_SEAT_NATIVE (seat),
383                                            constraint_impl);
384 }
385 
386 static void
meta_backend_native_update_screen_size(MetaBackend * backend,int width,int height)387 meta_backend_native_update_screen_size (MetaBackend *backend,
388                                         int width, int height)
389 {
390   ClutterActor *stage = meta_backend_get_stage (backend);
391   ClutterStageWindow *stage_window =
392     _clutter_stage_get_window (CLUTTER_STAGE (stage));
393   MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window);
394 
395   meta_stage_native_rebuild_views (stage_native);
396 
397   clutter_actor_set_size (stage, width, height);
398 }
399 
400 static MetaGpuKms *
create_gpu_from_udev_device(MetaBackendNative * native,GUdevDevice * device,GError ** error)401 create_gpu_from_udev_device (MetaBackendNative  *native,
402                              GUdevDevice        *device,
403                              GError            **error)
404 {
405   MetaKmsDeviceFlag flags = META_KMS_DEVICE_FLAG_NONE;
406   const char *device_path;
407   MetaKmsDevice *kms_device;
408 
409   if (meta_is_udev_device_platform_device (device))
410     flags |= META_KMS_DEVICE_FLAG_PLATFORM_DEVICE;
411 
412   if (meta_is_udev_device_boot_vga (device))
413     flags |= META_KMS_DEVICE_FLAG_BOOT_VGA;
414 
415   if (meta_is_udev_device_disable_modifiers (device))
416     flags |= META_KMS_DEVICE_FLAG_DISABLE_MODIFIERS;
417 
418   if (meta_is_udev_device_preferred_primary (device))
419     flags |= META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY;
420 
421   device_path = g_udev_device_get_device_file (device);
422 
423   kms_device = meta_kms_create_device (native->kms, device_path, flags,
424                                        error);
425   if (!kms_device)
426     return NULL;
427 
428   return meta_gpu_kms_new (native, kms_device, error);
429 }
430 
431 static void
on_udev_device_added(MetaUdev * udev,GUdevDevice * device,MetaBackendNative * native)432 on_udev_device_added (MetaUdev          *udev,
433                       GUdevDevice       *device,
434                       MetaBackendNative *native)
435 {
436   MetaBackend *backend = META_BACKEND (native);
437   g_autoptr (GError) error = NULL;
438   const char *device_path;
439   MetaGpuKms *new_gpu_kms;
440   GList *gpus, *l;
441 
442   if (!meta_udev_is_drm_device (udev, device))
443     return;
444 
445   device_path = g_udev_device_get_device_file (device);
446 
447   gpus = meta_backend_get_gpus (backend);
448   for (l = gpus; l; l = l->next)
449     {
450       MetaGpuKms *gpu_kms = l->data;
451 
452       if (!g_strcmp0 (device_path, meta_gpu_kms_get_file_path (gpu_kms)))
453         {
454           g_warning ("Failed to hotplug secondary gpu '%s': %s",
455                      device_path, "device already present");
456           return;
457         }
458     }
459 
460   if (meta_is_udev_device_ignore (device))
461     {
462       g_message ("Ignoring DRM device '%s' (from udev rule)", device_path);
463       return;
464     }
465 
466   new_gpu_kms = create_gpu_from_udev_device (native, device, &error);
467   if (!new_gpu_kms)
468     {
469       g_warning ("Failed to hotplug secondary gpu '%s': %s",
470                  device_path, error->message);
471       return;
472     }
473 
474   meta_backend_add_gpu (backend, META_GPU (new_gpu_kms));
475 }
476 
477 static gboolean
init_gpus(MetaBackendNative * native,GError ** error)478 init_gpus (MetaBackendNative  *native,
479            GError            **error)
480 {
481   MetaBackend *backend = META_BACKEND (native);
482   MetaUdev *udev = meta_backend_native_get_udev (native);
483   GList *devices;
484   GList *l;
485 
486   devices = meta_udev_list_drm_devices (udev, error);
487   if (*error)
488     return FALSE;
489 
490   for (l = devices; l; l = l->next)
491     {
492       GUdevDevice *device = l->data;
493       MetaGpuKms *gpu_kms;
494       GError *local_error = NULL;
495 
496       if (meta_is_udev_device_ignore (device))
497         {
498           g_message ("Ignoring DRM device '%s' (from udev rule)",
499                      g_udev_device_get_device_file (device));
500           continue;
501         }
502 
503       gpu_kms = create_gpu_from_udev_device (native, device, &local_error);
504 
505       if (!gpu_kms)
506         {
507           g_warning ("Failed to open gpu '%s': %s",
508                      g_udev_device_get_device_file (device),
509                      local_error->message);
510           g_clear_error (&local_error);
511           continue;
512         }
513 
514       meta_backend_add_gpu (backend, META_GPU (gpu_kms));
515     }
516 
517   g_list_free_full (devices, g_object_unref);
518 
519   if (!native->is_headless &&
520       g_list_length (meta_backend_get_gpus (backend)) == 0)
521     {
522       g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
523                    "No GPUs found");
524       return FALSE;
525     }
526 
527   g_signal_connect_object (native->udev, "device-added",
528                            G_CALLBACK (on_udev_device_added), native,
529                            0);
530 
531   return TRUE;
532 }
533 
534 static gboolean
meta_backend_native_initable_init(GInitable * initable,GCancellable * cancellable,GError ** error)535 meta_backend_native_initable_init (GInitable     *initable,
536                                    GCancellable  *cancellable,
537                                    GError       **error)
538 {
539   MetaBackendNative *native = META_BACKEND_NATIVE (initable);
540   MetaKmsFlags kms_flags;
541 
542   if (!meta_is_stage_views_enabled ())
543     {
544       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
545                    "The native backend requires stage views");
546       return FALSE;
547     }
548 
549   if (!native->is_headless)
550     {
551       native->launcher = meta_launcher_new (error);
552       if (!native->launcher)
553         return FALSE;
554     }
555 
556   native->device_pool = meta_device_pool_new (native->launcher);
557   native->udev = meta_udev_new (native);
558 
559   kms_flags = META_KMS_FLAG_NONE;
560   if (native->is_headless)
561     kms_flags |= META_KMS_FLAG_NO_MODE_SETTING;
562 
563   native->kms = meta_kms_new (META_BACKEND (native), kms_flags, error);
564   if (!native->kms)
565     return FALSE;
566 
567   if (!init_gpus (native, error))
568     return FALSE;
569 
570   return initable_parent_iface->init (initable, cancellable, error);
571 }
572 
573 static void
meta_backend_native_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)574 meta_backend_native_set_property (GObject      *object,
575                                   guint         prop_id,
576                                   const GValue *value,
577                                   GParamSpec   *pspec)
578 {
579   MetaBackendNative *backend_native = META_BACKEND_NATIVE (object);
580 
581   switch (prop_id)
582     {
583     case PROP_HEADLESS:
584       backend_native->is_headless = g_value_get_boolean (value);
585       break;
586     default:
587       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
588       break;
589     }
590 }
591 
592 static void
initable_iface_init(GInitableIface * initable_iface)593 initable_iface_init (GInitableIface *initable_iface)
594 {
595   initable_parent_iface = g_type_interface_peek_parent (initable_iface);
596 
597   initable_iface->init = meta_backend_native_initable_init;
598 }
599 
600 static void
meta_backend_native_class_init(MetaBackendNativeClass * klass)601 meta_backend_native_class_init (MetaBackendNativeClass *klass)
602 {
603   MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
604   GObjectClass *object_class = G_OBJECT_CLASS (klass);
605 
606   object_class->set_property = meta_backend_native_set_property;
607   object_class->dispose = meta_backend_native_dispose;
608 
609   backend_class->create_clutter_backend = meta_backend_native_create_clutter_backend;
610   backend_class->create_default_seat = meta_backend_native_create_default_seat;
611 
612   backend_class->post_init = meta_backend_native_post_init;
613 
614   backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager;
615   backend_class->get_cursor_renderer = meta_backend_native_get_cursor_renderer;
616   backend_class->create_renderer = meta_backend_native_create_renderer;
617   backend_class->get_input_settings = meta_backend_native_get_input_settings;
618 
619   backend_class->get_current_logical_monitor = meta_backend_native_get_current_logical_monitor;
620 
621   backend_class->set_keymap = meta_backend_native_set_keymap;
622   backend_class->get_keymap = meta_backend_native_get_keymap;
623   backend_class->get_keymap_layout_group = meta_backend_native_get_keymap_layout_group;
624   backend_class->lock_layout_group = meta_backend_native_lock_layout_group;
625   backend_class->update_screen_size = meta_backend_native_update_screen_size;
626 
627   backend_class->set_pointer_constraint = meta_backend_native_set_pointer_constraint;
628 
629   obj_props[PROP_HEADLESS] =
630     g_param_spec_boolean ("headless",
631                           "headless",
632                           "Headless",
633                           FALSE,
634                           G_PARAM_WRITABLE |
635                           G_PARAM_CONSTRUCT_ONLY |
636                           G_PARAM_STATIC_STRINGS);
637   g_object_class_install_properties (object_class, N_PROPS, obj_props);
638 }
639 
640 static void
meta_backend_native_init(MetaBackendNative * native)641 meta_backend_native_init (MetaBackendNative *native)
642 {
643 }
644 
645 MetaLauncher *
meta_backend_native_get_launcher(MetaBackendNative * native)646 meta_backend_native_get_launcher (MetaBackendNative *native)
647 {
648   return native->launcher;
649 }
650 
651 MetaDevicePool *
meta_backend_native_get_device_pool(MetaBackendNative * native)652 meta_backend_native_get_device_pool (MetaBackendNative *native)
653 {
654   return native->device_pool;
655 }
656 
657 MetaUdev *
meta_backend_native_get_udev(MetaBackendNative * native)658 meta_backend_native_get_udev (MetaBackendNative *native)
659 {
660   return native->udev;
661 }
662 
663 MetaKms *
meta_backend_native_get_kms(MetaBackendNative * native)664 meta_backend_native_get_kms (MetaBackendNative *native)
665 {
666   return native->kms;
667 }
668 
669 gboolean
meta_activate_vt(int vt,GError ** error)670 meta_activate_vt (int vt, GError **error)
671 {
672   MetaBackend *backend = meta_get_backend ();
673   MetaBackendNative *native = META_BACKEND_NATIVE (backend);
674   MetaLauncher *launcher = meta_backend_native_get_launcher (native);
675 
676   if (native->is_headless)
677     {
678       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
679                    "Can't switch VT while headless");
680       return FALSE;
681     }
682 
683   return meta_launcher_activate_vt (launcher, vt, error);
684 }
685 
686 void
meta_backend_native_pause(MetaBackendNative * native)687 meta_backend_native_pause (MetaBackendNative *native)
688 {
689   MetaBackend *backend = META_BACKEND (native);
690   MetaMonitorManager *monitor_manager =
691     meta_backend_get_monitor_manager (backend);
692   MetaMonitorManagerNative *monitor_manager_native =
693     META_MONITOR_MANAGER_NATIVE (monitor_manager);
694   ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
695   MetaSeatNative *seat =
696     META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));
697   MetaRenderer *renderer = meta_backend_get_renderer (backend);
698 
699   COGL_TRACE_BEGIN_SCOPED (MetaBackendNativePause,
700                            "Backend (pause)");
701 
702   meta_seat_native_release_devices (seat);
703   meta_renderer_pause (renderer);
704   meta_udev_pause (native->udev);
705 
706   meta_monitor_manager_native_pause (monitor_manager_native);
707 }
708 
meta_backend_native_resume(MetaBackendNative * native)709 void meta_backend_native_resume (MetaBackendNative *native)
710 {
711   MetaBackend *backend = META_BACKEND (native);
712   ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
713   MetaMonitorManager *monitor_manager =
714     meta_backend_get_monitor_manager (backend);
715   MetaMonitorManagerNative *monitor_manager_native =
716     META_MONITOR_MANAGER_NATIVE (monitor_manager);
717   ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
718   MetaSeatNative *seat =
719     META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));
720   MetaRenderer *renderer = meta_backend_get_renderer (backend);
721   MetaIdleManager *idle_manager;
722   MetaInputSettings *input_settings;
723 
724   COGL_TRACE_BEGIN_SCOPED (MetaBackendNativeResume,
725                            "Backend (resume)");
726 
727   meta_monitor_manager_native_resume (monitor_manager_native);
728   meta_udev_resume (native->udev);
729   meta_kms_resume (native->kms);
730 
731   meta_seat_native_reclaim_devices (seat);
732   meta_renderer_resume (renderer);
733 
734   clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
735 
736   idle_manager = meta_backend_get_idle_manager (backend);
737   meta_idle_manager_reset_idle_time (idle_manager);
738 
739   input_settings = meta_backend_get_input_settings (backend);
740   meta_input_settings_maybe_restore_numlock_state (input_settings);
741 
742   clutter_seat_ensure_a11y_state (CLUTTER_SEAT (seat));
743 }
744