Compare commits
	
		
			116 Commits
		
	
	
		
			wip/nields
			...
			wip/gbsnet
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | cf9136ecd6 | ||
|   | 6f436023ed | ||
|   | d147cc3ece | ||
|   | f980445a54 | ||
|   | 5977c1a183 | ||
|   | ff6ef0edc4 | ||
|   | 9583632bd0 | ||
|   | 0a1ea1407e | ||
|   | 8ba01d3373 | ||
|   | a47d42f2c6 | ||
|   | 1a0f53f5d2 | ||
|   | f627676878 | ||
|   | 66079b676f | ||
|   | c3acb5a6e9 | ||
|   | dbcb6e3341 | ||
|   | 1f3210f795 | ||
|   | a0eac7b417 | ||
|   | b9e1e28db8 | ||
|   | 3532766c3e | ||
|   | 881f7a07dc | ||
|   | a5e8aae839 | ||
|   | 7dbe79474b | ||
|   | 02b549bd0d | ||
|   | a56a6a43aa | ||
|   | 45190c46b5 | ||
|   | 23ef452721 | ||
|   | 174387c4ea | ||
|   | db50205b1f | ||
|   | 63c3631850 | ||
|   | fc87b6137c | ||
|   | 2464f00902 | ||
|   | 9b5d9f3cb3 | ||
|   | 088117a619 | ||
|   | 4a19628829 | ||
|   | 0cd54c5735 | ||
|   | cc2c670a5e | ||
|   | 769a01f4e9 | ||
|   | 9c1afbbb67 | ||
|   | 376725e30e | ||
|   | b836e661cf | ||
|   | 446e82e86d | ||
|   | f2020913fd | ||
|   | d9fb11b043 | ||
|   | 56ddaaa380 | ||
|   | 1efb32d300 | ||
|   | 6dba56223a | ||
|   | 2ff6beea35 | ||
|   | 689c7f4107 | ||
|   | 59bf1f4838 | ||
|   | db0f85ba5d | ||
|   | 425611eadf | ||
|   | 9213574870 | ||
|   | 3073acc3b0 | ||
|   | a61d525111 | ||
|   | 4064d9a7a7 | ||
|   | 8a06cfdd81 | ||
|   | d3e789e677 | ||
|   | c24d8e856b | ||
|   | 9db9793f33 | ||
|   | c237bc5f45 | ||
|   | 178b975d6a | ||
|   | 4abca411f3 | ||
|   | e48c7c009a | ||
|   | 36b361617d | ||
|   | 5eac1d696d | ||
|   | 9b53583945 | ||
|   | 1dbf25afa1 | ||
|   | e415cc538a | ||
|   | 67a3715ded | ||
|   | 35aa278194 | ||
|   | a76762a05e | ||
|   | ccf27e5f83 | ||
|   | 912a9ecfba | ||
|   | 0487d672ed | ||
|   | e94a0fced9 | ||
|   | a3b86447f7 | ||
|   | 1d76eace1e | ||
|   | c1303bd642 | ||
|   | db11a37a68 | ||
|   | 0d0b9da6f8 | ||
|   | ab0b407da4 | ||
|   | c33b330799 | ||
|   | 144b24bfcc | ||
|   | 4d21650d6d | ||
|   | a6fc656e91 | ||
|   | a38bae259e | ||
|   | c53aa89098 | ||
|   | 851b7d0639 | ||
|   | b4c78726cf | ||
|   | c9cc07fd3a | ||
|   | f6eb2a8cf8 | ||
|   | 08e5589836 | ||
|   | 4f5a5e84fc | ||
|   | 0786683189 | ||
|   | 4887de533c | ||
|   | 57945a730f | ||
|   | 78254146f3 | ||
|   | 3e2a2cf532 | ||
|   | 04b240b50c | ||
|   | 7810f0e276 | ||
|   | 9b8f9b65b8 | ||
|   | e741cab3f4 | ||
|   | 53748e3da7 | ||
|   | 17c5436f6e | ||
|   | 04fb6f7659 | ||
|   | e5e58f8075 | ||
|   | 1da0355528 | ||
|   | e5881156f6 | ||
|   | 60170cff70 | ||
|   | e2bea48073 | ||
|   | bbfaf8204b | ||
|   | b3e19ee669 | ||
|   | 75e2bfb062 | ||
|   | a859d76c72 | ||
|   | 2145333969 | ||
|   | 1b61b9cd73 | 
| @@ -15,6 +15,7 @@ RUN dnf -y update && dnf -y upgrade && \ | ||||
|  | ||||
|     # Unpackaged versions | ||||
|     dnf install -y https://copr-be.cloud.fedoraproject.org/results/jadahl/mutter-ci/fedora-29-x86_64/00834984-gsettings-desktop-schemas/gsettings-desktop-schemas-3.30.1-1.20181206git918efdd69be53.fc29.x86_64.rpm https://copr-be.cloud.fedoraproject.org/results/jadahl/mutter-ci/fedora-29-x86_64/00834984-gsettings-desktop-schemas/gsettings-desktop-schemas-devel-3.30.1-1.20181206git918efdd69be53.fc29.x86_64.rpm && \ | ||||
|     dnf install -y https://copr-be.cloud.fedoraproject.org/results/hergertme/sysprof-3/fedora-30-x86_64/00917385-sysprof/libsysprof-ui-3.33.2-1.fc30.x86_64.rpm https://copr-be.cloud.fedoraproject.org/results/hergertme/sysprof-3/fedora-30-x86_64/00917385-sysprof/sysprof-cli-3.33.2-1.fc30.x86_64.rpm https://copr-be.cloud.fedoraproject.org/results/hergertme/sysprof-3/fedora-30-x86_64/00917385-sysprof/sysprof-3.33.2-1.fc30.x86_64.rpm https://copr-be.cloud.fedoraproject.org/results/hergertme/sysprof-3/fedora-30-x86_64/00917385-sysprof/sysprof-devel-3.33.2-1.fc30.x86_64.rpm && \ | ||||
|  | ||||
|     dnf install -y intltool redhat-rpm-config make && \ | ||||
|  | ||||
|   | ||||
| @@ -17551,7 +17551,7 @@ _clutter_actor_get_paint_volume_real (ClutterActor *self, | ||||
|                l != NULL && l->data != priv->current_effect; | ||||
|                l = l->next) | ||||
|             { | ||||
|               if (!_clutter_effect_get_paint_volume (l->data, pv)) | ||||
|               if (!_clutter_effect_modify_paint_volume (l->data, pv)) | ||||
|                 { | ||||
|                   clutter_paint_volume_free (pv); | ||||
|                   CLUTTER_NOTE (CLIPPING, "Bail from get_paint_volume (%s): " | ||||
| @@ -17569,7 +17569,7 @@ _clutter_actor_get_paint_volume_real (ClutterActor *self, | ||||
|           /* otherwise, get the cumulative volume */ | ||||
|           effects = _clutter_meta_group_peek_metas (priv->effects); | ||||
|           for (l = effects; l != NULL; l = l->next) | ||||
|             if (!_clutter_effect_get_paint_volume (l->data, pv)) | ||||
|             if (!_clutter_effect_modify_paint_volume (l->data, pv)) | ||||
|               { | ||||
|                 clutter_paint_volume_free (pv); | ||||
|                 CLUTTER_NOTE (CLIPPING, "Bail from get_paint_volume (%s): " | ||||
|   | ||||
| @@ -178,8 +178,8 @@ clutter_blur_effect_paint_target (ClutterOffscreenEffect *effect) | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_blur_effect_get_paint_volume (ClutterEffect      *effect, | ||||
|                                       ClutterPaintVolume *volume) | ||||
| clutter_blur_effect_modify_paint_volume (ClutterEffect      *effect, | ||||
|                                          ClutterPaintVolume *volume) | ||||
| { | ||||
|   gfloat cur_width, cur_height; | ||||
|   ClutterVertex origin; | ||||
| @@ -223,7 +223,7 @@ clutter_blur_effect_class_init (ClutterBlurEffectClass *klass) | ||||
|   gobject_class->dispose = clutter_blur_effect_dispose; | ||||
|  | ||||
|   effect_class->pre_paint = clutter_blur_effect_pre_paint; | ||||
|   effect_class->get_paint_volume = clutter_blur_effect_get_paint_volume; | ||||
|   effect_class->modify_paint_volume = clutter_blur_effect_modify_paint_volume; | ||||
|  | ||||
|   offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); | ||||
|   offscreen_class->paint_target = clutter_blur_effect_paint_target; | ||||
|   | ||||
| @@ -69,6 +69,22 @@ typedef struct _ClutterTouchInfo | ||||
|   gfloat current_y; | ||||
| } ClutterTouchInfo; | ||||
|  | ||||
| typedef struct _ClutterPtrA11yData | ||||
| { | ||||
|   int n_btn_pressed; | ||||
|   float current_x; | ||||
|   float current_y; | ||||
|  | ||||
|   float dwell_x; | ||||
|   float dwell_y; | ||||
|   gboolean dwell_drag_started; | ||||
|   gboolean dwell_gesture_started; | ||||
|   guint dwell_timer; | ||||
|  | ||||
|   guint secondary_click_timer; | ||||
|   gboolean secondary_click_triggered; | ||||
| } ClutterPtrA11yData; | ||||
|  | ||||
| struct _ClutterInputDevice | ||||
| { | ||||
|   GObject parent_instance; | ||||
| @@ -143,6 +159,10 @@ struct _ClutterInputDevice | ||||
|  | ||||
|   guint has_cursor : 1; | ||||
|   guint is_enabled : 1; | ||||
|  | ||||
|   /* Accessiblity */ | ||||
|   ClutterVirtualInputDevice *accessibility_virtual_device; | ||||
|   ClutterPtrA11yData *ptr_a11y_data; | ||||
| }; | ||||
|  | ||||
| typedef void (*ClutterEmitInputDeviceEvent) (ClutterEvent       *event, | ||||
|   | ||||
| @@ -47,6 +47,7 @@ | ||||
| #include "clutter-stage-private.h" | ||||
| #include "clutter-virtual-input-device.h" | ||||
| #include "clutter-input-device-tool.h" | ||||
| #include "clutter-input-pointer-a11y-private.h" | ||||
|  | ||||
| struct _ClutterDeviceManagerPrivate | ||||
| { | ||||
| @@ -55,6 +56,8 @@ struct _ClutterDeviceManagerPrivate | ||||
|  | ||||
|   /* Keyboard a11y */ | ||||
|   ClutterKbdA11ySettings kbd_a11y_settings; | ||||
|   /* Pointer a11y */ | ||||
|   ClutterPointerA11ySettings pointer_a11y_settings; | ||||
| }; | ||||
|  | ||||
| enum | ||||
| @@ -75,6 +78,9 @@ enum | ||||
|   TOOL_CHANGED, | ||||
|   KBD_A11Y_MASK_CHANGED, | ||||
|   KBD_A11Y_FLAGS_CHANGED, | ||||
|   PTR_A11Y_DWELL_CLICK_TYPE_CHANGED, | ||||
|   PTR_A11Y_TIMEOUT_STARTED, | ||||
|   PTR_A11Y_TIMEOUT_STOPPED, | ||||
|  | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
| @@ -239,6 +245,67 @@ clutter_device_manager_class_init (ClutterDeviceManagerClass *klass) | ||||
|                   G_TYPE_NONE, 2, | ||||
|                   G_TYPE_UINT, | ||||
|                   G_TYPE_UINT); | ||||
|  | ||||
|   /** | ||||
|    * ClutterDeviceManager::ptr-a11y-dwell-click-type-changed: | ||||
|    * @manager: the #ClutterDeviceManager that emitted the signal | ||||
|    * @click_type: the new #ClutterPointerA11yDwellClickType mode | ||||
|    * | ||||
|    * The ::ptr-a11y-dwell-click-type-changed signal is emitted each time | ||||
|    * the ClutterPointerA11yDwellClickType mode is changed as the result | ||||
|    * of pointer accessibility operations. | ||||
|    */ | ||||
|   manager_signals[PTR_A11Y_DWELL_CLICK_TYPE_CHANGED] = | ||||
|     g_signal_new (I_("ptr-a11y-dwell-click-type-changed"), | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   0, NULL, NULL, | ||||
|                   g_cclosure_marshal_VOID__FLAGS, | ||||
|                   G_TYPE_NONE, 1, | ||||
|                   CLUTTER_TYPE_POINTER_A11Y_DWELL_CLICK_TYPE); | ||||
|  | ||||
|   /** | ||||
|    * ClutterDeviceManager::ptr-a11y-timeout-started: | ||||
|    * @manager: the #ClutterDeviceManager that emitted the signal | ||||
|    * @device: the core pointer #ClutterInputDevice | ||||
|    * @timeout_type: the type of timeout #ClutterPointerA11yTimeoutType | ||||
|    * @delay: the delay in ms before secondary-click is triggered. | ||||
|    * | ||||
|    * The ::ptr-a11y-timeout-started signal is emitted when a | ||||
|    * pointer accessibility timeout delay is started, so that upper | ||||
|    * layers can notify the user with some visual feedback. | ||||
|    */ | ||||
|   manager_signals[PTR_A11Y_TIMEOUT_STARTED] = | ||||
|     g_signal_new (I_("ptr-a11y-timeout-started"), | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   0, NULL, NULL, | ||||
|                   _clutter_marshal_VOID__OBJECT_FLAGS_UINT, | ||||
|                   G_TYPE_NONE, 3, | ||||
|                   CLUTTER_TYPE_INPUT_DEVICE, | ||||
|                   CLUTTER_TYPE_POINTER_A11Y_TIMEOUT_TYPE, | ||||
|                   G_TYPE_UINT); | ||||
|  | ||||
|   /** | ||||
|    * ClutterDeviceManager::ptr-a11y-timeout-stopped: | ||||
|    * @manager: the #ClutterDeviceManager that emitted the signal | ||||
|    * @device: the core pointer #ClutterInputDevice | ||||
|    * @timeout_type: the type of timeout #ClutterPointerA11yTimeoutType | ||||
|    * | ||||
|    * The ::ptr-a11y-timeout-stopped signal is emitted when a running | ||||
|    * pointer accessibility timeout delay is stopped, either because | ||||
|    * it's triggered at the end of the delay or cancelled, so that | ||||
|    * upper layers can notify the user with some visual feedback. | ||||
|    */ | ||||
|   manager_signals[PTR_A11Y_TIMEOUT_STOPPED] = | ||||
|     g_signal_new (I_("ptr-a11y-timeout-stopped"), | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   0, NULL, NULL, | ||||
|                   _clutter_marshal_VOID__OBJECT_FLAGS, | ||||
|                   G_TYPE_NONE, 2, | ||||
|                   CLUTTER_TYPE_INPUT_DEVICE, | ||||
|                   CLUTTER_TYPE_POINTER_A11Y_TIMEOUT_TYPE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -579,3 +646,88 @@ clutter_device_manager_get_kbd_a11y_settings (ClutterDeviceManager   *device_man | ||||
|  | ||||
|   *settings = device_manager->priv->kbd_a11y_settings; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| are_pointer_a11y_settings_equal (ClutterPointerA11ySettings *a, | ||||
|                                  ClutterPointerA11ySettings *b) | ||||
| { | ||||
|   return (memcmp (a, b, sizeof (ClutterPointerA11ySettings)) == 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_device_manager_enable_pointer_a11y (ClutterDeviceManager *device_manager) | ||||
| { | ||||
|   ClutterInputDevice *core_pointer; | ||||
|  | ||||
|   core_pointer = clutter_device_manager_get_core_device (device_manager, | ||||
|                                                          CLUTTER_POINTER_DEVICE); | ||||
|  | ||||
|   _clutter_input_pointer_a11y_add_device (core_pointer); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_device_manager_disable_pointer_a11y (ClutterDeviceManager *device_manager) | ||||
| { | ||||
|   ClutterInputDevice *core_pointer; | ||||
|  | ||||
|   core_pointer = clutter_device_manager_get_core_device (device_manager, | ||||
|                                                          CLUTTER_POINTER_DEVICE); | ||||
|  | ||||
|   _clutter_input_pointer_a11y_remove_device (core_pointer); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_device_manager_set_pointer_a11y_settings: | ||||
|  * @device_manager: a #ClutterDeviceManager | ||||
|  * @settings: a pointer to a #ClutterPointerA11ySettings | ||||
|  * | ||||
|  * Sets the pointer accessibility settings | ||||
|  **/ | ||||
| void | ||||
| clutter_device_manager_set_pointer_a11y_settings (ClutterDeviceManager       *device_manager, | ||||
|                                                   ClutterPointerA11ySettings *settings) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager)); | ||||
|  | ||||
|   if (are_pointer_a11y_settings_equal (&device_manager->priv->pointer_a11y_settings, settings)) | ||||
|     return; | ||||
|  | ||||
|   if (device_manager->priv->pointer_a11y_settings.controls == 0 && settings->controls != 0) | ||||
|     clutter_device_manager_enable_pointer_a11y (device_manager); | ||||
|   else if (device_manager->priv->pointer_a11y_settings.controls != 0 && settings->controls == 0) | ||||
|     clutter_device_manager_disable_pointer_a11y (device_manager); | ||||
|  | ||||
|   device_manager->priv->pointer_a11y_settings = *settings; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_device_manager_get_pointer_a11y_settings: | ||||
|  * @device_manager: a #ClutterDeviceManager | ||||
|  * @settings: a pointer to a #ClutterPointerA11ySettings | ||||
|  * | ||||
|  * Gets the current pointer accessibility settings | ||||
|  **/ | ||||
| void | ||||
| clutter_device_manager_get_pointer_a11y_settings (ClutterDeviceManager       *device_manager, | ||||
|                                                   ClutterPointerA11ySettings *settings) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager)); | ||||
|  | ||||
|   *settings = device_manager->priv->pointer_a11y_settings; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_device_manager_set_pointer_a11y_dwell_click_type: | ||||
|  * @device_manager: a #ClutterDeviceManager | ||||
|  * @click_type: type of click as #ClutterPointerA11yDwellClickType | ||||
|  * | ||||
|  * Sets the dwell click type | ||||
|  **/ | ||||
| void | ||||
| clutter_device_manager_set_pointer_a11y_dwell_click_type (ClutterDeviceManager             *device_manager, | ||||
|                                                           ClutterPointerA11yDwellClickType  click_type) | ||||
| { | ||||
|   g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager)); | ||||
|  | ||||
|   device_manager->priv->pointer_a11y_settings.dwell_click_type = click_type; | ||||
| } | ||||
|   | ||||
| @@ -73,6 +73,27 @@ typedef struct _ClutterKbdA11ySettings | ||||
|   gint mousekeys_accel_time; | ||||
| } ClutterKbdA11ySettings; | ||||
|  | ||||
| /** | ||||
|  * ClutterPointerA11ySettings: | ||||
|  * | ||||
|  * The #ClutterPointerA11ySettings structure contains pointer accessibility | ||||
|  * settings | ||||
|  * | ||||
|  */ | ||||
| typedef struct _ClutterPointerA11ySettings | ||||
| { | ||||
|   ClutterPointerA11yFlags controls; | ||||
|   ClutterPointerA11yDwellClickType dwell_click_type; | ||||
|   ClutterPointerA11yDwellMode dwell_mode; | ||||
|   ClutterPointerA11yDwellDirection dwell_gesture_single; | ||||
|   ClutterPointerA11yDwellDirection dwell_gesture_double; | ||||
|   ClutterPointerA11yDwellDirection dwell_gesture_drag; | ||||
|   ClutterPointerA11yDwellDirection dwell_gesture_secondary; | ||||
|   gint secondary_click_delay; | ||||
|   gint dwell_delay; | ||||
|   gint dwell_threshold; | ||||
| } ClutterPointerA11ySettings; | ||||
|  | ||||
| /** | ||||
|  * ClutterDeviceManager: | ||||
|  * | ||||
| @@ -152,10 +173,23 @@ ClutterVirtualDeviceType clutter_device_manager_get_supported_virtual_device_typ | ||||
| CLUTTER_EXPORT | ||||
| void clutter_device_manager_set_kbd_a11y_settings (ClutterDeviceManager   *device_manager, | ||||
|                                                    ClutterKbdA11ySettings *settings); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_device_manager_get_kbd_a11y_settings (ClutterDeviceManager   *device_manager, | ||||
|                                                    ClutterKbdA11ySettings *settings); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_device_manager_set_pointer_a11y_settings (ClutterDeviceManager       *device_manager, | ||||
|                                                        ClutterPointerA11ySettings *settings); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_device_manager_get_pointer_a11y_settings (ClutterDeviceManager       *device_manager, | ||||
|                                                        ClutterPointerA11ySettings *settings); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_device_manager_set_pointer_a11y_dwell_click_type (ClutterDeviceManager             *device_manager, | ||||
|                                                                ClutterPointerA11yDwellClickType  click_type); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_DEVICE_MANAGER_H__ */ | ||||
|   | ||||
| @@ -7,7 +7,7 @@ G_BEGIN_DECLS | ||||
|  | ||||
| gboolean        _clutter_effect_pre_paint               (ClutterEffect           *effect); | ||||
| void            _clutter_effect_post_paint              (ClutterEffect           *effect); | ||||
| gboolean        _clutter_effect_get_paint_volume        (ClutterEffect           *effect, | ||||
| gboolean        _clutter_effect_modify_paint_volume     (ClutterEffect           *effect, | ||||
|                                                          ClutterPaintVolume      *volume); | ||||
| gboolean        _clutter_effect_has_custom_paint_volume (ClutterEffect           *effect); | ||||
| void            _clutter_effect_paint                   (ClutterEffect           *effect, | ||||
|   | ||||
| @@ -188,8 +188,8 @@ clutter_effect_real_post_paint (ClutterEffect *effect) | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_effect_real_get_paint_volume (ClutterEffect      *effect, | ||||
|                                       ClutterPaintVolume *volume) | ||||
| clutter_effect_real_modify_paint_volume (ClutterEffect      *effect, | ||||
|                                          ClutterPaintVolume *volume) | ||||
| { | ||||
|   return TRUE; | ||||
| } | ||||
| @@ -252,7 +252,7 @@ clutter_effect_class_init (ClutterEffectClass *klass) | ||||
|  | ||||
|   klass->pre_paint = clutter_effect_real_pre_paint; | ||||
|   klass->post_paint = clutter_effect_real_post_paint; | ||||
|   klass->get_paint_volume = clutter_effect_real_get_paint_volume; | ||||
|   klass->modify_paint_volume = clutter_effect_real_modify_paint_volume; | ||||
|   klass->paint = clutter_effect_real_paint; | ||||
|   klass->pick = clutter_effect_real_pick; | ||||
| } | ||||
| @@ -297,13 +297,14 @@ _clutter_effect_pick (ClutterEffect           *effect, | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| _clutter_effect_get_paint_volume (ClutterEffect      *effect, | ||||
|                                   ClutterPaintVolume *volume) | ||||
| _clutter_effect_modify_paint_volume (ClutterEffect      *effect, | ||||
|                                      ClutterPaintVolume *volume) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE); | ||||
|   g_return_val_if_fail (volume != NULL, FALSE); | ||||
|  | ||||
|   return CLUTTER_EFFECT_GET_CLASS (effect)->get_paint_volume (effect, volume); | ||||
|   return CLUTTER_EFFECT_GET_CLASS (effect)->modify_paint_volume (effect, | ||||
|                                                                  volume); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| @@ -311,7 +312,7 @@ _clutter_effect_has_custom_paint_volume (ClutterEffect *effect) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE); | ||||
|  | ||||
|   return CLUTTER_EFFECT_GET_CLASS (effect)->get_paint_volume != clutter_effect_real_get_paint_volume; | ||||
|   return CLUTTER_EFFECT_GET_CLASS (effect)->modify_paint_volume != clutter_effect_real_modify_paint_volume; | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -60,7 +60,7 @@ struct _ClutterEffect | ||||
|  * ClutterEffectClass: | ||||
|  * @pre_paint: virtual function | ||||
|  * @post_paint: virtual function | ||||
|  * @get_paint_volume: virtual function | ||||
|  * @modify_paint_volume: virtual function | ||||
|  * @paint: virtual function | ||||
|  * @pick: virtual function | ||||
|  * | ||||
| @@ -74,16 +74,16 @@ struct _ClutterEffectClass | ||||
|   ClutterActorMetaClass parent_class; | ||||
|  | ||||
|   /*< public >*/ | ||||
|   gboolean (* pre_paint)        (ClutterEffect           *effect); | ||||
|   void     (* post_paint)       (ClutterEffect           *effect); | ||||
|   gboolean (* pre_paint)           (ClutterEffect           *effect); | ||||
|   void     (* post_paint)          (ClutterEffect           *effect); | ||||
|  | ||||
|   gboolean (* get_paint_volume) (ClutterEffect           *effect, | ||||
|                                  ClutterPaintVolume      *volume); | ||||
|   gboolean (* modify_paint_volume) (ClutterEffect           *effect, | ||||
|                                     ClutterPaintVolume      *volume); | ||||
|  | ||||
|   void     (* paint)            (ClutterEffect           *effect, | ||||
|                                  ClutterEffectPaintFlags  flags); | ||||
|   void     (* pick)             (ClutterEffect           *effect, | ||||
|                                  ClutterEffectPaintFlags  flags); | ||||
|   void     (* paint)               (ClutterEffect           *effect, | ||||
|                                     ClutterEffectPaintFlags  flags); | ||||
|   void     (* pick)                (ClutterEffect           *effect, | ||||
|                                     ClutterEffectPaintFlags  flags); | ||||
|  | ||||
|   /*< private >*/ | ||||
|   void (* _clutter_effect4) (void); | ||||
|   | ||||
| @@ -13,7 +13,7 @@ G_BEGIN_DECLS | ||||
| /*** END file-header ***/ | ||||
|  | ||||
| /*** BEGIN file-production ***/ | ||||
| /* enumerations from "@filename@" */ | ||||
| /* enumerations from "@basename@" */ | ||||
| /*** END file-production ***/ | ||||
|  | ||||
| /*** BEGIN value-header ***/ | ||||
|   | ||||
| @@ -443,6 +443,88 @@ typedef enum | ||||
|   CLUTTER_A11Y_FEATURE_STATE_CHANGE_BEEP = 1 << 13, | ||||
| } ClutterKeyboardA11yFlags; | ||||
|  | ||||
| /** | ||||
|  * ClutterPointerA11yFlags: | ||||
|  * @CLUTTER_A11Y_POINTER_ENABLED: | ||||
|  * @CLUTTER_A11Y_SECONDARY_CLICK_ENABLED: | ||||
|  * @CLUTTER_A11Y_DWELL_ENABLED: | ||||
|  * | ||||
|  * Pointer accessibility features applied to a ClutterInputDevice pointer. | ||||
|  * | ||||
|  */ | ||||
| typedef enum { | ||||
|   CLUTTER_A11Y_SECONDARY_CLICK_ENABLED   = 1 << 0, | ||||
|   CLUTTER_A11Y_DWELL_ENABLED             = 1 << 1, | ||||
| } ClutterPointerA11yFlags; | ||||
|  | ||||
| /** | ||||
|  * ClutterPointerA11yDwellClickType: | ||||
|  * @CLUTTER_A11Y_DWELL_CLICK_TYPE_NONE: Internal use only | ||||
|  * @CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY: | ||||
|  * @CLUTTER_A11Y_DWELL_CLICK_TYPE_SECONDARY: | ||||
|  * @CLUTTER_A11Y_DWELL_CLICK_TYPE_MIDDLE: | ||||
|  * @CLUTTER_A11Y_DWELL_CLICK_TYPE_DOUBLE: | ||||
|  * @CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG: | ||||
|  * | ||||
|  * Dwell click types. | ||||
|  * | ||||
|  */ | ||||
| typedef enum { | ||||
|   CLUTTER_A11Y_DWELL_CLICK_TYPE_NONE, | ||||
|   CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY, | ||||
|   CLUTTER_A11Y_DWELL_CLICK_TYPE_SECONDARY, | ||||
|   CLUTTER_A11Y_DWELL_CLICK_TYPE_MIDDLE, | ||||
|   CLUTTER_A11Y_DWELL_CLICK_TYPE_DOUBLE, | ||||
|   CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG, | ||||
| } ClutterPointerA11yDwellClickType; | ||||
|  | ||||
| /** | ||||
|  * ClutterPointerA11yDwellDirection: | ||||
|  * @CLUTTER_A11Y_DWELL_DIRECTION_NONE: | ||||
|  * @CLUTTER_A11Y_DWELL_DIRECTION_LEFT: | ||||
|  * @CLUTTER_A11Y_DWELL_DIRECTION_RIGHT: | ||||
|  * @CLUTTER_A11Y_DWELL_DIRECTION_UP: | ||||
|  * @CLUTTER_A11Y_DWELL_DIRECTION_DOWN: | ||||
|  * | ||||
|  * Dwell gesture directions. | ||||
|  * | ||||
|  */ | ||||
| typedef enum { | ||||
|   CLUTTER_A11Y_DWELL_DIRECTION_NONE, | ||||
|   CLUTTER_A11Y_DWELL_DIRECTION_LEFT, | ||||
|   CLUTTER_A11Y_DWELL_DIRECTION_RIGHT, | ||||
|   CLUTTER_A11Y_DWELL_DIRECTION_UP, | ||||
|   CLUTTER_A11Y_DWELL_DIRECTION_DOWN, | ||||
| } ClutterPointerA11yDwellDirection; | ||||
|  | ||||
| /** | ||||
|  * ClutterPointerA11yDwellMode: | ||||
|  * @CLUTTER_A11Y_DWELL_MODE_WINDOW: | ||||
|  * @CLUTTER_A11Y_DWELL_MODE_GESTURE: | ||||
|  * | ||||
|  * Dwell mode. | ||||
|  * | ||||
|  */ | ||||
| typedef enum { | ||||
|   CLUTTER_A11Y_DWELL_MODE_WINDOW, | ||||
|   CLUTTER_A11Y_DWELL_MODE_GESTURE, | ||||
| } ClutterPointerA11yDwellMode; | ||||
|  | ||||
| /** | ||||
|  * ClutterPointerA11yTimeoutType: | ||||
|  * @CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK: | ||||
|  * @CLUTTER_A11Y_TIMEOUT_TYPE_DWELL: | ||||
|  * @CLUTTER_A11Y_TIMEOUT_TYPE_GESTURE: | ||||
|  * | ||||
|  * Pointer accessibility timeout type. | ||||
|  * | ||||
|  */ | ||||
| typedef enum { | ||||
|   CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK, | ||||
|   CLUTTER_A11Y_TIMEOUT_TYPE_DWELL, | ||||
|   CLUTTER_A11Y_TIMEOUT_TYPE_GESTURE, | ||||
| } ClutterPointerA11yTimeoutType; | ||||
|  | ||||
| /** | ||||
|  * ClutterActorFlags: | ||||
|  * @CLUTTER_ACTOR_MAPPED: the actor will be painted (is visible, and inside | ||||
| @@ -892,8 +974,6 @@ typedef enum /*< prefix=CLUTTER_SCROLL >*/ | ||||
|  | ||||
| /** | ||||
|  * ClutterStageState: | ||||
|  * @CLUTTER_STAGE_STATE_FULLSCREEN: Fullscreen mask | ||||
|  * @CLUTTER_STAGE_STATE_OFFSCREEN: Offscreen mask (deprecated) | ||||
|  * @CLUTTER_STAGE_STATE_ACTIVATED: Activated mask | ||||
|  * | ||||
|  * Stage state masks, used by the #ClutterEvent of type %CLUTTER_STAGE_STATE. | ||||
| @@ -902,8 +982,6 @@ typedef enum /*< prefix=CLUTTER_SCROLL >*/ | ||||
|  */ | ||||
| typedef enum | ||||
| { | ||||
|   CLUTTER_STAGE_STATE_FULLSCREEN       = (1 << 1), | ||||
|   CLUTTER_STAGE_STATE_OFFSCREEN        = (1 << 2), | ||||
|   CLUTTER_STAGE_STATE_ACTIVATED        = (1 << 3) | ||||
| } ClutterStageState; | ||||
|  | ||||
| @@ -913,7 +991,6 @@ typedef enum | ||||
|  * @CLUTTER_FEATURE_TEXTURE_YUV: Set if YUV based textures supported. | ||||
|  * @CLUTTER_FEATURE_TEXTURE_READ_PIXELS: Set if texture pixels can be read. | ||||
|  * @CLUTTER_FEATURE_STAGE_STATIC: Set if stage size if fixed (i.e framebuffer) | ||||
|  * @CLUTTER_FEATURE_STAGE_USER_RESIZE: Set if stage is able to be user resized. | ||||
|  * @CLUTTER_FEATURE_STAGE_CURSOR: Set if stage has a graphical cursor. | ||||
|  * @CLUTTER_FEATURE_SHADERS_GLSL: Set if the backend supports GLSL shaders. | ||||
|  * @CLUTTER_FEATURE_OFFSCREEN: Set if the backend supports offscreen rendering. | ||||
| @@ -931,7 +1008,6 @@ typedef enum | ||||
|   CLUTTER_FEATURE_TEXTURE_YUV            = (1 << 4), | ||||
|   CLUTTER_FEATURE_TEXTURE_READ_PIXELS    = (1 << 5), | ||||
|   CLUTTER_FEATURE_STAGE_STATIC           = (1 << 6), | ||||
|   CLUTTER_FEATURE_STAGE_USER_RESIZE      = (1 << 7), | ||||
|   CLUTTER_FEATURE_STAGE_CURSOR           = (1 << 8), | ||||
|   CLUTTER_FEATURE_SHADERS_GLSL           = (1 << 9), | ||||
|   CLUTTER_FEATURE_OFFSCREEN              = (1 << 10), | ||||
|   | ||||
| @@ -107,6 +107,9 @@ clutter_input_device_dispose (GObject *gobject) | ||||
|       device->associated = NULL; | ||||
|     } | ||||
|  | ||||
|   if (device->accessibility_virtual_device) | ||||
|     g_clear_object (&device->accessibility_virtual_device); | ||||
|  | ||||
|   g_clear_pointer (&device->axes, g_array_unref); | ||||
|   g_clear_pointer (&device->keys, g_array_unref); | ||||
|   g_clear_pointer (&device->scroll_info, g_array_unref); | ||||
|   | ||||
							
								
								
									
										42
									
								
								clutter/clutter/clutter-input-pointer-a11y-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								clutter/clutter/clutter-input-pointer-a11y-private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| /* | ||||
|  * Copyright (C) 2019 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Author: Olivier Fourdan <ofourdan@redhat.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef __CLUTTER_INPUT_POINTER_A11Y_H__ | ||||
| #define __CLUTTER_INPUT_POINTER_A11Y_H__ | ||||
|  | ||||
| #include <clutter/clutter-types.h> | ||||
| #include "clutter-enum-types.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| void _clutter_input_pointer_a11y_add_device      (ClutterInputDevice   *device); | ||||
| void _clutter_input_pointer_a11y_remove_device   (ClutterInputDevice   *device); | ||||
| void _clutter_input_pointer_a11y_on_motion_event (ClutterInputDevice   *device, | ||||
|                                                   float                 x, | ||||
|                                                   float                 y); | ||||
| void _clutter_input_pointer_a11y_on_button_event (ClutterInputDevice   *device, | ||||
|                                                   int                   button, | ||||
|                                                   gboolean              pressed); | ||||
| gboolean _clutter_is_input_pointer_a11y_enabled  (ClutterInputDevice     *device); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_INPUT_POINTER_A11Y_H__ */ | ||||
							
								
								
									
										669
									
								
								clutter/clutter/clutter-input-pointer-a11y.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										669
									
								
								clutter/clutter/clutter-input-pointer-a11y.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,669 @@ | ||||
| /* | ||||
|  * Copyright (C) 2019 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Author: Olivier Fourdan <ofourdan@redhat.com> | ||||
|  * | ||||
|  * This reimplements in Clutter the same behavior as mousetweaks original | ||||
|  * implementation by Gerd Kohlberger <gerdko gmail com> | ||||
|  * mousetweaks Copyright (C) 2007-2010 Gerd Kohlberger <gerdko gmail com> | ||||
|  */ | ||||
|  | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #include "clutter-device-manager.h" | ||||
| #include "clutter-device-manager-private.h" | ||||
| #include "clutter-enum-types.h" | ||||
| #include "clutter-input-device.h" | ||||
| #include "clutter-input-pointer-a11y-private.h" | ||||
| #include "clutter-main.h" | ||||
| #include "clutter-virtual-input-device.h" | ||||
|  | ||||
| static gboolean | ||||
| is_secondary_click_enabled (ClutterInputDevice *device) | ||||
| { | ||||
|   ClutterPointerA11ySettings settings; | ||||
|  | ||||
|   clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings); | ||||
|  | ||||
|   return (settings.controls & CLUTTER_A11Y_SECONDARY_CLICK_ENABLED); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_dwell_click_enabled (ClutterInputDevice *device) | ||||
| { | ||||
|   ClutterPointerA11ySettings settings; | ||||
|  | ||||
|   clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings); | ||||
|  | ||||
|   return (settings.controls & CLUTTER_A11Y_DWELL_ENABLED); | ||||
| } | ||||
|  | ||||
| static unsigned int | ||||
| get_secondary_click_delay (ClutterInputDevice *device) | ||||
| { | ||||
|   ClutterPointerA11ySettings settings; | ||||
|  | ||||
|   clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings); | ||||
|  | ||||
|   return settings.secondary_click_delay; | ||||
| } | ||||
|  | ||||
| static unsigned int | ||||
| get_dwell_delay (ClutterInputDevice *device) | ||||
| { | ||||
|   ClutterPointerA11ySettings settings; | ||||
|  | ||||
|   clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings); | ||||
|  | ||||
|   return settings.dwell_delay; | ||||
| } | ||||
|  | ||||
| static unsigned int | ||||
| get_dwell_threshold (ClutterInputDevice *device) | ||||
| { | ||||
|   ClutterPointerA11ySettings settings; | ||||
|  | ||||
|   clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings); | ||||
|  | ||||
|   return settings.dwell_threshold; | ||||
| } | ||||
|  | ||||
| static ClutterPointerA11yDwellMode | ||||
| get_dwell_mode (ClutterInputDevice *device) | ||||
| { | ||||
|   ClutterPointerA11ySettings settings; | ||||
|  | ||||
|   clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings); | ||||
|  | ||||
|   return settings.dwell_mode; | ||||
| } | ||||
|  | ||||
| static ClutterPointerA11yDwellClickType | ||||
| get_dwell_click_type (ClutterInputDevice *device) | ||||
| { | ||||
|   ClutterPointerA11ySettings settings; | ||||
|  | ||||
|   clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings); | ||||
| # | ||||
|   return settings.dwell_click_type; | ||||
| } | ||||
|  | ||||
| static ClutterPointerA11yDwellClickType | ||||
| get_dwell_click_type_for_direction (ClutterInputDevice               *device, | ||||
|                                     ClutterPointerA11yDwellDirection  direction) | ||||
| { | ||||
|   ClutterPointerA11ySettings settings; | ||||
|  | ||||
|   clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings); | ||||
|  | ||||
|   if (direction == settings.dwell_gesture_single) | ||||
|     return CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY; | ||||
|   else if (direction == settings.dwell_gesture_double) | ||||
|     return CLUTTER_A11Y_DWELL_CLICK_TYPE_DOUBLE; | ||||
|   else if (direction == settings.dwell_gesture_drag) | ||||
|     return CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG; | ||||
|   else if (direction == settings.dwell_gesture_secondary) | ||||
|     return CLUTTER_A11Y_DWELL_CLICK_TYPE_SECONDARY; | ||||
|  | ||||
|   return CLUTTER_A11Y_DWELL_CLICK_TYPE_NONE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| emit_button_press (ClutterInputDevice *device, | ||||
|                    gint                button) | ||||
| { | ||||
|   clutter_virtual_input_device_notify_button (device->accessibility_virtual_device, | ||||
|                                               g_get_monotonic_time (), | ||||
|                                               button, | ||||
|                                               CLUTTER_BUTTON_STATE_PRESSED); | ||||
| } | ||||
|  | ||||
| static void | ||||
| emit_button_release (ClutterInputDevice *device, | ||||
|                      gint                button) | ||||
| { | ||||
|   clutter_virtual_input_device_notify_button (device->accessibility_virtual_device, | ||||
|                                               g_get_monotonic_time (), | ||||
|                                               button, | ||||
|                                               CLUTTER_BUTTON_STATE_RELEASED); | ||||
| } | ||||
|  | ||||
| static void | ||||
| emit_button_click (ClutterInputDevice *device, | ||||
|                    gint                button) | ||||
| { | ||||
|   emit_button_press (device, button); | ||||
|   emit_button_release (device, button); | ||||
| } | ||||
|  | ||||
| static void | ||||
| restore_dwell_position (ClutterInputDevice *device) | ||||
| { | ||||
|   clutter_virtual_input_device_notify_absolute_motion (device->accessibility_virtual_device, | ||||
|                                                        g_get_monotonic_time (), | ||||
|                                                        device->ptr_a11y_data->dwell_x, | ||||
|                                                        device->ptr_a11y_data->dwell_y); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| trigger_secondary_click (gpointer data) | ||||
| { | ||||
|   ClutterInputDevice *device = data; | ||||
|  | ||||
|   device->ptr_a11y_data->secondary_click_triggered = TRUE; | ||||
|   device->ptr_a11y_data->secondary_click_timer = 0; | ||||
|  | ||||
|   g_signal_emit_by_name (device->device_manager, | ||||
|                          "ptr-a11y-timeout-stopped", | ||||
|                          device, | ||||
|                          CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK); | ||||
|  | ||||
|   return G_SOURCE_REMOVE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| start_secondary_click_timeout (ClutterInputDevice *device) | ||||
| { | ||||
|   unsigned int delay = get_secondary_click_delay (device); | ||||
|  | ||||
|   device->ptr_a11y_data->secondary_click_timer = | ||||
|     clutter_threads_add_timeout (delay, trigger_secondary_click, device); | ||||
|  | ||||
|   g_signal_emit_by_name (device->device_manager, | ||||
|                          "ptr-a11y-timeout-started", | ||||
|                          device, | ||||
|                          CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK, | ||||
|                          delay); | ||||
| } | ||||
|  | ||||
| static void | ||||
| stop_secondary_click_timeout (ClutterInputDevice *device) | ||||
| { | ||||
|   if (device->ptr_a11y_data->secondary_click_timer) | ||||
|     { | ||||
|       g_source_remove (device->ptr_a11y_data->secondary_click_timer); | ||||
|       device->ptr_a11y_data->secondary_click_timer = 0; | ||||
|  | ||||
|       g_signal_emit_by_name (device->device_manager, | ||||
|                              "ptr-a11y-timeout-stopped", | ||||
|                              device, | ||||
|                              CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK); | ||||
|     } | ||||
|   device->ptr_a11y_data->secondary_click_triggered = FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| pointer_has_moved (ClutterInputDevice *device) | ||||
| { | ||||
|   float dx, dy; | ||||
|   gint threshold; | ||||
|  | ||||
|   dx = device->ptr_a11y_data->dwell_x - device->ptr_a11y_data->current_x; | ||||
|   dy = device->ptr_a11y_data->dwell_y - device->ptr_a11y_data->current_y; | ||||
|   threshold = get_dwell_threshold (device); | ||||
|  | ||||
|   /* Pythagorean theorem */ | ||||
|   return ((dx * dx) + (dy * dy)) > (threshold * threshold); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_secondary_click_pending (ClutterInputDevice *device) | ||||
| { | ||||
|   return device->ptr_a11y_data->secondary_click_timer != 0; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_secondary_click_triggered (ClutterInputDevice *device) | ||||
| { | ||||
|   return device->ptr_a11y_data->secondary_click_triggered; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_dwell_click_pending (ClutterInputDevice *device) | ||||
| { | ||||
|   return device->ptr_a11y_data->dwell_timer != 0; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_dwell_dragging (ClutterInputDevice *device) | ||||
| { | ||||
|   return device->ptr_a11y_data->dwell_drag_started; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_dwell_gesturing (ClutterInputDevice *device) | ||||
| { | ||||
|   return device->ptr_a11y_data->dwell_gesture_started; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| has_button_pressed (ClutterInputDevice *device) | ||||
| { | ||||
|   return device->ptr_a11y_data->n_btn_pressed > 0; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| should_start_secondary_click_timeout (ClutterInputDevice *device) | ||||
| { | ||||
|   return !is_dwell_dragging (device); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| should_start_dwell (ClutterInputDevice *device) | ||||
| { | ||||
|   /* We should trigger a dwell if we've not already started one, and if | ||||
|    * no button is currently pressed or we are in the middle of a dwell | ||||
|    * drag action. | ||||
|    */ | ||||
|   return !is_dwell_click_pending (device) && | ||||
|          (is_dwell_dragging (device) || | ||||
|           !has_button_pressed (device)); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| should_stop_dwell (ClutterInputDevice *device) | ||||
| { | ||||
|   /* We should stop a dwell if the motion exceeds the threshold, unless | ||||
|    * we've started a gesture, because we want to keep the original dwell | ||||
|    * location to both detect a gesture and restore the original pointer | ||||
|    * location once the gesture is finished. | ||||
|    */ | ||||
|   return pointer_has_moved (device) && | ||||
|          !is_dwell_gesturing (device); | ||||
| } | ||||
|  | ||||
|  | ||||
| static gboolean | ||||
| should_update_dwell_position (ClutterInputDevice *device) | ||||
| { | ||||
|   return !is_dwell_gesturing (device) && | ||||
|          !is_dwell_click_pending (device) && | ||||
|          !is_secondary_click_pending (device); | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_dwell_click_type (ClutterInputDevice *device) | ||||
| { | ||||
|   ClutterPointerA11ySettings settings; | ||||
|   ClutterPointerA11yDwellClickType dwell_click_type; | ||||
|  | ||||
|   clutter_device_manager_get_pointer_a11y_settings (device->device_manager, &settings); | ||||
|  | ||||
|   dwell_click_type = settings.dwell_click_type; | ||||
|   switch (dwell_click_type) | ||||
|     { | ||||
|     case CLUTTER_A11Y_DWELL_CLICK_TYPE_DOUBLE: | ||||
|     case CLUTTER_A11Y_DWELL_CLICK_TYPE_SECONDARY: | ||||
|     case CLUTTER_A11Y_DWELL_CLICK_TYPE_MIDDLE: | ||||
|       dwell_click_type = CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY; | ||||
|       break; | ||||
|  | ||||
|     case CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG: | ||||
|       if (!is_dwell_dragging (device)) | ||||
|         dwell_click_type = CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY; | ||||
|       break; | ||||
|  | ||||
|     case CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY: | ||||
|     case CLUTTER_A11Y_DWELL_CLICK_TYPE_NONE: | ||||
|     default: | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   if (dwell_click_type != settings.dwell_click_type) | ||||
|     { | ||||
|       settings.dwell_click_type = dwell_click_type; | ||||
|       clutter_device_manager_set_pointer_a11y_settings (device->device_manager, | ||||
|                                                         &settings); | ||||
|  | ||||
|       g_signal_emit_by_name (device->device_manager, | ||||
|                              "ptr-a11y-dwell-click-type-changed", | ||||
|                              dwell_click_type); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| emit_dwell_click (ClutterInputDevice               *device, | ||||
|                   ClutterPointerA11yDwellClickType  dwell_click_type) | ||||
| { | ||||
|   switch (dwell_click_type) | ||||
|     { | ||||
|     case CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY: | ||||
|       emit_button_click (device, CLUTTER_BUTTON_PRIMARY); | ||||
|       break; | ||||
|  | ||||
|     case CLUTTER_A11Y_DWELL_CLICK_TYPE_DOUBLE: | ||||
|       emit_button_click (device, CLUTTER_BUTTON_PRIMARY); | ||||
|       emit_button_click (device, CLUTTER_BUTTON_PRIMARY); | ||||
|       break; | ||||
|  | ||||
|     case CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG: | ||||
|       if (is_dwell_dragging (device)) | ||||
|         { | ||||
|           emit_button_release (device, CLUTTER_BUTTON_PRIMARY); | ||||
|           device->ptr_a11y_data->dwell_drag_started = FALSE; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           emit_button_press (device, CLUTTER_BUTTON_PRIMARY); | ||||
|           device->ptr_a11y_data->dwell_drag_started = TRUE; | ||||
|         } | ||||
|       break; | ||||
|  | ||||
|     case CLUTTER_A11Y_DWELL_CLICK_TYPE_SECONDARY: | ||||
|       emit_button_click (device, CLUTTER_BUTTON_SECONDARY); | ||||
|       break; | ||||
|  | ||||
|     case CLUTTER_A11Y_DWELL_CLICK_TYPE_MIDDLE: | ||||
|       emit_button_click (device, CLUTTER_BUTTON_MIDDLE); | ||||
|       break; | ||||
|  | ||||
|     case CLUTTER_A11Y_DWELL_CLICK_TYPE_NONE: | ||||
|     default: | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static ClutterPointerA11yDwellDirection | ||||
| get_dwell_direction (ClutterInputDevice *device) | ||||
| { | ||||
|   float dx, dy; | ||||
|  | ||||
|   dx = ABS (device->ptr_a11y_data->dwell_x - device->ptr_a11y_data->current_x); | ||||
|   dy = ABS (device->ptr_a11y_data->dwell_y - device->ptr_a11y_data->current_y); | ||||
|  | ||||
|   /* The pointer hasn't moved */ | ||||
|   if (!pointer_has_moved (device)) | ||||
|     return CLUTTER_A11Y_DWELL_DIRECTION_NONE; | ||||
|  | ||||
|   if (device->ptr_a11y_data->dwell_x < device->ptr_a11y_data->current_x) | ||||
|     { | ||||
|       if (dx > dy) | ||||
|         return CLUTTER_A11Y_DWELL_DIRECTION_LEFT; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (dx > dy) | ||||
|         return CLUTTER_A11Y_DWELL_DIRECTION_RIGHT; | ||||
|     } | ||||
|  | ||||
|   if (device->ptr_a11y_data->dwell_y < device->ptr_a11y_data->current_y) | ||||
|     return CLUTTER_A11Y_DWELL_DIRECTION_UP; | ||||
|  | ||||
|   return CLUTTER_A11Y_DWELL_DIRECTION_DOWN; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| trigger_clear_dwell_gesture (gpointer data) | ||||
| { | ||||
|   ClutterInputDevice *device = data; | ||||
|  | ||||
|   device->ptr_a11y_data->dwell_timer = 0; | ||||
|   device->ptr_a11y_data->dwell_gesture_started = FALSE; | ||||
|  | ||||
|   return G_SOURCE_REMOVE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| trigger_dwell_gesture (gpointer data) | ||||
| { | ||||
|   ClutterInputDevice *device = data; | ||||
|   ClutterPointerA11yDwellDirection direction; | ||||
|   unsigned int delay = get_dwell_delay (device); | ||||
|  | ||||
|   restore_dwell_position (device); | ||||
|   direction = get_dwell_direction (device); | ||||
|   emit_dwell_click (device, | ||||
|                     get_dwell_click_type_for_direction (device, | ||||
|                                                         direction)); | ||||
|  | ||||
|   /* Do not clear the gesture right away, otherwise we'll start another one */ | ||||
|   device->ptr_a11y_data->dwell_timer = | ||||
|     clutter_threads_add_timeout (delay, trigger_clear_dwell_gesture, device); | ||||
|  | ||||
|   g_signal_emit_by_name (device->device_manager, | ||||
|                          "ptr-a11y-timeout-stopped", | ||||
|                          device, | ||||
|                          CLUTTER_A11Y_TIMEOUT_TYPE_GESTURE); | ||||
|  | ||||
|   return G_SOURCE_REMOVE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| start_dwell_gesture_timeout (ClutterInputDevice *device) | ||||
| { | ||||
|   unsigned int delay = get_dwell_delay (device); | ||||
|  | ||||
|   device->ptr_a11y_data->dwell_timer = | ||||
|     clutter_threads_add_timeout (delay, trigger_dwell_gesture, device); | ||||
|   device->ptr_a11y_data->dwell_gesture_started = TRUE; | ||||
|  | ||||
|   g_signal_emit_by_name (device->device_manager, | ||||
|                          "ptr-a11y-timeout-started", | ||||
|                          device, | ||||
|                          CLUTTER_A11Y_TIMEOUT_TYPE_GESTURE, | ||||
|                          delay); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| trigger_dwell_click (gpointer data) | ||||
| { | ||||
|   ClutterInputDevice *device = data; | ||||
|  | ||||
|   device->ptr_a11y_data->dwell_timer = 0; | ||||
|  | ||||
|   g_signal_emit_by_name (device->device_manager, | ||||
|                          "ptr-a11y-timeout-stopped", | ||||
|                          device, | ||||
|                          CLUTTER_A11Y_TIMEOUT_TYPE_DWELL); | ||||
|  | ||||
|   if (get_dwell_mode (device) == CLUTTER_A11Y_DWELL_MODE_GESTURE) | ||||
|     { | ||||
|       if (is_dwell_dragging (device)) | ||||
|         emit_dwell_click (device, CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG); | ||||
|       else | ||||
|         start_dwell_gesture_timeout (device); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       emit_dwell_click (device, get_dwell_click_type (device)); | ||||
|       update_dwell_click_type (device); | ||||
|     } | ||||
|  | ||||
|   return G_SOURCE_REMOVE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| start_dwell_timeout (ClutterInputDevice *device) | ||||
| { | ||||
|   unsigned int delay = get_dwell_delay (device); | ||||
|  | ||||
|   device->ptr_a11y_data->dwell_timer = | ||||
|     clutter_threads_add_timeout (delay, trigger_dwell_click, device); | ||||
|  | ||||
|   g_signal_emit_by_name (device->device_manager, | ||||
|                          "ptr-a11y-timeout-started", | ||||
|                          device, | ||||
|                          CLUTTER_A11Y_TIMEOUT_TYPE_DWELL, | ||||
|                          delay); | ||||
| } | ||||
|  | ||||
| static void | ||||
| stop_dwell_timeout (ClutterInputDevice *device) | ||||
| { | ||||
|   if (device->ptr_a11y_data->dwell_timer) | ||||
|     { | ||||
|       g_source_remove (device->ptr_a11y_data->dwell_timer); | ||||
|       device->ptr_a11y_data->dwell_timer = 0; | ||||
|       device->ptr_a11y_data->dwell_gesture_started = FALSE; | ||||
|  | ||||
|       g_signal_emit_by_name (device->device_manager, | ||||
|                              "ptr-a11y-timeout-stopped", | ||||
|                              device, | ||||
|                              CLUTTER_A11Y_TIMEOUT_TYPE_DWELL); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_dwell_position (ClutterInputDevice *device) | ||||
| { | ||||
|   device->ptr_a11y_data->dwell_x = device->ptr_a11y_data->current_x; | ||||
|   device->ptr_a11y_data->dwell_y = device->ptr_a11y_data->current_y; | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_current_position (ClutterInputDevice *device, | ||||
|                          float               x, | ||||
|                          float               y) | ||||
| { | ||||
|   device->ptr_a11y_data->current_x = x; | ||||
|   device->ptr_a11y_data->current_y = y; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_device_core_pointer (ClutterInputDevice *device) | ||||
| { | ||||
|   ClutterInputDevice *core_pointer; | ||||
|  | ||||
|   core_pointer = clutter_device_manager_get_core_device (device->device_manager, | ||||
|                                                          CLUTTER_POINTER_DEVICE); | ||||
|   if (core_pointer == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   return (core_pointer == device); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_input_pointer_a11y_add_device (ClutterInputDevice *device) | ||||
| { | ||||
|   if (!is_device_core_pointer (device)) | ||||
|     return; | ||||
|  | ||||
|   device->accessibility_virtual_device = | ||||
|     clutter_device_manager_create_virtual_device (device->device_manager, | ||||
|                                                   CLUTTER_POINTER_DEVICE); | ||||
|  | ||||
|   device->ptr_a11y_data = g_new0 (ClutterPtrA11yData, 1); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_input_pointer_a11y_remove_device (ClutterInputDevice *device) | ||||
| { | ||||
|   if (!is_device_core_pointer (device)) | ||||
|     return; | ||||
|  | ||||
|   /* Terminate a drag if started */ | ||||
|   if (is_dwell_dragging (device)) | ||||
|     emit_dwell_click (device, CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG); | ||||
|  | ||||
|   stop_dwell_timeout (device); | ||||
|   stop_secondary_click_timeout (device); | ||||
|  | ||||
|   g_clear_pointer (&device->ptr_a11y_data, g_free); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_input_pointer_a11y_on_motion_event (ClutterInputDevice *device, | ||||
|                                              float               x, | ||||
|                                              float               y) | ||||
| { | ||||
|   if (!is_device_core_pointer (device)) | ||||
|     return; | ||||
|  | ||||
|   if (!_clutter_is_input_pointer_a11y_enabled (device)) | ||||
|     return; | ||||
|  | ||||
|   update_current_position (device, x, y); | ||||
|  | ||||
|   if (is_secondary_click_enabled (device)) | ||||
|     { | ||||
|       if (pointer_has_moved (device)) | ||||
|         stop_secondary_click_timeout (device); | ||||
|     } | ||||
|  | ||||
|   if (is_dwell_click_enabled (device)) | ||||
|     { | ||||
|       if (should_stop_dwell (device)) | ||||
|         stop_dwell_timeout (device); | ||||
|       else if (should_start_dwell (device)) | ||||
|         start_dwell_timeout (device); | ||||
|     } | ||||
|  | ||||
|   if (should_update_dwell_position (device)) | ||||
|     update_dwell_position (device); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_input_pointer_a11y_on_button_event (ClutterInputDevice *device, | ||||
|                                              int                 button, | ||||
|                                              gboolean            pressed) | ||||
| { | ||||
|   if (!is_device_core_pointer (device)) | ||||
|     return; | ||||
|  | ||||
|   if (!_clutter_is_input_pointer_a11y_enabled (device)) | ||||
|     return; | ||||
|  | ||||
|   if (pressed) | ||||
|     { | ||||
|       device->ptr_a11y_data->n_btn_pressed++; | ||||
|  | ||||
|       if (is_dwell_click_enabled (device)) | ||||
|         stop_dwell_timeout (device); | ||||
|  | ||||
|       if (is_dwell_dragging (device)) | ||||
|         stop_dwell_timeout (device); | ||||
|  | ||||
|       if (is_secondary_click_enabled (device)) | ||||
|         { | ||||
|           if (button == CLUTTER_BUTTON_PRIMARY) | ||||
|             { | ||||
|               if (should_start_secondary_click_timeout (device)) | ||||
|                 start_secondary_click_timeout (device); | ||||
|             } | ||||
|           else if (is_secondary_click_pending (device)) | ||||
|             { | ||||
|               stop_secondary_click_timeout (device); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (has_button_pressed (device)) | ||||
|         device->ptr_a11y_data->n_btn_pressed--; | ||||
|  | ||||
|       if (is_secondary_click_triggered (device)) | ||||
|         { | ||||
|           emit_button_click (device, CLUTTER_BUTTON_SECONDARY); | ||||
|           stop_secondary_click_timeout (device); | ||||
|         } | ||||
|  | ||||
|       if (is_secondary_click_pending (device)) | ||||
|         stop_secondary_click_timeout (device); | ||||
|  | ||||
|       if (is_dwell_dragging (device)) | ||||
|         emit_dwell_click (device, CLUTTER_A11Y_DWELL_CLICK_TYPE_DRAG); | ||||
|     } | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| _clutter_is_input_pointer_a11y_enabled (ClutterInputDevice *device) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE); | ||||
|  | ||||
|   return (is_secondary_click_enabled (device) || is_dwell_click_enabled (device)); | ||||
| } | ||||
| @@ -58,6 +58,7 @@ | ||||
| #include "clutter-device-manager-private.h" | ||||
| #include "clutter-event-private.h" | ||||
| #include "clutter-feature.h" | ||||
| #include "clutter-input-pointer-a11y-private.h" | ||||
| #include "clutter-main.h" | ||||
| #include "clutter-master-clock.h" | ||||
| #include "clutter-mutter.h" | ||||
| @@ -2261,6 +2262,21 @@ _clutter_process_event_details (ClutterActor        *stage, | ||||
|         break; | ||||
|  | ||||
|       case CLUTTER_MOTION: | ||||
| #ifdef CLUTTER_WINDOWING_X11 | ||||
|         if (!clutter_check_windowing_backend (CLUTTER_WINDOWING_X11)) | ||||
|           { | ||||
|             if (_clutter_is_input_pointer_a11y_enabled (device)) | ||||
|               { | ||||
|                 ClutterInputDevice *core_pointer; | ||||
|                 gfloat x, y; | ||||
|  | ||||
|                 clutter_event_get_coords (event, &x, &y); | ||||
|                 core_pointer = clutter_device_manager_get_core_device (device->device_manager, | ||||
|                                                                        CLUTTER_POINTER_DEVICE); | ||||
|                 _clutter_input_pointer_a11y_on_motion_event (core_pointer, x, y); | ||||
|               } | ||||
|           } | ||||
| #endif /* CLUTTER_WINDOWING_X11 */ | ||||
|         /* only the stage gets motion events if they are enabled */ | ||||
|         if (!clutter_stage_get_motion_events_enabled (CLUTTER_STAGE (stage)) && | ||||
|             event->any.source == NULL) | ||||
| @@ -2299,6 +2315,22 @@ _clutter_process_event_details (ClutterActor        *stage, | ||||
|       /* fallthrough from motion */ | ||||
|       case CLUTTER_BUTTON_PRESS: | ||||
|       case CLUTTER_BUTTON_RELEASE: | ||||
| #ifdef CLUTTER_WINDOWING_X11 | ||||
|         if (!clutter_check_windowing_backend (CLUTTER_WINDOWING_X11)) | ||||
|           { | ||||
|             if (_clutter_is_input_pointer_a11y_enabled (device) && (event->type != CLUTTER_MOTION)) | ||||
|               { | ||||
|                 ClutterInputDevice *core_pointer; | ||||
|  | ||||
|                 core_pointer = clutter_device_manager_get_core_device (device->device_manager, | ||||
|                                                                        CLUTTER_POINTER_DEVICE); | ||||
|  | ||||
|                 _clutter_input_pointer_a11y_on_button_event (core_pointer, | ||||
|                                                              event->button.button, | ||||
|                                                              event->type == CLUTTER_BUTTON_PRESS); | ||||
|               } | ||||
|           } | ||||
| #endif /* CLUTTER_WINDOWING_X11 */ | ||||
|       case CLUTTER_SCROLL: | ||||
|       case CLUTTER_TOUCHPAD_PINCH: | ||||
|       case CLUTTER_TOUCHPAD_SWIPE: | ||||
| @@ -2520,7 +2552,7 @@ _clutter_process_event_details (ClutterActor        *stage, | ||||
|         break; | ||||
|  | ||||
|       case CLUTTER_STAGE_STATE: | ||||
|         /* fullscreen / focus - forward to stage */ | ||||
|         /* focus - forward to stage */ | ||||
|         event->any.source = stage; | ||||
|         if (!_clutter_event_process_filters (event)) | ||||
|           clutter_stage_event (CLUTTER_STAGE (stage), event); | ||||
|   | ||||
| @@ -23,6 +23,7 @@ VOID:FLOAT,FLOAT | ||||
| VOID:INT,INT,INT,INT | ||||
| VOID:OBJECT | ||||
| VOID:OBJECT,FLAGS | ||||
| VOID:OBJECT,FLAGS,UINT | ||||
| VOID:OBJECT,FLOAT,FLOAT | ||||
| VOID:OBJECT,FLOAT,FLOAT,FLAGS | ||||
| VOID:OBJECT,OBJECT | ||||
|   | ||||
| @@ -64,9 +64,6 @@ struct _ClutterMasterClockDefault | ||||
|   /* the current state of the clock, in usecs */ | ||||
|   gint64 cur_tick; | ||||
|  | ||||
|   /* the previous state of the clock, in usecs, used to compute the delta */ | ||||
|   gint64 prev_tick; | ||||
|  | ||||
| #ifdef CLUTTER_ENABLE_DEBUG | ||||
|   gint64 frame_budget; | ||||
|   gint64 remaining_budget; | ||||
| @@ -77,12 +74,6 @@ struct _ClutterMasterClockDefault | ||||
|    */ | ||||
|   GSource *source; | ||||
|  | ||||
|   /* If the master clock is idle that means it has | ||||
|    * fallen back to idle polling for timeline | ||||
|    * progressions and it may have been some time since | ||||
|    * the last real stage update. | ||||
|    */ | ||||
|   guint idle : 1; | ||||
|   guint ensure_next_iteration : 1; | ||||
|  | ||||
|   guint paused : 1; | ||||
| @@ -275,78 +266,12 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock, | ||||
| static gint | ||||
| master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock) | ||||
| { | ||||
|   gint64 now, next; | ||||
|   gint swap_delay; | ||||
|  | ||||
|   if (!master_clock_is_running (master_clock)) | ||||
|     return -1; | ||||
|  | ||||
|   /* If all of the stages are busy waiting for a swap-buffers to complete | ||||
|    * then we wait for one to be ready.. */ | ||||
|   swap_delay = master_clock_get_swap_wait_time (master_clock); | ||||
|   if (swap_delay != 0) | ||||
|     return swap_delay; | ||||
|  | ||||
|   /* When we have sync-to-vblank, we count on swap-buffer requests (or | ||||
|    * swap-buffer-complete events if supported in the backend) to throttle our | ||||
|    * frame rate so no additional delay is needed to start the next frame. | ||||
|    * | ||||
|    * If the master-clock has become idle due to no timeline progression causing | ||||
|    * redraws then we can no longer rely on vblank synchronization because the | ||||
|    * last real stage update/redraw may have happened a long time ago and so we | ||||
|    * fallback to polling for timeline progressions every 1/frame_rate seconds. | ||||
|    * | ||||
|    * (NB: if there aren't even any timelines running then the master clock will | ||||
|    * be completely stopped in master_clock_is_running()) | ||||
|    */ | ||||
|   if (clutter_feature_available (CLUTTER_FEATURE_SWAP_THROTTLE) && | ||||
|       !master_clock->idle) | ||||
|     { | ||||
|       CLUTTER_NOTE (SCHEDULER, "swap throttling available and updated stages"); | ||||
|       return 0; | ||||
|     } | ||||
|  | ||||
|   if (master_clock->prev_tick == 0) | ||||
|     { | ||||
|       /* If we weren't previously running, then draw the next frame | ||||
|        * immediately | ||||
|        */ | ||||
|       CLUTTER_NOTE (SCHEDULER, "draw the first frame immediately"); | ||||
|       return 0; | ||||
|     } | ||||
|  | ||||
|   /* Otherwise, wait at least 1/frame_rate seconds since we last | ||||
|    * started a frame | ||||
|    */ | ||||
|   now = g_source_get_time (master_clock->source); | ||||
|  | ||||
|   next = master_clock->prev_tick; | ||||
|  | ||||
|   /* If time has gone backwards then there's no way of knowing how | ||||
|      long we should wait so let's just dispatch immediately */ | ||||
|   if (now <= next) | ||||
|     { | ||||
|       CLUTTER_NOTE (SCHEDULER, "Time has gone backwards"); | ||||
|  | ||||
|       return 0; | ||||
|     } | ||||
|  | ||||
|   next += (1000000L / clutter_get_default_frame_rate ()); | ||||
|  | ||||
|   if (next <= now) | ||||
|     { | ||||
|       CLUTTER_NOTE (SCHEDULER, "Less than %lu microsecs", | ||||
|                     1000000L / (gulong) clutter_get_default_frame_rate ()); | ||||
|  | ||||
|       return 0; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       CLUTTER_NOTE (SCHEDULER, "Waiting %" G_GINT64_FORMAT " msecs", | ||||
|                    (next - now) / 1000); | ||||
|  | ||||
|       return (next - now) / 1000; | ||||
|     } | ||||
|   return master_clock_get_swap_wait_time (master_clock); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -530,7 +455,6 @@ clutter_clock_dispatch (GSource     *source, | ||||
| { | ||||
|   ClutterClockSource *clock_source = (ClutterClockSource *) source; | ||||
|   ClutterMasterClockDefault *master_clock = clock_source->master_clock; | ||||
|   gboolean stages_updated = FALSE; | ||||
|   GSList *stages; | ||||
|  | ||||
|   CLUTTER_NOTE (SCHEDULER, "Master clock [tick]"); | ||||
| @@ -550,8 +474,6 @@ clutter_clock_dispatch (GSource     *source, | ||||
|    */ | ||||
|   stages = master_clock_list_ready_stages (master_clock); | ||||
|  | ||||
|   master_clock->idle = FALSE; | ||||
|  | ||||
|   /* Each frame is split into three separate phases: */ | ||||
|  | ||||
|   /* 1. process all the events; each stage goes through its events queue | ||||
| @@ -564,19 +486,12 @@ clutter_clock_dispatch (GSource     *source, | ||||
|   master_clock_advance_timelines (master_clock); | ||||
|  | ||||
|   /* 3. relayout and redraw the stages */ | ||||
|   stages_updated = master_clock_update_stages (master_clock, stages); | ||||
|  | ||||
|   /* The master clock goes idle if no stages were updated and falls back | ||||
|    * to polling for timeline progressions... */ | ||||
|   if (!stages_updated) | ||||
|     master_clock->idle = TRUE; | ||||
|   master_clock_update_stages (master_clock, stages); | ||||
|  | ||||
|   master_clock_reschedule_stage_updates (master_clock, stages); | ||||
|  | ||||
|   g_slist_free_full (stages, g_object_unref); | ||||
|  | ||||
|   master_clock->prev_tick = master_clock->cur_tick; | ||||
|  | ||||
|   _clutter_threads_release_lock (); | ||||
|  | ||||
|   return TRUE; | ||||
| @@ -608,7 +523,6 @@ clutter_master_clock_default_init (ClutterMasterClockDefault *self) | ||||
|   source = clutter_clock_source_new (self); | ||||
|   self->source = source; | ||||
|  | ||||
|   self->idle = FALSE; | ||||
|   self->ensure_next_iteration = FALSE; | ||||
|   self->paused = FALSE; | ||||
|  | ||||
|   | ||||
| @@ -40,6 +40,7 @@ void                _clutter_stage_paint_view            (ClutterStage | ||||
|                                                           ClutterStageView            *view, | ||||
|                                                           const cairo_rectangle_int_t *clip); | ||||
|  | ||||
| void                _clutter_stage_emit_after_paint      (ClutterStage          *stage); | ||||
| void                _clutter_stage_set_window            (ClutterStage          *stage, | ||||
|                                                           ClutterStageWindow    *stage_window); | ||||
| ClutterStageWindow *_clutter_stage_get_window            (ClutterStage          *stage); | ||||
| @@ -117,7 +118,6 @@ void            _clutter_stage_remove_touch_drag_actor (ClutterStage         *st | ||||
|  | ||||
| ClutterStageState       _clutter_stage_get_state        (ClutterStage      *stage); | ||||
| gboolean                _clutter_stage_is_activated     (ClutterStage      *stage); | ||||
| gboolean                _clutter_stage_is_fullscreen    (ClutterStage      *stage); | ||||
| gboolean                _clutter_stage_update_state     (ClutterStage      *stage, | ||||
|                                                          ClutterStageState  unset_state, | ||||
|                                                          ClutterStageState  set_state); | ||||
|   | ||||
							
								
								
									
										37
									
								
								clutter/clutter/clutter-stage-view-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								clutter/clutter/clutter-stage-view-private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| /* | ||||
|  * Copyright (C) 2019 Red Hat Inc. | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This library 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 | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef __CLUTTER_STAGE_VIEW_PRIVATE_H__ | ||||
| #define __CLUTTER_STAGE_VIEW_PRIVATE_H__ | ||||
|  | ||||
| #include "clutter/clutter-stage-view.h" | ||||
|  | ||||
| void clutter_stage_view_blit_offscreen (ClutterStageView            *view, | ||||
|                                         const cairo_rectangle_int_t *clip); | ||||
|  | ||||
| gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view); | ||||
|  | ||||
| void clutter_stage_view_set_dirty_viewport (ClutterStageView *view, | ||||
|                                             gboolean          dirty); | ||||
|  | ||||
| gboolean clutter_stage_view_is_dirty_projection (ClutterStageView *view); | ||||
|  | ||||
| void clutter_stage_view_set_dirty_projection (ClutterStageView *view, | ||||
|                                               gboolean          dirty); | ||||
|  | ||||
|  | ||||
| #endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */ | ||||
| @@ -18,6 +18,7 @@ | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #include "clutter/clutter-stage-view.h" | ||||
| #include "clutter/clutter-stage-view-private.h" | ||||
|  | ||||
| #include <cairo-gobject.h> | ||||
| #include <math.h> | ||||
| @@ -61,6 +62,14 @@ clutter_stage_view_get_layout (ClutterStageView      *view, | ||||
|   *rect = priv->layout; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_view_get_framebuffer: | ||||
|  * @view: a #ClutterStageView | ||||
|  * | ||||
|  * Retrieves the framebuffer of @view to draw to. | ||||
|  * | ||||
|  * Returns: (transfer none): a #CoglFramebuffer | ||||
|  */ | ||||
| CoglFramebuffer * | ||||
| clutter_stage_view_get_framebuffer (ClutterStageView *view) | ||||
| { | ||||
| @@ -73,6 +82,14 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view) | ||||
|     return priv->framebuffer; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_view_get_onscreen: | ||||
|  * @view: a #ClutterStageView | ||||
|  * | ||||
|  * Retrieves the onscreen framebuffer of @view if available. | ||||
|  * | ||||
|  * Returns: (transfer none): a #CoglFramebuffer | ||||
|  */ | ||||
| CoglFramebuffer * | ||||
| clutter_stage_view_get_onscreen (ClutterStageView *view) | ||||
| { | ||||
|   | ||||
| @@ -18,6 +18,10 @@ | ||||
| #ifndef __CLUTTER_STAGE_VIEW_H__ | ||||
| #define __CLUTTER_STAGE_VIEW_H__ | ||||
|  | ||||
| #if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) | ||||
| #error "Only <clutter/clutter.h> can be included directly." | ||||
| #endif | ||||
|  | ||||
| #include <cairo.h> | ||||
| #include <glib-object.h> | ||||
| #include <cogl/cogl.h> | ||||
| @@ -57,22 +61,9 @@ void             clutter_stage_view_transform_to_onscreen (ClutterStageView *vie | ||||
|                                                            gfloat           *x, | ||||
|                                                            gfloat           *y); | ||||
|  | ||||
| void clutter_stage_view_blit_offscreen (ClutterStageView            *view, | ||||
| 					const cairo_rectangle_int_t *clip); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| float clutter_stage_view_get_scale (ClutterStageView *view); | ||||
|  | ||||
| gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view); | ||||
|  | ||||
| void clutter_stage_view_set_dirty_viewport (ClutterStageView *view, | ||||
|                                             gboolean          dirty); | ||||
|  | ||||
| gboolean clutter_stage_view_is_dirty_projection (ClutterStageView *view); | ||||
|  | ||||
| void clutter_stage_view_set_dirty_projection (ClutterStageView *view, | ||||
|                                               gboolean          dirty); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void clutter_stage_view_get_offscreen_transformation_matrix (ClutterStageView *view, | ||||
|                                                              CoglMatrix       *matrix); | ||||
|   | ||||
| @@ -62,16 +62,6 @@ _clutter_stage_window_set_title (ClutterStageWindow *window, | ||||
|     iface->set_title (window, title); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_stage_window_set_fullscreen (ClutterStageWindow *window, | ||||
|                                       gboolean            is_fullscreen) | ||||
| { | ||||
|   ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window); | ||||
|  | ||||
|   if (iface->set_fullscreen) | ||||
|     iface->set_fullscreen (window, is_fullscreen); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_stage_window_set_cursor_visible (ClutterStageWindow *window, | ||||
|                                           gboolean            is_visible) | ||||
| @@ -82,14 +72,6 @@ _clutter_stage_window_set_cursor_visible (ClutterStageWindow *window, | ||||
|     iface->set_cursor_visible (window, is_visible); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_stage_window_set_user_resizable (ClutterStageWindow *window, | ||||
|                                           gboolean            is_resizable) | ||||
| { | ||||
|   CLUTTER_STAGE_WINDOW_GET_IFACE (window)->set_user_resizable (window, | ||||
|                                                                is_resizable); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| _clutter_stage_window_realize (ClutterStageWindow *window) | ||||
| { | ||||
|   | ||||
| @@ -30,12 +30,8 @@ struct _ClutterStageWindowInterface | ||||
|  | ||||
|   void              (* set_title)               (ClutterStageWindow *stage_window, | ||||
|                                                  const gchar        *title); | ||||
|   void              (* set_fullscreen)          (ClutterStageWindow *stage_window, | ||||
|                                                  gboolean            is_fullscreen); | ||||
|   void              (* set_cursor_visible)      (ClutterStageWindow *stage_window, | ||||
|                                                  gboolean            cursor_visible); | ||||
|   void              (* set_user_resizable)      (ClutterStageWindow *stage_window, | ||||
|                                                  gboolean            is_resizable); | ||||
|  | ||||
|   gboolean          (* realize)                 (ClutterStageWindow *stage_window); | ||||
|   void              (* unrealize)               (ClutterStageWindow *stage_window); | ||||
| @@ -83,12 +79,8 @@ ClutterActor *    _clutter_stage_window_get_wrapper        (ClutterStageWindow * | ||||
|  | ||||
| void              _clutter_stage_window_set_title          (ClutterStageWindow *window, | ||||
|                                                             const gchar        *title); | ||||
| void              _clutter_stage_window_set_fullscreen     (ClutterStageWindow *window, | ||||
|                                                             gboolean            is_fullscreen); | ||||
| void              _clutter_stage_window_set_cursor_visible (ClutterStageWindow *window, | ||||
|                                                             gboolean            is_visible); | ||||
| void              _clutter_stage_window_set_user_resizable (ClutterStageWindow *window, | ||||
|                                                             gboolean            is_resizable); | ||||
|  | ||||
| gboolean          _clutter_stage_window_realize                 (ClutterStageWindow *window); | ||||
| void              _clutter_stage_window_unrealize               (ClutterStageWindow *window); | ||||
|   | ||||
| @@ -72,9 +72,11 @@ | ||||
| #include "clutter-private.h" | ||||
| #include "clutter-stage-manager-private.h" | ||||
| #include "clutter-stage-private.h" | ||||
| #include "clutter-stage-view-private.h" | ||||
| #include "clutter-private.h" | ||||
|  | ||||
| #include "cogl/cogl.h" | ||||
| #include "cogl/cogl-trace.h" | ||||
|  | ||||
| /* <private> | ||||
|  * ClutterStageHint: | ||||
| @@ -147,13 +149,13 @@ struct _ClutterStagePrivate | ||||
|   gpointer paint_data; | ||||
|   GDestroyNotify paint_notify; | ||||
|  | ||||
|   cairo_rectangle_int_t view_clip; | ||||
|  | ||||
|   int update_freeze_count; | ||||
|  | ||||
|   guint relayout_pending       : 1; | ||||
|   guint redraw_pending         : 1; | ||||
|   guint is_fullscreen          : 1; | ||||
|   guint is_cursor_visible      : 1; | ||||
|   guint is_user_resizable      : 1; | ||||
|   guint use_fog                : 1; | ||||
|   guint throttle_motion_events : 1; | ||||
|   guint use_alpha              : 1; | ||||
| @@ -169,12 +171,9 @@ enum | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_COLOR, | ||||
|   PROP_FULLSCREEN_SET, | ||||
|   PROP_OFFSCREEN, | ||||
|   PROP_CURSOR_VISIBLE, | ||||
|   PROP_PERSPECTIVE, | ||||
|   PROP_TITLE, | ||||
|   PROP_USER_RESIZABLE, | ||||
|   PROP_USE_FOG, | ||||
|   PROP_FOG, | ||||
|   PROP_USE_ALPHA, | ||||
| @@ -185,12 +184,11 @@ enum | ||||
|  | ||||
| enum | ||||
| { | ||||
|   FULLSCREEN, | ||||
|   UNFULLSCREEN, | ||||
|   ACTIVATE, | ||||
|   DEACTIVATE, | ||||
|   DELETE_EVENT, | ||||
|   AFTER_PAINT, | ||||
|   PAINT_VIEW, | ||||
|   PRESENTED, | ||||
|  | ||||
|   LAST_SIGNAL | ||||
| @@ -403,40 +401,37 @@ clutter_stage_allocate (ClutterActor           *self, | ||||
|                                     flags | CLUTTER_DELEGATE_LAYOUT); | ||||
|  | ||||
|       /* Ensure the window is sized correctly */ | ||||
|       if (!priv->is_fullscreen) | ||||
|       if (priv->min_size_changed) | ||||
|         { | ||||
|           if (priv->min_size_changed) | ||||
|             { | ||||
|               gfloat min_width, min_height; | ||||
|               gboolean min_width_set, min_height_set; | ||||
|           gfloat min_width, min_height; | ||||
|           gboolean min_width_set, min_height_set; | ||||
|  | ||||
|               g_object_get (G_OBJECT (self), | ||||
|                             "min-width", &min_width, | ||||
|                             "min-width-set", &min_width_set, | ||||
|                             "min-height", &min_height, | ||||
|                             "min-height-set", &min_height_set, | ||||
|                             NULL); | ||||
|           g_object_get (G_OBJECT (self), | ||||
|                         "min-width", &min_width, | ||||
|                         "min-width-set", &min_width_set, | ||||
|                         "min-height", &min_height, | ||||
|                         "min-height-set", &min_height_set, | ||||
|                         NULL); | ||||
|  | ||||
|               if (!min_width_set) | ||||
|                 min_width = 1; | ||||
|               if (!min_height_set) | ||||
|                 min_height = 1; | ||||
|           if (!min_width_set) | ||||
|             min_width = 1; | ||||
|           if (!min_height_set) | ||||
|             min_height = 1; | ||||
|  | ||||
|               if (width < min_width) | ||||
|                 width = min_width; | ||||
|               if (height < min_height) | ||||
|                 height = min_height; | ||||
|           if (width < min_width) | ||||
|             width = min_width; | ||||
|           if (height < min_height) | ||||
|             height = min_height; | ||||
|  | ||||
|               priv->min_size_changed = FALSE; | ||||
|             } | ||||
|           priv->min_size_changed = FALSE; | ||||
|         } | ||||
|  | ||||
|           if (window_size.width != CLUTTER_NEARBYINT (width) || | ||||
|               window_size.height != CLUTTER_NEARBYINT (height)) | ||||
|             { | ||||
|               _clutter_stage_window_resize (priv->impl, | ||||
|                                             CLUTTER_NEARBYINT (width), | ||||
|                                             CLUTTER_NEARBYINT (height)); | ||||
|             } | ||||
|       if (window_size.width != CLUTTER_NEARBYINT (width) || | ||||
|           window_size.height != CLUTTER_NEARBYINT (height)) | ||||
|         { | ||||
|           _clutter_stage_window_resize (priv->impl, | ||||
|                                         CLUTTER_NEARBYINT (width), | ||||
|                                         CLUTTER_NEARBYINT (height)); | ||||
|         } | ||||
|     } | ||||
|   else | ||||
| @@ -688,7 +683,22 @@ _clutter_stage_paint_view (ClutterStage                *stage, | ||||
|   if (!priv->impl) | ||||
|     return; | ||||
|  | ||||
|   clutter_stage_do_paint_view (stage, view, clip); | ||||
|   COGL_TRACE_BEGIN_SCOPED (ClutterStagePaintView, "Paint (view)"); | ||||
|  | ||||
|   priv->view_clip = *clip; | ||||
|  | ||||
|   if (g_signal_has_handler_pending (stage, stage_signals[PAINT_VIEW], | ||||
|                                     0, TRUE)) | ||||
|     g_signal_emit (stage, stage_signals[PAINT_VIEW], 0, view); | ||||
|   else | ||||
|     CLUTTER_STAGE_GET_CLASS (stage)->paint_view (stage, view); | ||||
|  | ||||
|   priv->view_clip = (cairo_rectangle_int_t) { 0 }; | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_stage_emit_after_paint (ClutterStage *stage) | ||||
| { | ||||
|   g_signal_emit (stage, stage_signals[AFTER_PAINT], 0); | ||||
| } | ||||
|  | ||||
| @@ -844,40 +854,6 @@ clutter_stage_real_deactivate (ClutterStage *stage) | ||||
|   clutter_stage_emit_key_focus_event (stage, FALSE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_real_fullscreen (ClutterStage *stage) | ||||
| { | ||||
|   ClutterStagePrivate *priv = stage->priv; | ||||
|   cairo_rectangle_int_t geom; | ||||
|   ClutterActorBox box; | ||||
|  | ||||
|   /* we need to force an allocation here because the size | ||||
|    * of the stage might have been changed by the backend | ||||
|    * | ||||
|    * this is a really bad solution to the issues caused by | ||||
|    * the fact that fullscreening the stage on the X11 backends | ||||
|    * is really an asynchronous operation | ||||
|    */ | ||||
|   _clutter_stage_window_get_geometry (priv->impl, &geom); | ||||
|  | ||||
|   box.x1 = 0; | ||||
|   box.y1 = 0; | ||||
|   box.x2 = geom.width; | ||||
|   box.y2 = geom.height; | ||||
|  | ||||
|   /* we need to blow the caching on the Stage size, given that | ||||
|    * we're about to force an allocation, because if anything | ||||
|    * ends up querying the size of the stage during the allocate() | ||||
|    * call, like constraints or signal handlers, we'll get into an | ||||
|    * inconsistent state: the stage will report the old cached size, | ||||
|    * but the allocation will be updated anyway. | ||||
|    */ | ||||
|   clutter_actor_set_size (CLUTTER_ACTOR (stage), -1.0, -1.0); | ||||
|   clutter_actor_allocate (CLUTTER_ACTOR (stage), | ||||
|                           &box, | ||||
|                           CLUTTER_ALLOCATION_NONE); | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_stage_queue_event (ClutterStage *stage, | ||||
|                             ClutterEvent *event, | ||||
| @@ -1225,22 +1201,31 @@ _clutter_stage_do_update (ClutterStage *stage) | ||||
|   if (!CLUTTER_ACTOR_IS_REALIZED (stage)) | ||||
|     return FALSE; | ||||
|  | ||||
|   COGL_TRACE_BEGIN_SCOPED (ClutterStageDoUpdate, "Update"); | ||||
|  | ||||
|   /* NB: We need to ensure we have an up to date layout *before* we | ||||
|    * check or clear the pending redraws flag since a relayout may | ||||
|    * queue a redraw. | ||||
|    */ | ||||
|   COGL_TRACE_BEGIN (ClutterStageRelayout, "Layout"); | ||||
|  | ||||
|   _clutter_stage_maybe_relayout (CLUTTER_ACTOR (stage)); | ||||
|  | ||||
|   COGL_TRACE_END (ClutterStageRelayout); | ||||
|  | ||||
|   if (!priv->redraw_pending) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (stage_was_relayout) | ||||
|     pointers = _clutter_stage_check_updated_pointers (stage); | ||||
|  | ||||
|   clutter_stage_maybe_finish_queue_redraws (stage); | ||||
|   COGL_TRACE_BEGIN (ClutterStagePaint, "Paint"); | ||||
|  | ||||
|   clutter_stage_maybe_finish_queue_redraws (stage); | ||||
|   clutter_stage_do_redraw (stage); | ||||
|  | ||||
|   COGL_TRACE_END (ClutterStagePaint); | ||||
|  | ||||
|   /* reset the guard, so that new redraws are possible */ | ||||
|   priv->redraw_pending = FALSE; | ||||
|  | ||||
| @@ -1254,12 +1239,16 @@ _clutter_stage_do_update (ClutterStage *stage) | ||||
|     } | ||||
| #endif /* CLUTTER_ENABLE_DEBUG */ | ||||
|  | ||||
|   COGL_TRACE_BEGIN (ClutterStagePick, "Pick"); | ||||
|  | ||||
|   while (pointers) | ||||
|     { | ||||
|       _clutter_input_device_update (pointers->data, NULL, TRUE); | ||||
|       pointers = g_slist_delete_link (pointers, pointers); | ||||
|     } | ||||
|  | ||||
|   COGL_TRACE_END (ClutterStagePick); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| @@ -1570,10 +1559,13 @@ _clutter_stage_do_pick_on_view (ClutterStage     *stage, | ||||
|   return retval; | ||||
| } | ||||
|  | ||||
| static ClutterStageView * | ||||
| get_view_at (ClutterStage *stage, | ||||
|              int           x, | ||||
|              int           y) | ||||
| /** | ||||
|  * clutter_stage_get_view_at: (skip) | ||||
|  */ | ||||
| ClutterStageView * | ||||
| clutter_stage_get_view_at (ClutterStage *stage, | ||||
|                            float         x, | ||||
|                            float         y) | ||||
| { | ||||
|   ClutterStagePrivate *priv = stage->priv; | ||||
|   GList *l; | ||||
| @@ -1620,7 +1612,7 @@ _clutter_stage_do_pick (ClutterStage   *stage, | ||||
|   if (x < 0 || x >= stage_width || y < 0 || y >= stage_height) | ||||
|     return actor; | ||||
|  | ||||
|   view = get_view_at (stage, x, y); | ||||
|   view = clutter_stage_get_view_at (stage, x, y); | ||||
|   if (view) | ||||
|     return _clutter_stage_do_pick_on_view (stage, x, y, mode, view); | ||||
|  | ||||
| @@ -1699,11 +1691,6 @@ clutter_stage_set_property (GObject      *object, | ||||
|                                           clutter_value_get_color (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_OFFSCREEN: | ||||
|       if (g_value_get_boolean (value)) | ||||
|         g_warning ("Offscreen stages are currently not supported\n"); | ||||
|       break; | ||||
|  | ||||
|     case PROP_CURSOR_VISIBLE: | ||||
|       if (g_value_get_boolean (value)) | ||||
|         clutter_stage_show_cursor (stage); | ||||
| @@ -1719,10 +1706,6 @@ clutter_stage_set_property (GObject      *object, | ||||
|       clutter_stage_set_title (stage, g_value_get_string (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_USER_RESIZABLE: | ||||
|       clutter_stage_set_user_resizable (stage, g_value_get_boolean (value)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_USE_FOG: | ||||
|       clutter_stage_set_use_fog (stage, g_value_get_boolean (value)); | ||||
|       break; | ||||
| @@ -1773,14 +1756,6 @@ clutter_stage_get_property (GObject    *gobject, | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case PROP_OFFSCREEN: | ||||
|       g_value_set_boolean (value, FALSE); | ||||
|       break; | ||||
|  | ||||
|     case PROP_FULLSCREEN_SET: | ||||
|       g_value_set_boolean (value, priv->is_fullscreen); | ||||
|       break; | ||||
|  | ||||
|     case PROP_CURSOR_VISIBLE: | ||||
|       g_value_set_boolean (value, priv->is_cursor_visible); | ||||
|       break; | ||||
| @@ -1793,10 +1768,6 @@ clutter_stage_get_property (GObject    *gobject, | ||||
|       g_value_set_string (value, priv->title); | ||||
|       break; | ||||
|  | ||||
|     case PROP_USER_RESIZABLE: | ||||
|       g_value_set_boolean (value, priv->is_user_resizable); | ||||
|       break; | ||||
|  | ||||
|     case PROP_USE_FOG: | ||||
|       g_value_set_boolean (value, priv->use_fog); | ||||
|       break; | ||||
| @@ -1891,6 +1862,16 @@ clutter_stage_finalize (GObject *object) | ||||
|   G_OBJECT_CLASS (clutter_stage_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_real_paint_view (ClutterStage     *stage, | ||||
|                                ClutterStageView *view) | ||||
| { | ||||
|   ClutterStagePrivate *priv = stage->priv; | ||||
|   const cairo_rectangle_int_t *clip = &priv->view_clip; | ||||
|  | ||||
|   clutter_stage_do_paint_view (stage, view, clip); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_class_init (ClutterStageClass *klass) | ||||
| { | ||||
| @@ -1920,42 +1901,8 @@ clutter_stage_class_init (ClutterStageClass *klass) | ||||
|   actor_class->queue_redraw = clutter_stage_real_queue_redraw; | ||||
|   actor_class->apply_transform = clutter_stage_real_apply_transform; | ||||
|  | ||||
|   /** | ||||
|    * ClutterStage:fullscreen: | ||||
|    * | ||||
|    * Whether the stage should be fullscreen or not. | ||||
|    * | ||||
|    * This property is set by calling clutter_stage_set_fullscreen() | ||||
|    * but since the actual implementation is delegated to the backend | ||||
|    * you should connect to the notify::fullscreen-set signal in order | ||||
|    * to get notification if the fullscreen state has been successfully | ||||
|    * achieved. | ||||
|    * | ||||
|    * Since: 1.0 | ||||
|    */ | ||||
|   pspec = g_param_spec_boolean ("fullscreen-set", | ||||
|                                 P_("Fullscreen Set"), | ||||
|                                 P_("Whether the main stage is fullscreen"), | ||||
|                                 FALSE, | ||||
|                                 CLUTTER_PARAM_READABLE); | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_FULLSCREEN_SET, | ||||
|                                    pspec); | ||||
|   /** | ||||
|    * ClutterStage:offscreen: | ||||
|    * | ||||
|    * Whether the stage should be rendered in an offscreen buffer. | ||||
|    * | ||||
|    * Deprecated: 1.10: This property does not do anything. | ||||
|    */ | ||||
|   pspec = g_param_spec_boolean ("offscreen", | ||||
|                                 P_("Offscreen"), | ||||
|                                 P_("Whether the main stage should be rendered offscreen"), | ||||
|                                 FALSE, | ||||
|                                 CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED); | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_OFFSCREEN, | ||||
|                                    pspec); | ||||
|   klass->paint_view = clutter_stage_real_paint_view; | ||||
|  | ||||
|   /** | ||||
|    * ClutterStage:cursor-visible: | ||||
|    * | ||||
| @@ -1969,21 +1916,6 @@ clutter_stage_class_init (ClutterStageClass *klass) | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_CURSOR_VISIBLE, | ||||
|                                    pspec); | ||||
|   /** | ||||
|    * ClutterStage:user-resizable: | ||||
|    * | ||||
|    * Whether the stage is resizable via user interaction. | ||||
|    * | ||||
|    * Since: 0.4 | ||||
|    */ | ||||
|   pspec = g_param_spec_boolean ("user-resizable", | ||||
|                                 P_("User Resizable"), | ||||
|                                 P_("Whether the stage is able to be resized via user interaction"), | ||||
|                                 FALSE, | ||||
|                                 CLUTTER_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_USER_RESIZABLE, | ||||
|                                    pspec); | ||||
|   /** | ||||
|    * ClutterStage:color: | ||||
|    * | ||||
| @@ -2131,39 +2063,6 @@ clutter_stage_class_init (ClutterStageClass *klass) | ||||
|                                 CLUTTER_PARAM_READWRITE); | ||||
|   g_object_class_install_property (gobject_class, PROP_ACCEPT_FOCUS, pspec); | ||||
|  | ||||
|   /** | ||||
|    * ClutterStage::fullscreen: | ||||
|    * @stage: the stage which was fullscreened | ||||
|    * | ||||
|    * The ::fullscreen signal is emitted when the stage is made fullscreen. | ||||
|    * | ||||
|    * Since: 0.6 | ||||
|    */ | ||||
|   stage_signals[FULLSCREEN] = | ||||
|     g_signal_new (I_("fullscreen"), | ||||
| 		  G_TYPE_FROM_CLASS (gobject_class), | ||||
| 		  G_SIGNAL_RUN_FIRST, | ||||
| 		  G_STRUCT_OFFSET (ClutterStageClass, fullscreen), | ||||
| 		  NULL, NULL, | ||||
| 		  _clutter_marshal_VOID__VOID, | ||||
| 		  G_TYPE_NONE, 0); | ||||
|   /** | ||||
|    * ClutterStage::unfullscreen: | ||||
|    * @stage: the stage which has left a fullscreen state. | ||||
|    * | ||||
|    * The ::unfullscreen signal is emitted when the stage leaves a fullscreen | ||||
|    * state. | ||||
|    * | ||||
|    * Since: 0.6 | ||||
|    */ | ||||
|   stage_signals[UNFULLSCREEN] = | ||||
|     g_signal_new (I_("unfullscreen"), | ||||
| 		  G_TYPE_FROM_CLASS (gobject_class), | ||||
| 		  G_SIGNAL_RUN_LAST, | ||||
| 		  G_STRUCT_OFFSET (ClutterStageClass, unfullscreen), | ||||
| 		  NULL, NULL, | ||||
| 		  _clutter_marshal_VOID__VOID, | ||||
| 		  G_TYPE_NONE, 0); | ||||
|   /** | ||||
|    * ClutterStage::activate: | ||||
|    * @stage: the stage which was activated | ||||
| @@ -2247,6 +2146,28 @@ clutter_stage_class_init (ClutterStageClass *klass) | ||||
|                   NULL, NULL, NULL, | ||||
|                   G_TYPE_NONE, 0); | ||||
|  | ||||
|   /** | ||||
|    * ClutterStage::paint-view: | ||||
|    * @stage: the stage that received the event | ||||
|    * @view: a #ClutterStageView | ||||
|    * | ||||
|    * The ::paint-view signal is emitted before a #ClutterStageView is being | ||||
|    * painted. | ||||
|    * | ||||
|    * The view is painted in the default handler. Hence, if you want to perform | ||||
|    * some action after the view is painted, like reading the contents of the | ||||
|    * framebuffer, use g_signal_connect_after() or pass %G_CONNECT_AFTER. | ||||
|    */ | ||||
|   stage_signals[PAINT_VIEW] = | ||||
|     g_signal_new (I_("paint-view"), | ||||
|                   G_TYPE_FROM_CLASS (gobject_class), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   G_STRUCT_OFFSET (ClutterStageClass, paint_view), | ||||
|                   NULL, NULL, | ||||
|                   _clutter_marshal_VOID__OBJECT, | ||||
|                   G_TYPE_NONE, 1, | ||||
|                   CLUTTER_TYPE_STAGE_VIEW); | ||||
|  | ||||
|   /** | ||||
|    * ClutterStage::presented: (skip) | ||||
|    * @stage: the stage that received the event | ||||
| @@ -2264,7 +2185,6 @@ clutter_stage_class_init (ClutterStageClass *klass) | ||||
|                   G_TYPE_NONE, 2, | ||||
|                   G_TYPE_INT, G_TYPE_POINTER); | ||||
|  | ||||
|   klass->fullscreen = clutter_stage_real_fullscreen; | ||||
|   klass->activate = clutter_stage_real_activate; | ||||
|   klass->deactivate = clutter_stage_real_deactivate; | ||||
|   klass->delete_event = clutter_stage_real_delete_event; | ||||
| @@ -2315,8 +2235,6 @@ clutter_stage_init (ClutterStage *self) | ||||
|  | ||||
|   priv->event_queue = g_queue_new (); | ||||
|  | ||||
|   priv->is_fullscreen = FALSE; | ||||
|   priv->is_user_resizable = FALSE; | ||||
|   priv->is_cursor_visible = TRUE; | ||||
|   priv->use_fog = FALSE; | ||||
|   priv->throttle_motion_events = TRUE; | ||||
| @@ -2712,136 +2630,6 @@ _clutter_stage_get_viewport (ClutterStage *stage, | ||||
|   *height = priv->viewport[3]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_set_fullscreen: | ||||
|  * @stage: a #ClutterStage | ||||
|  * @fullscreen: %TRUE to to set the stage fullscreen | ||||
|  * | ||||
|  * Asks to place the stage window in the fullscreen or unfullscreen | ||||
|  * states. | ||||
|  * | ||||
|  ( Note that you shouldn't assume the window is definitely full screen | ||||
|  * afterward, because other entities (e.g. the user or window manager) | ||||
|  * could unfullscreen it again, and not all window managers honor | ||||
|  * requests to fullscreen windows. | ||||
|  * | ||||
|  * If you want to receive notification of the fullscreen state you | ||||
|  * should either use the #ClutterStage::fullscreen and | ||||
|  * #ClutterStage::unfullscreen signals, or use the notify signal | ||||
|  * for the #ClutterStage:fullscreen-set property | ||||
|  * | ||||
|  * Since: 1.0 | ||||
|  */ | ||||
| void | ||||
| clutter_stage_set_fullscreen (ClutterStage *stage, | ||||
|                               gboolean      fullscreen) | ||||
| { | ||||
|   ClutterStagePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_STAGE (stage)); | ||||
|  | ||||
|   priv = stage->priv; | ||||
|  | ||||
|   if (priv->is_fullscreen != fullscreen) | ||||
|     { | ||||
|       ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl); | ||||
|       ClutterStageWindowInterface *iface; | ||||
|  | ||||
|       iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl); | ||||
|  | ||||
|       /* Only set if backend implements. | ||||
|        * | ||||
|        * Also see clutter_stage_event() for setting priv->is_fullscreen | ||||
|        * on state change event. | ||||
|        */ | ||||
|       if (iface->set_fullscreen) | ||||
| 	iface->set_fullscreen (impl, fullscreen); | ||||
|     } | ||||
|  | ||||
|   /* If the backend did fullscreen the stage window then we need to resize | ||||
|    * the stage and update its viewport so we queue a relayout.  Note: if the | ||||
|    * fullscreen request is handled asynchronously we can't rely on this | ||||
|    * queue_relayout to update the viewport, but for example the X backend | ||||
|    * will recieve a ConfigureNotify after a successful resize which is how | ||||
|    * we ensure the viewport is updated on X. | ||||
|    */ | ||||
|   clutter_actor_queue_relayout (CLUTTER_ACTOR (stage)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_get_fullscreen: | ||||
|  * @stage: a #ClutterStage | ||||
|  * | ||||
|  * Retrieves whether the stage is full screen or not | ||||
|  * | ||||
|  * Return value: %TRUE if the stage is full screen | ||||
|  * | ||||
|  * Since: 1.0 | ||||
|  */ | ||||
| gboolean | ||||
| clutter_stage_get_fullscreen (ClutterStage *stage) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); | ||||
|  | ||||
|   return stage->priv->is_fullscreen; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_set_user_resizable: | ||||
|  * @stage: a #ClutterStage | ||||
|  * @resizable: whether the stage should be user resizable. | ||||
|  * | ||||
|  * Sets if the stage is resizable by user interaction (e.g. via | ||||
|  * window manager controls) | ||||
|  * | ||||
|  * Since: 0.4 | ||||
|  */ | ||||
| void | ||||
| clutter_stage_set_user_resizable (ClutterStage *stage, | ||||
|                                   gboolean      resizable) | ||||
| { | ||||
|   ClutterStagePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_STAGE (stage)); | ||||
|  | ||||
|   priv = stage->priv; | ||||
|  | ||||
|   if (clutter_feature_available (CLUTTER_FEATURE_STAGE_USER_RESIZE) | ||||
|       && priv->is_user_resizable != resizable) | ||||
|     { | ||||
|       ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl); | ||||
|       ClutterStageWindowInterface *iface; | ||||
|  | ||||
|       iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl); | ||||
|       if (iface->set_user_resizable) | ||||
|         { | ||||
|           priv->is_user_resizable = resizable; | ||||
|  | ||||
|           iface->set_user_resizable (impl, resizable); | ||||
|  | ||||
|           g_object_notify (G_OBJECT (stage), "user-resizable"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_get_user_resizable: | ||||
|  * @stage: a #ClutterStage | ||||
|  * | ||||
|  * Retrieves the value set with clutter_stage_set_user_resizable(). | ||||
|  * | ||||
|  * Return value: %TRUE if the stage is resizable by the user. | ||||
|  * | ||||
|  * Since: 0.4 | ||||
|  */ | ||||
| gboolean | ||||
| clutter_stage_get_user_resizable (ClutterStage *stage) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); | ||||
|  | ||||
|   return stage->priv->is_user_resizable; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_stage_show_cursor: | ||||
|  * @stage: a #ClutterStage | ||||
| @@ -2945,6 +2733,8 @@ clutter_stage_read_pixels (ClutterStage *stage, | ||||
|   float pixel_height; | ||||
|   uint8_t *pixels; | ||||
|  | ||||
|   COGL_TRACE_BEGIN_SCOPED (ClutterStageReadPixels, "Read Pixels"); | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL); | ||||
|  | ||||
|   priv = stage->priv; | ||||
| @@ -3010,7 +2800,11 @@ clutter_stage_read_pixels (ClutterStage *stage, | ||||
|  * @y: Y coordinate to check | ||||
|  * | ||||
|  * Checks the scene at the coordinates @x and @y and returns a pointer | ||||
|  * to the #ClutterActor at those coordinates. | ||||
|  * to the #ClutterActor at those coordinates. The result is the actor which | ||||
|  * would be at the specified location on the next redraw, and is not | ||||
|  * necessarily that which was there on the previous redraw. This allows the | ||||
|  * function to perform chronologically correctly after any queued changes to | ||||
|  * the scene, and even if nothing has been drawn. | ||||
|  * | ||||
|  * By using @pick_mode it is possible to control which actors will be | ||||
|  * painted and thus available. | ||||
| @@ -3047,13 +2841,9 @@ gboolean | ||||
| clutter_stage_event (ClutterStage *stage, | ||||
|                      ClutterEvent *event) | ||||
| { | ||||
|   ClutterStagePrivate *priv; | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); | ||||
|   g_return_val_if_fail (event != NULL, FALSE); | ||||
|  | ||||
|   priv = stage->priv; | ||||
|  | ||||
|   if (event->type == CLUTTER_DELETE) | ||||
|     { | ||||
|       gboolean retval = FALSE; | ||||
| @@ -3073,24 +2863,6 @@ clutter_stage_event (ClutterStage *stage, | ||||
|   if (clutter_actor_event (CLUTTER_ACTOR (stage), event, FALSE)) | ||||
|     return TRUE; | ||||
|  | ||||
|   if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_FULLSCREEN) | ||||
|     { | ||||
|       if (event->stage_state.new_state & CLUTTER_STAGE_STATE_FULLSCREEN) | ||||
| 	{ | ||||
| 	  priv->is_fullscreen = TRUE; | ||||
| 	  g_signal_emit (stage, stage_signals[FULLSCREEN], 0); | ||||
|  | ||||
|           g_object_notify (G_OBJECT (stage), "fullscreen-set"); | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| 	  priv->is_fullscreen = FALSE; | ||||
| 	  g_signal_emit (stage, stage_signals[UNFULLSCREEN], 0); | ||||
|  | ||||
|           g_object_notify (G_OBJECT (stage), "fullscreen-set"); | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_ACTIVATED) | ||||
|     { | ||||
|       if (event->stage_state.new_state & CLUTTER_STAGE_STATE_ACTIVATED) | ||||
| @@ -3945,8 +3717,6 @@ clutter_stage_get_use_alpha (ClutterStage *stage) | ||||
|  * If the current size of @stage is smaller than the minimum size, the | ||||
|  * @stage will be resized to the new @width and @height | ||||
|  * | ||||
|  * This function has no effect if @stage is fullscreen | ||||
|  * | ||||
|  * Since: 1.2 | ||||
|  */ | ||||
| void | ||||
| @@ -4633,20 +4403,6 @@ _clutter_stage_is_activated (ClutterStage *stage) | ||||
|   return (stage->priv->current_state & CLUTTER_STAGE_STATE_ACTIVATED) != 0; | ||||
| } | ||||
|  | ||||
| /*< private > | ||||
|  * _clutter_stage_is_fullscreen: | ||||
|  * @stage: a #ClutterStage | ||||
|  * | ||||
|  * Checks whether the @stage state includes %CLUTTER_STAGE_STATE_FULLSCREEN. | ||||
|  * | ||||
|  * Return value: %TRUE if the @stage is fullscreen | ||||
|  */ | ||||
| gboolean | ||||
| _clutter_stage_is_fullscreen (ClutterStage *stage) | ||||
| { | ||||
|   return (stage->priv->current_state & CLUTTER_STAGE_STATE_FULLSCREEN) != 0; | ||||
| } | ||||
|  | ||||
| /*< private > | ||||
|  * _clutter_stage_update_state: | ||||
|  * @stage: a #ClutterStage | ||||
|   | ||||
| @@ -30,6 +30,7 @@ | ||||
|  | ||||
| #include <clutter/clutter-types.h> | ||||
| #include <clutter/clutter-group.h> | ||||
| #include <clutter/clutter-stage-view.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| @@ -61,8 +62,6 @@ struct _ClutterStage | ||||
| }; | ||||
| /** | ||||
|  * ClutterStageClass: | ||||
|  * @fullscreen: handler for the #ClutterStage::fullscreen signal | ||||
|  * @unfullscreen: handler for the #ClutterStage::unfullscreen signal | ||||
|  * @activate: handler for the #ClutterStage::activate signal | ||||
|  * @deactivate: handler for the #ClutterStage::deactivate signal | ||||
|  * @delete_event: handler for the #ClutterStage::delete-event signal | ||||
| @@ -79,17 +78,18 @@ struct _ClutterStageClass | ||||
|  | ||||
|   /*< public >*/ | ||||
|   /* signals */ | ||||
|   void (* fullscreen)   (ClutterStage *stage); | ||||
|   void (* unfullscreen) (ClutterStage *stage); | ||||
|   void (* activate)     (ClutterStage *stage); | ||||
|   void (* deactivate)   (ClutterStage *stage); | ||||
|  | ||||
|   gboolean (* delete_event) (ClutterStage *stage, | ||||
|                              ClutterEvent *event); | ||||
|  | ||||
|   void (* paint_view) (ClutterStage     *stage, | ||||
|                        ClutterStageView *view); | ||||
|  | ||||
|   /*< private >*/ | ||||
|   /* padding for future expansion */ | ||||
|   gpointer _padding_dummy[31]; | ||||
|   gpointer _padding_dummy[30]; | ||||
| }; | ||||
|  | ||||
| /** | ||||
| @@ -168,11 +168,6 @@ CLUTTER_EXPORT | ||||
| void            clutter_stage_get_perspective                   (ClutterStage          *stage, | ||||
| 			                                         ClutterPerspective    *perspective); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_stage_set_fullscreen                    (ClutterStage          *stage, | ||||
|                                                                  gboolean               fullscreen); | ||||
| CLUTTER_EXPORT | ||||
| gboolean        clutter_stage_get_fullscreen                    (ClutterStage          *stage); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_stage_show_cursor                       (ClutterStage          *stage); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_stage_hide_cursor                       (ClutterStage          *stage); | ||||
| @@ -181,11 +176,6 @@ void            clutter_stage_set_title                         (ClutterStage | ||||
|                                                                  const gchar           *title); | ||||
| CLUTTER_EXPORT | ||||
| const gchar *   clutter_stage_get_title                         (ClutterStage          *stage); | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_stage_set_user_resizable                (ClutterStage          *stage, | ||||
| 						                 gboolean               resizable); | ||||
| CLUTTER_EXPORT | ||||
| gboolean        clutter_stage_get_user_resizable                (ClutterStage          *stage); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_stage_set_minimum_size                  (ClutterStage          *stage, | ||||
| @@ -274,6 +264,10 @@ gboolean clutter_stage_capture (ClutterStage          *stage, | ||||
|                                 cairo_rectangle_int_t *rect, | ||||
|                                 ClutterCapture       **captures, | ||||
|                                 int                   *n_captures); | ||||
| CLUTTER_EXPORT | ||||
| ClutterStageView * clutter_stage_get_view_at (ClutterStage *stage, | ||||
|                                               float         x, | ||||
|                                               float         y); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
|   | ||||
| @@ -101,6 +101,7 @@ | ||||
| #include "clutter-snap-constraint.h" | ||||
| #include "clutter-stage.h" | ||||
| #include "clutter-stage-manager.h" | ||||
| #include "clutter-stage-view.h" | ||||
| #include "clutter-tap-action.h" | ||||
| #include "clutter-test-utils.h" | ||||
| #include "clutter-texture.h" | ||||
|   | ||||
| @@ -45,6 +45,9 @@ | ||||
| #include "clutter-main.h" | ||||
| #include "clutter-private.h" | ||||
| #include "clutter-stage-private.h" | ||||
| #include "clutter-stage-view-private.h" | ||||
|  | ||||
| #include "cogl/cogl-trace.h" | ||||
|  | ||||
| typedef struct _ClutterStageViewCoglPrivate | ||||
| { | ||||
| @@ -183,38 +186,56 @@ clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window, | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   /* We only extrapolate presentation times for 150ms  - this is somewhat | ||||
|    * arbitrary. The reasons it might not be accurate for larger times are | ||||
|    * that the refresh interval might be wrong or the vertical refresh | ||||
|    * might be downclocked if nothing is going on onscreen. | ||||
|    */ | ||||
|   if (stage_cogl->last_presentation_time == 0|| | ||||
|       stage_cogl->last_presentation_time < now - 150000) | ||||
|   refresh_rate = stage_cogl->refresh_rate; | ||||
|   if (refresh_rate <= 0.0) | ||||
|     refresh_rate = clutter_get_default_frame_rate (); | ||||
|  | ||||
|   refresh_interval = (gint64) (0.5 + G_USEC_PER_SEC / refresh_rate); | ||||
|   if (refresh_interval == 0) | ||||
|     { | ||||
|       stage_cogl->update_time = now; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   refresh_rate = stage_cogl->refresh_rate; | ||||
|   if (refresh_rate == 0.0) | ||||
|     refresh_rate = 60.0; | ||||
|  | ||||
|   refresh_interval = (gint64) (0.5 + 1000000 / refresh_rate); | ||||
|   if (refresh_interval == 0) | ||||
|     refresh_interval = 16667; /* 1/60th second */ | ||||
|  | ||||
|   min_render_time_allowed = refresh_interval / 2; | ||||
|   max_render_time_allowed = refresh_interval - 1000 * sync_delay; | ||||
|  | ||||
|   /* Be robust in the case of incredibly bogus refresh rate */ | ||||
|   if (max_render_time_allowed <= 0) | ||||
|     { | ||||
|       g_warning ("Unsupported monitor refresh rate detected. " | ||||
|                  "(Refresh rate: %.3f, refresh interval: %ld)", | ||||
|                  refresh_rate, | ||||
|                  refresh_interval); | ||||
|       stage_cogl->update_time = now; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   if (min_render_time_allowed > max_render_time_allowed) | ||||
|     min_render_time_allowed = max_render_time_allowed; | ||||
|  | ||||
|   next_presentation_time = stage_cogl->last_presentation_time + refresh_interval; | ||||
|  | ||||
|   /* Get next_presentation_time closer to its final value, to reduce | ||||
|    * the number of while iterations below. | ||||
|    */ | ||||
|   if (next_presentation_time < now) | ||||
|     { | ||||
|       int64_t last_virtual_presentation_time = now - now % refresh_interval; | ||||
|       int64_t hardware_clock_phase = | ||||
|         stage_cogl->last_presentation_time % refresh_interval; | ||||
|  | ||||
|       next_presentation_time = | ||||
|         last_virtual_presentation_time + hardware_clock_phase; | ||||
|     } | ||||
|  | ||||
|   while (next_presentation_time < now + min_render_time_allowed) | ||||
|     next_presentation_time += refresh_interval; | ||||
|  | ||||
|   stage_cogl->update_time = next_presentation_time - max_render_time_allowed; | ||||
|  | ||||
|   if (stage_cogl->update_time == stage_cogl->last_update_time) | ||||
|     stage_cogl->update_time = stage_cogl->last_update_time + refresh_interval; | ||||
| } | ||||
|  | ||||
| static gint64 | ||||
| @@ -233,6 +254,7 @@ clutter_stage_cogl_clear_update_time (ClutterStageWindow *stage_window) | ||||
| { | ||||
|   ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); | ||||
|  | ||||
|   stage_cogl->last_update_time = stage_cogl->update_time; | ||||
|   stage_cogl->update_time = -1; | ||||
| } | ||||
|  | ||||
| @@ -905,26 +927,16 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, | ||||
|    */ | ||||
|   if (use_clipped_redraw) | ||||
|     { | ||||
|       if (use_clipped_redraw && clip_region_empty) | ||||
|       if (clip_region_empty) | ||||
|         { | ||||
|           do_swap_buffer = FALSE; | ||||
|         } | ||||
|       else if (use_clipped_redraw) | ||||
|       else | ||||
|         { | ||||
|           swap_region = fb_clip_region; | ||||
|           g_assert (swap_region.width > 0); | ||||
|           do_swap_buffer = TRUE; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           swap_region = (cairo_rectangle_int_t) { | ||||
|             .x = 0, | ||||
|             .y = 0, | ||||
|             .width = view_rect.width * fb_scale, | ||||
|             .height = view_rect.height * fb_scale, | ||||
|           }; | ||||
|           do_swap_buffer = TRUE; | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|     { | ||||
| @@ -934,6 +946,9 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window, | ||||
|  | ||||
|   if (do_swap_buffer) | ||||
|     { | ||||
|       COGL_TRACE_BEGIN_SCOPED (ClutterStageCoglRedrawViewSwapFramebuffer, | ||||
|                                "Paint (swap framebuffer)"); | ||||
|  | ||||
|       if (clutter_stage_view_get_onscreen (view) != | ||||
|           clutter_stage_view_get_framebuffer (view)) | ||||
|         { | ||||
| @@ -958,6 +973,8 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) | ||||
|   gboolean swap_event = FALSE; | ||||
|   GList *l; | ||||
|  | ||||
|   COGL_TRACE_BEGIN (ClutterStageCoglRedraw, "Paint (Cogl Redraw)"); | ||||
|  | ||||
|   for (l = _clutter_stage_window_get_views (stage_window); l; l = l->next) | ||||
|     { | ||||
|       ClutterStageView *view = l->data; | ||||
| @@ -966,6 +983,8 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) | ||||
|         clutter_stage_cogl_redraw_view (stage_window, view) || swap_event; | ||||
|     } | ||||
|  | ||||
|   _clutter_stage_emit_after_paint (stage_cogl->wrapper); | ||||
|  | ||||
|   _clutter_stage_window_finish_frame (stage_window); | ||||
|  | ||||
|   if (swap_event) | ||||
| @@ -981,6 +1000,8 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window) | ||||
|   stage_cogl->initialized_redraw_clip = FALSE; | ||||
|  | ||||
|   stage_cogl->frame_count++; | ||||
|  | ||||
|   COGL_TRACE_END (ClutterStageCoglRedraw); | ||||
| } | ||||
|  | ||||
| static void | ||||
|   | ||||
| @@ -53,6 +53,7 @@ struct _ClutterStageCogl | ||||
|  | ||||
|   gint64 last_presentation_time; | ||||
|   gint64 update_time; | ||||
|   int64_t last_update_time; | ||||
|  | ||||
|   /* We only enable clipped redraws after 2 frames, since we've seen | ||||
|    * a lot of drivers can struggle to get going and may output some | ||||
|   | ||||
| @@ -739,31 +739,33 @@ get_button_index (gint button) | ||||
| } | ||||
|  | ||||
| static void | ||||
| emulate_button_press (ClutterInputDeviceEvdev *device) | ||||
| emulate_button_press (ClutterInputDeviceEvdev *device_evdev) | ||||
| { | ||||
|   gint btn = device->mousekeys_btn; | ||||
|   ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); | ||||
|   gint btn = device_evdev->mousekeys_btn; | ||||
|  | ||||
|   if (device->mousekeys_btn_states[get_button_index (btn)]) | ||||
|   if (device_evdev->mousekeys_btn_states[get_button_index (btn)]) | ||||
|     return; | ||||
|  | ||||
|   clutter_virtual_input_device_notify_button (device->mousekeys_virtual_device, | ||||
|   clutter_virtual_input_device_notify_button (device->accessibility_virtual_device, | ||||
|                                               g_get_monotonic_time (), btn, | ||||
|                                               CLUTTER_BUTTON_STATE_PRESSED); | ||||
|   device->mousekeys_btn_states[get_button_index (btn)] = CLUTTER_BUTTON_STATE_PRESSED; | ||||
|   device_evdev->mousekeys_btn_states[get_button_index (btn)] = CLUTTER_BUTTON_STATE_PRESSED; | ||||
| } | ||||
|  | ||||
| static void | ||||
| emulate_button_release (ClutterInputDeviceEvdev *device) | ||||
| emulate_button_release (ClutterInputDeviceEvdev *device_evdev) | ||||
| { | ||||
|   gint btn = device->mousekeys_btn; | ||||
|   ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); | ||||
|   gint btn = device_evdev->mousekeys_btn; | ||||
|  | ||||
|   if (device->mousekeys_btn_states[get_button_index (btn)] == CLUTTER_BUTTON_STATE_RELEASED) | ||||
|   if (device_evdev->mousekeys_btn_states[get_button_index (btn)] == CLUTTER_BUTTON_STATE_RELEASED) | ||||
|     return; | ||||
|  | ||||
|   clutter_virtual_input_device_notify_button (device->mousekeys_virtual_device, | ||||
|   clutter_virtual_input_device_notify_button (device->accessibility_virtual_device, | ||||
|                                               g_get_monotonic_time (), btn, | ||||
|                                               CLUTTER_BUTTON_STATE_RELEASED); | ||||
|   device->mousekeys_btn_states[get_button_index (btn)] = CLUTTER_BUTTON_STATE_RELEASED; | ||||
|   device_evdev->mousekeys_btn_states[get_button_index (btn)] = CLUTTER_BUTTON_STATE_RELEASED; | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -830,17 +832,18 @@ mousekeys_get_speed_factor (ClutterInputDeviceEvdev *device, | ||||
| #undef MOUSEKEYS_CURVE | ||||
|  | ||||
| static void | ||||
| emulate_pointer_motion (ClutterInputDeviceEvdev *device, | ||||
| emulate_pointer_motion (ClutterInputDeviceEvdev *device_evdev, | ||||
|                         gint                     dx, | ||||
|                         gint                     dy) | ||||
| { | ||||
|   ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); | ||||
|   gdouble dx_motion; | ||||
|   gdouble dy_motion; | ||||
|   gdouble speed; | ||||
|   gint64 time_us; | ||||
|  | ||||
|   time_us = g_get_monotonic_time (); | ||||
|   speed = mousekeys_get_speed_factor (device, time_us); | ||||
|   speed = mousekeys_get_speed_factor (device_evdev, time_us); | ||||
|  | ||||
|   if (dx < 0) | ||||
|     dx_motion = floor (((gdouble) dx) * speed); | ||||
| @@ -852,7 +855,7 @@ emulate_pointer_motion (ClutterInputDeviceEvdev *device, | ||||
|   else | ||||
|     dy_motion = ceil (((gdouble) dy) * speed); | ||||
|  | ||||
|   clutter_virtual_input_device_notify_relative_motion (device->mousekeys_virtual_device, | ||||
|   clutter_virtual_input_device_notify_relative_motion (device->accessibility_virtual_device, | ||||
|                                                        time_us, dx_motion, dy_motion); | ||||
| } | ||||
| static gboolean | ||||
| @@ -865,51 +868,53 @@ is_numlock_active (ClutterInputDeviceEvdev *device) | ||||
| } | ||||
|  | ||||
| static void | ||||
| enable_mousekeys (ClutterInputDeviceEvdev *device) | ||||
| enable_mousekeys (ClutterInputDeviceEvdev *device_evdev) | ||||
| { | ||||
|   ClutterDeviceManager *manager; | ||||
|   ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); | ||||
|   ClutterDeviceManager *manager = device->device_manager; | ||||
|  | ||||
|   device->mousekeys_btn = CLUTTER_BUTTON_PRIMARY; | ||||
|   device->move_mousekeys_timer = 0; | ||||
|   device->mousekeys_first_motion_time = 0; | ||||
|   device->mousekeys_last_motion_time = 0; | ||||
|   device->last_mousekeys_key = 0; | ||||
|   device_evdev->mousekeys_btn = CLUTTER_BUTTON_PRIMARY; | ||||
|   device_evdev->move_mousekeys_timer = 0; | ||||
|   device_evdev->mousekeys_first_motion_time = 0; | ||||
|   device_evdev->mousekeys_last_motion_time = 0; | ||||
|   device_evdev->last_mousekeys_key = 0; | ||||
|  | ||||
|   if (device->mousekeys_virtual_device) | ||||
|   if (device->accessibility_virtual_device) | ||||
|     return; | ||||
|  | ||||
|   manager = CLUTTER_INPUT_DEVICE (device)->device_manager; | ||||
|   device->mousekeys_virtual_device = | ||||
|   device->accessibility_virtual_device = | ||||
|     clutter_device_manager_create_virtual_device (manager, | ||||
|                                                   CLUTTER_POINTER_DEVICE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| disable_mousekeys (ClutterInputDeviceEvdev *device) | ||||
| disable_mousekeys (ClutterInputDeviceEvdev *device_evdev) | ||||
| { | ||||
|   stop_mousekeys_move (device); | ||||
|   ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); | ||||
|  | ||||
|   stop_mousekeys_move (device_evdev); | ||||
|  | ||||
|   /* Make sure we don't leave button pressed behind... */ | ||||
|   if (device->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_PRIMARY)]) | ||||
|   if (device_evdev->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_PRIMARY)]) | ||||
|     { | ||||
|       device->mousekeys_btn = CLUTTER_BUTTON_PRIMARY; | ||||
|       emulate_button_release (device); | ||||
|       device_evdev->mousekeys_btn = CLUTTER_BUTTON_PRIMARY; | ||||
|       emulate_button_release (device_evdev); | ||||
|     } | ||||
|  | ||||
|   if (device->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_MIDDLE)]) | ||||
|   if (device_evdev->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_MIDDLE)]) | ||||
|     { | ||||
|       device->mousekeys_btn = CLUTTER_BUTTON_MIDDLE; | ||||
|       emulate_button_release (device); | ||||
|       device_evdev->mousekeys_btn = CLUTTER_BUTTON_MIDDLE; | ||||
|       emulate_button_release (device_evdev); | ||||
|     } | ||||
|  | ||||
|   if (device->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_SECONDARY)]) | ||||
|   if (device_evdev->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_SECONDARY)]) | ||||
|     { | ||||
|       device->mousekeys_btn = CLUTTER_BUTTON_SECONDARY; | ||||
|       emulate_button_release (device); | ||||
|       device_evdev->mousekeys_btn = CLUTTER_BUTTON_SECONDARY; | ||||
|       emulate_button_release (device_evdev); | ||||
|     } | ||||
|  | ||||
|   if (device->mousekeys_virtual_device) | ||||
|     g_clear_object (&device->mousekeys_virtual_device); | ||||
|   if (device->accessibility_virtual_device) | ||||
|     g_clear_object (&device->accessibility_virtual_device); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
|   | ||||
| @@ -94,7 +94,6 @@ struct _ClutterInputDeviceEvdev | ||||
|   gdouble mousekeys_curve_factor; | ||||
|   guint move_mousekeys_timer; | ||||
|   guint16 last_mousekeys_key; | ||||
|   ClutterVirtualInputDevice *mousekeys_virtual_device; | ||||
| }; | ||||
|  | ||||
| GType                     _clutter_input_device_evdev_get_type        (void) G_GNUC_CONST; | ||||
|   | ||||
| @@ -75,6 +75,7 @@ clutter_headers = [ | ||||
|   'clutter-snap-constraint.h', | ||||
|   'clutter-stage.h', | ||||
|   'clutter-stage-manager.h', | ||||
|   'clutter-stage-view.h', | ||||
|   'clutter-tap-action.h', | ||||
|   'clutter-test-utils.h', | ||||
|   'clutter-texture.h', | ||||
| @@ -133,6 +134,7 @@ clutter_sources = [ | ||||
|   'clutter-input-device-tool.c', | ||||
|   'clutter-input-focus.c', | ||||
|   'clutter-input-method.c', | ||||
|   'clutter-input-pointer-a11y.c', | ||||
|   'clutter-virtual-input-device.c', | ||||
|   'clutter-interval.c', | ||||
|   'clutter-keyframe-transition.c', | ||||
| @@ -163,6 +165,7 @@ clutter_sources = [ | ||||
|   'clutter-snap-constraint.c', | ||||
|   'clutter-stage.c', | ||||
|   'clutter-stage-manager.c', | ||||
|   'clutter-stage-view.c', | ||||
|   'clutter-stage-window.c', | ||||
|   'clutter-tap-action.c', | ||||
|   'clutter-test-utils.c', | ||||
| @@ -195,6 +198,7 @@ clutter_private_headers = [ | ||||
|   'clutter-id-pool.h', | ||||
|   'clutter-input-focus-private.h', | ||||
|   'clutter-input-method-private.h', | ||||
|   'clutter-input-pointer-a11y-private.h', | ||||
|   'clutter-master-clock.h', | ||||
|   'clutter-master-clock-default.h', | ||||
|   'clutter-offscreen-effect-private.h', | ||||
| @@ -205,7 +209,7 @@ clutter_private_headers = [ | ||||
|   'clutter-settings-private.h', | ||||
|   'clutter-stage-manager-private.h', | ||||
|   'clutter-stage-private.h', | ||||
|   'clutter-stage-view.h', | ||||
|   'clutter-stage-view-private.h', | ||||
|   'clutter-stage-window.h', | ||||
| ] | ||||
|  | ||||
| @@ -213,7 +217,6 @@ clutter_nonintrospected_sources = [ | ||||
|   'clutter-easing.c', | ||||
|   'clutter-event-translator.c', | ||||
|   'clutter-id-pool.c', | ||||
|   'clutter-stage-view.c', | ||||
| ] | ||||
|  | ||||
| clutter_deprecated_headers = [ | ||||
| @@ -341,14 +344,8 @@ if have_native_backend | ||||
| endif | ||||
|  | ||||
| if have_wayland | ||||
|   clutter_wayland_nonintrospected_sources = [ | ||||
|     'wayland/clutter-wayland-surface.c', | ||||
|   ] | ||||
|   clutter_backend_nonintrospected_sources += clutter_wayland_nonintrospected_sources | ||||
|  | ||||
|   clutter_wayland_private_headers = [ | ||||
|     'wayland/clutter-wayland-compositor.h', | ||||
|     'wayland/clutter-wayland-surface.h', | ||||
|   ] | ||||
|   clutter_backend_private_headers += clutter_wayland_private_headers | ||||
| endif | ||||
| @@ -504,7 +501,12 @@ libmutter_clutter_dep = declare_dependency( | ||||
| ) | ||||
|  | ||||
| if have_introspection | ||||
|   clutter_introspection_args = introspection_args + clutter_c_args | ||||
|   clutter_introspection_args = introspection_args + [ | ||||
|     '-DCLUTTER_SYSCONFDIR="@0@"'.format(join_paths(prefix, sysconfdir)), | ||||
|     '-DCLUTTER_COMPILATION=1', | ||||
|     '-DCOGL_DISABLE_DEPRECATION_WARNINGS', | ||||
|     '-DG_LOG_DOMAIN="Clutter"' | ||||
|   ] | ||||
|  | ||||
|   libmutter_clutter_gir = gnome.generate_gir(libmutter_clutter, | ||||
|     sources: [ | ||||
|   | ||||
| @@ -1,654 +0,0 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Copyright (C) 2011 Intel Corporation. | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This library 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 | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library. If not, see | ||||
|  * <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Authors: | ||||
|  *  Robert Bragg <robert@linux.intel.com> | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:clutter-wayland-surface | ||||
|  * @Title: ClutterWaylandSurface | ||||
|  * @short_description: An actor which displays the content of a client surface | ||||
|  * | ||||
|  * #ClutterWaylandSurface is an actor for displaying the contents of a client | ||||
|  * surface. It is intended to support developers implementing Clutter based | ||||
|  * wayland compositors. | ||||
|  */ | ||||
|  | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #define CLUTTER_ENABLE_EXPERIMENTAL_API | ||||
|  | ||||
| #include "clutter-wayland-surface.h" | ||||
|  | ||||
| #include "clutter-actor-private.h" | ||||
| #include "clutter-marshal.h" | ||||
| #include "clutter-paint-volume-private.h" | ||||
| #include "clutter-private.h" | ||||
| #include "clutter-backend.h" | ||||
|  | ||||
| #include <cogl/cogl.h> | ||||
| #include <cogl/cogl-wayland-server.h> | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_SURFACE = 1, | ||||
|   PROP_SURFACE_WIDTH, | ||||
|   PROP_SURFACE_HEIGHT, | ||||
|   PROP_COGL_TEXTURE, | ||||
|   PROP_LAST | ||||
| }; | ||||
|  | ||||
| static GParamSpec *obj_props[PROP_LAST]; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   QUEUE_DAMAGE_REDRAW, | ||||
|  | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| static guint signals[LAST_SIGNAL] = { 0, }; | ||||
|  | ||||
| struct _ClutterWaylandSurfacePrivate | ||||
| { | ||||
|   struct wl_surface *surface; | ||||
|   CoglTexture2D *buffer; | ||||
|   int width, height; | ||||
|   CoglPipeline *pipeline; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (ClutterWaylandSurface, | ||||
|                             clutter_wayland_surface, | ||||
|                             CLUTTER_TYPE_ACTOR) | ||||
|  | ||||
| static gboolean | ||||
| clutter_wayland_surface_get_paint_volume (ClutterActor *self, | ||||
|                                           ClutterPaintVolume *volume) | ||||
| { | ||||
|   return clutter_paint_volume_set_from_allocation (volume, self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_wayland_surface_queue_damage_redraw (ClutterWaylandSurface *texture, | ||||
|                                              gint x, | ||||
|                                              gint y, | ||||
|                                              gint width, | ||||
|                                              gint height) | ||||
| { | ||||
|   ClutterWaylandSurfacePrivate *priv = texture->priv; | ||||
|   ClutterActor *self = CLUTTER_ACTOR (texture); | ||||
|   ClutterActorBox allocation; | ||||
|   float scale_x; | ||||
|   float scale_y; | ||||
|   cairo_rectangle_int_t clip; | ||||
|  | ||||
|   /* NB: clutter_actor_queue_redraw_with_clip expects a box in the actor's | ||||
|    * coordinate space so we need to convert from surface coordinates to | ||||
|    * actor coordinates... | ||||
|    */ | ||||
|  | ||||
|   /* Calling clutter_actor_get_allocation_box() is enormously expensive | ||||
|    * if the actor has an out-of-date allocation, since it triggers | ||||
|    * a full redraw. clutter_actor_queue_redraw_with_clip() would redraw | ||||
|    * the whole stage anyways in that case, so just go ahead and do | ||||
|    * it here. | ||||
|    */ | ||||
|   if (!clutter_actor_has_allocation (self)) | ||||
|     { | ||||
|       clutter_actor_queue_redraw (self); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   if (priv->width == 0 || priv->height == 0) | ||||
|     return; | ||||
|  | ||||
|   clutter_actor_get_allocation_box (self, &allocation); | ||||
|  | ||||
|   scale_x = (allocation.x2 - allocation.x1) / priv->width; | ||||
|   scale_y = (allocation.y2 - allocation.y1) / priv->height; | ||||
|  | ||||
|   clip.x = x * scale_x; | ||||
|   clip.y = y * scale_y; | ||||
|   clip.width = width * scale_x; | ||||
|   clip.height = height * scale_y; | ||||
|   clutter_actor_queue_redraw_with_clip (self, &clip); | ||||
| } | ||||
|  | ||||
| static void | ||||
| free_pipeline (ClutterWaylandSurface *self) | ||||
| { | ||||
|   ClutterWaylandSurfacePrivate *priv = self->priv; | ||||
|  | ||||
|   if (priv->pipeline) | ||||
|     { | ||||
|       cogl_object_unref (priv->pipeline); | ||||
|       priv->pipeline = NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| opacity_change_cb (ClutterWaylandSurface *self) | ||||
| { | ||||
|   free_pipeline (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_wayland_surface_init (ClutterWaylandSurface *self) | ||||
| { | ||||
|   ClutterWaylandSurfacePrivate *priv; | ||||
|    | ||||
|   priv = clutter_wayland_surface_get_instance_private (self); | ||||
|   priv->surface = NULL; | ||||
|   priv->width = 0; | ||||
|   priv->height = 0; | ||||
|  | ||||
|   self->priv = priv; | ||||
|  | ||||
|   g_signal_connect (self, "notify::opacity", G_CALLBACK (opacity_change_cb), NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| free_surface_buffers (ClutterWaylandSurface *self) | ||||
| { | ||||
|   ClutterWaylandSurfacePrivate *priv = self->priv; | ||||
|  | ||||
|   if (priv->buffer) | ||||
|     { | ||||
|       cogl_object_unref (priv->buffer); | ||||
|       priv->buffer = NULL; | ||||
|       free_pipeline (self); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_wayland_surface_dispose (GObject *object) | ||||
| { | ||||
|   ClutterWaylandSurface *self = CLUTTER_WAYLAND_SURFACE (object); | ||||
|   ClutterWaylandSurfacePrivate *priv = self->priv; | ||||
|  | ||||
|   free_pipeline (self); | ||||
|   free_surface_buffers (self); | ||||
|   priv->surface = NULL; | ||||
|  | ||||
|   G_OBJECT_CLASS (clutter_wayland_surface_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_size (ClutterWaylandSurface *self, | ||||
|           int width, | ||||
|           int height) | ||||
| { | ||||
|   ClutterWaylandSurfacePrivate *priv = self->priv; | ||||
|  | ||||
|   if (priv->width != width) | ||||
|     { | ||||
|       priv->width = width; | ||||
|       g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SURFACE_WIDTH]); | ||||
|     } | ||||
|   if (priv->height != height) | ||||
|     { | ||||
|       priv->height = height; | ||||
|       g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SURFACE_HEIGHT]); | ||||
|     } | ||||
|  | ||||
|   clutter_actor_set_size (CLUTTER_ACTOR (self), priv->width, priv->height); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_wayland_surface_get_surface: | ||||
|  * @self: a #ClutterWaylandSurface | ||||
|  * | ||||
|  * Retrieves a point to the Wayland surface used by the actor. | ||||
|  * | ||||
|  * Return value: (transfer none): a wl_surface pointer, or %NULL | ||||
|  * | ||||
|  * Since: 1.10 | ||||
|  */ | ||||
| struct wl_surface * | ||||
| clutter_wayland_surface_get_surface (ClutterWaylandSurface *self) | ||||
| { | ||||
|   ClutterWaylandSurfacePrivate *priv = self->priv; | ||||
|   return priv->surface; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_wayland_surface_set_surface: | ||||
|  * @self: a #ClutterWaylandSurface | ||||
|  * @surface: a Wayland wl_surface pointer | ||||
|  * | ||||
|  * Sets the Wayland surface to be used by the actor. | ||||
|  * | ||||
|  * Since: 1.10 | ||||
|  */ | ||||
| void | ||||
| clutter_wayland_surface_set_surface (ClutterWaylandSurface *self, | ||||
|                                      struct wl_surface *surface) | ||||
| { | ||||
|   ClutterWaylandSurfacePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self)); | ||||
|  | ||||
|   priv = self->priv; | ||||
|  | ||||
|   if (priv->surface == surface) | ||||
|     return; | ||||
|  | ||||
|   if (priv->surface) | ||||
|     { | ||||
|       free_pipeline (self); | ||||
|       free_surface_buffers (self); | ||||
|       g_signal_emit (self, signals[QUEUE_DAMAGE_REDRAW], | ||||
|                      0, | ||||
|                      0, 0, priv->width, priv->height); | ||||
|     } | ||||
|  | ||||
|   priv->surface = surface; | ||||
|  | ||||
|   /* XXX: should we freeze/thaw notifications? */ | ||||
|  | ||||
|   g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SURFACE]); | ||||
|  | ||||
|   /* We have to wait until the next attach event to find out the surface | ||||
|    * geometry... */ | ||||
|   set_size (self, 0, 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_wayland_surface_set_property (GObject *object, | ||||
|                                       guint prop_id, | ||||
|                                       const GValue *value, | ||||
|                                       GParamSpec *pspec) | ||||
| { | ||||
|   ClutterWaylandSurface *self = CLUTTER_WAYLAND_SURFACE (object); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_SURFACE: | ||||
|       clutter_wayland_surface_set_surface (self, g_value_get_pointer (value)); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_wayland_surface_get_property (GObject *object, | ||||
|                                       guint prop_id, | ||||
|                                       GValue *value, | ||||
|                                       GParamSpec *pspec) | ||||
| { | ||||
|   ClutterWaylandSurface *self = CLUTTER_WAYLAND_SURFACE (object); | ||||
|   ClutterWaylandSurfacePrivate *priv = self->priv; | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_SURFACE: | ||||
|       g_value_set_pointer (value, priv->surface); | ||||
|       break; | ||||
|     case PROP_SURFACE_WIDTH: | ||||
|       g_value_set_uint (value, priv->width); | ||||
|       break; | ||||
|     case PROP_SURFACE_HEIGHT: | ||||
|       g_value_set_uint (value, priv->height); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_wayland_surface_paint (ClutterActor *self) | ||||
| { | ||||
|   ClutterWaylandSurfacePrivate *priv; | ||||
|   CoglFramebuffer *framebuffer; | ||||
|   ClutterActorBox box; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self)); | ||||
|  | ||||
|   priv = CLUTTER_WAYLAND_SURFACE (self)->priv; | ||||
|   framebuffer = cogl_get_draw_framebuffer (); | ||||
|  | ||||
|   if (G_UNLIKELY (priv->pipeline == NULL)) | ||||
|     { | ||||
|       CoglContext *ctx = | ||||
|         clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|       guint8 paint_opacity = clutter_actor_get_paint_opacity (self); | ||||
|  | ||||
|       priv->pipeline = cogl_pipeline_new (ctx); | ||||
|       cogl_pipeline_set_color4ub (priv->pipeline, | ||||
|                                   paint_opacity, | ||||
|                                   paint_opacity, | ||||
|                                   paint_opacity, | ||||
|                                   paint_opacity); | ||||
|       cogl_pipeline_set_layer_texture (priv->pipeline, 0, | ||||
|                                        COGL_TEXTURE (priv->buffer)); | ||||
|     } | ||||
|  | ||||
|   clutter_actor_get_allocation_box (self, &box); | ||||
|   cogl_framebuffer_draw_rectangle (framebuffer, | ||||
|                                    priv->pipeline, | ||||
|                                    0, 0, | ||||
|                                    box.x2 - box.x1, box.y2 - box.y1); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_wayland_surface_get_preferred_width (ClutterActor *self, | ||||
|                                              gfloat for_height, | ||||
|                                              gfloat *min_width_p, | ||||
|                                              gfloat *natural_width_p) | ||||
| { | ||||
|   ClutterWaylandSurfacePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self)); | ||||
|  | ||||
|   priv = CLUTTER_WAYLAND_SURFACE (self)->priv; | ||||
|  | ||||
|   if (min_width_p) | ||||
|     *min_width_p = 0; | ||||
|  | ||||
|   if (natural_width_p) | ||||
|     *natural_width_p = priv->width; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_wayland_surface_get_preferred_height (ClutterActor *self, | ||||
|                                               gfloat for_width, | ||||
|                                               gfloat *min_height_p, | ||||
|                                               gfloat *natural_height_p) | ||||
| { | ||||
|   ClutterWaylandSurfacePrivate *priv; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self)); | ||||
|  | ||||
|   priv = CLUTTER_WAYLAND_SURFACE (self)->priv; | ||||
|  | ||||
|   if (min_height_p) | ||||
|     *min_height_p = 0; | ||||
|  | ||||
|   if (natural_height_p) | ||||
|     *natural_height_p = priv->height; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_wayland_surface_has_overlaps (ClutterActor *self) | ||||
| { | ||||
|   /* Rectangles never need an offscreen redirect because there are | ||||
|      never any overlapping primitives */ | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_wayland_surface_class_init (ClutterWaylandSurfaceClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   GParamSpec *pspec; | ||||
|  | ||||
|   actor_class->get_paint_volume = clutter_wayland_surface_get_paint_volume; | ||||
|   actor_class->paint = clutter_wayland_surface_paint; | ||||
|   actor_class->get_preferred_width = | ||||
|     clutter_wayland_surface_get_preferred_width; | ||||
|   actor_class->get_preferred_height = | ||||
|     clutter_wayland_surface_get_preferred_height; | ||||
|   actor_class->has_overlaps = clutter_wayland_surface_has_overlaps; | ||||
|  | ||||
|   object_class->dispose      = clutter_wayland_surface_dispose; | ||||
|   object_class->set_property = clutter_wayland_surface_set_property; | ||||
|   object_class->get_property = clutter_wayland_surface_get_property; | ||||
|  | ||||
|   pspec = g_param_spec_pointer ("surface", | ||||
| 			        P_("Surface"), | ||||
| 			        P_("The underlying wayland surface"), | ||||
|                                 CLUTTER_PARAM_READWRITE| | ||||
|                                 G_PARAM_CONSTRUCT_ONLY); | ||||
|   obj_props[PROP_SURFACE] = pspec; | ||||
|   g_object_class_install_property (object_class, PROP_SURFACE, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_uint ("surface-width", | ||||
|                              P_("Surface width"), | ||||
|                              P_("The width of the underlying wayland surface"), | ||||
|                              0, G_MAXUINT, | ||||
|                              0, | ||||
|                              G_PARAM_READABLE); | ||||
|   obj_props[PROP_SURFACE_WIDTH] = pspec; | ||||
|   g_object_class_install_property (object_class, PROP_SURFACE_WIDTH, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_uint ("surface-height", | ||||
|                              P_("Surface height"), | ||||
|                              P_("The height of the underlying wayland surface"), | ||||
|                              0, G_MAXUINT, | ||||
|                              0, | ||||
|                              G_PARAM_READABLE); | ||||
|   obj_props[PROP_SURFACE_HEIGHT] = pspec; | ||||
|   g_object_class_install_property (object_class, PROP_SURFACE_HEIGHT, pspec); | ||||
|  | ||||
|   pspec = g_param_spec_boxed ("cogl-texture", | ||||
|                               P_("Cogl Texture"), | ||||
|                               P_("The underlying Cogl texture handle used to draw this actor"), | ||||
|                               COGL_TYPE_HANDLE, | ||||
|                               CLUTTER_PARAM_READWRITE); | ||||
|   obj_props[PROP_COGL_TEXTURE] = pspec; | ||||
|   g_object_class_install_property (object_class, PROP_COGL_TEXTURE, pspec); | ||||
|  | ||||
|   /** | ||||
|    * ClutterWaylandSurface::queue-damage-redraw: | ||||
|    * @texture: the object which received the signal | ||||
|    * @x: The top left x position of the damage region | ||||
|    * @y: The top left y position of the damage region | ||||
|    * @width: The width of the damage region | ||||
|    * @height: The height of the damage region | ||||
|    * | ||||
|    * ::queue-damage-redraw is emitted to notify that some sub-region | ||||
|    * of the texture has been changed. This usually means a redraw | ||||
|    * needs to be queued for the actor. | ||||
|    * | ||||
|    * The default handler will queue a clipped redraw in response to | ||||
|    * the damage, using the assumption that the pixmap is being painted | ||||
|    * to a rectangle covering the transformed allocation of the actor. | ||||
|    * If you sub-class and change the paint method so this isn't true | ||||
|    * then you must also provide your own damage signal handler to | ||||
|    * queue a redraw that blocks this default behaviour. | ||||
|    * | ||||
|    * Since: 1.10 | ||||
|    */ | ||||
|   signals[QUEUE_DAMAGE_REDRAW] = | ||||
|     g_signal_new (g_intern_static_string ("queue-damage-redraw"), | ||||
|                   G_TYPE_FROM_CLASS (object_class), | ||||
|                   G_SIGNAL_RUN_FIRST, | ||||
|                   G_STRUCT_OFFSET (ClutterWaylandSurfaceClass, queue_damage_redraw), | ||||
|                   NULL, NULL, | ||||
|                   _clutter_marshal_VOID__INT_INT_INT_INT, | ||||
|                   G_TYPE_NONE, 4, | ||||
|                   G_TYPE_INT, | ||||
|                   G_TYPE_INT, | ||||
|                   G_TYPE_INT, | ||||
|                   G_TYPE_INT); | ||||
|   klass->queue_damage_redraw = clutter_wayland_surface_queue_damage_redraw; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_wayland_surface_new: | ||||
|  * @surface: the Wayland surface this actor should represent | ||||
|  * | ||||
|  * Creates a new #ClutterWaylandSurface for @surface | ||||
|  * | ||||
|  * Return value: A new #ClutterWaylandSurface representing @surface | ||||
|  * | ||||
|  * Since: 1.8 | ||||
|  * Stability: unstable | ||||
|  */ | ||||
| ClutterActor * | ||||
| clutter_wayland_surface_new (struct wl_surface *surface) | ||||
| { | ||||
|   ClutterActor *actor; | ||||
|  | ||||
|   actor = g_object_new (CLUTTER_WAYLAND_TYPE_SURFACE, | ||||
|                         "surface", surface, | ||||
|                         NULL); | ||||
|  | ||||
|   return actor; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_wayland_surface_attach_buffer: | ||||
|  * @self: A #ClutterWaylandSurface actor | ||||
|  * @buffer: A compositor side resource representing a wl_buffer | ||||
|  * @error: A #GError | ||||
|  * | ||||
|  * This associates a client's buffer with the #ClutterWaylandSurface | ||||
|  * actor @self. This will automatically result in @self being re-drawn | ||||
|  * with the new buffer contents. | ||||
|  * | ||||
|  * Since: 1.8 | ||||
|  * Stability: unstable | ||||
|  */ | ||||
| gboolean | ||||
| clutter_wayland_surface_attach_buffer (ClutterWaylandSurface *self, | ||||
|                                        struct wl_resource *buffer, | ||||
|                                        GError **error) | ||||
| { | ||||
|   ClutterWaylandSurfacePrivate *priv; | ||||
|   ClutterBackend *backend = clutter_get_default_backend (); | ||||
|   CoglContext *context = clutter_backend_get_cogl_context (backend); | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self), TRUE); | ||||
|  | ||||
|   priv = self->priv; | ||||
|  | ||||
|   free_surface_buffers (self); | ||||
|  | ||||
|   priv->buffer = | ||||
|     cogl_wayland_texture_2d_new_from_buffer (context, buffer, error); | ||||
|  | ||||
|   g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_COGL_TEXTURE]); | ||||
|  | ||||
|   /* NB: We don't queue a redraw of the actor here because we don't | ||||
|    * know how much of the buffer has changed with respect to the | ||||
|    * previous buffer. We only ever queue a redraw in response to | ||||
|    * surface damage. */ | ||||
|  | ||||
|   if (!priv->buffer) | ||||
|     return FALSE; | ||||
|  | ||||
|   set_size (self, | ||||
|             cogl_texture_get_width (COGL_TEXTURE (priv->buffer)), | ||||
|             cogl_texture_get_height (COGL_TEXTURE (priv->buffer))); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_wayland_surface_damage_buffer: | ||||
|  * @self: A #ClutterWaylandSurface actor | ||||
|  * @buffer: A wayland resource for a buffer | ||||
|  * @x: The x coordinate of the damaged rectangle | ||||
|  * @y: The y coordinate of the damaged rectangle | ||||
|  * @width: The width of the damaged rectangle | ||||
|  * @height: The height of the damaged rectangle | ||||
|  * | ||||
|  * This marks a region of the given @buffer has having been changed by | ||||
|  * the client. This will automatically result in the corresponding damaged | ||||
|  * region of the actor @self being redrawn. | ||||
|  * | ||||
|  * If multiple regions are changed then this should be called multiple | ||||
|  * times with different damage rectangles. | ||||
|  * | ||||
|  * Since: 1.8 | ||||
|  * Stability: unstable | ||||
|  */ | ||||
| void | ||||
| clutter_wayland_surface_damage_buffer (ClutterWaylandSurface *self, | ||||
|                                        struct wl_resource *buffer, | ||||
|                                        gint32 x, | ||||
|                                        gint32 y, | ||||
|                                        gint32 width, | ||||
|                                        gint32 height) | ||||
| { | ||||
|   ClutterWaylandSurfacePrivate *priv; | ||||
|   struct wl_shm_buffer *shm_buffer; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self)); | ||||
|  | ||||
|   priv = self->priv; | ||||
|  | ||||
|   shm_buffer = wl_shm_buffer_get (buffer); | ||||
|  | ||||
|   if (priv->buffer && shm_buffer) | ||||
|     { | ||||
|       CoglPixelFormat format; | ||||
|  | ||||
|       switch (wl_shm_buffer_get_format (shm_buffer)) | ||||
|         { | ||||
| #if G_BYTE_ORDER == G_BIG_ENDIAN | ||||
|           case WL_SHM_FORMAT_ARGB8888: | ||||
|             format = COGL_PIXEL_FORMAT_ARGB_8888_PRE; | ||||
|             break; | ||||
|           case WL_SHM_FORMAT_XRGB8888: | ||||
|             format = COGL_PIXEL_FORMAT_ARGB_8888; | ||||
|             break; | ||||
| #elif G_BYTE_ORDER == G_LITTLE_ENDIAN | ||||
|           case WL_SHM_FORMAT_ARGB8888: | ||||
|             format = COGL_PIXEL_FORMAT_BGRA_8888_PRE; | ||||
|             break; | ||||
|           case WL_SHM_FORMAT_XRGB8888: | ||||
|             format = COGL_PIXEL_FORMAT_BGRA_8888; | ||||
|             break; | ||||
| #endif | ||||
|           default: | ||||
|             g_warn_if_reached (); | ||||
|             format = COGL_PIXEL_FORMAT_ARGB_8888; | ||||
|         } | ||||
|  | ||||
|       cogl_texture_set_region (COGL_TEXTURE (priv->buffer), | ||||
|                                x, y, | ||||
|                                x, y, | ||||
|                                width, height, | ||||
|                                width, height, | ||||
|                                format, | ||||
|                                wl_shm_buffer_get_stride (shm_buffer), | ||||
|                                wl_shm_buffer_get_data (shm_buffer)); | ||||
|     } | ||||
|  | ||||
|   g_signal_emit (self, signals[QUEUE_DAMAGE_REDRAW], | ||||
|                  0, | ||||
|                  x, y, width, height); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_wayland_surface_get_cogl_texture: | ||||
|  * @self: a #ClutterWaylandSurface | ||||
|  * | ||||
|  * Retrieves the Cogl texture with the contents of the Wayland surface. | ||||
|  * | ||||
|  * Return value: (transfer none): a Cogl texture, or %NULL | ||||
|  * | ||||
|  * Since: 1.10 | ||||
|  */ | ||||
| CoglTexture * | ||||
| clutter_wayland_surface_get_cogl_texture (ClutterWaylandSurface *self) | ||||
| { | ||||
|   g_return_val_if_fail (CLUTTER_WAYLAND_IS_SURFACE (self), NULL); | ||||
|  | ||||
|   return COGL_TEXTURE (self->priv->buffer); | ||||
| } | ||||
| @@ -1,117 +0,0 @@ | ||||
| /* | ||||
|  * Clutter. | ||||
|  * | ||||
|  * An OpenGL based 'interactive canvas' library. | ||||
|  * | ||||
|  * Copyright (C) 2011 Intel Corporation. | ||||
|  * | ||||
|  * This library is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This library 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 | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library. If not, see | ||||
|  * <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Authors: | ||||
|  *   Robert Bragg <robert@linux.intel.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef __CLUTTER_WAYLAND_SURFACE_H__ | ||||
| #define __CLUTTER_WAYLAND_SURFACE_H__ | ||||
|  | ||||
| #include <glib.h> | ||||
| #include <glib-object.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include <wayland-server.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define CLUTTER_WAYLAND_TYPE_SURFACE                 (clutter_wayland_surface_get_type ()) | ||||
| #define CLUTTER_WAYLAND_SURFACE(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_WAYLAND_TYPE_SURFACE, ClutterWaylandSurface)) | ||||
| #define CLUTTER_WAYLAND_SURFACE_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_WAYLAND_TYPE_SURFACE, ClutterWaylandSurfaceClass)) | ||||
| #define CLUTTER_WAYLAND_IS_SURFACE(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_WAYLAND_TYPE_SURFACE)) | ||||
| #define CLUTTER_WAYLAND_IS_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_WAYLAND_TYPE_SURFACE)) | ||||
| #define CLUTTER_WAYLAND_SURFACE_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_WAYLAND_TYPE_SURFACE, ClutterWaylandSurfaceClass)) | ||||
|  | ||||
| typedef struct _ClutterWaylandSurface        ClutterWaylandSurface; | ||||
| typedef struct _ClutterWaylandSurfaceClass   ClutterWaylandSurfaceClass; | ||||
| typedef struct _ClutterWaylandSurfacePrivate ClutterWaylandSurfacePrivate; | ||||
|  | ||||
| /** | ||||
|  * ClutterWaylandSurface: | ||||
|  * | ||||
|  * The #ClutterWaylandSurface structure contains only private data | ||||
|  * | ||||
|  * Since: 1.10 | ||||
|  * Stability: unstable | ||||
|  */ | ||||
| struct _ClutterWaylandSurface | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActor parent; | ||||
|  | ||||
|   ClutterWaylandSurfacePrivate *priv; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * ClutterWaylandSurfaceClass: | ||||
|  * @queue_damage_redraw: class handler of the #ClutterWaylandSurface::queue-damage-redraw signal | ||||
|  * | ||||
|  * The #ClutterWaylandSurfaceClass structure contains only private data | ||||
|  * | ||||
|  * Since: 1.10 | ||||
|  * Stability: unstable | ||||
|  */ | ||||
| struct _ClutterWaylandSurfaceClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActorClass parent_class; | ||||
|  | ||||
|   /*< public >*/ | ||||
|   void (*queue_damage_redraw) (ClutterWaylandSurface *texture, | ||||
|                                gint x, | ||||
|                                gint y, | ||||
|                                gint width, | ||||
|                                gint height); | ||||
|  | ||||
|   /*< private >*/ | ||||
|   /* padding for future expansion */ | ||||
|   gpointer _padding_dummy[8]; | ||||
| }; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| GType clutter_wayland_surface_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterActor *clutter_wayland_surface_new               (struct wl_surface *surface); | ||||
| CLUTTER_EXPORT | ||||
| void          clutter_wayland_surface_set_surface       (ClutterWaylandSurface *self, | ||||
|                                                          struct wl_surface *surface); | ||||
| CLUTTER_EXPORT | ||||
| struct wl_surface *clutter_wayland_surface_get_surface  (ClutterWaylandSurface *self); | ||||
| CLUTTER_EXPORT | ||||
| gboolean      clutter_wayland_surface_attach_buffer     (ClutterWaylandSurface *self, | ||||
|                                                          struct wl_resource *buffer, | ||||
|                                                          GError **error); | ||||
| CLUTTER_EXPORT | ||||
| void          clutter_wayland_surface_damage_buffer     (ClutterWaylandSurface *self, | ||||
|                                                          struct wl_resource *buffer, | ||||
|                                                          gint32 x, | ||||
|                                                          gint32 y, | ||||
|                                                          gint32 width, | ||||
|                                                          gint32 height); | ||||
| CLUTTER_EXPORT | ||||
| CoglTexture  *clutter_wayland_surface_get_cogl_texture  (ClutterWaylandSurface *self); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif | ||||
| @@ -89,7 +89,6 @@ static const gchar *atom_names[] = { | ||||
|   "_NET_WM_PID", | ||||
|   "_NET_WM_PING", | ||||
|   "_NET_WM_STATE", | ||||
|   "_NET_WM_STATE_FULLSCREEN", | ||||
|   "_NET_WM_USER_TIME", | ||||
|   "WM_PROTOCOLS", | ||||
|   "WM_DELETE_WINDOW", | ||||
| @@ -441,14 +440,13 @@ clutter_backend_x11_post_parse (ClutterBackend  *backend, | ||||
|   backend_x11->atom_NET_WM_PID = atoms[0]; | ||||
|   backend_x11->atom_NET_WM_PING = atoms[1]; | ||||
|   backend_x11->atom_NET_WM_STATE = atoms[2]; | ||||
|   backend_x11->atom_NET_WM_STATE_FULLSCREEN = atoms[3]; | ||||
|   backend_x11->atom_NET_WM_USER_TIME = atoms[4]; | ||||
|   backend_x11->atom_WM_PROTOCOLS = atoms[5]; | ||||
|   backend_x11->atom_WM_DELETE_WINDOW = atoms[6]; | ||||
|   backend_x11->atom_XEMBED = atoms[7]; | ||||
|   backend_x11->atom_XEMBED_INFO = atoms[8]; | ||||
|   backend_x11->atom_NET_WM_NAME = atoms[9]; | ||||
|   backend_x11->atom_UTF8_STRING = atoms[10]; | ||||
|   backend_x11->atom_NET_WM_USER_TIME = atoms[3]; | ||||
|   backend_x11->atom_WM_PROTOCOLS = atoms[4]; | ||||
|   backend_x11->atom_WM_DELETE_WINDOW = atoms[5]; | ||||
|   backend_x11->atom_XEMBED = atoms[6]; | ||||
|   backend_x11->atom_XEMBED_INFO = atoms[7]; | ||||
|   backend_x11->atom_NET_WM_NAME = atoms[8]; | ||||
|   backend_x11->atom_UTF8_STRING = atoms[9]; | ||||
|  | ||||
|   g_free (clutter_display_name); | ||||
|  | ||||
| @@ -563,8 +561,7 @@ clutter_backend_x11_dispose (GObject *gobject) | ||||
| static ClutterFeatureFlags | ||||
| clutter_backend_x11_get_features (ClutterBackend *backend) | ||||
| { | ||||
|   ClutterFeatureFlags flags = CLUTTER_FEATURE_STAGE_USER_RESIZE | ||||
|                             | CLUTTER_FEATURE_STAGE_CURSOR; | ||||
|   ClutterFeatureFlags flags = CLUTTER_FEATURE_STAGE_CURSOR; | ||||
|  | ||||
|   flags |= CLUTTER_BACKEND_CLASS (clutter_backend_x11_parent_class)->get_features (backend); | ||||
|  | ||||
|   | ||||
| @@ -89,7 +89,6 @@ struct _ClutterBackendX11 | ||||
|   Atom atom_NET_WM_PID; | ||||
|   Atom atom_NET_WM_PING; | ||||
|   Atom atom_NET_WM_STATE; | ||||
|   Atom atom_NET_WM_STATE_FULLSCREEN; | ||||
|   Atom atom_NET_WM_USER_TIME; | ||||
|   Atom atom_WM_PROTOCOLS; | ||||
|   Atom atom_WM_DELETE_WINDOW; | ||||
|   | ||||
| @@ -30,6 +30,7 @@ | ||||
| #include "clutter-backend-x11.h" | ||||
| #include "clutter-input-device-xi2.h" | ||||
| #include "clutter-input-device-tool-xi2.h" | ||||
| #include "clutter-input-pointer-a11y-private.h" | ||||
| #include "clutter-virtual-input-device-x11.h" | ||||
| #include "clutter-stage-x11.h" | ||||
|  | ||||
| @@ -1273,6 +1274,60 @@ translate_pad_event (ClutterEvent       *event, | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| handle_raw_event (ClutterDeviceManagerXI2 *manager_xi2, | ||||
|                   XEvent                  *xevent) | ||||
| { | ||||
|   ClutterInputDevice *device; | ||||
|   XGenericEventCookie *cookie; | ||||
|   XIEvent *xi_event; | ||||
|   XIRawEvent *xev; | ||||
|   float x,y; | ||||
|  | ||||
|   cookie = &xevent->xcookie; | ||||
|   xi_event = (XIEvent *) cookie->data; | ||||
|   xev = (XIRawEvent *) xi_event; | ||||
|  | ||||
|   device = g_hash_table_lookup (manager_xi2->devices_by_id, | ||||
|                                 GINT_TO_POINTER (xev->deviceid)); | ||||
|   if (device == NULL) | ||||
|     return; | ||||
|  | ||||
|   if (!_clutter_is_input_pointer_a11y_enabled (device)) | ||||
|     return; | ||||
|  | ||||
|   switch (cookie->evtype) | ||||
|     { | ||||
|     case XI_RawMotion: | ||||
|       CLUTTER_NOTE (EVENT, | ||||
|                     "raw motion: device:%d '%s'", | ||||
|                     device->id, | ||||
|                     device->device_name); | ||||
|       /* We don't get actual pointer location with raw events, and we cannot | ||||
|        * rely on `clutter_input_device_get_coords()` either because of | ||||
|        * unreparented toplevels (like all client-side decoration windows), | ||||
|        * so we need to explicitely query the pointer here... | ||||
|        */ | ||||
|       if (clutter_input_device_xi2_get_pointer_location (device, &x, &y)) | ||||
|         _clutter_input_pointer_a11y_on_motion_event (device, x, y); | ||||
|       break; | ||||
|     case XI_RawButtonPress: | ||||
|     case XI_RawButtonRelease: | ||||
|       CLUTTER_NOTE (EVENT, | ||||
|                     "raw button %s: device:%d '%s' button %i", | ||||
|                     cookie->evtype == XI_RawButtonPress | ||||
|                       ? "press  " | ||||
|                       : "release", | ||||
|                     device->id, | ||||
|                     device->device_name, | ||||
|                     xev->detail); | ||||
|       _clutter_input_pointer_a11y_on_button_event (device, | ||||
|                                                   xev->detail, | ||||
|                                                   (cookie->evtype == XI_RawButtonPress)); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static ClutterTranslateReturn | ||||
| clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator, | ||||
|                                             gpointer                native, | ||||
| @@ -1303,6 +1358,14 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator, | ||||
|   if (!xi_event) | ||||
|     return CLUTTER_TRANSLATE_REMOVE; | ||||
|  | ||||
|   if (cookie->evtype == XI_RawMotion || | ||||
|       cookie->evtype == XI_RawButtonPress || | ||||
|       cookie->evtype == XI_RawButtonRelease) | ||||
|     { | ||||
|       handle_raw_event (manager_xi2, xevent); | ||||
|       return CLUTTER_TRANSLATE_REMOVE; | ||||
|     } | ||||
|  | ||||
|   if (!(xi_event->evtype == XI_HierarchyChanged || | ||||
|         xi_event->evtype == XI_DeviceChanged || | ||||
|         xi_event->evtype == XI_PropertyEvent)) | ||||
| @@ -2031,7 +2094,7 @@ clutter_device_manager_xi2_constructed (GObject *gobject) | ||||
|   GHashTable *masters, *slaves; | ||||
|   XIDeviceInfo *info; | ||||
|   XIEventMask event_mask; | ||||
|   unsigned char mask[2] = { 0, }; | ||||
|   unsigned char mask[(XI_LASTEVENT + 7) / 8] = { 0, }; | ||||
|   int n_devices, i; | ||||
|  | ||||
|   backend_x11 = | ||||
| @@ -2083,6 +2146,19 @@ clutter_device_manager_xi2_constructed (GObject *gobject) | ||||
|   event_mask.mask_len = sizeof (mask); | ||||
|   event_mask.mask = mask; | ||||
|  | ||||
|   clutter_device_manager_xi2_select_events (manager, | ||||
|                                             clutter_x11_get_root_window (), | ||||
|                                             &event_mask); | ||||
|  | ||||
|   memset(mask, 0, sizeof (mask)); | ||||
|   XISetMask (mask, XI_RawMotion); | ||||
|   XISetMask (mask, XI_RawButtonPress); | ||||
|   XISetMask (mask, XI_RawButtonRelease); | ||||
|  | ||||
|   event_mask.deviceid = XIAllMasterDevices; | ||||
|   event_mask.mask_len = sizeof (mask); | ||||
|   event_mask.mask = mask; | ||||
|  | ||||
|   clutter_device_manager_xi2_select_events (manager, | ||||
|                                             clutter_x11_get_root_window (), | ||||
|                                             &event_mask); | ||||
|   | ||||
| @@ -46,6 +46,11 @@ struct _ClutterInputDeviceXI2 | ||||
|   gint device_id; | ||||
|   ClutterInputDeviceTool *current_tool; | ||||
|  | ||||
|   guint inhibit_pointer_query_timer; | ||||
|   gboolean query_status; | ||||
|   float current_x; | ||||
|   float current_y; | ||||
|  | ||||
| #ifdef HAVE_LIBWACOM | ||||
|   WacomDevice *wacom_device; | ||||
|   GArray *group_modes; | ||||
| @@ -112,6 +117,9 @@ clutter_input_device_xi2_finalize (GObject *object) | ||||
|  | ||||
|   if (device_xi2->group_modes) | ||||
|     g_array_unref (device_xi2->group_modes); | ||||
|  | ||||
|   if (device_xi2->inhibit_pointer_query_timer) | ||||
|     g_source_remove (device_xi2->inhibit_pointer_query_timer); | ||||
| #endif | ||||
|  | ||||
|   G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->finalize (object); | ||||
| @@ -293,6 +301,75 @@ clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device) | ||||
|   return device_xi2->current_tool; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clutter_input_device_xi2_query_pointer_location (ClutterInputDeviceXI2 *device_xi2) | ||||
| { | ||||
|   Window xroot_window, xchild_window; | ||||
|   double xroot_x, xroot_y, xwin_x, xwin_y; | ||||
|   XIButtonState button_state; | ||||
|   XIModifierState mod_state; | ||||
|   XIGroupState group_state; | ||||
|   int result; | ||||
|  | ||||
|   clutter_x11_trap_x_errors (); | ||||
|   result = XIQueryPointer (clutter_x11_get_default_display (), | ||||
|                            device_xi2->device_id, | ||||
|                            clutter_x11_get_root_window (), | ||||
|                            &xroot_window, | ||||
|                            &xchild_window, | ||||
|                            &xroot_x, &xroot_y, | ||||
|                            &xwin_x, &xwin_y, | ||||
|                            &button_state, | ||||
|                            &mod_state, | ||||
|                            &group_state); | ||||
|   clutter_x11_untrap_x_errors (); | ||||
|  | ||||
|   if (!result) | ||||
|     return FALSE; | ||||
|  | ||||
|   device_xi2->current_x = (float) xroot_x; | ||||
|   device_xi2->current_y = (float) xroot_y; | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| clear_inhibit_pointer_query_cb (gpointer data) | ||||
| { | ||||
|   ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (data); | ||||
|  | ||||
|   device_xi2->inhibit_pointer_query_timer = 0; | ||||
|  | ||||
|   return G_SOURCE_REMOVE; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| clutter_input_device_xi2_get_pointer_location (ClutterInputDevice *device, | ||||
|                                                float              *x, | ||||
|                                                float              *y) | ||||
|  | ||||
| { | ||||
|   ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); | ||||
|  | ||||
|   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE); | ||||
|   g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_XI2 (device_xi2), FALSE); | ||||
|   g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, FALSE); | ||||
|  | ||||
|   /* Throttle XServer queries and roundtrips using an idle timeout */ | ||||
|   if (device_xi2->inhibit_pointer_query_timer == 0) | ||||
|     { | ||||
|       device_xi2->query_status = | ||||
|         clutter_input_device_xi2_query_pointer_location (device_xi2); | ||||
|       device_xi2->inhibit_pointer_query_timer = | ||||
|         clutter_threads_add_idle (clear_inhibit_pointer_query_cb, device_xi2); | ||||
|     } | ||||
|  | ||||
|   *x = device_xi2->current_x; | ||||
|   *y = device_xi2->current_y; | ||||
|  | ||||
|   return device_xi2->query_status; | ||||
| } | ||||
|  | ||||
| #ifdef HAVE_LIBWACOM | ||||
| void | ||||
| clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice  *device, | ||||
|   | ||||
| @@ -48,6 +48,9 @@ void  _clutter_input_device_xi2_translate_state (ClutterEvent    *event, | ||||
| void  clutter_input_device_xi2_update_tool      (ClutterInputDevice     *device, | ||||
|                                                  ClutterInputDeviceTool *tool); | ||||
| ClutterInputDeviceTool * clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device); | ||||
| gboolean clutter_input_device_xi2_get_pointer_location (ClutterInputDevice *device, | ||||
|                                                         float              *x, | ||||
|                                                         float              *y); | ||||
|  | ||||
| #ifdef HAVE_LIBWACOM | ||||
| void clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice  *device, | ||||
|   | ||||
| @@ -87,60 +87,6 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageX11, | ||||
|   ButtonReleaseMask | \ | ||||
|   PointerMotionMask | ||||
|  | ||||
| static void | ||||
| send_wmspec_change_state (ClutterBackendX11 *backend_x11, | ||||
|                           Window             window, | ||||
|                           Atom               state, | ||||
|                           gboolean           add) | ||||
| { | ||||
|   XClientMessageEvent xclient; | ||||
|  | ||||
|   CLUTTER_NOTE (BACKEND, "%s NET_WM state", add ? "adding" : "removing"); | ||||
|  | ||||
|   memset (&xclient, 0, sizeof (xclient)); | ||||
|  | ||||
|   xclient.type         = ClientMessage; | ||||
|   xclient.window       = window; | ||||
|   xclient.message_type = backend_x11->atom_NET_WM_STATE; | ||||
|   xclient.format       = 32; | ||||
|  | ||||
|   xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; | ||||
|   xclient.data.l[1] = state; | ||||
|   xclient.data.l[2] = 0; | ||||
|   xclient.data.l[3] = 0; | ||||
|   xclient.data.l[4] = 0; | ||||
|  | ||||
|   XSendEvent (backend_x11->xdpy,  | ||||
|               DefaultRootWindow (backend_x11->xdpy), | ||||
|               False, | ||||
|               SubstructureRedirectMask | SubstructureNotifyMask, | ||||
|               (XEvent *)&xclient); | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_state (ClutterStageX11   *stage_x11, | ||||
|               ClutterBackendX11 *backend_x11, | ||||
|               Atom              *state, | ||||
|               gboolean           add) | ||||
| { | ||||
|   if (add) | ||||
|     { | ||||
|       /* FIXME: This wont work if we support more states */ | ||||
|       XChangeProperty (backend_x11->xdpy, | ||||
|                        stage_x11->xwin, | ||||
|                        backend_x11->atom_NET_WM_STATE, XA_ATOM, 32, | ||||
|                        PropModeReplace, | ||||
|                        (unsigned char *) state, 1); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|        /* FIXME: This wont work if we support more states */ | ||||
|        XDeleteProperty (backend_x11->xdpy, | ||||
|                         stage_x11->xwin, | ||||
|                         backend_x11->atom_NET_WM_STATE); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11, | ||||
|                                    gint             new_width, | ||||
| @@ -153,9 +99,6 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11, | ||||
|     { | ||||
|       guint min_width, min_height; | ||||
|       XSizeHints *size_hints; | ||||
|       gboolean resize; | ||||
|  | ||||
|       resize = clutter_stage_get_user_resizable (stage_cogl->wrapper); | ||||
|  | ||||
|       size_hints = XAllocSizeHints(); | ||||
|  | ||||
| @@ -169,27 +112,11 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11, | ||||
|       if (new_height <= 0) | ||||
|         new_height = min_height; | ||||
|  | ||||
|       size_hints->flags = 0; | ||||
|  | ||||
|       /* If we are going fullscreen then we don't want any | ||||
|          restrictions on the window size */ | ||||
|       if (!stage_x11->fullscreening) | ||||
|         { | ||||
|           if (resize) | ||||
|             { | ||||
|               size_hints->min_width = min_width; | ||||
|               size_hints->min_height = min_height; | ||||
|               size_hints->flags = PMinSize; | ||||
|             } | ||||
|           else | ||||
|             { | ||||
|               size_hints->min_width = new_width; | ||||
|               size_hints->min_height = new_height; | ||||
|               size_hints->max_width = new_width; | ||||
|               size_hints->max_height = new_height; | ||||
|               size_hints->flags = PMinSize | PMaxSize; | ||||
|             } | ||||
|         } | ||||
|       size_hints->min_width = new_width; | ||||
|       size_hints->min_height = new_height; | ||||
|       size_hints->max_width = new_width; | ||||
|       size_hints->max_height = new_height; | ||||
|       size_hints->flags = PMinSize | PMaxSize; | ||||
|  | ||||
|       XSetWMNormalHints (backend_x11->xdpy, stage_x11->xwin, size_hints); | ||||
|  | ||||
| @@ -216,28 +143,8 @@ clutter_stage_x11_get_geometry (ClutterStageWindow    *stage_window, | ||||
|                                 cairo_rectangle_int_t *geometry) | ||||
| { | ||||
|   ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); | ||||
|   ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); | ||||
|   ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); | ||||
|  | ||||
|   geometry->x = geometry->y = 0; | ||||
|  | ||||
|   /* If we're fullscreen, return the size of the display. | ||||
|    * | ||||
|    * FIXME - this is utterly broken for anything that is not a single | ||||
|    * head set up; the window manager will give us the right size in a | ||||
|    * ConfigureNotify, but between the fullscreen signal emission on the | ||||
|    * stage and the following frame, the size returned by the stage will | ||||
|    * be wrong. | ||||
|    */ | ||||
|   if (_clutter_stage_is_fullscreen (stage_cogl->wrapper) && | ||||
|       stage_x11->fullscreening) | ||||
|     { | ||||
|       geometry->width = DisplayWidth (backend_x11->xdpy, backend_x11->xscreen_num); | ||||
|       geometry->height = DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num); | ||||
|  | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   geometry->width = stage_x11->xwin_width; | ||||
|   geometry->height = stage_x11->xwin_height; | ||||
| } | ||||
| @@ -263,10 +170,6 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window, | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   /* If we're going fullscreen, don't mess with the size */ | ||||
|   if (stage_x11->fullscreening) | ||||
|     return; | ||||
|  | ||||
|   if (width == 0 || height == 0) | ||||
|     { | ||||
|       /* Should not happen, if this turns up we need to debug it and | ||||
| @@ -460,117 +363,6 @@ _clutter_stage_x11_update_foreign_event_mask (CoglOnscreen *onscreen, | ||||
|                            &attrs); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window, | ||||
|                                   gboolean            is_fullscreen) | ||||
| { | ||||
|   ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); | ||||
|   ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11); | ||||
|   ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend); | ||||
|   ClutterStage *stage = stage_cogl->wrapper; | ||||
|   gboolean was_fullscreen; | ||||
|  | ||||
|   if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage)) | ||||
|     return; | ||||
|  | ||||
|   was_fullscreen = _clutter_stage_is_fullscreen (stage); | ||||
|   is_fullscreen = !!is_fullscreen; | ||||
|  | ||||
|   if (was_fullscreen == is_fullscreen) | ||||
|     return; | ||||
|  | ||||
|   CLUTTER_NOTE (BACKEND, "%ssetting fullscreen", is_fullscreen ? "" : "un"); | ||||
|  | ||||
|   if (is_fullscreen) | ||||
|     { | ||||
| #if 0 | ||||
|       int width, height; | ||||
|  | ||||
|       /* FIXME: this will do the wrong thing for dual-headed | ||||
|          displays. This will return the size of the combined display | ||||
|          but Metacity (at least) will fullscreen to only one of the | ||||
|          displays. This will cause the actor to report the wrong size | ||||
|          until the ConfigureNotify for the correct size is received */ | ||||
|       width  = DisplayWidth (backend_x11->xdpy, backend_x11->xscreen_num); | ||||
|       height = DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num); | ||||
| #endif | ||||
|  | ||||
|       /* Set the fullscreen hint so we can retain the old size of the window. */ | ||||
|       stage_x11->fullscreening = TRUE; | ||||
|  | ||||
|       if (stage_x11->xwin != None) | ||||
|         { | ||||
|           /* if the actor is not mapped we resize the stage window to match | ||||
|            * the size of the screen; this is useful for e.g. EGLX to avoid | ||||
|            * a resize when calling clutter_stage_fullscreen() before showing | ||||
|            * the stage | ||||
|            */ | ||||
|           if (!STAGE_X11_IS_MAPPED (stage_x11)) | ||||
|             { | ||||
|               CLUTTER_NOTE (BACKEND, "Fullscreening unmapped stage"); | ||||
|  | ||||
|               update_state (stage_x11, backend_x11, | ||||
|                             &backend_x11->atom_NET_WM_STATE_FULLSCREEN, | ||||
|                             TRUE); | ||||
|             } | ||||
|           else | ||||
|             { | ||||
|               CLUTTER_NOTE (BACKEND, "Fullscreening mapped stage"); | ||||
|  | ||||
|               /* We need to fix the window size so that it will remove | ||||
|                  the maximum and minimum window hints. Otherwise | ||||
|                  metacity will honour the restrictions and not | ||||
|                  fullscreen correctly. */ | ||||
|               clutter_stage_x11_fix_window_size (stage_x11, -1, -1); | ||||
|  | ||||
|               send_wmspec_change_state (backend_x11, stage_x11->xwin, | ||||
|                                         backend_x11->atom_NET_WM_STATE_FULLSCREEN, | ||||
|                                         TRUE); | ||||
|             } | ||||
|         } | ||||
|       else | ||||
|         stage_x11->fullscreen_on_realize = TRUE; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       stage_x11->fullscreening = FALSE; | ||||
|  | ||||
|       if (stage_x11->xwin != None) | ||||
|         { | ||||
|           if (!STAGE_X11_IS_MAPPED (stage_x11)) | ||||
|             { | ||||
|               CLUTTER_NOTE (BACKEND, "Un-fullscreening unmapped stage"); | ||||
|  | ||||
|               update_state (stage_x11, backend_x11, | ||||
|                             &backend_x11->atom_NET_WM_STATE_FULLSCREEN, | ||||
|                             FALSE); | ||||
|             } | ||||
|           else | ||||
|             { | ||||
|               CLUTTER_NOTE (BACKEND, "Un-fullscreening mapped stage"); | ||||
|  | ||||
|               send_wmspec_change_state (backend_x11, | ||||
|                                         stage_x11->xwin, | ||||
|                                         backend_x11->atom_NET_WM_STATE_FULLSCREEN, | ||||
|                                         FALSE); | ||||
|  | ||||
|               /* Fix the window size to restore the minimum/maximum | ||||
|                  restriction */ | ||||
|               clutter_stage_x11_fix_window_size (stage_x11, | ||||
|                                                  stage_x11->xwin_width, | ||||
|                                                  stage_x11->xwin_height); | ||||
|             } | ||||
|         } | ||||
|       else | ||||
|         stage_x11->fullscreen_on_realize = FALSE; | ||||
|     } | ||||
|  | ||||
|   /* XXX: Note we rely on the ConfigureNotify mechanism as the common | ||||
|    * mechanism to handle notifications of new X window sizes from the | ||||
|    * X server so we don't actively change the stage viewport here or | ||||
|    * queue a relayout etc. */ | ||||
| } | ||||
|  | ||||
| void | ||||
| _clutter_stage_x11_events_device_changed (ClutterStageX11 *stage_x11, | ||||
|                                           ClutterInputDevice *device, | ||||
| @@ -722,13 +514,6 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window) | ||||
|                                      stage_x11->xwin_height); | ||||
|   clutter_stage_x11_set_wm_protocols (stage_x11); | ||||
|  | ||||
|   if (stage_x11->fullscreen_on_realize) | ||||
|     { | ||||
|       stage_x11->fullscreen_on_realize = FALSE; | ||||
|  | ||||
|       clutter_stage_x11_set_fullscreen (stage_window, TRUE); | ||||
|     } | ||||
|  | ||||
|   CLUTTER_NOTE (BACKEND, "Successfully realized stage"); | ||||
|  | ||||
|   return TRUE; | ||||
| @@ -755,17 +540,6 @@ clutter_stage_x11_set_title (ClutterStageWindow *stage_window, | ||||
|   set_wm_title (stage_x11); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_stage_x11_set_user_resizable (ClutterStageWindow *stage_window, | ||||
|                                       gboolean            is_resizable) | ||||
| { | ||||
|   ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); | ||||
|  | ||||
|   clutter_stage_x11_fix_window_size (stage_x11, | ||||
|                                      stage_x11->xwin_width, | ||||
|                                      stage_x11->xwin_height); | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| update_wm_hints (ClutterStageX11 *stage_x11) | ||||
| { | ||||
| @@ -840,11 +614,6 @@ clutter_stage_x11_show (ClutterStageWindow *stage_window, | ||||
|           set_stage_x11_state (stage_x11, STAGE_X11_WITHDRAWN, 0); | ||||
|  | ||||
|           update_wm_hints (stage_x11); | ||||
|  | ||||
|           if (stage_x11->fullscreening) | ||||
|             clutter_stage_x11_set_fullscreen (stage_window, TRUE); | ||||
|           else | ||||
|             clutter_stage_x11_set_fullscreen (stage_window, FALSE); | ||||
|         } | ||||
|  | ||||
|       g_assert (STAGE_X11_IS_MAPPED (stage_x11)); | ||||
| @@ -966,7 +735,6 @@ clutter_stage_x11_init (ClutterStageX11 *stage) | ||||
|   stage->wm_state = STAGE_X11_WITHDRAWN; | ||||
|  | ||||
|   stage->is_foreign_xwin = FALSE; | ||||
|   stage->fullscreening = FALSE; | ||||
|   stage->is_cursor_visible = TRUE; | ||||
|   stage->accept_focus = TRUE; | ||||
|  | ||||
| @@ -979,9 +747,7 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface) | ||||
|   clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface); | ||||
|  | ||||
|   iface->set_title = clutter_stage_x11_set_title; | ||||
|   iface->set_fullscreen = clutter_stage_x11_set_fullscreen; | ||||
|   iface->set_cursor_visible = clutter_stage_x11_set_cursor_visible; | ||||
|   iface->set_user_resizable = clutter_stage_x11_set_user_resizable; | ||||
|   iface->set_accept_focus = clutter_stage_x11_set_accept_focus; | ||||
|   iface->show = clutter_stage_x11_show; | ||||
|   iface->hide = clutter_stage_x11_hide; | ||||
| @@ -1101,13 +867,8 @@ clutter_stage_x11_translate_event (ClutterEventTranslator *translator, | ||||
|                         xevent->xconfigure.width, | ||||
|                         xevent->xconfigure.height); | ||||
|  | ||||
|           /* When fullscreen, we'll keep the xwin_width/height | ||||
|              variables to track the old size of the window and we'll | ||||
|              assume all ConfigureNotifies constitute a size change */ | ||||
|           if (_clutter_stage_is_fullscreen (stage)) | ||||
|             size_changed = TRUE; | ||||
|           else if ((stage_x11->xwin_width != xevent->xconfigure.width) || | ||||
|                    (stage_x11->xwin_height != xevent->xconfigure.height)) | ||||
|           if ((stage_x11->xwin_width != xevent->xconfigure.width) || | ||||
|               (stage_x11->xwin_height != xevent->xconfigure.height)) | ||||
|             { | ||||
|               size_changed = TRUE; | ||||
|               stage_x11->xwin_width = xevent->xconfigure.width; | ||||
| @@ -1197,57 +958,6 @@ clutter_stage_x11_translate_event (ClutterEventTranslator *translator, | ||||
|         } | ||||
|       break; | ||||
|  | ||||
|     case PropertyNotify: | ||||
|       if (xevent->xproperty.atom == backend_x11->atom_NET_WM_STATE && | ||||
|           xevent->xproperty.window == stage_xwindow && | ||||
|           !stage_x11->is_foreign_xwin) | ||||
|         { | ||||
|           Atom     type; | ||||
|           gint     format; | ||||
|           gulong   n_items, bytes_after; | ||||
|           guchar  *data = NULL; | ||||
|           gboolean fullscreen_set = FALSE; | ||||
|  | ||||
|           clutter_x11_trap_x_errors (); | ||||
|           XGetWindowProperty (backend_x11->xdpy, stage_xwindow, | ||||
|                               backend_x11->atom_NET_WM_STATE, | ||||
|                               0, G_MAXLONG, | ||||
|                               False, XA_ATOM, | ||||
|                               &type, &format, &n_items, | ||||
|                               &bytes_after, &data); | ||||
|           clutter_x11_untrap_x_errors (); | ||||
|  | ||||
|           if (type != None && data != NULL) | ||||
|             { | ||||
|               gboolean is_fullscreen = FALSE; | ||||
|               Atom *atoms = (Atom *) data; | ||||
|               gulong i; | ||||
|  | ||||
|               for (i = 0; i < n_items; i++) | ||||
|                 { | ||||
|                   if (atoms[i] == backend_x11->atom_NET_WM_STATE_FULLSCREEN) | ||||
|                     fullscreen_set = TRUE; | ||||
|                 } | ||||
|  | ||||
|               is_fullscreen = _clutter_stage_is_fullscreen (stage_cogl->wrapper); | ||||
|  | ||||
|               if (fullscreen_set != is_fullscreen) | ||||
|                 { | ||||
|                   if (fullscreen_set) | ||||
|                     _clutter_stage_update_state (stage_cogl->wrapper, | ||||
|                                                  0, | ||||
|                                                  CLUTTER_STAGE_STATE_FULLSCREEN); | ||||
|                   else | ||||
|                     _clutter_stage_update_state (stage_cogl->wrapper, | ||||
|                                                  CLUTTER_STAGE_STATE_FULLSCREEN, | ||||
|                                                  0); | ||||
|                 } | ||||
|  | ||||
|               XFree (data); | ||||
|             } | ||||
|         } | ||||
|       break; | ||||
|  | ||||
|     case FocusIn: | ||||
|       if (!_clutter_stage_is_activated (stage_cogl->wrapper)) | ||||
|         { | ||||
|   | ||||
| @@ -70,11 +70,9 @@ struct _ClutterStageX11 | ||||
|   ClutterStageX11State wm_state; | ||||
|  | ||||
|   guint is_foreign_xwin       : 1; | ||||
|   guint fullscreening         : 1; | ||||
|   guint is_cursor_visible     : 1; | ||||
|   guint viewport_initialized  : 1; | ||||
|   guint accept_focus          : 1; | ||||
|   guint fullscreen_on_realize : 1; | ||||
| }; | ||||
|  | ||||
| struct _ClutterStageX11Class | ||||
|   | ||||
| @@ -12,19 +12,19 @@ clutter_c_args = [ | ||||
| ] | ||||
|  | ||||
| clutter_debug_c_args = [] | ||||
| if buildtype.startswith('debug') | ||||
|   clutter_debug_c_args += '-DG_DISABLE_CAST_CHECKS' | ||||
|   if buildtype == 'debug' | ||||
|     clutter_debug_c_args += '-DCLUTTER_ENABLE_DEBUG' | ||||
|   endif | ||||
| elif buildtype == 'release' | ||||
| if get_option('debug') | ||||
|   clutter_debug_c_args += [ | ||||
|     '-DCLUTTER_ENABLE_DEBUG', | ||||
|     '-fno-omit-frame-pointer' | ||||
|   ] | ||||
| elif buildtype != 'plain' | ||||
|   clutter_debug_c_args += [ | ||||
|     '-DG_DISABLE_ASSERT', | ||||
|     '-DG_DISABLE_CHECKS', | ||||
|     '-DG_DISABLE_CAST_CHECKS', | ||||
|   ] | ||||
| endif | ||||
|  | ||||
| supported_clutter_debug_c_args = cc.get_supported_arguments(clutter_debug_c_args) | ||||
| clutter_c_args += clutter_debug_c_args | ||||
|  | ||||
| clutter_pkg_deps = [ | ||||
|   | ||||
| @@ -209,14 +209,16 @@ make_actor (GType shader_type) | ||||
| } | ||||
|  | ||||
| static guint32 | ||||
| get_pixel (int x, int y) | ||||
| get_pixel (CoglFramebuffer *fb, | ||||
|            int              x, | ||||
|            int              y) | ||||
| { | ||||
|   guint8 data[4]; | ||||
|  | ||||
|   cogl_read_pixels (x, y, 1, 1, | ||||
|                     COGL_READ_PIXELS_COLOR_BUFFER, | ||||
|                     COGL_PIXEL_FORMAT_RGBA_8888_PRE, | ||||
|                     data); | ||||
|   cogl_framebuffer_read_pixels (fb, | ||||
|                                 x, y, 1, 1, | ||||
|                                 COGL_PIXEL_FORMAT_RGBA_8888_PRE, | ||||
|                                 data); | ||||
|  | ||||
|   return (((guint32) data[0] << 16) | | ||||
|           ((guint32) data[1] << 8) | | ||||
| @@ -224,19 +226,21 @@ get_pixel (int x, int y) | ||||
| } | ||||
|  | ||||
| static void | ||||
| paint_cb (ClutterStage *stage, | ||||
|           gpointer      data) | ||||
| view_painted_cb (ClutterStage     *stage, | ||||
|                  ClutterStageView *view, | ||||
|                  gpointer          data) | ||||
| { | ||||
|   CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (view); | ||||
|   gboolean *was_painted = data; | ||||
|  | ||||
|   /* old shader effect */ | ||||
|   g_assert_cmpint (get_pixel (0, 25), ==, 0xff0000); | ||||
|   g_assert_cmpint (get_pixel (fb, 0, 25), ==, 0xff0000); | ||||
|   /* new shader effect */ | ||||
|   g_assert_cmpint (get_pixel (100, 25), ==, 0x00ffff); | ||||
|   g_assert_cmpint (get_pixel (fb, 100, 25), ==, 0x00ffff); | ||||
|   /* another new shader effect */ | ||||
|   g_assert_cmpint (get_pixel (200, 25), ==, 0xff00ff); | ||||
|   g_assert_cmpint (get_pixel (fb, 200, 25), ==, 0xff00ff); | ||||
|   /* new shader effect */ | ||||
|   g_assert_cmpint (get_pixel (300, 25), ==, 0x00ffff); | ||||
|   g_assert_cmpint (get_pixel (fb, 300, 25), ==, 0x00ffff); | ||||
|  | ||||
|   *was_painted = TRUE; | ||||
| } | ||||
| @@ -271,9 +275,9 @@ actor_shader_effect (void) | ||||
|   clutter_actor_show (stage); | ||||
|  | ||||
|   was_painted = FALSE; | ||||
|   g_signal_connect (stage, "after-paint", | ||||
|                     G_CALLBACK (paint_cb), | ||||
|                     &was_painted); | ||||
|   g_signal_connect_after (stage, "paint-view", | ||||
|                           G_CALLBACK (view_painted_cb), | ||||
|                           &was_painted); | ||||
|  | ||||
|   while (!was_painted) | ||||
|     g_main_context_iteration (NULL, FALSE); | ||||
|   | ||||
| @@ -199,7 +199,6 @@ test_actors_main (int argc, char *argv[]) | ||||
|   g_signal_connect (oh->stage, "destroy", G_CALLBACK (stop_and_quit), oh); | ||||
|  | ||||
|   clutter_stage_set_title (CLUTTER_STAGE (oh->stage), "Actors"); | ||||
|   clutter_stage_set_user_resizable (CLUTTER_STAGE (oh->stage), TRUE); | ||||
|  | ||||
|   /* Create a timeline to manage animation */ | ||||
|   oh->timeline = clutter_timeline_new (6000); | ||||
|   | ||||
| @@ -181,7 +181,6 @@ test_bind_constraint_main (int argc, char *argv[]) | ||||
|   stage = clutter_stage_new (); | ||||
|   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); | ||||
|   clutter_stage_set_title (CLUTTER_STAGE (stage), "Constraints"); | ||||
|   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); | ||||
|   clutter_actor_set_size (stage, 800, 600); | ||||
|  | ||||
|   /* main rectangle */ | ||||
|   | ||||
| @@ -91,7 +91,6 @@ test_cairo_clock_main (int argc, char *argv[]) | ||||
|   /* create a resizable stage */ | ||||
|   stage = clutter_stage_new (); | ||||
|   clutter_stage_set_title (CLUTTER_STAGE (stage), "2D Clock"); | ||||
|   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); | ||||
|   clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue); | ||||
|   clutter_actor_set_size (stage, 300, 300); | ||||
|   clutter_actor_show (stage); | ||||
|   | ||||
| @@ -181,7 +181,6 @@ test_content_main (int argc, char *argv[]) | ||||
|   stage = clutter_stage_new (); | ||||
|   clutter_actor_set_name (stage, "Stage"); | ||||
|   clutter_stage_set_title (CLUTTER_STAGE (stage), "Content"); | ||||
|   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); | ||||
|   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); | ||||
|   clutter_actor_show (stage); | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| #include <clutter/clutter.h> | ||||
| #include <string.h> | ||||
|  | ||||
| gboolean IsFullScreen = FALSE, IsMotion = TRUE; | ||||
| gboolean IsMotion = TRUE; | ||||
|  | ||||
| int | ||||
| test_events_main (int argc, char *argv[]); | ||||
| @@ -114,28 +114,6 @@ stage_state_cb (ClutterStage    *stage, | ||||
|   printf("[stage signal] %s\n", detail); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| blue_button_cb (ClutterActor *actor, | ||||
| 		ClutterEvent *event, | ||||
| 		gpointer      data) | ||||
| { | ||||
|   ClutterActor *stage; | ||||
|  | ||||
|   stage = clutter_actor_get_stage (actor); | ||||
|  | ||||
|   if (IsFullScreen) | ||||
|     IsFullScreen = FALSE; | ||||
|   else | ||||
|     IsFullScreen = TRUE; | ||||
|  | ||||
|   clutter_stage_set_fullscreen (CLUTTER_STAGE (stage), IsFullScreen); | ||||
|  | ||||
|   g_print ("*** Fullscreen %s ***\n", | ||||
|            IsFullScreen ? "enabled" : "disabled"); | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| red_button_cb (ClutterActor *actor, | ||||
|                ClutterEvent *event, | ||||
| @@ -429,10 +407,6 @@ test_events_main (int argc, char *argv[]) | ||||
|   clutter_actor_set_name (stage, "Stage"); | ||||
|   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); | ||||
|   g_signal_connect (stage, "event", G_CALLBACK (input_cb), (char *) "stage"); | ||||
|   g_signal_connect (stage, "fullscreen",  | ||||
| 		    G_CALLBACK (stage_state_cb), (char *) "fullscreen"); | ||||
|   g_signal_connect (stage, "unfullscreen",  | ||||
| 		    G_CALLBACK (stage_state_cb), (char *) "unfullscreen"); | ||||
|   g_signal_connect (stage, "activate",  | ||||
| 		    G_CALLBACK (stage_state_cb), (char *) "activate"); | ||||
|   g_signal_connect (stage, "deactivate",  | ||||
| @@ -468,19 +442,6 @@ test_events_main (int argc, char *argv[]) | ||||
| 		    focus_box); | ||||
|   g_signal_connect (actor, "captured-event", G_CALLBACK (capture_cb), NULL); | ||||
|  | ||||
|   actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Blue); | ||||
|   clutter_actor_set_name (actor, "Blue Box"); | ||||
|   clutter_actor_set_size (actor, 100, 100); | ||||
|   clutter_actor_set_position (actor, 400, 100); | ||||
|   clutter_actor_set_reactive (actor, TRUE); | ||||
|   clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL); | ||||
|   g_signal_connect (actor, "event", G_CALLBACK (input_cb), (char *) "blue box"); | ||||
|   g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb), | ||||
| 		    focus_box); | ||||
|   /* Fullscreen */ | ||||
|   g_signal_connect (actor, "button-press-event", | ||||
|                     G_CALLBACK (blue_button_cb), NULL); | ||||
|  | ||||
|   /* non reactive */ | ||||
|   actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Black); | ||||
|   clutter_actor_set_name (actor, "Black Box"); | ||||
|   | ||||
| @@ -218,10 +218,6 @@ test_grab_main (int argc, char *argv[]) | ||||
|   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); | ||||
|   g_signal_connect (stage, "event", | ||||
|                     G_CALLBACK (debug_event_cb), (char *) "stage"); | ||||
|   g_signal_connect (stage, "fullscreen",  | ||||
| 		    G_CALLBACK (stage_state_cb), (char *) "fullscreen"); | ||||
|   g_signal_connect (stage, "unfullscreen",  | ||||
| 		    G_CALLBACK (stage_state_cb), (char *) "unfullscreen"); | ||||
|   g_signal_connect (stage, "activate",  | ||||
| 		    G_CALLBACK (stage_state_cb), (char *) "activate"); | ||||
|   g_signal_connect (stage, "deactivate",  | ||||
|   | ||||
| @@ -189,7 +189,6 @@ test_image_main (int argc, char *argv[]) | ||||
|   stage = clutter_stage_new (); | ||||
|   clutter_actor_set_name (stage, "Stage"); | ||||
|   clutter_stage_set_title (CLUTTER_STAGE (stage), "Content"); | ||||
|   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); | ||||
|   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); | ||||
|   clutter_actor_show (stage); | ||||
|  | ||||
|   | ||||
| @@ -73,7 +73,6 @@ test_rotate_zoom_main (int argc, char *argv[]) | ||||
|   stage = clutter_stage_new (); | ||||
|   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); | ||||
|   clutter_stage_set_title (CLUTTER_STAGE (stage), "Rotate and Zoom actions"); | ||||
|   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); | ||||
|   clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); | ||||
|   clutter_actor_set_reactive (stage, FALSE); | ||||
|   clutter_actor_show (stage); | ||||
|   | ||||
| @@ -8,21 +8,6 @@ test_stage_sizing_main (int argc, char *argv[]); | ||||
| const char * | ||||
| test_stage_sizing_describe (void); | ||||
|  | ||||
| static gboolean | ||||
| fullscreen_clicked_cb (ClutterStage *stage) | ||||
| { | ||||
|   clutter_stage_set_fullscreen (stage, !clutter_stage_get_fullscreen (stage)); | ||||
|   return CLUTTER_EVENT_STOP; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| resize_clicked_cb (ClutterStage *stage) | ||||
| { | ||||
|   clutter_stage_set_user_resizable (stage, | ||||
|                                     !clutter_stage_get_user_resizable (stage)); | ||||
|   return CLUTTER_EVENT_STOP; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| shrink_clicked_cb (ClutterActor *stage) | ||||
| { | ||||
| @@ -41,22 +26,6 @@ expand_clicked_cb (ClutterActor *stage) | ||||
|   return CLUTTER_EVENT_STOP; | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_fullscreen (ClutterStage *stage) | ||||
| { | ||||
|   float width, height; | ||||
|   gboolean is_fullscreen; | ||||
|  | ||||
|   is_fullscreen = clutter_stage_get_fullscreen (stage); | ||||
|  | ||||
|   clutter_actor_get_size (CLUTTER_ACTOR (stage), &width, &height); | ||||
|  | ||||
|   g_print ("Stage size [%s]: %d x %d\n", | ||||
|            is_fullscreen ? "fullscreen" : "not fullscreen", | ||||
|            (int) width, | ||||
|            (int) height); | ||||
| } | ||||
|  | ||||
| G_MODULE_EXPORT int | ||||
| test_stage_sizing_main (int argc, char *argv[]) | ||||
| { | ||||
| @@ -69,40 +38,12 @@ test_stage_sizing_main (int argc, char *argv[]) | ||||
|   stage = clutter_stage_new (); | ||||
|   clutter_stage_set_title (CLUTTER_STAGE (stage), "Stage Sizing"); | ||||
|   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); | ||||
|   g_signal_connect_after (stage, "notify::fullscreen-set", G_CALLBACK (on_fullscreen), NULL); | ||||
|  | ||||
|   box = clutter_actor_new (); | ||||
|   clutter_actor_set_layout_manager (box, clutter_box_layout_new ()); | ||||
|   clutter_actor_add_constraint (box, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5)); | ||||
|   clutter_actor_add_child (stage, box); | ||||
|  | ||||
|   rect = clutter_actor_new (); | ||||
|   clutter_actor_set_layout_manager (rect, | ||||
|                                     clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, | ||||
|                                                             CLUTTER_BIN_ALIGNMENT_CENTER)); | ||||
|   clutter_actor_set_background_color (rect, CLUTTER_COLOR_LightScarletRed); | ||||
|   clutter_actor_set_reactive (rect, TRUE); | ||||
|   g_signal_connect_swapped (rect, "button-press-event", | ||||
|                             G_CALLBACK (fullscreen_clicked_cb), | ||||
|                             stage); | ||||
|   label = clutter_text_new_with_text ("Sans 16", "Toggle fullscreen"); | ||||
|   clutter_actor_set_margin (label, &margin); | ||||
|   clutter_actor_add_child (rect, label); | ||||
|   clutter_actor_add_child (box, rect); | ||||
|  | ||||
|   rect = clutter_actor_new (); | ||||
|   clutter_actor_set_layout_manager (rect, | ||||
|                                     clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, | ||||
|                                                             CLUTTER_BIN_ALIGNMENT_CENTER)); | ||||
|   clutter_actor_set_background_color (rect, CLUTTER_COLOR_Chameleon); | ||||
|   clutter_actor_set_reactive (rect, TRUE); | ||||
|   g_signal_connect_swapped (rect, "button-press-event", | ||||
|                             G_CALLBACK (resize_clicked_cb), stage); | ||||
|   label = clutter_text_new_with_text ("Sans 16", "Toggle resizable"); | ||||
|   clutter_actor_set_margin (label, &margin); | ||||
|   clutter_actor_add_child (rect, label); | ||||
|   clutter_actor_add_child (box, rect); | ||||
|  | ||||
|   rect = clutter_actor_new (); | ||||
|   clutter_actor_set_layout_manager (rect, | ||||
|                                     clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER, | ||||
|   | ||||
| @@ -28,7 +28,6 @@ test_state_script_main (int argc, char *argv[]) | ||||
|  | ||||
|   stage = clutter_stage_new (); | ||||
|   clutter_stage_set_title (CLUTTER_STAGE (stage), "State Script"); | ||||
|   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); | ||||
|   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); | ||||
|   clutter_actor_show (stage); | ||||
|  | ||||
|   | ||||
| @@ -179,7 +179,6 @@ test_table_layout_main (int argc, char *argv[]) | ||||
|  | ||||
|   stage = clutter_stage_new (); | ||||
|   clutter_stage_set_title (CLUTTER_STAGE (stage), "Table Layout"); | ||||
|   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); | ||||
|   clutter_actor_set_size (stage, 640, 480); | ||||
|   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); | ||||
|  | ||||
|   | ||||
| @@ -146,7 +146,6 @@ test_touch_events_main (int argc, char *argv[]) | ||||
|   stage = clutter_stage_new (); | ||||
|   g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); | ||||
|   clutter_stage_set_title (CLUTTER_STAGE (stage), "Touch events"); | ||||
|   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); | ||||
|   clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); | ||||
|   clutter_actor_set_reactive (stage, TRUE); | ||||
|   clutter_actor_show (stage); | ||||
|   | ||||
| @@ -4,6 +4,9 @@ | ||||
| /* Have GLES 2.0 for rendering */ | ||||
| #mesondefine HAVE_COGL_GLES2 | ||||
|  | ||||
| /* Building with Sysprof profiling suport */ | ||||
| #mesondefine HAVE_TRACING | ||||
|  | ||||
| /* Enable unit tests */ | ||||
| #mesondefine ENABLE_UNIT_TESTS | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,7 @@ G_BEGIN_DECLS | ||||
| /*** END file-header ***/ | ||||
|  | ||||
| /*** BEGIN file-production ***/ | ||||
| /* enumerations from "@filename@" */ | ||||
| /* enumerations from "@basename@" */ | ||||
| /*** END file-production ***/ | ||||
|  | ||||
| /*** BEGIN file-tail ***/ | ||||
|   | ||||
| @@ -274,183 +274,6 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx, | ||||
| } | ||||
| #endif /* defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) */ | ||||
|  | ||||
| #ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT | ||||
| static void | ||||
| shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer, | ||||
|                                   CoglPixelFormat *format_out, | ||||
|                                   CoglTextureComponents *components_out) | ||||
| { | ||||
|   CoglPixelFormat format; | ||||
|   CoglTextureComponents components = COGL_TEXTURE_COMPONENTS_RGBA; | ||||
|  | ||||
|   switch (wl_shm_buffer_get_format (shm_buffer)) | ||||
|     { | ||||
| #if G_BYTE_ORDER == G_BIG_ENDIAN | ||||
|     case WL_SHM_FORMAT_ARGB8888: | ||||
|       format = COGL_PIXEL_FORMAT_ARGB_8888_PRE; | ||||
|       break; | ||||
|     case WL_SHM_FORMAT_XRGB8888: | ||||
|       format = COGL_PIXEL_FORMAT_ARGB_8888; | ||||
|       components = COGL_TEXTURE_COMPONENTS_RGB; | ||||
|       break; | ||||
| #elif G_BYTE_ORDER == G_LITTLE_ENDIAN | ||||
|     case WL_SHM_FORMAT_ARGB8888: | ||||
|       format = COGL_PIXEL_FORMAT_BGRA_8888_PRE; | ||||
|       break; | ||||
|     case WL_SHM_FORMAT_XRGB8888: | ||||
|       format = COGL_PIXEL_FORMAT_BGRA_8888; | ||||
|       components = COGL_TEXTURE_COMPONENTS_RGB; | ||||
|       break; | ||||
| #endif | ||||
|     default: | ||||
|       g_warn_if_reached (); | ||||
|       format = COGL_PIXEL_FORMAT_ARGB_8888; | ||||
|     } | ||||
|  | ||||
|   if (format_out) | ||||
|     *format_out = format; | ||||
|   if (components_out) | ||||
|     *components_out = components; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| cogl_wayland_texture_set_region_from_shm_buffer (CoglTexture *texture, | ||||
|                                                  int src_x, | ||||
|                                                  int src_y, | ||||
|                                                  int width, | ||||
|                                                  int height, | ||||
|                                                  struct wl_shm_buffer * | ||||
|                                                    shm_buffer, | ||||
|                                                  int dst_x, | ||||
|                                                  int dst_y, | ||||
|                                                  int level, | ||||
|                                                  CoglError **error) | ||||
| { | ||||
|   const uint8_t *data = wl_shm_buffer_get_data (shm_buffer); | ||||
|   int32_t stride = wl_shm_buffer_get_stride (shm_buffer); | ||||
|   CoglPixelFormat format; | ||||
|   int bpp; | ||||
|  | ||||
|   shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL); | ||||
|   bpp = _cogl_pixel_format_get_bytes_per_pixel (format); | ||||
|  | ||||
|   return _cogl_texture_set_region (COGL_TEXTURE (texture), | ||||
|                                    width, height, | ||||
|                                    format, | ||||
|                                    stride, | ||||
|                                    data + src_x * bpp + src_y * stride, | ||||
|                                    dst_x, dst_y, | ||||
|                                    level, | ||||
|                                    error); | ||||
| } | ||||
|  | ||||
| CoglTexture2D * | ||||
| cogl_wayland_texture_2d_new_from_buffer (CoglContext *ctx, | ||||
|                                          struct wl_resource *buffer, | ||||
|                                          CoglError **error) | ||||
| { | ||||
|   struct wl_shm_buffer *shm_buffer; | ||||
|   CoglTexture2D *tex = NULL; | ||||
|  | ||||
|   shm_buffer = wl_shm_buffer_get (buffer); | ||||
|  | ||||
|   if (shm_buffer) | ||||
|     { | ||||
|       int stride = wl_shm_buffer_get_stride (shm_buffer); | ||||
|       int width = wl_shm_buffer_get_width (shm_buffer); | ||||
|       int height = wl_shm_buffer_get_height (shm_buffer); | ||||
|       CoglPixelFormat format; | ||||
|       CoglTextureComponents components; | ||||
|       CoglBitmap *bmp; | ||||
|  | ||||
|       shm_buffer_get_cogl_pixel_format (shm_buffer, &format, &components); | ||||
|  | ||||
|       bmp = cogl_bitmap_new_for_data (ctx, | ||||
|                                       width, height, | ||||
|                                       format, | ||||
|                                       stride, | ||||
|                                       wl_shm_buffer_get_data (shm_buffer)); | ||||
|  | ||||
|       tex = cogl_texture_2d_new_from_bitmap (bmp); | ||||
|  | ||||
|       cogl_texture_set_components (COGL_TEXTURE (tex), components); | ||||
|  | ||||
|       cogl_object_unref (bmp); | ||||
|  | ||||
|       if (!cogl_texture_allocate (COGL_TEXTURE (tex), error)) | ||||
|         { | ||||
|           cogl_object_unref (tex); | ||||
|           return NULL; | ||||
|         } | ||||
|       else | ||||
|         return tex; | ||||
|     } | ||||
| #ifdef COGL_HAS_EGL_SUPPORT | ||||
|   else | ||||
|     { | ||||
|       int format, width, height; | ||||
|  | ||||
|       if (_cogl_egl_query_wayland_buffer (ctx, | ||||
|                                           buffer, | ||||
|                                           EGL_TEXTURE_FORMAT, | ||||
|                                           &format) && | ||||
|           _cogl_egl_query_wayland_buffer (ctx, | ||||
|                                           buffer, | ||||
|                                           EGL_WIDTH, | ||||
|                                           &width) && | ||||
|           _cogl_egl_query_wayland_buffer (ctx, | ||||
|                                           buffer, | ||||
|                                           EGL_HEIGHT, | ||||
|                                           &height)) | ||||
|         { | ||||
|           EGLImageKHR image; | ||||
|           CoglPixelFormat internal_format; | ||||
|  | ||||
|           _COGL_RETURN_VAL_IF_FAIL (_cogl_context_get_winsys (ctx)->constraints & | ||||
|                                     COGL_RENDERER_CONSTRAINT_USES_EGL, | ||||
|                                     NULL); | ||||
|  | ||||
|           switch (format) | ||||
|             { | ||||
|             case EGL_TEXTURE_RGB: | ||||
|               internal_format = COGL_PIXEL_FORMAT_RGB_888; | ||||
|               break; | ||||
|             case EGL_TEXTURE_RGBA: | ||||
|               internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; | ||||
|               break; | ||||
|             default: | ||||
|               _cogl_set_error (error, | ||||
|                                COGL_SYSTEM_ERROR, | ||||
|                                COGL_SYSTEM_ERROR_UNSUPPORTED, | ||||
|                                "Can't create texture from unknown " | ||||
|                                "wayland buffer format %d\n", format); | ||||
|               return NULL; | ||||
|             } | ||||
|  | ||||
|           image = _cogl_egl_create_image (ctx, | ||||
|                                           EGL_WAYLAND_BUFFER_WL, | ||||
|                                           buffer, | ||||
|                                           NULL); | ||||
|           tex = cogl_egl_texture_2d_new_from_image (ctx, | ||||
|                                                     width, height, | ||||
|                                                     internal_format, | ||||
|                                                     image, | ||||
|                                                     error); | ||||
|           _cogl_egl_destroy_image (ctx, image); | ||||
|           return tex; | ||||
|         } | ||||
|     } | ||||
| #endif /* COGL_HAS_EGL_SUPPORT */ | ||||
|  | ||||
|   _cogl_set_error (error, | ||||
|                    COGL_SYSTEM_ERROR, | ||||
|                    COGL_SYSTEM_ERROR_UNSUPPORTED, | ||||
|                    "Can't create texture from unknown " | ||||
|                    "wayland buffer type\n"); | ||||
|   return NULL; | ||||
| } | ||||
| #endif /* COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT */ | ||||
|  | ||||
| void | ||||
| _cogl_texture_2d_externally_modified (CoglTexture *texture) | ||||
| { | ||||
|   | ||||
							
								
								
									
										258
									
								
								cogl/cogl/cogl-trace.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								cogl/cogl/cogl-trace.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,258 @@ | ||||
| /* | ||||
|  * Copyright 2018 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, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "cogl-config.h" | ||||
|  | ||||
| #ifdef HAVE_TRACING | ||||
|  | ||||
| #include "cogl/cogl-trace.h" | ||||
|  | ||||
| #include <sysprof-capture.h> | ||||
| #include <syscall.h> | ||||
| #include <sys/types.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #define COGL_TRACE_OUTPUT_FILE "cogl-trace-sp-capture.syscap" | ||||
| #define BUFFER_LENGTH (4096 * 4) | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   int   fd; | ||||
|   char *filename; | ||||
|   char *group; | ||||
| } TraceData; | ||||
|  | ||||
| static void | ||||
| trace_data_free (gpointer user_data) | ||||
| { | ||||
|   TraceData *data = user_data; | ||||
|  | ||||
|   data->fd = -1; | ||||
|   g_clear_pointer (&data->group, g_free); | ||||
|   g_clear_pointer (&data->filename, g_free); | ||||
|   g_free (data); | ||||
| } | ||||
|  | ||||
| static void cogl_trace_thread_context_free (gpointer data); | ||||
|  | ||||
| GPrivate cogl_trace_thread_data = G_PRIVATE_INIT (cogl_trace_thread_context_free); | ||||
| CoglTraceContext *cogl_trace_context; | ||||
| GMutex cogl_trace_mutex; | ||||
|  | ||||
| static CoglTraceContext * | ||||
| cogl_trace_context_new (int         fd, | ||||
|                         const char *filename) | ||||
| { | ||||
|   CoglTraceContext *context; | ||||
|   SysprofCaptureWriter *writer; | ||||
|  | ||||
|   if (fd != -1) | ||||
|     { | ||||
|       g_debug ("Initializing trace context with fd=%d", fd); | ||||
|       writer = sysprof_capture_writer_new_from_fd (fd, BUFFER_LENGTH); | ||||
|     } | ||||
|   else if (filename != NULL) | ||||
|     { | ||||
|       g_debug ("Initializing trace context with filename='%s'", filename); | ||||
|       writer = sysprof_capture_writer_new (filename, BUFFER_LENGTH); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       g_debug ("Initializing trace context with default filename"); | ||||
|       writer = sysprof_capture_writer_new (COGL_TRACE_OUTPUT_FILE, BUFFER_LENGTH); | ||||
|     } | ||||
|  | ||||
|   context = g_new0 (CoglTraceContext, 1); | ||||
|   context->writer = writer; | ||||
|   return context; | ||||
| } | ||||
|  | ||||
| static void | ||||
| cogl_trace_context_free (CoglTraceContext *trace_context) | ||||
| { | ||||
|   g_clear_pointer (&trace_context->writer, sysprof_capture_writer_unref); | ||||
|   g_free (trace_context); | ||||
| } | ||||
|  | ||||
| static void | ||||
| ensure_trace_context (TraceData *data) | ||||
| { | ||||
|   g_mutex_lock (&cogl_trace_mutex); | ||||
|   if (!cogl_trace_context) | ||||
|     cogl_trace_context = cogl_trace_context_new (data->fd, data->filename); | ||||
|   g_mutex_unlock (&cogl_trace_mutex); | ||||
| } | ||||
|  | ||||
| static CoglTraceThreadContext * | ||||
| cogl_trace_thread_context_new (const char *group) | ||||
| { | ||||
|   CoglTraceThreadContext *thread_context; | ||||
|   pid_t tid; | ||||
|  | ||||
|   tid = (pid_t) syscall (SYS_gettid); | ||||
|  | ||||
|   thread_context = g_new0 (CoglTraceThreadContext, 1); | ||||
|   thread_context->cpu_id = -1; | ||||
|   thread_context->pid = getpid (); | ||||
|   thread_context->group = | ||||
|     group ? g_strdup (group) : g_strdup_printf ("t:%d", tid); | ||||
|  | ||||
|   return thread_context; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| enable_tracing_idle_callback (gpointer user_data) | ||||
| { | ||||
|   CoglTraceThreadContext *thread_context = | ||||
|     g_private_get (&cogl_trace_thread_data); | ||||
|   TraceData *data = user_data; | ||||
|  | ||||
|   ensure_trace_context (data); | ||||
|  | ||||
|   if (thread_context) | ||||
|     { | ||||
|       g_warning ("Tracing already enabled"); | ||||
|       return G_SOURCE_REMOVE; | ||||
|     } | ||||
|  | ||||
|   thread_context = cogl_trace_thread_context_new (data->group); | ||||
|   g_private_set (&cogl_trace_thread_data, thread_context); | ||||
|  | ||||
|   return G_SOURCE_REMOVE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| cogl_trace_thread_context_free (gpointer data) | ||||
| { | ||||
|   CoglTraceThreadContext *thread_context = data; | ||||
|  | ||||
|   if (!thread_context) | ||||
|     return; | ||||
|  | ||||
|   g_free (thread_context->group); | ||||
|   g_free (thread_context); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| disable_tracing_idle_callback (gpointer user_data) | ||||
| { | ||||
|   CoglTraceThreadContext *thread_context = | ||||
|     g_private_get (&cogl_trace_thread_data); | ||||
|   CoglTraceContext *trace_context; | ||||
|  | ||||
|   if (!thread_context) | ||||
|     { | ||||
|       g_warning ("Tracing not enabled"); | ||||
|       return G_SOURCE_REMOVE; | ||||
|     } | ||||
|  | ||||
|   g_private_replace (&cogl_trace_thread_data, NULL); | ||||
|  | ||||
|   g_mutex_lock (&cogl_trace_mutex); | ||||
|   trace_context = cogl_trace_context; | ||||
|   sysprof_capture_writer_flush (trace_context->writer); | ||||
|  | ||||
|   g_clear_pointer (&cogl_trace_context, cogl_trace_context_free); | ||||
|  | ||||
|   g_mutex_unlock (&cogl_trace_mutex); | ||||
|  | ||||
|   return G_SOURCE_REMOVE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_tracing_enabled_on_thread (GMainContext *main_context, | ||||
|                                const char   *group, | ||||
|                                int           fd, | ||||
|                                const char   *filename) | ||||
| { | ||||
|   TraceData *data; | ||||
|   GSource *source; | ||||
|  | ||||
|   data = g_new0 (TraceData, 1); | ||||
|   data->fd = fd; | ||||
|   data->group = group ? strdup (group) : NULL; | ||||
|   data->filename = filename ? strdup (filename) : NULL; | ||||
|  | ||||
|   source = g_idle_source_new (); | ||||
|  | ||||
|   g_source_set_callback (source, | ||||
|                          enable_tracing_idle_callback, | ||||
|                          data, | ||||
|                          trace_data_free); | ||||
|  | ||||
|   g_source_attach (source, main_context); | ||||
|   g_source_unref (source); | ||||
| } | ||||
|  | ||||
| void | ||||
| cogl_set_tracing_enabled_on_thread_with_fd (GMainContext *main_context, | ||||
|                                             const char   *group, | ||||
|                                             int           fd) | ||||
| { | ||||
|   set_tracing_enabled_on_thread (main_context, group, fd, NULL); | ||||
| } | ||||
|  | ||||
| void | ||||
| cogl_set_tracing_enabled_on_thread (GMainContext *main_context, | ||||
|                                     const char   *group, | ||||
|                                     const char   *filename) | ||||
| { | ||||
|   set_tracing_enabled_on_thread (main_context, group, -1, filename); | ||||
| } | ||||
|  | ||||
| void | ||||
| cogl_set_tracing_disabled_on_thread (GMainContext *main_context) | ||||
| { | ||||
|   GSource *source; | ||||
|  | ||||
|   source = g_idle_source_new (); | ||||
|  | ||||
|   g_source_set_callback (source, disable_tracing_idle_callback, NULL, NULL); | ||||
|  | ||||
|   g_source_attach (source, main_context); | ||||
|   g_source_unref (source); | ||||
| } | ||||
|  | ||||
| #else | ||||
|  | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| void | ||||
| cogl_set_tracing_enabled_on_thread_with_fd (void       *data, | ||||
|                                             const char *group, | ||||
|                                             int         fd) | ||||
| { | ||||
|   fprintf (stderr, "Tracing not enabled"); | ||||
| } | ||||
|  | ||||
| void | ||||
| cogl_set_tracing_enabled_on_thread (void       *data, | ||||
|                                     const char *group, | ||||
|                                     const char *filename) | ||||
| { | ||||
|   fprintf (stderr, "Tracing not enabled"); | ||||
| } | ||||
|  | ||||
| void | ||||
| cogl_set_tracing_disabled_on_thread (void *data) | ||||
| { | ||||
|   fprintf (stderr, "Tracing not enabled"); | ||||
| } | ||||
|  | ||||
| #endif /* HAVE_TRACING */ | ||||
							
								
								
									
										147
									
								
								cogl/cogl/cogl-trace.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								cogl/cogl/cogl-trace.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | ||||
| /* | ||||
|  * Copyright 2018 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, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef COGL_TRACE_H | ||||
| #define COGL_TRACE_H | ||||
|  | ||||
| #include "cogl-config.h" | ||||
|  | ||||
| #ifdef HAVE_TRACING | ||||
|  | ||||
| #include <glib.h> | ||||
| #include <sysprof-capture-writer.h> | ||||
| #include <sysprof-clock.h> | ||||
| #include <stdint.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| typedef struct _CoglTraceContext | ||||
| { | ||||
|   SysprofCaptureWriter *writer; | ||||
| } CoglTraceContext; | ||||
|  | ||||
| typedef struct _CoglTraceThreadContext | ||||
| { | ||||
|   int cpu_id; | ||||
|   GPid pid; | ||||
|   char *group; | ||||
| } CoglTraceThreadContext; | ||||
|  | ||||
| typedef struct _CoglTraceHead | ||||
| { | ||||
|   SysprofTimeStamp begin_time; | ||||
|   const char *name; | ||||
| } CoglTraceHead; | ||||
|  | ||||
| extern GPrivate cogl_trace_thread_data; | ||||
| extern CoglTraceContext *cogl_trace_context; | ||||
| extern GMutex cogl_trace_mutex; | ||||
|  | ||||
| void cogl_set_tracing_enabled_on_thread_with_fd (GMainContext *main_context, | ||||
|                                                  const char   *group, | ||||
|                                                  int           fd); | ||||
|  | ||||
| void cogl_set_tracing_enabled_on_thread (GMainContext *main_context, | ||||
|                                          const char   *group, | ||||
|                                          const char   *filename); | ||||
|  | ||||
| void cogl_set_tracing_disabled_on_thread (GMainContext *main_context); | ||||
|  | ||||
| static inline void | ||||
| cogl_trace_begin (CoglTraceHead *head, | ||||
|                   const char    *name) | ||||
| { | ||||
|   head->begin_time = g_get_monotonic_time () * 1000; | ||||
|   head->name = name; | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| cogl_trace_end (CoglTraceHead *head) | ||||
| { | ||||
|   SysprofTimeStamp end_time; | ||||
|   CoglTraceContext *trace_context; | ||||
|   CoglTraceThreadContext *trace_thread_context; | ||||
|  | ||||
|   end_time = g_get_monotonic_time () * 1000; | ||||
|   trace_context = cogl_trace_context; | ||||
|   trace_thread_context = g_private_get (&cogl_trace_thread_data); | ||||
|  | ||||
|   g_mutex_lock (&cogl_trace_mutex); | ||||
|   if (!sysprof_capture_writer_add_mark (trace_context->writer, | ||||
|                                         head->begin_time, | ||||
|                                         trace_thread_context->cpu_id, | ||||
|                                         trace_thread_context->pid, | ||||
|                                         (uint64_t) end_time - head->begin_time, | ||||
|                                         trace_thread_context->group, | ||||
|                                         head->name, | ||||
|                                         NULL)) | ||||
|     { | ||||
|       /* XXX: g_main_context_get_thread_default() might be wrong, it probably | ||||
|        * needs to store the GMainContext in CoglTraceThreadContext when creating | ||||
|        * and use it here. | ||||
|        */ | ||||
|       if (errno == EPIPE) | ||||
|         cogl_set_tracing_disabled_on_thread (g_main_context_get_thread_default ()); | ||||
|     } | ||||
|   g_mutex_unlock (&cogl_trace_mutex); | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| cogl_auto_trace_end_helper (CoglTraceHead **head) | ||||
| { | ||||
|   if (*head) | ||||
|     cogl_trace_end (*head); | ||||
| } | ||||
|  | ||||
| #define COGL_TRACE_BEGIN(Name, description) \ | ||||
|   CoglTraceHead CoglTrace##Name = { 0 }; \ | ||||
|   if (g_private_get (&cogl_trace_thread_data)) \ | ||||
|     cogl_trace_begin (&CoglTrace##Name, description); \ | ||||
|  | ||||
| #define COGL_TRACE_END(Name)\ | ||||
|   if (g_private_get (&cogl_trace_thread_data)) \ | ||||
|     cogl_trace_end (&CoglTrace##Name); | ||||
|  | ||||
| #define COGL_TRACE_BEGIN_SCOPED(Name, description) \ | ||||
|   CoglTraceHead CoglTrace##Name = { 0 }; \ | ||||
|   __attribute__((cleanup (cogl_auto_trace_end_helper))) \ | ||||
|     CoglTraceHead *ScopedCoglTrace##Name = NULL; \ | ||||
|   if (g_private_get (&cogl_trace_thread_data)) \ | ||||
|     { \ | ||||
|       cogl_trace_begin (&CoglTrace##Name, description); \ | ||||
|       ScopedCoglTrace##Name = &CoglTrace##Name; \ | ||||
|     } | ||||
|  | ||||
| #else /* HAVE_TRACING */ | ||||
|  | ||||
| #include <stdio.h> | ||||
|  | ||||
| #define COGL_TRACE_BEGIN(Name, description) (void) 0 | ||||
| #define COGL_TRACE_END(Name) (void) 0 | ||||
| #define COGL_TRACE_BEGIN_SCOPED(Name, description) (void) 0 | ||||
|  | ||||
| void cogl_set_tracing_enabled_on_thread_with_fd (void       *data, | ||||
|                                                  const char *group, | ||||
|                                                  int         fd); | ||||
| void cogl_set_tracing_enabled_on_thread (void       *data, | ||||
|                                          const char *group, | ||||
|                                          const char *filename); | ||||
| void cogl_set_tracing_disabled_on_thread (void *data); | ||||
|  | ||||
| #endif /* HAVE_TRACING */ | ||||
|  | ||||
| #endif /* COGL_TRACE_H */ | ||||
| @@ -70,81 +70,6 @@ void | ||||
| cogl_wayland_display_set_compositor_display (CoglDisplay *display, | ||||
|                                           struct wl_display *wayland_display); | ||||
|  | ||||
| /** | ||||
|  * cogl_wayland_texture_2d_new_from_buffer: | ||||
|  * @ctx: A #CoglContext | ||||
|  * @buffer: A Wayland resource for a buffer | ||||
|  * @error: A #CoglError for exceptions | ||||
|  * | ||||
|  * Uploads the @buffer referenced by the given Wayland resource to a | ||||
|  * #CoglTexture2D. The buffer resource may refer to a wl_buffer or a | ||||
|  * wl_shm_buffer. | ||||
|  * | ||||
|  * <note>The results are undefined for passing an invalid @buffer | ||||
|  * pointer</note> | ||||
|  * <note>It is undefined if future updates to @buffer outside the | ||||
|  * control of Cogl will affect the allocated #CoglTexture2D. In some | ||||
|  * cases the contents of the buffer are copied (such as shm buffers), | ||||
|  * and in other cases the underlying storage is re-used directly (such | ||||
|  * as drm buffers)</note> | ||||
|  * | ||||
|  * Returns: A newly allocated #CoglTexture2D, or if Cogl could not | ||||
|  *          validate the @buffer in some way (perhaps because of | ||||
|  *          an unsupported format) it will return %NULL and set | ||||
|  *          @error. | ||||
|  * | ||||
|  * Since: 1.10 | ||||
|  * Stability: unstable | ||||
|  */ | ||||
| CoglTexture2D * | ||||
| cogl_wayland_texture_2d_new_from_buffer (CoglContext *ctx, | ||||
|                                          struct wl_resource *buffer, | ||||
|                                          CoglError **error); | ||||
|  | ||||
| /** | ||||
|  * cogl_wayland_texture_set_region_from_shm_buffer: | ||||
|  * @texture: a #CoglTexture | ||||
|  * @width: The width of the region to copy | ||||
|  * @height: The height of the region to copy | ||||
|  * @shm_buffer: The source buffer | ||||
|  * @src_x: The X offset within the source bufer to copy from | ||||
|  * @src_y: The Y offset within the source bufer to copy from | ||||
|  * @dst_x: The X offset within the texture to copy to | ||||
|  * @dst_y: The Y offset within the texture to copy to | ||||
|  * @level: The mipmap level of the texture to copy to | ||||
|  * @error: A #CoglError to return exceptional errors | ||||
|  * | ||||
|  * Sets the pixels in a rectangular subregion of @texture from a | ||||
|  * Wayland SHM buffer. Generally this would be used in response to | ||||
|  * wl_surface.damage event in a compositor in order to update the | ||||
|  * texture with the damaged region. This is just a convenience wrapper | ||||
|  * around getting the SHM buffer pointer and calling | ||||
|  * cogl_texture_set_region(). See that function for a description of | ||||
|  * the level parameter. | ||||
|  * | ||||
|  * <note>Since the storage for a #CoglTexture is allocated lazily then | ||||
|  * if the given @texture has not previously been allocated then this | ||||
|  * api can return %FALSE and throw an exceptional @error if there is | ||||
|  * not enough memory to allocate storage for @texture.</note> | ||||
|  * | ||||
|  * Return value: %TRUE if the subregion upload was successful, and | ||||
|  *   %FALSE otherwise | ||||
|  * Since: 1.18 | ||||
|  * Stability: unstable | ||||
|  */ | ||||
| gboolean | ||||
| cogl_wayland_texture_set_region_from_shm_buffer (CoglTexture *texture, | ||||
|                                                  int src_x, | ||||
|                                                  int src_y, | ||||
|                                                  int width, | ||||
|                                                  int height, | ||||
|                                                  struct wl_shm_buffer * | ||||
|                                                    shm_buffer, | ||||
|                                                  int dst_x, | ||||
|                                                  int dst_y, | ||||
|                                                  int level, | ||||
|                                                  CoglError **error); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| /* The gobject introspection scanner seems to parse public headers in | ||||
|   | ||||
| @@ -1006,8 +1006,6 @@ cogl_wayland_onscreen_resize | ||||
| cogl_wayland_renderer_get_display | ||||
| cogl_wayland_renderer_set_event_dispatch_enabled | ||||
| cogl_wayland_renderer_set_foreign_display | ||||
| cogl_wayland_texture_set_region_from_shm_buffer | ||||
| cogl_wayland_texture_2d_new_from_buffer | ||||
| #endif | ||||
|  | ||||
| cogl_winding_get_type | ||||
|   | ||||
| @@ -303,6 +303,8 @@ cogl_sources = [ | ||||
|   'cogl-blend-string.c', | ||||
|   'cogl-blend-string.h', | ||||
|   'cogl-debug.c', | ||||
|   'cogl-trace.c', | ||||
|   'cogl-trace.h', | ||||
|   'cogl-sub-texture-private.h', | ||||
|   'cogl-texture-private.h', | ||||
|   'cogl-texture-2d-private.h', | ||||
|   | ||||
| @@ -7,6 +7,7 @@ cogl_includepath = include_directories('.', 'cogl') | ||||
| cdata = configuration_data() | ||||
| cdata.set('HAVE_COGL_GL', have_gl) | ||||
| cdata.set('HAVE_COGL_GLES2', have_gles2) | ||||
| cdata.set('HAVE_TRACING', have_profiler) | ||||
| cdata.set('ENABLE_UNIT_TESTS', have_cogl_tests) | ||||
|  | ||||
| cogl_config_h = configure_file( | ||||
| @@ -26,6 +27,12 @@ cogl_pkg_private_deps = [ | ||||
|   #uprof_dep, | ||||
| ] | ||||
|  | ||||
| if have_profiler | ||||
|   cogl_pkg_private_deps += [ | ||||
|     sysprof_dep, | ||||
|   ] | ||||
| endif | ||||
|  | ||||
| if have_wayland | ||||
|   cogl_pkg_deps += [ | ||||
|     wayland_server_dep, | ||||
| @@ -87,19 +94,21 @@ if have_gles2 | ||||
| endif | ||||
|  | ||||
| cogl_debug_c_args = [] | ||||
| if buildtype.startswith('debug') | ||||
| buildtype = get_option('buildtype') | ||||
| if get_option('debug') | ||||
|   cogl_debug_c_args += [ | ||||
|     '-DCOGL_GL_DEBUG', | ||||
|     '-DCOGL_OBJECT_DEBUG', | ||||
|     '-DCOGL_ENABLE_DEBUG', | ||||
|     '-fno-omit-frame-pointer' | ||||
|   ] | ||||
| elif buildtype == 'release' | ||||
| elif buildtype != 'plain' | ||||
|   cogl_debug_c_args += [ | ||||
|     '-DG_DISABLE_CHECKS', | ||||
|     '-DG_DISABLE_CAST_CHECKS', | ||||
|     '-DG_DISABLE_CAST_CHECKS' | ||||
|   ] | ||||
| endif | ||||
|  | ||||
| supported_cogl_debug_c_args = cc.get_supported_arguments(cogl_debug_c_args) | ||||
| cogl_c_args += cogl_debug_c_args | ||||
|  | ||||
| if have_cogl_tests | ||||
|   | ||||
| @@ -49,6 +49,9 @@ | ||||
| /* Building with startup notification support */ | ||||
| #mesondefine HAVE_STARTUP_NOTIFICATION | ||||
|  | ||||
| /* Building with Sysprof profiling suport */ | ||||
| #mesondefine HAVE_PROFILER | ||||
|  | ||||
| /* Path to Xwayland executable */ | ||||
| #mesondefine XWAYLAND_PATH | ||||
|  | ||||
|   | ||||
| @@ -127,6 +127,14 @@ | ||||
|       </description> | ||||
|     </key> | ||||
|  | ||||
|     <key name="locate-pointer-key" type="s"> | ||||
|       <default>'Control_L'</default> | ||||
|       <summary>Modifier to use to locate the pointer</summary> | ||||
|       <description> | ||||
|         This key will initiate the “locate pointer” action. | ||||
|       </description> | ||||
|     </key> | ||||
|  | ||||
|     <child name="keybindings" schema="org.gnome.mutter.keybindings"/> | ||||
|  | ||||
|   </schema> | ||||
|   | ||||
| @@ -61,10 +61,17 @@ | ||||
|  | ||||
|     <key name="xwayland-allow-grabs" type="b"> | ||||
|       <default>false</default> | ||||
|       <summary>Allow grabs with Xwayland</summary> | ||||
|       <summary>Allow X11 grabs to lock keyboard focus with Xwayland</summary> | ||||
|       <description> | ||||
|         Allow keyboard grabs issued by X11 applications running in Xwayland | ||||
|         to be taken into account. | ||||
|         Allow all keyboard events to be routed to X11 “override redirect” | ||||
|         windows with a grab when running in Xwayland. | ||||
|  | ||||
|         This option is to support X11 clients which map an “override redirect” | ||||
|         window (which do not receive keyboard focus) and issue a keyboard | ||||
|         grab to force all keyboard events to that window. | ||||
|  | ||||
|         This option is seldom used and has no effect on regular X11 windows | ||||
|         which can receive keyboard focus under normal circumstances. | ||||
|  | ||||
|         For a X11 grab to be taken into account under Wayland, the client must | ||||
|         also either send a specific X11 ClientMessage to the root window or be | ||||
|   | ||||
							
								
								
									
										102
									
								
								meson.build
									
									
									
									
									
								
							
							
						
						
									
										102
									
								
								meson.build
									
									
									
									
									
								
							| @@ -264,6 +264,11 @@ if have_tests | ||||
|   have_installed_tests = get_option('installed_tests') | ||||
| endif | ||||
|  | ||||
| have_profiler = get_option('profiler') | ||||
| if have_profiler | ||||
|   sysprof_dep = dependency('sysprof-capture-3') | ||||
| endif | ||||
|  | ||||
| required_functions = [ | ||||
|   'ffs', | ||||
|   'clz', | ||||
| @@ -276,54 +281,57 @@ endforeach | ||||
|  | ||||
| add_project_arguments('-D_GNU_SOURCE', language: 'c') | ||||
|  | ||||
| all_warnings = [ | ||||
|   '-fno-strict-aliasing', | ||||
|   '-Wpointer-arith', | ||||
|   '-Wmissing-declarations', | ||||
|   '-Wimplicit-function-declaration', | ||||
|   '-Wformat=2', | ||||
|   '-Wformat-nonliteral', | ||||
|   '-Wformat-security', | ||||
|   '-Wstrict-prototypes', | ||||
|   '-Wmissing-prototypes', | ||||
|   '-Wnested-externs', | ||||
|   '-Wold-style-definition', | ||||
|   '-Wundef', | ||||
|   '-Wunused', | ||||
|   '-Wcast-align', | ||||
|   '-Wmissing-noreturn', | ||||
|   '-Wmissing-format-attribute', | ||||
|   '-Wmissing-include-dirs', | ||||
|   '-Wlogical-op', | ||||
|   '-Wignored-qualifiers', | ||||
|   '-Werror=redundant-decls', | ||||
|   '-Werror=implicit', | ||||
|   '-Werror=nonnull', | ||||
|   '-Werror=init-self', | ||||
|   '-Werror=main', | ||||
|   '-Werror=missing-braces', | ||||
|   '-Werror=sequence-point', | ||||
|   '-Werror=return-type', | ||||
|   '-Werror=trigraphs', | ||||
|   '-Werror=array-bounds', | ||||
|   '-Werror=write-strings', | ||||
|   '-Werror=address', | ||||
|   '-Werror=int-to-pointer-cast', | ||||
|   '-Werror=pointer-to-int-cast', | ||||
|   '-Werror=empty-body', | ||||
|   '-Werror=write-strings', | ||||
| ] | ||||
|  | ||||
| supported_warnings = cc.get_supported_arguments(all_warnings) | ||||
|  | ||||
| add_project_arguments(supported_warnings, language: 'c') | ||||
|  | ||||
| debug_c_args = [] | ||||
| buildtype = get_option('buildtype') | ||||
| if buildtype.startswith('debug') | ||||
|   debug_c_args += '-DG_ENABLE_DEBUG' | ||||
| if buildtype != 'plain' | ||||
|   all_warnings = [ | ||||
|     '-fno-strict-aliasing', | ||||
|     '-Wpointer-arith', | ||||
|     '-Wmissing-declarations', | ||||
|     '-Wimplicit-function-declaration', | ||||
|     '-Wformat=2', | ||||
|     '-Wformat-nonliteral', | ||||
|     '-Wformat-security', | ||||
|     '-Wstrict-prototypes', | ||||
|     '-Wmissing-prototypes', | ||||
|     '-Wnested-externs', | ||||
|     '-Wold-style-definition', | ||||
|     '-Wundef', | ||||
|     '-Wunused', | ||||
|     '-Wcast-align', | ||||
|     '-Wmissing-noreturn', | ||||
|     '-Wmissing-format-attribute', | ||||
|     '-Wmissing-include-dirs', | ||||
|     '-Wlogical-op', | ||||
|     '-Wignored-qualifiers', | ||||
|     '-Werror=redundant-decls', | ||||
|     '-Werror=implicit', | ||||
|     '-Werror=nonnull', | ||||
|     '-Werror=init-self', | ||||
|     '-Werror=main', | ||||
|     '-Werror=missing-braces', | ||||
|     '-Werror=sequence-point', | ||||
|     '-Werror=return-type', | ||||
|     '-Werror=trigraphs', | ||||
|     '-Werror=array-bounds', | ||||
|     '-Werror=write-strings', | ||||
|     '-Werror=address', | ||||
|     '-Werror=int-to-pointer-cast', | ||||
|     '-Werror=pointer-to-int-cast', | ||||
|     '-Werror=empty-body', | ||||
|     '-Werror=write-strings', | ||||
|   ] | ||||
|   supported_warnings = cc.get_supported_arguments(all_warnings) | ||||
|   add_project_arguments(supported_warnings, language: 'c') | ||||
| endif | ||||
|  | ||||
| if get_option('debug') | ||||
|   debug_c_args = [ | ||||
|     '-DG_ENABLE_DEBUG', | ||||
|     '-fno-omit-frame-pointer' | ||||
|   ] | ||||
|   supported_debug_c_args = cc.get_supported_arguments(debug_c_args) | ||||
|   add_project_arguments(supported_debug_c_args, language: 'c') | ||||
| endif | ||||
| add_project_arguments(debug_c_args, language: 'c') | ||||
|  | ||||
| cc.compiles('void main (void) { __builtin_ffsl (0); __builtin_popcountl (0); }') | ||||
|  | ||||
| @@ -343,6 +351,7 @@ cdata.set('HAVE_LIBWACOM', have_libwacom) | ||||
| cdata.set('HAVE_SM', have_sm) | ||||
| cdata.set('HAVE_STARTUP_NOTIFICATION', have_startup_notification) | ||||
| cdata.set('HAVE_INTROSPECTION', have_introspection) | ||||
| cdata.set('HAVE_PROFILER', have_profiler) | ||||
|  | ||||
| xkb_base = xkeyboard_config_dep.get_pkgconfig_variable('xkb_base') | ||||
| cdata.set_quoted('XKB_BASE', xkb_base) | ||||
| @@ -408,6 +417,7 @@ output = [ | ||||
|   '        SM....................... ' + have_sm.to_string(), | ||||
|   '        Startup notification..... ' + have_startup_notification.to_string(), | ||||
|   '        Introspection............ ' + have_introspection.to_string(), | ||||
|   '        Profiler................. ' + have_profiler.to_string(), | ||||
|   '', | ||||
|   '    Tests:', | ||||
|   '', | ||||
|   | ||||
| @@ -123,6 +123,12 @@ option('tests', | ||||
|   description: 'Enable tests globally. Specific test suites can be controlled with core_tests, clutter_tests, and cogl_tests' | ||||
| ) | ||||
|  | ||||
| option('profiler', | ||||
|   type: 'boolean', | ||||
|   value: true, | ||||
|   description: 'Enable Sysprof tracing' | ||||
| ) | ||||
|  | ||||
| option('installed_tests', | ||||
|   type: 'boolean', | ||||
|   value: true, | ||||
|   | ||||
| @@ -9,6 +9,7 @@ data/org.gnome.mutter.gschema.xml.in | ||||
| data/org.gnome.mutter.wayland.gschema.xml.in | ||||
| src/backends/meta-input-settings.c | ||||
| src/backends/meta-monitor-manager.c | ||||
| src/backends/meta-profiler.c | ||||
| src/compositor/compositor.c | ||||
| src/compositor/meta-background.c | ||||
| src/core/bell.c | ||||
|   | ||||
							
								
								
									
										94
									
								
								po/es.po
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								po/es.po
									
									
									
									
									
								
							| @@ -13,8 +13,8 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: mutter.master\n" | ||||
| "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" | ||||
| "POT-Creation-Date: 2019-05-15 13:19+0000\n" | ||||
| "PO-Revision-Date: 2019-05-16 12:38+0200\n" | ||||
| "POT-Creation-Date: 2019-06-13 16:48+0000\n" | ||||
| "PO-Revision-Date: 2019-06-19 09:53+0200\n" | ||||
| "Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n" | ||||
| "Language-Team: es <gnome-es-list@gnome.org>\n" | ||||
| "Language: es\n" | ||||
| @@ -397,16 +397,6 @@ msgid "Enable experimental features" | ||||
| msgstr "Activar las características experimentales" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:108 | ||||
| #| msgid "" | ||||
| #| "To enable experimental features, add the feature keyword to the list. " | ||||
| #| "Whether the feature requires restarting the compositor depends on the " | ||||
| #| "given feature. Any experimental feature is not required to still be " | ||||
| #| "available, or configurable. Don’t expect adding anything in this setting " | ||||
| #| "to be future proof. Currently possible keywords: • “scale-monitor-" | ||||
| #| "framebuffer” — makes mutter default to layout logical monitors in a " | ||||
| #| "logical pixel coordinate space, while scaling monitor framebuffers " | ||||
| #| "instead of window content, to manage HiDPI monitors. Does not require a " | ||||
| #| "restart." | ||||
| msgid "" | ||||
| "To enable experimental features, add the feature keyword to the list. " | ||||
| "Whether the feature requires restarting the compositor depends on the given " | ||||
| @@ -432,19 +422,27 @@ msgstr "" | ||||
| "planificación en tiempo real con prioridad baja. El ejecutable o el usuario " | ||||
| "deben tener CAP_SYS_NICE. Requiere reniciar." | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:145 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:132 | ||||
| msgid "Modifier to use to locate the pointer" | ||||
| msgstr "Modificador que usar para encontrar el puntero" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:133 | ||||
| msgid "This key will initiate the “locate pointer” action." | ||||
| msgstr "Esta tecla iniciará la acción de encontrar el puntero." | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:153 | ||||
| msgid "Select window from tab popup" | ||||
| msgstr "Seleccionar ventana de la pestaña emergente" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:150 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:158 | ||||
| msgid "Cancel tab popup" | ||||
| msgstr "Cancelar pestaña emergente" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:155 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:163 | ||||
| msgid "Switch monitor configurations" | ||||
| msgstr "Cambiar la configuración del monitor" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:160 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:168 | ||||
| msgid "Rotates the built-in monitor configuration" | ||||
| msgstr "Rota la configuración del monitor empotrado" | ||||
|  | ||||
| @@ -501,28 +499,44 @@ msgid "Re-enable shortcuts" | ||||
| msgstr "Volver a activar los atajos" | ||||
|  | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:64 | ||||
| msgid "Allow grabs with Xwayland" | ||||
| msgstr "Permitir capturas con Xwayland" | ||||
| msgid "Allow X11 grabs to lock keyboard focus with Xwayland" | ||||
| msgstr "" | ||||
| "Permitir capturas con X11 para bloquear el foco del teclado con Xwayland" | ||||
|  | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:65 | ||||
| #| msgid "" | ||||
| #| "Allow keyboard grabs issued by X11 applications running in Xwayland to be " | ||||
| #| "taken into account. For a X11 grab to be taken into account under " | ||||
| #| "Wayland, the client must also either send a specific X11 ClientMessage to " | ||||
| #| "the root window or be among the applications white-listed in key " | ||||
| #| "“xwayland-grab-access-rules”." | ||||
| msgid "" | ||||
| "Allow keyboard grabs issued by X11 applications running in Xwayland to be " | ||||
| "taken into account. For a X11 grab to be taken into account under Wayland, " | ||||
| "the client must also either send a specific X11 ClientMessage to the root " | ||||
| "window or be among the applications white-listed in key “xwayland-grab-" | ||||
| "access-rules”." | ||||
| "Allow all keyboard events to be routed to X11 “override redirect” windows " | ||||
| "with a grab when running in Xwayland. This option is to support X11 clients " | ||||
| "which map an “override redirect” window (which do not receive keyboard " | ||||
| "focus) and issue a keyboard grab to force all keyboard events to that " | ||||
| "window. This option is seldom used and has no effect on regular X11 windows " | ||||
| "which can receive keyboard focus under normal circumstances. For a X11 grab " | ||||
| "to be taken into account under Wayland, the client must also either send a " | ||||
| "specific X11 ClientMessage to the root window or be among the applications " | ||||
| "white-listed in key “xwayland-grab-access-rules”." | ||||
| msgstr "" | ||||
| "Permitir que las pulsaciones del teclado emitidas por aplicaciones X11 " | ||||
| "ejecutándose en XWayland se tengan en cuenta. Para que una pulsación X11 se " | ||||
| "Permitir que los eventos del teclado se dirijan a ventanas X11 “override " | ||||
| "redirect” con una pulsación cuando se ejecutan en Xwayland. Esta opción es " | ||||
| "para soportar clientes X11 que mapean una ventana “override redirect” (que " | ||||
| "no recibe el foco del teclado) y recoge una pulsación del teclado para " | ||||
| "forzar todos los eventos del teclado en esa ventana. Esta opción se usa " | ||||
| "raramente y no tiene efecto en ventanas X11 normales que pueden recibir el " | ||||
| "foco del teclado en circunstancias normales. Para que una pulsación X11 se " | ||||
| "tenga en cuenta en Wayland el cliente debe o bien enviar un ClientMessage " | ||||
| "específico de X11 a la ventana raíz o estar en la lista blanca de " | ||||
| "aplicaciones en la clave “xwayland-grab-access-rules”." | ||||
|  | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:77 | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:84 | ||||
| msgid "Xwayland applications allowed to issue keyboard grabs" | ||||
| msgstr "Aplicaciones de Xwayland que pueden capturar el teclado" | ||||
|  | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:78 | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:85 | ||||
| msgid "" | ||||
| "List the resource names or resource class of X11 windows either allowed or " | ||||
| "not allowed to issue X11 keyboard grabs under Xwayland. The resource name or " | ||||
| @@ -548,7 +562,7 @@ msgstr "" | ||||
| #. TRANSLATORS: This string refers to a button that switches between | ||||
| #. * different modes. | ||||
| #. | ||||
| #: src/backends/meta-input-settings.c:2426 | ||||
| #: src/backends/meta-input-settings.c:2529 | ||||
| #, c-format | ||||
| msgid "Mode Switch (Group %d)" | ||||
| msgstr "Cambiar modo (grupo %d)" | ||||
| @@ -556,11 +570,11 @@ msgstr "Cambiar modo (grupo %d)" | ||||
| #. TRANSLATORS: This string refers to an action, cycles drawing tablets' | ||||
| #. * mapping through the available outputs. | ||||
| #. | ||||
| #: src/backends/meta-input-settings.c:2449 | ||||
| #: src/backends/meta-input-settings.c:2552 | ||||
| msgid "Switch monitor" | ||||
| msgstr "Cambiar monitor" | ||||
|  | ||||
| #: src/backends/meta-input-settings.c:2451 | ||||
| #: src/backends/meta-input-settings.c:2554 | ||||
| msgid "Show on-screen help" | ||||
| msgstr "Mostrar la ayuda en pantalla" | ||||
|  | ||||
| @@ -591,9 +605,14 @@ msgctxt "" | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #. Translators: this string will appear in Sysprof | ||||
| #: src/backends/meta-profiler.c:82 | ||||
| msgid "Compositor" | ||||
| msgstr "Compositor" | ||||
|  | ||||
| #. This probably means that a non-WM compositor like xcompmgr is running; | ||||
| #. * we have no way to get it to exit | ||||
| #: src/compositor/compositor.c:508 | ||||
| #: src/compositor/compositor.c:510 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Another compositing manager is already running on screen %i on display “%s”." | ||||
| @@ -699,7 +718,7 @@ msgstr "Imprimir versión" | ||||
| msgid "Mutter plugin to use" | ||||
| msgstr "Complemento de mutter que usar" | ||||
|  | ||||
| #: src/core/prefs.c:1786 | ||||
| #: src/core/prefs.c:1834 | ||||
| #, c-format | ||||
| msgid "Workspace %d" | ||||
| msgstr "Área de trabajo %d" | ||||
| @@ -713,7 +732,7 @@ msgstr "Mutter fue compilado sin soporte para modo prolijo\n" | ||||
| msgid "Mode Switch: Mode %d" | ||||
| msgstr "Cambiar modo: modo %d" | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:669 | ||||
| #: src/x11/meta-x11-display.c:681 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Display “%s” already has a window manager; try using the --replace option to " | ||||
| @@ -722,16 +741,16 @@ msgstr "" | ||||
| "La pantalla «%s» ya tiene un gestor de ventanas; pruebe a usar la opción «--" | ||||
| "replace» para reemplazar el gestor de ventanas activo." | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:1011 | ||||
| #: src/x11/meta-x11-display.c:1023 | ||||
| msgid "Failed to initialize GDK\n" | ||||
| msgstr "Falló al inicializar GDK\n" | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:1035 | ||||
| #: src/x11/meta-x11-display.c:1047 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display “%s”\n" | ||||
| msgstr "Ocurrió un error al abrir la pantalla de X Window System «%s»\n" | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:1116 | ||||
| #: src/x11/meta-x11-display.c:1131 | ||||
| #, c-format | ||||
| msgid "Screen %d on display “%s” is invalid\n" | ||||
| msgstr "La ventana %d en la pantalla «%s» no es válida\n" | ||||
| @@ -2134,9 +2153,6 @@ msgstr "%s (on %s)" | ||||
| #~ msgid "Commands to run in response to keybindings" | ||||
| #~ msgstr "Comandos a ejecutar en respuesta a combinaciones de teclas" | ||||
|  | ||||
| #~ msgid "Compositing Manager" | ||||
| #~ msgstr "Gestor de composición" | ||||
|  | ||||
| #~ msgid "Control how new windows get focus" | ||||
| #~ msgstr "Controla cómo obtienen el foco las ventanas nuevas" | ||||
|  | ||||
|   | ||||
							
								
								
									
										77
									
								
								po/hu.po
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								po/hu.po
									
									
									
									
									
								
							| @@ -6,20 +6,20 @@ | ||||
| # Gabor Sari <saga at externet dot hu>, 2003. | ||||
| # Laszlo Dvornik <dvornik at gnome dot hu>, 2004. | ||||
| # Gabor Kelemen <kelemeng at gnome dot hu>, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013. | ||||
| # Balázs Úr <urbalazs at gmail dot com>, 2013, 2014, 2015, 2016, 2017, 2018, 2019. | ||||
| # Balázs Úr <ur.balazs at fsf dot hu>, 2013, 2014, 2015, 2016, 2017, 2018, 2019. | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: mutter master\n" | ||||
| "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" | ||||
| "POT-Creation-Date: 2019-02-04 17:52+0000\n" | ||||
| "PO-Revision-Date: 2019-02-05 21:06+0100\n" | ||||
| "Last-Translator: Balázs Úr <urbalazs@gmail.com>\n" | ||||
| "POT-Creation-Date: 2019-05-31 18:48+0000\n" | ||||
| "PO-Revision-Date: 2019-06-01 17:46+0200\n" | ||||
| "Last-Translator: Balázs Úr <ur.balazs at fsf dot hu>\n" | ||||
| "Language-Team: Hungarian <gnome-hu-list at gnome dot org>\n" | ||||
| "Language: hu\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "X-Generator: Lokalize 1.2\n" | ||||
| "X-Generator: Lokalize 18.12.3\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||||
|  | ||||
| #: data/50-mutter-navigation.xml:6 | ||||
| @@ -395,7 +395,9 @@ msgid "" | ||||
| "proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes " | ||||
| "mutter default to layout logical monitors in a logical pixel coordinate " | ||||
| "space, while scaling monitor framebuffers instead of window content, to " | ||||
| "manage HiDPI monitors. Does not require a restart." | ||||
| "manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes " | ||||
| "mutter request a low priority real-time scheduling. The executable or user " | ||||
| "must have CAP_SYS_NICE. Requires a restart." | ||||
| msgstr "" | ||||
| "A kísérleti funkciók engedélyezéséhez adja hozzá a funkció kulcsszavát a " | ||||
| "listához. A funkció a betűszedő újraindítását igényelheti az adott " | ||||
| @@ -406,21 +408,23 @@ msgstr "" | ||||
| "teszi a mutter programot a logikai monitorok elrendezéséhez egy logikai " | ||||
| "képpontkoordináta-térben, miközben átméretezi a monitor keretpufferét az " | ||||
| "ablaktartalom helyett azért, hogy kezelje a HiDPI monitorokat. Nem igényel " | ||||
| "újraindítást." | ||||
| "újraindítást. • „rt-scheduler” — alacsony prioritású, valós idejű ütemezésre " | ||||
| "kéri a mutter programot. A programnak vagy a felhasználónak CAP_SYS_NICE " | ||||
| "értékkel kell rendelkeznie. Újraindítást igényel." | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:141 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:145 | ||||
| msgid "Select window from tab popup" | ||||
| msgstr "Ablakok kiválasztása tab billentyűre felugró ablakból" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:146 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:150 | ||||
| msgid "Cancel tab popup" | ||||
| msgstr "Tab felugró kikapcsolása" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:151 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:155 | ||||
| msgid "Switch monitor configurations" | ||||
| msgstr "Monitorkonfiguráció átváltása" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:156 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:160 | ||||
| msgid "Rotates the built-in monitor configuration" | ||||
| msgstr "Cserélgeti a beépített monitorkonfigurációkat" | ||||
|  | ||||
| @@ -525,7 +529,7 @@ msgstr "" | ||||
| #. TRANSLATORS: This string refers to a button that switches between | ||||
| #. * different modes. | ||||
| #. | ||||
| #: src/backends/meta-input-settings.c:2423 | ||||
| #: src/backends/meta-input-settings.c:2426 | ||||
| #, c-format | ||||
| msgid "Mode Switch (Group %d)" | ||||
| msgstr "Módkapcsoló (%d. csoport)" | ||||
| @@ -533,34 +537,34 @@ msgstr "Módkapcsoló (%d. csoport)" | ||||
| #. TRANSLATORS: This string refers to an action, cycles drawing tablets' | ||||
| #. * mapping through the available outputs. | ||||
| #. | ||||
| #: src/backends/meta-input-settings.c:2446 | ||||
| #: src/backends/meta-input-settings.c:2449 | ||||
| msgid "Switch monitor" | ||||
| msgstr "Monitorváltás" | ||||
|  | ||||
| #: src/backends/meta-input-settings.c:2448 | ||||
| #: src/backends/meta-input-settings.c:2451 | ||||
| msgid "Show on-screen help" | ||||
| msgstr "Képernyősúgó megjelenítése" | ||||
|  | ||||
| #: src/backends/meta-monitor-manager.c:954 | ||||
| #: src/backends/meta-monitor-manager.c:976 | ||||
| msgid "Built-in display" | ||||
| msgstr "Beépített kijelző" | ||||
|  | ||||
| #: src/backends/meta-monitor-manager.c:986 | ||||
| #: src/backends/meta-monitor-manager.c:1008 | ||||
| msgid "Unknown" | ||||
| msgstr "Ismeretlen" | ||||
|  | ||||
| #: src/backends/meta-monitor-manager.c:988 | ||||
| #: src/backends/meta-monitor-manager.c:1010 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Ismeretlen kijelző" | ||||
|  | ||||
| #: src/backends/meta-monitor-manager.c:996 | ||||
| #: src/backends/meta-monitor-manager.c:1018 | ||||
| #, c-format | ||||
| msgctxt "" | ||||
| "This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #: src/backends/meta-monitor-manager.c:1004 | ||||
| #: src/backends/meta-monitor-manager.c:1026 | ||||
| #, c-format | ||||
| msgctxt "" | ||||
| "This is a monitor vendor name followed by product/model name where size in " | ||||
| @@ -568,9 +572,14 @@ msgctxt "" | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #. Translators: this string will appear in Sysprof | ||||
| #: src/backends/meta-profiler.c:82 | ||||
| msgid "Compositor" | ||||
| msgstr "Betűszedő" | ||||
|  | ||||
| #. This probably means that a non-WM compositor like xcompmgr is running; | ||||
| #. * we have no way to get it to exit | ||||
| #: src/compositor/compositor.c:482 | ||||
| #: src/compositor/compositor.c:510 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Another compositing manager is already running on screen %i on display “%s”." | ||||
| @@ -578,7 +587,7 @@ msgstr "" | ||||
| "Már fut egy másik kompozitálás-kezelő a(z) %i. képernyőn a(z) „%s” " | ||||
| "megjelenítőn." | ||||
|  | ||||
| #: src/core/bell.c:252 | ||||
| #: src/core/bell.c:192 | ||||
| msgid "Bell event" | ||||
| msgstr "Csengetés esemény" | ||||
|  | ||||
| @@ -628,16 +637,16 @@ msgid "Run with X11 backend" | ||||
| msgstr "Futtatás X11 háttérprogrammal" | ||||
|  | ||||
| #. Translators: %s is a window title | ||||
| #: src/core/meta-close-dialog-default.c:150 | ||||
| #: src/core/meta-close-dialog-default.c:151 | ||||
| #, c-format | ||||
| msgid "“%s” is not responding." | ||||
| msgstr "„%s” nem válaszol." | ||||
|  | ||||
| #: src/core/meta-close-dialog-default.c:152 | ||||
| #: src/core/meta-close-dialog-default.c:153 | ||||
| msgid "Application is not responding." | ||||
| msgstr "Az alkalmazás nem válaszol." | ||||
|  | ||||
| #: src/core/meta-close-dialog-default.c:157 | ||||
| #: src/core/meta-close-dialog-default.c:158 | ||||
| msgid "" | ||||
| "You may choose to wait a short while for it to continue or force the " | ||||
| "application to quit entirely." | ||||
| @@ -645,11 +654,11 @@ msgstr "" | ||||
| "Várhat egy kicsit a folytatódására, vagy kikényszerítheti az alkalmazás " | ||||
| "teljes kilépését." | ||||
|  | ||||
| #: src/core/meta-close-dialog-default.c:164 | ||||
| #: src/core/meta-close-dialog-default.c:165 | ||||
| msgid "_Force Quit" | ||||
| msgstr "_Erőltetett kilépés" | ||||
|  | ||||
| #: src/core/meta-close-dialog-default.c:164 | ||||
| #: src/core/meta-close-dialog-default.c:165 | ||||
| msgid "_Wait" | ||||
| msgstr "Vá_rakozás" | ||||
|  | ||||
| @@ -690,7 +699,7 @@ msgstr "A Mutter ablakkezelőt a részletes mód támogatása nélkül fordítot | ||||
| msgid "Mode Switch: Mode %d" | ||||
| msgstr "Módkapcsoló: %d. mód" | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:666 | ||||
| #: src/x11/meta-x11-display.c:674 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Display “%s” already has a window manager; try using the --replace option to " | ||||
| @@ -699,20 +708,25 @@ msgstr "" | ||||
| "A(z) „%s” kijelző már rendelkezik ablakkezelővel; próbálja a --replace " | ||||
| "kapcsolóval helyettesíteni a jelenlegi ablakkezelőt." | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:1008 | ||||
| #: src/x11/meta-x11-display.c:1016 | ||||
| msgid "Failed to initialize GDK\n" | ||||
| msgstr "A GDK előkészítése meghiúsult\n" | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:1032 | ||||
| #: src/x11/meta-x11-display.c:1040 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display “%s”\n" | ||||
| msgstr "Nem sikerült megnyitni a(z) „%s” X Window rendszer képernyőt\n" | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:1115 | ||||
| #: src/x11/meta-x11-display.c:1124 | ||||
| #, c-format | ||||
| msgid "Screen %d on display “%s” is invalid\n" | ||||
| msgstr "A(z) %d. képernyő a(z) „%s” megjelenítőn érvénytelen\n" | ||||
|  | ||||
| #: src/x11/meta-x11-selection-input-stream.c:445 | ||||
| #, c-format | ||||
| msgid "Format %s not supported" | ||||
| msgstr "A(z) %s formátum nem támogatott" | ||||
|  | ||||
| #: src/x11/session.c:1821 | ||||
| msgid "" | ||||
| "These windows do not support “save current setup” and will have to be " | ||||
| @@ -721,8 +735,7 @@ msgstr "" | ||||
| "Az alábbi ablakok nem támogatják az „aktuális beállítások mentését”, emiatt " | ||||
| "ezeket a legközelebbi bejelentkezéskor manuálisan újra kell indítania." | ||||
|  | ||||
| #: src/x11/window-props.c:568 | ||||
| #: src/x11/window-props.c:569 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (ezen: %s)" | ||||
|  | ||||
|   | ||||
							
								
								
									
										111
									
								
								po/nl.po
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								po/nl.po
									
									
									
									
									
								
							| @@ -10,8 +10,8 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: mutter\n" | ||||
| "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n" | ||||
| "POT-Creation-Date: 2019-02-04 17:52+0000\n" | ||||
| "PO-Revision-Date: 2019-02-24 12:38+0100\n" | ||||
| "POT-Creation-Date: 2019-06-13 16:48+0000\n" | ||||
| "PO-Revision-Date: 2019-06-18 10:21+0200\n" | ||||
| "Last-Translator: Nathan Follens <nthn@unseen.is>\n" | ||||
| "Language-Team: Dutch <vertaling@vrijschrift.org>\n" | ||||
| "Language: nl\n" | ||||
| @@ -20,7 +20,7 @@ msgstr "" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||||
| "X-Project-Style: gnome\n" | ||||
| "X-Generator: Poedit 2.2.1\n" | ||||
| "X-Generator: Poedit 2.2.3\n" | ||||
|  | ||||
| #: data/50-mutter-navigation.xml:6 | ||||
| msgid "Navigation" | ||||
| @@ -397,7 +397,9 @@ msgid "" | ||||
| "proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes " | ||||
| "mutter default to layout logical monitors in a logical pixel coordinate " | ||||
| "space, while scaling monitor framebuffers instead of window content, to " | ||||
| "manage HiDPI monitors. Does not require a restart." | ||||
| "manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes " | ||||
| "mutter request a low priority real-time scheduling. The executable or user " | ||||
| "must have CAP_SYS_NICE. Requires a restart." | ||||
| msgstr "" | ||||
| "Voeg het sleutelwoord van een experimentele functie toe aan de lijst om deze " | ||||
| "in te schakelen. Of de compositor herstart moet worden vooraleer de functie " | ||||
| @@ -408,21 +410,31 @@ msgstr "" | ||||
| "framebuffer’ — zorgt dat mutter standaard logische beeldschermen indeelt in " | ||||
| "een logische pixelcoördinaatruimte, en beeldschermframebuffers schaalt in " | ||||
| "plaats van vensterinhoud, om HiDPI-beeldschermen te beheren. Hiervoor is " | ||||
| "opnieuw opstarten niet vereist." | ||||
| "opnieuw opstarten niet vereist. • “rt-scheduler” — zorgt ervoor dat mutter " | ||||
| "real-time plannen met lage prioriteit aanvraagt. Het uitvoerbaar bestand of " | ||||
| "de gebruiker moet CAP_SYS_NICE hebben. Hiervoor is opnieuw opstarten vereist." | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:141 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:132 | ||||
| msgid "Modifier to use to locate the pointer" | ||||
| msgstr "Controletoets om de muispijl te lokaliseren" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:133 | ||||
| msgid "This key will initiate the “locate pointer” action." | ||||
| msgstr "Deze sleutel activeert de actie ‘muispijl lokaliseren’." | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:153 | ||||
| msgid "Select window from tab popup" | ||||
| msgstr "Venster selecteren uit tab-pop-up" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:146 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:158 | ||||
| msgid "Cancel tab popup" | ||||
| msgstr "Tab-pop-up annuleren" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:151 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:163 | ||||
| msgid "Switch monitor configurations" | ||||
| msgstr "Tussen beeldschermconfiguraties schakelen" | ||||
|  | ||||
| #: data/org.gnome.mutter.gschema.xml.in:156 | ||||
| #: data/org.gnome.mutter.gschema.xml.in:168 | ||||
| msgid "Rotates the built-in monitor configuration" | ||||
| msgstr "Roteert de ingebouwde beeldschermconfiguratie" | ||||
|  | ||||
| @@ -479,16 +491,27 @@ msgid "Re-enable shortcuts" | ||||
| msgstr "Sneltoetsen opnieuw inschakelen" | ||||
|  | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:64 | ||||
| msgid "Allow grabs with Xwayland" | ||||
| msgstr "Grabs met Xwayland toestaan" | ||||
| msgid "Allow X11 grabs to lock keyboard focus with Xwayland" | ||||
| msgstr "X11-grabs toestaan om toetsenbordfocus met Xwayland te vergrendelen" | ||||
|  | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:65 | ||||
| #, fuzzy | ||||
| #| msgid "" | ||||
| #| "Allow keyboard grabs issued by X11 applications running in Xwayland to be " | ||||
| #| "taken into account. For a X11 grab to be taken into account under " | ||||
| #| "Wayland, the client must also either send a specific X11 ClientMessage to " | ||||
| #| "the root window or be among the applications white-listed in key " | ||||
| #| "“xwayland-grab-access-rules”." | ||||
| msgid "" | ||||
| "Allow keyboard grabs issued by X11 applications running in Xwayland to be " | ||||
| "taken into account. For a X11 grab to be taken into account under Wayland, " | ||||
| "the client must also either send a specific X11 ClientMessage to the root " | ||||
| "window or be among the applications white-listed in key “xwayland-grab-" | ||||
| "access-rules”." | ||||
| "Allow all keyboard events to be routed to X11 “override redirect” windows " | ||||
| "with a grab when running in Xwayland. This option is to support X11 clients " | ||||
| "which map an “override redirect” window (which do not receive keyboard " | ||||
| "focus) and issue a keyboard grab to force all keyboard events to that " | ||||
| "window. This option is seldom used and has no effect on regular X11 windows " | ||||
| "which can receive keyboard focus under normal circumstances. For a X11 grab " | ||||
| "to be taken into account under Wayland, the client must also either send a " | ||||
| "specific X11 ClientMessage to the root window or be among the applications " | ||||
| "white-listed in key “xwayland-grab-access-rules”." | ||||
| msgstr "" | ||||
| "Toestaan dat rekening wordt gehouden met toetsenbord-grabs door X11-" | ||||
| "toepassingen die in Xwayland draaien. Om rekening te houden met een X11-grab " | ||||
| @@ -496,11 +519,11 @@ msgstr "" | ||||
| "het root-venster sturen, óf vermeld staan in de witte lijst van toepassingen " | ||||
| "in de sleutel ‘xwayland-grab-access-rules’." | ||||
|  | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:77 | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:84 | ||||
| msgid "Xwayland applications allowed to issue keyboard grabs" | ||||
| msgstr "Xwayland-toepassingen mogen toetsenbord-grabs doen" | ||||
|  | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:78 | ||||
| #: data/org.gnome.mutter.wayland.gschema.xml.in:85 | ||||
| msgid "" | ||||
| "List the resource names or resource class of X11 windows either allowed or " | ||||
| "not allowed to issue X11 keyboard grabs under Xwayland. The resource name or " | ||||
| @@ -527,7 +550,7 @@ msgstr "" | ||||
| #. TRANSLATORS: This string refers to a button that switches between | ||||
| #. * different modes. | ||||
| #. | ||||
| #: src/backends/meta-input-settings.c:2423 | ||||
| #: src/backends/meta-input-settings.c:2529 | ||||
| #, c-format | ||||
| msgid "Mode Switch (Group %d)" | ||||
| msgstr "Moduswisselaar (groep %d)" | ||||
| @@ -535,34 +558,34 @@ msgstr "Moduswisselaar (groep %d)" | ||||
| #. TRANSLATORS: This string refers to an action, cycles drawing tablets' | ||||
| #. * mapping through the available outputs. | ||||
| #. | ||||
| #: src/backends/meta-input-settings.c:2446 | ||||
| #: src/backends/meta-input-settings.c:2552 | ||||
| msgid "Switch monitor" | ||||
| msgstr "Van beeldscherm wisselen" | ||||
|  | ||||
| #: src/backends/meta-input-settings.c:2448 | ||||
| #: src/backends/meta-input-settings.c:2554 | ||||
| msgid "Show on-screen help" | ||||
| msgstr "Hulptekst op scherm tonen" | ||||
|  | ||||
| #: src/backends/meta-monitor-manager.c:954 | ||||
| #: src/backends/meta-monitor-manager.c:976 | ||||
| msgid "Built-in display" | ||||
| msgstr "Ingebouwd beeldscherm" | ||||
|  | ||||
| #: src/backends/meta-monitor-manager.c:986 | ||||
| #: src/backends/meta-monitor-manager.c:1008 | ||||
| msgid "Unknown" | ||||
| msgstr "Onbekend" | ||||
|  | ||||
| #: src/backends/meta-monitor-manager.c:988 | ||||
| #: src/backends/meta-monitor-manager.c:1010 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Onbekend beeldscherm" | ||||
|  | ||||
| #: src/backends/meta-monitor-manager.c:996 | ||||
| #: src/backends/meta-monitor-manager.c:1018 | ||||
| #, c-format | ||||
| msgctxt "" | ||||
| "This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'" | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #: src/backends/meta-monitor-manager.c:1004 | ||||
| #: src/backends/meta-monitor-manager.c:1026 | ||||
| #, c-format | ||||
| msgctxt "" | ||||
| "This is a monitor vendor name followed by product/model name where size in " | ||||
| @@ -570,9 +593,14 @@ msgctxt "" | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #. Translators: this string will appear in Sysprof | ||||
| #: src/backends/meta-profiler.c:82 | ||||
| msgid "Compositor" | ||||
| msgstr "Compositor" | ||||
|  | ||||
| #. This probably means that a non-WM compositor like xcompmgr is running; | ||||
| #. * we have no way to get it to exit | ||||
| #: src/compositor/compositor.c:482 | ||||
| #: src/compositor/compositor.c:510 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Another compositing manager is already running on screen %i on display “%s”." | ||||
| @@ -580,7 +608,7 @@ msgstr "" | ||||
| "Er is al een andere ‘compositing manager’ actief op scherm %i van " | ||||
| "beeldscherm ‘%s’." | ||||
|  | ||||
| #: src/core/bell.c:252 | ||||
| #: src/core/bell.c:192 | ||||
| msgid "Bell event" | ||||
| msgstr "Bel-gebeurtenis" | ||||
|  | ||||
| @@ -629,16 +657,16 @@ msgid "Run with X11 backend" | ||||
| msgstr "Uitvoeren met X11-backend" | ||||
|  | ||||
| #. Translators: %s is a window title | ||||
| #: src/core/meta-close-dialog-default.c:150 | ||||
| #: src/core/meta-close-dialog-default.c:151 | ||||
| #, c-format | ||||
| msgid "“%s” is not responding." | ||||
| msgstr "‘%s’ reageert niet." | ||||
|  | ||||
| #: src/core/meta-close-dialog-default.c:152 | ||||
| #: src/core/meta-close-dialog-default.c:153 | ||||
| msgid "Application is not responding." | ||||
| msgstr "De toepassing reageert niet." | ||||
|  | ||||
| #: src/core/meta-close-dialog-default.c:157 | ||||
| #: src/core/meta-close-dialog-default.c:158 | ||||
| msgid "" | ||||
| "You may choose to wait a short while for it to continue or force the " | ||||
| "application to quit entirely." | ||||
| @@ -646,11 +674,11 @@ msgstr "" | ||||
| "U kunt ervoor kiezen even te wachten totdat het doorgaat of de toepassing " | ||||
| "dwingen om helemaal af te sluiten." | ||||
|  | ||||
| #: src/core/meta-close-dialog-default.c:164 | ||||
| #: src/core/meta-close-dialog-default.c:165 | ||||
| msgid "_Force Quit" | ||||
| msgstr "Ge_forceerd afsluiten" | ||||
|  | ||||
| #: src/core/meta-close-dialog-default.c:164 | ||||
| #: src/core/meta-close-dialog-default.c:165 | ||||
| msgid "_Wait" | ||||
| msgstr "_Wachten" | ||||
|  | ||||
| @@ -677,7 +705,7 @@ msgstr "Versie-informatie tonen" | ||||
| msgid "Mutter plugin to use" | ||||
| msgstr "Te gebruiken Mutter-plug-in" | ||||
|  | ||||
| #: src/core/prefs.c:1786 | ||||
| #: src/core/prefs.c:1834 | ||||
| #, c-format | ||||
| msgid "Workspace %d" | ||||
| msgstr "Werkblad %d" | ||||
| @@ -691,7 +719,7 @@ msgstr "Mutter is gecompileerd zonder ondersteuning voor verbose-mode\n" | ||||
| msgid "Mode Switch: Mode %d" | ||||
| msgstr "Moduswisselaar: modus %d" | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:666 | ||||
| #: src/x11/meta-x11-display.c:681 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Display “%s” already has a window manager; try using the --replace option to " | ||||
| @@ -700,20 +728,25 @@ msgstr "" | ||||
| "Beeldscherm ‘%s’ heeft al een vensterbeheerder; probeer de optie: --replace " | ||||
| "te gebruiken om de huidige vensterbeheerder te vervangen." | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:1008 | ||||
| #: src/x11/meta-x11-display.c:1023 | ||||
| msgid "Failed to initialize GDK\n" | ||||
| msgstr "Initialiseren van GDK mislukt\n" | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:1032 | ||||
| #: src/x11/meta-x11-display.c:1047 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display “%s”\n" | ||||
| msgstr "Openen van X Window System display ‘%s’ mislukt\n" | ||||
|  | ||||
| #: src/x11/meta-x11-display.c:1115 | ||||
| #: src/x11/meta-x11-display.c:1131 | ||||
| #, c-format | ||||
| msgid "Screen %d on display “%s” is invalid\n" | ||||
| msgstr "Scherm %d op beeldscherm ‘%s’ is ongeldig\n" | ||||
|  | ||||
| #: src/x11/meta-x11-selection-input-stream.c:445 | ||||
| #, c-format | ||||
| msgid "Format %s not supported" | ||||
| msgstr "Formaat %s wordt niet ondersteund" | ||||
|  | ||||
| #: src/x11/session.c:1821 | ||||
| msgid "" | ||||
| "These windows do not support “save current setup” and will have to be " | ||||
| @@ -722,7 +755,7 @@ msgstr "" | ||||
| "Deze vensters ondersteunen het opslaan van de huidige instellingen niet en " | ||||
| "zullen bij een volgende sessie opnieuw moeten worden opgestart." | ||||
|  | ||||
| #: src/x11/window-props.c:568 | ||||
| #: src/x11/window-props.c:569 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (op %s)" | ||||
|   | ||||
| @@ -181,4 +181,11 @@ void meta_backend_notify_keymap_layout_group_changed (MetaBackend *backend, | ||||
|  | ||||
| void meta_backend_notify_ui_scaling_factor_changed (MetaBackend *backend); | ||||
|  | ||||
| META_EXPORT_TEST | ||||
| void meta_backend_add_gpu (MetaBackend *backend, | ||||
|                            MetaGpu     *gpu); | ||||
|  | ||||
| META_EXPORT_TEST | ||||
| GList * meta_backend_get_gpus (MetaBackend *backend); | ||||
|  | ||||
| #endif /* META_BACKEND_PRIVATE_H */ | ||||
|   | ||||
| @@ -66,6 +66,10 @@ | ||||
| #include "meta/meta-backend.h" | ||||
| #include "meta/util.h" | ||||
|  | ||||
| #ifdef HAVE_PROFILER | ||||
| #include "backends/meta-profiler.h" | ||||
| #endif | ||||
|  | ||||
| #ifdef HAVE_REMOTE_DESKTOP | ||||
| #include "backends/meta-dbus-session-watcher.h" | ||||
| #include "backends/meta-remote-access-controller-private.h" | ||||
| @@ -85,6 +89,7 @@ enum | ||||
|   KEYMAP_LAYOUT_GROUP_CHANGED, | ||||
|   LAST_DEVICE_CHANGED, | ||||
|   LID_IS_CLOSED_CHANGED, | ||||
|   GPU_ADDED, | ||||
|  | ||||
|   N_SIGNALS | ||||
| }; | ||||
| @@ -127,9 +132,15 @@ struct _MetaBackendPrivate | ||||
|   MetaRemoteDesktop *remote_desktop; | ||||
| #endif | ||||
|  | ||||
| #ifdef HAVE_PROFILER | ||||
|   MetaProfiler *profiler; | ||||
| #endif | ||||
|  | ||||
|   ClutterBackend *clutter_backend; | ||||
|   ClutterActor *stage; | ||||
|  | ||||
|   GList *gpus; | ||||
|  | ||||
|   gboolean is_pointer_position_initialized; | ||||
|  | ||||
|   guint device_update_idle_id; | ||||
| @@ -167,6 +178,8 @@ meta_backend_finalize (GObject *object) | ||||
|   MetaBackend *backend = META_BACKEND (object); | ||||
|   MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); | ||||
|  | ||||
|   g_list_free_full (priv->gpus, g_object_unref); | ||||
|  | ||||
|   g_clear_object (&priv->monitor_manager); | ||||
|   g_clear_object (&priv->orientation_manager); | ||||
|   g_clear_object (&priv->input_settings); | ||||
| @@ -193,6 +206,10 @@ meta_backend_finalize (GObject *object) | ||||
|  | ||||
|   g_clear_object (&priv->settings); | ||||
|  | ||||
| #ifdef HAVE_PROFILER | ||||
|   g_clear_object (&priv->profiler); | ||||
| #endif | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| @@ -740,6 +757,18 @@ meta_backend_class_init (MetaBackendClass *klass) | ||||
|                   0, | ||||
|                   NULL, NULL, NULL, | ||||
|                   G_TYPE_NONE, 1, G_TYPE_BOOLEAN); | ||||
|   /** | ||||
|    * MetaBackend::gpu-added: (skip) | ||||
|    * @backend: the #MetaBackend | ||||
|    * @gpu: the #MetaGpu | ||||
|    */ | ||||
|   signals[GPU_ADDED] = | ||||
|     g_signal_new ("gpu-added", | ||||
|                   G_TYPE_FROM_CLASS (klass), | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   0, | ||||
|                   NULL, NULL, NULL, | ||||
|                   G_TYPE_NONE, 1, META_TYPE_GPU); | ||||
|  | ||||
|   mutter_stage_views = g_getenv ("MUTTER_STAGE_VIEWS"); | ||||
|   stage_views_disabled = g_strcmp0 (mutter_stage_views, "0") == 0; | ||||
| @@ -841,6 +870,10 @@ meta_backend_initable_init (GInitable     *initable, | ||||
|              system_bus_gotten_cb, | ||||
|              backend); | ||||
|  | ||||
| #ifdef HAVE_PROFILER | ||||
|   priv->profiler = meta_profiler_new (); | ||||
| #endif | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| @@ -1383,3 +1416,22 @@ meta_backend_notify_keymap_layout_group_changed (MetaBackend *backend, | ||||
|   g_signal_emit (backend, signals[KEYMAP_LAYOUT_GROUP_CHANGED], 0, | ||||
|                  locked_group); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_backend_add_gpu (MetaBackend *backend, | ||||
|                       MetaGpu     *gpu) | ||||
| { | ||||
|   MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); | ||||
|  | ||||
|   priv->gpus = g_list_append (priv->gpus, gpu); | ||||
|  | ||||
|   g_signal_emit (backend, signals[GPU_ADDED], 0, gpu); | ||||
| } | ||||
|  | ||||
| GList * | ||||
| meta_backend_get_gpus (MetaBackend *backend) | ||||
| { | ||||
|   MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); | ||||
|  | ||||
|   return priv->gpus; | ||||
| } | ||||
|   | ||||
| @@ -30,6 +30,7 @@ | ||||
|  | ||||
| #include "backends/meta-stage-private.h" | ||||
| #include "clutter/clutter.h" | ||||
| #include "clutter/clutter-mutter.h" | ||||
| #include "cogl/cogl.h" | ||||
| #include "meta/meta-backend.h" | ||||
| #include "meta/util.h" | ||||
| @@ -82,6 +83,33 @@ meta_cursor_renderer_emit_painted (MetaCursorRenderer *renderer, | ||||
|   g_signal_emit (renderer, signals[CURSOR_PAINTED], 0, cursor_sprite); | ||||
| } | ||||
|  | ||||
| static void | ||||
| align_cursor_position (MetaCursorRenderer *renderer, | ||||
|                        ClutterRect        *rect) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = | ||||
|     meta_cursor_renderer_get_instance_private (renderer); | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   ClutterActor *stage = meta_backend_get_stage (backend); | ||||
|   ClutterStageView *view; | ||||
|   cairo_rectangle_int_t view_layout; | ||||
|   float view_scale; | ||||
|  | ||||
|   view = clutter_stage_get_view_at (CLUTTER_STAGE (stage), | ||||
|                                     priv->current_x, | ||||
|                                     priv->current_y); | ||||
|   if (!view) | ||||
|     return; | ||||
|  | ||||
|   clutter_stage_view_get_layout (view, &view_layout); | ||||
|   view_scale = clutter_stage_view_get_scale (view); | ||||
|  | ||||
|   clutter_rect_offset (rect, -view_layout.x, -view_layout.y); | ||||
|   rect->origin.x = floorf (rect->origin.x * view_scale) / view_scale; | ||||
|   rect->origin.y = floorf (rect->origin.y * view_scale) / view_scale; | ||||
|   clutter_rect_offset (rect, view_layout.x, view_layout.y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| queue_redraw (MetaCursorRenderer *renderer, | ||||
|               MetaCursorSprite   *cursor_sprite) | ||||
| @@ -92,13 +120,16 @@ queue_redraw (MetaCursorRenderer *renderer, | ||||
|   CoglTexture *texture; | ||||
|   ClutterRect rect = CLUTTER_RECT_INIT_ZERO; | ||||
|  | ||||
|   if (cursor_sprite) | ||||
|     rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); | ||||
|  | ||||
|   /* During early initialization, we can have no stage */ | ||||
|   if (!stage) | ||||
|     return; | ||||
|  | ||||
|   if (cursor_sprite) | ||||
|     { | ||||
|       rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); | ||||
|       align_cursor_position (renderer, &rect); | ||||
|     } | ||||
|  | ||||
|   if (!priv->stage_overlay) | ||||
|     priv->stage_overlay = meta_stage_create_cursor_overlay (META_STAGE (stage)); | ||||
|  | ||||
|   | ||||
| @@ -23,13 +23,14 @@ | ||||
|  | ||||
| #include "backends/meta-gpu.h" | ||||
|  | ||||
| #include "backends/meta-backend-private.h" | ||||
| #include "backends/meta-output.h" | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|  | ||||
|   PROP_MONITOR_MANAGER, | ||||
|   PROP_BACKEND, | ||||
|  | ||||
|   PROP_LAST | ||||
| }; | ||||
| @@ -38,7 +39,7 @@ static GParamSpec *obj_props[PROP_LAST]; | ||||
|  | ||||
| typedef struct _MetaGpuPrivate | ||||
| { | ||||
|   MetaMonitorManager *monitor_manager; | ||||
|   MetaBackend *backend; | ||||
|  | ||||
|   GList *outputs; | ||||
|   GList *crtcs; | ||||
| @@ -88,12 +89,12 @@ meta_gpu_read_current (MetaGpu  *gpu, | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| MetaMonitorManager * | ||||
| meta_gpu_get_monitor_manager (MetaGpu *gpu) | ||||
| MetaBackend * | ||||
| meta_gpu_get_backend (MetaGpu *gpu) | ||||
| { | ||||
|   MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); | ||||
|  | ||||
|   return priv->monitor_manager; | ||||
|   return priv->backend; | ||||
| } | ||||
|  | ||||
| GList * | ||||
| @@ -158,8 +159,8 @@ meta_gpu_set_property (GObject      *object, | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_MONITOR_MANAGER: | ||||
|       priv->monitor_manager = g_value_get_object (value); | ||||
|     case PROP_BACKEND: | ||||
|       priv->backend = g_value_get_object (value); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
| @@ -177,8 +178,8 @@ meta_gpu_get_property (GObject    *object, | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_MONITOR_MANAGER: | ||||
|       g_value_set_object (value, priv->monitor_manager); | ||||
|     case PROP_BACKEND: | ||||
|       g_value_set_object (value, priv->backend); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
| @@ -212,11 +213,11 @@ meta_gpu_class_init (MetaGpuClass *klass) | ||||
|   object_class->get_property = meta_gpu_get_property; | ||||
|   object_class->finalize = meta_gpu_finalize; | ||||
|  | ||||
|   obj_props[PROP_MONITOR_MANAGER] = | ||||
|     g_param_spec_object ("monitor-manager", | ||||
|                          "monitor-manager", | ||||
|                          "MetaMonitorManager", | ||||
|                          META_TYPE_MONITOR_MANAGER, | ||||
|   obj_props[PROP_BACKEND] = | ||||
|     g_param_spec_object ("backend", | ||||
|                          "backend", | ||||
|                          "MetaBackend", | ||||
|                          META_TYPE_BACKEND, | ||||
|                          G_PARAM_READWRITE | | ||||
|                          G_PARAM_CONSTRUCT_ONLY | | ||||
|                          G_PARAM_STATIC_STRINGS); | ||||
|   | ||||
| @@ -46,7 +46,7 @@ META_EXPORT_TEST | ||||
| gboolean meta_gpu_has_hotplug_mode_update (MetaGpu *gpu); | ||||
|  | ||||
| META_EXPORT_TEST | ||||
| MetaMonitorManager * meta_gpu_get_monitor_manager (MetaGpu *gpu); | ||||
| MetaBackend * meta_gpu_get_backend (MetaGpu *gpu); | ||||
|  | ||||
| META_EXPORT_TEST | ||||
| GList * meta_gpu_get_outputs (MetaGpu *gpu); | ||||
|   | ||||
| @@ -76,7 +76,8 @@ struct _MetaInputSettingsPrivate | ||||
|   GSettings *trackball_settings; | ||||
|   GSettings *keyboard_settings; | ||||
|   GSettings *gsd_settings; | ||||
|   GSettings *a11y_settings; | ||||
|   GSettings *keyboard_a11y_settings; | ||||
|   GSettings *mouse_a11y_settings; | ||||
|  | ||||
|   GHashTable *mappable_devices; | ||||
|  | ||||
| @@ -161,7 +162,8 @@ meta_input_settings_dispose (GObject *object) | ||||
|   g_clear_object (&priv->trackball_settings); | ||||
|   g_clear_object (&priv->keyboard_settings); | ||||
|   g_clear_object (&priv->gsd_settings); | ||||
|   g_clear_object (&priv->a11y_settings); | ||||
|   g_clear_object (&priv->keyboard_a11y_settings); | ||||
|   g_clear_object (&priv->mouse_a11y_settings); | ||||
|   g_clear_object (&priv->input_mapper); | ||||
|   g_clear_pointer (&priv->mappable_devices, g_hash_table_unref); | ||||
|   g_clear_pointer (&priv->current_tools, g_hash_table_unref); | ||||
| @@ -1191,10 +1193,10 @@ apply_mappable_device_settings (MetaInputSettings *input_settings, | ||||
|     } | ||||
| } | ||||
|  | ||||
| struct _a11y_settings_flags_pair { | ||||
| struct _keyboard_a11y_settings_flags_pair { | ||||
|   const char *name; | ||||
|   ClutterKeyboardA11yFlags flag; | ||||
| } settings_flags_pair[] = { | ||||
| } keyboard_a11y_settings_flags_pair[] = { | ||||
|   { "enable",                    CLUTTER_A11Y_KEYBOARD_ENABLED }, | ||||
|   { "timeout-enable",            CLUTTER_A11Y_TIMEOUT_ENABLED }, | ||||
|   { "mousekeys-enable",          CLUTTER_A11Y_MOUSE_KEYS_ENABLED }, | ||||
| @@ -1225,23 +1227,23 @@ load_keyboard_a11y_settings (MetaInputSettings  *input_settings, | ||||
|     return; | ||||
|  | ||||
|   kbd_a11y_settings.controls = 0; | ||||
|   for (i = 0; i < G_N_ELEMENTS (settings_flags_pair); i++) | ||||
|   for (i = 0; i < G_N_ELEMENTS (keyboard_a11y_settings_flags_pair); i++) | ||||
|     { | ||||
|       if (g_settings_get_boolean (priv->a11y_settings, settings_flags_pair[i].name)) | ||||
|         kbd_a11y_settings.controls |= settings_flags_pair[i].flag; | ||||
|       if (g_settings_get_boolean (priv->keyboard_a11y_settings, keyboard_a11y_settings_flags_pair[i].name)) | ||||
|         kbd_a11y_settings.controls |= keyboard_a11y_settings_flags_pair[i].flag; | ||||
|     } | ||||
|  | ||||
|   kbd_a11y_settings.timeout_delay = g_settings_get_int (priv->a11y_settings, | ||||
|   kbd_a11y_settings.timeout_delay = g_settings_get_int (priv->keyboard_a11y_settings, | ||||
|                                                         "disable-timeout"); | ||||
|   kbd_a11y_settings.slowkeys_delay = g_settings_get_int (priv->a11y_settings, | ||||
|   kbd_a11y_settings.slowkeys_delay = g_settings_get_int (priv->keyboard_a11y_settings, | ||||
|                                                          "slowkeys-delay"); | ||||
|   kbd_a11y_settings.debounce_delay = g_settings_get_int (priv->a11y_settings, | ||||
|   kbd_a11y_settings.debounce_delay = g_settings_get_int (priv->keyboard_a11y_settings, | ||||
|                                                          "bouncekeys-delay"); | ||||
|   kbd_a11y_settings.mousekeys_init_delay = g_settings_get_int (priv->a11y_settings, | ||||
|   kbd_a11y_settings.mousekeys_init_delay = g_settings_get_int (priv->keyboard_a11y_settings, | ||||
|                                                                "mousekeys-init-delay"); | ||||
|   kbd_a11y_settings.mousekeys_max_speed = g_settings_get_int (priv->a11y_settings, | ||||
|   kbd_a11y_settings.mousekeys_max_speed = g_settings_get_int (priv->keyboard_a11y_settings, | ||||
|                                                               "mousekeys-max-speed"); | ||||
|   kbd_a11y_settings.mousekeys_accel_time = g_settings_get_int (priv->a11y_settings, | ||||
|   kbd_a11y_settings.mousekeys_accel_time = g_settings_get_int (priv->keyboard_a11y_settings, | ||||
|                                                                "mousekeys-accel-time"); | ||||
|  | ||||
|   clutter_device_manager_set_kbd_a11y_settings (priv->device_manager, &kbd_a11y_settings); | ||||
| @@ -1256,25 +1258,121 @@ on_keyboard_a11y_settings_changed (ClutterDeviceManager    *device_manager, | ||||
|   MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   guint i; | ||||
|  | ||||
|   for (i = 0; i < G_N_ELEMENTS (settings_flags_pair); i++) | ||||
|   for (i = 0; i < G_N_ELEMENTS (keyboard_a11y_settings_flags_pair); i++) | ||||
|     { | ||||
|       if (settings_flags_pair[i].flag & what_changed) | ||||
|         g_settings_set_boolean (priv->a11y_settings, | ||||
|                                 settings_flags_pair[i].name, | ||||
|                                 (new_flags & settings_flags_pair[i].flag) ? TRUE : FALSE); | ||||
|       if (keyboard_a11y_settings_flags_pair[i].flag & what_changed) | ||||
|         g_settings_set_boolean (priv->keyboard_a11y_settings, | ||||
|                                 keyboard_a11y_settings_flags_pair[i].name, | ||||
|                                 (new_flags & keyboard_a11y_settings_flags_pair[i].flag) ? TRUE : FALSE); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_a11y_settings_changed (GSettings  *settings, | ||||
|                                   const char *key, | ||||
|                                   gpointer    user_data) | ||||
| meta_input_keyboard_a11y_settings_changed (GSettings  *settings, | ||||
|                                            const char *key, | ||||
|                                            gpointer    user_data) | ||||
| { | ||||
|   MetaInputSettings *input_settings = META_INPUT_SETTINGS (user_data); | ||||
|  | ||||
|   load_keyboard_a11y_settings (input_settings, NULL); | ||||
| } | ||||
|  | ||||
| struct _pointer_a11y_settings_flags_pair { | ||||
|   const char *name; | ||||
|   ClutterPointerA11yFlags flag; | ||||
| } pointer_a11y_settings_flags_pair[] = { | ||||
|   { "secondary-click-enabled", CLUTTER_A11Y_SECONDARY_CLICK_ENABLED }, | ||||
|   { "dwell-click-enabled",     CLUTTER_A11Y_DWELL_ENABLED }, | ||||
| }; | ||||
|  | ||||
| static ClutterPointerA11yDwellDirection | ||||
| pointer_a11y_dwell_direction_from_setting (MetaInputSettings *input_settings, | ||||
|                                            const char        *key) | ||||
| { | ||||
|   MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   GDesktopMouseDwellDirection dwell_gesture_direction; | ||||
|  | ||||
|   dwell_gesture_direction = g_settings_get_enum (priv->mouse_a11y_settings, key); | ||||
|   switch (dwell_gesture_direction) | ||||
|     { | ||||
|     case G_DESKTOP_MOUSE_DWELL_DIRECTION_LEFT: | ||||
|       return CLUTTER_A11Y_DWELL_DIRECTION_LEFT; | ||||
|       break; | ||||
|     case G_DESKTOP_MOUSE_DWELL_DIRECTION_RIGHT: | ||||
|       return CLUTTER_A11Y_DWELL_DIRECTION_RIGHT; | ||||
|       break; | ||||
|     case G_DESKTOP_MOUSE_DWELL_DIRECTION_UP: | ||||
|       return CLUTTER_A11Y_DWELL_DIRECTION_UP; | ||||
|       break; | ||||
|     case G_DESKTOP_MOUSE_DWELL_DIRECTION_DOWN: | ||||
|       return CLUTTER_A11Y_DWELL_DIRECTION_DOWN; | ||||
|       break; | ||||
|     default: | ||||
|       break; | ||||
|     } | ||||
|   return CLUTTER_A11Y_DWELL_DIRECTION_NONE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| load_pointer_a11y_settings (MetaInputSettings  *input_settings, | ||||
|                             ClutterInputDevice *device) | ||||
| { | ||||
|   MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   ClutterPointerA11ySettings pointer_a11y_settings; | ||||
|   ClutterInputDevice *core_pointer; | ||||
|   GDesktopMouseDwellMode dwell_mode; | ||||
|  | ||||
|   guint i; | ||||
|  | ||||
|   core_pointer = clutter_device_manager_get_core_device (priv->device_manager, CLUTTER_POINTER_DEVICE); | ||||
|   if (device && device != core_pointer) | ||||
|     return; | ||||
|  | ||||
|   clutter_device_manager_get_pointer_a11y_settings (priv->device_manager, &pointer_a11y_settings); | ||||
|   pointer_a11y_settings.controls = 0; | ||||
|   for (i = 0; i < G_N_ELEMENTS (pointer_a11y_settings_flags_pair); i++) | ||||
|     { | ||||
|       if (g_settings_get_boolean (priv->mouse_a11y_settings, pointer_a11y_settings_flags_pair[i].name)) | ||||
|         pointer_a11y_settings.controls |= pointer_a11y_settings_flags_pair[i].flag; | ||||
|     } | ||||
|  | ||||
|   /* "secondary-click-time" is expressed in seconds */ | ||||
|   pointer_a11y_settings.secondary_click_delay = | ||||
|     (1000 * g_settings_get_double (priv->mouse_a11y_settings, "secondary-click-time")); | ||||
|   /* "dwell-time" is expressed in seconds */ | ||||
|   pointer_a11y_settings.dwell_delay = | ||||
|     (1000 * g_settings_get_double (priv->mouse_a11y_settings, "dwell-time")); | ||||
|   pointer_a11y_settings.dwell_threshold = g_settings_get_int (priv->mouse_a11y_settings, | ||||
|                                                               "dwell-threshold"); | ||||
|  | ||||
|   dwell_mode = g_settings_get_enum (priv->mouse_a11y_settings, "dwell-mode"); | ||||
|   if (dwell_mode == G_DESKTOP_MOUSE_DWELL_MODE_WINDOW) | ||||
|     pointer_a11y_settings.dwell_mode = CLUTTER_A11Y_DWELL_MODE_WINDOW; | ||||
|   else | ||||
|     pointer_a11y_settings.dwell_mode = CLUTTER_A11Y_DWELL_MODE_GESTURE; | ||||
|  | ||||
|   pointer_a11y_settings.dwell_gesture_single = | ||||
|     pointer_a11y_dwell_direction_from_setting (input_settings, "dwell-gesture-single"); | ||||
|   pointer_a11y_settings.dwell_gesture_double = | ||||
|     pointer_a11y_dwell_direction_from_setting (input_settings, "dwell-gesture-double"); | ||||
|   pointer_a11y_settings.dwell_gesture_drag = | ||||
|     pointer_a11y_dwell_direction_from_setting (input_settings, "dwell-gesture-drag"); | ||||
|   pointer_a11y_settings.dwell_gesture_secondary = | ||||
|     pointer_a11y_dwell_direction_from_setting (input_settings, "dwell-gesture-secondary"); | ||||
|  | ||||
|   clutter_device_manager_set_pointer_a11y_settings (priv->device_manager, &pointer_a11y_settings); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_mouse_a11y_settings_changed (GSettings  *settings, | ||||
|                                         const char *key, | ||||
|                                         gpointer    user_data) | ||||
| { | ||||
|   MetaInputSettings *input_settings = META_INPUT_SETTINGS (user_data); | ||||
|  | ||||
|   load_pointer_a11y_settings (input_settings, NULL); | ||||
| } | ||||
|  | ||||
| static GSettings * | ||||
| lookup_device_settings (ClutterInputDevice *device) | ||||
| { | ||||
| @@ -1556,6 +1654,7 @@ apply_device_settings (MetaInputSettings  *input_settings, | ||||
|                                 priv->trackball_settings, | ||||
|                                 device); | ||||
|   load_keyboard_a11y_settings (input_settings, device); | ||||
|   load_pointer_a11y_settings (input_settings, device); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -1856,12 +1955,16 @@ meta_input_settings_init (MetaInputSettings *settings) | ||||
|                    clutter_settings_get_default(), "double-click-time", | ||||
|                    G_SETTINGS_BIND_GET); | ||||
|  | ||||
|   priv->a11y_settings = g_settings_new ("org.gnome.desktop.a11y.keyboard"); | ||||
|   g_signal_connect (priv->a11y_settings, "changed", | ||||
|                     G_CALLBACK (meta_input_a11y_settings_changed), settings); | ||||
|   priv->keyboard_a11y_settings = g_settings_new ("org.gnome.desktop.a11y.keyboard"); | ||||
|   g_signal_connect (priv->keyboard_a11y_settings, "changed", | ||||
|                     G_CALLBACK (meta_input_keyboard_a11y_settings_changed), settings); | ||||
|   g_signal_connect (priv->device_manager, "kbd-a11y-flags-changed", | ||||
|                     G_CALLBACK (on_keyboard_a11y_settings_changed), settings); | ||||
|  | ||||
|   priv->mouse_a11y_settings = g_settings_new ("org.gnome.desktop.a11y.mouse"); | ||||
|   g_signal_connect (priv->mouse_a11y_settings, "changed", | ||||
|                     G_CALLBACK (meta_input_mouse_a11y_settings_changed), settings); | ||||
|  | ||||
|   priv->mappable_devices = | ||||
|     g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) device_mapping_info_free); | ||||
|  | ||||
|   | ||||
| @@ -242,6 +242,7 @@ foreach_crtc (MetaMonitor         *monitor, | ||||
|   ForeachCrtcData *data = user_data; | ||||
|  | ||||
|   data->func (data->logical_monitor, | ||||
|               monitor_crtc_mode->output, | ||||
|               meta_output_get_assigned_crtc (monitor_crtc_mode->output), | ||||
|               data->user_data); | ||||
|  | ||||
|   | ||||
| @@ -63,6 +63,7 @@ G_DECLARE_FINAL_TYPE (MetaLogicalMonitor, meta_logical_monitor, | ||||
|                       GObject) | ||||
|  | ||||
| typedef void (* MetaLogicalMonitorCrtcFunc) (MetaLogicalMonitor *logical_monitor, | ||||
|                                              MetaOutput         *output, | ||||
|                                              MetaCrtc           *crtc, | ||||
|                                              gpointer            user_data); | ||||
|  | ||||
|   | ||||
| @@ -47,8 +47,6 @@ struct _MetaMonitorManagerDummy | ||||
| { | ||||
|   MetaMonitorManager parent_instance; | ||||
|  | ||||
|   MetaGpu *gpu; | ||||
|  | ||||
|   gboolean is_transform_handled; | ||||
| }; | ||||
|  | ||||
| @@ -98,6 +96,14 @@ create_mode (CrtcModeSpec *spec, | ||||
|   return mode; | ||||
| } | ||||
|  | ||||
| static MetaGpu * | ||||
| get_gpu (MetaMonitorManager *manager) | ||||
| { | ||||
|   MetaBackend *backend = meta_monitor_manager_get_backend (manager); | ||||
|  | ||||
|   return META_GPU (meta_backend_get_gpus (backend)->data); | ||||
| } | ||||
|  | ||||
| static void | ||||
| append_monitor (MetaMonitorManager *manager, | ||||
|                 GList             **modes, | ||||
| @@ -105,8 +111,7 @@ append_monitor (MetaMonitorManager *manager, | ||||
|                 GList             **outputs, | ||||
|                 float               scale) | ||||
| { | ||||
|   MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager); | ||||
|   MetaGpu *gpu = manager_dummy->gpu; | ||||
|   MetaGpu *gpu = get_gpu (manager); | ||||
|   CrtcModeSpec default_specs[] = { | ||||
|     { | ||||
|       .width = 800, | ||||
| @@ -246,8 +251,7 @@ append_tiled_monitor (MetaMonitorManager *manager, | ||||
|                       GList             **outputs, | ||||
|                       int                 scale) | ||||
| { | ||||
|   MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager); | ||||
|   MetaGpu *gpu = manager_dummy->gpu; | ||||
|   MetaGpu *gpu = get_gpu (manager); | ||||
|   CrtcModeSpec mode_specs[] = { | ||||
|     { | ||||
|       .width = 800, | ||||
| @@ -371,8 +375,7 @@ meta_output_dummy_notify_destroy (MetaOutput *output) | ||||
| static void | ||||
| meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager) | ||||
| { | ||||
|   MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager); | ||||
|   MetaGpu *gpu = manager_dummy->gpu; | ||||
|   MetaGpu *gpu = get_gpu (manager); | ||||
|   unsigned int num_monitors = 1; | ||||
|   float *monitor_scales = NULL; | ||||
|   const char *num_monitors_str; | ||||
| @@ -495,7 +498,6 @@ apply_crtc_assignments (MetaMonitorManager *manager, | ||||
|                         MetaOutputInfo    **outputs, | ||||
|                         unsigned int        n_outputs) | ||||
| { | ||||
|   MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager); | ||||
|   GList *l; | ||||
|   unsigned i; | ||||
|  | ||||
| @@ -560,7 +562,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, | ||||
|     } | ||||
|  | ||||
|   /* Disable CRTCs not mentioned in the list */ | ||||
|   for (l = meta_gpu_get_crtcs (manager_dummy->gpu); l; l = l->next) | ||||
|   for (l = meta_gpu_get_crtcs (get_gpu (manager)); l; l = l->next) | ||||
|     { | ||||
|       MetaCrtc *crtc = l->data; | ||||
|  | ||||
| @@ -580,7 +582,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, | ||||
|     } | ||||
|  | ||||
|   /* Disable outputs not mentioned in the list */ | ||||
|   for (l = meta_gpu_get_outputs (manager_dummy->gpu); l; l = l->next) | ||||
|   for (l = meta_gpu_get_outputs (get_gpu (manager)); l; l = l->next) | ||||
|     { | ||||
|       MetaOutput *output = l->data; | ||||
|  | ||||
| @@ -772,11 +774,32 @@ meta_monitor_manager_dummy_get_default_layout_mode (MetaMonitorManager *manager) | ||||
|     return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_dummy_constructed (GObject *object) | ||||
| { | ||||
|   MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (object); | ||||
|   const char *nested_offscreen_transform; | ||||
|   GObjectClass *parent_object_class = | ||||
|     G_OBJECT_CLASS (meta_monitor_manager_dummy_parent_class); | ||||
|  | ||||
|   parent_object_class->constructed (object); | ||||
|  | ||||
|   nested_offscreen_transform = | ||||
|     g_getenv ("MUTTER_DEBUG_NESTED_OFFSCREEN_TRANSFORM"); | ||||
|   if (g_strcmp0 (nested_offscreen_transform, "1") == 0) | ||||
|     manager_dummy->is_transform_handled = FALSE; | ||||
|   else | ||||
|     manager_dummy->is_transform_handled = TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass); | ||||
|  | ||||
|   object_class->constructed = meta_monitor_manager_dummy_constructed; | ||||
|  | ||||
|   manager_class->ensure_initial_config = meta_monitor_manager_dummy_ensure_initial_config; | ||||
|   manager_class->apply_monitors_config = meta_monitor_manager_dummy_apply_monitors_config; | ||||
|   manager_class->is_transform_handled = meta_monitor_manager_dummy_is_transform_handled; | ||||
| @@ -790,27 +813,14 @@ meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass) | ||||
| static void | ||||
| meta_monitor_manager_dummy_init (MetaMonitorManagerDummy *manager_dummy) | ||||
| { | ||||
|   MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_dummy); | ||||
|   const char *nested_offscreen_transform; | ||||
|  | ||||
|   nested_offscreen_transform = | ||||
|     g_getenv ("MUTTER_DEBUG_NESTED_OFFSCREEN_TRANSFORM"); | ||||
|   if (g_strcmp0 (nested_offscreen_transform, "1") == 0) | ||||
|     manager_dummy->is_transform_handled = FALSE; | ||||
|   else | ||||
|     manager_dummy->is_transform_handled = TRUE; | ||||
|  | ||||
|   manager_dummy->gpu = g_object_new (META_TYPE_GPU_DUMMY, | ||||
|                                      "monitor-manager", manager, | ||||
|                                      NULL); | ||||
|   meta_monitor_manager_add_gpu (manager, manager_dummy->gpu); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_gpu_dummy_read_current (MetaGpu  *gpu, | ||||
|                              GError  **error) | ||||
| { | ||||
|   MetaMonitorManager *manager = meta_gpu_get_monitor_manager (gpu); | ||||
|   MetaBackend *backend = meta_gpu_get_backend (gpu); | ||||
|   MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend); | ||||
|  | ||||
|   meta_monitor_manager_dummy_read_current (manager); | ||||
|  | ||||
|   | ||||
| @@ -121,8 +121,6 @@ struct _MetaMonitorManager | ||||
|   int screen_width; | ||||
|   int screen_height; | ||||
|  | ||||
|   GList *gpus; | ||||
|  | ||||
|   GList *monitors; | ||||
|  | ||||
|   GList *logical_monitors; | ||||
| @@ -248,6 +246,7 @@ struct _MetaMonitorManagerClass | ||||
|   MetaLogicalMonitorLayoutMode (*get_default_layout_mode) (MetaMonitorManager *); | ||||
| }; | ||||
|  | ||||
| META_EXPORT_TEST | ||||
| MetaBackend *       meta_monitor_manager_get_backend (MetaMonitorManager *manager); | ||||
|  | ||||
| void                meta_monitor_manager_setup (MetaMonitorManager *manager); | ||||
| @@ -295,12 +294,6 @@ MetaMonitor *       meta_monitor_manager_get_monitor_from_connector (MetaMonitor | ||||
| META_EXPORT_TEST | ||||
| GList *             meta_monitor_manager_get_monitors      (MetaMonitorManager *manager); | ||||
|  | ||||
| META_EXPORT_TEST | ||||
| void                meta_monitor_manager_add_gpu (MetaMonitorManager *manager, | ||||
|                                                   MetaGpu            *gpu); | ||||
| META_EXPORT_TEST | ||||
| GList *             meta_monitor_manager_get_gpus (MetaMonitorManager *manager); | ||||
|  | ||||
| void                meta_monitor_manager_get_screen_size   (MetaMonitorManager *manager, | ||||
|                                                             int                *width, | ||||
|                                                             int                *height); | ||||
|   | ||||
| @@ -511,9 +511,11 @@ meta_monitor_manager_apply_monitors_config (MetaMonitorManager      *manager, | ||||
| gboolean | ||||
| meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager) | ||||
| { | ||||
|   GList *gpus; | ||||
|   GList *l; | ||||
|  | ||||
|   for (l = manager->gpus; l; l = l->next) | ||||
|   gpus = meta_backend_get_gpus (manager->backend); | ||||
|   for (l = gpus; l; l = l->next) | ||||
|     { | ||||
|       MetaGpu *gpu = l->data; | ||||
|  | ||||
| @@ -794,7 +796,6 @@ meta_monitor_manager_finalize (GObject *object) | ||||
| { | ||||
|   MetaMonitorManager *manager = META_MONITOR_MANAGER (object); | ||||
|  | ||||
|   g_list_free_full (manager->gpus, g_object_unref); | ||||
|   g_list_free_full (manager->logical_monitors, g_object_unref); | ||||
|  | ||||
|   g_signal_handler_disconnect (manager->backend, | ||||
| @@ -1063,10 +1064,12 @@ static GList * | ||||
| combine_gpu_lists (MetaMonitorManager    *manager, | ||||
|                    GList              * (*list_getter) (MetaGpu *gpu)) | ||||
| { | ||||
|   GList *gpus; | ||||
|   GList *list = NULL; | ||||
|   GList *l; | ||||
|  | ||||
|   for (l = manager->gpus; l; l = l->next) | ||||
|   gpus = meta_backend_get_gpus (manager->backend); | ||||
|   for (l = gpus; l; l = l->next) | ||||
|     { | ||||
|       MetaGpu *gpu = l->data; | ||||
|  | ||||
| @@ -2676,26 +2679,6 @@ meta_monitor_manager_get_monitors (MetaMonitorManager *manager) | ||||
|   return manager->monitors; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_monitor_manager_add_gpu: | ||||
|  * @manager: A #MetaMonitorManager object | ||||
|  * | ||||
|  * Should only be called by subclasses. Adds a #MetaGpu to the internal list of | ||||
|  * GPU's. | ||||
|  */ | ||||
| void | ||||
| meta_monitor_manager_add_gpu (MetaMonitorManager *manager, | ||||
|                               MetaGpu            *gpu) | ||||
| { | ||||
|   manager->gpus = g_list_append (manager->gpus, gpu); | ||||
| } | ||||
|  | ||||
| GList * | ||||
| meta_monitor_manager_get_gpus (MetaMonitorManager *manager) | ||||
| { | ||||
|   return manager->gpus; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_monitor_manager_get_screen_size (MetaMonitorManager *manager, | ||||
|                                       int                *width, | ||||
| @@ -2717,6 +2700,7 @@ meta_monitor_manager_get_power_save_mode (MetaMonitorManager *manager) | ||||
| static void | ||||
| rebuild_monitors (MetaMonitorManager *manager) | ||||
| { | ||||
|   GList *gpus; | ||||
|   GList *l; | ||||
|  | ||||
|   if (manager->monitors) | ||||
| @@ -2725,7 +2709,8 @@ rebuild_monitors (MetaMonitorManager *manager) | ||||
|       manager->monitors = NULL; | ||||
|     } | ||||
|  | ||||
|   for (l = manager->gpus; l; l = l->next) | ||||
|   gpus = meta_backend_get_gpus (manager->backend); | ||||
|   for (l = gpus; l; l = l->next) | ||||
|     { | ||||
|       MetaGpu *gpu = l->data; | ||||
|       GList *k; | ||||
| @@ -2740,7 +2725,7 @@ rebuild_monitors (MetaMonitorManager *manager) | ||||
|                 { | ||||
|                   MetaMonitorTiled *monitor_tiled; | ||||
|  | ||||
|                   monitor_tiled = meta_monitor_tiled_new (gpu, output); | ||||
|                   monitor_tiled = meta_monitor_tiled_new (gpu, manager, output); | ||||
|                   manager->monitors = g_list_append (manager->monitors, | ||||
|                                                      monitor_tiled); | ||||
|                 } | ||||
| @@ -2797,7 +2782,7 @@ meta_monitor_manager_real_read_current_state (MetaMonitorManager *manager) | ||||
|  | ||||
|   manager->serial++; | ||||
|  | ||||
|   for (l = manager->gpus; l; l = l->next) | ||||
|   for (l = meta_backend_get_gpus (manager->backend); l; l = l->next) | ||||
|     { | ||||
|       MetaGpu *gpu = l->data; | ||||
|       GError *error = NULL; | ||||
|   | ||||
| @@ -34,6 +34,7 @@ enum _MetaMonitorTransform | ||||
|   META_MONITOR_TRANSFORM_FLIPPED_180, | ||||
|   META_MONITOR_TRANSFORM_FLIPPED_270, | ||||
| }; | ||||
| #define META_MONITOR_N_TRANSFORMS (META_MONITOR_TRANSFORM_FLIPPED_270 + 1) | ||||
|  | ||||
| /* Returns true if transform causes width and height to be inverted | ||||
|    This is true for the odd transforms in the enum */ | ||||
|   | ||||
| @@ -90,6 +90,8 @@ struct _MetaMonitorTiled | ||||
| { | ||||
|   MetaMonitor parent; | ||||
|  | ||||
|   MetaMonitorManager *monitor_manager; | ||||
|  | ||||
|   uint32_t tile_group_id; | ||||
|  | ||||
|   /* The tile (0, 0) output. */ | ||||
| @@ -1176,10 +1178,10 @@ meta_monitor_tiled_generate_modes (MetaMonitorTiled *monitor_tiled) | ||||
| } | ||||
|  | ||||
| MetaMonitorTiled * | ||||
| meta_monitor_tiled_new (MetaGpu    *gpu, | ||||
|                         MetaOutput *output) | ||||
| meta_monitor_tiled_new (MetaGpu            *gpu, | ||||
|                         MetaMonitorManager *monitor_manager, | ||||
|                         MetaOutput         *output) | ||||
| { | ||||
|   MetaMonitorManager *monitor_manager; | ||||
|   MetaMonitorTiled *monitor_tiled; | ||||
|   MetaMonitor *monitor; | ||||
|   MetaMonitorPrivate *monitor_priv; | ||||
| @@ -1200,7 +1202,7 @@ meta_monitor_tiled_new (MetaGpu    *gpu, | ||||
|  | ||||
|   meta_monitor_generate_spec (monitor); | ||||
|  | ||||
|   monitor_manager = meta_gpu_get_monitor_manager (gpu); | ||||
|   monitor_tiled->monitor_manager = monitor_manager; | ||||
|   meta_monitor_manager_tiled_monitor_added (monitor_manager, | ||||
|                                             META_MONITOR (monitor_tiled)); | ||||
|  | ||||
| @@ -1286,14 +1288,10 @@ meta_monitor_tiled_calculate_crtc_pos (MetaMonitor          *monitor, | ||||
| static void | ||||
| meta_monitor_tiled_finalize (GObject *object) | ||||
| { | ||||
|   MetaMonitor *monitor = META_MONITOR (object); | ||||
|   MetaMonitorPrivate *monitor_priv = | ||||
|     meta_monitor_get_instance_private (monitor); | ||||
|   MetaMonitorManager *monitor_manager; | ||||
|   MetaMonitorTiled *monitor_tiled = META_MONITOR_TILED (object); | ||||
|  | ||||
|   monitor_manager = meta_gpu_get_monitor_manager (monitor_priv->gpu); | ||||
|   meta_monitor_manager_tiled_monitor_removed (monitor_manager, | ||||
|                                               monitor); | ||||
|   meta_monitor_manager_tiled_monitor_removed (monitor_tiled->monitor_manager, | ||||
|                                               META_MONITOR (monitor_tiled)); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_monitor_tiled_parent_class)->finalize (object); | ||||
| } | ||||
|   | ||||
| @@ -96,8 +96,9 @@ G_DECLARE_FINAL_TYPE (MetaMonitorTiled, meta_monitor_tiled, | ||||
|                       MetaMonitor) | ||||
|  | ||||
| META_EXPORT_TEST | ||||
| MetaMonitorTiled * meta_monitor_tiled_new (MetaGpu    *gpu, | ||||
|                                            MetaOutput *output); | ||||
| MetaMonitorTiled * meta_monitor_tiled_new (MetaGpu            *gpu, | ||||
|                                            MetaMonitorManager *monitor_manager, | ||||
|                                            MetaOutput         *output); | ||||
|  | ||||
| META_EXPORT_TEST | ||||
| MetaMonitorNormal * meta_monitor_normal_new (MetaGpu    *gpu, | ||||
|   | ||||
							
								
								
									
										206
									
								
								src/backends/meta-profiler.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								src/backends/meta-profiler.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,206 @@ | ||||
| /* | ||||
|  * Copyright (C) 2019 Endless, 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. | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "src/backends/meta-profiler.h" | ||||
|  | ||||
| #include <glib-unix.h> | ||||
| #include <glib/gi18n.h> | ||||
| #include <gio/gunixfdlist.h> | ||||
|  | ||||
| #include "cogl/cogl-trace.h" | ||||
|  | ||||
| #define META_SYSPROF_PROFILER_DBUS_PATH "/org/gnome/Sysprof3/Profiler" | ||||
|  | ||||
| struct _MetaProfiler | ||||
| { | ||||
|   MetaDBusSysprof3ProfilerSkeleton parent_instance; | ||||
|  | ||||
|   GDBusConnection *connection; | ||||
|   GCancellable *cancellable; | ||||
|  | ||||
|   gboolean running; | ||||
| }; | ||||
|  | ||||
| static void | ||||
| meta_sysprof_capturer_init_iface (MetaDBusSysprof3ProfilerIface *iface); | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (MetaProfiler, | ||||
|                          meta_profiler, | ||||
|                          META_DBUS_TYPE_SYSPROF3_PROFILER_SKELETON, | ||||
|                          G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_SYSPROF3_PROFILER, | ||||
|                                                 meta_sysprof_capturer_init_iface)) | ||||
|  | ||||
| static gboolean | ||||
| handle_start (MetaDBusSysprof3Profiler *dbus_profiler, | ||||
|               GDBusMethodInvocation    *invocation, | ||||
|               GVariant                 *options, | ||||
|               GVariant                 *fd_variant) | ||||
| { | ||||
|   MetaProfiler *profiler = META_PROFILER (dbus_profiler); | ||||
|   GMainContext *main_context = g_main_context_default (); | ||||
|   GDBusMessage *message; | ||||
|   GUnixFDList *fd_list; | ||||
|   const char *group_name; | ||||
|   int position; | ||||
|   int fd = -1; | ||||
|  | ||||
|   if (profiler->running) | ||||
|     { | ||||
|       g_dbus_method_invocation_return_error (invocation, | ||||
|                                              G_DBUS_ERROR, | ||||
|                                              G_DBUS_ERROR_FAILED, | ||||
|                                              "Profiler already running"); | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   g_variant_get (fd_variant, "h", &position); | ||||
|  | ||||
|   message = g_dbus_method_invocation_get_message (invocation); | ||||
|   fd_list = g_dbus_message_get_unix_fd_list (message); | ||||
|   if (fd_list) | ||||
|     fd = g_unix_fd_list_get (fd_list, position, NULL); | ||||
|  | ||||
|   /* Translators: this string will appear in Sysprof */ | ||||
|   group_name = _("Compositor"); | ||||
|  | ||||
|   if (fd != -1) | ||||
|     { | ||||
|       cogl_set_tracing_enabled_on_thread_with_fd (main_context, | ||||
|                                                   group_name, | ||||
|                                                   fd); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       cogl_set_tracing_enabled_on_thread (main_context, | ||||
|                                           group_name, | ||||
|                                           "mutter-profile.syscap"); | ||||
|     } | ||||
|  | ||||
|   profiler->running = TRUE; | ||||
|  | ||||
|   g_debug ("Profiler running"); | ||||
|  | ||||
|   meta_dbus_sysprof3_profiler_complete_start (dbus_profiler, invocation); | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| handle_stop (MetaDBusSysprof3Profiler *dbus_profiler, | ||||
|              GDBusMethodInvocation    *invocation) | ||||
| { | ||||
|   MetaProfiler *profiler = META_PROFILER (dbus_profiler); | ||||
|  | ||||
|   if (!profiler->running) | ||||
|     { | ||||
|       g_dbus_method_invocation_return_error (invocation, | ||||
|                                              G_DBUS_ERROR, | ||||
|                                              G_DBUS_ERROR_FAILED, | ||||
|                                              "Profiler not running"); | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   cogl_set_tracing_disabled_on_thread (g_main_context_default ()); | ||||
|   profiler->running = FALSE; | ||||
|  | ||||
|   g_debug ("Stopping profiler"); | ||||
|  | ||||
|   meta_dbus_sysprof3_profiler_complete_stop (dbus_profiler, invocation); | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_sysprof_capturer_init_iface (MetaDBusSysprof3ProfilerIface *iface) | ||||
| { | ||||
|   iface->handle_start = handle_start; | ||||
|   iface->handle_stop = handle_stop; | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_bus_acquired_cb (GObject      *source, | ||||
|                     GAsyncResult *result, | ||||
|                     gpointer      user_data) | ||||
| { | ||||
|   g_autoptr (GDBusConnection) connection = NULL; | ||||
|   GDBusInterfaceSkeleton *interface_skeleton; | ||||
|   g_autoptr (GError) error = NULL; | ||||
|   MetaProfiler *profiler; | ||||
|  | ||||
|   connection = g_bus_get_finish (result, &error); | ||||
|  | ||||
|   if (error) | ||||
|     { | ||||
|       if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) | ||||
|         g_warning ("Failed to get session bus: %s\n", error->message); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   profiler = META_PROFILER (user_data); | ||||
|   interface_skeleton = G_DBUS_INTERFACE_SKELETON (profiler); | ||||
|  | ||||
|   if (!g_dbus_interface_skeleton_export (interface_skeleton, | ||||
|                                          connection, | ||||
|                                          META_SYSPROF_PROFILER_DBUS_PATH, | ||||
|                                          &error)) | ||||
|     { | ||||
|       g_warning ("Failed to export profiler object: %s\n", error->message); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   profiler->connection = g_steal_pointer (&connection); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_profiler_finalize (GObject *object) | ||||
| { | ||||
|   MetaProfiler *self = (MetaProfiler *)object; | ||||
|  | ||||
|   g_cancellable_cancel (self->cancellable); | ||||
|  | ||||
|   g_clear_object (&self->cancellable); | ||||
|   g_clear_object (&self->connection); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_profiler_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_profiler_class_init (MetaProfilerClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->finalize = meta_profiler_finalize; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_profiler_init (MetaProfiler *self) | ||||
| { | ||||
|   self->cancellable = g_cancellable_new (); | ||||
|  | ||||
|   g_bus_get (G_BUS_TYPE_SESSION, | ||||
|              self->cancellable, | ||||
|              on_bus_acquired_cb, | ||||
|              self); | ||||
| } | ||||
|  | ||||
| MetaProfiler * | ||||
| meta_profiler_new (void) | ||||
| { | ||||
|   return g_object_new (META_TYPE_PROFILER, NULL); | ||||
| } | ||||
							
								
								
									
										41
									
								
								src/backends/meta-profiler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/backends/meta-profiler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
|  * Copyright (C) 2019 Endless, 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. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_PROFILER_H | ||||
| #define META_PROFILER_H | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| #include "meta-dbus-sysprof3-profiler.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define META_TYPE_PROFILER (meta_profiler_get_type()) | ||||
|  | ||||
| G_DECLARE_FINAL_TYPE (MetaProfiler, | ||||
|                       meta_profiler, | ||||
|                       META, | ||||
|                       PROFILER, | ||||
|                       MetaDBusSysprof3ProfilerSkeleton) | ||||
|  | ||||
| MetaProfiler * meta_profiler_new (void); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* META_PROFILER_H */ | ||||
| @@ -32,6 +32,7 @@ | ||||
| #include "backends/meta-monitor.h" | ||||
| #include "backends/meta-screen-cast-monitor-stream.h" | ||||
| #include "backends/meta-screen-cast-session.h" | ||||
| #include "backends/meta-stage-private.h" | ||||
| #include "clutter/clutter.h" | ||||
| #include "clutter/clutter-mutter.h" | ||||
| #include "core/boxes-private.h" | ||||
| @@ -42,8 +43,9 @@ struct _MetaScreenCastMonitorStreamSrc | ||||
|  | ||||
|   gboolean cursor_bitmap_invalid; | ||||
|  | ||||
|   gulong actors_painted_handler_id; | ||||
|   gulong paint_handler_id; | ||||
|   MetaStageWatch *paint_watch; | ||||
|   MetaStageWatch *after_paint_watch; | ||||
|  | ||||
|   gulong cursor_moved_handler_id; | ||||
|   gulong cursor_changed_handler_id; | ||||
| }; | ||||
| @@ -113,10 +115,11 @@ meta_screen_cast_monitor_stream_src_get_specs (MetaScreenCastStreamSrc *src, | ||||
| } | ||||
|  | ||||
| static void | ||||
| stage_painted (ClutterActor                   *actor, | ||||
|                MetaScreenCastMonitorStreamSrc *monitor_src) | ||||
| stage_painted (MetaStage        *stage, | ||||
|                ClutterStageView *view, | ||||
|                gpointer          user_data) | ||||
| { | ||||
|   MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src); | ||||
|   MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data); | ||||
|  | ||||
|   meta_screen_cast_stream_src_maybe_record_frame (src); | ||||
| } | ||||
| @@ -245,12 +248,28 @@ meta_screen_cast_monitor_stream_src_enable (MetaScreenCastStreamSrc *src) | ||||
|   MetaScreenCastMonitorStreamSrc *monitor_src = | ||||
|     META_SCREEN_CAST_MONITOR_STREAM_SRC (src); | ||||
|   MetaBackend *backend = get_backend (monitor_src); | ||||
|   MetaRenderer *renderer = meta_backend_get_renderer (backend); | ||||
|   MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); | ||||
|   MetaRendererView *view; | ||||
|   MetaMonitor *monitor; | ||||
|   MetaLogicalMonitor *logical_monitor; | ||||
|   MetaStage *meta_stage; | ||||
|   ClutterStageView *stage_view; | ||||
|   ClutterStage *stage; | ||||
|   MetaScreenCastStream *stream; | ||||
|  | ||||
|   stream = meta_screen_cast_stream_src_get_stream (src); | ||||
|   stage = get_stage (monitor_src); | ||||
|   meta_stage = META_STAGE (stage); | ||||
|   monitor = get_monitor (monitor_src); | ||||
|   logical_monitor = meta_monitor_get_logical_monitor (monitor); | ||||
|   view = meta_renderer_get_view_from_logical_monitor (renderer, | ||||
|                                                       logical_monitor); | ||||
|  | ||||
|   if (view) | ||||
|     stage_view = CLUTTER_STAGE_VIEW (view); | ||||
|   else | ||||
|     stage_view = NULL; | ||||
|  | ||||
|   switch (meta_screen_cast_stream_get_cursor_mode (stream)) | ||||
|     { | ||||
| @@ -265,17 +284,21 @@ meta_screen_cast_monitor_stream_src_enable (MetaScreenCastStreamSrc *src) | ||||
|                                 monitor_src); | ||||
|       /* Intentional fall-through */ | ||||
|     case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: | ||||
|       monitor_src->actors_painted_handler_id = | ||||
|         g_signal_connect (stage, "actors-painted", | ||||
|                           G_CALLBACK (stage_painted), | ||||
|                           monitor_src); | ||||
|       monitor_src->paint_watch = | ||||
|         meta_stage_watch_view (meta_stage, | ||||
|                                stage_view, | ||||
|                                META_STAGE_WATCH_AFTER_ACTOR_PAINT, | ||||
|                                stage_painted, | ||||
|                                monitor_src); | ||||
|       break; | ||||
|     case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: | ||||
|       inhibit_hw_cursor (monitor_src); | ||||
|       monitor_src->paint_handler_id = | ||||
|         g_signal_connect_after (stage, "paint", | ||||
|                                 G_CALLBACK (stage_painted), | ||||
|                                 monitor_src); | ||||
|       monitor_src->after_paint_watch = | ||||
|         meta_stage_watch_view (meta_stage, | ||||
|                                stage_view, | ||||
|                                META_STAGE_WATCH_AFTER_PAINT, | ||||
|                                stage_painted, | ||||
|                                monitor_src); | ||||
|       break; | ||||
|     } | ||||
|  | ||||
| @@ -290,21 +313,21 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src) | ||||
|   MetaBackend *backend = get_backend (monitor_src); | ||||
|   MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); | ||||
|   ClutterStage *stage; | ||||
|   MetaStage *meta_stage; | ||||
|  | ||||
|   stage = get_stage (monitor_src); | ||||
|   meta_stage = META_STAGE (stage); | ||||
|  | ||||
|   if (monitor_src->actors_painted_handler_id) | ||||
|   if (monitor_src->paint_watch) | ||||
|     { | ||||
|       g_signal_handler_disconnect (stage, | ||||
|                                    monitor_src->actors_painted_handler_id); | ||||
|       monitor_src->actors_painted_handler_id = 0; | ||||
|       meta_stage_remove_watch (meta_stage, monitor_src->paint_watch); | ||||
|       monitor_src->paint_watch = NULL; | ||||
|     } | ||||
|  | ||||
|   if (monitor_src->paint_handler_id) | ||||
|   if (monitor_src->after_paint_watch) | ||||
|     { | ||||
|       g_signal_handler_disconnect (stage, | ||||
|                                    monitor_src->paint_handler_id); | ||||
|       monitor_src->paint_handler_id = 0; | ||||
|       meta_stage_remove_watch (meta_stage, monitor_src->after_paint_watch); | ||||
|       monitor_src->after_paint_watch = NULL; | ||||
|       uninhibit_hw_cursor (monitor_src); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -113,7 +113,9 @@ meta_screen_cast_monitor_stream_new (MetaScreenCastSession     *session, | ||||
|                                      GError                   **error) | ||||
| { | ||||
|   MetaGpu *gpu = meta_monitor_get_gpu (monitor); | ||||
|   MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu); | ||||
|   MetaBackend *backend = meta_gpu_get_backend (gpu); | ||||
|   MetaMonitorManager *monitor_manager = | ||||
|     meta_backend_get_monitor_manager (backend); | ||||
|   MetaScreenCastMonitorStream *monitor_stream; | ||||
|  | ||||
|   if (!meta_monitor_is_active (monitor)) | ||||
|   | ||||
| @@ -66,6 +66,6 @@ void meta_settings_get_xwayland_grab_patterns (MetaSettings  *settings, | ||||
|                                                GPtrArray    **whitelist_patterns, | ||||
|                                                GPtrArray    **blacklist_patterns); | ||||
|  | ||||
| gboolean  meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings); | ||||
| gboolean meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings); | ||||
|  | ||||
| #endif /* META_SETTINGS_PRIVATE_H */ | ||||
|   | ||||
| @@ -404,7 +404,7 @@ meta_settings_get_xwayland_grab_patterns (MetaSettings  *settings, | ||||
| } | ||||
|  | ||||
| gboolean | ||||
|  meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings) | ||||
| meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings) | ||||
| { | ||||
|   return (settings->xwayland_allow_grabs); | ||||
| } | ||||
|   | ||||
| @@ -27,8 +27,21 @@ | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| typedef struct _MetaStageWatch MetaStageWatch; | ||||
| typedef struct _MetaOverlay    MetaOverlay; | ||||
|  | ||||
| typedef enum | ||||
| { | ||||
|   META_STAGE_WATCH_BEFORE_PAINT, | ||||
|   META_STAGE_WATCH_AFTER_ACTOR_PAINT, | ||||
|   META_STAGE_WATCH_AFTER_OVERLAY_PAINT, | ||||
|   META_STAGE_WATCH_AFTER_PAINT, | ||||
| } MetaStageWatchPhase; | ||||
|  | ||||
| typedef void (* MetaStageWatchFunc) (MetaStage        *stage, | ||||
|                                      ClutterStageView *view, | ||||
|                                      gpointer          user_data); | ||||
|  | ||||
| ClutterActor     *meta_stage_new                     (MetaBackend *backend); | ||||
|  | ||||
| MetaOverlay      *meta_stage_create_cursor_overlay   (MetaStage   *stage); | ||||
| @@ -43,6 +56,15 @@ void              meta_stage_update_cursor_overlay   (MetaStage   *stage, | ||||
| void meta_stage_set_active (MetaStage *stage, | ||||
|                             gboolean   is_active); | ||||
|  | ||||
| MetaStageWatch * meta_stage_watch_view (MetaStage           *stage, | ||||
|                                         ClutterStageView    *view, | ||||
|                                         MetaStageWatchPhase  watch_mode, | ||||
|                                         MetaStageWatchFunc   callback, | ||||
|                                         gpointer             user_data); | ||||
|  | ||||
| void meta_stage_remove_watch (MetaStage      *stage, | ||||
|                               MetaStageWatch *watch); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* META_STAGE_PRIVATE_H */ | ||||
|   | ||||
| @@ -30,6 +30,8 @@ | ||||
| #include "meta/meta-monitor-manager.h" | ||||
| #include "meta/util.h" | ||||
|  | ||||
| #define N_WATCH_MODES 4 | ||||
|  | ||||
| enum | ||||
| { | ||||
|   ACTORS_PAINTED, | ||||
| @@ -39,6 +41,13 @@ enum | ||||
|  | ||||
| static guint signals[N_SIGNALS]; | ||||
|  | ||||
| struct _MetaStageWatch | ||||
| { | ||||
|   ClutterStageView *view; | ||||
|   MetaStageWatchFunc callback; | ||||
|   gpointer user_data; | ||||
| }; | ||||
|  | ||||
| struct _MetaOverlay | ||||
| { | ||||
|   gboolean enabled; | ||||
| @@ -55,6 +64,9 @@ struct _MetaStage | ||||
| { | ||||
|   ClutterStage parent; | ||||
|  | ||||
|   GPtrArray *watchers[N_WATCH_MODES]; | ||||
|   ClutterStageView *current_view; | ||||
|  | ||||
|   GList *overlays; | ||||
|   gboolean is_active; | ||||
| }; | ||||
| @@ -135,6 +147,7 @@ meta_stage_finalize (GObject *object) | ||||
| { | ||||
|   MetaStage *stage = META_STAGE (object); | ||||
|   GList *l; | ||||
|   int i; | ||||
|  | ||||
|   l = stage->overlays; | ||||
|   while (l) | ||||
| @@ -143,9 +156,33 @@ meta_stage_finalize (GObject *object) | ||||
|       l = g_list_delete_link (l, l); | ||||
|     } | ||||
|  | ||||
|   for (i = 0; i < N_WATCH_MODES; i++) | ||||
|     g_clear_pointer (&stage->watchers[i], g_ptr_array_unref); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_stage_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| notify_watchers_for_mode (MetaStage           *stage, | ||||
|                           ClutterStageView    *view, | ||||
|                           MetaStageWatchPhase  watch_phase) | ||||
| { | ||||
|   GPtrArray *watchers; | ||||
|   int i; | ||||
|  | ||||
|   watchers = stage->watchers[watch_phase]; | ||||
|  | ||||
|   for (i = 0; i < watchers->len; i++) | ||||
|     { | ||||
|       MetaStageWatch *watch = g_ptr_array_index (watchers, i); | ||||
|  | ||||
|       if (watch->view && view != watch->view) | ||||
|         continue; | ||||
|  | ||||
|       watch->callback (stage, view, watch->user_data); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_stage_paint (ClutterActor *actor) | ||||
| { | ||||
| @@ -154,10 +191,30 @@ meta_stage_paint (ClutterActor *actor) | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor); | ||||
|  | ||||
|   notify_watchers_for_mode (stage, stage->current_view, | ||||
|                             META_STAGE_WATCH_AFTER_ACTOR_PAINT); | ||||
|  | ||||
|   g_signal_emit (stage, signals[ACTORS_PAINTED], 0); | ||||
|  | ||||
|   for (l = stage->overlays; l; l = l->next) | ||||
|     meta_overlay_paint (l->data); | ||||
|  | ||||
|   notify_watchers_for_mode (stage, stage->current_view, | ||||
|                             META_STAGE_WATCH_AFTER_OVERLAY_PAINT); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_stage_paint_view (ClutterStage     *stage, | ||||
|                        ClutterStageView *view) | ||||
| { | ||||
|   MetaStage *meta_stage = META_STAGE (stage); | ||||
|  | ||||
|   notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_BEFORE_PAINT); | ||||
|  | ||||
|   meta_stage->current_view = view; | ||||
|   CLUTTER_STAGE_CLASS (meta_stage_parent_class)->paint_view (stage, view); | ||||
|  | ||||
|   notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_AFTER_PAINT); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -202,6 +259,7 @@ meta_stage_class_init (MetaStageClass *klass) | ||||
|  | ||||
|   stage_class->activate = meta_stage_activate; | ||||
|   stage_class->deactivate = meta_stage_deactivate; | ||||
|   stage_class->paint_view = meta_stage_paint_view; | ||||
|  | ||||
|   signals[ACTORS_PAINTED] = g_signal_new ("actors-painted", | ||||
|                                           G_TYPE_FROM_CLASS (klass), | ||||
| @@ -214,7 +272,10 @@ meta_stage_class_init (MetaStageClass *klass) | ||||
| static void | ||||
| meta_stage_init (MetaStage *stage) | ||||
| { | ||||
|   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE); | ||||
|   int i; | ||||
|  | ||||
|   for (i = 0; i < N_WATCH_MODES; i++) | ||||
|     stage->watchers[i] = g_ptr_array_new_with_free_func (g_free); | ||||
| } | ||||
|  | ||||
| ClutterActor * | ||||
| @@ -346,3 +407,44 @@ meta_stage_set_active (MetaStage *stage, | ||||
|    */ | ||||
|   clutter_stage_event (CLUTTER_STAGE (stage), &event); | ||||
| } | ||||
|  | ||||
| MetaStageWatch * | ||||
| meta_stage_watch_view (MetaStage           *stage, | ||||
|                        ClutterStageView    *view, | ||||
|                        MetaStageWatchPhase  watch_phase, | ||||
|                        MetaStageWatchFunc   callback, | ||||
|                        gpointer             user_data) | ||||
| { | ||||
|   MetaStageWatch *watch; | ||||
|   GPtrArray *watchers; | ||||
|  | ||||
|   watch = g_new0 (MetaStageWatch, 1); | ||||
|   watch->view = view; | ||||
|   watch->callback = callback; | ||||
|   watch->user_data = user_data; | ||||
|  | ||||
|   watchers = stage->watchers[watch_phase]; | ||||
|   g_ptr_array_add (watchers, watch); | ||||
|  | ||||
|   return watch; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_stage_remove_watch (MetaStage      *stage, | ||||
|                          MetaStageWatch *watch) | ||||
| { | ||||
|   GPtrArray *watchers; | ||||
|   gboolean removed = FALSE; | ||||
|   int i; | ||||
|  | ||||
|   for (i = 0; i < N_WATCH_MODES; i++) | ||||
|     { | ||||
|       watchers = stage->watchers[i]; | ||||
|       removed = g_ptr_array_remove_fast (watchers, watch); | ||||
|  | ||||
|       if (removed) | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|   g_assert (removed); | ||||
| } | ||||
|   | ||||
							
								
								
									
										26
									
								
								src/backends/native/meta-backend-native-types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/backends/native/meta-backend-native-types.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| /* | ||||
|  * Copyright (C) 2019 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #ifndef META_BACKEND_NATIVE_TYPES_H | ||||
| #define META_BACKEND_NATIVE_TYPES_H | ||||
|  | ||||
| typedef struct _MetaBackendNative MetaBackendNative; | ||||
|  | ||||
| #endif /* META_BACKEND_NATIVE_TYPES_H */ | ||||
| @@ -51,6 +51,8 @@ | ||||
| #include "backends/native/meta-clutter-backend-native.h" | ||||
| #include "backends/native/meta-cursor-renderer-native.h" | ||||
| #include "backends/native/meta-input-settings-native.h" | ||||
| #include "backends/native/meta-kms.h" | ||||
| #include "backends/native/meta-kms-device.h" | ||||
| #include "backends/native/meta-launcher.h" | ||||
| #include "backends/native/meta-monitor-manager-kms.h" | ||||
| #include "backends/native/meta-renderer-native.h" | ||||
| @@ -62,14 +64,14 @@ | ||||
| struct _MetaBackendNative | ||||
| { | ||||
|   MetaBackend parent; | ||||
| }; | ||||
|  | ||||
| struct _MetaBackendNativePrivate | ||||
| { | ||||
|   MetaLauncher *launcher; | ||||
|   MetaUdev *udev; | ||||
|   MetaKms *kms; | ||||
|   MetaBarrierManagerNative *barrier_manager; | ||||
|  | ||||
|   guint udev_device_added_handler_id; | ||||
| }; | ||||
| typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate; | ||||
|  | ||||
| static GInitableIface *initable_parent_iface; | ||||
|  | ||||
| @@ -77,17 +79,23 @@ static void | ||||
| initable_iface_init (GInitableIface *initable_iface); | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND, | ||||
|                          G_ADD_PRIVATE (MetaBackendNative) | ||||
|                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, | ||||
|                                                 initable_iface_init)) | ||||
|  | ||||
| static void | ||||
| disconnect_udev_device_added_handler (MetaBackendNative *native); | ||||
|  | ||||
| static void | ||||
| meta_backend_native_finalize (GObject *object) | ||||
| { | ||||
|   MetaBackendNative *native = META_BACKEND_NATIVE (object); | ||||
|   MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native); | ||||
|  | ||||
|   meta_launcher_free (priv->launcher); | ||||
|   if (native->udev_device_added_handler_id) | ||||
|     disconnect_udev_device_added_handler (native); | ||||
|  | ||||
|   g_clear_object (&native->udev); | ||||
|   g_clear_object (&native->kms); | ||||
|   meta_launcher_free (native->launcher); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object); | ||||
| } | ||||
| @@ -99,10 +107,8 @@ constrain_to_barriers (ClutterInputDevice *device, | ||||
|                        float              *new_y) | ||||
| { | ||||
|   MetaBackendNative *native = META_BACKEND_NATIVE (meta_get_backend ()); | ||||
|   MetaBackendNativePrivate *priv = | ||||
|     meta_backend_native_get_instance_private (native); | ||||
|  | ||||
|   meta_barrier_manager_native_process (priv->barrier_manager, | ||||
|   meta_barrier_manager_native_process (native->barrier_manager, | ||||
|                                        device, | ||||
|                                        time, | ||||
|                                        new_x, new_y); | ||||
| @@ -376,13 +382,10 @@ static MetaRenderer * | ||||
| meta_backend_native_create_renderer (MetaBackend *backend, | ||||
|                                      GError     **error) | ||||
| { | ||||
|   MetaMonitorManager *monitor_manager = | ||||
|     meta_backend_get_monitor_manager (backend); | ||||
|   MetaMonitorManagerKms *monitor_manager_kms = | ||||
|     META_MONITOR_MANAGER_KMS (monitor_manager); | ||||
|   MetaBackendNative *native = META_BACKEND_NATIVE (backend); | ||||
|   MetaRendererNative *renderer_native; | ||||
|  | ||||
|   renderer_native = meta_renderer_native_new (monitor_manager_kms, error); | ||||
|   renderer_native = meta_renderer_native_new (native, error); | ||||
|   if (!renderer_native) | ||||
|     return NULL; | ||||
|  | ||||
| @@ -519,11 +522,142 @@ meta_backend_native_update_screen_size (MetaBackend *backend, | ||||
|   clutter_actor_set_size (stage, width, height); | ||||
| } | ||||
|  | ||||
| static MetaGpuKms * | ||||
| create_gpu_from_udev_device (MetaBackendNative  *native, | ||||
|                              GUdevDevice        *device, | ||||
|                              GError            **error) | ||||
| { | ||||
|   MetaKmsDeviceFlag flags = META_KMS_DEVICE_FLAG_NONE; | ||||
|   const char *device_path; | ||||
|   MetaKmsDevice *kms_device; | ||||
|  | ||||
|   if (meta_is_udev_device_platform_device (device)) | ||||
|     flags |= META_KMS_DEVICE_FLAG_PLATFORM_DEVICE; | ||||
|  | ||||
|   if (meta_is_udev_device_boot_vga (device)) | ||||
|     flags |= META_KMS_DEVICE_FLAG_BOOT_VGA; | ||||
|  | ||||
|   device_path = g_udev_device_get_device_file (device); | ||||
|  | ||||
|   kms_device = meta_kms_create_device (native->kms, device_path, flags, | ||||
|                                        error); | ||||
|   if (!kms_device) | ||||
|     return NULL; | ||||
|  | ||||
|   return meta_gpu_kms_new (native, kms_device, error); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_udev_device_added (MetaUdev          *udev, | ||||
|                       GUdevDevice       *device, | ||||
|                       MetaBackendNative *native) | ||||
| { | ||||
|   MetaBackend *backend = META_BACKEND (native); | ||||
|   g_autoptr (GError) error = NULL; | ||||
|   const char *device_path; | ||||
|   MetaGpuKms *new_gpu_kms; | ||||
|   GList *gpus, *l; | ||||
|  | ||||
|   if (!meta_udev_is_drm_device (udev, device)) | ||||
|     return; | ||||
|  | ||||
|   device_path = g_udev_device_get_device_file (device); | ||||
|  | ||||
|   gpus = meta_backend_get_gpus (backend);; | ||||
|   for (l = gpus; l; l = l->next) | ||||
|     { | ||||
|       MetaGpuKms *gpu_kms = l->data; | ||||
|  | ||||
|       if (!g_strcmp0 (device_path, meta_gpu_kms_get_file_path (gpu_kms))) | ||||
|         { | ||||
|           g_warning ("Failed to hotplug secondary gpu '%s': %s", | ||||
|                      device_path, "device already present"); | ||||
|           return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   new_gpu_kms = create_gpu_from_udev_device (native, device, &error); | ||||
|   if (!new_gpu_kms) | ||||
|     { | ||||
|       g_warning ("Failed to hotplug secondary gpu '%s': %s", | ||||
|                  device_path, error->message); | ||||
|       g_error_free (error); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   meta_backend_add_gpu (backend, META_GPU (new_gpu_kms)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| connect_udev_device_added_handler (MetaBackendNative *native) | ||||
| { | ||||
|   native->udev_device_added_handler_id = | ||||
|     g_signal_connect (native->udev, "device-added", | ||||
|                       G_CALLBACK (on_udev_device_added), native); | ||||
| } | ||||
|  | ||||
| static void | ||||
| disconnect_udev_device_added_handler (MetaBackendNative *native) | ||||
| { | ||||
|   g_signal_handler_disconnect (native->udev, | ||||
|                                native->udev_device_added_handler_id); | ||||
|   native->udev_device_added_handler_id = 0; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| init_gpus (MetaBackendNative  *native, | ||||
|            GError            **error) | ||||
| { | ||||
|   MetaBackend *backend = META_BACKEND (native); | ||||
|   MetaUdev *udev = meta_backend_native_get_udev (native); | ||||
|   GList *devices; | ||||
|   GList *l; | ||||
|  | ||||
|   devices = meta_udev_list_drm_devices (udev, error); | ||||
|   if (!devices) | ||||
|     return FALSE; | ||||
|  | ||||
|   for (l = devices; l; l = l->next) | ||||
|     { | ||||
|       GUdevDevice *device = l->data; | ||||
|       MetaGpuKms *gpu_kms; | ||||
|       GError *local_error = NULL; | ||||
|  | ||||
|       gpu_kms = create_gpu_from_udev_device (native, device, &local_error); | ||||
|  | ||||
|       if (!gpu_kms) | ||||
|         { | ||||
|           g_warning ("Failed to open gpu '%s': %s", | ||||
|                      g_udev_device_get_device_file (device), | ||||
|                      local_error->message); | ||||
|           g_clear_error (&local_error); | ||||
|           continue; | ||||
|         } | ||||
|  | ||||
|       meta_backend_add_gpu (backend, META_GPU (gpu_kms)); | ||||
|     } | ||||
|  | ||||
|   g_list_free_full (devices, g_object_unref); | ||||
|  | ||||
|   if (g_list_length (meta_backend_get_gpus (backend)) == 0) | ||||
|     { | ||||
|       g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, | ||||
|                    "No GPUs found"); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   connect_udev_device_added_handler (native); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_backend_native_initable_init (GInitable     *initable, | ||||
|                                    GCancellable  *cancellable, | ||||
|                                    GError       **error) | ||||
| { | ||||
|   MetaBackendNative *native = META_BACKEND_NATIVE (initable); | ||||
|  | ||||
|   if (!meta_is_stage_views_enabled ()) | ||||
|     { | ||||
|       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, | ||||
| @@ -531,6 +665,20 @@ meta_backend_native_initable_init (GInitable     *initable, | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   native->launcher = meta_launcher_new (error); | ||||
|   if (!native->launcher) | ||||
|     return FALSE; | ||||
|  | ||||
|   native->udev = meta_udev_new (native); | ||||
|   native->barrier_manager = meta_barrier_manager_native_new (); | ||||
|  | ||||
|   native->kms = meta_kms_new (META_BACKEND (native), error); | ||||
|   if (!native->kms) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (!init_gpus (native, error)) | ||||
|     return FALSE; | ||||
|  | ||||
|   return initable_parent_iface->init (initable, cancellable, error); | ||||
| } | ||||
|  | ||||
| @@ -575,26 +723,24 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass) | ||||
| static void | ||||
| meta_backend_native_init (MetaBackendNative *native) | ||||
| { | ||||
|   MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native); | ||||
|   GError *error = NULL; | ||||
|  | ||||
|   priv->launcher = meta_launcher_new (&error); | ||||
|   if (priv->launcher == NULL) | ||||
|     { | ||||
|       g_warning ("Can't initialize KMS backend: %s\n", error->message); | ||||
|       exit (1); | ||||
|     } | ||||
|  | ||||
|   priv->barrier_manager = meta_barrier_manager_native_new (); | ||||
| } | ||||
|  | ||||
| MetaLauncher * | ||||
| meta_backend_native_get_launcher (MetaBackendNative *native) | ||||
| { | ||||
|   MetaBackendNativePrivate *priv = | ||||
|     meta_backend_native_get_instance_private (native); | ||||
|   return native->launcher; | ||||
| } | ||||
|  | ||||
|   return priv->launcher; | ||||
| MetaUdev * | ||||
| meta_backend_native_get_udev (MetaBackendNative *native) | ||||
| { | ||||
|   return native->udev; | ||||
| } | ||||
|  | ||||
| MetaKms * | ||||
| meta_backend_native_get_kms (MetaBackendNative *native) | ||||
| { | ||||
|   return native->kms; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| @@ -610,10 +756,7 @@ meta_activate_vt (int vt, GError **error) | ||||
| MetaBarrierManagerNative * | ||||
| meta_backend_native_get_barrier_manager (MetaBackendNative *native) | ||||
| { | ||||
|   MetaBackendNativePrivate *priv = | ||||
|     meta_backend_native_get_instance_private (native); | ||||
|  | ||||
|   return priv->barrier_manager; | ||||
|   return native->barrier_manager; | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -634,9 +777,8 @@ meta_activate_session (void) | ||||
|     return TRUE; | ||||
|  | ||||
|   MetaBackendNative *native = META_BACKEND_NATIVE (backend); | ||||
|   MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native); | ||||
|  | ||||
|   if (!meta_launcher_activate_session (priv->launcher, &error)) | ||||
|   if (!meta_launcher_activate_session (native->launcher, &error)) | ||||
|     { | ||||
|       g_warning ("Could not activate session: %s\n", error->message); | ||||
|       g_error_free (error); | ||||
| @@ -659,6 +801,8 @@ meta_backend_native_pause (MetaBackendNative *native) | ||||
|   clutter_evdev_release_devices (); | ||||
|   clutter_stage_freeze_updates (stage); | ||||
|  | ||||
|   disconnect_udev_device_added_handler (native); | ||||
|  | ||||
|   meta_monitor_manager_kms_pause (monitor_manager_kms); | ||||
| } | ||||
|  | ||||
| @@ -674,6 +818,8 @@ void meta_backend_native_resume (MetaBackendNative *native) | ||||
|  | ||||
|   meta_monitor_manager_kms_resume (monitor_manager_kms); | ||||
|  | ||||
|   connect_udev_device_added_handler (native); | ||||
|  | ||||
|   clutter_evdev_reclaim_devices (); | ||||
|   clutter_stage_thaw_updates (stage); | ||||
|  | ||||
|   | ||||
| @@ -27,7 +27,9 @@ | ||||
|  | ||||
| #include "backends/meta-backend-private.h" | ||||
| #include "backends/native/meta-clutter-backend-native.h" | ||||
| #include "backends/native/meta-kms-types.h" | ||||
| #include "backends/native/meta-launcher.h" | ||||
| #include "backends/native/meta-udev.h" | ||||
|  | ||||
| #define META_TYPE_BACKEND_NATIVE (meta_backend_native_get_type ()) | ||||
| G_DECLARE_FINAL_TYPE (MetaBackendNative, meta_backend_native, | ||||
| @@ -41,4 +43,8 @@ void meta_backend_native_resume (MetaBackendNative *backend_native); | ||||
|  | ||||
| MetaLauncher * meta_backend_native_get_launcher (MetaBackendNative *native); | ||||
|  | ||||
| MetaUdev * meta_backend_native_get_udev (MetaBackendNative *native); | ||||
|  | ||||
| MetaKms * meta_backend_native_get_kms (MetaBackendNative *native); | ||||
|  | ||||
| #endif /* META_BACKEND_NATIVE_H */ | ||||
|   | ||||
| @@ -24,68 +24,24 @@ | ||||
|  | ||||
| #include "backends/native/meta-crtc-kms.h" | ||||
|  | ||||
| #include <drm_fourcc.h> | ||||
| #include <drm_mode.h> | ||||
|  | ||||
| #include "backends/meta-backend-private.h" | ||||
| #include "backends/meta-logical-monitor.h" | ||||
| #include "backends/native/meta-gpu-kms.h" | ||||
| #include "backends/native/meta-output-kms.h" | ||||
| #include "backends/native/meta-kms-device.h" | ||||
| #include "backends/native/meta-kms-plane.h" | ||||
| #include "backends/native/meta-kms-update.h" | ||||
|  | ||||
| /* added in libdrm 2.4.95 */ | ||||
| #ifndef DRM_FORMAT_INVALID | ||||
| #define DRM_FORMAT_INVALID 0 | ||||
| #endif | ||||
|  | ||||
| #define ALL_TRANSFORMS (META_MONITOR_TRANSFORM_FLIPPED_270 + 1) | ||||
| #define ALL_TRANSFORMS_MASK ((1 << ALL_TRANSFORMS) - 1) | ||||
| #define ALL_TRANSFORMS_MASK ((1 << META_MONITOR_N_TRANSFORMS) - 1) | ||||
|  | ||||
| typedef struct _MetaCrtcKms | ||||
| { | ||||
|   unsigned int index; | ||||
|   uint32_t primary_plane_id; | ||||
|   uint32_t rotation_prop_id; | ||||
|   uint32_t rotation_map[ALL_TRANSFORMS]; | ||||
|   uint32_t all_hw_transforms; | ||||
|   MetaKmsCrtc *kms_crtc; | ||||
|  | ||||
|   /* | ||||
|    * primary plane's supported formats and maybe modifiers | ||||
|    * key: GUINT_TO_POINTER (format) | ||||
|    * value: owned GArray* (uint64_t modifier), or NULL | ||||
|    */ | ||||
|   GHashTable *formats_modifiers; | ||||
|   MetaKmsPlane *primary_plane; | ||||
| } MetaCrtcKms; | ||||
|  | ||||
| /** | ||||
|  * meta_drm_format_to_string: | ||||
|  * @tmp: temporary buffer | ||||
|  * @drm_format: DRM fourcc pixel format | ||||
|  * | ||||
|  * Returns a pointer to a string naming the given pixel format, | ||||
|  * usually a pointer to the temporary buffer but not always. | ||||
|  * Invalid formats may return nonsense names. | ||||
|  * | ||||
|  * When calling this, allocate one MetaDrmFormatBuf on the stack to | ||||
|  * be used as the temporary buffer. | ||||
|  */ | ||||
| const char * | ||||
| meta_drm_format_to_string (MetaDrmFormatBuf *tmp, | ||||
|                            uint32_t          drm_format) | ||||
| { | ||||
|   int i; | ||||
|  | ||||
|   if (drm_format == DRM_FORMAT_INVALID) | ||||
|     return "INVALID"; | ||||
|  | ||||
|   G_STATIC_ASSERT (sizeof (tmp->s) == 5); | ||||
|   for (i = 0; i < 4; i++) | ||||
|     { | ||||
|       char c = (drm_format >> (i * 8)) & 0xff; | ||||
|       tmp->s[i] = g_ascii_isgraph (c) ? c : '.'; | ||||
|     } | ||||
|  | ||||
|   tmp->s[i] = 0; | ||||
|  | ||||
|   return tmp->s; | ||||
| } | ||||
| static GQuark kms_crtc_crtc_kms_quark; | ||||
|  | ||||
| gboolean | ||||
| meta_crtc_kms_is_transform_handled (MetaCrtc             *crtc, | ||||
| @@ -93,77 +49,147 @@ meta_crtc_kms_is_transform_handled (MetaCrtc             *crtc, | ||||
| { | ||||
|   MetaCrtcKms *crtc_kms = crtc->driver_private; | ||||
|  | ||||
|   if ((1 << transform) & crtc_kms->all_hw_transforms) | ||||
|     return TRUE; | ||||
|   else | ||||
|   if (!crtc_kms->primary_plane) | ||||
|     return FALSE; | ||||
|  | ||||
|   return meta_kms_plane_is_transform_handled (crtc_kms->primary_plane, | ||||
|                                               transform); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_crtc_kms_apply_transform (MetaCrtc *crtc) | ||||
| meta_crtc_kms_apply_transform (MetaCrtc               *crtc, | ||||
|                                MetaKmsPlaneAssignment *kms_plane_assignment) | ||||
| { | ||||
|   MetaCrtcKms *crtc_kms = crtc->driver_private; | ||||
|   MetaGpu *gpu = meta_crtc_get_gpu (crtc); | ||||
|   MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); | ||||
|   int kms_fd; | ||||
|   MetaMonitorTransform hw_transform; | ||||
|  | ||||
|   kms_fd = meta_gpu_kms_get_fd (gpu_kms); | ||||
|  | ||||
|   if (crtc_kms->all_hw_transforms & (1 << crtc->transform)) | ||||
|     hw_transform = crtc->transform; | ||||
|   else | ||||
|   hw_transform = crtc->transform; | ||||
|   if (!meta_crtc_kms_is_transform_handled (crtc, hw_transform)) | ||||
|     hw_transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|  | ||||
|   if (!meta_crtc_kms_is_transform_handled (crtc, META_MONITOR_TRANSFORM_NORMAL)) | ||||
|   if (!meta_crtc_kms_is_transform_handled (crtc, hw_transform)) | ||||
|     return; | ||||
|  | ||||
|   if (drmModeObjectSetProperty (kms_fd, | ||||
|                                 crtc_kms->primary_plane_id, | ||||
|                                 DRM_MODE_OBJECT_PLANE, | ||||
|                                 crtc_kms->rotation_prop_id, | ||||
|                                 crtc_kms->rotation_map[hw_transform]) != 0) | ||||
|     { | ||||
|       g_warning ("Failed to apply DRM plane transform %d: %m", hw_transform); | ||||
|  | ||||
|       /* | ||||
|        * Blacklist this HW transform, we want to fallback to our | ||||
|        * fallbacks in this case. | ||||
|        */ | ||||
|       crtc_kms->all_hw_transforms &= ~(1 << hw_transform); | ||||
|     } | ||||
|   meta_kms_plane_update_set_rotation (crtc_kms->primary_plane, | ||||
|                                       kms_plane_assignment, | ||||
|                                       hw_transform); | ||||
| } | ||||
|  | ||||
| static int | ||||
| find_property_index (MetaGpu                    *gpu, | ||||
|                      drmModeObjectPropertiesPtr  props, | ||||
|                      const char                 *prop_name, | ||||
|                      drmModePropertyPtr         *out_prop) | ||||
| void | ||||
| meta_crtc_kms_assign_primary_plane (MetaCrtc      *crtc, | ||||
|                                     uint32_t       fb_id, | ||||
|                                     MetaKmsUpdate *kms_update) | ||||
| { | ||||
|   MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); | ||||
|   int kms_fd; | ||||
|   unsigned int i; | ||||
|   MetaRectangle logical_monitor_rect; | ||||
|   int x, y; | ||||
|   MetaFixed16Rectangle src_rect; | ||||
|   MetaFixed16Rectangle dst_rect; | ||||
|   MetaKmsCrtc *kms_crtc; | ||||
|   MetaKmsDevice *kms_device; | ||||
|   MetaKmsPlane *primary_kms_plane; | ||||
|   MetaKmsPlaneAssignment *plane_assignment; | ||||
|  | ||||
|   kms_fd = meta_gpu_kms_get_fd (gpu_kms); | ||||
|   logical_monitor_rect = | ||||
|     meta_logical_monitor_get_layout (crtc->logical_monitor); | ||||
|   x = crtc->rect.x - logical_monitor_rect.x; | ||||
|   y = crtc->rect.y - logical_monitor_rect.y; | ||||
|   src_rect = (MetaFixed16Rectangle) { | ||||
|     .x = meta_fixed_16_from_int (x), | ||||
|     .y = meta_fixed_16_from_int (y), | ||||
|     .width = meta_fixed_16_from_int (crtc->rect.width), | ||||
|     .height = meta_fixed_16_from_int (crtc->rect.height), | ||||
|   }; | ||||
|   dst_rect = (MetaFixed16Rectangle) { | ||||
|     .x = meta_fixed_16_from_int (0), | ||||
|     .y = meta_fixed_16_from_int (0), | ||||
|     .width = meta_fixed_16_from_int (crtc->rect.width), | ||||
|     .height = meta_fixed_16_from_int (crtc->rect.height), | ||||
|   }; | ||||
|  | ||||
|   for (i = 0; i < props->count_props; i++) | ||||
|   kms_crtc = meta_crtc_kms_get_kms_crtc (crtc); | ||||
|   kms_device = meta_kms_crtc_get_device (kms_crtc); | ||||
|   primary_kms_plane = meta_kms_device_get_primary_plane_for (kms_device, | ||||
|                                                              kms_crtc); | ||||
|   plane_assignment = meta_kms_update_assign_plane (kms_update, | ||||
|                                                    kms_crtc, | ||||
|                                                    primary_kms_plane, | ||||
|                                                    fb_id, | ||||
|                                                    src_rect, | ||||
|                                                    dst_rect); | ||||
|   meta_crtc_kms_apply_transform (crtc, plane_assignment); | ||||
| } | ||||
|  | ||||
| static GList * | ||||
| generate_crtc_connector_list (MetaGpu  *gpu, | ||||
|                               MetaCrtc *crtc) | ||||
| { | ||||
|   GList *connectors = NULL; | ||||
|   GList *l; | ||||
|  | ||||
|   for (l = meta_gpu_get_outputs (gpu); l; l = l->next) | ||||
|     { | ||||
|       drmModePropertyPtr prop; | ||||
|       MetaOutput *output = l->data; | ||||
|       MetaCrtc *assigned_crtc; | ||||
|  | ||||
|       prop = drmModeGetProperty (kms_fd, props->props[i]); | ||||
|       if (!prop) | ||||
|         continue; | ||||
|  | ||||
|       if (strcmp (prop->name, prop_name) == 0) | ||||
|       assigned_crtc = meta_output_get_assigned_crtc (output); | ||||
|       if (assigned_crtc == crtc) | ||||
|         { | ||||
|           *out_prop = prop; | ||||
|           return i; | ||||
|         } | ||||
|           MetaKmsConnector *kms_connector = | ||||
|             meta_output_kms_get_kms_connector (output); | ||||
|  | ||||
|       drmModeFreeProperty (prop); | ||||
|           connectors = g_list_prepend (connectors, kms_connector); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   return -1; | ||||
|   return connectors; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_crtc_kms_set_mode (MetaCrtc      *crtc, | ||||
|                         MetaKmsUpdate *kms_update) | ||||
| { | ||||
|   MetaGpu *gpu = meta_crtc_get_gpu (crtc); | ||||
|   GList *connectors; | ||||
|   drmModeModeInfo *mode; | ||||
|  | ||||
|   connectors = generate_crtc_connector_list (gpu, crtc); | ||||
|  | ||||
|   if (connectors) | ||||
|     { | ||||
|       mode = crtc->current_mode->driver_private; | ||||
|  | ||||
|       g_debug ("Setting CRTC (%ld) mode to %s", crtc->crtc_id, mode->name); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       mode = NULL; | ||||
|  | ||||
|       g_debug ("Unsetting CRTC (%ld) mode", crtc->crtc_id); | ||||
|     } | ||||
|  | ||||
|   meta_kms_update_mode_set (kms_update, | ||||
|                             meta_crtc_kms_get_kms_crtc (crtc), | ||||
|                             g_steal_pointer (&connectors), | ||||
|                             mode); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_crtc_kms_page_flip (MetaCrtc                      *crtc, | ||||
|                          const MetaKmsPageFlipFeedback *page_flip_feedback, | ||||
|                          gpointer                       user_data, | ||||
|                          MetaKmsUpdate                 *kms_update) | ||||
| { | ||||
|   meta_kms_update_page_flip (kms_update, | ||||
|                              meta_crtc_kms_get_kms_crtc (crtc), | ||||
|                              page_flip_feedback, | ||||
|                              user_data); | ||||
| } | ||||
|  | ||||
| MetaKmsCrtc * | ||||
| meta_crtc_kms_get_kms_crtc (MetaCrtc *crtc) | ||||
| { | ||||
|   MetaCrtcKms *crtc_kms = crtc->driver_private; | ||||
|  | ||||
|   return crtc_kms->kms_crtc; | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -186,8 +212,8 @@ meta_crtc_kms_get_modifiers (MetaCrtc *crtc, | ||||
| { | ||||
|   MetaCrtcKms *crtc_kms = crtc->driver_private; | ||||
|  | ||||
|   return g_hash_table_lookup (crtc_kms->formats_modifiers, | ||||
|                               GUINT_TO_POINTER (format)); | ||||
|   return meta_kms_plane_get_modifiers_for_format (crtc_kms->primary_plane, | ||||
|                                                   format); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -202,24 +228,8 @@ GArray * | ||||
| meta_crtc_kms_copy_drm_format_list (MetaCrtc *crtc) | ||||
| { | ||||
|   MetaCrtcKms *crtc_kms = crtc->driver_private; | ||||
|   GArray *formats; | ||||
|   GHashTableIter it; | ||||
|   gpointer key; | ||||
|   unsigned int n_formats_modifiers; | ||||
|  | ||||
|   n_formats_modifiers = g_hash_table_size (crtc_kms->formats_modifiers); | ||||
|   formats = g_array_sized_new (FALSE, | ||||
|                                FALSE, | ||||
|                                sizeof (uint32_t), | ||||
|                                n_formats_modifiers); | ||||
|   g_hash_table_iter_init (&it, crtc_kms->formats_modifiers); | ||||
|   while (g_hash_table_iter_next (&it, &key, NULL)) | ||||
|     { | ||||
|       uint32_t drm_format = GPOINTER_TO_UINT (key); | ||||
|       g_array_append_val (formats, drm_format); | ||||
|     } | ||||
|  | ||||
|   return formats; | ||||
|   return meta_kms_plane_copy_drm_format_list (crtc_kms->primary_plane); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -235,284 +245,47 @@ meta_crtc_kms_supports_format (MetaCrtc *crtc, | ||||
| { | ||||
|   MetaCrtcKms *crtc_kms = crtc->driver_private; | ||||
|  | ||||
|   return g_hash_table_lookup_extended (crtc_kms->formats_modifiers, | ||||
|                                        GUINT_TO_POINTER (drm_format), | ||||
|                                        NULL, | ||||
|                                        NULL); | ||||
|   return meta_kms_plane_is_format_supported (crtc_kms->primary_plane, | ||||
|                                              drm_format); | ||||
| } | ||||
|  | ||||
| static inline uint32_t * | ||||
| formats_ptr (struct drm_format_modifier_blob *blob) | ||||
| MetaCrtc * | ||||
| meta_crtc_kms_from_kms_crtc (MetaKmsCrtc *kms_crtc) | ||||
| { | ||||
|   return (uint32_t *) (((char *) blob) + blob->formats_offset); | ||||
| } | ||||
|  | ||||
| static inline struct drm_format_modifier * | ||||
| modifiers_ptr (struct drm_format_modifier_blob *blob) | ||||
| { | ||||
|   return (struct drm_format_modifier *) (((char *) blob) + | ||||
|                                          blob->modifiers_offset); | ||||
| } | ||||
|  | ||||
| static void | ||||
| free_modifier_array (GArray *array) | ||||
| { | ||||
|   if (!array) | ||||
|     return; | ||||
|  | ||||
|   g_array_free (array, TRUE); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * In case the DRM driver does not expose a format list for the | ||||
|  * primary plane (does not support universal planes nor | ||||
|  * IN_FORMATS property), hardcode something that is probably supported. | ||||
|  */ | ||||
| static const uint32_t drm_default_formats[] = | ||||
|   { | ||||
|     DRM_FORMAT_XRGB8888 /* The format everything should always support by convention */, | ||||
| #if G_BYTE_ORDER == G_LITTLE_ENDIAN | ||||
|     DRM_FORMAT_XBGR8888 /* OpenGL GL_RGBA, GL_UNSIGNED_BYTE format, hopefully supported */ | ||||
| #endif | ||||
|   }; | ||||
|  | ||||
| static void | ||||
| set_formats_from_array (MetaCrtc       *crtc, | ||||
|                         const uint32_t *formats, | ||||
|                         size_t          n_formats) | ||||
| { | ||||
|   MetaCrtcKms *crtc_kms = crtc->driver_private; | ||||
|   size_t i; | ||||
|  | ||||
|   for (i = 0; i < n_formats; i++) | ||||
|     { | ||||
|       g_hash_table_insert (crtc_kms->formats_modifiers, | ||||
|                            GUINT_TO_POINTER (formats[i]), NULL); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| parse_formats (MetaCrtc *crtc, | ||||
|                int       kms_fd, | ||||
|                uint32_t  blob_id) | ||||
| { | ||||
|   MetaCrtcKms *crtc_kms = crtc->driver_private; | ||||
|   drmModePropertyBlobPtr blob; | ||||
|   struct drm_format_modifier_blob *blob_fmt; | ||||
|   uint32_t *formats; | ||||
|   struct drm_format_modifier *modifiers; | ||||
|   unsigned int fmt_i, mod_i; | ||||
|  | ||||
|   g_return_if_fail (g_hash_table_size (crtc_kms->formats_modifiers) == 0); | ||||
|  | ||||
|   if (blob_id == 0) | ||||
|     return; | ||||
|  | ||||
|   blob = drmModeGetPropertyBlob (kms_fd, blob_id); | ||||
|   if (!blob) | ||||
|     return; | ||||
|  | ||||
|   if (blob->length < sizeof (struct drm_format_modifier_blob)) | ||||
|     { | ||||
|       drmModeFreePropertyBlob (blob); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   blob_fmt = blob->data; | ||||
|  | ||||
|   formats = formats_ptr (blob_fmt); | ||||
|   modifiers = modifiers_ptr (blob_fmt); | ||||
|  | ||||
|   for (fmt_i = 0; fmt_i < blob_fmt->count_formats; fmt_i++) | ||||
|     { | ||||
|       GArray *mod_tmp = g_array_new (FALSE, FALSE, sizeof (uint64_t)); | ||||
|  | ||||
|       for (mod_i = 0; mod_i < blob_fmt->count_modifiers; mod_i++) | ||||
|         { | ||||
|           struct drm_format_modifier *modifier = &modifiers[mod_i]; | ||||
|  | ||||
|           /* The modifier advertisement blob is partitioned into groups of | ||||
|            * 64 formats. */ | ||||
|           if (fmt_i < modifier->offset || fmt_i > modifier->offset + 63) | ||||
|             continue; | ||||
|  | ||||
|           if (!(modifier->formats & (1 << (fmt_i - modifier->offset)))) | ||||
|             continue; | ||||
|  | ||||
|           g_array_append_val (mod_tmp, modifier->modifier); | ||||
|         } | ||||
|  | ||||
|       if (mod_tmp->len == 0) | ||||
|         { | ||||
|           free_modifier_array (mod_tmp); | ||||
|           mod_tmp = NULL; | ||||
|         } | ||||
|  | ||||
|       g_hash_table_insert (crtc_kms->formats_modifiers, | ||||
|                            GUINT_TO_POINTER (formats[fmt_i]), mod_tmp); | ||||
|     } | ||||
|  | ||||
|   drmModeFreePropertyBlob (blob); | ||||
| } | ||||
|  | ||||
| static void | ||||
| parse_transforms (MetaCrtc          *crtc, | ||||
|                   drmModePropertyPtr prop) | ||||
| { | ||||
|   MetaCrtcKms *crtc_kms = crtc->driver_private; | ||||
|   int i; | ||||
|  | ||||
|   for (i = 0; i < prop->count_enums; i++) | ||||
|     { | ||||
|       int transform = -1; | ||||
|  | ||||
|       if (strcmp (prop->enums[i].name, "rotate-0") == 0) | ||||
|         transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|       else if (strcmp (prop->enums[i].name, "rotate-90") == 0) | ||||
|         transform = META_MONITOR_TRANSFORM_90; | ||||
|       else if (strcmp (prop->enums[i].name, "rotate-180") == 0) | ||||
|         transform = META_MONITOR_TRANSFORM_180; | ||||
|       else if (strcmp (prop->enums[i].name, "rotate-270") == 0) | ||||
|         transform = META_MONITOR_TRANSFORM_270; | ||||
|  | ||||
|       if (transform != -1) | ||||
|         { | ||||
|           crtc_kms->all_hw_transforms |= 1 << transform; | ||||
|           crtc_kms->rotation_map[transform] = 1 << prop->enums[i].value; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_primary_plane (MetaGpu                   *gpu, | ||||
|                   drmModeObjectPropertiesPtr props) | ||||
| { | ||||
|   drmModePropertyPtr prop; | ||||
|   int idx; | ||||
|  | ||||
|   idx = find_property_index (gpu, props, "type", &prop); | ||||
|   if (idx < 0) | ||||
|     return FALSE; | ||||
|  | ||||
|   drmModeFreeProperty (prop); | ||||
|   return props->prop_values[idx] == DRM_PLANE_TYPE_PRIMARY; | ||||
| } | ||||
|  | ||||
| static void | ||||
| init_crtc_rotations (MetaCrtc *crtc, | ||||
|                      MetaGpu  *gpu) | ||||
| { | ||||
|   MetaCrtcKms *crtc_kms = crtc->driver_private; | ||||
|   MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); | ||||
|   int kms_fd; | ||||
|   drmModeObjectPropertiesPtr props; | ||||
|   drmModePlaneRes *planes; | ||||
|   drmModePlane *drm_plane; | ||||
|   unsigned int i; | ||||
|  | ||||
|   kms_fd = meta_gpu_kms_get_fd (gpu_kms); | ||||
|  | ||||
|   planes = drmModeGetPlaneResources (kms_fd); | ||||
|   if (planes == NULL) | ||||
|     return; | ||||
|  | ||||
|   for (i = 0; i < planes->count_planes; i++) | ||||
|     { | ||||
|       drmModePropertyPtr prop; | ||||
|  | ||||
|       drm_plane = drmModeGetPlane (kms_fd, planes->planes[i]); | ||||
|  | ||||
|       if (!drm_plane) | ||||
|         continue; | ||||
|  | ||||
|       if ((drm_plane->possible_crtcs & (1 << crtc_kms->index))) | ||||
|         { | ||||
|           props = drmModeObjectGetProperties (kms_fd, | ||||
|                                               drm_plane->plane_id, | ||||
|                                               DRM_MODE_OBJECT_PLANE); | ||||
|  | ||||
|           if (props && is_primary_plane (gpu, props)) | ||||
|             { | ||||
|               int rotation_idx, fmts_idx; | ||||
|  | ||||
|               crtc_kms->primary_plane_id = drm_plane->plane_id; | ||||
|               rotation_idx = find_property_index (gpu, props, | ||||
|                                                   "rotation", &prop); | ||||
|               if (rotation_idx >= 0) | ||||
|                 { | ||||
|                   crtc_kms->rotation_prop_id = props->props[rotation_idx]; | ||||
|                   parse_transforms (crtc, prop); | ||||
|                   drmModeFreeProperty (prop); | ||||
|                 } | ||||
|  | ||||
|               fmts_idx = find_property_index (gpu, props, | ||||
|                                               "IN_FORMATS", &prop); | ||||
|               if (fmts_idx >= 0) | ||||
|                 { | ||||
|                   parse_formats (crtc, kms_fd, props->prop_values[fmts_idx]); | ||||
|                   drmModeFreeProperty (prop); | ||||
|                 } | ||||
|  | ||||
|               /* fall back to universal plane formats without modifiers */ | ||||
|               if (g_hash_table_size (crtc_kms->formats_modifiers) == 0) | ||||
|                 { | ||||
|                   set_formats_from_array (crtc, | ||||
|                                           drm_plane->formats, | ||||
|                                           drm_plane->count_formats); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|           if (props) | ||||
|             drmModeFreeObjectProperties (props); | ||||
|         } | ||||
|  | ||||
|       drmModeFreePlane (drm_plane); | ||||
|     } | ||||
|  | ||||
|   crtc->all_transforms |= crtc_kms->all_hw_transforms; | ||||
|  | ||||
|   drmModeFreePlaneResources (planes); | ||||
|  | ||||
|   /* final formats fallback to something hardcoded */ | ||||
|   if (g_hash_table_size (crtc_kms->formats_modifiers) == 0) | ||||
|     { | ||||
|       set_formats_from_array (crtc, | ||||
|                               drm_default_formats, | ||||
|                               G_N_ELEMENTS (drm_default_formats)); | ||||
|     } | ||||
|   return g_object_get_qdata (G_OBJECT (kms_crtc), kms_crtc_crtc_kms_quark); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_crtc_destroy_notify (MetaCrtc *crtc) | ||||
| { | ||||
|   MetaCrtcKms *crtc_kms = crtc->driver_private; | ||||
|  | ||||
|   g_hash_table_destroy (crtc_kms->formats_modifiers); | ||||
|   g_free (crtc->driver_private); | ||||
| } | ||||
|  | ||||
| MetaCrtc * | ||||
| meta_create_kms_crtc (MetaGpuKms   *gpu_kms, | ||||
|                       drmModeCrtc  *drm_crtc, | ||||
|                       unsigned int  crtc_index) | ||||
| meta_create_kms_crtc (MetaGpuKms  *gpu_kms, | ||||
|                       MetaKmsCrtc *kms_crtc) | ||||
| { | ||||
|   MetaGpu *gpu = META_GPU (gpu_kms); | ||||
|   MetaKmsDevice *kms_device; | ||||
|   MetaCrtc *crtc; | ||||
|   MetaCrtcKms *crtc_kms; | ||||
|   MetaKmsPlane *primary_plane; | ||||
|   const MetaKmsCrtcState *crtc_state; | ||||
|  | ||||
|   kms_device = meta_gpu_kms_get_kms_device (gpu_kms); | ||||
|   primary_plane = meta_kms_device_get_primary_plane_for (kms_device, | ||||
|                                                          kms_crtc); | ||||
|   crtc_state = meta_kms_crtc_get_current_state (kms_crtc); | ||||
|  | ||||
|   crtc = g_object_new (META_TYPE_CRTC, NULL); | ||||
|  | ||||
|   crtc->gpu = gpu; | ||||
|   crtc->crtc_id = drm_crtc->crtc_id; | ||||
|   crtc->rect.x = drm_crtc->x; | ||||
|   crtc->rect.y = drm_crtc->y; | ||||
|   crtc->rect.width = drm_crtc->width; | ||||
|   crtc->rect.height = drm_crtc->height; | ||||
|   crtc->crtc_id = meta_kms_crtc_get_id (kms_crtc); | ||||
|   crtc->rect = crtc_state->rect; | ||||
|   crtc->is_dirty = FALSE; | ||||
|   crtc->transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|   crtc->all_transforms = ALL_TRANSFORMS_MASK; | ||||
|  | ||||
|   if (drm_crtc->mode_valid) | ||||
|   if (crtc_state->is_drm_mode_valid) | ||||
|     { | ||||
|       GList *l; | ||||
|  | ||||
| @@ -520,7 +293,7 @@ meta_create_kms_crtc (MetaGpuKms   *gpu_kms, | ||||
|         { | ||||
|           MetaCrtcMode *mode = l->data; | ||||
|  | ||||
|           if (meta_drm_mode_equal (&drm_crtc->mode, mode->driver_private)) | ||||
|           if (meta_drm_mode_equal (&crtc_state->drm_mode, mode->driver_private)) | ||||
|             { | ||||
|               crtc->current_mode = mode; | ||||
|               break; | ||||
| @@ -529,18 +302,19 @@ meta_create_kms_crtc (MetaGpuKms   *gpu_kms, | ||||
|     } | ||||
|  | ||||
|   crtc_kms = g_new0 (MetaCrtcKms, 1); | ||||
|   crtc_kms->index = crtc_index; | ||||
|  | ||||
|   crtc_kms->formats_modifiers = | ||||
|     g_hash_table_new_full (g_direct_hash, | ||||
|                            g_direct_equal, | ||||
|                            NULL, | ||||
|                            (GDestroyNotify) free_modifier_array); | ||||
|   crtc_kms->kms_crtc = kms_crtc; | ||||
|   crtc_kms->primary_plane = primary_plane; | ||||
|  | ||||
|   crtc->driver_private = crtc_kms; | ||||
|   crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify; | ||||
|  | ||||
|   init_crtc_rotations (crtc, gpu); | ||||
|   if (!kms_crtc_crtc_kms_quark) | ||||
|     { | ||||
|       kms_crtc_crtc_kms_quark = | ||||
|         g_quark_from_static_string ("meta-kms-crtc-crtc-kms-quark"); | ||||
|     } | ||||
|  | ||||
|   g_object_set_qdata (G_OBJECT (kms_crtc), kms_crtc_crtc_kms_quark, crtc); | ||||
|  | ||||
|   return crtc; | ||||
| } | ||||
|   | ||||
| @@ -29,20 +29,30 @@ | ||||
| #include "backends/meta-backend-types.h" | ||||
| #include "backends/meta-crtc.h" | ||||
| #include "backends/native/meta-gpu-kms.h" | ||||
|  | ||||
| typedef struct _MetaDrmFormatBuf | ||||
| { | ||||
|   char s[5]; | ||||
| } MetaDrmFormatBuf; | ||||
|  | ||||
| const char * | ||||
| meta_drm_format_to_string (MetaDrmFormatBuf *tmp, | ||||
|                            uint32_t          format); | ||||
| #include "backends/native/meta-kms-crtc.h" | ||||
|  | ||||
| gboolean meta_crtc_kms_is_transform_handled (MetaCrtc             *crtc, | ||||
|                                              MetaMonitorTransform  transform); | ||||
|  | ||||
| void meta_crtc_kms_apply_transform (MetaCrtc *crtc); | ||||
| void meta_crtc_kms_apply_transform (MetaCrtc               *crtc, | ||||
|                                     MetaKmsPlaneAssignment *kms_plane_assignment); | ||||
|  | ||||
| void meta_crtc_kms_assign_primary_plane (MetaCrtc      *crtc, | ||||
|                                          uint32_t       fb_id, | ||||
|                                          MetaKmsUpdate *kms_update); | ||||
|  | ||||
| void meta_crtc_kms_set_mode (MetaCrtc      *crtc, | ||||
|                              MetaKmsUpdate *kms_update); | ||||
|  | ||||
| void meta_crtc_kms_page_flip (MetaCrtc                      *crtc, | ||||
|                               const MetaKmsPageFlipFeedback *page_flip_feedback, | ||||
|                               gpointer                       user_data, | ||||
|                               MetaKmsUpdate                 *kms_update); | ||||
|  | ||||
| void meta_crtc_kms_set_is_underscanning (MetaCrtc *crtc, | ||||
|                                          gboolean  is_underscanning); | ||||
|  | ||||
| MetaKmsCrtc * meta_crtc_kms_get_kms_crtc (MetaCrtc *crtc); | ||||
|  | ||||
| GArray * meta_crtc_kms_get_modifiers (MetaCrtc *crtc, | ||||
|                                       uint32_t  format); | ||||
| @@ -54,8 +64,9 @@ gboolean | ||||
| meta_crtc_kms_supports_format (MetaCrtc *crtc, | ||||
|                                uint32_t  drm_format); | ||||
|  | ||||
| MetaCrtc * meta_create_kms_crtc (MetaGpuKms   *gpu_kms, | ||||
|                                  drmModeCrtc  *drm_crtc, | ||||
|                                  unsigned int  crtc_index); | ||||
| MetaCrtc * meta_crtc_kms_from_kms_crtc (MetaKmsCrtc *kms_crtc); | ||||
|  | ||||
| MetaCrtc * meta_create_kms_crtc (MetaGpuKms  *gpu_kms, | ||||
|                                  MetaKmsCrtc *kms_crtc); | ||||
|  | ||||
| #endif /* META_CRTC_KMS_H */ | ||||
|   | ||||
| @@ -77,7 +77,7 @@ struct _MetaCursorRendererNative | ||||
|  | ||||
| struct _MetaCursorRendererNativePrivate | ||||
| { | ||||
|   MetaMonitorManager *monitor_manager; | ||||
|   MetaBackend *backend; | ||||
|  | ||||
|   gboolean hw_state_invalidated; | ||||
|   gboolean has_hw_cursor; | ||||
| @@ -387,7 +387,9 @@ update_hw_cursor (MetaCursorRendererNative *native, | ||||
|   MetaCursorRendererNativePrivate *priv = | ||||
|     meta_cursor_renderer_native_get_instance_private (native); | ||||
|   MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); | ||||
|   MetaMonitorManager *monitor_manager = priv->monitor_manager; | ||||
|   MetaBackend *backend = priv->backend; | ||||
|   MetaMonitorManager *monitor_manager = | ||||
|     meta_backend_get_monitor_manager (backend); | ||||
|   GList *logical_monitors; | ||||
|   GList *l; | ||||
|   ClutterRect rect; | ||||
| @@ -480,7 +482,9 @@ cursor_over_transformed_logical_monitor (MetaCursorRenderer *renderer, | ||||
|     META_CURSOR_RENDERER_NATIVE (renderer); | ||||
|   MetaCursorRendererNativePrivate *priv = | ||||
|     meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); | ||||
|   MetaMonitorManager *monitor_manager = priv->monitor_manager; | ||||
|   MetaBackend *backend = priv->backend; | ||||
|   MetaMonitorManager *monitor_manager = | ||||
|     meta_backend_get_monitor_manager (backend); | ||||
|   GList *logical_monitors; | ||||
|   GList *l; | ||||
|   ClutterRect cursor_rect; | ||||
| @@ -538,7 +542,9 @@ can_draw_cursor_unscaled (MetaCursorRenderer *renderer, | ||||
|     META_CURSOR_RENDERER_NATIVE (renderer); | ||||
|   MetaCursorRendererNativePrivate *priv = | ||||
|     meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); | ||||
|   MetaMonitorManager *monitor_manager = priv->monitor_manager; | ||||
|   MetaBackend *backend = priv->backend; | ||||
|   MetaMonitorManager *monitor_manager = | ||||
|     meta_backend_get_monitor_manager (backend); | ||||
|   ClutterRect cursor_rect; | ||||
|   GList *logical_monitors; | ||||
|   GList *l; | ||||
| @@ -680,7 +686,9 @@ calculate_cursor_sprite_gpus (MetaCursorRenderer *renderer, | ||||
|   MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); | ||||
|   MetaCursorRendererNativePrivate *priv = | ||||
|     meta_cursor_renderer_native_get_instance_private (native); | ||||
|   MetaMonitorManager *monitor_manager = priv->monitor_manager; | ||||
|   MetaBackend *backend = priv->backend; | ||||
|   MetaMonitorManager *monitor_manager = | ||||
|     meta_backend_get_monitor_manager (backend); | ||||
|   GList *gpus = NULL; | ||||
|   GList *logical_monitors; | ||||
|   GList *l; | ||||
| @@ -1175,7 +1183,7 @@ init_hw_cursor_support (MetaCursorRendererNative *cursor_renderer_native) | ||||
|   GList *gpus; | ||||
|   GList *l; | ||||
|  | ||||
|   gpus = meta_monitor_manager_get_gpus (priv->monitor_manager); | ||||
|   gpus = meta_backend_get_gpus (priv->backend); | ||||
|   for (l = gpus; l; l = l->next) | ||||
|     { | ||||
|       MetaGpuKms *gpu_kms = l->data; | ||||
| @@ -1223,7 +1231,7 @@ meta_cursor_renderer_native_new (MetaBackend *backend) | ||||
|                            G_CALLBACK (on_monitors_changed), | ||||
|                            cursor_renderer_native, 0); | ||||
|  | ||||
|   priv->monitor_manager = monitor_manager; | ||||
|   priv->backend = backend; | ||||
|   priv->hw_state_invalidated = TRUE; | ||||
|  | ||||
|   init_hw_cursor_support (cursor_renderer_native); | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user